Logo Search packages:      
Sourcecode: dact version File versions  Download package

dact_common.c

/*
 * Copyright (C) 2001, 2002, and 2003  Roy Keene
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *      email: dact@rkeene.org
 */

#include "dact.h"
#define __DACT_C
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "parse.h"
#include "dendian.h"
#include "crc.h"
#include "math.h"
#include "dact_common.h"
#include "algorithms.h"
#include "ciphers.h"
#include "module.h"
#include "header.h"
#include "parse.h"
#include "net.h"
#include "sfx.h"
#include "ui.h"
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
#endif

char dact_nonetwork=0;

uint32_t dact_blksize_calc(int fsize) {
      uint32_t ret=0;

      if (fsize==0) return(DACT_BLK_SIZE_DEF);
      if (fsize<(204800)) {
            ret=(fsize+5);
      }
      if (ret==0) ret=(((int) ((((float) fsize)/102400.0)-(0.9999999)))*65535);
      if (ret>DACT_BLK_SIZE_MAX) ret=DACT_BLK_SIZE_MAX;
      return(ret);
}

int dact_config_execute(const char *cmd, char *options, uint32_t *blksize) {
      char *line=NULL, *line_s, *item_buf[4]={NULL, NULL, NULL, NULL};
      int i;

      line_s=line=strdup(cmd);
      if (line[0]=='#') return(0);
      while (line[strlen(line)-1]<32) line[strlen(line)-1]='\0';
      for (i=0;i<4;i++) item_buf[i]=NULL;
      for (i=0;i<4;i++) {
            if ((item_buf[i]=strsep(&line, "\t "))==NULL)  break;
            if (item_buf[i][0]==0) i--;
      }
      if (item_buf[0]==NULL || item_buf[1]==NULL) return(0); /* This means all commands must have arguments. */

      switch (elfcrc(0, item_buf[0], strlen(item_buf[0]))) {
            case 164209419: /* binary_check */
                  options[DACT_OPT_BINCHK]=!!strcmp(item_buf[1],"off");
                  break;
            case 9456603: /* version_check */
                  options[DACT_OPT_VERCHK]=!!strcmp(item_buf[1],"off");
                  break;
            case 204349618: /* module_dir */
                  if ((sizeof(moduledirectory)-strlen(moduledirectory)-1)<=0) break;
                  strncat(moduledirectory,":",sizeof(moduledirectory)-strlen(moduledirectory)-1);
                  strncat(moduledirectory,item_buf[1],sizeof(moduledirectory)-strlen(moduledirectory)-1);
                  break;
            case 247248556: /* module_load_all */
                  if (strcmp(item_buf[1], "on")==0) {
                        init_modules();
                        load_modules_all(options);
                  }
                  break;
            case 48402100:  /* module_load */
            case 106360197: /* load_module */
                  init_modules();
                  load_module(item_buf[1], options);
                  break;
            case 164097267: /* network_access */
#ifndef NO_NETWORK
                  dact_nonetwork=!strcmp(item_buf[1],"off");
#endif
                  break;
            case 209445231: /* exclude_algo */
                  i=(atoi(item_buf[1])&0xff);
                  algorithms[i]=DACT_FAILED_ALGO;
                  break;
            case 168825941: /* block_size */
                  if (blksize!=NULL) {
                        *blksize=atoi2(item_buf[1]);
                  }
                  break;
            case 162975987: /* use_urls */
                  options[DACT_OPT_URL]=!!strcmp(item_buf[1],"off");
                  break;
            case 104235033: /* color_ui */
                  dact_ui_setopt(DACT_UI_OPT_COLOR,!!strcmp(item_buf[1],"off"));
                  break;
            case 164800901: /* module_upgrade */
                  if (strcmp(item_buf[1],"on")==0) options[DACT_OPT_UPGRADE]=1;
                  break;
            case 63160590: /* pass_use_stdin */
            case 191551086: /* use_stdin */
                  dact_ui_setopt(DACT_UI_OPT_PASSSTDIN, 1);
                  break;
#ifdef DEBUG
            default:
                  fprintf(stderr, "Unknown command %s (%i)\n",item_buf[0],elfcrc(0,item_buf[0],strlen(item_buf[0])));
                  break;
#endif
      }
      free(line_s);
      return(1);
}

