Ejemplo n.º 1
0
static void
chmfile_windows_info(struct chmFile *cfd, ChmFile *chmfile)
{
  struct chmUnitInfo ui;
  unsigned char buffer[4096];
  size_t size = 0;
  u_int32_t entries, entry_size;
  u_int32_t hhc, hhk, title, home;

  if (chm_resolve_object(cfd, "/#WINDOWS", &ui) != CHM_RESOLVE_SUCCESS)
    return;

  size = chm_retrieve_object(cfd, &ui, buffer, 0L, 8);

  if (size < 8)
    return;

  entries = get_dword(buffer);
  if (entries < 1)
    return;

  entry_size = get_dword(buffer + 4);
  size = chm_retrieve_object(cfd, &ui, buffer, 8L, entry_size);
  if (size < entry_size)
    return;

  hhc = get_dword(buffer + 0x60);
  hhk = get_dword(buffer + 0x64);
  home = get_dword(buffer + 0x68);
  title = get_dword(buffer + 0x14);

  if (chm_resolve_object(cfd, "/#STRINGS", &ui) != CHM_RESOLVE_SUCCESS)
    return;

  size = chm_retrieve_object(cfd, &ui, buffer, 0L, 4096);

  if (!size)
    return;

  if (chmfile->hhc == NULL && hhc)
    chmfile->hhc = g_strdup_printf("/%s", buffer + hhc);
  if (chmfile->hhk == NULL && hhk)
    chmfile->hhk = g_strdup_printf("/%s", buffer + hhk);
  if (chmfile->home == NULL && home)
    chmfile->home = g_strdup_printf("/%s", buffer + home);
  if (chmfile->title == NULL && title)
    chmfile->title = g_strdup((char *)buffer + title);
}
Ejemplo n.º 2
0
unsigned char *ChmDoc::GetData(const char *fileName, size_t *lenOut)
{
    ScopedMem<char> fileNameTmp;
    if (!str::StartsWith(fileName, "/")) {
        fileNameTmp.Set(str::Join("/", fileName));
        fileName = fileNameTmp;
    } else if (str::StartsWith(fileName, "///")) {
        fileName += 2;
    }

    struct chmUnitInfo info;
    int res = chm_resolve_object(chmHandle, fileName, &info);
    if (CHM_RESOLVE_SUCCESS != res)
        return NULL;
    size_t len = (size_t)info.length;
    if (len > 128 * 1024 * 1024) {
        // don't allow anything above 128 MB
        return NULL;
    }

    // +1 for 0 terminator for C string compatibility
    ScopedMem<unsigned char> data((unsigned char *)malloc(len + 1));
    if (!data)
        return NULL;
    if (!chm_retrieve_object(chmHandle, &info, data.Get(), 0, len))
        return NULL;
    data[len] = '\0';

    if (lenOut)
        *lenOut = len;
    return data.StealData();
}
Ejemplo n.º 3
0
static HRESULT WINAPI ITSProtocol_Read(IInternetProtocol *iface, void *pv,
        ULONG cb, ULONG *pcbRead)
{
    ITSProtocol *This = impl_from_IInternetProtocol(iface);

    TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);

    if(!This->chm_file)
        return INET_E_DATA_NOT_AVAILABLE;

    *pcbRead = chm_retrieve_object(This->chm_file, &This->chm_object, pv, This->offset, cb);
    This->offset += *pcbRead;

    return *pcbRead ? S_OK : S_FALSE;
}
Ejemplo n.º 4
0
/*
 * Class:     org_chm4j_ChmEntry
 * Method:    readContent
 * Signature: (Ljava/lang/String;Ljava/lang/String;)[B
 */
