コード例 #1
0
ファイル: gzip.c プロジェクト: paulsapps/libdeflate
static int
do_compress(struct deflate_compressor *compressor,
	    struct file_stream *in, struct file_stream *out)
{
	const void *uncompressed_data = in->mmap_mem;
	size_t uncompressed_size = in->mmap_size;
	void *compressed_data;
	size_t actual_compressed_size;
	size_t max_compressed_size;
	int ret;

	max_compressed_size = gzip_compress_bound(compressor, uncompressed_size);
	compressed_data = xmalloc(max_compressed_size);
	if (compressed_data == NULL) {
		msg("%"TS": file is probably too large to be processed by this "
		    "program", in->name);
		ret = -1;
		goto out;
	}

	actual_compressed_size =
		gzip_compress(compressor, uncompressed_data, uncompressed_size,
			      compressed_data, max_compressed_size);

	if (actual_compressed_size == 0) {
		msg("Bug in gzip_compress_bound()!");
		ret = -1;
		goto out;
	}

	ret = full_write(out, compressed_data, actual_compressed_size);
out:
	free(compressed_data);
	return ret;
}
コード例 #2
0
ファイル: gzip.c プロジェクト: CERT-Polska/hsn2-razorback
int compress_buffer(ssh_session session, ssh_buffer buf) {
    ssh_buffer dest = NULL;

    dest = gzip_compress(session, buf, session->compressionlevel);
    if (dest == NULL) {
        return -1;
    }

    if (buffer_reinit(buf) < 0) {
        ssh_buffer_free(dest);
        return -1;
    }

    if (buffer_add_data(buf, buffer_get_rest(dest), buffer_get_rest_len(dest)) < 0) {
        ssh_buffer_free(dest);
        return -1;
    }

    ssh_buffer_free(dest);
    return 0;
}
コード例 #3
0
ファイル: compression.c プロジェクト: Enigmedia/opensips
int mc_compress_cb(char** buf_p, void* param, int type, int* olen)
{
	int rc;
	int len;
	int algo;
	int flags;
	int compress_len=0;
	int uncompress_len=0;
	int hdr_compress_len=0;

	str msg_start;

	char *buf=*buf_p;
	char *end=buf+strlen(buf);
	unsigned long temp;
	struct mc_comp_args *args=(struct mc_comp_args*)param;

	struct hdr_field *hf;
	struct hdr_field *mnd_hdrs=NULL;
	struct hdr_field *non_mnd_hdrs=NULL;
	struct hdr_field *mnd_hdrs_head=NULL;
	struct hdr_field *non_mnd_hdrs_head=NULL;

	mc_param_p wh_param;
	mc_whitelist_p hdr2compress_list;

	wh_param = args->wh_param;
	hdr2compress_list = args->hdr2compress_list;
	algo = args->algo;
	flags = args->flags;

	mc_parse_first_line(&msg_start, &buf);

	uncompress_len = msg_start.len;

	/* Parse the message until the body is found
		Build two lists one of mandatory headers and one
			of non mandatory headers */

	while (1) {
		hf = pkg_malloc(sizeof(struct hdr_field));
		if (hf == NULL) {
			LM_ERR("no more pkg mem\n");
			goto free_mem_full;
		}
		memset(hf, 0, sizeof(struct hdr_field));
		hf->type=HDR_ERROR_T;
		buf=get_hdr_field(buf, end, hf);

		if (hf->type == HDR_ERROR_T) {
			goto free_mem_full;
		}

		if (hf->type == HDR_EOH_T) {
			compress_len += strlen(buf);
			compress_len = compress_len > CRLF_LEN ? compress_len : 0;
			pkg_free(hf);
			break;
		}

		/*if Content-Length=0 then header must remain*/
		if (hf->type == HDR_CONTENTLENGTH_T &&
				hf->body.s[0] == '0') {
			goto set_mandatory;
		}

		if (mc_is_in_whitelist(hf, hdr2compress_list)) {
			if (!non_mnd_hdrs) {
				non_mnd_hdrs_head = non_mnd_hdrs = hf;
			} else {
				non_mnd_hdrs->next = hf;
				non_mnd_hdrs = non_mnd_hdrs->next;
			}

			/* in case will have a separate compressed header */
			if ((flags&SEPARATE_COMP_FLG && flags&BODY_COMP_FLG &&
							flags&HDR_COMP_FLG) ||
				(flags&HDR_COMP_FLG && !(flags&BODY_COMP_FLG)))
				hdr_compress_len += hf->len;
			else
				compress_len += hf->len;

		} else {
		set_mandatory:
			if (!mnd_hdrs) {
				mnd_hdrs_head = mnd_hdrs = hf;
			} else {
				mnd_hdrs->next = hf;
				mnd_hdrs = mnd_hdrs->next;
			}
			uncompress_len += hf->len;
		}
		hf = 0;
	}

	str buf2compress={NULL, 0};
	str hdr_buf2compress={NULL, 0};

	/* Copy headers only if they exist and only if were asked*/
	non_mnd_hdrs = non_mnd_hdrs_head;
	if (!non_mnd_hdrs || !(flags&HDR_COMP_FLG))
		goto only_body;

	/* If body compression and header compression flags are set and
		they have to be together in the body */
	if ((flags&BODY_COMP_FLG && flags&HDR_COMP_FLG &&
						!(flags&SEPARATE_COMP_FLG)) ||
		(flags&BODY_COMP_FLG && !(flags&HDR_COMP_FLG))){

		if (wrap_realloc(&body_in, compress_len))
			goto free_mem_full;

		buf2compress.s = body_in.s;
		buf2compress.len = 0;

		for (hf = non_mnd_hdrs; hf; hf = hf->next) {
			wrap_copy_and_update( &buf2compress.s, hf->name.s,
						hf->len, &buf2compress.len);
		}
	/* body compression and header compression but separately or
		only header compression */
	} else if ((flags&BODY_COMP_FLG && flags&HDR_COMP_FLG &&
			flags&SEPARATE_COMP_FLG) ||
		    (!(flags&BODY_COMP_FLG) && flags&HDR_COMP_FLG)) {

		if (wrap_realloc(&hdr_in, hdr_compress_len))
			goto free_mem_full;

		hdr_buf2compress.s = hdr_in.s;

		for (hf = non_mnd_hdrs; hf; hf = hf->next) {
			wrap_copy_and_update( &hdr_buf2compress.s, hf->name.s,
						hf->len, &hdr_buf2compress.len);
		}
	}

only_body:
	/* Copy the body of the message only if body compression is asked */
	if (flags&BODY_COMP_FLG && compress_len) {
		if (!buf2compress.s) {
			if (wrap_realloc(&body_in, compress_len))
				goto free_mem_full;
			buf2compress.s = body_in.s;
		}

		wrap_copy_and_update( &buf2compress.s, buf, strlen(buf),
							&buf2compress.len);
	}

	if (!buf2compress.s && !hdr_buf2compress.s) {
		LM_WARN("Nothing to compress. Specified headers not found\n");
		goto free_mem_full;
	}

	/* Compress the message */
	str bufcompressed={NULL, 0};
	str hdr_bufcompressed={NULL, 0};

	switch (algo) {
	case 0: /* deflate */

		if (buf2compress.s) {
			bufcompressed.len = compressBound((unsigned long)buf2compress.len);
			if (wrap_realloc(&body_out, bufcompressed.len))
				goto free_mem_full;

			bufcompressed.s = body_out.s;
			temp = (unsigned long)bufcompressed.len;

			rc = compress2((unsigned char*)bufcompressed.s,
					&temp,
					(unsigned char*)buf2compress.s,
					(unsigned long)buf2compress.len,
					mc_level);

			bufcompressed.len = (int)temp;

			if (check_zlib_rc(rc)) {
				LM_ERR("Body compression failed\n");
				goto free_mem_full;
			}
		}

		if ((flags&HDR_COMP_FLG) && hdr_buf2compress.s) {
			hdr_bufcompressed.len = compressBound((unsigned long)hdr_buf2compress.len);
			if (wrap_realloc(&hdr_out, hdr_bufcompressed.len))
				goto free_mem_full;

			hdr_bufcompressed.s = hdr_out.s;
			temp = (unsigned long)hdr_bufcompressed.len;

			rc = compress2((unsigned char*)hdr_bufcompressed.s,
					&temp,
					(unsigned char*)hdr_buf2compress.s,
					(unsigned long)hdr_buf2compress.len,
					mc_level);

			hdr_bufcompressed.len = temp;

			if (check_zlib_rc(rc)) {
				LM_ERR("Header compression failed\n");
				goto free_mem_full;
			}
		}

		break;
	case 1: /* gzip */
		if (buf2compress.s) {
			rc = gzip_compress(
					(unsigned char*)buf2compress.s,
					(unsigned long)buf2compress.len,
					&body_out,
					&temp,
					mc_level);

			if (check_zlib_rc(rc)) {
				LM_ERR("Body compression failed\n");
				goto free_mem_full;
			}

			bufcompressed.s = body_out.s;
			bufcompressed.len = (int)temp;
		}

		if ((flags&HDR_COMP_FLG) && hdr_buf2compress.s) {
			rc = gzip_compress(
					(unsigned char*)hdr_buf2compress.s,
					(unsigned long)hdr_buf2compress.len,
					&hdr_out,
					&temp,
					mc_level);

			if (check_zlib_rc(rc)) {
				LM_ERR("Header compression failed\n");
				goto free_mem_full;
			}
			hdr_bufcompressed.s = hdr_out.s;
			hdr_bufcompressed.len = temp;
		}

		break;
	default:
		LM_WARN("Invalind algo! no compression made\n");
		goto free_mem_full;
	}

	str bufencoded={NULL, 0};
	str hdr_bufencoded={NULL, 0};

	if ((flags&B64_ENCODED_FLG) && bufcompressed.s) {
		bufencoded.len = calc_base64_encode_len(bufcompressed.len);
		if (wrap_realloc( &body_in, 2*CRLF_LEN + bufencoded.len))
			goto free_mem_full;
		bufencoded.s = body_in.s;

		memcpy(bufencoded.s, CRLF, CRLF_LEN);

		base64encode((unsigned char*)(bufencoded.s + CRLF_LEN),
				(unsigned char*)bufcompressed.s,
							bufcompressed.len);
	} else if (bufcompressed.s) {
		if (wrap_realloc(&body_in, bufcompressed.len + 2*CRLF_LEN))
			goto free_mem_full;

		/* !!! shift buf2compressed CRLF_LEN to the right !!! */
		memcpy(body_in.s+CRLF_LEN, bufcompressed.s, bufcompressed.len);
		memcpy(body_in.s, CRLF, CRLF_LEN);

		bufencoded.len = bufcompressed.len;
		bufencoded.s = body_in.s;
	}

	if (hdr_bufcompressed.s) {

		hdr_bufencoded.len = calc_base64_encode_len(hdr_bufcompressed.len);

		if (wrap_realloc( &hdr_in, hdr_bufencoded.len + CRLF_LEN))
			goto free_mem_full;
		hdr_bufencoded.s = hdr_in.s;

		base64encode((unsigned char*)hdr_bufencoded.s,
				(unsigned char*)hdr_bufcompressed.s,
							hdr_bufcompressed.len);

		wrap_copy_and_update(&hdr_bufencoded.s, CRLF, CRLF_LEN,
							&hdr_bufencoded.len);
	}

	/* Allocate the new buffer */
	int alloc_size;
	str buf2send={NULL, 0};

	alloc_size = msg_start.len + uncompress_len + CRLF_LEN/*the one before all headers*/;

	if (hdr_bufencoded.s) {
		alloc_size += COMP_HDRS_LEN + hdr_bufencoded.len;
		alloc_size += sizeof(HDRS_ENCODING) - 1;
	}

	/* if body compressed new content length and content encoding
	 * plus if required more space for base64 in content encoding header*/

	if (bufencoded.s) {
		alloc_size += CL_NAME_LEN + mc_ndigits(bufencoded.len) + CRLF_LEN;
		alloc_size += CE_NAME_LEN + CRLF_LEN;
		if (flags&B64_ENCODED_FLG) {
			alloc_size += ATTR_DELIM_LEN + (sizeof(BASE64_ALGO)-1);
		}
	}


	switch (algo) {
		case 0: /* deflate*/
			if (bufencoded.s)
				alloc_size += DEFLATE_CE_LEN;
			if (hdr_bufencoded.s)
				alloc_size += sizeof(DEFLATE_ALGO) - 1;
			break;
		case 1: /* gzip */
			if (bufencoded.s)
				alloc_size += GZIP_CE_LEN;
			if (hdr_bufencoded.s)
				alloc_size += sizeof(GZIP_ALGO) - 1;
			break;
		default:
			LM_ERR("compression algo not impelemented\n");
			goto free_mem_full;
	}

	if (bufencoded.s)
		alloc_size += bufencoded.len + CRLF_LEN;
	else
		alloc_size += strlen(buf);

	if (wrap_realloc(&buf_out, alloc_size))
		goto free_mem_full;

	buf2send.s = buf_out.s;

	/* Copy message start */
	wrap_copy_and_update( &buf2send.s, msg_start.s, msg_start.len,
							&buf2send.len);

	/* Copy mandatory headers */
	for (mnd_hdrs = mnd_hdrs_head; mnd_hdrs; mnd_hdrs = mnd_hdrs->next) {
		wrap_copy_and_update( &buf2send.s, mnd_hdrs->name.s,
						mnd_hdrs->len, &buf2send.len);
	}


	if ((flags&BODY_COMP_FLG) && bufencoded.s) {
		wrap_copy_and_update( &buf2send.s, CL_NAME,
						CL_NAME_LEN, &buf2send.len);

		wrap_copy_and_update( &buf2send.s, int2str(bufencoded.len, &len),
					mc_ndigits(bufencoded.len), &buf2send.len);
		wrap_copy_and_update( &buf2send.s, CRLF, CRLF_LEN, &buf2send.len);
	}

	if (hdr_bufencoded.s) {
		wrap_copy_and_update( &buf2send.s, COMP_HDRS, COMP_HDRS_LEN,
								&buf2send.len);

		wrap_copy_and_update( &buf2send.s, hdr_bufencoded.s,
					hdr_bufencoded.len, &buf2send.len);

	}

	switch (algo) {
	case 0: /* deflate */
		if (hdr_bufencoded.s) {
			str hdr_name = str_init(HDRS_ENCODING),
				hdr_value = str_init(DEFLATE_ALGO);
			wrap_copy_and_update(&buf2send.s, hdr_name.s,
						hdr_name.len, &buf2send.len);

			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, hdr_value.s,
						hdr_value.len, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);

		}

		if (bufencoded.s) {
			wrap_copy_and_update(&buf2send.s, CE_NAME,
						CE_NAME_LEN, &buf2send.len);

			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, DEFLATE_ALGO,
							sizeof(DEFLATE_ALGO)-1, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);
		}
		break;
	case 1: /* gzip */
		if (hdr_bufencoded.s) {
			str hdr_name = str_init(HDRS_ENCODING),
				hdr_value = str_init(GZIP_ALGO);
			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, hdr_name.s,
						hdr_name.len, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, hdr_value.s,
						hdr_value.len, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);
		}

		if (bufencoded.s) {
			wrap_copy_and_update(&buf2send.s, CE_NAME,
						CE_NAME_LEN, &buf2send.len);
			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, GZIP_ALGO,
							sizeof(GZIP_ALGO)-1, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);
		}
		break;
	default:
		LM_ERR("compression algo not impelemented\n");
		goto free_mem_full;
	}


	/* Copy message body */
	if (bufencoded.s) {
		wrap_copy_and_update( &buf2send.s, bufencoded.s,
					bufencoded.len+CRLF_LEN, &buf2send.len);

		wrap_copy_and_update( &buf2send.s, CRLF,
						CRLF_LEN, &buf2send.len);
	} else {
		wrap_copy_and_update( &buf2send.s, buf, strlen(buf),
							&buf2send.len);
	}

	switch (type) {
		case TM_CB:
			shm_free(*buf_p);
			*buf_p = shm_malloc(buf2send.len+1);
			if (*buf_p == NULL) {
				LM_ERR("no more sh mem\n");
				goto free_mem_full;
			}
			break;
		case PROCESSING_CB:
			*buf_p = pkg_malloc(buf2send.len+1);
			if (*buf_p == NULL) {
				LM_ERR("no more pkg mem\n");
				goto free_mem_full;
			}
			break;
		default:
			LM_ERR("invalid type\n");
			goto free_mem_full;
	}

	memcpy(*buf_p, buf2send.s, buf2send.len);
	(*buf_p)[buf2send.len] = '\0';
	*olen = buf2send.len;

	free_hdr_list(&mnd_hdrs_head);
	free_hdr_list(&non_mnd_hdrs_head);

	if (wh_param && wh_param->type == WH_TYPE_PVS)
		free_whitelist(&hdr2compress_list);

	return 0;

