Пример #1
0
  //--------------------------------------------------------------------------//
  //--------------------------------------------------------------------------//
  Font::CacheEntry* Font::find_cached(const String &msg){
    Hash_t hash =gen_hash( (const byte*)&m_position, sizeof(m_position) );
    hash        =gen_hash(msg, hash);

    for(Cache::iterator it=m_cache.begin(); it!=m_cache.end();++it){
      if( it->hash == hash )
        return &*it;
    }
    return NULL;
  }
Пример #2
0
 //--------------------------------------------------------------------------//
 //--------------------------------------------------------------------------//
 Font::CacheEntry* Font::cache(const String &msg){
   m_cache.push_back( CacheEntry() );
   CacheEntry &ce=m_cache.back();
   ce.hash         =gen_hash( (const byte*)&m_position, sizeof(m_position) );
   ce.hash         =gen_hash(msg, ce.hash);
   ce.lastUsed     =m_counter;
   ce.vertCount    =msg.length()*4;
   ce.verts        =new Vertex[ce.vertCount];
   m_cacheUpdated  =false;
   return &ce;
 }
Пример #3
0
int tsht_remove(TSHTable *ht, char *str, void **datum) {
	unsigned long hash;
	H_Entry *p, *q;
	int found = 0;

	pthread_mutex_lock(&(ht->lock));
	hash = gen_hash(str, ht->size);
	p = ht->table[hash].first;
	q = NULL;
	while (p != NULL) {
		if (strcmp(str, p->key) == 0) {
			found++;
			break;
		}
		q = p;
		p = q->next;
	}
	if (found) {
		*datum = p->datum;
		if (q == NULL)
			ht->table[hash].first = p->next;
		else
			q->next = p->next;
		ht->nelements--;
		mem_free((void *)p->key);
		mem_free((void *)p);
	}
	pthread_mutex_unlock(&(ht->lock));
	return found;
}
Пример #4
0
/* 
 * This function tries to find a running server for the proxy <px> following
 * the URL parameter hash method. It looks for a specific parameter in the
 * URL and hashes it to compute the server ID. This is useful to optimize
 * performance by avoiding bounces between servers in contexts where sessions
 * are shared but cookies are not usable. If the parameter is not found, NULL
 * is returned. If any server is found, it will be returned. If no valid server
 * is found, NULL is returned.
 */
struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
{
	unsigned int hash = 0;
	const char *start, *end;
	const char *p;
	const char *params;
	int plen;

	/* when tot_weight is 0 then so is srv_count */
	if (px->lbprm.tot_weight == 0)
		return NULL;

	if ((p = memchr(uri, '?', uri_len)) == NULL)
		return NULL;

	p++;

	uri_len -= (p - uri);
	plen = px->url_param_len;
	params = p;

	while (uri_len > plen) {
		/* Look for the parameter name followed by an equal symbol */
		if (params[plen] == '=') {
			if (memcmp(params, px->url_param_name, plen) == 0) {
				/* OK, we have the parameter here at <params>, and
				 * the value after the equal sign, at <p>
				 * skip the equal symbol
				 */
				p += plen + 1;
				start = end = p;
				uri_len -= plen + 1;

				while (uri_len && *end != '&') {
					uri_len--;
					end++;
				}
				hash = gen_hash(px, start, (end - start));

				if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
					hash = full_hash(hash);

				if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
					return chash_get_server_hash(px, hash);
				else
					return map_get_server_hash(px, hash);
			}
		}
		/* skip to next parameter */
		p = memchr(params, '&', uri_len);
		if (!p)
			return NULL;
		p++;
		uri_len -= (p - params);
		params = p;
	}
	return NULL;
}
Пример #5
0
void scanDataFileBefore(HTree* tree, int bucket, const char* path, time_t before)
{
    MFile *f = open_mfile(path);
    if (f == NULL) return;
    
    fprintf(stderr, "scan datafile %s before %ld\n", path, before);
    char *p = f->addr, *end = f->addr + f->size;
    int broken = 0;
    while (p < end) {
        DataRecord *r = decode_record(p, end-p, false);
        if (r != NULL) {
            if (r->tstamp >= before ){
                break;
            }
            uint32_t pos = p - f->addr;
            p += record_length(r); 
            r = decompress_record(r);
            uint16_t hash = gen_hash(r->value, r->vsz);
            if (r->version > 0){
                uint16_t hash = gen_hash(r->value, r->vsz);
                ht_add2(tree, r->key, r->ksz, pos | bucket, hash, r->version);            
            }else{
                ht_remove2(tree, r->key, r->ksz);
            }
            free_record(r);
        } else {
            broken ++;
            if (broken > 40960) { // 10M
                fprintf(stderr, "unexpected broken data in %s at %ld\n", path, p - f->addr - broken * PADDING);
                break;
            }
            p += PADDING;
        }
    }

    close_mfile(f);
}
Пример #6
0
void *tsht_lookup(TSHTable *ht, char *str) {
	unsigned long hash;
	H_Entry *p;

	pthread_mutex_lock(&(ht->lock));
	hash = gen_hash(str, ht->size);
	p = ht->table[hash].first;
	while (p != NULL) {
		if (strcmp(str, p->key) == 0) {
			pthread_mutex_unlock(&(ht->lock));
			return p->datum;
		}
		p = p->next;
	}
	pthread_mutex_unlock(&(ht->lock));
	return NULL;
}
Пример #7
0
char *hs_get(HStore *store, char *key, int *vlen, uint32_t *flag)
{
    if (!key || !store) return NULL;

    if (key[0] == '@'){
        char *r = hs_list(store, key+1);
        if (r) *vlen = strlen(r);
        *flag = 0;
        return r;
    }
    
    bool info = false;
    if (key[0] == '?'){
        info = true;
        key ++;
    }
    int index = get_index(store, key);
    DataRecord *r = bc_get(store->bitcasks[index], key);
    if (r == NULL){
        return NULL;
    }
    
    char *res = NULL;
    if (info){
        res = malloc(256);
        if (!res) {
            free_record(r);
            return NULL;
        }
        uint16_t hash = 0;
        if (r->version > 0){
            hash = gen_hash(r->value, r->vsz);
        }
        *vlen = snprintf(res, 255, "%d %u %u %u %u", r->version, 
            hash, r->flag, r->vsz, r->tstamp);
        *flag = 0;
    }else if (r->version > 0){
        res = record_value(r);
        r->value = NULL;
        *vlen = r->vsz;
        *flag = r->flag;
    }
    free_record(r);
    return res;
}
Пример #8
0
/* RDP Cookie HASH.  */
struct server *get_server_rch(struct session *s)
{
	unsigned int hash = 0;
	struct proxy    *px   = s->be;
	unsigned long    len;
	int              ret;
	struct sample    smp;
	int rewind;

