pidgin2adium 3.3.0 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -3
  3. data/.rspec +1 -0
  4. data/.simplecov +5 -0
  5. data/.travis.yml +12 -0
  6. data/Gemfile +6 -1
  7. data/LICENSE +17 -17
  8. data/NEWS.md +89 -0
  9. data/README.md +60 -0
  10. data/Rakefile +5 -23
  11. data/bin/pidgin2adium +19 -90
  12. data/lib/pidgin2adium.rb +4 -136
  13. data/lib/pidgin2adium/adium_chat_file_creator.rb +64 -0
  14. data/lib/pidgin2adium/file_finder.rb +23 -0
  15. data/lib/pidgin2adium/runner.rb +23 -0
  16. data/lib/pidgin2adium/version.rb +1 -1
  17. data/pidgin2adium.gemspec +25 -21
  18. data/spec/features/parse_pidgin_log_file_spec.rb +50 -0
  19. data/spec/fixtures/input/input.html +3 -0
  20. data/spec/fixtures/output.xml +5 -0
  21. data/spec/pidgin2adium/adium_chat_file_creator_spec.rb +89 -0
  22. data/spec/pidgin2adium/file_finder_spec.rb +63 -0
  23. data/spec/spec_helper.rb +17 -59
  24. metadata +96 -89
  25. data/.autotest +0 -28
  26. data/ChangeLog +0 -79
  27. data/Manifest.txt +0 -18
  28. data/README.rdoc +0 -122
  29. data/config/website.yml +0 -2
  30. data/ext/balance_tags_c/balance_tags_c.c +0 -198
  31. data/ext/balance_tags_c/extconf.rb +0 -4
  32. data/lib/pidgin2adium/log_converter.rb +0 -71
  33. data/lib/pidgin2adium/log_file.rb +0 -100
  34. data/lib/pidgin2adium/log_parser.rb +0 -2
  35. data/lib/pidgin2adium/message.rb +0 -2
  36. data/lib/pidgin2adium/messages/all.rb +0 -5
  37. data/lib/pidgin2adium/messages/auto_reply_message.rb +0 -11
  38. data/lib/pidgin2adium/messages/event.rb +0 -17
  39. data/lib/pidgin2adium/messages/message.rb +0 -39
  40. data/lib/pidgin2adium/messages/status_message.rb +0 -17
  41. data/lib/pidgin2adium/messages/xml_message.rb +0 -40
  42. data/lib/pidgin2adium/parsers/all.rb +0 -3
  43. data/lib/pidgin2adium/parsers/basic_parser.rb +0 -456
  44. data/lib/pidgin2adium/parsers/html_log_parser.rb +0 -125
  45. data/lib/pidgin2adium/parsers/text_log_parser.rb +0 -39
  46. data/spec/balance_tags_c_extn_spec.rb +0 -47
  47. data/spec/basic_parser_spec.rb +0 -219
  48. data/spec/html_log_parser_spec.rb +0 -150
  49. data/spec/log_converter_spec.rb +0 -48
  50. data/spec/log_file_spec.rb +0 -176
  51. data/spec/logfiles/2006-12-21.223606.txt +0 -3
  52. data/spec/logfiles/2008-01-15.071445-0500PST.htm +0 -5
  53. data/spec/logfiles/2008-01-15.071445-0500PST.html +0 -5
  54. data/spec/pidgin2adium_spec.rb +0 -252
  55. data/spec/spec.opts +0 -1
  56. data/spec/test-output/README.md +0 -1
  57. data/spec/test-output/html_log_output.xml +0 -6
  58. data/spec/test-output/text_log_output.xml +0 -4
  59. data/spec/text_log_parser_spec.rb +0 -42
  60. data/tasks/extconf.rake +0 -8
  61. data/tasks/extconf/balance_tags_c.rake +0 -47
metadata CHANGED
@@ -1,135 +1,142 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pidgin2adium
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
5
- prerelease:
4
+ version: 4.0.0.beta1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Gabe Berke-Williams
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2011-10-16 00:00:00.000000000Z
11
+ date: 2014-08-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: &2155249120 !ruby/object:Gem::Requirement
17
- none: false
14
+ name: pipio
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: 1.0.0
22
- type: :development
19
+ version: 0.0.2
20
+ type: :runtime
23
21
  prerelease: false
24
- version_requirements: *2155249120
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.2
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: rspec
27
- requirement: &2155248600 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
29
37
  requirements:
30
- - - ~>
38
+ - - "~>"
31
39
  - !ruby/object:Gem::Version
32
- version: 2.4.0
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
33
48
  type: :development
34
49
  prerelease: false
35
- version_requirements: *2155248600
36
- description: Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs
37
- to the Adium format.
38
- email: gbw@brandeis.edu
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fakefs
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A fast, easy way to convert Pidgin (gaim) logs to the Adium format.
84
+ email: gabe@thoughtbot.com
39
85
  executables:
40
86
  - pidgin2adium
41
- extensions:
42
- - ext/balance_tags_c/extconf.rb
43
- extra_rdoc_files:
44
- - ChangeLog
45
- - LICENSE
46
- - README.rdoc
87
+ extensions: []
88
+ extra_rdoc_files: []
47
89
  files:
48
- - .autotest
49
- - .gitignore
50
- - .rspec
51
- - ChangeLog
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".simplecov"
93
+ - ".travis.yml"
52
94
  - Gemfile
53
95
  - LICENSE
54
- - Manifest.txt
55
- - README.rdoc
96
+ - NEWS.md
97
+ - README.md
56
98
  - Rakefile
57
99
  - bin/pidgin2adium
58
- - config/website.yml
59
- - ext/balance_tags_c/balance_tags_c.c
60
- - ext/balance_tags_c/extconf.rb
61
100
  - lib/pidgin2adium.rb
62
- - lib/pidgin2adium/log_converter.rb
63
- - lib/pidgin2adium/log_file.rb
64
- - lib/pidgin2adium/log_parser.rb
65
- - lib/pidgin2adium/message.rb
66
- - lib/pidgin2adium/messages/all.rb
67
- - lib/pidgin2adium/messages/auto_reply_message.rb
68
- - lib/pidgin2adium/messages/event.rb
69
- - lib/pidgin2adium/messages/message.rb
70
- - lib/pidgin2adium/messages/status_message.rb
71
- - lib/pidgin2adium/messages/xml_message.rb
72
- - lib/pidgin2adium/parsers/all.rb
73
- - lib/pidgin2adium/parsers/basic_parser.rb
74
- - lib/pidgin2adium/parsers/html_log_parser.rb
75
- - lib/pidgin2adium/parsers/text_log_parser.rb
101
+ - lib/pidgin2adium/adium_chat_file_creator.rb
102
+ - lib/pidgin2adium/file_finder.rb
103
+ - lib/pidgin2adium/runner.rb
76
104
  - lib/pidgin2adium/version.rb
77
105
  - pidgin2adium.gemspec
78
- - spec/balance_tags_c_extn_spec.rb
79
- - spec/basic_parser_spec.rb
80
- - spec/html_log_parser_spec.rb
81
- - spec/log_converter_spec.rb
82
- - spec/log_file_spec.rb
83
- - spec/logfiles/2006-12-21.223606.txt
84
- - spec/logfiles/2008-01-15.071445-0500PST.htm
85
- - spec/logfiles/2008-01-15.071445-0500PST.html
86
- - spec/pidgin2adium_spec.rb
87
- - spec/spec.opts
106
+ - spec/features/parse_pidgin_log_file_spec.rb
107
+ - spec/fixtures/input/input.html
108
+ - spec/fixtures/output.xml
109
+ - spec/pidgin2adium/adium_chat_file_creator_spec.rb
110
+ - spec/pidgin2adium/file_finder_spec.rb
88
111
  - spec/spec_helper.rb
89
- - spec/test-output/README.md
90
- - spec/test-output/html_log_output.xml
91
- - spec/test-output/text_log_output.xml
92
- - spec/text_log_parser_spec.rb
93
- - tasks/extconf.rake
94
- - tasks/extconf/balance_tags_c.rake
95
- homepage: http://github.com/gabebw/pidgin2adium
96
- licenses: []
112
+ homepage: https://github.com/gabebw/pidgin2adium
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
97
116
  post_install_message:
98
117
  rdoc_options: []
99
118
  require_paths:
100
119
  - lib
101
120
  required_ruby_version: !ruby/object:Gem::Requirement
102
- none: false
103
121
  requirements:
104
- - - ! '>='
122
+ - - ">="
105
123
  - !ruby/object:Gem::Version
106
- version: '0'
124
+ version: 1.9.2
107
125
  required_rubygems_version: !ruby/object:Gem::Requirement
108
- none: false
109
126
  requirements:
110
- - - ! '>='
127
+ - - ">"
111
128
  - !ruby/object:Gem::Version