void dact_config_loadfile(const char *path, char *options, uint32_t *blksize) {
      char *line=NULL;
      FILE *cfd;

      line=malloc(512);
      if ((cfd=fopen(path,"r"))==NULL) return;
      while (!feof(cfd)) {
            fgets(line, 511, cfd);
            dact_config_execute(line, options, blksize);
      }
      free(line);
      fclose(cfd);
}

uint32_t dact_blk_decompress(char *ret, const char *srcbuf, const uint32_t size, const char *options, const int algo, uint32_t bufsize) {
      uint32_t retval;

      if (algo==0xff) return(0);

      if (algorithms[algo]==NULL) {
            PRINTERR("Algorithm unavailble.");
            return(0);
      }

      retval=algorithms[algo](DACT_MODE_DECMP, NULL, srcbuf, ret, size, bufsize);

      return(retval);
}


uint32_t dact_blk_compress(char *algo, char *ret, const char *srcbuf, const uint32_t size, const char *options, uint32_t bufsize) {
      char *tmpbuf, *smallbuf=NULL;
      int i, highest_algo=0;
      char smallest_algo;
      uint32_t smallest_size=-1, x;
#ifndef DACT_UNSAFE
      char *verif_bf=NULL;
      uint32_t m;
      if ((verif_bf=malloc(size))==NULL) { PERROR("malloc"); return(0); }
#endif

      if ((tmpbuf=malloc(bufsize))==NULL) { PERROR("malloc"); return(0); }

      for (i=0;i<256;i++) {
            if (algorithms[i]!=NULL && algorithms[i]!=DACT_FAILED_ALGO) highest_algo=i;
      }

      for (i=0;i<=highest_algo;i++) {
            if (algorithms[i]!=NULL && algorithms[i]!=DACT_FAILED_ALGO) {
                  x=algorithms[i](DACT_MODE_COMPR, NULL, srcbuf, tmpbuf, size, bufsize);
#ifndef DACT_UNSAFE
                  if ((x<smallest_size || smallest_size==-1) && x!=-1) {
                        m=algorithms[i](DACT_MODE_DECMP, NULL, tmpbuf, verif_bf, x, size);
                        if (memcmp(verif_bf, srcbuf,m) || m!=size) {
                              x=-1;
                              if (options[DACT_OPT_COMPLN]) {
                                    dact_ui_status(DACT_UI_LVL_ALL, "Compression verification failed (ignoring)");
                              }
                        }
                  }
#endif
                  if ((x<smallest_size || smallest_size==-1) && x!=-1) {
                        smallest_size=x;
                        smallest_algo=i;
                        if (smallbuf!=NULL) free(smallbuf);
                        if ((smallbuf=malloc(smallest_size))==NULL) { 
                              PERROR("malloc");
                              free(tmpbuf);
#ifndef DACT_UNSAFE
                              free(verif_bf);
#endif
                              return(0);
                        }
                        memcpy(smallbuf, tmpbuf, smallest_size);
                  }

                  if (options[DACT_OPT_VERB]>2) {
                        PRINT_LINE; fprintf(stderr, "dact: \033[%im----| %03i  | %-7i | %s\033[0m\n", (smallest_algo==i)*7 , i, x, algorithm_names[i]);
                  }

            }
      }

      free(tmpbuf);
#ifndef DACT_UNSAFE
      free(verif_bf);
#endif
      if (smallest_size==-1) {
            return(0);
      }
      memcpy(algo, &smallest_algo, sizeof(char));
      memcpy(ret, smallbuf, smallest_size);
/* This was MISSING !  memory leak. */
      free(smallbuf);
      return(smallest_size);
}