	/* tot_weight appears to mean srv_count */
	if (px->lbprm.tot_weight == 0)
		return NULL;

	memset(&smp, 0, sizeof(smp));

	b_rew(s->req.buf, rewind = s->req.buf->o);

	ret = fetch_rdp_cookie_name(s, &smp, px->hh_name, px->hh_len);
	len = smp.data.str.len;

	b_adv(s->req.buf, rewind);

	if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || len == 0)
		return NULL;

	/* note: we won't hash if there's only one server left */
	if (px->lbprm.tot_used == 1)
		goto hash_done;

	/* Found a the hh_name in the headers.
	 * we will compute the hash based on this value ctx.val.
	 */
	hash = gen_hash(px, smp.data.str.str, len);

	if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
		hash = full_hash(hash);
 hash_done:
	if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
		return chash_get_server_hash(px, hash);
	else
		return map_get_server_hash(px, hash);
}
Пример #9
0
/*
 * This function tries to find a running server for the proxy <px> following
 * the URI hash method. In order to optimize cache hits, the hash computation
 * ends at the question mark. Depending on the number of active/backup servers,
 * it will either look for active servers, or for backup servers.
 * If any server is found, it will be returned. If no valid server is found,
 * NULL is returned.
 *
 * This code was contributed by Guillaume Dallaire, who also selected this hash
 * algorithm out of a tens because it gave him the best results.
 *
 */
struct server *get_server_uh(struct proxy *px, char *uri, int uri_len)
{
	unsigned int hash = 0;
	int c;
	int slashes = 0;
	const char *start, *end;

	if (px->lbprm.tot_weight == 0)
		return NULL;

	/* note: we won't hash if there's only one server left */
	if (px->lbprm.tot_used == 1)
		goto hash_done;

	if (px->uri_len_limit)
		uri_len = MIN(uri_len, px->uri_len_limit);

	start = end = uri;
	while (uri_len--) {
		c = *end;
		if (c == '/') {
			slashes++;
			if (slashes == px->uri_dirs_depth1) /* depth+1 */
				break;
		}
		else if (c == '?' && !px->uri_whole)
			break;
		end++;
	}

	hash = gen_hash(px, start, (end - start));

