home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / HILFEN / SYSTEM / MSH / ZIPLS.C < prev    next >
C/C++ Source or Header  |  1993-12-01  |  4KB  |  135 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <alloc.h>
  5. #include <dos.h>
  6. #include <mem.h>
  7. #include <io.h>
  8. #include <fcntl.h>
  9.  
  10. /* this file is what allows MSH to work inside zip archives.
  11.    It is given as an example so you may write your own directory-reader
  12.    for other types of archives (you will get complimentary copies
  13.    of all our products if you are the first person to send me back
  14.    such a reader for one of the common types which are not yet supported
  15.    by MSH). If you define another lister, just add it in the list of
  16.    panel_listers in primitiv.c
  17. */
  18.  
  19. static int ZipHandle;
  20.  
  21. #include "msh.h"
  22.  
  23. /* service routines: ReadZip and baseptr */
  24.  
  25. static int ReadZip(long offset,int fromwhere,void *ReadBuf,int ReadSize)
  26. { if((lseek(ZipHandle,offset,fromwhere)<0) ||
  27.     (_read(ZipHandle,ReadBuf,ReadSize)!=ReadSize))
  28.   {(*efns)(WARNING_,"Invalid Zip format");return -1;}
  29.   else return 0;
  30. }
  31.  
  32. char *baseptr(char *name)
  33. {char *s;
  34.  for(s=name;*name;name++)if(*name=='\\' || *name=='/' || *name==':')s=name+1;
  35.  return s;
  36. }
  37.  
  38. /* the following function 'addlist' from msh.lib does the main job: you call
  39.    it once for each name found in the archive. If the name given matches
  40.    the pattern given, addlist returns a pointer to a structure that you then
  41.    have to fill */
  42. struct dlst{refobj fname;
  43.         unsigned long size;
  44.         unsigned long time;
  45.         unsigned read:1;
  46.         unsigned system:1;
  47.         unsigned hidden:1;
  48.         unsigned isdir:1;
  49.         unsigned selected:1;
  50.         unsigned selected_shown:1;
  51.        }*addlist(char *name,char *pattern);
  52.  
  53. void zip_ls(char *Zipname)
  54. {/* Format information for ZIP files (produced by PKWARE's PKZIP.EXE) */
  55.  
  56. /* Structure of the central directory record */
  57. struct CENTRAL_RECORD
  58. { long    Signature;
  59.   int    VersionMadeBy;
  60.   int    VersionNeeded;
  61.   int    BitFlag;
  62.   int    CompressionMethod;
  63.   long  FileTime;
  64.   long    CRC32;
  65.   long    CompressedSize;
  66.   long    UnCompressedSize;
  67.   int    FileNameLength;
  68.   int    ExtraFieldLength;
  69.   int    CommentFieldLength;
  70.   int    DiskStartNumber;
  71.   int    InternalAttributes;
  72.   long    ExternalAttributes;
  73.   long    LocalHeaderOffset;
  74. }*ZipCR, *pCR;
  75. #define CENTRALDIRSIG 0x02014b50L
  76.  
  77. struct END_CENTRAL_RECORD
  78. { long Signature;
  79.   int    DiskNumber;
  80.   int    DiskWithCD;
  81.   int    DiskCD;
  82.   int    CDEntries;
  83.   long CDSize;
  84.   long CDOffset;
  85.   int    ZipCommentLength;
  86. }*ECR;
  87. #define ENDCENTRALSIG 0x06054b50L
  88.  
  89. #define sizeofECR sizeof(struct END_CENTRAL_RECORD)
  90.   int i, nbentries, ZipCmtLngth, dnlen;
  91.   char Buffer[sizeofECR], *Pathname=strstr(Zipname,".zip")+5, dn[_MAX_PATH];
  92.   Pathname[-1]=0;
  93.   if((ZipHandle=_open(Zipname,O_RDONLY|O_BINARY))==-1)
  94.   {(*efns)(WARNING_|FILE_,"Cannot open %s",Zipname);goto end2;}
  95.   if(ReadZip(-(long)sizeofECR,SEEK_END,Buffer,sizeofECR))goto end;
  96.   while(1)
  97.   { for(i=0;i<sizeofECR-sizeof(long);i++)
  98.       if(*(long *)(Buffer+i)==ENDCENTRALSIG)goto found;
  99.     if(ReadZip(3-2*(long)sizeofECR,SEEK_CUR,Buffer,sizeofECR))goto end;
  100.   }
  101. found:
  102.   if(ReadZip(i-(long)sizeof(int),SEEK_CUR,&ZipCmtLngth,sizeof(int)))goto end;
  103.   testalloc(ECR=malloc(sizeofECR+ZipCmtLngth));
  104.   if(ReadZip(-(long)sizeofECR,SEEK_CUR,ECR,sizeofECR+ZipCmtLngth))
  105.   { free(ECR);goto end;}
  106. /* Allocate 1 more byte to avoid malloc(0)==NULL (fuck you, ANSI commitee!!) */
  107.   testalloc(ZipCR=malloc((int)ECR->CDSize+1));
  108.   if(ReadZip(ECR->CDOffset,SEEK_SET,(char *)ZipCR,(int)ECR->CDSize))
  109.   { free(ZipCR);free(ECR);goto end;}
  110.   else nbentries=ECR->CDEntries;
  111.   free(ECR);
  112.   addlist("..",NULL);
  113.   dnlen=baseptr(Pathname)-Pathname;
  114.   strncpy(dn,Pathname,dnlen);dn[dnlen]=0;strupr(dn);
  115.   for(i=0,pCR=ZipCR;i<nbentries;i++,pCR++)
  116.   { char *name=(char *)(pCR+1), *s;
  117.     name[pCR->FileNameLength]=0;strupr(name);
  118.     for(s=name;*s;s++)if(*s=='/')*s='\\';
  119.     if(strstr(name,dn)==name)
  120.     { char *pattern=NULL;struct dlst *d;name+=strlen(dn);
  121.       if((s=strpbrk(name,"\\/"))==NULL)pattern=Pathname+strlen(dn);
  122.       else { *s=0;name=baseptr(name);}
  123.       if((d=addlist(name,pattern))&& pattern)
  124.       {    d->time=pCR->FileTime;
  125.     d->size=pCR->UnCompressedSize;
  126.       }
  127.     }
  128.     (char *)pCR+=pCR->CommentFieldLength+pCR->FileNameLength+
  129.                      pCR->ExtraFieldLength;
  130.   }
  131.   free(ZipCR);
  132.  end:  close(ZipHandle);
  133.  end2: Pathname[-1]='\\';
  134. }
  135.