JNIEXPORT jbyteArray JNICALL Java_org_chm4j_ChmEntry_readContent
(JNIEnv *env, jobject jobj, jstring jfilename, jstring jpath) {

    // opens the file
    const char *filename = (*env)->GetStringUTFChars(env, jfilename, 0);
    struct chmFile* cFile =  chm_open(filename);
    (*env)->ReleaseStringUTFChars(env, jfilename, filename);
    if(cFile == NULL) {
        J_ThrowException(env, "java/io/IOException", "failed to open the file");
        return NULL;
    }

    // resolves entry
    struct chmUnitInfo cUnit;
    const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
    int res = chm_resolve_object(cFile, path, &cUnit);
    (*env)->ReleaseStringUTFChars(env, jpath, path);
    if(res != CHM_RESOLVE_SUCCESS) {
        // close the file
        chm_close(cFile);
        J_ThrowException(env, "java.io.IOException", "failed to resolve entry");
        return NULL;
    }

    // retrieves entry content
    unsigned char* buf = (unsigned char*) malloc(sizeof(unsigned char) * cUnit.length);
    if(buf == NULL) {
        // close the file
        chm_close(cFile);
        J_ThrowException(env, "java.io.IOException", "failed to allocate buffer");
        return NULL;
    }
    jlong nbRead = (jlong) chm_retrieve_object(cFile, &cUnit, buf, 0, cUnit.length);

    // close the file
    chm_close(cFile);

    // creates and fills java byte array
    jbyteArray data = (*env)->NewByteArray(env, nbRead);
    if(nbRead > 0) {
        (*env)->SetByteArrayRegion(env, data, 0, nbRead, buf);
    }
    free(buf);

    return data;
}
Ejemplo n.º 5
0
static HRESULT WINAPI ITSS_IStream_Read(
        IStream* iface,
        void* pv,
        ULONG cb,
        ULONG* pcbRead)
{
    IStream_Impl *This = impl_from_IStream(iface);
    ULONG count;

    TRACE("%p %p %u %p\n", This, pv, cb, pcbRead);

    count = chm_retrieve_object(This->stg->chmfile, 
                          &This->ui, pv, This->addr, cb);
    This->addr += count;
    if( pcbRead )
        *pcbRead = count;

    return count ? S_OK : S_FALSE;
}
Ejemplo n.º 6
0
unsigned char *ChmDoc::GetData(const char *fileName, size_t *lenOut)
{
    ScopedMem<char> fileNameTmp;
    if (!str::StartsWith(fileName, "/")) {
        fileNameTmp.Set(str::Join("/", fileName));
        fileName = fileNameTmp;
    } else if (str::StartsWith(fileName, "///")) {
        fileName += 2;
    }

    struct chmUnitInfo info;
    int res = chm_resolve_object(chmHandle, fileName, &info);
    if (CHM_RESOLVE_SUCCESS != res && str::FindChar(fileName, '\\')) {
        // Microsoft's HTML Help CHM viewer tolerates backslashes in URLs
        fileNameTmp.SetCopy(fileName);
        str::TransChars(fileNameTmp, "\\", "/");
        fileName = fileNameTmp;
        res = chm_resolve_object(chmHandle, fileName, &info);
    }
    if (CHM_RESOLVE_SUCCESS != res)
        return nullptr;
    size_t len = (size_t)info.length;
    if (len > 128 * 1024 * 1024) {
        // don't allow anything above 128 MB
        return nullptr;
    }

    // +1 for 0 terminator for C string compatibility
    ScopedMem<unsigned char> data((unsigned char *)malloc(len + 1));
    if (!data)
        return nullptr;
    if (!chm_retrieve_object(chmHandle, &info, data.Get(), 0, len))
        return nullptr;
    data[len] = '\0';

    if (lenOut)
        *lenOut = len;
    return data.StealData();
}
Ejemplo n.º 7
0
static int savetofile(struct chmFile *c, struct chmUnitInfo *ui, long extractwithoutpath)
{
    LONGINT64 length=0;
    char *outbuf=NULL;
    FILE *f;
    char fullpath[CHM_MAX_PATHLEN*2+1];
    char target[CHM_MAX_PATHLEN*2+1];
    wchar_t temp[CHM_MAX_PATHLEN+1];
#ifdef UNIX
    size_t pathlen;
#endif

    if (ui->length)
    {
        outbuf = (char *)malloc((unsigned int)ui->length);
        if (!outbuf)
            return -1;
        length = chm_retrieve_object(c, ui, outbuf, 0, ui->length);
        if (length==0)
        {
            if (outbuf) free(outbuf);
            return -1;
        }
    }
#ifndef UNIX
    GetCurrentDirectory(sizeof(fullpath)-1,fullpath);
    while ((p = strstr(fullpath,"\\")) != NULL)
        *p = '/';
    if (fullpath[strlen(fullpath)-1] != '/')
        strcat(fullpath,"/");
#else
    getcwd(fullpath, sizeof(fullpath)-1);
    pathlen = strlen(fullpath);
    if (pathlen == 0)
        return -1;	/* impossible but... defensive programming */
    if (fullpath[pathlen - 1] != '/')
    {
        if (pathlen == PATH_MAX)
            return -1;
        else
            fullpath[pathlen] = '/';
        fullpath[pathlen+1] = 0;
    }
#endif
    decode_UTF8(temp,ui->path);
#ifndef UNIX
    WideCharToMultiByte(CP_ACP,0,temp,-1,target,sizeof(target),NULL,NULL);
#else
    wcstombs(target, temp, sizeof(target));
#endif
    ReplaceIllegalChars(target);
    strcat(fullpath,extractwithoutpath?pointtoname(target):(target[0]=='/'?target+1:target));
    if (!extractwithoutpath)
        if (!makedir(fullpath))
        {
            if (outbuf) free(outbuf);
            return -1;
        }
    if (fullpath[strlen(fullpath)-1]!='/')
    {
        f = fopen(fullpath, "wb");
        if (!f)
        {
            printf(" Error: Couldn't open %s\n", fullpath);
            return -1;
        }
        if (length)
            fwrite(outbuf, 1, length, f);
        fclose(f);
    }
    if (outbuf) free(outbuf);
    return 0;
}
Ejemplo n.º 8
0
/*
 * callback function for enumerate API
 */
