home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Cruncher / XPK416SR.LHA / xpk_Source / xpkmaster / open.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  12.9 KB  |  462 lines

  1. #ifndef XPKMASTER_OPEN_C
  2. #define XPKMASTER_OPEN_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        open.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: open.c 1.8 (18.08.97)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    Opening and initialisation routines for XPK files
  12.  
  13.  1.0   06.10.96 : first real version
  14.  1.1   28.10.96 : reincluded A4 support
  15.  1.2   03.03.97 : added Prefs, corrected length recognition
  16.  1.3   07.03.97 : fixed prefs handling, new features
  17.  1.4   09.03.97 : added DEBUG statement
  18.  1.5   28.03.97 : auto decrunch password
  19.  1.6   29.03.97 : fixed prefs stuff, moved getinlen into hooks
  20.  1.7   31.03.97 : changed the password stuff
  21. */
  22.  
  23. #include <xpk/xpkprefs.h>
  24. #include <exec/memory.h>
  25. #include <proto/exec.h>
  26. #include <proto/dos.h>
  27. #include <proto/xpkmaster.h>
  28. #include "xpkmaster.h"
  29. #include "xpk_strings.h"
  30.  
  31. struct XpkInfo DONTInfo = { 1,0,0,1,"DONT","Copy",
  32. 0, 0x55534552, XPKIF_PK_CHUNK|XPKIF_UP_CHUNK, 50000, 10, 50000,
  33. 0,0,0,0,100,0,0 /* Mode */,0,0,0,0,0,0};
  34.  
  35. static LONG GetPrefsPacker(struct XpkBuffer *xbuf);
  36. static LONG GetPassword(struct XpkBuffer *xbuf, struct TagItem *tags);
  37. static struct XpkTypeData *BufRecog(ULONG, struct XpkBuffer *,
  38.   struct XpkPrefsSemaphore *);
  39.  
  40. #define ROW_OF_MINUS    0x2d2d2d2d    /* '----' */
  41. #define PP_COOKIE    0x50503230    /* 'PP20' */
  42.  
  43. LONG __asm xpkopen(register __a0 struct XpkBuffer **xbufp,
  44. register __a1 struct TagItem *tags, register __d2 ULONG examine A4PROTO)
  45. {
  46.   struct Library     *XpkSubBase;
  47.   struct XpkBuffer     *xbuf;
  48.   struct XpkStreamHeader *globhdr;
  49.   struct XpkFib         *fib;
  50.   LONG bytesread;    /* used to be able to reset after a short read */
  51.  
  52. #if defined(DEBUG) && defined(SUPPORT_A4)
  53.   DebugRunTime("xpkopen: A4 = %ld", a4);
  54. #elif defined (DEBUG)
  55.   DebugRunTime("xpkopen");
  56. #endif
  57.  
  58.   *xbufp = 0;
  59.   if(!(xbuf = initxbuf()))
  60.   {
  61.     parseerrortags(tags);
  62.     return XPKERR_NOMEM;
  63.   }
  64.  
  65. #ifdef SUPPORT_A4
  66.   xbuf->xb_regA4 = a4;
  67. #endif
  68.  
  69.   globhdr = &xbuf->xb_Headers.h_Glob;
  70.   fib = &xbuf->xb_Fib;
  71.  
  72.   if(parsebuftags(xbuf, tags, 0))
  73.     goto Abort;
  74.  
  75.   *xbufp = xbuf;
  76.   if(xbuf->xb_Flags & XMF_PACKING)
  77.     return xpkopenwrite(xbufp, tags);
  78.  
  79.   if(!hookread(xbuf, XIO_READ, globhdr, 4))
  80.   {    /* Read first longword only */
  81.     bytesread = xbuf->xb_RMsg.xmm_Size;
  82.     if(xbuf->xb_Result != XPKERR_TRUNCATED)
  83.       goto Abort;
  84.     /* else handle now as uncompressed file */
  85.   }
  86.   else
  87.     bytesread = 4;
  88.  
  89.   /**************************** Standard XPK file *********************/
  90.   if(globhdr->xsh_Pack == XPK_COOKIE)
  91.   {    /* Standard XPK packed files */
  92.     UWORD exthlen = 0;        /* size of extended header if present */
  93.  
  94.     xbuf->xb_Format = XPKMODE_UPSTD;
  95.  
  96.     /* Read rest of the global header */
  97.     if(!hookread(xbuf, XIO_READ, (STRPTR) globhdr + 4, sizeof(struct XpkStreamHeader) - 4))
  98.       goto Abort;
  99.  
  100.     if(hchecksum((STRPTR) globhdr, sizeof(struct XpkStreamHeader)))
  101.     {
  102.       xbuf->xb_Result = XPKERR_CHECKSUM;
  103.       goto Abort;
  104.     }
  105.  
  106.     if(!examine && globhdr->xsh_Flags & XPKSTREAMF_PASSWORD &&
  107.     !xbuf->xb_Password)
  108.     {
  109.       if((xbuf->xb_Result = GetPassword(xbuf, tags)))
  110.         goto Abort;
  111.     }
  112.  
  113.     if(globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS)
  114.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrLong);
  115.     else
  116.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrWord);
  117.  
  118.     if(globhdr->xsh_Flags & XPKSTREAMF_EXTHEADER)
  119.     {
  120.       if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
  121.     goto Abort;
  122.       if(!hookread(xbuf, XIO_READ, NULL, exthlen))
  123.     goto Abort;
  124.       exthlen += sizeof(UWORD);    /* for unwinding while XpkExamine */
  125.     }
  126.  
  127.     if(!hookread(xbuf, XIO_READ, &xbuf->xb_Headers.h_Loc,
  128.     xbuf->xb_Headers.h_LocSize))    /* first lochdr */
  129.       goto Abort;
  130.  
  131.     xbuf->xb_Fib.xf_CCur = sizeof(struct XpkStreamHeader);
  132.     updatefib(xbuf);
  133.     xbuf->xb_InLen = xbuf->xb_Fib.xf_CLen;
  134.  
  135.     if(!(xbuf->xb_SubBase = XpkSubBase = opensub(xbuf, globhdr->xsh_Type)))
  136.       goto Abort;
  137.  
  138.     if(globhdr->xsh_SubVrs > xbuf->xb_SubInfo->xi_LibVersion)
  139.     {
  140.       xbuf->xb_Result = XPKERR_OLDSUBLIB;
  141.       goto Abort;
  142.     }
  143.  
  144.     xbuf->xb_ULen = globhdr->xsh_ULen;
  145.     xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_UnpackMsg ?
  146.       xbuf->xb_SubInfo->xi_UnpackMsg : strings[TXT_UNPACKING_UPPER];
  147.     xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  148.     xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_UnpackedMsg ?
  149.       xbuf->xb_SubInfo->xi_UnpackedMsg : strings[TXT_UNPACKED];
  150.  
  151.     if(globhdr->xsh_Flags & XPKSTREAMF_PASSWORD)
  152.       xbuf->xb_Fib.xf_Flags |= XPKFLAGS_PASSWORD;
  153.  
  154.     if(examine && !hookread(xbuf, XIO_SEEK, 0,
  155.     -(sizeof(struct XpkStreamHeader) + xbuf->xb_Headers.h_LocSize+exthlen)))
  156.       goto Abort;
  157.  
  158.     goto Exit;
  159.   }
  160.  
  161.   if(!hookread(xbuf, XIO_SEEK, 0, -bytesread))
  162.     goto Abort;
  163.  
  164.   if(xbuf->xb_InLen == -1)
  165.   {
  166.     if(!hookread(xbuf, XIO_TOTSIZE, 0, 0))    /* get input length */
  167.       return xbuf->xb_Result;
  168.     else if(xbuf->xb_RMsg.xmm_Size)
  169.       xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  170.   }
  171.  
  172. #ifdef USE_POWERPACKER
  173.   /***************************** PowerPacker file ***********************/
  174.   if(globhdr->xsh_Pack == PP_COOKIE)
  175.   {
  176.     struct Library *PPBase;
  177.     LONG outsize;
  178.  
  179.     xbuf->xb_Format = XPKMODE_UPPP;
  180.  
  181.     if(!hookread(xbuf, XIO_SEEK, 0, xbuf->xb_InLen - 4))
  182.       goto Abort;                /* 4 Bytes before EOF */
  183.     if(!hookread(xbuf, XIO_READ, &outsize, 4))
  184.       goto Abort;
  185.     if(!hookread(xbuf, XIO_SEEK, 0, - (xbuf->xb_InLen - 4) - (examine<<2)))
  186.       goto Abort;    /* back to start when examine, else 4 bytes later */
  187.  
  188.     outsize >>= 8;
  189.  
  190. #ifdef DEBUG
  191.     DebugRunTime("xpkopen: PP, InLen %ld, OutLen %ld", xbuf->xb_InLen,
  192.     outsize);
  193. #endif
  194.  
  195.     fib->xf_Type = XPKTYPE_PACKED;
  196.     fib->xf_CLen = xbuf->xb_InLen;
  197.     fib->xf_ULen = outsize;
  198.     fib->xf_NLen = outsize + XPK_MARGIN;
  199.     fib->xf_ID = PP_COOKIE;
  200.     percentages(fib);
  201.  
  202.     if(examine)
  203.       goto Exit;
  204.  
  205.     xbuf->xb_Prog.xp_Activity = strings[TXT_UNPACKING_UPPER];
  206.     xbuf->xb_Prog.xp_PackerName = "PowerPacker";
  207.     xbuf->xb_LastMsg = strings[TXT_UNPACKED];
  208.     xbuf->xb_ULen = outsize;
  209.  
  210.     if(!(PPBase = OpenLibrary ("powerpacker.library", 0)))
  211.     {
  212.       xbuf->xb_Result = XPKERR_MISSINGLIB;
  213.       goto Abort;
  214.     }
  215.     xbuf->xb_SubBase = PPBase;
  216.  
  217.     goto Exit;
  218.   }
  219. #endif /* USE_POWERPACKER */
  220.  
  221.   /**************************** Uncompressed file *************************/
  222.   if(examine || xbuf->xb_Flags & XMF_PASSTHRU)        /* Unpacked */
  223.   {
  224.     xbuf->xb_Format = XPKMODE_UPUP;
  225.  
  226.     fib->xf_Type = XPKTYPE_UNPACKED;
  227.     fib->xf_CLen = xbuf->xb_InLen;
  228.     fib->xf_ULen = xbuf->xb_InLen;
  229.     fib->xf_NLen = Min(CHUNKSIZE, xbuf->xb_InLen) + XPK_MARGIN;
  230.     fib->xf_ID = ROW_OF_MINUS;
  231.  
  232.     xbuf->xb_Prog.xp_Activity = strings[TXT_READING];
  233.     xbuf->xb_Prog.xp_PackerName = "MASTER";
  234.     xbuf->xb_LastMsg = strings[TXT_READ];
  235.     xbuf->xb_ULen = xbuf->xb_InLen;
  236.  
  237.     xbuf->xb_Result = XPKERR_OK;    /* if != 0 is was XPKERR_TRUNCATED */
  238.  
  239.     goto Exit;
  240.   }
  241.  
  242.   xbuf->xb_Result = XPKERR_NOTPACKED;    /* Can't unpack, can't passthru */
  243.  
  244. Abort:
  245.   *xbufp = 0;
  246.   return XpkClose((struct XpkFib *) xbuf);
  247.  
  248. Exit:
  249.   *xbufp = xbuf;
  250.   return XPKERR_OK;
  251. }
  252.  
  253. /****************************** Open for packing **************************/
  254. LONG xpkopenwrite(struct XpkBuffer **xbufp, struct TagItem *tags)
  255. {
  256.   struct XpkBuffer        *xbuf        = *xbufp;
  257.   struct XpkStreamHeader    *globhdr    = &xbuf->xb_Headers.h_Glob;
  258.   struct Library        *XpkSubBase;
  259.   LONG                 res;
  260.  
  261.   xbuf->xb_Format = XPKMODE_PKSTD;
  262.  
  263.   if(xbuf->xb_InLen == -1)
  264.   {
  265.     if(!hookread(xbuf, XIO_TOTSIZE, 0, 0))    /* get input length */
  266.       return xbuf->xb_Result;
  267.     else if(xbuf->xb_RMsg.xmm_Size)
  268.       xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  269.   }
  270.  
  271.   if(!(XpkSubBase = xbuf->xb_SubBase) &&  /* Do we know the sublib? */
  272.   GetPrefsPacker(xbuf))
  273.   { /* no sublib and no prefs packer finder */
  274.     xbuf->xb_Result = XPKERR_BADPARAMS;
  275.     goto Abort;
  276.   }
  277.  
  278.   xbuf->xb_MinChunk = xbuf->xb_SubInfo->xi_MinPkInChunk;
  279.  
  280.   if(xbuf->xb_Password && !(xbuf->xb_SubInfo->xi_Flags & XPKIF_ENCRYPTION))
  281.   {
  282.     xbuf->xb_Result = XPKERR_NOCRYPT;
  283.     goto Abort;
  284.   }
  285.  
  286.   if(!xbuf->xb_Password && (xbuf->xb_SubInfo->xi_Flags & XPKIF_NEEDPASSWD))
  287.   { /* automatic password requester */
  288.     if((xbuf->xb_Result = GetPassword(xbuf, tags)))
  289.       goto Abort;
  290.   }
  291.  
  292.   if(!(xbuf->xb_Flags & XMF_LOSSYOK) &&
  293.   xbuf->xb_SubInfo->xi_Flags & XPKIF_LOSSY)
  294.   {
  295.     xbuf->xb_Result = XPKERR_LOSSY;
  296.     goto Abort;
  297.   }
  298.  
  299.   if(xbuf->xb_PackingMode > 100)    /* Is packing mode valid? */
  300.     xbuf->xb_PackingMode = 100;        /* Use max */
  301.  
  302.   if(!hookwrite(xbuf, XIO_TOTSIZE, 0, ROUNDLONG
  303.   (xbuf->xb_InLen + (xbuf->xb_InLen >> 5)) + (XPK_MARGIN<<1)))
  304.     goto Abort;
  305.  
  306.   /*********************** Find the chunk size *********************/
  307.   if((xbuf->xb_ChunkSize == 0) &&
  308.   ((xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_DefPkInChunk) == 0))
  309.     xbuf->xb_ChunkSize = DEFAULTCHUNKSIZE;
  310.   if(xbuf->xb_ChunkSize < xbuf->xb_SubInfo->xi_MinPkInChunk)
  311.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MinPkInChunk;
  312.   if((xbuf->xb_SubInfo->xi_MaxPkInChunk) &&
  313.   (xbuf->xb_ChunkSize > xbuf->xb_SubInfo->xi_MaxPkInChunk))
  314.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MaxPkInChunk;
  315.  
  316.   /******************* Prepare global header *********************/
  317.   globhdr->xsh_Pack = 0;        /* Initialize the global header */
  318.   globhdr->xsh_Type = xbuf->xb_SubID;
  319.  
  320.   if(xbuf->xb_ChunkSize > 65000)
  321.     globhdr->xsh_Flags |= XPKSTREAMF_LONGHEADERS;
  322.   if(xbuf->xb_Password)
  323.     globhdr->xsh_Flags |= XPKSTREAMF_PASSWORD;
  324.  
  325.   xbuf->xb_Headers.h_LocSize = globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS
  326.     ? sizeof (struct XpkChunkHdrLong)
  327.     : sizeof (struct XpkChunkHdrWord);
  328.  
  329.   memset(globhdr->xsh_Initial, 0xff, 16);    /* Read first 16 bytes */
  330.  
  331.   xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_PackMsg ?
  332.   xbuf->xb_SubInfo->xi_PackMsg : strings[TXT_PACKING_UPPER];
  333.   xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  334.   xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_PackedMsg ?
  335.   xbuf->xb_SubInfo->xi_PackedMsg : strings[TXT_PACKED];
  336.  
  337. Abort:
  338.   xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  339.   xbuf->xb_ChunkSize);
  340.  
  341.   if((res = xbuf->xb_Result))
  342.     res = XpkClose((struct XpkFib *) xbuf);
  343.  
  344.   return res;
  345. }
  346.  
  347. typedef struct XpkTypeData * __asm (*RecogFunc) (register __a0 STRPTR,
  348.   register __a1 STRPTR, register __d0 ULONG, register __d1 ULONG,
  349.   register __a2 struct TagItem *);
  350.  
  351. static LONG GetPrefsPacker(struct XpkBuffer *xbuf)
  352. {
  353.   LONG ret = XPKERR_UNKNOWN;
  354.   struct XpkPrefsSemaphore *sem;
  355.   ULONG bufsize;
  356.   struct XpkTypeData *td = 0;
  357.  
  358.   if((xbuf->xb_Flags & XMF_NOPREFS) || !(sem = GetPrefsSem()))
  359.     return XPKERR_NOFUNC;
  360.  
  361.   bufsize = Min(xbuf->xb_InLen, sem->xps_RecogSize);
  362.  
  363.   if(sem->xps_RecogFunc && (td = BufRecog(bufsize, xbuf, sem)) ==
  364.   (struct XpkTypeData *) 0xFFFFFFFF)
  365.     td = BufRecog(xbuf->xb_InLen, xbuf, sem);
  366.  
  367.   if(!td || td == (struct XpkTypeData *) 0xFFFFFFFF)
  368.     td = sem->xps_MainPrefs ? sem->xps_MainPrefs->xmp_DefaultType : 0;
  369.  
  370.   if(td)
  371.   {
  372.     if(td->xtd_Flags & XTD_NoPack)
  373.     {
  374.       xbuf->xb_Flags |= XMF_NOPACK;
  375.       xbuf->xb_SubInfo = &DONTInfo;
  376.       ret = XPKERR_OK;
  377.     }
  378.     else if(!(td->xtd_Flags & XTD_ReturnError))
  379.     {
  380.       struct Library *XpkSubBase;
  381.       struct XpkInfo *subinfo;
  382.  
  383.       if((XpkSubBase = opensub(xbuf, td->xtd_StdID)))
  384.       {
  385.     ret = XPKERR_OK;
  386.         subinfo = XpksPackerInfo();
  387.  
  388.         xbuf->xb_ChunkSize = td->xtd_ChunkSize;
  389.         xbuf->xb_PackingMode = ( td->xtd_Mode ? td->xtd_Mode :
  390.           subinfo->xi_DefMode);
  391. //    if(!(xbuf->xb_Password) && td->xtd_Password && 
  392. //    (xbuf->xb_PasswordSize = strlen(td->xtd_Password)))
  393. //    {
  394. //      /* we need a buffer including end byte! --> ++size */
  395. //      if(!(xbuf->xb_Password = (STRPTR)
  396. //      AllocMem(++xbuf->xb_PasswordSize, MEMF_PUBLIC)))
  397. //        ret = XPKERR_NOMEM;
  398. //        else
  399. //      {
  400. //        xbuf->Flags |= XMF_OWNPASSWORD;
  401. //        CopyMem(td->xtd_Password, xbuf->xb_Password, xbuf->xb_PasswordSize);
  402. //      }
  403. //    }
  404.       }
  405.     }
  406.   }
  407.  
  408.   if(td->xtd_Memory && td->xtd_MemorySize)
  409.     FreeMem(td->xtd_Memory, td->xtd_MemorySize);
  410.  
  411.   ReleaseSemaphore((struct SignalSemaphore *) sem);
  412.   return ret;
  413. }
  414.  
  415. static LONG GetPassword(struct XpkBuffer *xbuf, struct TagItem *tags)
  416. {
  417.  if(xbuf->xb_Flags & XMF_AUTOPASSWD)
  418.  {
  419.    if(!(xbuf->xb_Password = (STRPTR) AllocMem(AUTO_PASS_SIZE, MEMF_PUBLIC)))
  420.      return XPKERR_NOMEM;
  421.    xbuf->xb_PasswordSize = AUTO_PASS_SIZE;
  422.    xbuf->xb_Flags |= XMF_OWNPASSWORD; /* must be freed later */
  423.  
  424.    if((xbuf->xb_Result = XpkPassRequestTags(XPK_PasswordBuf,
  425.    xbuf->xb_Password, XPK_PassBufSize, xbuf->xb_PasswordSize, TAG_MORE,
  426.    tags, TAG_DONE)))
  427.      return xbuf->xb_Result;
  428.    else
  429.    {
  430. #ifdef DEBUG
  431.      DebugRunTime("GetPassword: %s", xbuf->xb_Password);
  432. #endif
  433.      return XPKERR_OK;
  434.    }
  435.  }
  436.  return XPKERR_NEEDPASSWD;
  437. }
  438.  
  439. static struct XpkTypeData *BufRecog(ULONG bufsize, struct XpkBuffer *xbuf,
  440. struct XpkPrefsSemaphore *sem)
  441. {
  442.   STRPTR bufptr;
  443.   struct XpkTypeData *ret = 0;
  444.   struct TagItem tag[] = {
  445.   { XPK_FileName, 0},
  446.   { XPK_PackMode, 0},
  447.   { TAG_DONE, 0}};
  448.  
  449.   tag[0].ti_Data = (ULONG) xbuf->xb_Prog.xp_FileName;
  450.   tag[1].ti_Data = xbuf->xb_PackingMode;
  451.  
  452.   if((bufptr = hookread(xbuf, XIO_READ, 0, bufsize)))
  453.   {
  454.     ret = (((RecogFunc) sem->xps_RecogFunc) (bufptr, xbuf->xb_InName,
  455.     bufsize, xbuf->xb_InLen, tag));
  456.     hookread(xbuf, XIO_SEEK, 0, -bufsize);
  457.   }
  458.   return ret;
  459. }
  460.  
  461. #endif /* XPKMASTER_OPEN_C */
  462.