112
- version: '0'
129
+ version: 1.3.1
113
130
  requirements: []
114
131
  rubyforge_project:
115
- rubygems_version: 1.8.10
132
+ rubygems_version: 2.2.2
116
133
  signing_key:
117
- specification_version: 3
118
- summary: Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to
119
- the Adium format
134
+ specification_version: 4
135
+ summary: A fast, easy way to convert Pidgin (gaim) logs to the Adium format.
120
136
  test_files:
121
- - spec/balance_tags_c_extn_spec.rb
122
- - spec/basic_parser_spec.rb
123
- - spec/html_log_parser_spec.rb
124
- - spec/log_converter_spec.rb
125
- - spec/log_file_spec.rb
126
- - spec/logfiles/2006-12-21.223606.txt
127
- - spec/logfiles/2008-01-15.071445-0500PST.htm
128
- - spec/logfiles/2008-01-15.071445-0500PST.html
129
- - spec/pidgin2adium_spec.rb
130
- - spec/spec.opts
137
+ - spec/features/parse_pidgin_log_file_spec.rb
138
+ - spec/fixtures/input/input.html
139
+ - spec/fixtures/output.xml
140
+ - spec/pidgin2adium/adium_chat_file_creator_spec.rb
141
+ - spec/pidgin2adium/file_finder_spec.rb
131
142
  - spec/spec_helper.rb