int _extract_callback(struct chmFile *h,
              struct chmUnitInfo *ui,
              void *context)
{
    LONGUINT64 ui_path_len;
    char buffer[32768];
    struct extract_context *ctx = (struct extract_context *)context;
    char *i;

    if (ui->path[0] != '/')
        return CHM_ENUMERATOR_CONTINUE;

    /* quick hack for security hole mentioned by Sven Tantau */
    if (strstr(ui->path, "/../") != NULL)
    {
        /* fprintf(stderr, "Not extracting %s (dangerous path)\n", ui->path); */
        return CHM_ENUMERATOR_CONTINUE;
    }

    if (snprintf(buffer, sizeof(buffer), "%s%s", ctx->base_path, ui->path) > 1024)
        return CHM_ENUMERATOR_FAILURE;

    /* Get the length of the path */
    ui_path_len = strlen(ui->path)-1;

    /* Distinguish between files and dirs */
    if (ui->path[ui_path_len] != '/' )
    {
        FILE *fout;
        LONGINT64 len, remain=ui->length;
        LONGUINT64 offset = 0;

        printf("--> %s\n", ui->path);
        if ((fout = fopen(buffer, "wb")) == NULL)
	{
	    /* make sure that it isn't just a missing directory before we abort */ 
	    char newbuf[32768];
	    strcpy(newbuf, buffer);
	    i = strrchr(newbuf, '/');
	    *i = '\0';
	    rmkdir(newbuf);
	    if ((fout = fopen(buffer, "wb")) == NULL)
              return CHM_ENUMERATOR_FAILURE;
	}

        while (remain != 0)
        {
            len = chm_retrieve_object(h, ui, (unsigned char *)buffer, offset, 32768);
            if (len > 0)
            {
                fwrite(buffer, 1, (size_t)len, fout);
                offset += len;
                remain -= len;
            }
            else
            {
                fprintf(stderr, "incomplete file: %s\n", ui->path);
                break;
            }
        }

        fclose(fout);
    }
    else
    {
        if (rmkdir(buffer) == -1)
            return CHM_ENUMERATOR_FAILURE;
    }

    return CHM_ENUMERATOR_CONTINUE;
}
Ejemplo n.º 9
0
static void
chmfile_system_info(struct chmFile *cfd, ChmFile *chmfile)
{
  struct chmUnitInfo ui;
  unsigned char buffer[4096];

  int index = 0;
  unsigned char* cursor = NULL;
  u_int16_t value = 0;
  u_int32_t lcid = 0;
  size_t size = 0;

  if (chm_resolve_object(cfd, "/#SYSTEM", &ui) != CHM_RESOLVE_SUCCESS)
    return;

  size = chm_retrieve_object(cfd, &ui, buffer, 4L, 4096);

  if (!size)
    return;

  buffer[size - 1] = 0;

  for(;;) {
    // This condition won't hold if I process anything
    // except NUL-terminated strings!
    if(index > size - 1 - (long)sizeof(u_int16_t))
      break;

    cursor = buffer + index;
    value = UINT16ARRAY(cursor);
    g_debug("system value = %d", value);
    switch(value) {
    case 0:
      index += 2;
      cursor = buffer + index;

      chmfile->hhc = g_strdup_printf("/%s", buffer + index + 2);
      g_debug("hhc %s", chmfile->hhc);

      break;
    case 1:
      index += 2;
      cursor = buffer + index;

      chmfile->hhk = g_strdup_printf("/%s", buffer + index + 2);
      g_debug("hhk %s", chmfile->hhk);

      break;
    case 2:
      index += 2;
      cursor = buffer + index;

      chmfile->home = g_strdup_printf("/%s", buffer + index + 2);
      g_debug("home %s", chmfile->home);

      break;
    case 3:
      index += 2;
      cursor = buffer + index;

      chmfile->title = g_strdup((char *)buffer + index + 2);
      g_debug("title %s", chmfile->title);

      break;
    case 4: // LCID stuff
      index += 2;
      cursor = buffer + index;

      lcid = UINT32ARRAY(buffer + index + 2);
      g_debug("lcid %x", lcid);
      chmfile->encoding = get_encoding_by_lcid(lcid);
      break;

    case 6:
      index += 2;
      cursor = buffer + index;

      if(!chmfile->hhc) {
        char *hhc, *hhk;

        hhc = g_strdup_printf("/%s.hhc", buffer + index + 2);
        hhk = g_strdup_printf("/%s.hhk", buffer + index + 2);

        if (chm_resolve_object(cfd, hhc, &ui) == CHM_RESOLVE_SUCCESS)
          chmfile->hhc = hhc;

        if (chm_resolve_object(cfd, hhk, &ui) == CHM_RESOLVE_SUCCESS)
          chmfile->hhk = hhk;
      }

      break;
    case 16:
      index += 2;
      cursor = buffer + index;

      g_debug("font %s", buffer + index + 2);
      break;

    default:
      index += 2;
      cursor = buffer + index;
    }

    value = UINT16ARRAY(cursor);
    index += value + 2;
  }
}
Ejemplo n.º 10
0
/*
 * callback function for enumerate API
 */
