Пример #1
0
buffer * strftime_cache_get(server *srv, time_t last_mod) {
	struct tm *tm;
	size_t i;

	for (i = 0; i < FILE_CACHE_MAX; i++) {
		/* found cache-entry */
		if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;

		/* found empty slot */
		if (srv->mtime_cache[i].mtime == 0) break;
	}

	if (i == FILE_CACHE_MAX) {
		i = 0;
	}

	srv->mtime_cache[i].mtime = last_mod;
	buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
	tm = gmtime(&(srv->mtime_cache[i].mtime));
	srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
						 srv->mtime_cache[i].str->size - 1,
						 "%a, %d %b %Y %H:%M:%S GMT", tm);
	srv->mtime_cache[i].str->used++;

	return srv->mtime_cache[i].str;
}
Пример #2
0
static int log_buffer_prepare(buffer *b, server *srv, const char *filename, unsigned int line) {
    switch(srv->errorlog_mode) {
    case ERRORLOG_PIPE:
    case ERRORLOG_FILE:
    case ERRORLOG_FD:
        if (-1 == srv->errorlog_fd) return -1;
        /* cache the generated timestamp */
        if (srv->cur_ts != srv->last_generated_debug_ts) {
            buffer_prepare_copy(srv->ts_debug_str, 255);
            strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
            srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;

            srv->last_generated_debug_ts = srv->cur_ts;
        }

        buffer_copy_string_buffer(b, srv->ts_debug_str);
        buffer_append_string_len(b, CONST_STR_LEN(": ("));
        break;
    case ERRORLOG_SYSLOG:
        /* syslog is generating its own timestamps */
        buffer_copy_string_len(b, CONST_STR_LEN("("));
        break;
    }

    buffer_append_string(b, filename);
    buffer_append_string_len(b, CONST_STR_LEN("."));
    buffer_append_long(b, line);
    buffer_append_string_len(b, CONST_STR_LEN(") "));

    return 0;
}
Пример #3
0
static int http_chunk_append_len(server *srv, connection *con, size_t len) {
	size_t i, olen = len, j;
	buffer *b;

	b = srv->tmp_chunk_len;

	if (len == 0) {
		buffer_copy_string_len(b, CONST_STR_LEN("0"));
	} else {
		for (i = 0; i < 8 && len; i++) {
			len >>= 4;
		}

		/* i is the number of hex digits we have */
		buffer_prepare_copy(b, i + 1);

		for (j = i-1, len = olen; j+1 > 0; j--) {
			b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
			len >>= 4;
		}
		b->used = i;
		b->ptr[b->used++] = '\0';
	}

	buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
	chunkqueue_append_buffer(con->write_queue, b);

	return 0;
}
Пример #4
0
unsigned char * base64_decode(buffer *out, const char *in) {
	unsigned char *result;
	int ch, j = 0, k;
	size_t i;

	size_t in_len = strlen(in);
	
	buffer_prepare_copy(out, in_len);

	result = (unsigned char *)out->ptr;

	ch = in[0];
	/* run through the whole string, converting as we go */
	for (i = 0; i < in_len; i++) {
		ch = in[i];

		if (ch == '\0') break;

		if (ch == base64_pad) break;

		ch = base64_reverse_table[ch];
		if (ch < 0) continue;

		switch(i % 4) {
		case 0:
			result[j] = ch << 2;
			break;
		case 1:
			result[j++] |= ch >> 4;
			result[j] = (ch & 0x0f) << 4;
			break;
		case 2:
			result[j++] |= ch >>2;
			result[j] = (ch & 0x03) << 6;
			break;
		case 3:
			result[j++] |= ch;
			break;
		}
	}
	k = j;
	/* mop things up if we ended on a boundary */
	if (ch == base64_pad) {
		switch(i % 4) {
		case 0:
		case 1:
			return NULL;
		case 2:
			k++;
		case 3:
			result[k++] = 0;
		}
	}
	result[k] = '\0';

	out->used = k;

	return result;
}
Пример #5
0
int buffer_copy_str_len(buffer *buf,const char *str,int len)
{
    if(!buf || !str || len <= 0) return -1;
    
    buffer_prepare_copy(buf,len + 1);
    memcpy(buf->ptr,str,len);
    buf->used = len;
    buf->ptr[buf->used] = '\0';
    
    return 0;
}
Пример #6
0
int buffer_copy_string(buffer *buf,const char *str)
{
    if(!buf || !str) return -1;
    
    int len = strlen(str);
    
    buffer_prepare_copy(buf,len + 1);
    memcpy(buf->ptr,str,len + 1);                           /* copy str and ending '\0' */
    buf->used = len;                                        /* not with ending '\0' */
    
    return 0;
}
Пример #7
0
static int stat_cache_attr_get(buffer *buf, char *name) {
	ssize_t attrlen;

	buffer_prepare_copy(buf, 1023);

	if (-1 != (attrlen = extattr_get_file(name, EXTATTR_NAMESPACE_USER, "Content-Type", buf->ptr, buf->size - 1))) {
		buf->used = attrlen + 1;
		buf->ptr[attrlen] = '\0';
		return 0;
	}
	return -1;
}
Пример #8
0
static int stat_cache_attr_get(buffer *buf, char *name) {
	int attrlen;
	int ret;

	attrlen = 1024;
	buffer_prepare_copy(buf, attrlen);
	attrlen--;
	if(0 == (ret = attr_get(name, "Content-Type", buf->ptr, &attrlen, 0))) {
		buf->used = attrlen + 1;
		buf->ptr[attrlen] = '\0';
	}
	return ret;
}
Пример #9
0
int buffer_copy_string(buffer *b, const char *s) {
	size_t s_len;

	if (!s || !b) return -1;

	s_len = strlen(s) + 1;
	buffer_prepare_copy(b, s_len);

	memcpy(b->ptr, s, s_len);
	b->used = s_len;

	return 0;
}
Пример #10
0
/**
 * 将s复制到b的数据区中,s_len是s的长度
 */
int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) 
{
	if (!s || !b)
	{
		return -1;
	}
	
	buffer_prepare_copy(b, s_len + 1);

	memcpy(b -> ptr, s, s_len);
	b -> ptr[s_len] = '\0';
	b -> used = s_len + 1;

	return 0;
}
Пример #11
0
int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
	size_t i;

	/* BO protection */
	if (in_len * 2 < in_len) return -1;

	buffer_prepare_copy(b, in_len * 2 + 1);

	for (i = 0; i < in_len; i++) {
		b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
		b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
	}
	b->ptr[b->used++] = '\0';

	return 0;
}
Пример #12
0
static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
	stat_cache_entry *sce = NULL;

	buffer_prepare_copy(out, 128);

	if (p->conf.server_root->used) {
		buffer_copy_string_buffer(out, p->conf.server_root);

		if (host->used) {
			/* a hostname has to start with a alpha-numerical character
			 * and must not contain a slash "/"
			 */
			char *dp;

			BUFFER_APPEND_SLASH(out);

			if (NULL == (dp = strchr(host->ptr, ':'))) {
				buffer_append_string_buffer(out, host);
			} else {
				buffer_append_string_len(out, host->ptr, dp - host->ptr);
			}
		}
		BUFFER_APPEND_SLASH(out);

		if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
			buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
		} else {
			buffer_append_string_buffer(out, p->conf.document_root);
			BUFFER_APPEND_SLASH(out);
		}
	} else {
		buffer_copy_string_buffer(out, con->conf.document_root);
		BUFFER_APPEND_SLASH(out);
	}

	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
		if (p->conf.debug) {
			log_error_write(srv, __FILE__, __LINE__, "sb",
					strerror(errno), out);
		}
		return -1;
	} else if (!S_ISDIR(sce->st.st_mode)) {
		return -1;
	}

	return 0;
}
Пример #13
0
buffer_t *buffer_new(size_t len)
{
    buffer_t *b;

    b = malloc(sizeof(*b));

    assert(b);

    b->ptr = NULL;
    b->size = 0;
    b->used = 0;

    if (len) {
        buffer_prepare_copy(b, len);
    }

    return b;
}
Пример #14
0
int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
	if (!s || !b) return -1;
#if 0
	/* removed optimization as we have to keep the empty string
	 * in some cases for the config handling
	 *
	 * url.access-deny = ( "" )
	 */
	if (s_len == 0) return 0;
#endif
	buffer_prepare_copy(b, s_len + 1);

	memcpy(b->ptr, s, s_len);
	b->ptr[s_len] = '\0';
	b->used = s_len + 1;

	return 0;
}
Пример #15
0
int config_read(server *srv, const char *fn) {
    config_t context;
    data_config *dc;
    data_integer *dpid;
    data_string *dcwd;
    int ret;
    char *pos;
    data_array *modules;

    context_init(srv, &context);
    context.all_configs = srv->config_context;

#ifdef __WIN32
    pos = strrchr(fn, '\\');
#else
    pos = strrchr(fn, '/');
#endif
    if (pos) {
        buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
        fn = pos + 1;
    }

    dc = data_config_init();
    buffer_copy_string_len(dc->key, CONST_STR_LEN("global"));

    assert(context.all_configs->used == 0);
    dc->context_ndx = context.all_configs->used;
    array_insert_unique(context.all_configs, (data_unset *)dc);
    context.current = dc;

    /* default context */
    srv->config = dc->value;
    dpid = data_integer_init();
    dpid->value = getpid();
    buffer_copy_string_len(dpid->key, CONST_STR_LEN("var.PID"));
    array_insert_unique(srv->config, (data_unset *)dpid);

    dcwd = data_string_init();
    buffer_prepare_copy(dcwd->value, 1024);
    if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
        dcwd->value->used = strlen(dcwd->value->ptr) + 1;
        buffer_copy_string_len(dcwd->key, CONST_STR_LEN("var.CWD"));
        array_insert_unique(srv->config, (data_unset *)dcwd);
    }

    ret = config_parse_file(srv, &context, fn);

    /* remains nothing if parser is ok */
    assert(!(0 == ret && context.ok && 0 != context.configs_stack->used));
    context_free(&context);

    if (0 != ret) {
        return ret;
    }

    if (NULL != (dc = (data_config *)array_get_element(srv->config_context, "global"))) {
        srv->config = dc->value;
    } else {
        return -1;
    }

    if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
        data_string *ds;
        data_array *prepends;

        if (modules->type != TYPE_ARRAY) {
            fprintf(stderr, "server.modules must be an array");
            return -1;
        }

        prepends = data_array_init();

        /* prepend default modules */
        if (NULL == array_get_element(modules->value, "mod_indexfile")) {
            ds = data_string_init();
            buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
            array_insert_unique(prepends->value, (data_unset *)ds);
        }

        prepends = (data_array *)configparser_merge_data((data_unset *)prepends, (data_unset *)modules);
        buffer_copy_string_buffer(prepends->key, modules->key);
        array_replace(srv->config, (data_unset *)prepends);
        modules->free((data_unset *)modules);
        modules = prepends;

        /* append default modules */
        if (NULL == array_get_element(modules->value, "mod_dirlisting")) {
            ds = data_string_init();
            buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
            array_insert_unique(modules->value, (data_unset *)ds);
        }

        if (NULL == array_get_element(modules->value, "mod_staticfile")) {
            ds = data_string_init();
            buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
            array_insert_unique(modules->value, (data_unset *)ds);
        }
    } else {
        data_string *ds;

        modules = data_array_init();

        /* server.modules is not set */
        ds = data_string_init();
        buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
        array_insert_unique(modules->value, (data_unset *)ds);

        ds = data_string_init();
        buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
        array_insert_unique(modules->value, (data_unset *)ds);

        ds = data_string_init();
        buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
        array_insert_unique(modules->value, (data_unset *)ds);

        buffer_copy_string_len(modules->key, CONST_STR_LEN("server.modules"));
        array_insert_unique(srv->config, (data_unset *)modules);
    }


    if (0 != config_insert(srv)) {
        return -1;
    }

    return 0;
}
Пример #16
0
static int cgi_demux_response(server *srv, handler_ctx *hctx) {
	plugin_data *p    = hctx->plugin_data;
	connection  *con  = hctx->remote_conn;

	while(1) {
		int n;

		buffer_prepare_copy(hctx->response, 1024);
		if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
			if (errno == EAGAIN || errno == EINTR) {
				/* would block, wait for signal */
				return FDEVENT_HANDLED_NOT_FINISHED;
			}
			/* error */
			log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
			return FDEVENT_HANDLED_ERROR;
		}

		if (n == 0) {
			/* read finished */

			con->file_finished = 1;

			/* send final chunk */
			http_chunk_append_mem(srv, con, NULL, 0);
			joblist_append(srv, con);

			return FDEVENT_HANDLED_FINISHED;
		}

		hctx->response->ptr[n] = '\0';
		hctx->response->used = n+1;

		/* split header from body */

		if (con->file_started == 0) {
			char *c;
			int in_header = 0;
			int header_end = 0;
			int cp, eol = EOL_UNSET;
			size_t used = 0;

			buffer_append_string_buffer(hctx->response_header, hctx->response);

			/* nph (non-parsed headers) */
			if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;

			/* search for the \r\n\r\n or \n\n in the string */
			for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
				if (*c == ':') in_header = 1;
				else if (*c == '\n') {
					if (in_header == 0) {
						/* got a response without a response header */

						c = NULL;
						header_end = 1;
						break;
					}

					if (eol == EOL_UNSET) eol = EOL_N;

					if (*(c+1) == '\n') {
						header_end = 1;
						break;
					}

				} else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
					if (in_header == 0) {
						/* got a response without a response header */

						c = NULL;
						header_end = 1;
						break;
					}

					if (eol == EOL_UNSET) eol = EOL_RN;

					if (used > 3 &&
					    *(c+2) == '\r' &&
					    *(c+3) == '\n') {
						header_end = 1;
						break;
					}

					/* skip the \n */
					c++;
					cp++;
					used--;
				}
			}

			if (header_end) {
				if (c == NULL) {
					/* no header, but a body */

					if (con->request.http_version == HTTP_VERSION_1_1) {
						con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
					}

					http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
					joblist_append(srv, con);
				} else {
					size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
					size_t blen = hctx->response_header->used - hlen - 1;

					/* a small hack: terminate after at the second \r */
					hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
					hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';

					/* parse the response header */
					cgi_response_parse(srv, con, p, hctx->response_header, eol);

					/* enable chunked-transfer-encoding */
					if (con->request.http_version == HTTP_VERSION_1_1 &&
					    !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
						con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
					}

					if ((hctx->response->used != hlen) && blen > 0) {
						http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
						joblist_append(srv, con);
					}
				}

				con->file_started = 1;
			}
		} else {
			http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
			joblist_append(srv, con);
		}

#if 0
		log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
#endif
	}

	return FDEVENT_HANDLED_NOT_FINISHED;
}
Пример #17
0
static int cgi_demux_response(server *srv, handler_ctx *hctx) {
	plugin_data *p    = hctx->plugin_data;
	connection  *con  = hctx->remote_conn;

	while(1) {
		int n;
		int toread;

#if defined(__WIN32)
		buffer_prepare_copy(hctx->response, 4 * 1024);
#else
		if (ioctl(con->fd, FIONREAD, &toread) || toread == 0 || toread <= 4*1024) {
			buffer_prepare_copy(hctx->response, 4 * 1024);
		} else {
			if (toread > MAX_READ_LIMIT) toread = MAX_READ_LIMIT;
			buffer_prepare_copy(hctx->response, toread + 1);
		}
#endif

		if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
			if (errno == EAGAIN || errno == EINTR) {
				/* would block, wait for signal */
				return FDEVENT_HANDLED_NOT_FINISHED;
			}
			/* error */
			log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
			return FDEVENT_HANDLED_ERROR;
		}

		if (n == 0) {
			/* read finished */

			con->file_finished = 1;

			/* send final chunk */
			http_chunk_append_mem(srv, con, NULL, 0);
			joblist_append(srv, con);

			return FDEVENT_HANDLED_FINISHED;
		}

		hctx->response->ptr[n] = '\0';
		hctx->response->used = n+1;

		/* split header from body */

		if (con->file_started == 0) {
			int is_header = 0;
			int is_header_end = 0;
			size_t last_eol = 0;
			size_t i;

			buffer_append_string_buffer(hctx->response_header, hctx->response);

			/**
			 * we have to handle a few cases:
			 *
			 * nph:
			 * 
			 *   HTTP/1.0 200 Ok\n
			 *   Header: Value\n
			 *   \n
			 *
			 * CGI:
			 *   Header: Value\n
			 *   Status: 200\n
			 *   \n
			 *
			 * and different mixes of \n and \r\n combinations
			 * 
			 * Some users also forget about CGI and just send a response and hope 
			 * we handle it. No headers, no header-content seperator
			 * 
			 */
			
			/* nph (non-parsed headers) */
			if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) is_header = 1;
				
			for (i = 0; !is_header_end && i < hctx->response_header->used - 1; i++) {
				char c = hctx->response_header->ptr[i];

				switch (c) {
				case ':':
					/* we found a colon
					 *
					 * looks like we have a normal header 
					 */
					is_header = 1;
					break;
				case '\n':
					/* EOL */
					if (is_header == 0) {
						/* we got a EOL but we don't seem to got a HTTP header */

						is_header_end = 1;

						break;
					}

					/**
					 * check if we saw a \n(\r)?\n sequence 
					 */
					if (last_eol > 0 && 
					    ((i - last_eol == 1) || 
					     (i - last_eol == 2 && hctx->response_header->ptr[i - 1] == '\r'))) {
						is_header_end = 1;
						break;
					}

					last_eol = i;

					break;
				}
			}

			if (is_header_end) {
				if (!is_header) {
					/* no header, but a body */

					if (con->request.http_version == HTTP_VERSION_1_1) {
						con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
					}

					http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
					joblist_append(srv, con);
				} else {
					const char *bstart;
					size_t blen;
					
					/**
					 * i still points to the char after the terminating EOL EOL
					 *
					 * put it on the last \n again
					 */
					i--;
					
					/* the body starts after the EOL */
					bstart = hctx->response_header->ptr + (i + 1);
					blen = (hctx->response_header->used - 1) - (i + 1);
					
					/* string the last \r?\n */
					if (i > 0 && (hctx->response_header->ptr[i - 1] == '\r')) {
						i--;
					}

					hctx->response_header->ptr[i] = '\0';
					hctx->response_header->used = i + 1; /* the string + \0 */
					
					/* parse the response header */
					cgi_response_parse(srv, con, p, hctx->response_header);

					/* enable chunked-transfer-encoding */
					if (con->request.http_version == HTTP_VERSION_1_1 &&
					    !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
						con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
					}

					if (blen > 0) {
						http_chunk_append_mem(srv, con, bstart, blen + 1);
						joblist_append(srv, con);
					}
				}

				con->file_started = 1;
			}
		} else {
			http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
			joblist_append(srv, con);
		}

#if 0
		log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
#endif
	}

	return FDEVENT_HANDLED_NOT_FINISHED;
}
Пример #18
0
/**
 * 输出日志.
 * 日志的格式:
 * 		2009-11-25 22:31:25: (filename.line) information
 *
 * 	参数fmt的说明如下:
 *  's':字符串   'b':buffer   'd':int   'o':off_t   'x':int的十六进制
 *  上面的几个参数,在输出相应的值后都追加一个空格' '。
 *  如果参数为大写,则不追加空格。
 *
 */
int log_error_write(server * srv, const char *filename, unsigned int line,
                    const char *fmt, ...)
{
    pthread_mutex_lock(&srv -> log_lock);
    va_list ap;

    switch (srv->errorlog_mode)
    {
    case ERRORLOG_FILE:
    case ERRORLOG_STDERR:
        /*
         * 日志文件和标准错误输出要设定日志的时间。
         */
        if (srv->cur_ts != srv->last_generated_debug_ts)
        {
            buffer_prepare_copy(srv->ts_debug_str, 1024);
            strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1,
                     "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
            srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;

            srv->last_generated_debug_ts = srv->cur_ts;
        }

        buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str);
        buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(": ("));
        break;
    case ERRORLOG_SYSLOG:
        /*
         * syslog自己产生时间
         */
        buffer_copy_string_len(srv->errorlog_buf, CONST_STR_LEN("("));
        break;
    }

    buffer_append_string(srv->errorlog_buf, filename);
    buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("."));
    buffer_append_long(srv->errorlog_buf, line);
    buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(") "));

    //根据字符串fmt来遍历可变参数。
    for (va_start(ap, fmt); *fmt; fmt++)
    {
        int d;
        char *s;
        buffer *b;
        off_t o;

        switch (*fmt)
        {
        case 's':				/* string */
            s = va_arg(ap, char *);
            buffer_append_string(srv->errorlog_buf, s);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
            break;
        case 'b':				/* buffer */
            b = va_arg(ap, buffer *);
            buffer_append_string_buffer(srv->errorlog_buf, b);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
            break;
        case 'd':				/* int */
            d = va_arg(ap, int);
            buffer_append_long(srv->errorlog_buf, d);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
            break;
        case 'o':				/* off_t */
            o = va_arg(ap, off_t);
            buffer_append_off_t(srv->errorlog_buf, o);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
            break;
        case 'x':				/* int (hex) */
            d = va_arg(ap, int);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
            buffer_append_long_hex(srv->errorlog_buf, d);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN(" "));
            break;
        case 'S':				/* string */
            s = va_arg(ap, char *);
            buffer_append_string(srv->errorlog_buf, s);
            break;
        case 'B':				/* buffer */
            b = va_arg(ap, buffer *);
            buffer_append_string_buffer(srv->errorlog_buf, b);
            break;
        case 'D':				/* int */
            d = va_arg(ap, int);
            buffer_append_long(srv->errorlog_buf, d);
            break;
        case 'O':				/* off_t */
            o = va_arg(ap, off_t);
            buffer_append_off_t(srv->errorlog_buf, o);
            break;
        case 'X':				/* int (hex) */
            d = va_arg(ap, int);
            buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("0x"));
            buffer_append_long_hex(srv->errorlog_buf, d);
            break;
        case '(':
        case ')':
        case '<':
        case '>':
        case ',':
        case ' ':
            buffer_append_string_len(srv->errorlog_buf, fmt, 1);
            break;
        }
    }
    va_end(ap);

    switch (srv->errorlog_mode)
    {
    case ERRORLOG_FILE:
        buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
        write(srv->errorlog_fd, srv->errorlog_buf->ptr,
              srv->errorlog_buf->used - 1);
        break;
    case ERRORLOG_STDERR:
        buffer_append_string_len(srv->errorlog_buf, CONST_STR_LEN("\n"));
        write(STDERR_FILENO, srv->errorlog_buf->ptr,
              srv->errorlog_buf->used - 1);
        break;
    case ERRORLOG_SYSLOG:
        syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
        break;
    }

    pthread_mutex_unlock(&srv -> log_lock);

    return 0;
}
Пример #19
0
int parse_umd_chapters(const char *umdfile, p_umd_chapter * pchapter)
{
	//int ret = -1;
	SceUID fd = -1;
	SceIoStat sta;
	buffer *pRaw = NULL;
	buffer *pzbuf = NULL;

	do {
		size_t stHeadSize = sizeof(struct UMDHeaderData);
		size_t stHeadExSize = sizeof(struct UMDHeaderDataEx);
		char *p;
		int Reserve;
		struct UMDHeaderData *pHead;
		struct UMDHeaderDataEx *pHeadEx;
		u_int i;
		size_t stlen;

		if (!umdfile || !pchapter || !(*pchapter))
			break;
		if (sceIoGetstat(umdfile, &sta) < 0) {
			return -1;
		}
		if ((fd = sceIoOpen(umdfile, PSP_O_RDONLY, 0777)) < 0) {
			return -2;
		}

		pRaw = buffer_init();

		if (pRaw == NULL)
			break;

		buffer_prepare_copy(pRaw, (10240 > sta.st_size) ? sta.st_size : 10240);

		pRaw->used = pRaw->size;
		if (0 > read_umd_buf(fd, &pRaw)) {
			//dbg_printf(d, "%s not start with 0xde9a9b89,that umd must be corrupted!",__func__);
			break;
		}

		p = pRaw->ptr;
		Reserve = *(int *) p;

		if (Reserve != (int) 0xde9a9b89 || *(p + sizeof(int)) != '#') {
			//dbg_printf(d, "%s not start with 0xde9a9b89,or not start with '#',that umd must be corrupted!",__func__);
			buffer_free(pRaw);
			break;
		}
		(*pchapter)->filesize = sta.st_size;
		buf_offset = sizeof(int);
		umdfile_offset = buf_offset;
		umdfile_remain = sta.st_size - buf_offset;
		pHead = NULL;
		pHeadEx = NULL;

		////dbg_printf(d,"%s start to parse\n",__func__);
		while (umdfile_remain > 0) {
			if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadSize))
				break;
			pHead = (struct UMDHeaderData *) p;
			if (pHead->Mark != '#' || pHead->Length < stHeadSize) {
				//dbg_printf(d, "%s head corrupted,flag:%c,length:%d!",__func__,pHead->Flag,pHead->Length);
				break;
			}
			if (pHead->hdType == 0x0e || pHead->hdType == 0x0f) {
				size_t stChapterCount;
				bool bchapterless;	//no chapters listed
				struct t_chapter *pchap;

				/*if((14 == hdType && 2 != (*pchapter)->umd_mode) || (15 == hdType && 3 != (*pchapter)->umd_mode) || *(*pSe) != '$')
				   {
				   ////dbg_printf(d,"%s umd mode:%d not fit for hdType %d or not start from $\n",__func__,(*pchapter)->umd_mode,hdType);
				   break;
				   } */
				if (0 > get_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize))
					break;
				memcpy(&(*pchapter)->umd_mode, p, 1);
				//cout << "umd mode:" << (*pchapter)->umd_mode << endl;
				if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadExSize))
					break;
				stChapterCount = (*pchapter)->chapter_count;
				bchapterless = false;	//no chapters listed
				pchap = (*pchapter)->pchapters;

				if (1 > stChapterCount) {
					bchapterless = true;
					stChapterCount = 16;
					(*pchapter)->pchapters = (struct t_chapter *) calloc(stChapterCount, sizeof(struct t_chapter));
					if (!(*pchapter)->pchapters)
						break;
					pchap = (*pchapter)->pchapters;
					for (i = 0; i < stChapterCount; i++) {
						if (!(pchap[i].name = buffer_init()))
							return -4;
						pchap[i].length = 1;
					}
				} else if (!(*pchapter)->pchapters)
					break;
				if (*p == '$')
					(*pchapter)->content_pos = umdfile_offset - 9;
				i = 0;
				while (*p == '$') {
					if (bchapterless) {
						if (i >= stChapterCount) {
							stChapterCount += 16;
							(*pchapter)->pchapters = (struct t_chapter *)
								realloc((*pchapter)->pchapters, stChapterCount * sizeof(struct t_chapter));
							if (!(*pchapter)->pchapters)
								break;
							pchap = (*pchapter)->pchapters;
						}
						if (!(pchap[i].name = buffer_init()))
							break;
						buffer_prepare_copy(pchap[i].name, 7);
						memcpy(pchap[i].name->ptr, "i\0m\0g\0", 6);
						pchap[i].name->ptr[6] = '\0';
						pchap[i].name->used = 7;
					} else if (i >= stChapterCount) {
						//dbg_printf(d,"%s get img chapters %d more than list %d",__func__,i,stChapterCount);
						buffer_free(pRaw);
						sceIoClose(fd);
						return i + 1;
					}
					pHeadEx = (struct UMDHeaderDataEx *) p;
					stlen = pHeadEx->Length;
					if (stlen < 9) {
						////dbg_printf(d,"%s zipLength %d  < 9",__func__,ZipLength);
						break;
					}
					printf("img:%d pos:%d\n", i, umdfile_offset - 9);
					pchap[i++].chunk_pos = umdfile_offset - 9;
					stlen -= 9;
					if (0 > get_chunk_buf(fd, &pRaw, &p, stlen))
						break;
					//cout << "img:" << i++ << " len:" << stlen << endl;
					if (*(pRaw->ptr + buf_offset) == '#') {
						if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadSize))
							break;
						pHead = (struct UMDHeaderData *) p;
						if (pHead->hdType == 10) {
							if (0 > get_offset_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize, stHeadExSize))
								break;
							//cout << "skip chunk" << endl;
						} else if (pHead->hdType == 0x81) {
							if (bchapterless && i < stChapterCount) {
								stChapterCount = i;
								(*pchapter)->pchapters = (struct t_chapter *)
									realloc((*pchapter)->pchapters, stChapterCount * sizeof(struct t_chapter));
								if (!(*pchapter)->pchapters)
									break;
								(*pchapter)->chapter_count = i;
							}
							//cout << "parse done" << endl;
							buffer_free(pRaw);
							sceIoClose(fd);
							return i + 1;
						}
					} else {
						if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadExSize))
							break;
					}
				}
				buffer_free(pRaw);
				sceIoClose(fd);
				return -1;
			} else if (pHead->hdType == 0x83) {
				size_t stChapterCount;

				if (0 > get_offset_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize, stHeadExSize))
					break;
				pHeadEx = (struct UMDHeaderDataEx *) p;
				if (pHeadEx->Length < stHeadExSize)
					break;
				stChapterCount = (pHeadEx->Length - stHeadExSize) / 4;

				if (0 < stChapterCount) {
					struct t_chapter *pchap;

					if (0 > get_chunk_buf(fd, &pRaw, &p, pHeadEx->Length - stHeadExSize))
						break;
					(*pchapter)->chapter_count = stChapterCount;
					(*pchapter)->pchapters = (struct t_chapter *) calloc(stChapterCount, sizeof(struct t_chapter));
					if (!(*pchapter)->pchapters)
						break;

					pchap = (*pchapter)->pchapters;

					for (i = 0; i < stChapterCount; i++) {
						if (!(pchap[i].name = buffer_init()))
							return -4;
						memcpy(&pchap[i].length, p, sizeof(u_int));
						p += 4;
					}
				} else
					continue;
			} else if (pHead->hdType == 0x84) {
				struct t_chapter *pchap;
				size_t stChapterCount;
				size_t stcontent_length = 0;
				bool bok = true;
				size_t stoutlen = 0;
				size_t stUnzipSize = 0;

				if (0 > get_offset_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize, stHeadExSize))
					break;
				pHeadEx = (struct UMDHeaderDataEx *) p;
				if (pHeadEx->Length < stHeadExSize)
					break;
				if (0 > get_chunk_buf(fd, &pRaw, &p, pHeadEx->Length - stHeadExSize))
					break;

				pchap = (*pchapter)->pchapters;
				stChapterCount = (*pchapter)->chapter_count;

				if (0 < stChapterCount) {
					for (i = 0; i < stChapterCount; i++) {
						stlen = *(u8 *) p;
						p += 1;
						buffer_copy_string_len(pchap[i].name, p, stlen);
						////dbg_printf(d,"%dth chapter name:%s\n",i,pchap[i].name->ptr);
						p += stlen;
					}
				}

				if (0x01 != (*pchapter)->umd_type)
					continue;
				if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadExSize))
					break;
				i = 0;

				if (*p == '$')
					(*pchapter)->content_pos = umdfile_offset - 9;

				pchap = (*pchapter)->pchapters;
				pzbuf = buffer_init();

				if (!pzbuf)
					break;
				while (*p == '$') {
					bok = false;
					pHeadEx = (struct UMDHeaderDataEx *) p;
					stlen = pHeadEx->Length;
					if (stlen < 9) {
						////dbg_printf(d,"%s zipLength %d  < 9",__func__,ZipLength);
						break;
					}
					//pchap[i++].pos = umdfile_offset - 9;
					stlen -= 9;
					stoutlen = stlen * 2;
					buffer_prepare_copy(pzbuf, stoutlen);
					if (0 > get_chunk_buf(fd, &pRaw, &p, stlen))
						break;
					stUnzipSize = umd_inflate((Byte *) p, (Byte *) pzbuf->ptr, stlen, stoutlen);
					if (stUnzipSize < 0 || stUnzipSize > stoutlen) {
						printf("stUnzipSize %d not in limit size:%d", stUnzipSize, stoutlen);
						break;
					}
					//stcontent_length += stlen;
					//for(;i < stChapterCount;i++)
					while (i < stChapterCount && pchap[i].length <= stcontent_length + stUnzipSize) {
						pchap[i].chunk_pos = umdfile_offset - 9 - stlen;
						pchap[i].chunk_offset = pchap[i].length - stcontent_length;
						if (i > 0)
							pchap[i - 1].length = pchap[i].length - pchap[i - 1].length;
						printf("%dth pos:%d offset:%d,cur len:%d\n", i, pchap[i].chunk_pos, pchap[i].length, stcontent_length);
						++i;
					}
					stcontent_length += stUnzipSize;
					if (i >= stChapterCount) {
						pchap[stChapterCount - 1].length = (*pchapter)->filesize - pchap[stChapterCount - 1].length;
						printf("x total %d pos fileoffset:%d\n", i, umdfile_offset);
						if (pzbuf)
							buffer_free(pzbuf);
						buffer_free(pRaw);
						sceIoClose(fd);
						return stChapterCount + 1;
					}
					if (*(pRaw->ptr + buf_offset) == '#') {
						bok = true;
						while (*(pRaw->ptr + buf_offset) == '#') {
							if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadSize)) {
								bok = false;
								break;
							}
							pHead = (struct UMDHeaderData *) p;
							if (pHead->hdType == 0xf1 || pHead->hdType == 10) {
								if (*(pRaw->ptr + buf_offset + pHead->Length - stHeadSize) == '#') {
									if (0 > get_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize)) {
										bok = false;
										break;
									}
								} else {
									if (0 > get_offset_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize, stHeadExSize))
										bok = false;
									break;
								}
							} else if (pHead->hdType == 0x81) {
								printf("total %d pos fileoffset:%d\n", i, umdfile_offset);
								if (pzbuf)
									buffer_free(pzbuf);
								buffer_free(pRaw);
								sceIoClose(fd);
								return stChapterCount + 1;
							}
						}
						if (!bok)
							break;
					} else {
						if (0 > get_chunk_buf(fd, &pRaw, &p, stHeadExSize))
							break;
					}
				}

			} else {
				if (0 > get_chunk_buf(fd, &pRaw, &p, pHead->Length - stHeadSize))
					break;
				if (0x01 == pHead->hdType)
					memcpy(&(*pchapter)->umd_type, p, 1);
				else if (0x0b == pHead->hdType)
					memcpy(&(*pchapter)->filesize, p, 4);
			}
			if (*p == '$') {
				//stbuf_offset += stHeadSize;
				//pRaw->used = 4;
				if (0 > get_chunk_buf(fd, &pRaw, &p, 4))
					break;
				//pHeadEx->Length = *(u_int*)p;
				//memcpy((char*)&pHeadEx->Length ,p,sizeof(u_int));
				memcpy((char *) &i, p, sizeof(u_int));
				if (9 > i || 0 > get_chunk_buf(fd, &pRaw, &p, i - stHeadExSize))
					break;
			}
		}

	} while (false);
	if (pRaw)
		buffer_free(pRaw);
	if (fd > 0)
		sceIoClose(fd);
	return 1;
}
Пример #20
0
static int proxy_demux_response(server *srv, handler_ctx *hctx) {
	int fin = 0;
	int b;
	ssize_t r;

	plugin_data *p    = hctx->plugin_data;
	connection *con   = hctx->remote_conn;
	int proxy_fd       = hctx->fd;

	/* check how much we have to read */
	if (ioctl(hctx->fd, FIONREAD, &b)) {
		log_error_write(srv, __FILE__, __LINE__, "sd",
				"ioctl failed: ",
				proxy_fd);
		return -1;
	}


	if (p->conf.debug) {
		log_error_write(srv, __FILE__, __LINE__, "sd",
			       "proxy - have to read:", b);
	}

	if (b > 0) {
		if (hctx->response->used == 0) {
			/* avoid too small buffer */
			buffer_prepare_append(hctx->response, b + 1);
			hctx->response->used = 1;
		} else {
			buffer_prepare_append(hctx->response, b);
		}

		if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
			if (errno == EAGAIN) return 0;
			log_error_write(srv, __FILE__, __LINE__, "sds",
					"unexpected end-of-file (perhaps the proxy process died):",
					proxy_fd, strerror(errno));
			return -1;
		}

		/* this should be catched by the b > 0 above */
		assert(r);

		hctx->response->used += r;
		hctx->response->ptr[hctx->response->used - 1] = '\0';

#if 0
		log_error_write(srv, __FILE__, __LINE__, "sdsbs",
				"demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
#endif

		if (0 == con->got_response) {
			con->got_response = 1;
			buffer_prepare_copy(hctx->response_header, 128);
		}

		if (0 == con->file_started) {
			char *c;

			/* search for the \r\n\r\n in the string */
			if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
				size_t hlen = c - hctx->response->ptr + 4;
				size_t blen = hctx->response->used - hlen - 1;
				/* found */

				buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
#endif
				/* parse the response header */
				proxy_response_parse(srv, con, p, hctx->response_header);

				/* enable chunked-transfer-encoding */
				if (con->request.http_version == HTTP_VERSION_1_1 &&
				    !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
					con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
				}

				con->file_started = 1;
				if (blen) {
					http_chunk_append_mem(srv, con, c + 4, blen + 1);
				}
				hctx->response->used = 0;
				joblist_append(srv, con);
			}
		} else {
			http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
			joblist_append(srv, con);
			hctx->response->used = 0;
		}

	} else {
		/* reading from upstream done */
		con->file_finished = 1;

		http_chunk_append_mem(srv, con, NULL, 0);
		joblist_append(srv, con);

		fin = 1;
	}

	return fin;
}
Пример #21
0
static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, const char **l, size_t n, stat_cache_entry *sce) {
	size_t i, ssicmd = 0;
	char buf[255];
	buffer *b = NULL;

	struct {
		const char *var;
		enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
				SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
				SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
	} ssicmds[] = {
		{ "echo",     SSI_ECHO },
		{ "include",  SSI_INCLUDE },
		{ "flastmod", SSI_FLASTMOD },
		{ "fsize",    SSI_FSIZE },
		{ "config",   SSI_CONFIG },
		{ "printenv", SSI_PRINTENV },
		{ "set",      SSI_SET },
		{ "if",       SSI_IF },
		{ "elif",     SSI_ELIF },
		{ "endif",    SSI_ENDIF },
		{ "else",     SSI_ELSE },
		{ "exec",     SSI_EXEC },

		{ NULL, SSI_UNSET }
	};

	for (i = 0; ssicmds[i].var; i++) {
		if (0 == strcmp(l[1], ssicmds[i].var)) {
			ssicmd = ssicmds[i].type;
			break;
		}
	}

	switch(ssicmd) {
	case SSI_ECHO: {
		/* echo */
		int var = 0;
		/* int enc = 0; */
		const char *var_val = NULL;

		struct {
			const char *var;
			enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
					SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
		} echovars[] = {
			{ "DATE_GMT",      SSI_ECHO_DATE_GMT },
			{ "DATE_LOCAL",    SSI_ECHO_DATE_LOCAL },
			{ "DOCUMENT_NAME", SSI_ECHO_DOCUMENT_NAME },
			{ "DOCUMENT_URI",  SSI_ECHO_DOCUMENT_URI },
			{ "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
			{ "USER_NAME",     SSI_ECHO_USER_NAME },

			{ NULL, SSI_ECHO_UNSET }
		};

/*
		struct {
			const char *var;
			enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
		} encvars[] = {
			{ "url",          SSI_ENC_URL },
			{ "none",         SSI_ENC_NONE },
			{ "entity",       SSI_ENC_ENTITY },

			{ NULL, SSI_ENC_UNSET }
		};
*/

		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "var")) {
				int j;

				var_val = l[i+1];

				for (j = 0; echovars[j].var; j++) {
					if (0 == strcmp(l[i+1], echovars[j].var)) {
						var = echovars[j].type;
						break;
					}
				}
			} else if (0 == strcmp(l[i], "encoding")) {
/*
				int j;

				for (j = 0; encvars[j].var; j++) {
					if (0 == strcmp(l[i+1], encvars[j].var)) {
						enc = encvars[j].type;
						break;
					}
				}
*/
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}

		if (p->if_is_false) break;

		if (!var_val) {
			log_error_write(srv, __FILE__, __LINE__, "sss",
					"ssi: ",
					l[1], "var is missing");
			break;
		}

		switch(var) {
		case SSI_ECHO_USER_NAME: {
			struct passwd *pw;

			b = chunkqueue_get_append_buffer(con->write_queue);
#ifdef HAVE_PWD_H
			if (NULL == (pw = getpwuid(sce->st.st_uid))) {
				buffer_copy_long(b, sce->st.st_uid);
			} else {
				buffer_copy_string(b, pw->pw_name);
			}
#else
			buffer_copy_long(b, sce->st.st_uid);
#endif
			break;
		}
		case SSI_ECHO_LAST_MODIFIED:	{
			time_t t = sce->st.st_mtime;

			b = chunkqueue_get_append_buffer(con->write_queue);
			if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
				buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
			} else {
				buffer_copy_string(b, buf);
			}
			break;
		}
		case SSI_ECHO_DATE_LOCAL: {
			time_t t = time(NULL);

			b = chunkqueue_get_append_buffer(con->write_queue);
			if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
				buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
			} else {
				buffer_copy_string(b, buf);
			}
			break;
		}
		case SSI_ECHO_DATE_GMT: {
			time_t t = time(NULL);

			b = chunkqueue_get_append_buffer(con->write_queue);
			if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
				buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
			} else {
				buffer_copy_string(b, buf);
			}
			break;
		}
		case SSI_ECHO_DOCUMENT_NAME: {
			char *sl;

			b = chunkqueue_get_append_buffer(con->write_queue);
			if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
				buffer_copy_string_buffer(b, con->physical.path);
			} else {
				buffer_copy_string(b, sl + 1);
			}
			break;
		}
		case SSI_ECHO_DOCUMENT_URI: {
			b = chunkqueue_get_append_buffer(con->write_queue);
			buffer_copy_string_buffer(b, con->uri.path);
			break;
		}
		default: {
			data_string *ds;
			/* check if it is a cgi-var */

			b = chunkqueue_get_append_buffer(con->write_queue);

			if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
				buffer_copy_string_buffer(b, ds->value);
			} else {
				buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
			}

			break;
		}
		}
		break;
	}
	case SSI_INCLUDE:
	case SSI_FLASTMOD:
	case SSI_FSIZE: {
		const char * file_path = NULL, *virt_path = NULL;
		struct stat st;
		char *sl;

		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "file")) {
				file_path = l[i+1];
			} else if (0 == strcmp(l[i], "virtual")) {
				virt_path = l[i+1];
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}

		if (!file_path && !virt_path) {
			log_error_write(srv, __FILE__, __LINE__, "sss",
					"ssi: ",
					l[1], "file or virtual are missing");
			break;
		}

		if (file_path && virt_path) {
			log_error_write(srv, __FILE__, __LINE__, "sss",
					"ssi: ",
					l[1], "only one of file and virtual is allowed here");
			break;
		}


		if (p->if_is_false) break;

		if (file_path) {
			/* current doc-root */
			if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
				buffer_copy_string_len(p->stat_fn, CONST_STR_LEN("/"));
			} else {
				buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
			}

			buffer_copy_string(srv->tmp_buf, file_path);
			buffer_urldecode_path(srv->tmp_buf);
			buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
			buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
		} else {
			/* virtual */

			if (virt_path[0] == '/') {
				buffer_copy_string(p->stat_fn, virt_path);
			} else {
				/* there is always a / */
				sl = strrchr(con->uri.path->ptr, '/');

				buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
				buffer_append_string(p->stat_fn, virt_path);
			}

			buffer_urldecode_path(p->stat_fn);
			buffer_path_simplify(srv->tmp_buf, p->stat_fn);

			/* we have an uri */

			buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
			buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
		}

		if (0 == stat(p->stat_fn->ptr, &st)) {
			time_t t = st.st_mtime;

			switch (ssicmd) {
			case SSI_FSIZE:
				b = chunkqueue_get_append_buffer(con->write_queue);
				if (p->sizefmt) {
					int j = 0;
					const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };

					off_t s = st.st_size;

					for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);

					buffer_copy_off_t(b, s);
					buffer_append_string(b, abr[j]);
				} else {
					buffer_copy_off_t(b, st.st_size);
				}
				break;
			case SSI_FLASTMOD:
				b = chunkqueue_get_append_buffer(con->write_queue);
				if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
					buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
				} else {
					buffer_copy_string(b, buf);
				}
				break;
			case SSI_INCLUDE:
				chunkqueue_append_file(con->write_queue, p->stat_fn, 0, st.st_size);

				/* Keep the newest mtime of included files */
				if (st.st_mtime > include_file_last_mtime)
				  include_file_last_mtime = st.st_mtime;

				break;
			}
		} else {
			log_error_write(srv, __FILE__, __LINE__, "sbs",
					"ssi: stating failed ",
					p->stat_fn, strerror(errno));
		}
		break;
	}
	case SSI_SET: {
		const char *key = NULL, *val = NULL;
		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "var")) {
				key = l[i+1];
			} else if (0 == strcmp(l[i], "value")) {
				val = l[i+1];
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}

		if (p->if_is_false) break;

		if (key && val) {
			data_string *ds;

			if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
				ds = data_string_init();
			}
			buffer_copy_string(ds->key,   key);
			buffer_copy_string(ds->value, val);

			array_insert_unique(p->ssi_vars, (data_unset *)ds);
		} else {
			log_error_write(srv, __FILE__, __LINE__, "sss",
					"ssi: var and value have to be set in",
					l[0], l[1]);
		}
		break;
	}
	case SSI_CONFIG:
		if (p->if_is_false) break;

		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "timefmt")) {
				buffer_copy_string(p->timefmt, l[i+1]);
			} else if (0 == strcmp(l[i], "sizefmt")) {
				if (0 == strcmp(l[i+1], "abbrev")) {
					p->sizefmt = 1;
				} else if (0 == strcmp(l[i+1], "abbrev")) {
					p->sizefmt = 0;
				} else {
					log_error_write(srv, __FILE__, __LINE__, "sssss",
							"ssi: unknow value for attribute '",
							l[i],
							"' for ",
							l[1], l[i+1]);
				}
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}
		break;
	case SSI_PRINTENV:
		if (p->if_is_false) break;

		b = chunkqueue_get_append_buffer(con->write_queue);
		for (i = 0; i < p->ssi_vars->used; i++) {
			data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];

			buffer_append_string_buffer(b, ds->key);
			buffer_append_string_len(b, CONST_STR_LEN("="));
			buffer_append_string_encoded(b, CONST_BUF_LEN(ds->value), ENCODING_MINIMAL_XML);
			buffer_append_string_len(b, CONST_STR_LEN("\n"));
		}
		for (i = 0; i < p->ssi_cgi_env->used; i++) {
			data_string *ds = (data_string *)p->ssi_cgi_env->data[p->ssi_cgi_env->sorted[i]];

			buffer_append_string_buffer(b, ds->key);
			buffer_append_string_len(b, CONST_STR_LEN("="));
			buffer_append_string_encoded(b, CONST_BUF_LEN(ds->value), ENCODING_MINIMAL_XML);
			buffer_append_string_len(b, CONST_STR_LEN("\n"));
		}

		break;
	case SSI_EXEC: {
		const char *cmd = NULL;
		pid_t pid;
		int from_exec_fds[2];

		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "cmd")) {
				cmd = l[i+1];
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}

		if (p->if_is_false) break;

		/* create a return pipe and send output to the html-page
		 *
		 * as exec is assumed evil it is implemented synchronously
		 */

		if (!cmd) break;