free_mem_full:
	free_hdr_list(&mnd_hdrs_head);
	free_hdr_list(&non_mnd_hdrs_head);
	if (wh_param && wh_param->type == WH_TYPE_PVS)
		free_whitelist(&hdr2compress_list);

	return -1;
}
コード例 #4
0
int main(int argc, char **argv)
{
	header_keys keys;
	u8 rawkheaderBk[0x90];

	if(argc < 2)
	{
		printf("USAGE: PrxEncrypter [prx]\n");
		return 0;
	}

	memset(in_buffer, 0, sizeof(in_buffer));
	memset(out_buffer, 0, sizeof(out_buffer));
	memset(kirk_raw, 0, sizeof(kirk_raw));
	memset(kirk_enc, 0, sizeof(kirk_enc));
	memset(elf, 0, sizeof(elf));

	kirk_init();

	int elfSize = load_elf(argv[1]);

	if(elfSize < 0) {
		printf("Cannot open %s\n", argv[1]);

		return 0;
	}

	Header_List *target_header = get_header_list( elfSize );

	if( target_header == NULL ) {
		printf("PRX SIGNER: Elf is to big\n");

		return 0;
	}

	u8 *kirkHeader	= target_header->kirkHeader;
	u8 *pspHeader	= target_header->pspHeader;
	int krawSize = get_kirk_size(kirkHeader);

	if (is_compressed(pspHeader)) {
		elfSize = get_elf_size(pspHeader);
		gzip_compress(elf, elf, elfSize);
	}

	memcpy(kirk_raw, kirkHeader, 0x110);
	memcpy(rawkheaderBk, kirk_raw, sizeof(rawkheaderBk));

	kirk_decrypt_keys((u8*)&keys, kirk_raw);
	memcpy(kirk_raw, &keys, sizeof(header_keys));
	memcpy(kirk_raw+0x110, elf, elfSize);

	if(kirk_CMD0(kirk_enc, kirk_raw, sizeof(kirk_enc), 0) != 0)
	{
		printf("PRX SIGNER: Could not encrypt elf\n");
		return 0;
	}

	memcpy(kirk_enc, rawkheaderBk, sizeof(rawkheaderBk));

	if(kirk_forge(kirk_enc, sizeof(kirk_enc)) != 0)
	{
		printf("PRX SIGNER: Could not forge cmac block\n");

		return 0;
	}

	memcpy(out_buffer, pspHeader, 0x150);
	memcpy(out_buffer+0x150, kirk_enc+0x110, krawSize-0x110);

	return dumpFile("./data.psp", out_buffer, (krawSize-0x110)+0x150);
}
コード例 #5
0
ファイル: main.c プロジェクト: nikatshun/asuswrt-merlin
/**
 * This handles requests that are daap-related.  For example,
 * /server-info, /login, etc.  This should really be split up
 * into multiple functions, and perhaps moved into daap.c
 *
 * \param pwsc Webserver connection info, passed from the webserver
 *
 * \todo Decomplexify this!
 */