	if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
		hash = full_hash(hash);
 hash_done:
	if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
		return chash_get_server_hash(px, hash);
	else
		return map_get_server_hash(px, hash);
}
Пример #10
0
int tsht_insert(TSHTable *ht, char *str, void *datum, void **old) {
	unsigned long hash;
	H_Entry *p;

	pthread_mutex_lock(&(ht->lock));
	hash = gen_hash(str, ht->size);
	p = ht->table[hash].first;
	while (p != NULL) {
		if (strcmp(str, p->key) == 0) {
			*old = p->datum;
		 p->datum = datum;
			pthread_mutex_unlock(&(ht->lock));
		 return 1;
		}
		p = p->next;
	}
	p = (H_Entry *)mem_alloc(sizeof(H_Entry));
	if (p != NULL) {
		char *s = strdup(str);
		if (s == NULL) {
			mem_free((void *)p);
			pthread_mutex_unlock(&(ht->lock));
			return 0;
		}
		p->key = s;
		p->datum = datum;
		p->next = ht->table[hash].first;
		ht->table[hash].first = p;
		ht->nelements++;
		pthread_mutex_unlock(&(ht->lock));
		*old = NULL;
		return 1;
	}
	pthread_mutex_unlock(&(ht->lock));
	return 0;
}
Пример #11
0
void miner_gen_nonce2_work(struct mm_work *mw, uint32_t nonce2, struct work *work)
{
	uint8_t merkle_root[32], merkle_sha[64];
	uint32_t *data32, *swap32, tmp32;
	int i;

	tmp32 = bswap_32(nonce2);
	memcpy(mw->coinbase + mw->nonce2_offset, (uint8_t *)(&tmp32), sizeof(uint32_t));
	work->nonce2 = nonce2;

	gen_hash(mw->coinbase, merkle_root, mw->coinbase_len);
	memcpy(merkle_sha, merkle_root, 32);
	for (i = 0; i < mw->nmerkles; i++) {
		memcpy(merkle_sha + 32, mw->merkles[i], 32);
		gen_hash(merkle_sha, merkle_root, 64);
		memcpy(merkle_sha, merkle_root, 32);
	}
	data32 = (uint32_t *)merkle_sha;
	swap32 = (uint32_t *)merkle_root;
	flip32(swap32, data32);

	memcpy(mw->header + mw->merkle_offset, merkle_root, 32);

	debug32("D: Work nonce2: %08x\n", work->nonce2);
	calc_midstate(mw, work);

	uint8_t work_t[44];
#ifdef HW_PRE_CALC
	uint8_t work_t[] = {
		0x05, 0x4e, 0x53, 0xc3, 0xc4, 0xd4, 0xba, 0x3e, 0x65, 0x40, 0x99, 0x4f, 0x06, 0x67, 0x91, 0x31,
		0xa7, 0x2d, 0x66, 0xaa, 0x68, 0x4f, 0x0e, 0xdb, 0xc3, 0x6d, 0x95, 0x8a, 0x46, 0x6e, 0x4d, 0xb2,
		0x1c, 0x26, 0x52, 0xfb, 0x52, 0xa0, 0x26, 0xf4, 0x19, 0x06, 0x12, 0x42};
#endif

	memcpy(work_t, work->data, 44);
	rev(work_t, 32);
	rev(work_t + 32, 12);
	memcpy(work->data, work_t, 44);

#ifdef HW_PRE_CALC
	calc_prepare(work, work_t);
	memcpy((uint8_t *)(&tmp32), work->a1, 4);
	debug32("%08x,", tmp32);
	memcpy((uint8_t *)(&tmp32), work->a0, 4);
	debug32("%08x,", tmp32);
	memcpy((uint8_t *)(&tmp32), work->e2, 4);
	debug32("%08x,", tmp32);
	memcpy((uint8_t *)(&tmp32), work->e1, 4);
	debug32("%08x,", tmp32);
	memcpy((uint8_t *)(&tmp32), work->e0, 4);
	debug32("%08x,", tmp32);
	memcpy((uint8_t *)(&tmp32), work->a2, 4);
	debug32("%08x", tmp32);
	debug32("\n");
#endif

	calc_prepare1(work, work->data);
	memcpy((uint8_t *)(&tmp32), work->a1, 4);
	memcpy((uint8_t *)(&tmp32), work->a0, 4);
	memcpy((uint8_t *)(&tmp32), work->e2, 4);
	memcpy((uint8_t *)(&tmp32), work->e1, 4);
	memcpy((uint8_t *)(&tmp32), work->e0, 4);
	memcpy((uint8_t *)(&tmp32), work->a2, 4);
}
Пример #12
0
/*
 * This function tries to find a running server for the proxy <px> following
 * the Header parameter hash method. It looks for a specific parameter in the
 * URL and hashes it to compute the server ID. This is useful to optimize
 * performance by avoiding bounces between servers in contexts where sessions
 * are shared but cookies are not usable. If the parameter is not found, NULL
 * is returned. If any server is found, it will be returned. If no valid server
 * is found, NULL is returned.
 */
