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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/** * 将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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/** * 输出日志. * 日志的格式: * 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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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 }
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; }
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; }
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; }