]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - decomp.c
Initialize LDAP connection after generating the useragent log
[thirdparty/sarg.git] / decomp.c
index 956e8168995db76f35a3dc2efb041530042a3476..5689d769177d2e66b229925dc504ac8c75ce2938 100644 (file)
--- a/decomp.c
+++ b/decomp.c
@@ -1,10 +1,11 @@
 /*
- * AUTHOR: Pedro Lineu Orso                          orso@brturbo.com.br
- *                                                            1998, 2005
- * SARG Squid Analysis Report Generator            http://sarg-squid.org
+ * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
+ *                                                            1998, 2015
  *
  * SARG donations:
  *      please look at http://sarg.sourceforge.net/donations.php
+ * Support:
+ *     http://sourceforge.net/projects/sarg/forums/forum/363374
  * ---------------------------------------------------------------------
  *
  *  This program is free software; you can redistribute it and/or modify
  */
 
 #include "include/conf.h"
+#include "include/defs.h"
+#ifdef HAVE_ZLIB_H
+#include "zlib.h"
+#endif
+#ifdef HAVE_BZLIB_H
+#include "bzlib.h"
+#endif
 
-void decomp(char *arq, char *zip, char *tmp)
+#ifdef HAVE_ZLIB_H
+/*!
+ * Read from gzip file.
+ *
+ * \param Data The file object.
+ * \param Buffer The boffer to store the data read.
+ * \param Size How many bytes to read.
+ *
+ * \return The number of bytes read.
+ */
+static int Gzip_Read(void *Data,void *Buffer,int Size)
+{
+       return(gzread((gzFile)Data,Buffer,Size));
+}
+
+/*!
+ * Check if end of file is reached.
+ *
+ * \param Data The file object.
+ *
+ * \return \c True if end of file is reached.
+ */
+static int Gzip_Eof(void *Data)
+{
+       return(gzeof((gzFile)Data));
+}
+
+/*!
+ * Return to the beginnig of the file.
+ *
+ * \param Data The file object.
+ */
+static void Gzip_Rewind(void *Data)
+{
+       gzrewind((gzFile)Data);
+}
+
+/*!
+ * Close the file.
+ *
+ * \param Data File to close.
+ *
+ * \return 0 on success or -1 on error.
+ */
+static int Gzip_Close(void *Data)
+{
+       int RetCode=-1;
+       int Status;
+
+       Status=gzclose((gzFile)Data);
+       switch (Status)
+       {
+       case Z_OK:
+               RetCode=0;
+               break;
+       case Z_STREAM_ERROR:
+               FileObject_SetLastCloseError(_("Invalid gzip file"));
+               break;
+       case Z_ERRNO:
+               FileObject_SetLastCloseError(_("File operation error"));
+               break;
+       case Z_MEM_ERROR:
+               FileObject_SetLastCloseError(_("Not enough memory"));
+               break;
+       case Z_BUF_ERROR:
+               FileObject_SetLastCloseError(_("Truncated gzip stream"));
+               break;
+       default:
+               FileObject_SetLastCloseError(_("Unknown error returned by zlib"));
+               break;
+       }
+       return(RetCode);
+}
+
+/*!
+ * Open a file object to read from a gzip file.
+ *
+ * \return The object to pass to other function in this module.
+ */
+static FileObject *Gzip_Open(int fd)
+{
+       FileObject *File;
+
+       FileObject_SetLastOpenError(NULL);
+       File=calloc(1,sizeof(*File));
+       if (!File)
+       {
+               FileObject_SetLastOpenError(_("Not enough memory"));
+               return(NULL);
+       }
+       File->Data=gzdopen(fd,"rb");
+       if (!File->Data)
+       {
+               free(File);
+               FileObject_SetLastOpenError(_("Error opening gzip file"));
+               return(NULL);
+       }
+       File->Read=Gzip_Read;
+       File->Eof=Gzip_Eof;
+       File->Rewind=Gzip_Rewind;
+       File->Close=Gzip_Close;
+       return(File);
+}
+#endif
+
+#ifdef HAVE_BZLIB_H
+
+struct BzlibInternalFile
+{
+       //! Bzlib object.
+       BZFILE *BzFile;
+       //! \c True if end of file is reached.
+       bool Eof;
+       //! Original file in case a rewind is necessary.
+       FILE *File;
+};
+
+/*!
+ * Read from bzip file.
+ *
+ * \param Data The file object.
+ * \param Buffer The boffer to store the data read.
+ * \param Size How many bytes to read.
+ *
+ * \return The number of bytes read.
+ */
+static int Bzip_Read(void *Data,void *Buffer,int Size)
 {
+       struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+       int nread;
+       int bzerr=BZ_OK;
+
+       if (BData->Eof) return(0);
+       nread=BZ2_bzRead(&bzerr,BData->BzFile,Buffer,Size);
+       if (bzerr==BZ_STREAM_END)
+               BData->Eof=true;
+       else if (bzerr!=BZ_OK)
+               return(0);
+       return(nread);
+}
 
