bool DetectEpubFormat( LVStreamRef stream ) { LVContainerRef m_arc = LVOpenArchieve( stream ); if ( m_arc.isNull() ) return false; // not a ZIP archive //dumpZip( m_arc ); // read "mimetype" file contents from root of archive lString16 mimeType; { LVStreamRef mtStream = m_arc->OpenStream(L"mimetype", LVOM_READ ); if ( !mtStream.isNull() ) { int size = mtStream->GetSize(); if ( size>4 && size<100 ) { LVArray<char> buf( size+1, '\0' ); if ( mtStream->Read( buf.get(), size, NULL )==LVERR_OK ) { for ( int i=0; i<size; i++ ) if ( buf[i]<32 || ((unsigned char)buf[i])>127 ) buf[i] = 0; buf[size] = 0; if ( buf[0] ) mimeType = Utf8ToUnicode( lString8( buf.get() ) ); } } } } if ( mimeType != L"application/epub+zip" ) return false; return true; }
bool read( LVStreamRef stream ) { // TODO: byte order support lvsize_t bytesRead = 0; if ( stream->Read(this, sizeof(PDBHdr), &bytesRead )!=LVERR_OK ) return false; if ( bytesRead!=sizeof(PDBHdr) ) return false; lvByteOrderConv cnv; if ( cnv.lsf() ) { cnv.rev(&attributes); cnv.rev(&version); cnv.rev(&creationDate); cnv.rev(&modificationDate); cnv.rev(&lastBackupDate); cnv.rev(&modificationNumber); cnv.rev(&appInfoID); cnv.rev(&sortInfoID); cnv.rev(&uniqueIDSeed); cnv.rev(&nextRecordList); cnv.rev(&recordCount); cnv.rev(&firstEntry); } return true; }
lString8 readFileToString( const char * fname ) { lString8 buf; LVStreamRef stream = LVOpenFileStream(fname, LVOM_READ); if (!stream) return buf; int sz = stream->GetSize(); if (sz>0) { buf.insert( 0, sz, ' ' ); stream->Read( buf.modify(), sz, NULL ); } return buf; }
//lUInt8 uniqueID[3]; bool read( LVStreamRef stream ) { // TODO: byte order support lvsize_t bytesRead = 0; if ( stream->Read(this, sizeof(PDBRecordEntry), &bytesRead )!=LVERR_OK ) return false; if ( bytesRead!=sizeof(PDBRecordEntry) ) return false; lvByteOrderConv cnv; if ( cnv.lsf() ) { cnv.rev(&localChunkId); } return true; }
jbyteArray CRJNIEnv::streamToJByteArray( LVStreamRef stream ) { if ( stream.isNull() ) return NULL; unsigned sz = stream->GetSize(); if ( sz<10 || sz>2000000 ) return NULL; jbyteArray array = env->NewByteArray(sz); lUInt8 * array_data = (lUInt8 *)env->GetByteArrayElements(array, 0); lvsize_t bytesRead = 0; stream->Read(array_data, sz, &bytesRead); env->ReleaseByteArrayElements(array, (jbyte*)array_data, 0); if (bytesRead != sz) return NULL; return array; }
bool read( LVStreamRef stream ) { // TODO: byte order support lvsize_t bytesRead = 0; if ( stream->Read(this, sizeof(MobiPreamble), &bytesRead )!=LVERR_OK ) return false; if ( bytesRead!=sizeof(MobiPreamble) ) return false; lvByteOrderConv cnv; if ( cnv.lsf() ) { cnv.rev(&compression); // 2 Compression 1 == no compression, 2 = PalmDOC compression (see below) cnv.rev(&textLength); // 4 text length Uncompressed length of the entire text of the book cnv.rev(&recordCount); // 2 record count Number of PDB records used for the text of the book. cnv.rev(&recordSize); // 2 record size Maximum size of each record containing text, always 4096 cnv.rev(&mobiEncryption);// 2 Encryption Type 0 == no encryption, 1 = Old Mobipocket Encryption, 2 = Mobipocket Encryption cnv.rev(&hederLength); // 20 4 header length the length of the MOBI header, including the previous 4 bytes cnv.rev(&mobiType); // 24 4 Mobi type The kind of Mobipocket file this is cnv.rev(&encoding); // 28 4 text Encoding 1252 = CP1252 (WinLatin1); 65001 = UTF-8 cnv.rev(&uid); // 32 4 Unique-ID Some kind of unique ID number (random?) cnv.rev(&fileVersion); // 36 4 File version Version of the Mobipocket format used in this file. cnv.rev(&firstNonBookIndex); // 80 4 First Non-book index? First record number (starting with 0) that's not the book's text cnv.rev(&fullNameOffset); // 84 4 Full Name Offset Offset in record 0 (not from start of file) of the full name of the book cnv.rev(&fullNameLength); // 88 4 Full Name Length Length in bytes of the full name of the book cnv.rev(&locale); // 92 4 Locale Book locale code. Low byte is main language 09= English, next byte is dialect, 08 = British, 04 = US. Thus US English is 1033, UK English is 2057. cnv.rev(&inputLanguage); // 96 4 Input Language Input language for a dictionary cnv.rev(&outputLanguage); // 100 4 Output Language Output language for a dictionary cnv.rev(&minVersion); // 104 4 Min version Minimum mobipocket version support needed to read this file. cnv.rev(&firstImageIndex); // 108 4 First Image index? First record number (starting with 0) that contains an image. Image records should be sequential. cnv.rev(&huffmanRecordOffset); // 112 4 Huffman Record Offset The record number of the first huffman compression record. cnv.rev(&huffmanRecordCount); // 116 4 Huffman Record Count The number of huffman compression records. cnv.rev(&mobiFlags); // 128 4 EXTH flags bitfield. if bit 6 (0x40) is set, then there's an EXTH record cnv.rev(&drmOffset); // 164 4 DRM Offset Offset to DRM key info in DRMed files. 0xFFFFFFFF if no DRM cnv.rev(&drmCount); // 168 4 DRM Count Number of entries in DRM info. 0xFFFFFFFF if no DRM cnv.rev(&drmSize); // 172 4 DRM Size Number of bytes in DRM info. cnv.rev(&drmFlags); // 176 4 DRM Flags Some flags concerning the DRM info. } if ( compression!=1 && compression!=2 ) return false; if ( mobiType!=2 && mobiType!=3 && mobiType!=517 && mobiType!=518 && mobiType!=257 && mobiType!=258 && mobiType!=259 ) return false; // unsupported type if ( mobiEncryption!=0 ) return false; // encryption is not supported return true; }
bool read( LVStreamRef stream ) { // TODO: byte order support lvsize_t bytesRead = 0; if ( stream->Read(this, sizeof(PalmDocPreamble), &bytesRead )!=LVERR_OK ) return false; if ( bytesRead!=sizeof(PalmDocPreamble) ) return false; lvByteOrderConv cnv; if ( cnv.lsf() ) { cnv.rev(&compression); // 2 Compression 1 == no compression, 2 = PalmDOC compression (see below) cnv.rev(&textLength); // 4 text length Uncompressed length of the entire text of the book cnv.rev(&recordCount); // 2 record count Number of PDB records used for the text of the book. cnv.rev(&recordSize); // 2 record size Maximum size of each record containing text, always 4096 } if ( compression!=1 && compression!=2 ) return false; return true; }
static int getCoverPageImageData(lua_State *L) { CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument"); LVStreamRef stream = doc->text_view->getCoverPageImageStream(); if (!stream.isNull()) { unsigned size = stream->GetSize(); lvsize_t read_size = 0; void *buffer = (void *)malloc(size); if (buffer != NULL) { stream->Read(buffer, size, &read_size); if (read_size == size) { lua_pushlightuserdata(L, buffer); lua_pushinteger(L, size); return 2; } } } return 0; }
void V3DocViewWin::showHelpDialog() { LVStreamRef stream = LVOpenFileStream( _helpFile.c_str(), LVOM_READ ); lString8 help; if ( stream.isNull() ) { // show warning lString8 body; body << "<title><p>" << _("No manual currently available for this language, sorry!") << "</p></title>"; help = CRViewDialog::makeFb2Xml( body ); } else { int len = stream->GetSize(); if ( len>100 && len <1000000 ) { help.append( len, ' ' ); stream->Read( help.modify(), len, NULL ); } } //lString8 help = UnicodeToUtf8( LVReadTextFile( _helpFile ) ); if ( !help.empty() ) { CRViewDialog * dlg = new CRViewDialog( _wm, lString16(_("Help")), help, lvRect(), true, true ); _wm->activateWindow( dlg ); } }
bool read( LVStreamRef stream ) { lvsize_t bytesRead = 0; if ( stream->Read(this, sizeof(EReaderHeader), &bytesRead )!=LVERR_OK ) return false; if ( bytesRead!=sizeof(EReaderHeader) ) return false; lvByteOrderConv cnv; if ( cnv.lsf() ) { cnv.rev(&compression); // 0-2 compression Specifies compression and drm. 2 = palmdoc, 10 = zlib. 260 and 272 = DRM cnv.rev(&encoding); // 6-8 encoding Always 25152 (0x6240). All text must be encoded as Latin-1 cp1252 cnv.rev(&smallPageCount); // 8-10 Number of small pages The number of small font pages. If page index is not build in then 0. cnv.rev(&largePageCount); // 10-12 Number of large pages The number of large font pages. If page index is not build in then 0. cnv.rev(&nonTextRecordStart); //12-14 Non-Text record start The location of the first non text records. record 1 to this value minus 1 are all text records cnv.rev(&numberOfChapters);// 14-16 Number of chapters The number of chapter index records contained in the file cnv.rev(&smallPageRecordCount); // 16-18 Number of small index The number of small font page index records contained in the file cnv.rev(&largePageRecordCount); // 18-20 Number of large index The number of large font page index records contained in the file cnv.rev(&imageCount); // 20-22 Number of images The number of images contained in the file cnv.rev(&linkCount); // 22-24 Number of links The number of links contained in the file cnv.rev(&metadataAvailable); // 24-26 Metadata avaliable Is there a metadata record in the file? 0 = None, 1 = There is a metadata record cnv.rev(&footnoteRecordsCount); // 28-30 Number of Footnotes The number of footnote records in the file cnv.rev(&sidebarRecordsCount); // 30-32 Number of Sidebars The number of sidebar records in the file cnv.rev(&chapterIndexStart); // 32-34 Chapter index record start The location of chapter index records. If there are no chapters use the value for the Last data record. cnv.rev(&smallPageIndexStart); // 36-38 Small page index start The location of small font page index records. If page table is not built in use the value for the Last data record. cnv.rev(&largePageIndexStart); // 38-40 Large page index start The location of large font page index records. If page table is not built in use the value for the Last data record. cnv.rev(&imageDataRecordStart); // 40-42 Image data record start The location of the first image record. If there are no images use the value for the Last data record. cnv.rev(&linksRecordStart); // 42-44 Links record start The location of the first link index record. If there are no links use the value for the Last data record. cnv.rev(&metadataRecordStart); // 44-46 Metadata record start The location of the metadata record. If there is no metadata use the value for the Last data record. cnv.rev(&footnoteRecordStart); // 48-50 Footnote record start The location of the first footnote record. If there are no footnotes use the value for the Last data record. cnv.rev(&sidebarRecordStart); // 50-52 Sidebar record start The location of the first sidebar record. If there are no sidebars use the value for the Last data record. cnv.rev(&lastDataRecord); // 52-54 Last data record The location of the last data record } if ( compression!=1 && compression!=2 && compression!=10 ) return false; return true; }
bool TexHyph::load( LVStreamRef stream ) { int w = isCorrectHyphFile(stream.get()); int patternCount = 0; if (w) { _hash = stream->crc32(); int i; lvsize_t dw; lvByteOrderConv cnv; int hyph_count = w; thyph hyph; lvpos_t p = 78 + (hyph_count * 8 + 2); stream->SetPos(p); if ( stream->SetPos(p)!=p ) return false; lChar16 charMap[256]; unsigned char buf[0x10000]; memset( charMap, 0, sizeof( charMap ) ); // make char map table for (i=0; i<hyph_count; i++) { if ( stream->Read( &hyph, 522, &dw )!=LVERR_OK || dw!=522 ) return false; cnv.msf( &hyph.len ); //rword(_main_hyph[i].len); lvpos_t newPos; if ( stream->Seek( hyph.len, LVSEEK_CUR, &newPos )!=LVERR_OK ) return false; cnv.msf( hyph.wl ); cnv.msf( hyph.wu ); charMap[ (unsigned char)hyph.al ] = hyph.wl; charMap[ (unsigned char)hyph.au ] = hyph.wu; // lChar16 ch = hyph.wl; // CRLog::debug("wl=%s mask=%c%c", LCSTR(lString16(&ch, 1)), hyph.mask0[0], hyph.mask0[1]); if (hyph.mask0[0]!='0'||hyph.mask0[1]!='0') { unsigned char pat[4]; pat[0] = hyph.al; pat[1] = hyph.mask0[0]; pat[2] = hyph.mask0[1]; pat[3] = 0; TexPattern * pattern = new TexPattern(pat, 1, charMap); #if DUMP_PATTERNS==1 CRLog::debug("Pattern: '%s' - %s", LCSTR(lString16(pattern->word)), pattern->attr ); #endif addPattern( pattern ); patternCount++; } } if ( stream->SetPos(p)!=p ) return false; for (i=0; i<hyph_count; i++) { stream->Read( &hyph, 522, &dw ); if (dw!=522) return false; cnv.msf( &hyph.len ); stream->Read(buf, hyph.len, &dw); if (dw!=hyph.len) return false; unsigned char * p = buf; unsigned char * end_p = p + hyph.len; while ( p < end_p ) { lUInt8 sz = *p++; if ( p + sz > end_p ) break; TexPattern * pattern = new TexPattern( p, sz, charMap ); #if DUMP_PATTERNS==1 CRLog::debug("Pattern: '%s' - %s", LCSTR(lString16(pattern->word)), pattern->attr); #endif addPattern( pattern ); patternCount++; p += sz + sz + 1; } } return patternCount>0; } else { // tex xml format as for FBReader lString16Collection data; HyphPatternReader reader( data ); LVXMLParser parser( stream, &reader ); if ( !parser.CheckFormat() ) return false; if ( !parser.Parse() ) return false; if ( !data.length() ) return false; for ( int i=0; i<(int)data.length(); i++ ) { data[i].lowercase(); TexPattern * pattern = new TexPattern( data[i] ); #if DUMP_PATTERNS==1 CRLog::debug("Pattern: (%s) '%s' - %s", LCSTR(data[i]), LCSTR(lString16(pattern->word)), pattern->attr); #endif addPattern( pattern ); patternCount++; } return patternCount>0; } }
int GetBookProperties(char *name, struct BookProperties* pBookProps, int localLanguage) { CRLog::trace("GetBookProperties( %s )", name); memset(pBookProps, 0, sizeof(BookProperties) ); // open stream LVStreamRef stream = LVOpenFileStream(name, LVOM_READ); if (!stream) { CRLog::error("cannot open file %s", name); return 0; } // check archieve #ifdef USE_ZLIB LVContainerRef arc; //printf("start opening arc\n"); //for ( int i=0; i<1000; i++ ) //for ( int kk=0; kk<1000; kk++) { arc = LVOpenArchieve( stream ); //printf("end opening arc\n"); if (!arc.isNull()) { CRLog::trace("%s is archive with %d items", name, arc->GetObjectCount()); // archieve const LVContainerItemInfo * bestitem = NULL; const LVContainerItemInfo * fb2item = NULL; const LVContainerItemInfo * fbditem = NULL; for (int i=0; i<arc->GetObjectCount(); i++) { const LVContainerItemInfo * item = arc->GetObjectInfo(i); if (item) { if ( !item->IsContainer() ) { lString16 name( item->GetName() ); if ( name.length() > 5 ) { name.lowercase(); const lChar16 * pext = name.c_str() + name.length() - 4; if ( pext[0]=='.' && pext[1]=='f' && pext[2]=='b' && pext[3]=='2') { fb2item = item; } else if ( pext[0]=='.' && pext[1]=='f' && pext[2]=='b' && pext[3]=='d') { fbditem = item; } } } } } bestitem = fb2item; if ( fbditem ) bestitem = fbditem; if ( !bestitem ) return 0; CRLog::trace( "opening item %s from archive", UnicodeToUtf8(bestitem->GetName()).c_str() ); //printf("start opening stream\n"); //for ( int k=0; k<1000; k++ ) { stream = arc->OpenStream( bestitem->GetName(), LVOM_READ ); char buf[8192]; stream->Read(buf, 8192, NULL ); //} //printf("end opening stream\n"); if ( stream.isNull() ) return 0; CRLog::trace( "stream created" ); // opened archieve stream } } #endif //USE_ZLIB // read document #if COMPACT_DOM==1 ldomDocument doc(stream, 0); #else ldomDocument doc; #endif ldomDocumentWriter writer(&doc, true); doc.setNodeTypes( fb2_elem_table ); doc.setAttributeTypes( fb2_attr_table ); doc.setNameSpaceTypes( fb2_ns_table ); LVXMLParser parser( stream, &writer ); CRLog::trace( "checking format..." ); if ( !parser.CheckFormat() ) { return 0; } CRLog::trace( "parsing..." ); if ( !parser.Parse() ) { return 0; } CRLog::trace( "parsed" ); #if 0 char ofname[512]; sprintf(ofname, "%s.xml", name); CRLog::trace(" writing to file %s", ofname); LVStreamRef out = LVOpenFileStream(ofname, LVOM_WRITE); doc.saveToStream(out, "utf16"); #endif lString16 authors = extractDocAuthors( &doc ); lString16 title = extractDocTitle( &doc ); lString16 series = extractDocSeriesReverse( &doc ); #if SERIES_IN_AUTHORS==1 if ( !series.empty() ) authors << L" " << series; #endif SetFieldValue( pBookProps->name, title ); if ( !authors.empty() ) SetFieldValue( pBookProps->author, authors ); if ( !series.empty() ) SetFieldValue( pBookProps->series, series ); pBookProps->filesize = (long)stream->GetSize(); strncpy( pBookProps->filename, name, MAX_PROPERTY_LEN-1 ); struct stat fs; time_t t; if ( stat( name, &fs ) ) { t = (time_t)time(0); } else { t = fs.st_mtime; } SetFieldValue( pBookProps->filedate, getDateTimeString( t, localLanguage ) ); return 1; }