#ifdef HAVE_FORK
		if (pipe(from_exec_fds)) {
			log_error_write(srv, __FILE__, __LINE__, "ss",
					"pipe failed: ", strerror(errno));
			return -1;
		}

		/* fork, execve */
		switch (pid = fork()) {
		case 0: {
			/* move stdout to from_rrdtool_fd[1] */
			close(STDOUT_FILENO);
			dup2(from_exec_fds[1], STDOUT_FILENO);
			close(from_exec_fds[1]);
			/* not needed */
			close(from_exec_fds[0]);

			/* close stdin */
			close(STDIN_FILENO);

			execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);

			log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);

			/* */
			SEGFAULT();
			break;
		}
		case -1:
			/* error */
			log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
			break;
		default: {
			/* father */
			int status;
			ssize_t r;
			int was_interrupted = 0;

			close(from_exec_fds[1]);

			/* wait for the client to end */

			/*
			 * OpenBSD and Solaris send a EINTR on SIGCHILD even if we ignore it
			 */
			do {
				if (-1 == waitpid(pid, &status, 0)) {
					if (errno == EINTR) {
						was_interrupted++;
					} else {
						was_interrupted = 0;
						log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
					}
				} else if (WIFEXITED(status)) {
					int toread;
					/* read everything from client and paste it into the output */
					was_interrupted = 0;
	
					while(1) {
						if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
							log_error_write(srv, __FILE__, __LINE__, "s",
								"unexpected end-of-file (perhaps the ssi-exec process died)");
							return -1;
						}
	
						if (toread > 0) {
							b = chunkqueue_get_append_buffer(con->write_queue);
	
							buffer_prepare_copy(b, toread + 1);
	
							if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
								/* read failed */
								break;
							} else {
								b->used = r;
								b->ptr[b->used++] = '\0';
							}
						} else {
							break;
						}
					}
				} else {
					was_interrupted = 0;
					log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
				}
			} while (was_interrupted > 0 && was_interrupted < 4); /* if waitpid() gets interrupted, retry, but max 4 times */

			close(from_exec_fds[0]);

			break;
		}
		}
