9 def initialize(fileName)
17 parseFileName!(fileName)
20 def self.canHandle?(fileName)
25 lowerName = fileName.downcase()
27 if lowerName.end_with?(".epub")
42 result.push('<b>' + @title + '</b>')
44 result.push('<i>(Unknown title)</i>')
47 result.push(@author.to_s())
52 seriesInfo.push(@series.to_s)
55 seriesInfo.push(@volume.to_s)
57 if seriesInfo.length > 0
58 result.push(seriesInfo.join(' '))
61 return result.join('<br/>')
67 data.push('author="' + @author.to_s + '"')
70 data.push('series="' + @series + '"')
73 data.push('volume="' + @volume + '"')
76 data.push('title="' + @title + '"')
79 data.push(@cover.inspect())
82 data.push('path="' + @path + '"')
84 return '(Book:' + data.join(',') + ')'
93 return /[[:upper:]]/.match(c)
97 def massageAuthor(input)
103 input.each_char do |c|
104 if isUpper?(c) and (result.length > 0)
113 # Returns (series, volumeNo, titleText)
115 def processTitle(input)
120 arr = input.split('_')
126 matchData = (arr[0]).match(/^([A-Z]+)([0-9]+)$/)
128 capt = matchData.captures
134 pos = arr[-1].rindex('.')
136 arr[-1] = arr[-1].slice(0, pos)
139 title = arr.join(' ')
141 return series, vol, title
145 def parseFileName!(fileName)
146 parts = fileName.split('/')
147 (@series, @volume, @title) = processTitle(parts[-1])
149 @author = massageAuthor(parts[-2])
152 if fileName.downcase.end_with?(".epub")
158 def scanEpub!(fileName)
159 puts 'Scanning "' + fileName.to_s + '"...'
160 Zip::File.open(fileName) do |zipfile|
161 contXml = zipfile.read('META-INF/container.xml')
162 contDoc = Nokogiri::XML(contXml)
163 opfPath = contDoc.css("container rootfiles rootfile")[0]['full-path']
165 scanOpf!(zipfile, opfPath)
170 def scanOpf!(zipfile, opfPath)
173 opfXml = zipfile.read(opfPath)
174 opfDoc = Nokogiri::XML(opfXml)
179 creator = opfDoc.css('dc|creator', 'dc' => 'http://purl.org/dc/elements/1.1/')
181 roleNode = creator.attr('role')
183 role = roleNode.value
185 name = creator.children[0].content
186 parts = name.split(' ')
189 givenNames = parts[0..-2].join(' ')
190 @author = Author.new(surname, givenNames)
192 @author = Author.new(name, '')
198 #---------------------------------------
199 # Other metadata: series, volume, cover
201 metas = opfDoc.css('package metadata meta')
204 content = m['content']
206 if 'calibre:series' == name
208 elsif 'calibre:series-index' == name
210 elsif 'cover' == name
220 items = opfDoc.css('package manifest item')
224 mimeType = i['media-type']
227 entry = zipfile.find_entry(href)
228 entry.get_input_stream() do |is|
229 @cover = Cover.new(is, href, mimeType)