struct server *get_server_hh(struct session *s)
{
	unsigned int hash = 0;
	struct http_txn *txn  = &s->txn;
	struct proxy    *px   = s->be;
	unsigned int     plen = px->hh_len;
	unsigned long    len;
	struct hdr_ctx   ctx;
	const char      *p;
	const char *start, *end;

	/* tot_weight appears to mean srv_count */
	if (px->lbprm.tot_weight == 0)
		return NULL;

	ctx.idx = 0;

	/* if the message is chunked, we skip the chunk size, but use the value as len */
	http_find_header2(px->hh_name, plen, b_ptr(s->req.buf, -http_hdr_rewind(&txn->req)), &txn->hdr_idx, &ctx);

	/* if the header is not found or empty, let's fallback to round robin */
	if (!ctx.idx || !ctx.vlen)
		return NULL;

	/* note: we won't hash if there's only one server left */
	if (px->lbprm.tot_used == 1)
		goto hash_done;

	/* Found a the hh_name in the headers.
	 * we will compute the hash based on this value ctx.val.
	 */
	len = ctx.vlen;
	p = (char *)ctx.line + ctx.val;
	if (!px->hh_match_domain) {
		hash = gen_hash(px, p, len);
	} else {
		int dohash = 0;
		p += len;
		/* special computation, use only main domain name, not tld/host
		 * going back from the end of string, start hashing at first
		 * dot stop at next.
		 * This is designed to work with the 'Host' header, and requires
		 * a special option to activate this.
		 */
		end = p;
		while (len) {
			if (dohash) {
				/* Rewind the pointer until the previous char
				 * is a dot, this will allow to set the start
				 * position of the domain. */
				if (*(p - 1) == '.')
					break;
			}
			else if (*p == '.') {
				/* The pointer is rewinded to the dot before the
				 * tld, we memorize the end of the domain and
				 * can enter the domain processing. */
				end = p;
				dohash = 1;
			}
			p--;
			len--;
		}
		start = p;
		hash = gen_hash(px, start, (end - start));
	}
	if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
		hash = full_hash(hash);
 hash_done:
	if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
		return chash_get_server_hash(px, hash);
	else
		return map_get_server_hash(px, hash);
}
Пример #13
0
/*
 * this does the same as the previous server_ph, but check the body contents
 */
struct server *get_server_ph_post(struct session *s)
{
	unsigned int hash = 0;
	struct http_txn *txn  = &s->txn;
	struct channel  *req  = &s->req;
	struct http_msg *msg  = &txn->req;
	struct proxy    *px   = s->be;
	unsigned int     plen = px->url_param_len;
	unsigned long    len  = http_body_bytes(msg);
	const char      *params = b_ptr(req->buf, -http_data_rewind(msg));
	const char      *p    = params;
	const char      *start, *end;

	if (len == 0)
		return NULL;

	if (px->lbprm.tot_weight == 0)
		return NULL;