#else

		return -1;
#endif

		break;
	}
	case SSI_IF: {
		const char *expr = NULL;

		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "expr")) {
				expr = l[i+1];
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}

		if (!expr) {
			log_error_write(srv, __FILE__, __LINE__, "sss",
					"ssi: ",
					l[1], "expr missing");
			break;
		}

		if ((!p->if_is_false) &&
		    ((p->if_is_false_level == 0) ||
		     (p->if_level < p->if_is_false_level))) {
			switch (ssi_eval_expr(srv, con, p, expr)) {
			case -1:
			case 0:
				p->if_is_false = 1;
				p->if_is_false_level = p->if_level;
				break;
			case 1:
				p->if_is_false = 0;
				break;
			}
		}

		p->if_level++;

		break;
	}
	case SSI_ELSE:
		p->if_level--;

		if (p->if_is_false) {
			if ((p->if_level == p->if_is_false_level) &&
			    (p->if_is_false_endif == 0)) {
				p->if_is_false = 0;
			}
		} else {
			p->if_is_false = 1;

			p->if_is_false_level = p->if_level;
		}
		p->if_level++;

		break;
	case SSI_ELIF: {
		const char *expr = NULL;
		for (i = 2; i < n; i += 2) {
			if (0 == strcmp(l[i], "expr")) {
				expr = l[i+1];
			} else {
				log_error_write(srv, __FILE__, __LINE__, "sss",
						"ssi: unknow attribute for ",
						l[1], l[i]);
			}
		}

		if (!expr) {
			log_error_write(srv, __FILE__, __LINE__, "sss",
					"ssi: ",
					l[1], "expr missing");
			break;
		}

		p->if_level--;

		if (p->if_level == p->if_is_false_level) {
			if ((p->if_is_false) &&
			    (p->if_is_false_endif == 0)) {
				switch (ssi_eval_expr(srv, con, p, expr)) {
				case -1:
				case 0:
					p->if_is_false = 1;
					p->if_is_false_level = p->if_level;
					break;
				case 1:
					p->if_is_false = 0;
					break;
				}
			} else {
				p->if_is_false = 1;
				p->if_is_false_level = p->if_level;
				p->if_is_false_endif = 1;
			}
		}

		p->if_level++;

		break;
	}
	case SSI_ENDIF:
		p->if_level--;

		if (p->if_level == p->if_is_false_level) {
			p->if_is_false = 0;
			p->if_is_false_endif = 0;
		}

		break;
	default:
		log_error_write(srv, __FILE__, __LINE__, "ss",
				"ssi: unknow ssi-command:",
				l[1]);
		break;
	}

	return 0;

}
Пример #22
0
int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq, off_t max_bytes) {
	chunk *c;

	for(c = cq->first; (max_bytes > 0) && (NULL != c); c = c->next) {
		int chunk_finished = 0;

		switch(c->type) {
		case MEM_CHUNK: {
			char * offset;
			off_t toSend;
			ssize_t r;

			if (c->mem->used == 0) {
				chunk_finished = 1;
				break;
			}

			offset = c->mem->ptr + c->offset;
			toSend = c->mem->used - 1 - c->offset;
			if (toSend > max_bytes) toSend = max_bytes;

#ifdef __WIN32
			if ((r = send(fd, offset, toSend, 0)) < 0) {
				/* no error handling for windows... */
				log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd);

				return -1;
			}
#else
			if ((r = write(fd, offset, toSend)) < 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);

					return -1;
				}
			}
#endif

			c->offset += r;
			cq->bytes_out += r;
			max_bytes -= r;

			if (c->offset == (off_t)c->mem->used - 1) {
				chunk_finished = 1;
			}

			break;
		}
		case FILE_CHUNK: {
#ifdef USE_MMAP
			char *p = NULL;
#endif
			ssize_t r;
			off_t offset;
			off_t toSend;
			stat_cache_entry *sce = NULL;
			int ifd;

			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						strerror(errno), c->file.name);
				return -1;
			}

			offset = c->file.start + c->offset;
			toSend = c->file.length - c->offset;

			if (toSend > max_bytes) toSend = max_bytes;

			if (offset > sce->st.st_size) {
				log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);

				return -1;
			}

			if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));

				return -1;
			}