uint64_t dact_process_file(const int src, const int dest, const int mode, const char *options, const char *filename, uint32_t *crcs, uint32_t dact_blksize, int cipher) {
      struct stat filestats;
      FILE *extd_urlfile;
      char *file_extd_urls[256];
      unsigned char algo;
      char ch;
      char *in_buf, *out_buf, *hdr_buf, *keybuf=NULL, *tmpbuf=NULL;
      char version[3]={DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION};
      char file_opts=0;
      uint32_t bytes_read, retsize;
      uint64_t filesize=0, fileoutsize=0, out_bufsize=0;
      uint32_t blk_cnt=0, file_extd_size=0, blksize=0, blksize_uncomp=0;
      uint32_t magic=0, file_extd_read=0, file_extd_urlcnt=0;
      int hdr_reg_size=28;
      int blksize_size;
      int x=0, new_fd, canlseek=0;
      ssize_t offset=0;

      if (fstat(src, &filestats)<0) {
            PERROR("fstat");
            return(0);
      }

      if (mode==DACT_MODE_COMPR) {
            blksize=dact_blksize;
            if (blksize==0) {
                  blksize=dact_blksize_calc(filestats.st_size);
            }

            if (options[DACT_OPT_SFX]) {
                  offset=sfx_init_compress(dest);
                  if (offset<0) {
                        PRINTERR("Couldn't initialize self-extracting header.");
                        return(0);
                  }
                  dact_hdr_ext_regn(DACT_HDR_SFXLEN, offset, sizeof(offset));
            }

            out_bufsize=blksize*2;
            if (((in_buf=malloc(blksize))==NULL) || \
                  ((out_buf=malloc(out_bufsize))==NULL)) {
                        PERROR("malloc");
                        return(0);
            }

            dact_ui_setup(((float) (filestats.st_size/blksize)+0.9999));
            if (cipher!=-1) {
                  dact_hdr_ext_regn(DACT_HDR_CIPHER, cipher, sizeof(cipher));
                  keybuf=malloc(DACT_KEY_SIZE);
                  ciphers[cipher](NULL, NULL, 0, keybuf, DACT_MODE_CINIT+DACT_MODE_CENC);
                  
            }

            blksize_size=BYTESIZE(blksize);

            if (!options[DACT_OPT_ORIG] && filename!=NULL)
                  dact_hdr_ext_regs(DACT_HDR_NAME, filename, strlen(filename));
            file_extd_size=(dact_hdr_ext_size()+14); /* The +14 is for crc0 and crc1 */
            write_de(dest, DACT_MAGIC_NUMBER, 4);
            write(dest, &version[0], 1);
            write(dest, &version[1], 1);
            write(dest, &version[2], 1);
            write_de(dest, 0, 8); /* Place holder for ORIG FILE SIZE */
            write_de(dest, 0, 4); /* Place holder for NUM BLOCKS */
            write_de(dest, blksize, 4);
            write_de(dest, file_opts, 1); /* XXX: Option byte... Or not? */
            write_de(dest, file_extd_size, 4); /* Place holder for SIZEOF EXTENDED DTA */
/* Fill the header with NOPs incase we can't come back and put the CRCs */
            ch=DACT_HDR_NOP;
            for (x=0;x<file_extd_size;x++) write(dest, &ch, 1);

            if (options[DACT_OPT_VERB]>1) {
                  PRINTERR("Blk | Algo | Size    | Name");
                  PRINTERR("----+------+---------+---------------------------");
            }

            memset(in_buf, 0, blksize);
            while ( (bytes_read=read_f(src, in_buf, blksize))>0) {
                  filesize+=bytes_read;
                  blk_cnt++;

                  retsize=dact_blk_compress(&algo, out_buf, in_buf, blksize, options, out_bufsize);

/* CIPHER the data if an encryption algorithm is specified. */
                  if (cipher!=-1) {
                        tmpbuf=malloc(retsize*2);
                        x=ciphers[cipher](out_buf, tmpbuf, retsize, keybuf, DACT_MODE_CENC);
                        memcpy(out_buf,tmpbuf,x);
                        free(tmpbuf);
                  }

                  if (retsize>0) {
                        if (options[DACT_OPT_VERB]>1) {
                              if (options[DACT_OPT_VERB]>2) {
                                    PRINTERR("^^^\\ /^^^^\\ /^^^^^^^\\ /^^^^^^^^^^^^^^^^^^^^^^^^^^");
                              }
                              PRINT_LINE; fprintf(stderr, "dact: %03i | %03i  | %-7i | %s\n",blk_cnt,algo,retsize,algorithm_names[algo]);
                              if (options[DACT_OPT_VERB]>2) {
                                    PRINTERR("___/ \\____/ \\_______/ \\__________________________");
                              }
                        }


                        dact_ui_incrblkcnt(1);
                        dact_ui_status(DACT_UI_LVL_GEN, "Algorithm ");
                        dact_ui_status_append(DACT_UI_LVL_GEN,algorithm_names[algo]);

                        crcs[0]=crc(crcs[0], out_buf, retsize);
                        /* Do not generate a CRC of the plaintext if encrypting */
                        if (cipher==-1) {
                              crcs[1]=crc(crcs[1], in_buf, blksize);
                        }

                        if (!options[DACT_OPT_HDONLY]) {
                              write(dest, &algo, 1);
                              write_de(dest, retsize, blksize_size);

                              if (write(dest, out_buf, retsize)!=retsize) {
                                    PERROR("write");
                                    free(in_buf);
                                    free(out_buf);
                                    return(0);
                              }
                        }
                  } else {
                        PRINTERR("Compression resulted in 0-byte block.");
                        free(in_buf);
                        free(out_buf);
                        return(0);
                  }
                  memset(in_buf, 0, blksize);
            }

            if (bytes_read<0) {
                  PERROR("read");
            }

            free(in_buf);
            free(out_buf);

            /* Put the filesize and file block count in the header, if possible. */
            if (lseek_net(dest, offset+7, SEEK_SET)<0) {
/* If we can't rewind the stream, put magic+fileisze */
                  write_de(dest, DACT_MAGIC_PEOF, 4);
                  write_de(dest, filesize, 8);
            } else {
                  write_de(dest, filesize, 8);
                  write_de(dest, blk_cnt, 4);
            } 

            if (lseek_net(dest, offset+hdr_reg_size, SEEK_SET)>0) {
                  if (!options[DACT_OPT_NOCRC]) {
                        dact_hdr_ext_regn(DACT_HDR_CRC0, crcs[0], 4);
                        dact_hdr_ext_regn(DACT_HDR_CRC1, crcs[1], 4);
                  }
                  write(dest, dact_hdr_ext_data(), dact_hdr_ext_size());
            }

            dact_hdr_ext_clear();

            return(filesize);
      }

      if (mode==DACT_MODE_DECMP) {

            dact_ui_status(DACT_UI_LVL_GEN, "Decompressing.");

            dact_hdr_ext_clear();

            read_de(src, &magic, 4, sizeof(magic));

            if (magic!=DACT_MAGIC_NUMBER) {
                  dact_ui_status(DACT_UI_LVL_GEN, "Bad DACT magic, checking others...");
                  return(dact_process_other(src,dest,magic,options));
            }

            read(src, &version[0], 1);
            read(src, &version[1], 1);
            read(src, &version[2], 1);
#ifndef DACT_DONT_SUPPORT_OLDDACT
            if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
                  PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
                  read_de(src, &filesize, 4, sizeof(filesize));
                  hdr_reg_size=24;
            } else {
                  read_de(src, &filesize, 8, sizeof(filesize));
            }
#else
            read_de(src, &filesize, 8, sizeof(filesize));
#endif
            read_de(src, &blk_cnt, 4, sizeof(blk_cnt));
            read_de(src, &blksize_uncomp, 4, sizeof(blksize_uncomp));
            read(src, &file_opts, 1);
            read_de(src, &file_extd_size, 4, sizeof(file_extd_size));



            while (file_extd_read<file_extd_size) {
                  x=0;
                  read(src, &ch, 1);
                  if (ch!=DACT_HDR_NOP) read_de(src, &x, 2, sizeof(x)); 
                  switch (ch) {
                        case DACT_HDR_CRC0:
                              read_de(src, &crcs[2], 4, sizeof(crcs[2]));
                              if (crcs[4]!=0 && crcs[2]!=crcs[4]) {
                                    dact_ui_status(DACT_UI_LVL_GEN, "CRC error.");
                                    if (!options[DACT_OPT_NOCRC])
                                          return(0);
                              }
                              break;
                        case DACT_HDR_CRC1:
                              read_de(src, &crcs[3], 4, sizeof(crcs[3]));
                              if (crcs[5]!=0 && crcs[3]!=crcs[5]) {
                                    dact_ui_status(DACT_UI_LVL_GEN, "CRC error.");
                                    if (!options[DACT_OPT_NOCRC])
                                          return(0);
                              }
                              break;
/*

XXX: Todo, make this do something...
                        case DACT_HDR_NAME:
                              break;
*/
                        case DACT_HDR_URL:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
                              free(hdr_buf);
                              break;
                        case DACT_HDR_URLFILE:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              extd_urlfile=fopen(hdr_buf, "r");
                              free(hdr_buf);   /* We shouldn't need this anymore. */
                              if (extd_urlfile==NULL) break;
                              hdr_buf=malloc(4096);
                              while (1) {
                                    fgets(hdr_buf, 4095, extd_urlfile);
                                    if (feof(extd_urlfile)) break;
                                    hdr_buf=strsep(&hdr_buf,"\n");
                                    file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
                              }
                              free(hdr_buf);
                              break;
                        case DACT_HDR_DESC:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              fprintf(stderr, "DESC: %s\n",hdr_buf);
                              free(hdr_buf);
                              break;
                        case DACT_HDR_CIPHER:
                              read_de(src, &cipher, x, sizeof(cipher));
                              break;
                        case DACT_HDR_NOP:
                              x=-2;
                              break;
                        case DACT_HDR_SFXLEN:
                              read_de(src, &offset, x, sizeof(offset));
                              break;
                        default:
                              hdr_buf=malloc(x);
                              read_f(src, hdr_buf, x);
                              free(hdr_buf);
                              break;
                  }



                  file_extd_read+=(x+3);
            }

            if (options[DACT_OPT_URL]) {
                  for (x=0;x<file_extd_urlcnt;x++) {
                        dact_ui_status(DACT_UI_LVL_GEN,"Trying to get remote url ");
                        dact_ui_status_append(DACT_UI_LVL_SPEC, file_extd_urls[x]);
                        if ((new_fd=open_net(file_extd_urls[x],O_RDONLY,0))<0) {
                              dact_ui_status(DACT_UI_LVL_GEN, "Failed.");
                              continue;
                        }
                        close(src);
                        crcs[4]=crcs[2];
                        crcs[5]=crcs[3];
                        return(dact_process_file(new_fd, dest, mode, options, filename, crcs, blksize_uncomp, cipher));
                  }
            }


/* 
   XXX: Even if we don't resolve it here, we can resolve it later...
   Should we even bother to do it here if we can?

   XXX: When CAN'T we rewind a read stream?
            When it's a pipe

*/
            if (filesize==0) {
/* See if we can rewind our stream, so when we get to the end, we can come back! */
                  if (lseek_net(src, offset+1, SEEK_SET)==(offset+1)) { /* MAJOR BUG HERE! was: lseek(src,1,SEEK_SET)==0 which will always be false. */
                        canlseek=1;
#ifndef DACT_DONT_SUPPORT_OLDDACT
                        if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
                              PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
                              lseek_net(src, -8, SEEK_END);
                              read_de(src, &magic, 4, sizeof(magic));
                              read_de(src, &filesize, 4, sizeof(filesize));
                              hdr_reg_size=24;
                        } else {
                              lseek_net(src, -12, SEEK_END);
                              read_de(src, &magic, 4, sizeof(magic));
                              read_de(src, &filesize, 8, sizeof(filesize));
                        }
#else
                        lseek_net(src, -12, SEEK_END);
                        read_de(src, &magic, 4, sizeof(magic));
                        read_de(src, &filesize, 8, sizeof(filesize));
#endif
                        if (magic!=DACT_MAGIC_PEOF) {
                              dact_ui_status(DACT_UI_LVL_GEN, "File is corrupt.");
                              filesize=0;
                        }
                        lseek_net(src, offset+hdr_reg_size+file_extd_size, SEEK_SET);
                  } else {
                        canlseek=0;
                  }
            }

            out_bufsize=blksize_uncomp;
            if (((out_buf=malloc(out_bufsize))==NULL)) {
                  PERROR("malloc");
                  return(0);
            }

            blksize_size=BYTESIZE(blksize_uncomp);

            dact_ui_setup((int)(((float) filesize/(float) blksize_uncomp)+0.9999));

            if (cipher!=-1) {
                  keybuf=malloc(DACT_KEY_SIZE);
                  ciphers[cipher](NULL, NULL, 0, keybuf, DACT_MODE_CINIT+DACT_MODE_CDEC);
                  
            }



            while (1) {
                  if (read(src, &algo, 1)==0) break;
                  if (algo==0xff) break; /* 0xff is reserved for EOF */

                  read_de(src, &blksize, blksize_size, sizeof(blksize));

                  if ((in_buf=malloc(blksize))==NULL) {
                        PERROR("malloc");
                        free(out_buf);
                        return(0);
                  }

                  read_f(src, in_buf, blksize);

#ifndef DACT_DONT_SUPPORT_OLDDACT
                  if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
                        PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
                        crcs[0]=elfcrc(crcs[0],in_buf,blksize);
                  } else {
                        crcs[0]=crc(crcs[0],in_buf,blksize);
                  }