	while (len > plen) {
		/* Look for the parameter name followed by an equal symbol */
		if (params[plen] == '=') {
			if (memcmp(params, px->url_param_name, plen) == 0) {
				/* OK, we have the parameter here at <params>, and
				 * the value after the equal sign, at <p>
				 * skip the equal symbol
				 */
				p += plen + 1;
				start = end = p;
				len -= plen + 1;

				while (len && *end != '&') {
					if (unlikely(!HTTP_IS_TOKEN(*p))) {
						/* if in a POST, body must be URI encoded or it's not a URI.
						 * Do not interpret any possible binary data as a parameter.
						 */
						if (likely(HTTP_IS_LWS(*p))) /* eol, uncertain uri len */
							break;
						return NULL;                 /* oh, no; this is not uri-encoded.
									      * This body does not contain parameters.
									      */
					}
					len--;
					end++;
					/* should we break if vlen exceeds limit? */
				}
				hash = gen_hash(px, start, (end - start));

				if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
					hash = full_hash(hash);

				if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
					return chash_get_server_hash(px, hash);
				else
					return map_get_server_hash(px, hash);
			}
		}
		/* skip to next parameter */
		p = memchr(params, '&', len);
		if (!p)
			return NULL;
		p++;
		len -= (p - params);
		params = p;
	}
	return NULL;
}
Пример #14
0
bool bc_set(Bitcask *bc, const char* key, char* value, int vlen, int flag, int version)
{
    if (version < 0 && vlen > 0 || vlen > MAX_RECORD_SIZE)
    {
        fprintf(stderr, "invalid set cmd \n");
        return false;
    }

    bool suc = false;
    pthread_mutex_lock(&bc->write_lock);

    int oldv = 0, ver = version;
    Item *it = ht_get(bc->tree, key);
    if (it != NULL)
    {
        oldv = it->ver;
    }

    if (version == 0 && oldv > 0)  // replace
    {
        ver = oldv + 1;
    }
    else if (version == 0 && oldv <= 0)    // add
    {
        ver = -oldv + 1;
    }
    else if (version < 0 && oldv <= 0)     // delete, not exist
    {
        goto SET_FAIL;
    }
    else if (version == -1)     // delete
    {
        ver = - abs(oldv) - 1;
    }
    else if (abs(version) <= abs(oldv))     // sync
    {
        goto SET_FAIL;
    }
    else     // sync
    {
        ver = version;
    }

    uint16_t hash = gen_hash(value, vlen);
    if (ver < 0) hash = 0;

    if (NULL != it && hash == it->hash)
    {
        DataRecord *r = bc_get(bc, key);
        if (r != NULL && r->flag == flag && vlen  == r->vsz
                && memcmp(value, r->value, vlen) == 0)
        {
            if (version != 0)
            {
                // update version
                if (it->pos & 0xff == bc->curr)
                {
                    ht_add(bc->curr_tree, key, it->pos, it->hash, ver);
                }
                ht_add(bc->tree, key, it->pos, it->hash, ver);
            }
            suc = true;
            free_record(r);
            goto SET_FAIL;
        }
        if (r != NULL) free_record(r);
    }

    int klen = strlen(key);
    DataRecord *r = (DataRecord*)malloc(sizeof(DataRecord) + klen);
    r->ksz = klen;
    memcpy(r->key, key, klen);
    r->vsz = vlen;
    r->value = value;
    r->free_value = false;
    r->flag = flag;
    r->version = ver;
    r->tstamp = time(NULL);

    int rlen;
    char *rbuf = encode_record(r, &rlen);
    if (rbuf == NULL || (rlen & 0xff) != 0)
    {
        fprintf(stderr, "encode_record() failed with %d\n", rlen);
        if (rbuf != NULL) free(rbuf);
        goto SET_FAIL;
    }

    pthread_mutex_lock(&bc->buffer_lock);
    // record maybe larger than buffer
    if (bc->wbuf_curr_pos + rlen > bc->wbuf_size)
    {
        pthread_mutex_unlock(&bc->buffer_lock);
        bc_flush(bc, 0, 0);
        pthread_mutex_lock(&bc->buffer_lock);

        while (rlen > bc->wbuf_size)
        {
            bc->wbuf_size *= 2;
            free(bc->write_buffer);
            bc->write_buffer = (char*)malloc(bc->wbuf_size);
        }
        if (bc->wbuf_start_pos + bc->wbuf_size > MAX_BUCKET_SIZE)
        {
            bc_rotate(bc);
        }
    }
    memcpy(bc->write_buffer + bc->wbuf_curr_pos, rbuf, rlen);
    int pos = (bc->wbuf_start_pos + bc->wbuf_curr_pos) | bc->curr;
    bc->wbuf_curr_pos += rlen;
    pthread_mutex_unlock(&bc->buffer_lock);

    ht_add(bc->curr_tree, key, pos, hash, ver);
    ht_add(bc->tree, key, pos, hash, ver);
    suc = true;
    free(rbuf);
    free_record(r);

SET_FAIL:
    pthread_mutex_unlock(&bc->write_lock);
    if (it != NULL) free(it);
    return suc;
}
Пример #15
0
/* DDS3.2.3: Authenticate */
int main(int argc, char *argv[])
{
	struct http_vars *vars;
	struct barcode_hash_entry *bcentry;
	struct barcode bc;
	char bchash[HASH_BITS+1];
	struct electorate *elecs, *i;
	PGconn *conn;
	int ppcode;

	/* Our own failure function */
	set_cgi_bailout();

	/* Can be called on slave as well as master */
	conn = connect_db_port("evacs", get_database_port());
	if (!conn) bailout("Could not open database connection\n");

	/* Copy barcode ascii code from POST arguments */
	vars = cgi_get_arguments();
	strncpy(bc.ascii, http_string(vars, "barcode"), sizeof(bc.ascii)-1);
	bc.ascii[sizeof(bc.ascii)-1] = '\0';
	http_free(vars);

	/* Extract data and checksum from ascii */
	if (!bar_decode_ascii(&bc))
		cgi_error_response(ERR_BARCODE_MISREAD);

	/* Hash the barcode to look up in the table */
	gen_hash(bchash, bc.data, sizeof(bc.data));

	bcentry = get_bhash_table(conn, bchash);
	if (!bcentry) {
		PQfinish(conn);
		fprintf(stderr, "Barcode `%s' not found\n", bc.ascii);
		cgi_error_response(ERR_BARCODE_AUTHENTICATION_FAILED);
	}

	/* DDS3.2.4: Check Unused */
	if (bcentry->used) {
		PQfinish(conn);
		fprintf(stderr, "Barcode `%s' already used\n", bc.ascii);
		cgi_error_response(ERR_BARCODE_USED);
	}

	ppcode = SQL_singleton_int(conn,"SELECT polling_place_code "
				   "FROM server_parameter;");
	if (ppcode < 0) {
		PQfinish(conn);
		cgi_error_response(ERR_SERVER_INTERNAL);
	}

	if (ppcode != bcentry->ppcode) {
		PQfinish(conn);
		cgi_error_response(ERR_BARCODE_PP_INCORRECT);
	}

	elecs = get_electorates(conn);
	for (i = elecs; i; i = i->next) {
		if (i->code == bcentry->ecode) {
			/* Found it! */
			vars = create_response(conn, i);
			free_electorates(elecs);
			PQfinish(conn);
			cgi_good_response(vars);
		}
	}

	/* Should never happen */
	free_electorates(elecs);
	PQfinish(conn);
	bailout("Barcode electorate %u not found\n", bcentry->ecode);
}
Пример #16
0
/* 封包索引目录提取函数 */
static int QLIE_pack_extract_directory(struct package *pkg,
											struct package_directory *pkg_dir)
{
	pack_tailer_t pack_tailer;
	hash_header_t *hash_header;
	my_hash_entry_t *my_index_buffer;
	BYTE buf[0x440];
	u32 key;
	BYTE *hash_index;
	unsigned int i;
	DWORD hash_index_length, index_buffer_length;
	int ret;
	int pack_ver, hash_ver;
	BYTE *p;

