Example #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);
}
Example #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();
}
Example #3
0
static HRESULT WINAPI ITSS_IStorageImpl_OpenStream(
    IStorage* iface,
    LPCOLESTR pwcsName,
    void* reserved1,
    DWORD grfMode,
    DWORD reserved2,
    IStream** ppstm)
{
    ITSS_IStorageImpl *This = impl_from_IStorage(iface);
    IStream_Impl *stm;
    DWORD len;
    struct chmUnitInfo ui;
    int r;
    WCHAR *path, *p;

    TRACE("%p %s %p %u %u %p\n", This, debugstr_w(pwcsName),
          reserved1, grfMode, reserved2, ppstm );

    len = strlenW( This->dir ) + strlenW( pwcsName ) + 1;
    path = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
    strcpyW( path, This->dir );

    if( pwcsName[0] == '/' || pwcsName[0] == '\\' )
    {
        p = &path[strlenW( path ) - 1];
        while( ( path <= p ) && ( *p == '/' ) )
            *p-- = 0;
    }
    strcatW( path, pwcsName );

    for(p=path; *p; p++) {
        if(*p == '\\')
            *p = '/';
    }

    if(*--p == '/')
        *p = 0;

    TRACE("Resolving %s\n", debugstr_w(path));

    r = chm_resolve_object(This->chmfile, path, &ui);
    HeapFree( GetProcessHeap(), 0, path );

    if( r != CHM_RESOLVE_SUCCESS ) {
        WARN("Could not resolve object\n");
        return STG_E_FILENOTFOUND;
    }

    stm = ITSS_create_stream( This, &ui );
    if( !stm )
        return E_FAIL;

    *ppstm = &stm->IStream_iface;

    return S_OK;
}
Example #4
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();
}
Example #5
0
bool ChmDoc::HasData(const char* fileName) {
    if (!fileName)
        return nullptr;

    AutoFree tmpName;
    if (!str::StartsWith(fileName, "/")) {
        tmpName.Set(str::Join("/", fileName));
        fileName = tmpName;
    } else if (str::StartsWith(fileName, "///"))
        fileName += 2;

    struct chmUnitInfo info;
    return chm_resolve_object(chmHandle, fileName, &info) == CHM_RESOLVE_SUCCESS;
}
Example #6
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;
}
Example #7
0
static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
        IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
        DWORD grfPI, HANDLE_PTR dwReserved)
{
    ITSProtocol *This = impl_from_IInternetProtocol(iface);
    BINDINFO bindinfo;
    DWORD bindf = 0, len;
    LPWSTR file_name, mime, object_name, p;
    LPCWSTR ptr;
    struct chmFile *chm_file;
    struct chmUnitInfo chm_object;
    int res;
    HRESULT hres;

    static const WCHAR separator[] = {':',':',0};

    TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
            pOIBindInfo, grfPI, dwReserved);

    ptr = skip_schema(szUrl);
    if(!ptr)
        return INET_E_USE_DEFAULT_PROTOCOLHANDLER;

    memset(&bindinfo, 0, sizeof(bindinfo));
    bindinfo.cbSize = sizeof(BINDINFO);
    hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
    if(FAILED(hres)) {
        WARN("GetBindInfo failed: %08x\n", hres);
        return hres;
    }

    ReleaseBindInfo(&bindinfo);

    len = strlenW(ptr)+3;
    file_name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
    memcpy(file_name, ptr, len*sizeof(WCHAR));
    hres = UrlUnescapeW(file_name, NULL, &len, URL_UNESCAPE_INPLACE);
    if(FAILED(hres)) {
        WARN("UrlUnescape failed: %08x\n", hres);
        HeapFree(GetProcessHeap(), 0, file_name);
        return hres;
    }

    p = strstrW(file_name, separator);
    if(!p) {
        WARN("invalid url\n");
        HeapFree(GetProcessHeap(), 0, file_name);
        return report_result(pOIProtSink, STG_E_FILENOTFOUND);
    }

    *p = 0;
    chm_file = chm_openW(file_name);
    if(!chm_file) {
        WARN("Could not open chm file\n");
        HeapFree(GetProcessHeap(), 0, file_name);
        return report_result(pOIProtSink, STG_E_FILENOTFOUND);
    }

    object_name = p+2;
    len = strlenW(object_name);

    if(*object_name != '/' && *object_name != '\\') {
        memmove(object_name+1, object_name, (len+1)*sizeof(WCHAR));
        *object_name = '/';
        len++;
    }

    if(object_name[len-1] == '/')
        object_name[--len] = 0;

    for(p=object_name; *p; p++) {
        if(*p == '\\')
            *p = '/';
    }

    remove_dot_segments(object_name);

    TRACE("Resolving %s\n", debugstr_w(object_name));

    memset(&chm_object, 0, sizeof(chm_object));
    res = chm_resolve_object(chm_file, object_name, &chm_object);
    if(res != CHM_RESOLVE_SUCCESS) {
        WARN("Could not resolve chm object\n");
        HeapFree(GetProcessHeap(), 0, file_name);
        chm_close(chm_file);
        return report_result(pOIProtSink, STG_E_FILENOTFOUND);
    }

    IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST,
                                         strrchrW(object_name, '/')+1);

    /* FIXME: Native doesn't use FindMimeFromData */
    hres = FindMimeFromData(NULL, object_name, NULL, 0, NULL, 0, &mime, 0);
    HeapFree(GetProcessHeap(), 0, file_name);
    if(SUCCEEDED(hres)) {
        IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
        CoTaskMemFree(mime);
    }

    release_chm(This); /* Native leaks handle here */
    This->chm_file = chm_file;
    This->chm_object = chm_object;

    hres = IInternetProtocolSink_ReportData(pOIProtSink,
            BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE,
            chm_object.length, chm_object.length);
    if(FAILED(hres)) {
        WARN("ReportData failed: %08x\n", hres);
        release_chm(This);
        return report_result(pOIProtSink, hres);
    }

    hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);

    return report_result(pOIProtSink, hres);
}
Example #8
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;
  }
}
Example #9
0
File: chm.c Project: 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;
}
Example #10
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;
}