#else
                  crcs[0]=crc(crcs[0],in_buf,blksize);
#endif

                  if (cipher!=-1) {
                        tmpbuf=malloc(blksize*2);
                        x=ciphers[cipher](in_buf, tmpbuf, blksize, keybuf, DACT_MODE_CDEC);
                        memcpy(in_buf,tmpbuf,x);
                        free(tmpbuf);
                  }

/*
 * If the filesize is not specified, try to find it in the stream...
 * this is pretty stupid, because if we can't rewind OUR read stream
 * we're SOL... do we really need the filesize that badly?  I guess
 * we do to truncate the last of it...  Adding more checks in here..
 *
 * This will never get used, canlseek will be 1 only if we can sucessfully
 * seek, in which case, we have done it above.
 */
#if 0
                  if (filesize==0 && canlseek) {
                        read_de(src, &magic, 4);
                        read_de(src, &filesize, 4);
                        if (read(src, &x, 1)==0) {
                              if (magic!=DACT_MAGIC_PEOF) {
                                    dact_ui_status(DACT_UI_LVL_GEN, "Stream is corrupt.");
                                    free(in_buf);
                                    free(out_buf);
                                    return(0);
                              }
                        } else {
                              lseek(src, -9, SEEK_CUR);
                              filesize=0;
                        }
                  }