	if (pkg->pio->readvec(pkg, &pack_tailer, sizeof(pack_tailer), 0 - sizeof(pack_tailer), IO_SEEK_END))
		return -CUI_EREADVEC;

	if (!strncmp(pack_tailer.magic, "FilePackVer3.0", 16))
		pack_ver = 3;
	else if (!strncmp(pack_tailer.magic, "FilePackVer2.0", 16))
		pack_ver = 2;
	else if (!strncmp(pack_tailer.magic, "FilePackVer1.0", 16))
		pack_ver = 1;

	if (pack_ver == 3 || pack_ver == 2) {
		if (pkg->pio->readvec(pkg, buf, sizeof(buf), 0 - sizeof(buf), IO_SEEK_END))
			return -CUI_EREADVEC;

		if (pack_ver == 3) {
			key = gen_hash((WORD *)&buf[0x24], 256) & 0x0fffffff;
			decode((DWORD *)buf, 32, key);// 计算出校验和
		} else if (pack_ver == 2)
			decode((DWORD *)buf, 32, 0);// 计算出校验和
	}

	u32 hash_size = 0;
	if (pkg->lst) {
		if (pkg->pio->open(pkg->lst, IO_READONLY))
			return -CUI_EOPEN;

		if (pkg->pio->length_of(pkg->lst, &hash_size)) {
			pkg->pio->close(pkg->lst);
			return -CUI_ELEN;
		}

		hash_header = (hash_header_t *)malloc(hash_size * 2);
		if (!hash_header) {
			pkg->pio->close(pkg->lst);
			return -CUI_EMEM;
		}

		if (pkg->pio->read(pkg->lst, hash_header, hash_size)) {
			free(hash_header);
			pkg->pio->close(pkg->lst);
			return -CUI_EREAD;
		}
		memcpy((BYTE *)hash_header + hash_size, hash_header, hash_size);
		pkg->pio->close(pkg->lst);
	} else if (pack_ver != 1) {
		hash_size = *(u32 *)&buf[32];
		hash_header = (hash_header_t *)malloc(hash_size);
		if (!hash_header)
			return -CUI_EMEM;

		if (pkg->pio->seek(pkg, 0 - (sizeof(buf) + hash_size), IO_SEEK_END)) {
			free(hash_header);
			return -CUI_ESEEK;
		}

		if (pkg->pio->read(pkg, hash_header, hash_size)) {
			free(hash_header);
			return -CUI_EREAD;
		}
	}

	if (!hash_size)
		goto no_hash;

