⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 leafpak.c

📁 leafpak: 一个文件打包器的源代码
💻 C
字号:
/* * leafpak.c * decode leaf archive file. * 10/06/1997 by TF <tf@imou.to> *//* * Changes: * 10/31/2000 TAKAHASHI Kaoru <kaoru@kaisei.org> *            Fixed a probrem when fopen(,"w") failed. * 10/17/1997 FUJIWARA Teruyoshi <tf@imou.to> *            Add auto key calculation. *            Support maxxdata.pak in 'Saorin to Issho!!'*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "leafpak.h"static void check_magic(FILE *);static int get_file_num(FILE *);static void set_type(LEAFPACK *);static void init_leafpack(LEAFPACK *);static void extract_table(LEAFPACK *);static void regularize_name(char *);static void guess_key(LEAFPACK *);#ifdef DEBUGstatic void verify_key(LEAFPACK *);#endif/* * Open archive file and extact file table. */LEAFPACK *leafpack_open(const char *filename){  LEAFPACK *lp = NULL;    lp = (LEAFPACK *)malloc(sizeof(LEAFPACK));  if (lp == NULL) {    fprintf(stderr, "leafpack_open: Memory allocation error.\n");    return NULL;  }    lp->fp = fopen(filename, "r");  if (lp->fp == NULL) {    fprintf(stderr, "leafpack_open: Can't open %s\n", filename);    return NULL;  }    check_magic(lp->fp);  lp->file_num = get_file_num(lp->fp);  set_type(lp);  if (lp->type == UNKNOWN) {    guess_key(lp);  }  init_leafpack(lp);  extract_table(lp);    return lp;}/* * Free allocated memories and close file. */void leafpack_close(LEAFPACK *lp){  int i;  if (lp->fp != NULL) {    fclose(lp->fp);  }  lp->fp = NULL;  for (i = 0; i < lp->file_num; i++) {    free(lp->name[i]);  }    free(lp->name);  free(lp->pos);  free(lp->len);  free(lp->nextpos);  free(lp);}/* * Extract all archive into current directory. Archive file * shuold already be opend. */void extract_all(LEAFPACK *lp){  int i, k;  int val, pos;  FILE *fp;  for (i = 0; i < lp->file_num; i++) {    fp = fopen(lp->name[i], "w");    if (fp == NULL) {      printf("Can't write %s. skip\n", lp->name[i]);    } else {      printf("extracting %s...", lp->name[i]);      fflush(stdout);      pos = lp->pos[i];      fseek(lp->fp, (long)pos, SEEK_SET);      k = 0;      while (pos != lp->nextpos[i]) {	val = (fgetc(lp->fp) - lp->key[k]) & 0xff;	k = (++k) % KEY_LEN; 	fputc(val, fp);	pos++;      }      fclose(fp);      printf("done.\n");    }  }  printf("\nAll files are extracted.\n");}/* * Extract a file specified by name from archive. Archive file * shuold already be opened. */int leafpack_extract_file(LEAFPACK *lp, const char *file){  int i = 0, k = 0;  int val, pos;  FILE *fp;  /* lookup table */  while (i < lp->file_num) {    if (!strcasecmp(file, lp->name[i])) {      break;    }    i++;  }    if (i == lp->file_num) {    printf("%s isn't included in this archive.\n", file);    return 1;  }  printf("extracting %s...", file);  fflush(stdout);  fp = fopen(file, "w");  if ( fp == NULL ) {    printf("Can't write %s.\n", file);    return -1;  }  pos = lp->pos[i];  fseek(lp->fp, (long)pos, SEEK_SET);  while (pos != lp->nextpos[i]) {    val = (fgetc(lp->fp) - lp->key[k]) & 0xff;    k = (++k) % KEY_LEN;     fputc(val, fp);    pos++;  }  fclose(fp);  printf("done.\n");  return 0;}/* * a char array 'buf' should have size more than 9.*/void leafpack_read_magic(LEAFPACK *lp, const char *file, char *buf){  int i = 0;  int pos;  /* lookup table */  while (i < lp->file_num) {    if (!strcasecmp(file, lp->name[i])) {      break;    }    i++;  }    if (i == lp->file_num) {    printf("%s isn't included in archive.\n", file);    buf[0] = '\0';    return;  }  pos = lp->pos[i];  fseek(lp->fp, (long)pos, SEEK_SET);  for (i = 0; i < 8; i++) {    buf[i] = (fgetc(lp->fp) - lp->key[i]) & 0xff;   }  buf[8] =  '\0';  return;}int *leafpack_extract_file_to_data(LEAFPACK *lp, const char *file, int *size){  int i = 0, j = 0, k = 0;  int pos;  int *res;  /* lookup table */  while (i < lp->file_num) {    if (!strcasecmp(file, lp->name[i])) {      break;    }    i++;  }    if (i == lp->file_num) {    printf("%s isn't included in archive.\n", file);    return NULL;  }  *size = lp->len[i];  printf("extracting %s...", file);  fflush(stdout);  res = (int *)calloc(lp->len[i], sizeof(int));  pos = lp->pos[i];  fseek(lp->fp, (long)pos, SEEK_SET);  while (pos != lp->nextpos[i]) {    res[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff;    k = (++k) % KEY_LEN;     pos++;    j++;  }  printf("done.\n");  return res;}/* * PRIVATE FUNCTIONS*/static void check_magic(FILE *fp){  int i;  char buf[9];  for (i = 0; i < 8; i++) {    buf[i] = fgetc(fp);  }  buf[8] = '\0';  if (strcmp(buf, "LEAFPACK")) {    fprintf(stderr, "This file isn't a Leaf archive file.\n");    exit(1);  }}static int get_file_num(FILE *fp){  int u, l;    l = fgetc(fp);  u = fgetc(fp);  return u << 8 | l;}/* * Type is set by the number of files included in an archive file. * (And this type is used to select an encryption key!) * Then we can't extract an unkown archive. *//* * 10/16/1997: Add auto key calculation feature(experimental). */static void set_type(LEAFPACK *lp){  guess_key(lp);  if (lp->file_num == 0x0248 || lp->file_num == 0x03e1) {    lp->type = TOHEART;    return;  } else if (lp->file_num == 0x01fb) {    lp->type = KIZUWIN;    return;  } else if (lp->file_num == 0x0193) {    lp->type = SIZUWIN;    return;  } else if (lp->file_num == 0x0072) {    lp->type = SAORIN;  } else {    lp->type = UNKNOWN;  }  #ifdef DEBUG  verify_key(lp);#endif}#ifdef DEBUGstatic void verify_key(LEAFPACK *lp){  int i;  int result = TRUE;  if (lp->type == UNKNOWN || lp->type == SAORIN) {    return;  }  for (i = 0; i < KEY_LEN; i++) {    if (key_const[lp->type][i] != lp->key[i]) {      fprintf(stderr, "Warning: An auto-calculated key is bad.\n");      result = FALSE;      break;    }  }  if (result == FALSE) {    for (i = 0; i < KEY_LEN; i++) {      lp->key[i] = key_const[lp->type][i];    }  }}#endifstatic void init_leafpack(LEAFPACK *lp){  int i;  /* initialize a filename table */  lp->name = (char **)calloc(lp->file_num, sizeof(char *));  for (i = 0; i < lp->file_num; i++) {    lp->name[i] = (char *)calloc(13, sizeof(char));  }  /* initialize table entories */  lp->pos = (int *)calloc(lp->file_num, sizeof(int));  lp->len = (int *)calloc(lp->file_num, sizeof(int));  lp->nextpos = (int *)calloc(lp->file_num, sizeof(int));}static void extract_table(LEAFPACK *lp){  int i, j;  int k = 0;  int b[4];  /* set a position to the head of the header part */  fseek(lp->fp, (long)(-24 * lp->file_num), SEEK_END);  for (i = 0; i < lp->file_num; i++) {    /* get filename */    for (j = 0; j < 12; j++) {      lp->name[i][j] = (fgetc(lp->fp) - lp->key[k]) & 0xff;      k = (++k) % KEY_LEN;     }    regularize_name(lp->name[i]);    /* a position in the archive file */    for (j = 0; j < 4; j++) {      b[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff;      k = (++k) % KEY_LEN;     }    lp->pos[i] = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];    /* file length */    for (j = 0; j < 4; j++) {      b[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff;      k = (++k) % KEY_LEN;     }    lp->len[i] = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];        /* the head of the next file */    for (j = 0; j < 4; j++) {      b[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff;      k = (++k) % KEY_LEN;     }    lp->nextpos[i] = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];  }}static void regularize_name(char *name){  char buf[12];  int i = 0;  strcpy(buf, name);  while (i < 8 && buf[i] != 0x20) {    name[i] = buf[i];    i++;  }  name[i++] = '.';  /* file extention */  name[i++] = buf[8];  name[i++] = buf[9];  name[i++] = buf[10];  name[i] = '\0';}void print_type(LEAFPACK *lp){  printf("Archive file: ");  switch (lp->type) {  case SIZUWIN:    printf("SHIZUKU for Windows95\n\n");    break;  case KIZUWIN:    printf("KIZUATO for Windows95\n\n");    break;  case TOHEART:    printf("To Heart\n\n");    break;  case SAORIN:    printf("Saorin to Issho!! (maxxdata.pak)\n\n");    break;  default:    printf("Unknown\n\n");  }}void print_table(LEAFPACK *lp, int verbose){  int i;  if (verbose == TRUE) {    printf("Key: ");    for (i = 0; i < KEY_LEN; i++) {      printf("%02x ", lp->key[i]);    }    printf("\n\n");  }    if (verbose == TRUE) {      printf("Filename      Position  Length   Next\n");    printf("------------  --------  -------  --------\n");  } else {    printf("Filename       Length\n");    printf("------------   -------\n");  }  for (i = 0; i < lp->file_num; i++) {    printf("%12s  ", lp->name[i]);    if (verbose == TRUE) {      printf("%08x ", lp->pos[i]);    }    printf("%8d  ", lp->len[i]);    if (verbose == TRUE) {      printf("%08x", lp->nextpos[i]);    }    printf("\n");  }  printf("%d files.\n", lp->file_num);}/* * Calculate key using length of archive data. * To use this function, the archive must include at least 3 files. */static void guess_key(LEAFPACK *lp){  int buf[72];  int i;  /* find the top of table */  fseek(lp->fp, (long)(-24 * lp->file_num), SEEK_END);  /* read 3 table entries, needed to calculate keys. */  for (i = 0; i < 72; i++) {    buf[i] = fgetc(lp->fp);  }    /* zero */  lp->key[0] = buf[11];    /* 1st position, (maybe :-)) constant */  lp->key[1] = (buf[12] - 0x0a) & 0xff;  lp->key[2] = buf[13];  lp->key[3] = buf[14];  lp->key[4] = buf[15];  /* 2nd position, from 1st next position */  lp->key[5] = (buf[38] -  buf[22] + lp->key[0]) & 0xff;  lp->key[6] = (buf[39] -  buf[23] + lp->key[1]) & 0xff;    /* 3rd position, from 2nd next position */  lp->key[7] = (buf[62] - buf[46] + lp->key[2]) & 0xff;  lp->key[8] = (buf[63] - buf[47] + lp->key[3]) & 0xff;  /* 1st next position, from 2nd position */  lp->key[9] = (buf[20] - buf[36] + lp->key[3]) & 0xff;  lp->key[10] = (buf[21] - buf[37] + lp->key[4]) & 0xff;}/* end of file */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -