Ejemplo n.º 1
0
/*
  In read_preview_data I must check if readed data are more than 
  those client said in preview header
*/
int read_preview_data(ci_request_t * req)
{
     int ret;
     char *wdata;

     req->current_chunk_len = 0;
     req->chunk_bytes_read = 0;
     req->write_to_module_pending = 0;

     if (req->pstrblock_read_len == 0) {
          if (!ci_wait_for_incomming_data(req->connection->fd, TIMEOUT))
               return CI_ERROR;
          if (net_data_read(req) == CI_ERROR)
               return CI_ERROR;
     }

     do {
          do {
               if ((ret = parse_chunk_data(req, &wdata)) == CI_ERROR) {
                    ci_debug_printf(1,
                                    "Error parsing chunks, current chunk len: %d readed:%d, str:%s\n",
                                    req->current_chunk_len,
                                    req->chunk_bytes_read, req->pstrblock_read);
                    return CI_ERROR;
               }
               if (ci_buf_write
                   (&(req->preview_data), wdata,
                    req->write_to_module_pending) < 0)
                    return CI_ERROR;
               req->write_to_module_pending = 0;

               if (ret == CI_EOF) {
                    req->pstrblock_read = NULL;
                    req->pstrblock_read_len = 0;
                    if (req->eof_received)
                         return CI_EOF;
                    return CI_OK;
               }
          } while (ret != CI_NEEDS_MORE);

          if (!ci_wait_for_incomming_data(req->connection->fd, TIMEOUT))
               return CI_ERROR;
          if (net_data_read(req) == CI_ERROR)
               return CI_ERROR;
     } while (1);

     return CI_ERROR;
}
Ejemplo n.º 2
0
void parse_multipart_form(struct form_t *form, char *post, size_t content_len, const char *boundary){
    char *start = post;
    while (post && post[0] == '-' && post[1] == '-' && startswith(post+2, boundary)){
        post += strlen("--") + strlen(boundary) + strlen("\r\n");
        struct mimeheader_t header = parse_chunk_headers(post);
        char *endp = memmem(header.datap, content_len - (size_t)(header.datap - start), boundary, strlen(boundary));
        if (!endp){
            break;
        }
        size_t obj_len = (size_t)(endp - header.datap) - strlen("--") - strlen("\r\n");
        if (obj_len){
            if (parse_chunk_data(&header, form, obj_len) == -1){
                fatal("error parsing data for chunk\n");
            }
        }
        post = endp - strlen("--");
    }
}
Ejemplo n.º 3
0
int client_parse_incoming_data(ci_request_t * req, void *data_dest,
                               int (*dest_write) (void *, char *, int))
{
     int ret, v1, v2, status, bytes, size;
     char *buf, *val;
     ci_headers_list_t *resp_heads;

     if (req->status == GET_NOTHING) {
          /*And reading the new ..... */
          ret = client_parse_icap_header(req, req->response_header);
          if (ret != CI_OK)
               return ret;
          sscanf(req->response_header->buf, "ICAP/%d.%d %d", &v1, &v2, &status);
          ci_debug_printf(3, "Response was with status:%d \n", status);
          ci_headers_unpack(req->response_header);

          if (ci_allow204(req) && status == 204) {
	       req->status = GET_EOF;
               return 204;
	  }

          if ((val = ci_headers_search(req->response_header, "Encapsulated")) == NULL) {
               ci_debug_printf(1, "No encapsulated entities!\n");
               return CI_ERROR;
          }
          process_encapsulated(req, val);

          if (!req->entities[0])
               return CI_ERROR;

          if (!req->entities[1]) {      /*Then we have only body */
               req->status = GET_BODY;
               if (req->pstrblock_read_len == 0)
                    return CI_NEEDS_MORE;
          }
          else {
               req->status = GET_HEADERS;
               size = req->entities[1]->start - req->entities[0]->start;
               resp_heads = req->entities[0]->entity;
               if (!ci_headers_setsize(resp_heads, size))
                    return CI_ERROR;
          }

//        return CI_NEEDS_MORE;
     }

     /*read encups headers */

     /*Non option responce has one or two entities: 
        "req-headers req-body|null-body" or [resp-headers] resp-body||null-body   
        So here client_parse_encaps_header will be called for one headers block
      */

     if (req->status == GET_HEADERS) {
          size = req->entities[1]->start - req->entities[0]->start;
          resp_heads = req->entities[0]->entity;
          if ((ret =
               client_parse_encaps_header(req, resp_heads, size)) != CI_OK)
               return ret;


          ci_headers_unpack(resp_heads);
          ci_debug_printf(5, "OK reading headers, going to read body\n");

          /*reseting body chunks related variables */
          req->current_chunk_len = 0;
          req->chunk_bytes_read = 0;
          req->write_to_module_pending = 0;

	  if (req->entities[1]->type == ICAP_NULL_BODY) {
	       req->status = GET_EOF;
	       return CI_OK;
	  }
	  else {
	       req->status = GET_BODY;
	       if (req->pstrblock_read_len == 0)
	            return CI_NEEDS_MORE;
	  }
     }

     if (req->status == GET_BODY) {
          do {
               if ((ret = parse_chunk_data(req, &buf)) == CI_ERROR) {
                    ci_debug_printf(1,
                                    "Error parsing chunks, current chunk len: %d, read: %d, readlen: %d, str: %s\n",
                                    req->current_chunk_len,
                                    req->chunk_bytes_read,
                                    req->pstrblock_read_len,
                                    req->pstrblock_read);
                    return CI_ERROR;
               }

               while (req->write_to_module_pending > 0) {
                    bytes =
                        (*dest_write) (data_dest, buf,
                                       req->write_to_module_pending);
                    if (bytes < 0) {
                         ci_debug_printf(1, "Error writing to output file!\n");
                         return CI_ERROR;
                    }
                    req->write_to_module_pending -= bytes;
               }

               if (ret == CI_EOF) {
                    req->status = GET_EOF;
                    return CI_OK;
               }
          } while (ret != CI_NEEDS_MORE);

          return CI_NEEDS_MORE;
     }

     return CI_OK;
}
Ejemplo n.º 4
0
int get_send_body(ci_request_t * req, int parse_only)
{
     char *wchunkdata = NULL, *rchunkdata = NULL;
     int ret, parse_chunk_ret, has_formated_data = 0;
     int (*service_io) (char *rbuf, int *rlen, char *wbuf, int *wlen, int iseof,
                        ci_request_t *);
     int action = 0, rchunkisfull = 0, service_eof = 0, wbytes, rbytes;
     int no_io;

     if (parse_only)
          service_io = mod_null_io;
     else
          service_io = req->current_service_mod->mod_service_io;
     if (!service_io)
          return CI_ERROR;

     req->status = SEND_NOTHING;
     /*in the case we did not have preview data and body is small maybe
        the c-icap already read the body with the headers so do not read
        if there are unparsed bytes in pstrblock buffer
      */
     if (req->pstrblock_read_len == 0)
          action = wait_for_read;
     do {
          ret = 0;
          if (action) {
               ci_debug_printf(9, "Going to %s/%s data\n",
                               (action & wait_for_read ? "Read" : "-"),
                               (action & wait_for_write ? "Write" : "-")
                   );
               if ((ret =
                    ci_wait_for_data(req->connection->fd, TIMEOUT,
                                     action)) <= 0)
                    break;
               if (ret & wait_for_read) {
                    if (net_data_read(req) == CI_ERROR)
                         return CI_ERROR;
               }
               if (ret & wait_for_write) {
                    if (!req->data_locked && req->status == SEND_NOTHING) {
                         update_send_status(req);
                    }
                    if (send_current_block_data(req) == CI_ERROR)
                         return CI_ERROR;
               }
               ci_debug_printf(9,
                               "OK done reading/writing going to process\n");
          }

          if (!req->data_locked && req->remain_send_block_bytes == 0) {
               if (update_send_status(req) == CI_ERROR)
                    return CI_ERROR;
               // if(update_send_status==CI_EOF)/*earlier responce from icap server???...*/
          }

          /*In the following loop, parses the chunks from readed data
             and try to write data to the service.
             At the same time reads the data from module and try to fill
             the req->wbuf
           */
          if (req->remain_send_block_bytes)
               has_formated_data = 1;
          else
               has_formated_data = 0;
          parse_chunk_ret = 0;
          do {
               if (req->pstrblock_read_len != 0
                   && req->write_to_module_pending == 0) {
                    if ((parse_chunk_ret =
                         parse_chunk_data(req, &wchunkdata)) == CI_ERROR) {
                         ci_debug_printf(1, "Error parsing chunks!\n");
                         return CI_ERROR;
                    }

                    if (parse_chunk_ret == CI_EOF)
                         req->eof_received = 1;
               }
               if (wchunkdata && req->write_to_module_pending)
                    wbytes = req->write_to_module_pending;
               else
                    wbytes = 0;

               if (req->status == SEND_BODY && !service_eof) {
                    if (req->remain_send_block_bytes == 0) {
                         /*Leave space for chunk spec.. */
                         rchunkdata = req->wbuf + EXTRA_CHUNK_SIZE;
                         req->pstrblock_responce = rchunkdata;  /*does not needed! */
                         rchunkisfull = 0;
                    }
                    if ((MAX_CHUNK_SIZE - req->remain_send_block_bytes) > 0
                        && has_formated_data == 0) {
                         rbytes = MAX_CHUNK_SIZE - req->remain_send_block_bytes;
                    }
                    else {
                         rchunkisfull = 1;
                         rbytes = 0;
                    }
               }
               else
                    rbytes = 0;

               no_io = 0;
               if ((*service_io)
                   (rchunkdata, &rbytes, wchunkdata, &wbytes, req->eof_received,
                    req) == CI_ERROR)
                    return CI_ERROR;
               no_io = (rbytes==0 && wbytes==0);
               if (wbytes) {
                    wchunkdata += wbytes;
                    req->write_to_module_pending -= wbytes;
               }
               if (rbytes > 0) {
                    rchunkdata += rbytes;
                    req->remain_send_block_bytes += rbytes;
               }
               else if (rbytes == CI_EOF)
                    service_eof = 1;
          } while (no_io == 0 && req->pstrblock_read_len != 0
                   && parse_chunk_ret != CI_NEEDS_MORE && !rchunkisfull);

          action = 0;
          if (!req->write_to_module_pending) {
               action = wait_for_read;
               wchunkdata = NULL;
          }

          if (req->status == SEND_BODY) {
               if (req->remain_send_block_bytes == 0 && service_eof == 1)
                    req->remain_send_block_bytes = CI_EOF;
               if (has_formated_data == 0) {
                    if (format_body_chunk(req) == CI_EOF)
                         req->status = SEND_EOF;
               }
          }

          if (req->remain_send_block_bytes) {
               action = action | wait_for_write;
          }

     } while (!req->eof_received && action);

     if (req->eof_received)
          return CI_OK;

     if (!action) {
          ci_debug_printf(1,
                          "Bug in the service. Please report to the servive author!!!!\n");
     }
     else {
          ci_debug_printf(5, "Error reading from network......\n");
     }
     return CI_ERROR;
}