home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <alloc.h>
- #include <dos.h>
- #include <mem.h>
- #include <io.h>
- #include <fcntl.h>
-
- /* this file is what allows MSH to work inside zip archives.
- It is given as an example so you may write your own directory-reader
- for other types of archives (you will get complimentary copies
- of all our products if you are the first person to send me back
- such a reader for one of the common types which are not yet supported
- by MSH). If you define another lister, just add it in the list of
- panel_listers in primitiv.c
- */
-
- static int ZipHandle;
-
- #include "msh.h"
-
- /* service routines: ReadZip and baseptr */
-
- static int ReadZip(long offset,int fromwhere,void *ReadBuf,int ReadSize)
- { if((lseek(ZipHandle,offset,fromwhere)<0) ||
- (_read(ZipHandle,ReadBuf,ReadSize)!=ReadSize))
- {(*efns)(WARNING_,"Invalid Zip format");return -1;}
- else return 0;
- }
-
- char *baseptr(char *name)
- {char *s;
- for(s=name;*name;name++)if(*name=='\\' || *name=='/' || *name==':')s=name+1;
- return s;
- }
-
- /* the following function 'addlist' from msh.lib does the main job: you call
- it once for each name found in the archive. If the name given matches
- the pattern given, addlist returns a pointer to a structure that you then
- have to fill */
- struct dlst{refobj fname;
- unsigned long size;
- unsigned long time;
- unsigned read:1;
- unsigned system:1;
- unsigned hidden:1;
- unsigned isdir:1;
- unsigned selected:1;
- unsigned selected_shown:1;
- }*addlist(char *name,char *pattern);
-
- void zip_ls(char *Zipname)
- {/* Format information for ZIP files (produced by PKWARE's PKZIP.EXE) */
-
- /* Structure of the central directory record */
- struct CENTRAL_RECORD
- { long Signature;
- int VersionMadeBy;
- int VersionNeeded;
- int BitFlag;
- int CompressionMethod;
- long FileTime;
- long CRC32;
- long CompressedSize;
- long UnCompressedSize;
- int FileNameLength;
- int ExtraFieldLength;
- int CommentFieldLength;
- int DiskStartNumber;
- int InternalAttributes;
- long ExternalAttributes;
- long LocalHeaderOffset;
- }*ZipCR, *pCR;
- #define CENTRALDIRSIG 0x02014b50L
-
- struct END_CENTRAL_RECORD
- { long Signature;
- int DiskNumber;
- int DiskWithCD;
- int DiskCD;
- int CDEntries;
- long CDSize;
- long CDOffset;
- int ZipCommentLength;
- }*ECR;
- #define ENDCENTRALSIG 0x06054b50L
-
- #define sizeofECR sizeof(struct END_CENTRAL_RECORD)
- int i, nbentries, ZipCmtLngth, dnlen;
- char Buffer[sizeofECR], *Pathname=strstr(Zipname,".zip")+5, dn[_MAX_PATH];
- Pathname[-1]=0;
- if((ZipHandle=_open(Zipname,O_RDONLY|O_BINARY))==-1)
- {(*efns)(WARNING_|FILE_,"Cannot open %s",Zipname);goto end2;}
- if(ReadZip(-(long)sizeofECR,SEEK_END,Buffer,sizeofECR))goto end;
- while(1)
- { for(i=0;i<sizeofECR-sizeof(long);i++)
- if(*(long *)(Buffer+i)==ENDCENTRALSIG)goto found;
- if(ReadZip(3-2*(long)sizeofECR,SEEK_CUR,Buffer,sizeofECR))goto end;
- }
- found:
- if(ReadZip(i-(long)sizeof(int),SEEK_CUR,&ZipCmtLngth,sizeof(int)))goto end;
- testalloc(ECR=malloc(sizeofECR+ZipCmtLngth));
- if(ReadZip(-(long)sizeofECR,SEEK_CUR,ECR,sizeofECR+ZipCmtLngth))
- { free(ECR);goto end;}
- /* Allocate 1 more byte to avoid malloc(0)==NULL (fuck you, ANSI commitee!!) */
- testalloc(ZipCR=malloc((int)ECR->CDSize+1));
- if(ReadZip(ECR->CDOffset,SEEK_SET,(char *)ZipCR,(int)ECR->CDSize))
- { free(ZipCR);free(ECR);goto end;}
- else nbentries=ECR->CDEntries;
- free(ECR);
- addlist("..",NULL);
- dnlen=baseptr(Pathname)-Pathname;
- strncpy(dn,Pathname,dnlen);dn[dnlen]=0;strupr(dn);
- for(i=0,pCR=ZipCR;i<nbentries;i++,pCR++)
- { char *name=(char *)(pCR+1), *s;
- name[pCR->FileNameLength]=0;strupr(name);
- for(s=name;*s;s++)if(*s=='/')*s='\\';
- if(strstr(name,dn)==name)
- { char *pattern=NULL;struct dlst *d;name+=strlen(dn);
- if((s=strpbrk(name,"\\/"))==NULL)pattern=Pathname+strlen(dn);
- else { *s=0;name=baseptr(name);}
- if((d=addlist(name,pattern))&& pattern)
- { d->time=pCR->FileTime;
- d->size=pCR->UnCompressedSize;
- }
- }
- (char *)pCR+=pCR->CommentFieldLength+pCR->FileNameLength+
- pCR->ExtraFieldLength;
- }
- free(ZipCR);
- end: close(ZipHandle);
- end2: Pathname[-1]='\\';
- }
-