#ifdef USE_MMAP
			if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));

				close(ifd);

				return -1;
			}
			close(ifd);

			if ((r = write(fd, p + offset, toSend)) <= 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					munmap(p, sce->st.st_size);
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);
					munmap(p, sce->st.st_size);

					return -1;
				}
			}

			munmap(p, sce->st.st_size);
#else /* USE_MMAP */
			buffer_prepare_copy(srv->tmp_buf, toSend);

			if (-1 == lseek(ifd, offset, SEEK_SET)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "lseek: ", strerror(errno));
				close(ifd);
				return -1;
			}
			if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
				close(ifd);
				return -1;
			}
			close(ifd);

#ifdef __WIN32
			if ((r = send(fd, srv->tmp_buf->ptr, toSend, 0)) < 0) {
				/* no error handling for windows... */
				log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd);

				return -1;
			}
#else /* __WIN32 */
			if ((r = write(fd, srv->tmp_buf->ptr, toSend)) < 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);

					return -1;
				}
			}
#endif /* __WIN32 */
#endif /* USE_MMAP */

			c->offset += r;
			cq->bytes_out += r;
			max_bytes -= r;

			if (c->offset == c->file.length) {
				chunk_finished = 1;
			}

			break;
		}
		default:

			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");

			return -1;
		}

		if (!chunk_finished) {
			/* not finished yet */

			break;
		}
	}

	return 0;
}
Пример #23
0
static void https_add_ssl_entries(connection *con) {
	X509 *xs;
	X509_NAME *xn;
	X509_NAME_ENTRY *xe;
	int i, nentries;

	if (
		SSL_get_verify_result(con->ssl) != X509_V_OK
		|| !(xs = SSL_get_peer_certificate(con->ssl))
	) {
		return;
	}

	xn = X509_get_subject_name(xs);
	for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
		int xobjnid;
		const char * xobjsn;
		data_string *envds;

		if (!(xe = X509_NAME_get_entry(xn, i))) {
			continue;
		}
		xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe));
		xobjsn = OBJ_nid2sn(xobjnid);
		if (!xobjsn) {
			continue;
		}

		if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
			envds = data_string_init();
		}
		buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_"));
		buffer_append_string(envds->key, xobjsn);
		buffer_copy_string_len(
			envds->value,
			(const char *)xe->value->data, xe->value->length
		);
		/* pick one of the exported values as "authed user", for example
		 * ssl.verifyclient.username   = "******" or "SSL_CLIENT_S_DN_emailAddress"
		 */
		if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) {
			buffer_copy_string_buffer(con->authed_user, envds->value);
		}
		array_insert_unique(con->environment, (data_unset *)envds);
	}
	if (con->conf.ssl_verifyclient_export_cert) {
		BIO *bio;
		if (NULL != (bio = BIO_new(BIO_s_mem()))) {
			data_string *envds;
			int n;

			PEM_write_bio_X509(bio, xs);
			n = BIO_pending(bio);

			if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
				envds = data_string_init();
			}

			buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT"));
			buffer_prepare_copy(envds->value, n+1);
			BIO_read(bio, envds->value->ptr, n);
			BIO_free(bio);
			envds->value->ptr[n] = '\0';
			envds->value->used = n+1;
			array_insert_unique(con->environment, (data_unset *)envds);
		}
	}
	X509_free(xs);
}
Пример #24
0
int ReadAdditionalSession(char **pSe, buffer ** buf, p_umd_chapter * pchapter, const u_short hdType, bool b_get_chapter)
{
	u_int ulTotalLength = 0;
	struct UMDHeaderDataEx *pHead;
	u_int i = 0;

	if (!pSe || !(*pSe))
		return -1;
	if (b_get_chapter && (!pchapter || !(*pchapter)))
		return -2;

	pHead = (struct UMDHeaderDataEx *) (*pSe);

	if (!pHead || pHead->Length < 9) {
		//cout << "invalid additional length:" << pHead->Length << endl;
		return -2;
	}

	pHead->Length -= 9;

	switch (hdType) {
		case 14:
		case 15:
			{
				/*if((14 == hdType && 2 != (*pchapter)->umd_mode) || (15 == hdType && 3 != (*pchapter)->umd_mode) || *(*pSe) != '$')
				   {
				   //dbg_printf(d,"%s umd mode:%d not fit for hdType %d or not start from $\n",__func__,(*pchapter)->umd_mode,hdType);
				   break;
				   } */
				buffer *pRaw = (buffer *) calloc(1, sizeof(*pRaw));

				if (pRaw == NULL)
					return -1;
				while (*(*pSe) == '$') {
					struct UMDHeaderDataEx *pEx = (struct UMDHeaderDataEx *) (*pSe);
					u_int ZipLength = pEx->Length;
					u_int len;

					if (ZipLength < 9) {
						//dbg_printf(d,"%s zipLength %d  < 9",__func__,ZipLength);
						break;
					}

					(*pSe) += 9;
					len = ZipLength - 9;
					buffer_append_memory(*buf, *pSe, len);
					(*pSe) += len;
					ulTotalLength += len;

					if (**pSe == '#') {
						struct UMDHeaderData *ps = (struct UMDHeaderData *) (*pSe);
						if (ps->hdType == 10)
							(*pSe) += ps->Length;
						else if (ps->hdType == 0x81) {
							buffer_free(pRaw);
							return 1;
						}
					}
				}
				buffer_free(pRaw);
				break;
			}

			/*  case 130:
			   break;
			   case 0x81:
			   pHead->Length /= 4;
			   //cout << "total " << pHead->Length << " blocks" << endl;
			   for(i = 0;i < pHead->Length;i++)
			   {
			   //cout << "block " << i << " is " << *(u_int*)(*pSe) << endl;
			   (*pSe) += 4;
			   }
			   break; */
		case 0x83:
			(*pSe) += 9;
			pHead->Length /= 4;
			//cout << "total " << pHead->Length << " chapters" << endl;
			if (b_get_chapter) {
				struct t_chapter *p;

				(*pchapter)->chapter_count = pHead->Length;
				(*pchapter)->pchapters = (struct t_chapter *) calloc(pHead->Length, sizeof(struct t_chapter));
				if (!(*pchapter)->pchapters)
					return -4;
				p = (*pchapter)->pchapters;

				for (i = 0; i < pHead->Length; i++) {
					//cout << "chapter " << i << " is " << *(u_int*)(*pSe) << endl;
					if (!(p[i].name = buffer_init()))
						return -4;
					memcpy(&p[i].chunk_pos, *pSe, 4);
					(*pSe) += 4;
				}
			} else {
				for (i = 0; i < pHead->Length; i++) {
					//cout << "chapter " << i << " is " << *(u_int*)(*pSe) << endl;
					(*pSe) += 4;
				}
			}
			break;
		case 0x84:
			{
				(*pSe) += 9;
				if (b_get_chapter) {
					//cout << "total " << pHead->Length << " chapters" << endl;
					size_t stlen = (*pchapter)->chapter_count;
					size_t chapter_len = 0;
					struct t_chapter *p = (*pchapter)->pchapters;

					for (i = 0; i < stlen; i++) {
						chapter_len = *(u8 *) (*pSe);
						(*pSe) += 1;
						buffer_copy_string_len(p[i].name, *pSe, (chapter_len > 256) ? 256 : chapter_len);
						//dbg_printf(d,"%dth chapter name:%s\n",i,p[i].name->ptr);
						(*pSe) += chapter_len;
					}
					return stlen;
				} else {
					size_t stUnzipSize = 0;
					Byte *p = NULL;
					buffer *pRaw;

					(*pSe) = (*pSe) + pHead->Length;
					if (pchapter && 1 != (*pchapter)->umd_mode)
						break;
					if (*(*pSe) != '$') {
						//printlog("ms0:/PSP/GAME371/xReader/xlog.txt","not $\n");
						break;
					}

					pRaw = buffer_init();

					if (pRaw == NULL)
						return -1;
					while (*(*pSe) == '$') {
						struct UMDHeaderDataEx *pEx = (struct UMDHeaderDataEx *) (*pSe);
						u_int len;
						u_int outlen;
						u_int ZipLength = pEx->Length;

						if (ZipLength < 9) {
							//printlog("ms0:/PSP/GAME371/xReader/xlog.txt","\nzipLength  < 9");
							//printlog("ms0:/PSP/GAME371/xReader/xlog.txt",&ZipLength);
							break;
						}

						(*pSe) += 9;
						len = ZipLength - 9;
						outlen = len * 2;

						buffer_prepare_copy(pRaw, outlen);
						stUnzipSize = umd_inflate((Byte *) ((*pSe)), (Byte *) pRaw->ptr, len, outlen);
						if (stUnzipSize < 0) {
							buffer_free(pRaw);
							return -1;
						}
						p = (Byte *) pRaw->ptr;
						buffer_append_memory(*buf, pRaw->ptr, stUnzipSize);
						(*pSe) += len;
						ulTotalLength += outlen;
						if (**pSe == '#') {
							struct UMDHeaderData *ps = (struct UMDHeaderData *) (*pSe);
							if (ps->hdType == 0xf1 || ps->hdType == 10)
								(*pSe) += ps->Length;
							else if (ps->hdType == 0x81) {
								buffer_free(pRaw);
								return 1;
							}
						}
					}
					buffer_free(pRaw);
				}
			}
			break;
		default:
			(*pSe) += 9;
			(*pSe) += pHead->Length;
			break;
	}
	return 1;
}
Пример #25
0
int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
	chunk *c;
	size_t chunks_written = 0;
	fprintf(stderr,"network_write_chunkqueue_write");

	for(c = cq->first; c; c = c->next) {
		int chunk_finished = 0;

		switch(c->type) {
		case MEM_CHUNK: {
			char * offset;
			size_t toSend;
			ssize_t r;

			if (c->mem->used == 0) {
				chunk_finished = 1;
				break;
			}

			offset = c->mem->ptr + c->offset;
			toSend = c->mem->used - 1 - c->offset;
#ifdef __WIN32
			if ((r = send(fd, offset, toSend, 0)) < 0) {
				/* no error handling for windows... */
				log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd);

				return -1;
			}
#else
			if ((r = write(fd, offset, toSend)) < 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);

					return -1;
				}
			}
#endif

			c->offset += r;
			cq->bytes_out += r;

			if (c->offset == (off_t)c->mem->used - 1) {
				chunk_finished = 1;
			}

			break;
		}
		case FILE_CHUNK: {
#ifdef USE_MMAP
			char *p = NULL;
#endif
			ssize_t r;
			off_t offset;
			size_t toSend;
			stat_cache_entry *sce = NULL;
			int ifd;
			
			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						strerror(errno), c->file.name);
				return -1;
			}

			offset = c->file.start + c->offset;
			toSend = c->file.length - c->offset;

			if (offset > sce->st.st_size) {
				log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);

				return -1;
			}

			if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));

				return -1;
			}