#endif


                  if ((bytes_read=dact_blk_decompress(out_buf, in_buf, blksize, 0, algo, out_bufsize))==0) {
                        if (cipher!=-1) {
                              PRINTERR("Decompression resulted in 0-byte block.  Invalid key?");
                        } else {
                              PRINTERR("Decompression resulted in 0-byte block.");
                        }
                  }
                  fileoutsize+=bytes_read;

/* If ciphering, don't try to calculate this (the plaintext) CRC. */
                  if (cipher==-1) {
#ifndef DACT_DONT_SUPPORT_OLDDACT
                        if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
                              PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
                              crcs[1]=elfcrc(crcs[1],out_buf,bytes_read);
                        } else {
                              crcs[1]=crc(crcs[1],out_buf,bytes_read);
                        }
#else
                        crcs[1]=crc(crcs[1],out_buf,bytes_read);
#endif
                  }

                  dact_ui_incrblkcnt(1);

                  if (fileoutsize>filesize && filesize!=0) {
                        write(dest, out_buf, blksize_uncomp-(fileoutsize-filesize));
                  } else {
                        write(dest, out_buf, bytes_read);
                  }

                  free(in_buf);
            }

            free(out_buf);

            if ((crcs[0]!=crcs[2] && crcs[0]!=0 && crcs[2]!=0) \
              || (crcs[1]!=crcs[3] && crcs[1]!=0 && crcs[3]!=0)) {
                  dact_ui_status(DACT_UI_LVL_GEN, "CRC error.");
                  if (!options[DACT_OPT_NOCRC] || options[DACT_OPT_FORCE]<1)
                        return(0);
            }

            dact_hdr_ext_clear();

            return(filesize);

      }


      if (mode==DACT_MODE_STAT) {
            read_de(src, &magic, 4, sizeof(magic));
            read(src, &version[0], 1);
            read(src, &version[1], 1);
            read(src, &version[2], 1);
#ifndef DACT_DONT_SUPPORT_OLDDACT
            if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
                  PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
                  read_de(src, &filesize, 4, sizeof(filesize));
                  hdr_reg_size=24;
            } else {
                  read_de(src, &filesize, 8, sizeof(filesize));
            }