static int
_extract_callback(struct chmFile *h, struct chmUnitInfo *ui, void *context)
{
  gchar* fname = NULL;
  char buffer[32768];
  struct extract_context *ctx = (struct extract_context *)context;
  char *i;

  if (ui->path[0] != '/') {
    return CHM_ENUMERATOR_CONTINUE;
  }

  g_debug("ui->path = %s", ui->path);

  fname = g_build_filename(ctx->base_path, ui->path+1, NULL);

  if (ui->length != 0) {
    FILE *fout;
    LONGINT64 len, remain = ui->length;
    LONGUINT64 offset = 0;

    gchar *file_ext;

    file_ext = g_strrstr(g_path_get_basename(ui->path), ".");
    g_debug("file_ext = %s", file_ext);

    if ((fout = fopen(fname, "wb")) == NULL) {
      /* make sure that it isn't just a missing directory before we abort */
      char newbuf[32768];
      strcpy(newbuf, fname);
      i = rindex(newbuf, '/');
      *i = '\0';
      rmkdir(newbuf);

      if ((fout = fopen(fname, "wb")) == NULL) {
        g_message("CHM_ENUMERATOR_FAILURE fopen");
        return CHM_ENUMERATOR_FAILURE;
      }
    }

    while (remain != 0) {
      len = chm_retrieve_object(h, ui, (unsigned char *)buffer, offset, 32768);
      if (len > 0) {
        if(fwrite(buffer, 1, (size_t)len, fout) != len) {
          g_message("CHM_ENUMERATOR_FAILURE fwrite");
          return CHM_ENUMERATOR_FAILURE;
        }
        offset += len;
        remain -= len;
      } else {
        break;
      }
    }

    fclose(fout);
    extract_post_file_write(fname);
  } else {
    if (rmkdir(fname) == -1) {
      g_message("CHM_ENUMERATOR_FAILURE rmkdir");
      return CHM_ENUMERATOR_FAILURE;
    }
  }
  g_free(fname);
  return CHM_ENUMERATOR_CONTINUE;
}
Ejemplo n.º 11
0
Archivo: chm.c Proyecto: db00/reader
/*
 * callback function for enumerate API
 */