#ifdef USE_MMAP
			if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));

				close(ifd);

				return -1;
			}
			close(ifd);

			if ((r = write(fd, p + offset, toSend)) <= 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					munmap(p, sce->st.st_size);
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);
					munmap(p, sce->st.st_size);

					return -1;
				}
			}

			munmap(p, sce->st.st_size);
#else /* USE_MMAP */
			buffer_prepare_copy(srv->tmp_buf, toSend);

			lseek(ifd, offset, SEEK_SET);
			if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
				close(ifd);

				return -1;
			}
			close(ifd);

#ifdef __WIN32
			if ((r = send(fd, srv->tmp_buf->ptr, toSend, 0)) < 0) {
				/* no error handling for windows... */
				log_error_write(srv, __FILE__, __LINE__, "ssd", "send failed: ", strerror(errno), fd);

				return -1;
			}
#else /* __WIN32 */
			if ((r = write(fd, srv->tmp_buf->ptr, toSend)) < 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);

					return -1;
				}
			}
#endif /* __WIN32 */
#endif /* USE_MMAP */

			c->offset += r;
			cq->bytes_out += r;

			if (c->offset == c->file.length) {
				chunk_finished = 1;
			}

			break;
		}

		case SMB_CHUNK: {
			ssize_t r;
			off_t offset;
			size_t toSend;
			off_t rest_len;
			stat_cache_entry *sce = NULL;
//#define BUFF_SIZE 2048			
#define BUFF_SIZE 100*1024

		
			char buff[BUFF_SIZE];
//			char *buff=NULL;
			int ifd;
			
			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
				log_error_write(srv, __FILE__, __LINE__, "sb",
						strerror(errno), c->file.name);
				Cdbg(DBE,"stat cache get entry failed");
				return -1;
			}

			offset = c->file.start + c->offset;
			toSend = (c->file.length - c->offset>BUFF_SIZE)?
			   BUFF_SIZE : c->file.length - c->offset ;

//			rest_len = c->file.length - c->offset; 
//			toSend =  
			Cdbg(DBE,"offset =%lli, toSend=%d, sce->st.st_size=%lli", offset, toSend, sce->st.st_size);

			if (offset > sce->st.st_size) {
				log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
				Cdbg(DBE,"offset > size");
				if(buff) free(buff);
				return -1;
			}

//			if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
				if (-1 == (ifd = smbc_wrapper_open(con,c->file.name->ptr, O_RDONLY, 0755))) {
					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
					Cdbg(DBE,"wrapper open failed,ifd=%d,  fn =%s, open failed =%s, errno =%d",ifd, c->file.name->ptr,strerror(errno),errno);
					return -1;
				}
			Cdbg(DBE,"ifd =%d, toSend=%d",ifd, toSend);
			smbc_wrapper_lseek(con, ifd, offset, SEEK_SET );		
			if (-1 == (toSend = smbc_wrapper_read(con, ifd, buff, toSend ))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
				smbc_wrapper_close(con, ifd);
				Cdbg(DBE,"ifd =%d,toSend =%d, errno=%s",ifd,toSend, strerror(errno));
				return -1;
			}
			Cdbg(DBE,"close ifd=%d, toSend=%d",ifd,toSend);
			smbc_wrapper_close(con, ifd);

			Cdbg(DBE,"write socket fd=%d",fd);
			if ((r = write(fd, buff, toSend)) < 0) {
				switch (errno) {
				case EAGAIN:
				case EINTR:
					r = 0;
					break;
				case EPIPE:
				case ECONNRESET:
					return -2;
				default:
					log_error_write(srv, __FILE__, __LINE__, "ssd",
						"write failed:", strerror(errno), fd);

					return -1;
				}
			}

			c->offset += r;
			cq->bytes_out += r;
			Cdbg(DBE,"r =%d",r);
			if (c->offset == c->file.length) {
				chunk_finished = 1;
			}
			break;
		}
		default:

			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");

			return -1;
		}

		if (!chunk_finished) {
			/* not finished yet */

			break;
		}

		chunks_written++;
	}

	return chunks_written;
}
Пример #26
0
static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
	struct stat st;
	int r;

	/* check if DB already exists */
	if (0 == stat(s->path_rrd->ptr, &st)) {
		/* check if it is plain file */
		if (!S_ISREG(st.st_mode)) {
			log_error_write(srv, __FILE__, __LINE__, "sb",
					"not a regular file:", s->path_rrd);
			return HANDLER_ERROR;
		}

		/* still create DB if it's empty file */
		if (st.st_size > 0) {
			return HANDLER_GO_ON;
		}
	}

	/* create a new one */
	buffer_copy_string_len(p->cmd, CONST_STR_LEN("create "));
	buffer_append_string_buffer(p->cmd, s->path_rrd);
	buffer_append_string_len(p->cmd, CONST_STR_LEN(
		" --step 60 "
		"DS:InOctets:ABSOLUTE:600:U:U "
		"DS:OutOctets:ABSOLUTE:600:U:U "
		"DS:Requests:ABSOLUTE:600:U:U "
		"RRA:AVERAGE:0.5:1:600 "
		"RRA:AVERAGE:0.5:6:700 "
		"RRA:AVERAGE:0.5:24:775 "
		"RRA:AVERAGE:0.5:288:797 "
		"RRA:MAX:0.5:1:600 "
		"RRA:MAX:0.5:6:700 "
		"RRA:MAX:0.5:24:775 "
		"RRA:MAX:0.5:288:797 "
		"RRA:MIN:0.5:1:600 "
		"RRA:MIN:0.5:6:700 "
		"RRA:MIN:0.5:24:775 "
		"RRA:MIN:0.5:288:797\n"));

	if (-1 == (safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
		log_error_write(srv, __FILE__, __LINE__, "ss",
			"rrdtool-write: failed", strerror(errno));

		return HANDLER_ERROR;
	}

	buffer_prepare_copy(p->resp, 4096);
	if (-1 == (r = safe_read(p->read_fd, p->resp->ptr, p->resp->size))) {
		log_error_write(srv, __FILE__, __LINE__, "ss",
			"rrdtool-read: failed", strerror(errno));

		return HANDLER_ERROR;
	}

	p->resp->used = r;

	if (p->resp->ptr[0] != 'O' ||
		p->resp->ptr[1] != 'K') {
		log_error_write(srv, __FILE__, __LINE__, "sbb",
			"rrdtool-response:", p->cmd, p->resp);

		return HANDLER_ERROR;
	}

	return HANDLER_GO_ON;
}
Пример #27
0
static int connection_handle_read_ssl(server *srv, connection *con) {
#ifdef USE_OPENSSL
	int r, ssl_err, len;
	buffer *b = NULL;

	if (!con->conf.is_ssl) return -1;

	/* don't resize the buffer if we were in SSL_ERROR_WANT_* */

	ERR_clear_error();
	do {
		if (!con->ssl_error_want_reuse_buffer) {
			b = buffer_init();
			buffer_prepare_copy(b, SSL_pending(con->ssl) + (16 * 1024)); /* the pending bytes + 16kb */

			/* overwrite everything with 0 */
			memset(b->ptr, 0, b->size);
		} else {
			b = con->ssl_error_want_reuse_buffer;
		}

		len = SSL_read(con->ssl, b->ptr, b->size - 1);
		con->ssl_error_want_reuse_buffer = NULL; /* reuse it only once */

		if (len > 0) {
			b->used = len;
			b->ptr[b->used++] = '\0';

		       	/* we move the buffer to the chunk-queue, no need to free it */

			chunkqueue_append_buffer_weak(con->read_queue, b);
			con->bytes_read += len;
			b = NULL;
		}
	} while (len > 0);


	if (len < 0) {
		switch ((r = SSL_get_error(con->ssl, len))) {
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
			con->is_readable = 0;
			con->ssl_error_want_reuse_buffer = b;

			b = NULL;

			/* we have to steal the buffer from the queue-queue */
			return 0;
		case SSL_ERROR_SYSCALL:
			/**
			 * man SSL_get_error()
			 *
			 * SSL_ERROR_SYSCALL
			 *   Some I/O error occurred.  The OpenSSL error queue may contain more
			 *   information on the error.  If the error queue is empty (i.e.
			 *   ERR_get_error() returns 0), ret can be used to find out more about
			 *   the error: If ret == 0, an EOF was observed that violates the
			 *   protocol.  If ret == -1, the underlying BIO reported an I/O error
			 *   (for socket I/O on Unix systems, consult errno for details).
			 *
			 */
			while((ssl_err = ERR_get_error())) {
				/* get all errors from the error-queue */
				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
						r, ERR_error_string(ssl_err, NULL));
			}

			switch(errno) {
			default:
				log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
						len, r, errno,
						strerror(errno));
				break;
			}

			break;
		case SSL_ERROR_ZERO_RETURN:
			/* clean shutdown on the remote side */

			if (r == 0) {
				/* FIXME: later */
			}

			/* fall thourgh */
		default:
			while((ssl_err = ERR_get_error())) {
				switch (ERR_GET_REASON(ssl_err)) {
				case SSL_R_SSL_HANDSHAKE_FAILURE:
				case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
				case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
				case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
					if (!con->conf.log_ssl_noise) continue;
					break;
				default:
					break;
				}
				/* get all errors from the error-queue */
				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
				                r, ERR_error_string(ssl_err, NULL));
			}
			break;
		}

		connection_set_state(srv, con, CON_STATE_ERROR);

		buffer_free(b);

		return -1;
	} else if (len == 0) {
		con->is_readable = 0;
		/* the other end close the connection -> KEEP-ALIVE */

		/* pipelining */
		buffer_free(b);

		return -2;
	}

	return 0;
#else
	UNUSED(srv);
	UNUSED(con);
	return -1;