#else
            read_de(src, &filesize, 8, sizeof(filesize));
#endif
            read_de(src, &blk_cnt, 4, sizeof(blk_cnt));
            read_de(src, &blksize, 4, sizeof(blksize));
            read(src, &file_opts, 1);
            read_de(src, &file_extd_size, 4, sizeof(file_extd_size));

            printf("File              :   %s\n", filename);
            printf("Magic             :   0x%08x",magic);
            if (magic!=DACT_MAGIC_NUMBER) {
                  printf(" (bad magic)\n");
                  return(0);
            } else {
                  printf("\n");
            }

            if (filesize==0) {
                  if (lseek_net(src, offset+1, SEEK_SET)==(offset+1)) {
#ifndef DACT_DONT_SUPPORT_OLDDACT
                        if (DACT_VERS(version[0], version[1], version[2])<DACT_VERS(0, 8, 39)) {
                              PRINTERR("**WARNING** This file uses the old DACT file header, support will go away in future versions for this.");
                              lseek_net(src, -8, SEEK_END);
                              read_de(src, &magic, 4, sizeof(magic));
                              read_de(src, &filesize, 4, sizeof(filesize));
                              hdr_reg_size=24;
                        } else {
                              lseek_net(src, -12, SEEK_END);
                              read_de(src, &magic, 4, sizeof(magic));
                              read_de(src, &filesize, 8, sizeof(filesize));
                        }
#else
                        lseek_net(src, -12, SEEK_END);
                        read_de(src, &magic, 4, sizeof(magic));
                        read_de(src, &filesize, 8, sizeof(filesize));
#endif
                        if (magic!=DACT_MAGIC_PEOF) {
                              PRINTERR("Bad end-of-file magic.  Corrupt or incomplete file?");
                              filesize=0;
                        }
                  }
            }
            fileoutsize=lseek_net(src, 0, SEEK_END);
            fileoutsize-=offset;

            printf("Dact Version      :   %i.%i.%i\n",version[0],version[1],version[2]);
            printf("Block Size        :   %i\n", blksize);
            printf("Block Header Size :   %i\n", BYTESIZE(blksize)+1);
            printf("Compressed Size   :   %llu\n", fileoutsize);
            printf("Uncompressed Size :   %llu\n", filesize);
            printf("Ratio             :   %2.3f to 1.0\n", ((float) filesize)/((float) fileoutsize) );
            lseek_net(src, offset+hdr_reg_size, SEEK_SET);
            while (file_extd_read<file_extd_size) {
                  x=0;
                  read(src, &ch, 1);
                  if (ch!=DACT_HDR_NOP) read_de(src, &x, 2, sizeof(x)); 
                  switch (ch) {
                        case DACT_HDR_CRC0:
                              read_de(src, &crcs[2], 4, sizeof(crcs[2]));
                              printf("CRC 0             :   0x%08x\n", crcs[2]);
                              break;
                        case DACT_HDR_CRC1:
                              read_de(src, &crcs[3], 4, sizeof(crcs[3]));
                              printf("CRC 1             :   0x%08x\n", crcs[3]);
                              break;
                        case DACT_HDR_NAME:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              printf("Original Name     :   %s\n", hdr_buf);
                              free(hdr_buf);
                              break;
                        case DACT_HDR_URL:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
                              free(hdr_buf);
                              break;
                        case DACT_HDR_URLFILE:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              printf("Download Loc File :   %s\n", hdr_buf);
                              extd_urlfile=fopen(hdr_buf, "r");
                              free(hdr_buf);   /* We shouldn't need this anymore. */
                              if (extd_urlfile==NULL) break;
                              hdr_buf=malloc(4096);
                              while (1) {
                                    fgets(hdr_buf, 4095, extd_urlfile);
                                    if (feof(extd_urlfile)) break;
                                    hdr_buf=strsep(&hdr_buf,"\n");
                                    file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename);
                              }
                              free(hdr_buf);
                              break;
                        case DACT_HDR_DESC:
                              hdr_buf=malloc(x+1);
                              read_f(src, hdr_buf, x);
                              hdr_buf[x]=0;
                              printf("Description       :   %s\n", hdr_buf);
                              free(hdr_buf);
                              break;
                        case DACT_HDR_CIPHER:
                              read_de(src, &cipher, x, sizeof(cipher));
                              printf("Ciphered using    :   %s\n", ciphers_name[cipher]);
                              break;
                        case DACT_HDR_NOP:
                              x=-2;
                              break;
                        case DACT_HDR_SFXLEN:
                              read_de(src, &offset, x, sizeof(offset));
                              printf("Program length    :   %lu\n", offset);
                              break;
                        default:
                              hdr_buf=malloc(x);
                              read_f(src, hdr_buf, x);
                              free(hdr_buf);
                              break;
                  }


                  file_extd_read+=(x+3);
            }

            for (x=0;x<file_extd_urlcnt;x++) {
                  printf("Download Location :   %s",file_extd_urls[x]);
                  if (options[DACT_OPT_VERB]) {
                        if ((new_fd=open_net(file_extd_urls[x],O_RDONLY, 0))<0) {
                              printf(" [broken]\n");
                              continue;
                        }
                        close(new_fd);
                  }
                  printf("\n");
            }

            blk_cnt=0;
            blksize_size=BYTESIZE(blksize);
            if (options[DACT_OPT_VERB]) {
                  lseek_net(src, offset+hdr_reg_size+file_extd_size, SEEK_SET);
                  printf("\n");
                  printf("Break down: \n");
                  printf("  Blk | Algo | Size    | Name\n");
                  printf("  ----+------+---------+---------------------------\n");
                  while (1) {
                        if (read(src, &algo, 1)==0) break;
                        if (algo==0xff) break; /* 0xff is reserved for EOF */

                        read_de(src, &blksize, blksize_size, sizeof(blksize));
                        lseek_net(src, blksize, SEEK_CUR);
                        printf("  %03i | %03i  | %-7i | %s\n",blk_cnt,algo,blksize,algorithm_names[algo]);
                        blk_cnt++;
                  }
            }

            printf("\n");


            return(1);
      }

      return(0);
}