static int _print_ui(struct chmFile *h,
		struct chmUnitInfo *ui,
		void *context)
{
	static char szBuf[128];
	memset(szBuf, 0, 128);
	if(ui->flags & CHM_ENUMERATE_NORMAL)
		strcpy(szBuf, "normal ");
	else if(ui->flags & CHM_ENUMERATE_SPECIAL)
		strcpy(szBuf, "special ");
	else if(ui->flags & CHM_ENUMERATE_META)
		strcpy(szBuf, "meta ");

	if(ui->flags & CHM_ENUMERATE_DIRS)
		strcat(szBuf, "dir");
	else if(ui->flags & CHM_ENUMERATE_FILES)
		strcat(szBuf, "file");

	struct chmfile * f = (struct chmfile*)context;
	if(f && f->filename && strlen(f->filename)) {
		if(strcmp(f->filename,ui->path)==0) {
			//printf("resolving %s\n", (char*)f->filename);
			if (CHM_RESOLVE_SUCCESS == chm_resolve_object(h, 
						f->filename,
						ui))
			{
				f->data = malloc(ui->length+1);
				memset(f->data ,0,ui->length+1);
				/*
				   printf("    object: <%d, %lu, %lu>\n",
				   ui->space,
				   (unsigned long)ui->start,
				   (unsigned long)ui->length);
				   */

				chm_retrieve_object(h, ui, (unsigned char*)f->data, 0, ui->length);
				f->len = ui->length+1;
				return CHM_ENUMERATOR_SUCCESS;
			}
		}
	}else{
		char out[1024];
		memset(out,0,sizeof(1024));
		sprintf(out,"   %1d %8d %8d   %s\t\t%s\n",
				(int)ui->space,
				(int)ui->start,
				(int)ui->length,
				szBuf,
				ui->path);
		if(f->data==NULL){
			f->data = malloc(strlen(out)+1);
			memset(f->data,0,strlen(out)+1);
			f->len = strlen(out)+1;
		}else{
			f->data = realloc(f->data,f->len+strlen(out));
			f->len += strlen(out);
		}
		//sprintf(f->data+strlen(f->data),"%s",out);
		strcat(f->data,out);
	}
	return CHM_ENUMERATOR_CONTINUE;
}
Ejemplo n.º 12
0
bool chm_read(chm_t* chm, FILE* fd) {
    if (fseek(fd, 0, SEEK_SET) != 0)
        return false;
    
    unsigned char      sbuffer[256];
    unsigned int       sremain;
    unsigned char      *sbufpos;
    chm_unitinfo       uiLzxc;
    chm_lzxc_ctldata   ctlData;
    
    memset(&uiLzxc, 0, sizeof(uiLzxc));
    memset(&ctlData, 0, sizeof(ctlData));

    chm->fd = fd;
    chm->lzx_state = NULL;
    chm->cache_blocks = NULL;
    chm->cache_block_indices = NULL;
    chm->cache_num_blocks = 0;
    
    /* read and verify header */
    sremain = CHM_ITSF_V3_LEN;
    sbufpos = sbuffer;
    if (_chm_fetch_bytes(chm, sbuffer, (uqword)0, sremain) != sremain    ||
        !_unmarshal_itsf_header(&sbufpos, &sremain, &chm->itsf)) {
        return false;
    }
    
    /* stash important values from header */
    chm->dir_offset  = chm->itsf.dir_offset;
    chm->dir_len     = chm->itsf.dir_len;
    chm->data_offset = chm->itsf.data_offset;
    
    /* now, read and verify the directory header chunk */
    sremain = CHM_ITSP_V1_LEN;
    sbufpos = sbuffer;
    if (_chm_fetch_bytes(chm, sbuffer,
                         (uqword)chm->itsf.dir_offset, sremain) != sremain       ||
        !_unmarshal_itsp_header(&sbufpos, &sremain, &chm->itsp)) {
        return false;
    }
    
    /* grab essential information from ITSP header */
    chm->dir_offset += chm->itsp.header_len;
    chm->dir_len    -= chm->itsp.header_len;
    chm->index_root  = chm->itsp.index_root;
    chm->index_head  = chm->itsp.index_head;
    chm->block_len   = chm->itsp.block_len;
    
    /* if the index root is -1, this means we don't have any PMGI blocks.
     * as a result, we must use the sole PMGL block as the index root
     */
    if (chm->index_root <= -1)
        chm->index_root = chm->index_head;
    
    /* By default, compression is enabled. */
    chm->compression_enabled = 1;
    
    /* prefetch most commonly needed unit infos */
    if (CHM_RESOLVE_SUCCESS != chm_resolve_object(chm,
                                                  _CHMU_RESET_TABLE,
                                                  &chm->rt_unit)    ||
        chm->rt_unit.space == CHM_COMPRESSED                        ||
        CHM_RESOLVE_SUCCESS != chm_resolve_object(chm,
                                                  _CHMU_CONTENT,
                                                  &chm->cn_unit)    ||
        chm->cn_unit.space == CHM_COMPRESSED                        ||
        CHM_RESOLVE_SUCCESS != chm_resolve_object(chm,
                                                  _CHMU_LZXC_CONTROLDATA,
                                                  &uiLzxc)                ||
        uiLzxc.space == CHM_COMPRESSED)
    {
        chm->compression_enabled = 0;
    }
    
    /* read reset table info */
    if (chm->compression_enabled)
    {
        sremain = CHM_LZXC_RESETTABLE_V1_LEN;
        sbufpos = sbuffer;
        if (chm_retrieve_object(chm, &chm->rt_unit, sbuffer,
                                0, sremain) != sremain                        ||
            !_unmarshal_lzxc_reset_table(&sbufpos, &sremain,
                                         &chm->reset_table))
        {
            chm->compression_enabled = 0;
        }
    }
    
    /* read control data */
    if (chm->compression_enabled)
    {
        sremain = (unsigned int)uiLzxc.length;
        if (uiLzxc.length > sizeof(sbuffer))
        {
            return false;
        }
        
        sbufpos = sbuffer;
        if (chm_retrieve_object(chm, &uiLzxc, sbuffer,
                                0, sremain) != sremain                       ||
            !_unmarshal_lzxc_control_data(&sbufpos, &sremain,
                                          &ctlData))
        {
            chm->compression_enabled = 0;
        }
        
        chm->window_size = ctlData.windowSize;
        chm->reset_interval = ctlData.resetInterval;
        
        chm->reset_blkcount = chm->reset_interval    /
        (chm->window_size / 2) *
        ctlData.windowsPerReset;
    }
    
    /* initialize cache */
    chm_set_param(chm, CHM_PARAM_MAX_BLOCKS_CACHED,
                  CHM_MAX_BLOCKS_CACHED);
    
    return true;
}