void daap_handler(WS_CONNINFO *pwsc) {
    int close;
    DAAP_BLOCK *root;
    int clientrev;

    /* for the /databases URI */
    char *uri;
    unsigned long int db_index;
    unsigned long int playlist_index;
    unsigned long int item=0;
    char *first, *last;
    char* index = 0;
    int streaming=0;
    int compress =0;
    int start_time;
    int end_time;
    int bytes_written;

    MP3FILE *pmp3;
    int file_fd;
    int session_id=0;

    int img_fd;
    struct stat sb;
    long img_size;

    off_t offset=0;
    off_t real_len;
    off_t file_len;

    int bytes_copied=0;

    GZIP_STREAM *gz;

    close=pwsc->close;
    pwsc->close=1;  /* in case we have any errors */
    root=NULL;

    ws_addresponseheader(pwsc,"Accept-Ranges","bytes");
    ws_addresponseheader(pwsc,"DAAP-Server","mt-daapd/%s",VERSION);
    ws_addresponseheader(pwsc,"Content-Type","application/x-dmap-tagged");

    if(ws_getvar(pwsc,"session-id")) {
        session_id=atoi(ws_getvar(pwsc,"session-id"));
    }

    if(!strcasecmp(pwsc->uri,"/server-info")) {
        config_set_status(pwsc,session_id,"Sending server info");
        root=daap_response_server_info(config.servername,
                                       ws_getrequestheader(pwsc,"Client-DAAP-Version"));
    } else if (!strcasecmp(pwsc->uri,"/content-codes")) {
        config_set_status(pwsc,session_id,"Sending content codes");
        root=daap_response_content_codes();
    } else if (!strcasecmp(pwsc->uri,"/login")) {
        config_set_status(pwsc,session_id,"Logging in");
        root=daap_response_login(pwsc->hostname);
    } else if (!strcasecmp(pwsc->uri,"/update")) {
        if(!ws_getvar(pwsc,"delta")) { /* first check */
            clientrev=db_version() - 1;
            config_set_status(pwsc,session_id,"Sending database");
        } else {
            clientrev=atoi(ws_getvar(pwsc,"delta"));
            config_set_status(pwsc,session_id,"Waiting for DB updates");
        }
        root=daap_response_update(pwsc->fd,clientrev);
        if((ws_getvar(pwsc,"delta")) && (root==NULL)) {
            DPRINTF(E_LOG,L_WS,"Client %s disconnected\n",pwsc->hostname);
            config_set_status(pwsc,session_id,NULL);
            pwsc->close=1;
            return;
        }
    } else if (!strcasecmp(pwsc->uri,"/logout")) {
        config_set_status(pwsc,session_id,NULL);
        ws_returnerror(pwsc,204,"Logout Successful");
        return;
    } else if(strcmp(pwsc->uri,"/databases")==0) {
        config_set_status(pwsc,session_id,"Sending database info");
        root=daap_response_dbinfo(config.servername);
        if(0 != (index = ws_getvar(pwsc, "index")))
            daap_handle_index(root, index);
    } else if(strncmp(pwsc->uri,"/databases/",11) == 0) {

        /* the /databases/ uri will either be:
         *
         * /databases/id/items, which returns items in a db
         * /databases/id/containers, which returns a container
         * /databases/id/containers/id/items, which returns playlist elements
         * /databases/id/items/id.mp3, to spool an mp3
 * /databases/id/browse/category
         */

        uri = strdup(pwsc->uri);
        first=(char*)&uri[11];
        last=first;
        while((*last) && (*last != '/')) {
            last++;
        }

        if(*last) {
            *last='\0';
            db_index=atoll(first);

            last++;

            if(strncasecmp(last,"items/",6)==0) {
                /* streaming */
                first=last+6;
                while((*last) && (*last != '.'))
                    last++;

                if(*last == '.') {
                    *last='\0';
                    item=atoll(first);
                    streaming=1;
                    DPRINTF(E_DBG,L_DAAP|L_WS,"Streaming request for id %lu\n",item);
                }
                free(uri);
            } else if (strncasecmp(last,"items",5)==0) {
                /* songlist */
                free(uri);
                // pass the meta field request for processing
                // pass the query request for processing
                root=daap_response_songlist(ws_getvar(pwsc,"meta"),
                                            ws_getvar(pwsc,"query"));
                config_set_status(pwsc,session_id,"Sending songlist");
            } else if (strncasecmp(last,"containers/",11)==0) {
                /* playlist elements */
                first=last + 11;
                last=first;
                while((*last) && (*last != '/')) {
                    last++;
                }

                if(*last) {
                    *last='\0';
                    playlist_index=atoll(first);
                    // pass the meta list info for processing
                    root=daap_response_playlist_items(playlist_index,
                                                      ws_getvar(pwsc,"meta"),
                                                      ws_getvar(pwsc,"query"));
                }
                free(uri);
                config_set_status(pwsc,session_id,"Sending playlist info");
            } else if (strncasecmp(last,"containers",10)==0) {
                /* list of playlists */
                free(uri);
                root=daap_response_playlists(config.servername);
                config_set_status(pwsc,session_id,"Sending playlist info");
            } else if (strncasecmp(last,"browse/",7)==0) {
                config_set_status(pwsc,session_id,"Compiling browse info");
                root = daap_response_browse(last + 7,
                                            ws_getvar(pwsc, "filter"));
                config_set_status(pwsc,session_id,"Sending browse info");
                free(uri);
            }
        }

        // prune the full list if an index range was specified
        if(0 != (index = ws_getvar(pwsc, "index")))
            daap_handle_index(root, index);
    }

    if((!root)&&(!streaming)) {
        DPRINTF(E_DBG,L_WS|L_DAAP,"Bad request -- root=%x, streaming=%d\n",root,streaming);
        ws_returnerror(pwsc,400,"Invalid Request");
        config_set_status(pwsc,session_id,NULL);
        return;
    }

    pwsc->close=close;

    if(!streaming) {
        DPRINTF(E_DBG,L_WS,"Satisfying request\n");

        if((config.compress) && ws_testrequestheader(pwsc,"Accept-Encoding","gzip") && root->reported_size >= 1000) {
          compress=1;
        }

        DPRINTF(E_DBG,L_WS|L_DAAP,"Serializing\n");
        start_time = time(NULL);
        if (compress) {
          DPRINTF(E_DBG,L_WS|L_DAAP,"Using compression: %s\n", pwsc->uri);
          gz = gzip_alloc();
          daap_serialize(root,pwsc->fd,gz);
          gzip_compress(gz);
          bytes_written = gz->bytes_out;
          ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
          ws_addresponseheader(pwsc,"Content-Length","%d",bytes_written);
          ws_addresponseheader(pwsc,"Content-Encoding","gzip");
          DPRINTF(E_DBG,L_WS,"Emitting headers\n");
          ws_emitheaders(pwsc);
          if (gzip_close(gz,pwsc->fd) != bytes_written) {
            DPRINTF(E_LOG,L_WS|L_DAAP,"Error compressing data\n");
          }
          DPRINTF(E_DBG,L_WS|L_DAAP,"Compression ratio: %f\n",((double) bytes_written)/(8.0 + root->reported_size))
        }
        else {