-   char cmd[1024];
-
-   if(access(arq, R_OK) != 0) {
-      sprintf(cmd,"%s: %s",text[64],arq);
-      debuga(cmd);
-      exit(1);
-   }
-
-   if(strstr(arq,".gz") !=0) {
-      sprintf(cmd,"%s: %s > %s/sarg-file.in (zcat)",text[62],arq,tmp);
-      debuga(cmd);
-      sprintf(cmd,"zcat %s > %s/sarg-file.in",arq,tmp);
-      system(cmd);
-      strcpy(zip,"zcat");
-      sprintf(arq,"%s/sarg-file.in",tmp);
-      return;
-   }
-
-   if(strstr(arq,".bz2") != 0) {
-      sprintf(cmd,"%s: %s > %s/sarg-file.in (bzcat)",text[62],arq,tmp);
-      debuga(cmd);
-      sprintf(cmd,"bzcat %s > %s/sarg-file.in",arq,tmp);
-      system(cmd);
-      strcpy(zip,"zcat");
-      sprintf(arq,"%s/sarg-file.in",tmp);
-      return;
-   }
-
-   if(strstr(arq,".Z")) {
-      sprintf(cmd,"%s: %s (uncompress)",text[62],arq);
-      debuga(cmd);
-      sprintf(cmd,"uncompress %s",arq);
-      system(cmd);
-      arq[strlen(arq)-2]='\0';
-      strcpy(zip,"compress");
-   }
-
-   return;
+/*!
+ * Check if end of file is reached.
+ *
+ * \param Data The file object.
+ *
+ * \return \c True if end of file is reached.
+ */
+static int Bzip_Eof(void *Data)
+{
+       struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+       return(BData->Eof);
+}
+
+/*!
+ * Return to the beginnig of the file.
+ *
+ * \param Data The file object.
+ */
+static void Bzip_Rewind(void *Data)
+{
+       struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+       int bzerr=BZ_OK;
 
+       BZ2_bzReadClose(&bzerr,BData->BzFile);
+       rewind(BData->File);
+       BData->BzFile=BZ2_bzReadOpen(&bzerr,BData->File,0,0,NULL,0);
+       if (!BData->BzFile)
+       {
+               debuga(__FILE__,__LINE__,_("Cannot rewind bzip file\n"));
+               exit(EXIT_FAILURE);
+       }
+       BData->Eof=false;
 }
 
+/*!
+ * Close the file.
+ *
+ * \param Data File to close.
+ *
+ * \return 0 on success or -1 on error.
+ */
+static int Bzip_Close(void *Data)
+{
+       struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+       int bzerr=BZ_OK;
+
+       BZ2_bzReadClose(&bzerr,BData->BzFile);
+       fclose(BData->File);
+       free(BData);
+       return(0);
+}
 
-void recomp(char *arq, char *zip) 
+/*!
+ * Open a file object to read from a bzip file.
+ *
+ * \return The object to pass to other function in this module.
+ */
+static FileObject *Bzip_Open(int fd)
 {
+       FileObject *File;
+       struct BzlibInternalFile *BData;
+       int bzerr=BZ_OK;
+
+       FileObject_SetLastOpenError(NULL);
+       File=calloc(1,sizeof(*File));
+       if (!File)
+       {
+               FileObject_SetLastOpenError(_("Not enough memory"));
+               return(NULL);
+       }
+       BData=calloc(1,sizeof(*BData));
+       if (!BData)
+       {
+               free(File);
+               FileObject_SetLastOpenError(_("Not enough memory"));
+               return(NULL);
+       }
+       BData->File=fdopen(fd,"rb");
+       if (BData->File==NULL)
+       {
+               free(BData);
+               free(File);
+               FileObject_SetLastOpenError(_("Error duplicating file descriptor"));
+               return(NULL);
+       }
+       File->Data=BData;
+       BData->BzFile=BZ2_bzReadOpen(&bzerr,BData->File,0,0,NULL,0);
+       if (!BData->BzFile)
+       {
+               fclose(BData->File);
+               free(BData);
+               free(File);
+               FileObject_SetLastOpenError(_("Error opening bzip file"));
+               return(NULL);
+       }
+       File->Read=Bzip_Read;
+       File->Eof=Bzip_Eof;
+       File->Rewind=Bzip_Rewind;
+       File->Close=Bzip_Close;
+       return(File);
+}
+#endif
 