uint32_t dact_process_other(int src, const int dest, const uint32_t magic, const char *options) {
      char *buf, tmpbuf[128]="/tmp/dactXXXXXX";
      uint32_t filesize=0, x;
      int tmpfd=0;
#if defined(HAVE_LIBBZ2) && (defined(HAVE_BZDOPEN) || defined(HAVE_NEW_BZDOPEN))
      BZFILE *bzfd;
#endif
#if defined(HAVE_LIBZ) && defined(HAVE_GZDOPEN)
      gzFile gzfd;
#endif

      filesize=0;  /* Fix a warning, that is all. */

/*
 * bad and broke stuff XXX FIXME XXX FIXME XXX FIXME
 * There has to be a better way to do this... I just want
 * to rewind my socket/pipe 4 bytes... 4 bytes is all I ask
 * Is that so much to ask for?  Well?!  Is it?!  I don't
 * think it is.
 * I give up on this.
 *
 * Someone please fix it.
 *  -- Roy Keene <dact@rkeene.org>
 */
      if (lseek_net(src, 0, SEEK_SET)<0) {
/*
 * lseek_net() should make this obsolete.
 *  ... EXCEPT! when reading from stdin.
 */
            tmpfd=mkstemp(tmpbuf);
            write_de(tmpfd, magic, 4);
            buf=malloc(1024);
            while (1) {
                  x=read_f(src, buf, 1024);
                  write(tmpfd, buf, x);
                  if (x<1024) break;
            }
            close(src);
            src=tmpfd;
            lseek_net(src, 0, SEEK_SET); /* Now bitch. */
            free(buf);
      }
#if defined(HAVE_LIBZ) && defined(HAVE_GZDOPEN)

      if ((magic&0xffff0000)==0x1f8b0000) { /* gzip */
            dact_ui_status(DACT_UI_LVL_GEN, "Gunzipping...");
            buf=malloc(1024);

            gzfd=gzdopen(src, "r");
/*XXX: need to dact_ui_setup() */
            while (1) {
                  dact_ui_incrblkcnt(1);
                  x=gzread(gzfd,buf,1024);
                  filesize+=write(dest, buf, x);
                  if (x<1024) break;
            }
            free(buf);
            if (tmpfd!=0) unlink(tmpbuf);
            return(filesize);
      }
#endif

#if defined(HAVE_LIBBZ2) && (defined(HAVE_BZDOPEN) || defined(HAVE_NEW_BZDOPEN))
      if ((magic&0xffffff00)==0x425a6800) { /* bzip2 */ 
            dact_ui_status(DACT_UI_LVL_GEN, "Bunzipping...");
            buf=malloc(1024);

#ifdef HAVE_NEW_BZDOPEN
            bzfd=BZ2_bzdopen(src, "r");
#else
            bzfd=bzdopen(src, "r");
#endif
/*XXX: need to dact_ui_setup() */
            while(1) {
                  dact_ui_incrblkcnt(1);
#ifdef HAVE_NEW_BZDOPEN
                  x=BZ2_bzread(bzfd, buf, 1024);
#else
                  x=bzread(bzfd, buf, 1024);
#endif
                  filesize+=write(dest, buf, x);
                  if (x<1024) break;
            }
            free(buf);
            if (tmpfd!=0) unlink(tmpbuf);
            return(filesize);
      }
#endif
      return(0);
}

Generated by  Doxygen 1.6.0   Back to index