	if (!strncmp(hash_header->magic, "HashVer1.3", sizeof(hash_header->magic)))
		hash_ver = 13;
	else if (!strncmp(hash_header->magic, "HashVer1.2", sizeof(hash_header->magic)))
		hash_ver = 12;
	else {
		free(hash_header);
		return -CUI_EMATCH;
	}		

retry:
	decode((DWORD *)(hash_header + 1), hash_header->data_length, 0x428);
	ret = pack_decompress(&hash_index, &hash_index_length, (pack_compr_t *)(hash_header + 1), hash_header->data_length);
	if (ret) {
		if (pack_ver == 1 && !new_pack_ver1) {
			new_pack_ver1 = 1;
			memcpy(hash_header, (BYTE *)hash_header + hash_size, hash_size);
			goto retry;
		}
		free(hash_header);
		return ret;
	}

	index_buffer_length = sizeof(my_hash_entry_t) * hash_header->hash_index_entries;
	my_index_buffer = (my_hash_entry_t *)malloc(index_buffer_length);
	if (!my_index_buffer) {
		free(hash_index);
		free(hash_header);
		return -CUI_EMEM;
	}

	/* 这个表的具体作用不明 */
	p = hash_index;
	for (i = 0; i < hash_header->hash_index_entries; i++) {		
		u16 n = *(u16 *)p;

		p += 2;
		for (u16 j = 0; j < n; ++j) {
			u16 name_length;
			u32 offset_lo, offset_hi;
			
			name_length = *(u16 *)p;
			p += 2;

			strncpy(my_index_buffer[i].name, (char *)p, name_length);
			my_index_buffer[i].name[name_length] = 0;
			p += name_length;
			offset_lo = *(u32 *)p;
			p += 4;
			offset_hi = *(u32 *)p;
			p += 4;
			if (hash_ver == 13) {
				my_index_buffer[i].hash = *(u32 *)p;
				p += 4;
				my_index_buffer[i].index_entries_offset = (u64)(offset_lo) | (u64)(offset_hi) << 32;			
			}
			//printf("%s: hash %x @ %08x%08x\n", my_index_buffer[i].name, my_index_buffer[i].hash, offset_hi, offset_lo);
		}
	}
	free(hash_index);
	free(hash_header);

no_hash:
	if (pkg->pio->seek(pkg, pack_tailer.index_offset_lo, IO_SEEK_SET)) {
		free(my_index_buffer);
		return -CUI_ESEEK;
	}

	my_entry_t *index_buffer = (my_entry_t *)malloc(sizeof(my_entry_t) * pack_tailer.index_entries);
	if (!index_buffer) {
		free(my_index_buffer);
		return -CUI_EMEM;
	}

	for (i = 0; i < pack_tailer.index_entries; ++i) {	
		u16 name_length;
		BYTE dec;
		u32 offset_lo, offset_hi;

		if (pkg->pio->read(pkg, &name_length, sizeof(name_length)))
			break;

		if (pkg->pio->read(pkg, index_buffer[i].name, name_length))
			break;

		if (pack_ver == 3)
			dec = name_length + (key ^ 0x3e);
		else if (pack_ver == 2)
			dec = name_length + (0xc4 ^ 0x3e);
		else if (!new_pack_ver1)
			dec = name_length + (0xc4 ^ 0x3e);
		else
			dec = 0xc4 ^ 0x3e;

		for (unsigned int k = 0; k < name_length; ++k)
			index_buffer[i].name[k] ^= (((k + 1) ^ dec) + (k + 1));
		index_buffer[i].name[k] = 0;

		if (pkg->pio->read(pkg, &offset_lo, sizeof(offset_lo)))
			break;

		if (pkg->pio->read(pkg, &offset_hi, sizeof(offset_hi)))
			break;

		if (pkg->pio->read(pkg, &index_buffer[i].comprlen, sizeof(index_buffer[i].comprlen)))
			break;

		if (pkg->pio->read(pkg, &index_buffer[i].uncomprlen, sizeof(index_buffer[i].uncomprlen)))
			break;

		if (pkg->pio->read(pkg, &index_buffer[i].is_compressed, sizeof(index_buffer[i].is_compressed)))
			break;

		if (pkg->pio->read(pkg, &index_buffer[i].is_encoded, sizeof(index_buffer[i].is_encoded)))
			break;

		if (new_pack_ver1)
			index_buffer[i].hash = 0;
		else {
			if (pkg->pio->read(pkg, &index_buffer[i].hash, sizeof(index_buffer[i].hash)))
				break;
		}

		index_buffer[i].offset = (u64)offset_lo | ((u64)offset_hi << 32);
		if (pack_ver == 3)
			index_buffer[i].key = key;
		else if (pack_ver == 2 || pack_ver == 1)
			index_buffer[i].key = 0;
	//	printf("%s: hash %x %d / %d @ %08x%08x\n", index_buffer[i].name, index_buffer[i].hash, index_buffer[i].comprlen, 
	//		index_buffer[i].uncomprlen, offset_hi, offset_lo);
	}
	if (i != pack_tailer.index_entries) {
		free(index_buffer);
		return -CUI_EREAD;
	}