132
- - spec/test-output/README.md
133
- - spec/test-output/html_log_output.xml
134
- - spec/test-output/text_log_output.xml
135
- - spec/text_log_parser_spec.rb
data/.autotest DELETED
@@ -1,28 +0,0 @@
1
- require 'autotest/growl'
2
- require 'autotest/fsevent'
3
-
4
- Autotest.add_hook :initialize do |at|
5
- # Modifying ext/balance_tags_c.c triggers spec/balance_tags_c_extn_spec.rb
6
- at.add_mapping(/ext\/.*\/(.*)\.[ch]/) do |_, m|
7
- ["spec/#{m[1]}_extn_spec.rb"]
8
- end
9
-
10
- at.add_mapping(%r{lib/pidgin2adium.rb}) do |_, m|
11
- ["spec/pidgin2adium_spec.rb"]
12
- end
13
-
14
- at.add_mapping(%r{lib/pidgin2adium/(.+_log_parser).rb}) do |_, m|
15
- ["spec/#{m[1]}_spec.rb"]
16
- end
17
-
18
- # Re-run spec files when they change
19
- at.add_mapping(%r{^spec/.+_spec.rb$}) do |filename, _|
20
- filename
21
- end
22
-
23
- at.libs = %w{. lib spec}
24
- end
25
-
26
- Autotest.add_hook :run_command do |at|
27
- system "rake compile"
28
- end
data/ChangeLog DELETED
@@ -1,79 +0,0 @@
1
- === 3.3.0 / 2011-10-16
2
- * Pidgin2Adium depended on itself for some reason. Now it doesn't.
3
-
4
- === 3.2.3 / 2010-11-08
5
- * Be more liberal in what Pidgin2Adium accepts when parsing the date and
6
- getting basic time info for the first line. Thanks to Matthew Jakubowski for
7
- helping me fix this bug.
8
-
9
- === 3.2.2 / 2010-11-08
10
- * Use DateTime#strftime to get dates in xmlschema format. DateTime#xmlschema
11
- doesn't exist in Ruby 1.8, and Ruby 1.9 has DateTime#iso8601, not
12
- DateTime#xmlschema. Just use strftime. Thanks to Matthew Jakubowski for
13
- pointing this bug out.
14
-
15
- === 3.2.1 / 2010-11-08
16
- * Use straight DateTime.parse when possible, and only fall back on hacky
17
- Date._strptime when we have to.
18
-
19
- === 3.2.0 / 2010-10-12
20
- * Last release broke 1.8 compatibility due to use of strptime. 1.8 and 1.9
21
- both work in 3.2.0.
22
- * Moved Pidgin2Adium::VERSION to its own file
23
-
24
- === 3.1.1 / 2010-08-13
25
- * Moved BasicParser and its subclasses into parsers/ subdir
26
- - You can now do "require 'pidgin2adium/parsers/all'",
27
- though the old "require 'pidgin2adium/log_parser" will still work
28
- * Moved Message and its subclasses into messages/ subdir
29
- - You can now do "require 'pidgin2adium/messages/all'",
30
- though the old "require 'pidgin2adium/message" will still work
31
-
32
- === 3.1.0 / 2010-08-13
33
- * Compatible with Ruby 1.9!
34
- - removed dependency on "parsedate" library, which 1.9 doesn't have
35
- * log_parser.rb has been split into separate files (1 per class, more or less)
36
- - "require pidgin2adium/log_parser" will still pull in all of the split-up
37
- classes
38
- * balance_tags_c extension really does work now
39
- * Cleans up more junk from Pidgin logfiles when parsing
40
- * Bugfixes and more graceful handling of error states
41
- * Fully tested (except bin/pidgin2adium, which remains tricky)
42
-
43
- === 3.0.1 / 2010-08-07
44
- Bugfix release:
45
- * balance_tags_c.c: Use rb_eval_string instead of rb_reg_regcomp to avoid
46
- segfaults (commit #733ce88b0836256e14f0, fixes #27811)
47
- Non-user-facing stuff:
48
- * Switched to Jeweler, RSpec, and Bundler
49
- * Rakefile now doesn't choke if Hanna gem isn't installed
50
-
51
- === 3.0.0 / 2010-01-31
52
- * balance_tags.rb is now a C extension (Pidgin2Adium.balance_tags_c)
53
- - the pure-ruby mixin balance_tags (without the trailing "_c") is gone
54
- * Better handling of command-line arguments
55
- * Format time zones offsets correctly (e.g. "+0500", not "+-0500")
56
- * Write Yahoo! and Jabber logs to correct directories (#27710)
57
- * Better matching of regexes against time strings
58
- * Better documentation
59
-
60
- === 2.0.2 / 2009-12-18
61
- * Much better documentation (more of it, and higher quality too!)
62
- * Allow user-provided output dir at commandline
63
- * Cleaner error messages
64
- * require 'time' for Time.zone_offset (fixes bug)
65
- * Gracefully handle lack of timezone info
66
- * Gracefully handle nonexistent output dir
67
- * Gracefully handle parsing errors
68
- * Print error messages during *and* after batch converting so they're actually seen
69
-
70
- === 2.0.1 / 2009-12-06
71
- * Fix timestamps so they show up in Adium chat log viewer
72
-
73
- === 2.0.0 / 2009-11-24
74
- * Added documentation, available at http://pidgin2adium.rubyforge.org/rdoc/
75
- * Added public interface for scripting purposes
76
- * Removed -o and -l options. Now gem automatically outputs to Adium log dir with no intermediate folder.
77
-
78
- === 1.0.0 / 2009-09-27
79
- * Birthday!
data/Manifest.txt DELETED
@@ -1,18 +0,0 @@
1
- .autotest
2
- History.txt
3
- Manifest.txt
4
- README.rdoc
5
- Rakefile.rb
6
- bin/pidgin2adium
7
- ext/balance_tags_c/balance_tags_c.c
8
- ext/balance_tags_c/extconf.rb
9
- lib/pidgin2adium.rb
10
- lib/pidgin2adium/log_converter.rb
11
- lib/pidgin2adium/log_file.rb
12
- lib/pidgin2adium/log_parser.rb
13
- script/console
14
- script/destroy
15
- script/generate
16
- tasks/extconf.rake
17
- tasks/extconf/balance_tags_c.rake
18
- test/test_balance_tags_c_extn.rb
data/README.rdoc DELETED
@@ -1,122 +0,0 @@
1
- = pidgin2adium
2
- * http://github.com/gabebw/pidgin2adium
3
- * http://rubygems.org/gems/pidgin2adium
4
-
5
- == DESCRIPTION:
6
- Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the
7
- Adium format.
8
- Note that it assumes a Mac OS X environment with Adium installed.
9
-
10
- == FEATURES/PROBLEMS:
11
- * No problems (well, hopefully).
12
-
13
- == SYNOPSIS:
14
-
15
- There are two ways you can use this gem: as a script or as a library.
16
- Both require you to provide aliases, which may require a bit of explanation.
17
- Adium and Pidgin allow you to set aliases for buddies as well as for yourself,
18
- so that you show up in chats as (for example) "Me" instead of as
19
- "best_screen_name_ever_018845".
20
-
21
- However, Pidgin then uses aliases in the log file instead of the actual screen
22
- name, which complicates things. To parse properly, this gem needs to know which
23
- aliases belong to you so it can map them to the correct screen name.
24
- If it encounters an alias that you did not list, it assumes that it belongs to
25
- the person to whom you are chatting.
26
- Note that aliases are lower-cased and space is removed, so providing "Gabe B-W,
27
- GBW" is the same as providing "gabeb-w,gbw".
28
-
29
- You do not need to provide your screenname in the alias list.
30
-
31
- ===Example (using script)
32
- Assuming that:
33
- * your Pidgin log files are in the "pidgin-logs" folder
34
- * your various aliases in your chats are "Gabe", "Gabe B-W", and "gbw"
35
- Then run (at the command line):
36
- $ pidgin2adium -i pidgin-logs -a "Gabe, Gabe B-W, gbw"
37
- Or:
38
- $ pidgin2adium -i pidgin-logs -a gabe,gabeb-w,gbw
39
-
40
- ===Example (using library)
41
- The library style allows you to parse a log file and get back a LogFile[link:classes/Pidgin2Adium/LogFile.html] instance for easy reading, manipulation, etc. If you don't need to do anything with the individual messages, use Pidgin2Adium.parse[link:classes/Pidgin2Adium.html#M000002].
42
-
43
- require 'pidgin2adium'
44
- logfile = Pidgin2Adium.parse("/path/to/log/file.html", "gabe,gbw,gabeb-w")
45
- if logfile == false
46
- puts "Oh no! Could not parse!"
47
- else
48
- logfile.each do |message|
49
- # Every Message subclass has sender, time, and buddy_alias
50
- puts "Sender's screen name: #{message.sender}"
51
- puts "Time message was sent: #{message.time}"
52
- puts "Sender's alias: #{message.buddy_alias}"
53
- if message.respond_to?(:body)
54
- puts "Message body: #{message.body}"
55
- if message.respond_to?(:event) # Pidgin2Adium::Event class
56
- puts "Event type: #{message.event_type}"
57
- end
58
- elsif message.respond_to?(:status) # Pidgin2Adium::StatusMessage
59
- puts "Status: #{message.status}"
60
- end
61
- # Prints out the message in Adium log format
62
- puts message.to_s
63
- end
64
-
65
- success = logfile.write_out()
66
- # To overwrite file if it exists:
67
- # logfile.write_out(overwrite = true)
68
- # To specify your own output dir (default = Pidgin2Adium::ADIUM_LOG_DIR):
69
- # logfile.write_out(false, output_dir = my_dir)
70
- # Or combine them:
71
- # logfile.write_out(true, my_dir)
72
- if success == false
73
- puts "An error occurred!"
74
- elsif success == Pidgin2Adium::FILE_EXISTS
75
- # Not returned if overwrite set to true
76
- puts "File already exists."
77
- else
78
- puts "Successfully wrote out log file!"
79
- puts "Path to output file: #{success}"
80
- end
81
- # This deletes search indexes so Adium re-indexes the new chat logs.
82
- # It is not automatically called after log_file.write_out()
83
- # Call it after converting all the logs, since it takes up a bit of
84
- # processing power.
85
- Pidgin2Adium.delete_search_indexes()
86
- end
87
-
88
- ===Example 2 (using library)
89
- If you want to parse the file and write it out instead of just parsing it, use Pidgin2Adium.parse_and_generate.
90
-
91
- Note: For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.html].
92
-
93
- require 'pidgin2adium'
94
- # Both options are optional; without :output_dir, writes to Adium log dir
95
- # (which is usually what you want anyway).
96
- opts = {:overwrite => true, :output_dir => "/my/output/dir"}
97
- path_to_converted_log = Pidgin2Adium.parse_and_generate("/path/to/log/file.html", "gabe,gbw,gabeb-w", opts)
98
-
99
- == REQUIREMENTS:
100
- * None
101
-
102
- == INSTALL:
103
- * sudo gem install pidgin2adium
104
-
105
- == THANKS
106
- With thanks to Li Ma, whose blog post at
107
- http://li-ma.blogspot.com/2008/10/pidgin-log-file-to-adium-log-converter.html
108
- helped tremendously.
109
-
110
- == Note on Patches/Pull Requests
111
-
112
- * Fork the project.
113
- * Make your feature addition or bug fix.
114
- * Add tests for it. This is important so I don't break it in a
115
- future version unintentionally.
116
- * Commit, do not mess with rakefile, version, or history.
117
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
118
- * Send me a pull request. Bonus points for topic branches.
119
-
120
- == Copyright
121
-
122
- Copyright (c) 2010 Gabe Berke-Williams. See LICENSE for details.