kindle_strip 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kindle_strip.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ueda Satoshi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # KindleStrip
2
+
3
+ Strip SRCS records from .mobi
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kindle_strip'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kindle_strip
18
+
19
+ ## Usage
20
+
21
+ $ kindle_strip input.mobi output.mobi
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/kindle_strip ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+ $LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
4
+
5
+ require "kindle_strip"
6
+
7
+ include KindleStrip
8
+
9
+ if ARGV.length == 2
10
+ File.open(ARGV[0], "rb") do |src|
11
+ buf = src.read
12
+ File.open(ARGV[1], "wb") do |dest|
13
+ dest.write(strip_srcs(buf))
14
+ end
15
+ end
16
+ else
17
+ puts "Usage: #{File.basename(__FILE__)} input.mobi output.mobi"
18
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kindle_strip/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "kindle_strip"
8
+ gem.version = KindleStrip::VERSION
9
+ gem.authors = ["Ueda Satoshi"]
10
+ gem.email = ["gunyoki@gmail.com"]
11
+ gem.description = %q{Strip SRCS records from .mobi}
12
+ gem.summary = %q{Amazon kindlegen generates .mobi file and adds a copy of the source files. It doubles the file size. This script strips unwanted payload.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,3 @@
1
+ module KindleStrip
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,130 @@
1
+ require "kindle_strip/version"
2
+
3
+ module KindleStrip
4
+ OFFSET_UNIQUE_ID_SEED = 68
5
+ OFFSET_NUMBER_OF_RECORDS = 76
6
+ OFFSET_RECORD_INFO = 78
7
+
8
+ def strip_srcs(input)
9
+ if input[0x3c, 8] != "BOOKMOBI"
10
+ raise "MobiPocket marker not found"
11
+ end
12
+ num_records = uint16_be(input, OFFSET_NUMBER_OF_RECORDS)
13
+ record0 = get_record0(input)
14
+ srcs_start = uint32_be(record0, 0xe0)
15
+ srcs_count = uint32_be(record0, 0xe4)
16
+ if srcs_start == 0xffffffff || srcs_count == 0
17
+ raise "File doesn't contain SRCS"
18
+ end
19
+ srcs_offset = uint32_be(input, OFFSET_RECORD_INFO + srcs_start * 8)
20
+ srcs_length = uint32_be(input, OFFSET_RECORD_INFO + (srcs_start + srcs_count) * 8) - srcs_offset
21
+ if input[srcs_offset, 4] != "SRCS"
22
+ raise "SRCS section num does not point to SRCS"
23
+ end
24
+
25
+ output = new_header(input, num_records - srcs_count)
26
+ output += new_record_infos(input, num_records, srcs_start, srcs_count, srcs_length)
27
+ output += make_padding(output)
28
+ output += new_records(input, srcs_offset, srcs_length)
29
+ fix_record0(record0, srcs_start, srcs_count)
30
+ set_record0(output, record0)
31
+ output
32
+ end
33
+
34
+ def get_record0(buf)
35
+ record0_offset = uint32_be(buf, OFFSET_RECORD_INFO)
36
+ record1_offset = uint32_be(buf, OFFSET_RECORD_INFO + 8)
37
+ buf[record0_offset ... record1_offset]
38
+ end
39
+ private :get_record0
40
+
41
+ def set_record0(buf, record0)
42
+ record0_offset = uint32_be(buf, OFFSET_RECORD_INFO)
43
+ record1_offset = uint32_be(buf, OFFSET_RECORD_INFO + 8)
44
+ buf[record0_offset ... record1_offset] = record0
45
+ end
46
+ private :set_record0
47
+
48
+ def new_header(input, num_records)
49
+ header = input[0 ... OFFSET_RECORD_INFO]
50
+ header[OFFSET_UNIQUE_ID_SEED, 4] = [num_records * 2 + 1].pack("N")
51
+ header[OFFSET_NUMBER_OF_RECORDS, 2] = [num_records].pack("n")
52
+ header
53
+ end
54
+ private :new_header
55
+
56
+ def new_record_infos(input, num_records, srcs_start, srcs_count, srcs_length)
57
+ srcs_end = srcs_start + srcs_count
58
+ record_infos = ""
59
+ num_records.times do |i|
60
+ next if (srcs_start ... srcs_end) === i
61
+ offset = uint32_be(input, OFFSET_RECORD_INFO + i * 8)
62
+ attr_and_id = uint32_be(input, OFFSET_RECORD_INFO + i * 8 + 4)
63
+ offset -= srcs_count * 8
64
+ if i >= srcs_end
65
+ offset -= srcs_length
66
+ attr_and_id = (i - srcs_count) * 2 | (attr_and_id & 0xff000000)
67
+ end
68
+ record_infos += [offset, attr_and_id].pack("NN")
69
+ end
70
+ record_infos
71
+ end
72
+ private :new_record_infos
73
+
74
+ def make_padding(output)
75
+ record_offset = uint32_be(output, OFFSET_RECORD_INFO)
76
+ [].pack("x#{record_offset - output.length}") # padding by NUL
77
+ end
78
+ private :make_padding
79
+
80
+ def new_records(input, srcs_offset, srcs_length)
81
+ record_offset = uint32_be(input, OFFSET_RECORD_INFO)
82
+ records = input[record_offset .. -1]
83
+ records[srcs_offset - record_offset, srcs_length] = "" # remove SRCS
84
+ records
85
+ end
86
+ private :new_records
87
+
88
+ def fix_record0(record0, srcs_start, srcs_count)
89
+ record0[0xe0, 8] = [0xffffffff, 0].pack("NN") # set no SRCS
90
+ fix_exth(record0, srcs_start, srcs_count)
91
+ end
92
+ private :fix_record0
93
+
94
+ def fix_exth(record0, srcs_start, srcs_count)
95
+ unless uint32_be(record0, 0x80) & 0x40
96
+ # no EXTH header
97
+ return
98
+ end
99
+ exth_offset = 16 + uint32_be(record0, 0x14)
100
+ exth = record0[exth_offset .. -1]
101
+ if exth[0, 4] != "EXTH"
102
+ # marker not found
103
+ return
104
+ end
105
+ num_records = uint32_be(exth, 8)
106
+ pos = 12
107
+ num_records.times do |i|
108
+ type = uint32_be(exth, pos)
109
+ size = uint32_be(exth, pos + 4)
110
+ if type == 121
111
+ boundary = uint32_be(exth, pos + 8)
112
+ if srcs_start <= boundary
113
+ record0[exth_offset + pos + 8, 4] = [boundary - srcs_count].pack("N")
114
+ end
115
+ end
116
+ pos += size
117
+ end
118
+ end
119
+ private :fix_exth
120
+
121
+ def uint16_be(buf, offset = 0)
122
+ buf.unpack("@#{offset}n").first
123
+ end
124
+ private :uint16_be
125
+
126
+ def uint32_be(buf, offset = 0)
127
+ buf.unpack("@#{offset}N").first
128
+ end
129
+ private :uint32_be
130
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kindle_strip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ueda Satoshi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-02 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Strip SRCS records from .mobi
15
+ email:
16
+ - gunyoki@gmail.com
17
+ executables:
18
+ - kindle_strip
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - bin/kindle_strip
28
+ - kindle_strip.gemspec
29
+ - lib/kindle_strip.rb
30
+ - lib/kindle_strip/version.rb
31
+ homepage: ''
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.23
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Amazon kindlegen generates .mobi file and adds a copy of the source files.
55
+ It doubles the file size. This script strips unwanted payload.
56
+ test_files: []