#endif
}
Пример #28
0
int read_umd_chapter_content(const char *umdfile, u_int index, p_umd_chapter pchapter
							 /*,size_t file_offset,size_t length */ ,
							 buffer ** pbuf)
{
	int ret = -1;
	SceUID fd = -1;
	SceIoStat sta;
	char buf[9] = { 0 };
	size_t stlen = 0;
	size_t stoutlen = 0;
	size_t stUnzipSize = 0;
	buffer *pzbuf = NULL;
	buffer *puzbuf = NULL;
	bool bok = false;
	struct t_chapter *pchap;
	size_t chunk_pos;
	size_t chunk_offset;
	size_t length;

	if (!umdfile || !pchapter || index + 1 > pchapter->chapter_count || !pchapter->pchapters || !(pchapter->pchapters + index) || !pbuf || !(*pbuf))
		return -1;

	pchap = pchapter->pchapters + index;
	chunk_pos = pchap->chunk_pos;
	chunk_offset = pchap->chunk_offset;
	length = pchap->length;

	do {
		char *p;
		struct UMDHeaderDataEx *pEx;

		if (sceIoGetstat(umdfile, &sta) < 0 || sta.st_size < chunk_pos) {
			return -1;
		}
		if ((fd = sceIoOpen(umdfile, PSP_O_RDONLY, 0777)) < 0) {
			return -2;
		}
		if (sceIoLseek(fd, chunk_pos, PSP_SEEK_SET) < 0) {
			break;
		}
		if ((stlen = sceIoRead(fd, buf, 9)) < 0) {
			//dbg_printf(d, "%s read umd file head chunk error!",__func__);
			break;
		}

		p = &buf[0];

		pzbuf = buffer_init();

		if (pzbuf == NULL)
			break;

		puzbuf = buffer_init();

		if (puzbuf == NULL)
			break;

		pEx = (struct UMDHeaderDataEx *) p;

		if (!pEx || pEx->Mark != '$' || pEx->Length < 9)
			break;
		stlen = pEx->Length - 9;
		stoutlen = stlen * 2;
		buf_offset = 0;
		umdfile_offset = chunk_pos + 9;
		umdfile_remain = sta.st_size - umdfile_offset;
		if (stlen < length + chunk_offset) {
			bool bfirst_chunk = true;
			size_t stHeadSize = sizeof(struct UMDHeaderData);
			size_t stHeadExSize = sizeof(struct UMDHeaderDataEx);

			//buffer_prepare_copy(pzbuf,stlen);
			buffer_prepare_copy(pzbuf, umdfile_remain);
			pzbuf->used = pzbuf->size;
			if (0 > read_umd_buf(fd, &pzbuf)) {
				//dbg_printf(d, "%s not start with 0xde9a9b89,that umd must be corrupted!",__func__);
				break;
			}
			buffer_prepare_copy(*pbuf, length);

			while (*p == '$') {
				bok = false;
				pEx = (struct UMDHeaderDataEx *) p;
				stlen = pEx->Length;
				if (stlen < 9) {
					////dbg_printf(d,"%s zipLength %d  < 9",__func__,ZipLength);
					break;
				}
				//pchap[i++].pos = umdfile_offset - 9;
				stlen -= 9;
				stoutlen = stlen * 2;
				buffer_prepare_copy(puzbuf, stoutlen);
				if (0 > get_chunk_buf(fd, &pzbuf, &p, stlen))
					break;
				stUnzipSize = umd_inflate((Byte *) p, (Byte *) puzbuf->ptr, stlen, stoutlen);
				if (stUnzipSize < 0 || stUnzipSize > stoutlen) {
					printf("stUnzipSize %d not in limit size:%d", stUnzipSize, stoutlen);
					break;
				}
				if (bfirst_chunk) {
					if (length <= stUnzipSize - chunk_offset) {
						buffer_append_memory(*pbuf, puzbuf->ptr + chunk_offset, length);
						ret = length;
						bok = true;
						break;
					}
					buffer_append_memory(*pbuf, puzbuf->ptr + chunk_offset, stUnzipSize - chunk_offset);
					length -= (stUnzipSize - chunk_offset);
					chunk_offset = 0;
					bfirst_chunk = false;
				} else if (length > stUnzipSize) {
					buffer_append_memory(*pbuf, puzbuf->ptr, stUnzipSize);
					length -= stUnzipSize;
				} else {
					buffer_append_memory(*pbuf, puzbuf->ptr + chunk_offset, stUnzipSize - chunk_offset);
					ret = pchap->length;
					bok = true;
					break;
				}

				if (*(pzbuf->ptr + buf_offset) == '#') {
					bok = true;
					while (*(pzbuf->ptr + buf_offset) == '#') {
						struct UMDHeaderData *pHead;

						if (0 > get_chunk_buf(fd, &pzbuf, &p, stHeadSize)) {
							bok = false;
							break;
						}

						pHead = (struct UMDHeaderData *) p;

						if (pHead->hdType == 0xf1 || pHead->hdType == 10) {
							if (*(pzbuf->ptr + buf_offset + pHead->Length - stHeadSize) == '#') {
								if (0 > get_chunk_buf(fd, &pzbuf, &p, pHead->Length - stHeadSize)) {
									bok = false;
									break;
								}
							} else {
								if (0 > get_offset_chunk_buf(fd, &pzbuf, &p, pHead->Length - stHeadSize, stHeadExSize))
									bok = false;
								break;
							}
						} else if (pHead->hdType == 0x81) {
							printf("you should never come here fileoffset:%d\n", umdfile_offset);
							if (pzbuf)
								buffer_free(pzbuf);
							if (puzbuf)
								buffer_free(puzbuf);
							sceIoClose(fd);
							return 0;
						}
					}
					if (!bok)
						break;
				} else {
					if (0 > get_chunk_buf(fd, &pzbuf, &p, stHeadExSize))
						break;
				}
			}
		} else {
			buffer_prepare_copy(pzbuf, stlen);
			pzbuf->used = pzbuf->size;
			if (0 > read_umd_buf(fd, &pzbuf)) {
				//dbg_printf(d, "%s not start with 0xde9a9b89,that umd must be corrupted!",__func__);
				break;
			}
			if (0 > get_chunk_buf(fd, &pzbuf, &p, stlen))
				break;
			buffer_prepare_copy(puzbuf, stoutlen);
			stUnzipSize = umd_inflate((Byte *) p, (Byte *) puzbuf->ptr, stlen, stoutlen);
			if (stUnzipSize < 0 || stUnzipSize > stoutlen) {
				printf("stUnzipSize %d not in limit size:%d", stUnzipSize, stoutlen);
				break;
			}
			buffer_copy_string_len(*pbuf, puzbuf->ptr + chunk_offset, length);
			ret = length;
		}
	} while (false);
	if (pzbuf)
		buffer_free(pzbuf);
	if (puzbuf)
		buffer_free(puzbuf);
	if (fd)
		sceIoClose(fd);
	return ret;
}
Пример #29
0
int http_response_write_header(server *srv, connection *con) {
	buffer *b;
	size_t i;
	int have_date = 0;
	int have_server = 0;

	b = chunkqueue_get_prepend_buffer(con->write_queue);

	if (con->request.http_version == HTTP_VERSION_1_1) {
		buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 "));
	} else {
		buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.0 "));
	}
	buffer_append_long(b, con->http_status);
	buffer_append_string_len(b, CONST_STR_LEN(" "));
	buffer_append_string(b, get_http_status_name(con->http_status));

	/* disable keep-alive if requested */
	if (con->request_count > con->conf.max_keep_alive_requests || 0 == con->conf.max_keep_alive_idle) {
		con->keep_alive = 0;
	} else {
		con->keep_alive_idle = con->conf.max_keep_alive_idle;
	}

	if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
		if (con->keep_alive) {
			response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
		} else {
			response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
		}
	}

	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
		response_header_overwrite(srv, con, CONST_STR_LEN("Transfer-Encoding"), CONST_STR_LEN("chunked"));
	}


	/* add all headers */
	for (i = 0; i < con->response.headers->used; i++) {
		data_string *ds;

		ds = (data_string *)con->response.headers->data[i];

		if (ds->value->used && ds->key->used &&
		    0 != strncasecmp(ds->key->ptr, CONST_STR_LEN("X-LIGHTTPD-")) &&
			0 != strncasecmp(ds->key->ptr, CONST_STR_LEN("X-Sendfile"))) {
			if (0 == strcasecmp(ds->key->ptr, "Date")) have_date = 1;
			if (0 == strcasecmp(ds->key->ptr, "Server")) have_server = 1;
			if (0 == strcasecmp(ds->key->ptr, "Content-Encoding") && 304 == con->http_status) continue;

			buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
			buffer_append_string_buffer(b, ds->key);
			buffer_append_string_len(b, CONST_STR_LEN(": "));
#if 0
			/** 
			 * the value might contain newlines, encode them with at least one white-space
			 */
			buffer_append_string_encoded(b, CONST_BUF_LEN(ds->value), ENCODING_HTTP_HEADER);
#else
			buffer_append_string_buffer(b, ds->value);
#endif
		}
	}

	if (!have_date) {
		/* HTTP/1.1 requires a Date: header */
		buffer_append_string_len(b, CONST_STR_LEN("\r\nDate: "));

		/* cache the generated timestamp */
		if (srv->cur_ts != srv->last_generated_date_ts) {
			buffer_prepare_copy(srv->ts_date_str, 255);

			strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
				 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));

			srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;

			srv->last_generated_date_ts = srv->cur_ts;
		}

		buffer_append_string_buffer(b, srv->ts_date_str);
	}

	if (!have_server) {
		if (buffer_is_empty(con->conf.server_tag)) {
			buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: " PACKAGE_DESC));
		} else if (con->conf.server_tag->used > 1) {
			buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: "));
			buffer_append_string_encoded(b, CONST_BUF_LEN(con->conf.server_tag), ENCODING_HTTP_HEADER);
		}
	}

	//- Jerry add 20110923
#if EMBEDDED_EANBLE	 
	char * ddns_host_n = nvram_get_ddns_host_name();	
	if(ddns_host_n){
		buffer_append_string_len(b, CONST_STR_LEN("\r\nDDNS: "));
		buffer_append_string(b, ddns_host_n);
	}else
#endif
	buffer_append_string_len(b, CONST_STR_LEN("\r\nDDNS: "));
	
	buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));


	con->bytes_header = b->used - 1;

	if (con->conf.log_response_header) {
		log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
	}

	return 0;
}
Пример #30
0
static int connection_handle_read(server *srv, connection *con) {
	int len;
	buffer *b;
	int toread;

	if (con->conf.is_ssl) {
		return connection_handle_read_ssl(srv, con);
	}

#if defined(__WIN32)
	b = chunkqueue_get_append_buffer(con->read_queue);
	buffer_prepare_copy(b, 4 * 1024);
	len = recv(con->fd, b->ptr, b->size - 1, 0);
#else
	if (ioctl(con->fd, FIONREAD, &toread)) {
		log_error_write(srv, __FILE__, __LINE__, "sd",
				"unexpected end-of-file:",
				con->fd);
		return -1;
	}
	b = chunkqueue_get_append_buffer(con->read_queue);
	buffer_prepare_copy(b, toread + 1);

	len = read(con->fd, b->ptr, b->size - 1);
#endif

	if (len < 0) {
		con->is_readable = 0;

		if (errno == EAGAIN) return 0;
		if (errno == EINTR) {
			/* we have been interrupted before we could read */
			con->is_readable = 1;
			return 0;
		}

		if (errno != ECONNRESET) {
			/* expected for keep-alive */
			log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
		}

		connection_set_state(srv, con, CON_STATE_ERROR);

		return -1;
	} else if (len == 0) {
		con->is_readable = 0;
		/* the other end close the connection -> KEEP-ALIVE */

		/* pipelining */

		return -2;
	} else if ((size_t)len < b->size - 1) {
		/* we got less then expected, wait for the next fd-event */

		con->is_readable = 0;
	}

	b->used = len;
	b->ptr[b->used++] = '\0';

	con->bytes_read += len;
#if 0
	dump_packet(b->ptr, len);
#endif

	return 0;
}