	pkg_dir->index_entries = pack_tailer.index_entries;
	pkg_dir->directory = index_buffer;
	pkg_dir->directory_length = sizeof(my_entry_t) * pack_tailer.index_entries;
	pkg_dir->index_entry_length = sizeof(my_entry_t);
	package_set_private(pkg, pack_ver);

	return 0;
}
Пример #17
0
/* 封包资源提取函数 */
static int QLIE_pack_extract_resource(struct package *pkg,
										   struct package_resource *pkg_res)
{
	BYTE *compr, *uncompr, **act_data;
	DWORD comprlen, uncomprlen, act_data_len;
	my_entry_t *my_entry;

	comprlen = pkg_res->raw_data_length;
	compr = (BYTE *)malloc(comprlen);
	if (!compr)
		return -CUI_EMEM;

	if (pkg->pio->readvec(pkg, compr, comprlen, pkg_res->offset, IO_SEEK_SET)) {
		free(compr);
		return -CUI_EREADVEC;
	}

	if (pkg_res->flags & PKG_RES_FLAG_RAW) {
		pkg_res->raw_data = compr;
		return 0;
	}

	my_entry = (my_entry_t *)pkg_res->actual_index_entry;
	if (my_entry->hash) {
		if (gen_hash((WORD *)compr, comprlen) != my_entry->hash) {
			free(compr);
			return -CUI_EMATCH;
		}
	}

	int pack_ver = (int)package_get_private(pkg);
	if (my_entry->is_encoded)
		decode((DWORD *)compr, comprlen, my_entry->key);

	if (my_entry->is_compressed) {
		int ret = pack_decompress(&uncompr, &uncomprlen, (pack_compr_t *)compr, comprlen);
		free(compr);
		compr = NULL;
		if (ret)
			return ret;
		act_data = &uncompr;
		act_data_len = uncomprlen;
	} else {
		uncompr = NULL;
		uncomprlen = 0;
		act_data = &compr;
		act_data_len = comprlen;
	}

	if (!strncmp("ARGBSaveData1", (char *)*act_data, 17)) {
		argb_header_t *argb_header = (argb_header_t *)*act_data;
		BYTE *argb_data;

		uncomprlen = argb_header->length;
		argb_data = (BYTE *)malloc(uncomprlen);
		if (!argb_data) {
			free(act_data);
			return -CUI_EMEM;
		}
		memcpy(argb_data, argb_header + 1, uncomprlen);
		free(*act_data);
		*act_data = NULL;
		uncompr = argb_data;

		pkg_res->flags |= PKG_RES_FLAG_APEXT;
		pkg_res->replace_extension = _T(".bmp");
	}
#if 0
	if (!strncmp("ABMP7", (char *)act_data, 8)) {
		int ret;
		BYTE *ret_data;
		DWORD ret_data_len;

		ret = abmp7_decompress(&ret_data, &ret_data_len, act_data, act_data_len);
		if (ret) {
			free(act_data);
			return ret;
		}
		free(act_data);
		uncompr = ret_data;
		uncomprlen = ret_data_len;

		if (!memcmp(uncompr, "\x89PNG", 4)) {
			pkg_res->flags |= PKG_RES_FLAG_APEXT;
			pkg_res->replace_extension = _T(".png");
		} else if (!memcmp(uncompr, "BM", 2)) {
			pkg_res->flags |= PKG_RES_FLAG_APEXT;
			pkg_res->replace_extension = _T(".bmp");
		}
	} else if (!strncmp("abmp10", (char *)act_data, 8)) {
		int ret;
		BYTE *ret_data;
		DWORD ret_data_len;

		ret = abmp10_decompress(&ret_data, &ret_data_len, act_data, act_data_len);
		if (ret) {
			free(act_data);
			return ret;
		}
		free(act_data);
		uncompr = ret_data;
		uncomprlen = ret_data_len;

		if (!memcmp(uncompr, "\x89PNG", 4)) {
			pkg_res->flags |= PKG_RES_FLAG_APEXT;
			pkg_res->replace_extension = _T(".png");
		} else if (!memcmp(uncompr, "BM", 2)) {
			pkg_res->flags |= PKG_RES_FLAG_APEXT;
			pkg_res->replace_extension = _T(".bmp");
		}
	}
#endif

	pkg_res->raw_data = compr;
	pkg_res->actual_data = uncompr;
	pkg_res->actual_data_length = uncomprlen;

	return 0;
}