-   char cmd[1024];
 
-   if(access(arq, R_OK) != 0) {
-      sprintf(cmd,"%s: %s",text[64],arq);
-      debuga(cmd);
-      exit(1);
-   }
+/*!
+Open the log file. If it is compressed, uncompress it through a pipe.
 
-   sprintf(cmd,"%s: %s",text[63],arq);
-   debuga(cmd);
+Log files compressed with gzip, bzip2 or compress are uncompressed with zcat or bzcat.
 
-   if(strcmp(zip,"gzip") == 0)
-      sprintf(cmd,"%s %s",zip,arq);    
+If the log file does not exist, the process terminates with an error message.
 
-   if(strcmp(zip,"compress") == 0)
-      sprintf(cmd,"%s %s",zip,arq);
+\param arq The log file to process.
+\param pipe A variable set to \c true if the log file is opened through a pipe or set to \c false if the file is open directly.
+
+\date 2009-09-24 - F Marchal\n This function used to uncompress .Z files in
+place using uncompress but that required a write access to the log directory,
+could conflict with logrotate and could leave the log file uncompressed if sarg
+crashed. According to the documentation, zcat is capable of uncompressing .Z
+files so it is now used.
+
+\date 2010-05-10 - F Marchal\n
+The function doesn't use a temporary file any more and read the compressed file through a pipe.
+*/
+FileObject *decomp(const char *arq)
+{
+       int fd;
+       FileObject *fi;
+       unsigned char buf[3];
+       ssize_t nread;
 
-   system(cmd);
-   return;
+       // guess file type
+       fd=open(arq,O_RDONLY | O_LARGEFILE);
+       if (fd==-1) {
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arq,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       nread=read(fd,buf,sizeof(buf));
+       if (nread==-1) {
+               debuga(__FILE__,__LINE__,_("Error while reading \"%s\" to guess its type: %s\n"),arq,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       if (nread<3) {
+               debuga(__FILE__,__LINE__,_("File \"%s\" is too small to guess its type\n"),arq);
+               exit(EXIT_FAILURE);
+       }
+       if (lseek(fd,0,SEEK_SET)==-1) {
+               debuga(__FILE__,__LINE__,_("Cannot return to the beginning of file \"%s\": %s"),arq,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
 
+       if (buf[0]==0x1F && buf[1]==0x8B && buf[2]==0x08)//gzip file
+       {
+#ifdef HAVE_ZLIB_H
+               fi=Gzip_Open(fd);
+#else
+               debuga(__FILE__,__LINE__,_("Sarg was not compiled with gzip support to read file \"%s\"\n"),arq);
+               exit(EXIT_FAILURE);
+#endif
+       }
+       else if (buf[0]==0x42 && buf[1]==0x5A && buf[2]==0x68)//bzip2 file
+       {
+#ifdef HAVE_BZLIB_H
+               fi=Bzip_Open(fd);
+#else
+               debuga(__FILE__,__LINE__,_("Sarg was not compiled with bzip support to read file \"%s\"\n"),arq);
+               exit(EXIT_FAILURE);
+#endif
+       }
+       else if (buf[0]==0x1F && (buf[1]==0x9D || buf[1]==0xA0))//LZW and LZH compressed file
+       {
+               debuga(__FILE__,__LINE__,_("Support for LZW and LZH compressed files was removed in sarg 2.4.\n"
+                                                                  "You can still read such a file with a command like this:\n"
+                                                                  "  zcat \"%s\" | sarg - [your usual options here]\n"
+                                                                  "If you think it is important for sarg to read those files, open a bug ticket at <http://sourceforge.net/p/sarg/bugs/>.\n"),
+                          arq);
+               exit(EXIT_FAILURE);
+       }
+       else //normal file
+       {
+               fi=FileObject_FdOpen(fd);
+       }
+       return(fi);
 }