Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Aportis.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <string.h>
00003 #include "Aportis.h"
00004 #include "my_list.h"
00005 #include "Bkmks.h"
00006 
00007 Aportis::Aportis() : peanutfile(false) { /*printf("constructing:%x\n",fin);*/ }
00008 
00009 void Aportis::dePeanut(int& ch)
00010 {
00011     if (peanutfile && ch != EOF)
00012     {
00013         unsigned char c = ch;
00014         if (peanutfile) c ^= 0xa5;
00015         ch = c;
00016     }
00017 }
00018 
00019 CList<Bkmk>* Aportis::getbkmklist()
00020 {
00021 /*
00022     if (peanutfile)
00023     {
00024         if (nRecs2 > nRecs)
00025         {
00026             CList<Bkmk>* t = new CList<Bkmk>;
00027             for (int i = nRecs; i < nRecs2; i++)
00028             {
00029                 char name[17];
00030                 name[16] = '\0';
00031 //              qDebug("Record:%d, Length:%u",i,recordlength(i));
00032                 gotorecordnumber(i);
00033                 fread(name,1,16,fin);
00034                 unsigned long lcn;
00035                 fread(&lcn,sizeof(lcn),1,fin);
00036                 lcn ^= 0xa5a5a5a5;
00037                 lcn = SwapLong(lcn);
00038 //              qDebug("Bookmark:%s:%u", name,lcn);
00039                 tchar tname[17];
00040                 memset(tname, 0, sizeof(tname));
00041                 for (int i = 0; name[i] != 0; i++)
00042                 {
00043                     tname[i] = name[i] ^ 0xa5;
00044                 }
00045                 t->push_back(Bkmk(tname, NULL, lcn));
00046             }
00047             return t;
00048         }
00049         else
00050         {
00051             return NULL;
00052         }
00053     }
00054 */
00055   if (bCompressed != 4) return NULL;
00056   CList<Bkmk>* t = new CList<Bkmk>;
00057   unsuspend();
00058   size_t cur = ftell(fin);
00059   for (int i = 0; i < nRecs2; i++)
00060     {
00061       DWORD dwPos;
00062       fseek(fin, 0x56 + 8*i, SEEK_SET);
00063       fread(&dwPos, 4, 1, fin);
00064       dwPos = SwapLong(dwPos);
00065       fseek(fin,dwPos,SEEK_SET);
00066       unsigned char ch;
00067       fread(&ch,1,1,fin);
00068       if (ch != 241)
00069       {
00070         char name[17];
00071         name[16] = '\0';
00072         fseek(fin,dwPos,SEEK_SET);
00073         fread(name,1,16,fin);
00074         unsigned long lcn;
00075         fread(&lcn,sizeof(lcn),1,fin);
00076         lcn = SwapLong(lcn);
00077 #ifdef _UNICODE
00078         tchar tname[17];
00079         memset(tname, 0, sizeof(tname));
00080         for (int i = 0; name[i] != 0; i++)
00081         {
00082             tname[i] = name[i];
00083         }
00084         t->push_back(Bkmk(tname, NULL, lcn));
00085 #else
00086         t->push_back(Bkmk(name,lcn));
00087 #endif
00088       }
00089     }
00090   fseek(fin, cur, SEEK_SET);
00091   return t;
00092 }
00093 
00094 int Aportis::OpenFile(const char *src)
00095 {
00096   //  printf("In openfile\n");
00097   int ret = 0;
00098   html = false;
00099   mobiimagerec = 0;
00100   if (!Cpdb::openpdbfile(src)) return -1;
00101 
00102   if (head.creator == 0x64414552 //   'dAER'
00103       || head.type == 0x74584554) // 'tXET')
00104     {
00105     }
00106   else if (memcmp(&head.creator, "PPrs", 4) == 0 && memcmp(&head.type, "PNRd", 4) == 0)
00107     {
00108       peanutfile = true;
00109     }
00110   else if (memcmp(&head.creator, "MOBI", 4) == 0 && memcmp(&head.type, "BOOK", 4) == 0)
00111     {
00112       html = true;
00113       unsigned char vsn;
00114       fseek(fin, recordpos(0)+39, SEEK_SET);
00115       fread(&vsn, 1, sizeof(vsn), fin);
00116       qDebug("Mobi version:%x", vsn);
00117       if (vsn > 2)
00118          {
00119             fseek(fin, recordpos(0)+110, SEEK_SET);
00120             fread(&mobiimagerec, 1, sizeof(mobiimagerec), fin);
00121             mobiimagerec = ntohs(mobiimagerec)-1;
00122          }
00123     }
00124   else
00125     {
00126       return -2;
00127     }
00128 
00129   nRecs2 = nRecs = SwapWord(head.recordList.numRecords) - 1;
00130 
00131   struct stat _stat;
00132   stat(src,&_stat);
00133   dwLen = _stat.st_size;
00134 
00135   //fseek(fin,0,SEEK_END);
00136   //dwLen = ftell(fin);
00137 
00138   if (peanutfile)
00139   {
00140       
00141       PeanutHeader hdr0;
00142       gotorecordnumber(0);
00143       fread(&hdr0, sizeof(hdr0), 1, fin);
00144 //      qDebug("Version:%x", ntohs(hdr0.Version));
00145       if (hdr0.Version && 0x0200)
00146       {
00147           bCompressed = 2;
00148       }
00149       else
00150       {
00151           bCompressed = 1;
00152       }
00153       BlockSize = 4096;
00154       nRecs = SwapWord(hdr0.Records)-1;
00155       dwTLen = nRecs*BlockSize;
00156   }
00157   else
00158   {
00159       gotorecordnumber(0);
00160       tDocRecord0 hdr0;
00161       fread(&hdr0, sizeof(hdr0), 1, fin);
00162       bCompressed = SwapWord(hdr0.wVersion);
00163       if (bCompressed!=1 && bCompressed!=2 && bCompressed != 4) {
00164           qDebug("ERROR:Unrecognised compression type in Aportis:%u", bCompressed);
00165         ret = bCompressed;
00166           bCompressed = 2;
00167       }
00168       switch (bCompressed)
00169       {
00170           case 4:
00171           {
00172               dwTLen = 0;
00173               int i;
00174               for (i = 0; i < nRecs; i++)
00175               {
00176                   unsigned int bs = GetBS(i);
00177                   if (bs == 0) break;
00178                   else dwTLen += bs;
00179               }
00180               nRecs = i;
00181               BlockSize = 0;
00182           }
00183           break;
00184           case 1:
00185           case 2:
00186           default:
00187               nRecs = SwapWord(hdr0.wNumRecs);
00188               if (mobiimagerec == 0 || mobiimagerec > nRecs2) mobiimagerec = nRecs;
00189               dwTLen = SwapLong(hdr0.dwStoryLen);
00190               BlockSize = SwapWord(hdr0.wRecSize);
00191               if (BlockSize == 0)
00192               {
00193                   BlockSize = 4096;
00194                   printf("WARNING: Blocksize not set in source file\n");
00195               }
00196       }
00197   }
00198    
00199   qDebug("Mobi image rec:%u", mobiimagerec);
00200 
00201   // this is the main record buffer
00202   // it knows how to stretch to accomodate the decompress
00203   currentrec = 0;
00204   cbptr = 0;
00205   outptr = 0;
00206   refreshbuffer();
00207   if (!html)
00208     {
00209       int c;
00210       char htmltag[] = "<HTML>";
00211       char *p = htmltag;
00212       while (1)
00213         {
00214           c = getch();
00215           char ch = *p++;
00216           if (ch == 0)
00217             {
00218               html = true;
00219               break;
00220             }
00221           if (c != ch)
00222             {
00223               html = false;
00224               break;
00225             }
00226         }
00227       currentrec = 0;
00228       cbptr = 0;
00229       outptr = 0;
00230       refreshbuffer();
00231     }
00232   /*
00233      for (int i = 0; i < nRecs2; i++)
00234      {
00235         qDebug("Record:%u - %u bytes at position %x", i, recordlength(i), recordpos(i));
00236      }
00237   */
00238 
00239   qDebug("Number of records:[%u,%u]", nRecs, nRecs2);
00240   return ret;
00241 }
00242 
00243 int Aportis::getch()
00244 {
00245   if (bCompressed == 1)
00246     {
00247       if ((dwRecLen == 0) && !refreshbuffer()) return EOF;
00248       else
00249         {
00250 unsuspend();
00251           int c = getc(fin);
00252           dePeanut(c);
00253           dwRecLen--;
00254           currentpos++;
00255           return c;
00256         }
00257     }
00258   if (outptr != cbptr)
00259     {
00260       currentpos++;
00261       return (circbuf[outptr = (outptr + 1) % 2048]);
00262     }
00263   if ((dwRecLen == 0) && !refreshbuffer()) return EOF;
00264   currentpos++;
00265   int c;
00266 
00267   // take a char from the input buffer
00268 unsuspend();
00269   c = getc(fin);
00270   dePeanut(c);
00271   dwRecLen--;
00272   // separate the char into zones: 0, 1...8, 9...0x7F, 0x80...0xBF, 0xC0...0xFF
00273 
00274   // codes 1...8 mean copy that many chars; for accented chars & binary
00275   if (c == 0)
00276     {
00277       circbuf[outptr = cbptr = (cbptr+1)%2048] = c;
00278       return c;
00279     }
00280   else if (c >= 0x09 && c <= 0x7F)
00281     {
00282       circbuf[outptr = cbptr = (cbptr+1)%2048] = c;
00283       return c;
00284     }
00285   else if (c >= 0x01 && c <= 0x08)
00286     {
00287       dwRecLen -= c;
00288       while(c--)
00289         {
00290             int c = getc(fin);
00291             dePeanut(c);
00292             circbuf[cbptr = (cbptr+1)%2048] = c;
00293         }
00294       return circbuf[outptr = (outptr+1)%2048];
00295     }
00296   else if (c >= 0x80 && c <= 0xBF)
00297     {
00298       int m,n;
00299       c <<= 8;
00300       int c1 = getc(fin);
00301       dePeanut(c1);
00302       c += c1;
00303       dwRecLen--;
00304       m = (c & 0x3FFF) >> COUNT_BITS;
00305       n = c & ((1<<COUNT_BITS) - 1);
00306       n += 3;
00307       while (n--)
00308         {
00309           cbptr = (cbptr+1)%2048;
00310           circbuf[cbptr] = circbuf[(cbptr+2048-m)%2048];
00311         }
00312       return circbuf[outptr = (outptr+1)%2048];
00313     }
00314   else if (c >= 0xC0 && c <= 0xFF)
00315     {
00316       circbuf[cbptr = (cbptr+1)%2048] = ' ';
00317       circbuf[cbptr = (cbptr+1)%2048] = c^0x80;
00318       return circbuf[outptr = (outptr+1)%2048];
00319     }
00320 }
00321 
00322 unsigned int Aportis::GetBS(unsigned int bn)
00323 {
00324   DWORD dwPos;
00325   WORD fs;
00326 unsuspend();
00327   fseek(fin, 0x56 + 8*bn, SEEK_SET);
00328   fread(&dwPos, 4, 1, fin);
00329   dwPos = SwapLong(dwPos);
00330   fseek(fin,dwPos,SEEK_SET);
00331 
00332 //  gotorecordnumber(bn+1);
00333   unsigned char ch;
00334   fread(&ch,1,1,fin);
00335   if (ch == 241)
00336     {
00337       fread(&fs,sizeof(fs),1,fin);
00338       fs = SwapWord(fs);
00339     }
00340   else
00341     fs = 0;
00342   return fs;
00343 }
00344 
00345 unsigned int Aportis::locate()
00346 {
00347   if (bCompressed == 4)
00348     {
00349 unsuspend();
00350       size_t cur = ftell(fin);
00351       unsigned int clen = 0;
00352       for (unsigned int i = 0; i < currentrec-1; i++)
00353         {
00354           unsigned int bs = GetBS(i);
00355           if (bs == 0) break;
00356           clen += bs;
00357         }
00358       fseek(fin,cur,SEEK_SET);
00359       return clen+currentpos;
00360     }
00361   else
00362     return (currentrec-1)*BlockSize+currentpos;
00363 }
00364 
00365 void Aportis::locate(unsigned int n)
00366 {
00367   unsigned int offset;
00368   //  currentrec = (n >> OFFBITS);
00369   switch (bCompressed)
00370     {
00371     case 4:
00372       {
00373         DWORD clen = 0;
00374         offset = n;
00375         unsigned int i;
00376         for (i = 0; i < nRecs; i++)
00377           {
00378             unsigned int bs = GetBS(i);
00379             if (bs == 0) break;
00380             clen += bs;
00381             if (clen > n) break;
00382             offset = n - clen;
00383           }
00384         currentrec = i;
00385       }
00386       break;
00387     case 1:
00388     case 2:
00389     default:
00390       currentrec = n / BlockSize;
00391       offset = n % BlockSize;
00392     }
00393 
00394   outptr = cbptr;
00395   refreshbuffer();
00396   while (currentpos < offset && getch() != EOF);
00397 }
00398 
00399 bool Aportis::refreshbuffer()
00400 {
00401   if (currentrec < nRecs)
00402     {
00403         dwRecLen = recordlength(currentrec+1);
00404         gotorecordnumber(currentrec+1);
00405       if (bCompressed == 4)
00406         {
00407           unsigned char t[3];
00408           unsuspend();
00409           fread(t,1,3,fin);
00410           if (t[0] != 241)
00411             {
00412               printf("You shouldn't be here!\n");
00413               return false;
00414             }
00415           dwRecLen -= 3;
00416         }
00417       /*
00418         int n = fread(t.buf, 1, dwRecLen, fin);
00419         t.len = n;
00420         //              if(bCompressed)
00421         t.Decompress();
00422 
00423         t.buf[t.Len()] = '\0';
00424       */
00425       currentpos = 0;
00426       currentrec++;
00427       return true;
00428     }
00429   else {
00430     return false;
00431   }
00432 }
00433 
00434 #include <qimage.h>
00435 
00436 QImage* Aportis::getPicture(unsigned long tgt)
00437 {
00438 unsuspend();
00439   unsigned short tgtrec = tgt+mobiimagerec;
00440   if (tgtrec > nRecs2) return NULL;
00441   size_t cur = ftell(fin);
00442   unsigned short reclen = recordlength(tgtrec);
00443   gotorecordnumber(tgtrec);
00444   UInt8* imgbuffer = new UInt8[reclen];
00445   fread(imgbuffer, 1, reclen, fin);
00446   QByteArray arr;
00447   arr.assign((const char*)imgbuffer, reclen);
00448 
00449   QImage* qimage = new QImage(arr);
00450   fseek(fin, cur, SEEK_SET);
00451 
00452   return qimage;
00453 }
00454 
00455 #ifndef __STATIC
00456 extern "C"
00457 {
00458   CExpander* newcodec() { return new Aportis; }
00459 }
00460 #endif

Generated on Sat Nov 5 16:16:53 2005 for OPIE by  doxygen 1.4.2