1 /* 2 * Copyright (C) 2001, 2002, and 2003 Roy Keene 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 18 * email: dact@rkeene.org 19 */ 20 21 #include "dact.h" 22 #define __DACT_C 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <ctype.h> 26 #ifdef HAVE_UNISTD_H 27 #include <unistd.h> 28 #endif 29 #ifdef HAVE_STDLIB_H 30 #include <stdlib.h> 31 #endif 32 #ifdef HAVE_STRING_H 33 #include <string.h> 34 #endif 35 #ifdef HAVE_SYS_STAT_H 36 #include <sys/stat.h> 37 #endif 38 #ifdef HAVE_SYS_WAIT_H 39 #include <sys/wait.h> 40 #endif 41 #ifdef HAVE_SYS_TYPES_H 42 #include <sys/types.h> 43 #endif 44 #include "parse.h" 45 #include "dendian.h" 46 #include "crc.h" 47 #include "math.h" 48 #include "dact_common.h" 49 #include "algorithms.h" 50 #include "ciphers.h" 51 #include "module.h" 52 #include "header.h" 53 #include "parse.h" 54 #include "net.h" 55 #include "ui.h" 56 #ifdef HAVE_ZLIB_H 57 #include <zlib.h> 58 #endif 59 #ifdef HAVE_BZLIB_H 60 #include <bzlib.h> 61 #endif 62 63 int dact_config_execute(const char *cmd, char *options, uint32_t *blksize) { 64 char *line=NULL, *line_s, *item_buf[4]={NULL, NULL, NULL, NULL}; 65 int i; 66 67 line_s=line=strdup(cmd); 68 if (line[0]=='#') return(0); 69 while (line[strlen(line)-1]<32) line[strlen(line)-1]='\0'; 70 for (i=0;i<4;i++) item_buf[i]=NULL; 71 for (i=0;i<4;i++) { 72 if ((item_buf[i]=strsep(&line, "\t "))==NULL) break; 73 if (item_buf[i][0]==0) i--; 74 } 75 if (item_buf[0]==NULL || item_buf[1]==NULL) return(0); /* This means all commands must have arguments. */ 76 77 switch (ELFCRC(0, item_buf[0], strlen(item_buf[0]))) { 78 case 164209419: /* binary_check */ 79 options[DACT_OPT_BINCHK]=!!strcmp(item_buf[1],"off"); 80 break; 81 case 9456603: /* version_check */ 82 options[DACT_OPT_VERCHK]=!!strcmp(item_buf[1],"off"); 83 break; 84 case 204349618: /* module_dir */ 85 if ((sizeof(moduledirectory)-strlen(moduledirectory)-1)<=0) break; 86 strncat(moduledirectory,":",sizeof(moduledirectory)-strlen(moduledirectory)-1); 87 strncat(moduledirectory,item_buf[1],sizeof(moduledirectory)-strlen(moduledirectory)-1); 88 break; 89 case 247248556: /* module_load_all */ 90 if (strcmp(item_buf[1], "on")==0) { 91 init_modules(); 92 load_modules_all(options); 93 } 94 break; 95 case 48402100: /* module_load */ 96 case 106360197: /* load_module */ 97 init_modules(); 98 load_module(item_buf[1], options); 99 break; 100 case 164097267: /* network_access */ 101 #ifndef NO_NETWORK 102 dact_nonetwork=!strcmp(item_buf[1],"off"); 103 #endif 104 break; 105 case 209445231: /* exclude_algo */ 106 i=(atoi(item_buf[1])&0xff); 107 algorithms[i]=DACT_FAILED_ALGO; 108 break; 109 case 168825941: /* block_size */ 110 if (blksize!=NULL) { 111 *blksize=atoi2(item_buf[1]); 112 } 113 break; 114 case 162975987: /* use_urls */ 115 options[DACT_OPT_URL]=!!strcmp(item_buf[1],"off"); 116 break; 117 case 104235033: /* color_ui */ 118 dact_ui_setopt(DACT_UI_OPT_COLOR,!!strcmp(item_buf[1],"off")); 119 break; 120 case 164800901: /* module_upgrade */ 121 if (strcmp(item_buf[1],"on")==0) options[DACT_OPT_UPGRADE]=1; 122 break; 123 case 63160590: /* pass_use_stdin */ 124 case 191551086: /* use_stdin */ 125 dact_ui_setopt(DACT_UI_OPT_PASSSTDIN, 1); 126 break; 127 #ifdef DEBUG 128 default: 129 fprintf(stderr, "Unknown command %s (%i)\n",item_buf[0],ELFCRC(0,item_buf[0],strlen(item_buf[0]))); 130 break; 131 #endif 132 } 133 free(line_s); 134 return(1); 135 } 136 137 void dact_config_loadfile(const char *path, char *options, uint32_t *blksize) { 138 char *line=NULL; 139 FILE *cfd; 140 141 line=malloc(512); 142 if ((cfd=fopen(path,"r"))==NULL) return; 143 while (!feof(cfd)) { 144 fgets(line, 511, cfd); 145 dact_config_execute(line, options, blksize); 146 } 147 free(line); 148 fclose(cfd); 149 } 150 151 uint32_t dact_blk_decompress(char *ret, const char *srcbuf, const uint32_t size, const char *options, const int algo, uint32_t bufsize) { 152 uint32_t retval; 153 154 if (algo==0xff) return(0); 155 156 if (algorithms[algo]==NULL) { 157 PRINTERR("Algorithm unavailble."); 158 return(0); 159 } 160 161 retval=algorithms[algo](DACT_MODE_DECMP, NULL, srcbuf, ret, size, bufsize); 162 163 return(retval); 164 } 165 166 167 uint32_t dact_blk_compress(char *algo, char *ret, const char *srcbuf, const uint32_t size, const char *options, uint32_t bufsize) { 168 char *tmpbuf, *smallbuf=NULL; 169 int i, highest_algo=0; 170 char smallest_algo; 171 uint32_t smallest_size=-1, x; 172 #ifndef DACT_UNSAFE 173 char *verif_bf=NULL; 174 uint32_t m; 175 if ((verif_bf=malloc(size))==NULL) { PERROR("malloc"); return(0); } 176 #endif 177 178 if ((tmpbuf=malloc(bufsize))==NULL) { PERROR("malloc"); return(0); } 179 180 for (i=0;i<256;i++) { 181 if (algorithms[i]!=NULL && algorithms[i]!=DACT_FAILED_ALGO) highest_algo=i; 182 } 183 184 for (i=0;i<=highest_algo;i++) { 185 if (algorithms[i]!=NULL && algorithms[i]!=DACT_FAILED_ALGO) { 186 x=algorithms[i](DACT_MODE_COMPR, NULL, srcbuf, tmpbuf, size, bufsize); 187 #ifndef DACT_UNSAFE 188 if ((x<smallest_size || smallest_size==-1) && x!=-1) { 189 m=algorithms[i](DACT_MODE_DECMP, NULL, tmpbuf, verif_bf, x, size); 190 if (memcmp(verif_bf, srcbuf,m) || m!=size) { 191 x=-1; 192 if (options[DACT_OPT_COMPLN]) { 193 dact_ui_status(DACT_UI_LVL_ALL, "Compression verification failed (ignoring)"); 194 } 195 } 196 } 197 #endif 198 if ((x<smallest_size || smallest_size==-1) && x!=-1) { 199 smallest_size=x; 200 smallest_algo=i; 201 if (smallbuf!=NULL) free(smallbuf); 202 if ((smallbuf=malloc(smallest_size))==NULL) { 203 PERROR("malloc"); 204 free(tmpbuf); 205 #ifndef DACT_UNSAFE 206 free(verif_bf); 207 #endif 208 return(0); 209 } 210 memcpy(smallbuf, tmpbuf, smallest_size); 211 } 212 213 if (options[DACT_OPT_VERB]>2) { 214 PRINT_LINE; fprintf(stderr, "dact: \033[%im----| %03i | %-7i | %s\033[0m\n", (smallest_algo==i)*7 , i, x, algorithm_names[i]); 215 } 216 217 } 218 } 219 220 free(tmpbuf); 221 #ifndef DACT_UNSAFE 222 free(verif_bf); 223 #endif 224 if (smallest_size==-1) { 225 return(0); 226 } 227 memcpy(algo, &smallest_algo, sizeof(char)); 228 memcpy(ret, smallbuf, smallest_size); 229 /* This was MISSING ! memory leak. */ 230 free(smallbuf); 231 return(smallest_size); 232 } 233 234 uint32_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) { 235 struct stat filestats; 236 FILE *extd_urlfile; 237 char *file_extd_urls[256]; 238 unsigned char algo; 239 char ch; 240 char *in_buf, *out_buf, *hdr_buf, *keybuf=NULL, *tmpbuf=NULL; 241 char version[3]={DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION}; 242 char file_opts=0; 243 uint32_t bytes_read, retsize; 244 uint32_t filesize=0, blk_cnt=0, file_extd_size=0, blksize=0, fileoutsize=0, out_bufsize=0; 245 uint32_t magic=0, file_extd_read=0, file_extd_urlcnt=0; 246 int blksize_size; 247 int x=0, new_fd, canlseek=0; 248 249 fstat(src,&filestats); 250 251 if (mode==DACT_MODE_COMPR) { 252 /* 253 * Calculate the default block size. 254 */ 255 blksize=dact_blksize; 256 if (blksize==0) { 257 blksize=dact_blksize_calc(filestats.st_size); 258 } 259 out_bufsize=blksize*2; 260 if (((in_buf=malloc(blksize))==NULL) || \ 261 ((out_buf=malloc(out_bufsize))==NULL)) { 262 PERROR("malloc"); 263 return(0); 264 } 265 266 dact_ui_setup(((float) (filestats.st_size/blksize)+0.9999)); 267 if (cipher!=-1) { 268 dact_hdr_ext_regn(DACT_HDR_CIPHER, cipher, sizeof(cipher)); 269 keybuf=malloc(DACT_KEY_SIZE); 270 ciphers[cipher](NULL, NULL, 0, keybuf, DACT_MODE_CINIT+DACT_MODE_CENC); 271 272 } 273 blksize_size=BYTESIZE(blksize); 274 275 if (!options[DACT_OPT_ORIG] && filename!=NULL) 276 dact_hdr_ext_regs(DACT_HDR_NAME, filename, strlen(filename)); 277 file_extd_size=(dact_hdr_ext_size()+14); /* The +14 is for crc0 and crc1 */ 278 write_de(dest, DACT_MAGIC_NUMBER, 4); 279 write(dest, &version[0], 1); 280 write(dest, &version[1], 1); 281 write(dest, &version[2], 1); 282 write_de(dest, 0, 4); /* Place holder for ORIG FILE SIZE */ 283 write_de(dest, 0, 4); /* Place holder for NUM BLOCKS */ 284 write_de(dest, blksize, 4); 285 write_de(dest, file_opts, 1); /* XXX: Option byte... Or not? */ 286 write_de(dest, file_extd_size, 4); /* Place holder for SIZEOF EXTENDED DTA */ 287 /* Fill the header with NOPs incase we can't come back and put the CRCs */ 288 ch=DACT_HDR_NOP; 289 for (x=0;x<file_extd_size;x++) write(dest, &ch, 1); 290 291 if (options[DACT_OPT_VERB]>1) { 292 PRINTERR("Blk | Algo | Size | Name"); 293 PRINTERR("----+------+---------+---------------------------"); 294 } 295 296 memset(in_buf, 0, blksize); 297 while ( (bytes_read=read_f(src, in_buf, blksize))>0) { 298 filesize+=bytes_read; 299 blk_cnt++; 300 301 retsize=dact_blk_compress(&algo, out_buf, in_buf, blksize, options, out_bufsize); 302 303 /* CIPHER the data if an encryption algorithm is specified. */ 304 if (cipher!=-1) { 305 tmpbuf=malloc(retsize*2); 306 x=ciphers[cipher](out_buf, tmpbuf, retsize, keybuf, DACT_MODE_CENC); 307 memcpy(out_buf,tmpbuf,x); 308 free(tmpbuf); 309 } 310 311 if (retsize>0) { 312 if (options[DACT_OPT_VERB]>1) { 313 if (options[DACT_OPT_VERB]>2) { 314 PRINTERR("^^^\\ /^^^^\\ /^^^^^^^\\ /^^^^^^^^^^^^^^^^^^^^^^^^^^"); 315 } 316 PRINT_LINE; fprintf(stderr, "dact: %03i | %03i | %-7i | %s\n",blk_cnt,algo,retsize,algorithm_names[algo]); 317 if (options[DACT_OPT_VERB]>2) { 318 PRINTERR("___/ \\____/ \\_______/ \\__________________________"); 319 } 320 } 321 322 323 dact_ui_incrblkcnt(1); 324 dact_ui_status(DACT_UI_LVL_GEN, "Algorithm "); 325 dact_ui_status_append(DACT_UI_LVL_GEN,algorithm_names[algo]); 326 327 crcs[0]=ELFCRC(crcs[0], out_buf, retsize); 328 /* Do not generate a CRC of the plaintext if encrypting */ 329 if (cipher==-1) { 330 crcs[1]=ELFCRC(crcs[1], in_buf, blksize); 331 } 332 333 if (!options[DACT_OPT_HDONLY]) { 334 write(dest, &algo, 1); 335 write_de(dest, retsize, blksize_size); 336 337 if (write(dest, out_buf, retsize)!=retsize) { 338 PERROR("write"); 339 free(in_buf); 340 free(out_buf); 341 return(0); 342 } 343 } 344 } else { 345 PRINTERR("Compression resulted in 0-byte block."); 346 free(in_buf); 347 free(out_buf); 348 return(0); 349 } 350 memset(in_buf, 0, blksize); 351 } 352 353 if (bytes_read<0) { 354 PERROR("read"); 355 } 356 357 free(in_buf); 358 free(out_buf); 359 360 if (lseek_net(dest, 7, SEEK_SET)<0) { 361 /* If we can't rewind the stream, put magic+fileisze */ 362 write_de(dest, DACT_MAGIC_PEOF, 4); 363 write_de(dest, filesize, 4); 364 } else { 365 write_de(dest, filesize, 4); 366 write_de(dest, blk_cnt, 4); 367 } 368 369 if (lseek_net(dest, DACT_HDR_REG_SIZE, SEEK_SET)>0) { 370 if (!options[DACT_OPT_NOCRC]) { 371 dact_hdr_ext_regn(DACT_HDR_CRC0, crcs[0], 4); 372 dact_hdr_ext_regn(DACT_HDR_CRC1, crcs[1], 4); 373 } 374 write(dest, dact_hdr_ext_data(), dact_hdr_ext_size()); 375 } 376 377 dact_hdr_ext_clear(); 378 379 return(filesize); 380 } 381 382 if (mode==DACT_MODE_DECMP) { 383 384 dact_ui_status(DACT_UI_LVL_GEN, "Decompressing."); 385 386 dact_hdr_ext_clear(); 387 388 read_de(src, &magic, 4, sizeof(magic)); 389 390 if (magic!=DACT_MAGIC_NUMBER) { 391 dact_ui_status(DACT_UI_LVL_GEN, "Bad DACT magic, checking others..."); 392 return(dact_process_other(src,dest,magic,options)); 393 } 394 395 read(src, &version[0], 1); 396 read(src, &version[1], 1); 397 read(src, &version[2], 1); 398 read_de(src, &filesize, 4, sizeof(filesize)); 399 read_de(src, &blk_cnt, 4, sizeof(blk_cnt)); 400 read_de(src, &blksize, 4, sizeof(blksize)); 401 read(src, &file_opts, 1); 402 read_de(src, &file_extd_size, 4, sizeof(file_extd_size)); 403 404 405 406 while (file_extd_read<file_extd_size) { 407 x=0; 408 read(src, &ch, 1); 409 if (ch!=DACT_HDR_NOP) read_de(src, &x, 2, sizeof(x)); 410 switch (ch) { 411 case DACT_HDR_CRC0: 412 read_de(src, &crcs[2], 4, sizeof(crcs[2])); 413 if (crcs[4]!=0 && crcs[2]!=crcs[4]) { 414 dact_ui_status(DACT_UI_LVL_GEN, "CRC error."); 415 if (!options[DACT_OPT_NOCRC]) 416 return(0); 417 } 418 break; 419 case DACT_HDR_CRC1: 420 read_de(src, &crcs[3], 4, sizeof(crcs[3])); 421 if (crcs[5]!=0 && crcs[3]!=crcs[5]) { 422 dact_ui_status(DACT_UI_LVL_GEN, "CRC error."); 423 if (!options[DACT_OPT_NOCRC]) 424 return(0); 425 } 426 break; 427 /* 428 429 XXX: Todo, make this do something... 430 case DACT_HDR_NAME: 431 break; 432 */ 433 case DACT_HDR_URL: 434 hdr_buf=malloc(x+1); 435 read_f(src, hdr_buf, x); 436 hdr_buf[x]=0; 437 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename); 438 free(hdr_buf); 439 break; 440 case DACT_HDR_URLFILE: 441 hdr_buf=malloc(x+1); 442 read_f(src, hdr_buf, x); 443 hdr_buf[x]=0; 444 extd_urlfile=fopen(hdr_buf, "r"); 445 free(hdr_buf); /* We shouldn't need this anymore. */ 446 if (extd_urlfile==NULL) break; 447 hdr_buf=malloc(4096); 448 while (1) { 449 fgets(hdr_buf, 4095, extd_urlfile); 450 if (feof(extd_urlfile)) break; 451 hdr_buf=strsep(&hdr_buf,"\n"); 452 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename); 453 } 454 free(hdr_buf); 455 break; 456 case DACT_HDR_DESC: 457 hdr_buf=malloc(x+1); 458 read_f(src, hdr_buf, x); 459 hdr_buf[x]=0; 460 fprintf(stderr, "DESC: %s\n",hdr_buf); 461 free(hdr_buf); 462 break; 463 case DACT_HDR_CIPHER: 464 read_de(src,&cipher,x,sizeof(cipher)); 465 break; 466 case DACT_HDR_NOP: 467 x=-2; 468 break; 469 default: 470 hdr_buf=malloc(x); 471 read_f(src, hdr_buf, x); 472 free(hdr_buf); 473 break; 474 } 475 476 477 478 file_extd_read+=(x+3); 479 } 480 481 if (options[DACT_OPT_URL]) { 482 for (x=0;x<file_extd_urlcnt;x++) { 483 dact_ui_status(DACT_UI_LVL_GEN,"Trying to get remote url "); 484 dact_ui_status_append(DACT_UI_LVL_SPEC, file_extd_urls[x]); 485 if ((new_fd=open_net(file_extd_urls[x],O_RDONLY,0))<0) { 486 dact_ui_status(DACT_UI_LVL_GEN, "Failed."); 487 continue; 488 } 489 close(src); 490 crcs[4]=crcs[2]; 491 crcs[5]=crcs[3]; 492 return(dact_process_file(new_fd, dest, mode, options, filename, crcs, blksize, cipher)); 493 } 494 } 495 496 497 /* 498 XXX: Even if we don't resolve it here, we can resolve it later... 499 Should we even bother to do it here if we can? 500 501 XXX: When CAN'T we rewind a read stream? 502 When it's a pipe 503 504 */ 505 if (filesize==0) { 506 /* See if we can rewind our stream, so when we get to the end, we can come back! */ 507 if (lseek_net(src, 1, SEEK_SET)==1) { /* MAJOR BUG HERE! was: lseek(src,1,SEEK_SET)==0 which will always be false. */ 508 canlseek=1; 509 lseek_net(src, -8, SEEK_END); 510 read_de(src, &magic, 4, sizeof(magic)); 511 if (magic!=DACT_MAGIC_PEOF) { 512 dact_ui_status(DACT_UI_LVL_GEN, "File is corrupt."); 513 return(0); 514 } 515 read_de(src, &filesize, 4, sizeof(filesize)); 516 lseek_net(src, DACT_HDR_REG_SIZE+file_extd_size, SEEK_SET); 517 } else { 518 canlseek=0; 519 } 520 } 521 522 out_bufsize=blksize; 523 if (((out_buf=malloc(out_bufsize))==NULL) ) { 524 PERROR("malloc"); 525 return(0); 526 } 527 528 529 blksize_size=BYTESIZE(blksize); 530 531 dact_ui_setup((int)(((float) filesize/(float) blksize)+0.9999)); 532 533 if (cipher!=-1) { 534 keybuf=malloc(DACT_KEY_SIZE); 535 ciphers[cipher](NULL, NULL, 0, keybuf, DACT_MODE_CINIT+DACT_MODE_CDEC); 536 537 } 538 539 540 541 while (1) { 542 if (read(src, &algo, 1)==0) break; 543 if (algo==0xff) break; /* 0xff is reserved for EOF */ 544 545 read_de(src, &blksize, blksize_size, sizeof(blksize)); 546 547 if ((in_buf=malloc(blksize))==NULL) { 548 PERROR("malloc"); 549 free(out_buf); 550 return(0); 551 } 552 553 read_f(src, in_buf, blksize); 554 555 crcs[0]=ELFCRC(crcs[0],in_buf,blksize); 556 557 if (cipher!=-1) { 558 tmpbuf=malloc(blksize*2); 559 x=ciphers[cipher](in_buf, tmpbuf, blksize, keybuf, DACT_MODE_CDEC); 560 memcpy(in_buf,tmpbuf,x); 561 free(tmpbuf); 562 } 563 564 /* 565 * If the filesize is not specified, try to find it in the stream... 566 * this is pretty stupid, because if we can't rewind OUR read stream 567 * we're SOL... do we really need the filesize that badly? I guess 568 * we do to truncate the last of it... Adding more checks in here.. 569 * 570 * This will never get used, canlseek will be 1 only if we can sucessfully 571 * seek, in which case, we have done it above. 572 */ 573 #if 0 574 if (filesize==0 && canlseek) { 575 read_de(src, &magic, 4); 576 read_de(src, &filesize, 4); 577 if (read(src, &x, 1)==0) { 578 if (magic!=DACT_MAGIC_PEOF) { 579 dact_ui_status(DACT_UI_LVL_GEN, "Stream is corrupt."); 580 free(in_buf); 581 free(out_buf); 582 return(0); 583 } 584 } else { 585 lseek(src, -9, SEEK_CUR); 586 filesize=0; 587 } 588 } 589 #endif 590 591 592 if ((bytes_read=dact_blk_decompress(out_buf, in_buf, blksize, 0, algo, out_bufsize))==0) { 593 if (cipher!=-1) { 594 PRINTERR("Decompression resulted in 0-byte block. Invalid key?"); 595 } else { 596 PRINTERR("Decompression resulted in 0-byte block."); 597 } 598 } 599 fileoutsize+=bytes_read; 600 601 /* If ciphering, don't try to calculate this CRC. */ 602 if (cipher==-1) { 603 crcs[1]=ELFCRC(crcs[1],out_buf,bytes_read); 604 } 605 606 dact_ui_incrblkcnt(1); 607 608 if (fileoutsize>filesize && filesize!=0) { 609 write(dest, out_buf, blksize-(fileoutsize-filesize)); 610 } else { 611 write(dest, out_buf, bytes_read); 612 } 613 614 615 616 free(in_buf); 617 618 619 } 620 621 free(out_buf); 622 623 if ((crcs[0]!=crcs[2] && crcs[0]!=0 && crcs[2]!=0) \ 624 || (crcs[1]!=crcs[3] && crcs[1]!=0 && crcs[3]!=0)) { 625 dact_ui_status(DACT_UI_LVL_GEN, "CRC error."); 626 if (!options[DACT_OPT_NOCRC] || options[DACT_OPT_FORCE]<1) 627 return(0); 628 } 629 630 dact_hdr_ext_clear(); 631 632 return(filesize); 633 634 } 635 636 637 if (mode==DACT_MODE_STAT) { 638 read_de(src, &magic, 4, sizeof(magic)); 639 read(src, &version[0], 1); 640 read(src, &version[1], 1); 641 read(src, &version[2], 1); 642 read_de(src, &filesize, 4, sizeof(filesize)); 643 read_de(src, &blk_cnt, 4, sizeof(blk_cnt)); 644 read_de(src, &blksize, 4, sizeof(blksize)); 645 read(src, &file_opts, 1); 646 read_de(src, &file_extd_size, 4, sizeof(file_extd_size)); 647 648 printf("File : %s\n", filename); 649 printf("Magic : 0x%08x",magic); 650 if (magic!=DACT_MAGIC_NUMBER) { 651 printf(" (bad magic)\n"); 652 return(0); 653 } else { 654 printf("\n"); 655 } 656 657 if (filesize==0) { 658 lseek_net(src, -8, SEEK_END); 659 read_de(src, &magic, 4, sizeof(magic)); 660 read_de(src, &filesize, 4, sizeof(filesize)); 661 if (magic!=DACT_MAGIC_PEOF) { 662 PRINTERR("Bad magic, corrupt stream."); 663 return(0); 664 } 665 } 666 fileoutsize=lseek_net(src, 0, SEEK_END); 667 668 printf("Dact Version : %i.%i.%i\n",version[0],version[1],version[2]); 669 printf("Block Size : %i\n", blksize); 670 printf("Block Header Size : %i\n", BYTESIZE(blksize)+1); 671 printf("Compressed Size : %i\n", fileoutsize); 672 printf("Uncompressed Size : %i\n", filesize); 673 printf("Ratio : %2.3f to 1.0\n", ((float) filesize)/((float) fileoutsize) ); 674 lseek_net(src, DACT_HDR_REG_SIZE, SEEK_SET); 675 while (file_extd_read<file_extd_size) { 676 x=0; 677 read(src, &ch, 1); 678 if (ch!=DACT_HDR_NOP) read_de(src, &x, 2, sizeof(x)); 679 switch (ch) { 680 case DACT_HDR_CRC0: 681 read_de(src, &crcs[2], 4, sizeof(crcs[2])); 682 printf("CRC 0 : 0x%08x\n", crcs[2]); 683 break; 684 case DACT_HDR_CRC1: 685 read_de(src, &crcs[3], 4, sizeof(crcs[3])); 686 printf("CRC 1 : 0x%08x\n", crcs[3]); 687 break; 688 case DACT_HDR_NAME: 689 hdr_buf=malloc(x+1); 690 read_f(src, hdr_buf, x); 691 hdr_buf[x]=0; 692 printf("Original Name : %s\n", hdr_buf); 693 free(hdr_buf); 694 break; 695 case DACT_HDR_URL: 696 hdr_buf=malloc(x+1); 697 read_f(src, hdr_buf, x); 698 hdr_buf[x]=0; 699 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename); 700 free(hdr_buf); 701 break; 702 case DACT_HDR_URLFILE: 703 hdr_buf=malloc(x+1); 704 read_f(src, hdr_buf, x); 705 hdr_buf[x]=0; 706 printf("Download Loc File : %s\n", hdr_buf); 707 extd_urlfile=fopen(hdr_buf, "r"); 708 free(hdr_buf); /* We shouldn't need this anymore. */ 709 if (extd_urlfile==NULL) break; 710 hdr_buf=malloc(4096); 711 while (1) { 712 fgets(hdr_buf, 4095, extd_urlfile); 713 if (feof(extd_urlfile)) break; 714 hdr_buf=strsep(&hdr_buf,"\n"); 715 file_extd_urls[file_extd_urlcnt++]=parse_url_subst(hdr_buf,filename); 716 } 717 free(hdr_buf); 718 break; 719 case DACT_HDR_DESC: 720 hdr_buf=malloc(x+1); 721 read_f(src, hdr_buf, x); 722 hdr_buf[x]=0; 723 printf("Description : %s\n", hdr_buf); 724 free(hdr_buf); 725 break; 726 case DACT_HDR_CIPHER: 727 read_de(src, &cipher, x, sizeof(cipher)); 728 printf("Ciphered using : %s\n", ciphers_name[cipher]); 729 break; 730 case DACT_HDR_NOP: 731 x=-2; 732 break; 733 default: 734 hdr_buf=malloc(x); 735 read_f(src, hdr_buf, x); 736 free(hdr_buf); 737 break; 738 } 739 740 741 file_extd_read+=(x+3); 742 } 743 744 for (x=0;x<file_extd_urlcnt;x++) { 745 printf("Download Location : %s",file_extd_urls[x]); 746 if (options[DACT_OPT_VERB]) { 747 if ((new_fd=open_net(file_extd_urls[x],O_RDONLY, 0))<0) { 748 printf(" [broken]\n"); 749 continue; 750 } 751 close(new_fd); 752 } 753 printf("\n"); 754 } 755 756 blk_cnt=0; 757 blksize_size=BYTESIZE(blksize); 758 if (options[DACT_OPT_VERB]) { 759 lseek_net(src, DACT_HDR_REG_SIZE+file_extd_size, SEEK_SET); 760 printf("\n"); 761 printf("Break down: \n"); 762 printf(" Blk | Algo | Size | Name\n"); 763 printf(" ----+------+---------+---------------------------\n"); 764 while (1) { 765 if (read(src, &algo, 1)==0) break; 766 if (algo==0xff) break; /* 0xff is reserved for EOF */ 767 768 read_de(src, &blksize, blksize_size, sizeof(blksize)); 769 lseek_net(src, blksize, SEEK_CUR); 770 printf(" %03i | %03i | %-7i | %s\n",blk_cnt,algo,blksize,algorithm_names[algo]); 771 blk_cnt++; 772 } 773 } 774 775 printf("\n"); 776 777 778 return(1); 779 } 780 781 return(0); 782 } |