static herror_t _hssl_server_context_init(void) { log_verbose3("enabled=%i, certificate=%p", enabled, certificate); if (!enabled || !certificate) return H_OK; if (!(context = SSL_CTX_new(SSLv23_method()))) { log_error1("Cannot create SSL context"); return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT, "Unable to create SSL context"); } if (!(SSL_CTX_use_certificate_file(context, certificate, SSL_FILETYPE_PEM))) { log_error2("Cannot read certificate file: \"%s\"", certificate); SSL_CTX_free(context); return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE, "Unable to use SSL certificate \"%s\"", certificate); } SSL_CTX_set_default_passwd_cb(context, _hssl_password_callback); if (!(SSL_CTX_use_PrivateKey_file(context, certificate, SSL_FILETYPE_PEM))) { log_error2("Cannot read key file: \"%s\"", certificate); SSL_CTX_free(context); return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM, "Unable to use private key"); } if (ca_list != NULL && *ca_list != '\0') { if (!(SSL_CTX_load_verify_locations(context, ca_list, NULL))) { SSL_CTX_free(context); log_error2("Cannot read CA list: \"%s\"", ca_list); return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST, "Unable to read certification authorities \"%s\""); } SSL_CTX_set_client_CA_list(context, SSL_load_client_CA_file(ca_list)); log_verbose1("Certification authority contacted"); } SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, _hssl_cert_verify_callback); log_verbose1("Certificate verification callback registered"); SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY); SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF); _hssl_superseed(); return H_OK; }
herror_t hssl_server_ssl(hsocket_t * sock) { SSL *ssl; int ret; BIO *sbio; if (!enabled) return H_OK; log_verbose2("Starting SSL initialization for socket %d", sock->sock); if (!(ssl = SSL_new(context))) { log_warn1("SSL_new failed"); return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "Cannot create SSL object"); } /* SSL_set_fd(ssl, sock->sock); */ sbio = BIO_new_socket(sock->sock, BIO_NOCLOSE); if (sbio == NULL) { log_error1("BIO_new_socket failed"); return NULL; } // BIO_set_callback(sbio, hssl_bio_cb); sbio->method->bread = _hssl_bio_read; SSL_set_bio(ssl, sbio, sbio); if ((ret = SSL_accept(ssl)) <= 0) { herror_t err; log_error2("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); SSL_free(ssl); return err; } sock->ssl = ssl; return H_OK; }
/** Send boundary and part header and continue with next part */ herror_t httpc_mime_send_file(httpc_conn_t * conn, const char *content_id, const char *content_type, const char *transfer_encoding, const char *filename) { herror_t status; FILE *fd = fopen(filename, "rb"); byte_t buffer[MAX_FILE_BUFFER_SIZE]; size_t size; if (fd == NULL) return herror_new("httpc_mime_send_file", FILE_ERROR_OPEN, "Can not open file '%s'", filename); status = httpc_mime_next(conn, content_id, content_type, transfer_encoding); if (status != H_OK) { fclose(fd); return status; } while (!feof(fd)) { size = fread(buffer, 1, MAX_FILE_BUFFER_SIZE, fd); if (size == -1) { fclose(fd); return herror_new("httpc_mime_send_file", FILE_ERROR_READ, "Can not read from file '%s'", filename); } if (size > 0) { /* DEBUG: fwrite(buffer, 1, size, stdout); */ status = http_output_stream_write(conn->out, buffer, size); if (status != H_OK) { fclose(fd); return status; } } } fclose(fd); log_verbose1("file sent!"); return H_OK; }
herror_t soap_ctx_add_file(SoapCtx * ctx, const char *filename, const char *content_type, char *dest_href) { char cid[250]; char id[250]; part_t *part; static int counter = 1; FILE *test = fopen(filename, "r"); if (!test) return herror_new("soap_ctx_add_file", FILE_ERROR_OPEN, "Can not open file '%s'", filename); fclose(test); /* generate an id */ sprintf(id, "005512345894583%d", counter++); sprintf(dest_href, "cid:%s", id); sprintf(cid, "<%s>", id); /* add part to context */ part = part_new(cid, filename, content_type, NULL, NULL); if (!ctx->attachments) ctx->attachments = attachments_new(); attachments_add_part(ctx->attachments, part); return H_OK; }
herror_t soap_env_new_with_response(SoapEnv * request, SoapEnv ** out) { char *method, *res_method; herror_t ret; char *urn; if (request == NULL) { return herror_new("soap_env_new_with_response", GENERAL_INVALID_PARAM, "request (first param) is NULL"); } if (request->root == NULL) { return herror_new("soap_env_new_with_response", GENERAL_INVALID_PARAM, "request (first param) has no xml structure"); } if (!(method = soap_env_find_methodname(request))) { return herror_new("soap_env_new_with_response", GENERAL_INVALID_PARAM, "Method name '%s' not found in request", SAVE_STR(method)); } if (!(urn = soap_env_find_urn(request))) { /* here we have no chance to find out the namespace */ /* try to continue without namespace (urn) */ urn = ""; } if (!(res_method = (char *)malloc(strlen(method)+9))) return herror_new("soap_env_new_with_response", GENERAL_INVALID_PARAM, "malloc failed"); sprintf(res_method, "%sResponse", method); ret = soap_env_new_with_method(urn, res_method, out); free(res_method); return ret; }
herror_t hssl_client_ssl(hsocket_t * sock) { SSL *ssl; int ret; log_verbose1("Starting SSL client initialization"); if (!(ssl = SSL_new(context))) { log_error1("Cannot create new SSL object"); return herror_new("hssl_client_ssl", HSSL_ERROR_CLIENT, "SSL_new failed"); } SSL_set_fd(ssl, sock->sock); if ((ret = SSL_connect(ssl)) <= 0) { herror_t err; log_error2("SSL connect error (%s)", _hssl_get_error(ssl, -1)); err = herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); SSL_free(ssl); return err; } /* SSL_connect should take care of this for us. if (SSL_get_peer_certificate(ssl) == NULL) { log_error1("No certificate provided"); SSL_free(ssl); return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "No certificate provided"); } if (SSL_get_verify_result(ssl) != X509_V_OK) { log_error1("Certificate did not verify"); SSL_free(ssl); return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); } */ log_verbose1("SSL client initialization completed"); sock->ssl = ssl; return H_OK; }
herror_t hssl_read(hsocket_t * sock, char *buf, size_t len, size_t * received) { int count; if ((count = hsocket_select_read(sock->sock, buf, len)) == -1) return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); *received = count; return H_OK; }
herror_t soap_env_new_from_buffer(const char *buffer, SoapEnv ** out) { xmlDocPtr doc; herror_t err; if (buffer == NULL) return herror_new("soap_env_new_from_buffer", GENERAL_INVALID_PARAM, "buffer (first param) is NULL"); if (!(doc = xmlParseDoc(BAD_CAST buffer))) return herror_new("soap_env_new_from_buffer", XML_ERROR_PARSE, "Can not parse xml"); if ((err = soap_env_new_from_doc(doc, out)) != H_OK) { xmlFreeDoc(doc); } return err; }
herror_t hssl_write(hsocket_t * sock, const char *buf, size_t len, size_t * sent) { int count; if ((count = send(sock->sock, buf, len, 0)) == -1) return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); *sent = count; return H_OK; }
herror_t httpd_register_secure(const char *context, httpd_service func, httpd_auth auth) { hservice_t *service; if (!(service = (hservice_t *) malloc(sizeof(hservice_t)))) { log_error("malloc failed (%s)", strerror(errno)); return herror_new("httpd_register_secure", 0, "malloc failed (%s)", strerror(errno)); } if (!(service->statistics = (struct service_statistics *)malloc(sizeof(struct service_statistics)))) { log_error("malloc failed (%s)", strerror(errno)); free(service); return herror_new("httpd_register_secure", 0, "malloc failed (%s)", strerror(errno)); } memset(service->statistics, 0, sizeof(struct service_statistics)); service->statistics->time.tv_sec = 0; service->statistics->time.tv_usec = 0; pthread_rwlock_init(&(service->statistics->lock), NULL); service->next = NULL; service->auth = auth; service->func = func; service->status = NHTTPD_SERVICE_UP; service->context = strdup(context); log_verbose("register service (%p) for \"%s\"", service, context); if (_httpd_services_head == NULL) { _httpd_services_head = _httpd_services_tail = service; } else { _httpd_services_tail->next = service; _httpd_services_tail = service; } return H_OK; }
/** Send boundary and part header and continue with next part */ herror_t httpd_mime_send_file(httpd_conn_t * conn, const char *content_id, const char *content_type, const char *transfer_encoding, const char *filename) { unsigned char buffer[MAX_FILE_BUFFER_SIZE]; herror_t status; FILE *fd; size_t size; if ((fd = fopen(filename, "rb")) == NULL) return herror_new("httpd_mime_send_file", FILE_ERROR_OPEN, "Can not open file '%d'", filename); status = httpd_mime_next(conn, content_id, content_type, transfer_encoding); if (status != H_OK) { fclose(fd); return status; } while (!feof(fd)) { size = fread(buffer, 1, MAX_FILE_BUFFER_SIZE, fd); if (size == -1) { fclose(fd); return herror_new("httpd_mime_send_file", FILE_ERROR_READ, "Can not read from file '%d'", filename); } if ((status = http_output_stream_write(conn->out, buffer, size)) != H_OK) { fclose(fd); return status; } } fclose(fd); return H_OK; }
herror_t soap_env_new_from_doc(xmlDocPtr doc, SoapEnv ** out) { xmlNodePtr node; SoapEnv *env; if (doc == NULL) { log_error1("Can not create xml document!"); return herror_new("soap_env_new_from_doc", GENERAL_INVALID_PARAM, "XML Document (xmlDocPtr) is NULL"); } if (!(node = xmlDocGetRootElement(doc))) { log_error1("XML document is empty!"); return herror_new("soap_env_new_from_doc", XML_ERROR_EMPTY_DOCUMENT, "XML Document is empty!"); } if (!(env = (SoapEnv *) malloc(sizeof(SoapEnv)))) { log_error2("malloc failed (%s)", strerror(errno)); return herror_new("soap_env_from_doc", GENERAL_INVALID_PARAM, "malloc failed"); } env->root = node; env->header = soap_env_get_header(env); env->body = soap_env_get_body(env); env->cur = soap_env_get_method(env); *out = env; return H_OK; }
herror_t hssl_write(hsocket_t * sock, const char *buf, size_t len, size_t * sent) { int count; /* log_verbose4("sock->sock=%d, sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); */ if (sock->ssl) { if ((count = SSL_write(sock->ssl, buf, len)) == -1) return herror_new("SSL_write", HSOCKET_ERROR_SEND, "SSL_write failed (%s)", _hssl_get_error(sock->ssl, count)); } else { if ((count = send(sock->sock, buf, len, 0)) == -1) return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); } *sent = count; return H_OK; }
herror_t hssl_read(hsocket_t * sock, char *buf, size_t len, size_t * received) { int count; /* log_verbose4("sock->sock=%d sock->ssl=%p, len=%li", sock->sock, sock->ssl, len); */ if (sock->ssl) { if ((count = SSL_read(sock->ssl, buf, len)) < 1) return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, "SSL_read failed (%s)", _hssl_get_error(sock->ssl, count)); } else { if ((count = hsocket_select_read(sock->sock, buf, len)) == -1) return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); } *received = count; return H_OK; }
herror_t soap_env_new_with_method(const char *urn, const char *method, SoapEnv ** out) { xmlDocPtr env; xmlChar buffer[1054]; log_verbose2("URN = '%s'", urn); log_verbose2("Method = '%s'", method); if (!strcmp(urn, "")) { #ifdef USE_XMLSTRING xmlStrPrintf(buffer, 1054, BAD_CAST _SOAP_MSG_TEMPLATE_EMPTY_TARGET_, soap_env_ns, soap_env_enc, soap_xsi_ns, soap_xsd_ns, BAD_CAST method, BAD_CAST urn, BAD_CAST method); #else sprintf((char *)buffer, _SOAP_MSG_TEMPLATE_EMPTY_TARGET_, soap_env_ns, soap_env_enc, soap_xsi_ns, soap_xsd_ns, method, urn, method); #endif } else { #ifdef USE_XMLSTRING xmlStrPrintf(buffer, 1054, BAD_CAST _SOAP_MSG_TEMPLATE_, soap_env_ns, soap_env_enc, soap_xsi_ns, soap_xsd_ns, BAD_CAST method, BAD_CAST urn, BAD_CAST method); #else sprintf((char *)buffer, _SOAP_MSG_TEMPLATE_, soap_env_ns, soap_env_enc, soap_xsi_ns, soap_xsd_ns, method, urn, method); #endif } if (!(env = xmlParseDoc(buffer))) return herror_new("soap_env_new_with_method", XML_ERROR_PARSE, "Can not parse xml"); return soap_env_new_from_doc(env, out); }
herror_t soap_env_new_with_fault(fault_code_t faultcode, const char *faultstring, const char *faultactor, const char *detail, SoapEnv ** out) { xmlDocPtr doc; herror_t err; doc = soap_fault_build(faultcode, faultstring, faultactor, detail); if (doc == NULL) return herror_new("soap_env_new_with_fault", XML_ERROR_PARSE, "Can not parse fault xml"); if ((err = soap_env_new_from_doc(doc, out)) != H_OK) { xmlFreeDoc(doc); } return err; }
herror_t soap_env_new_from_stream(http_input_stream_t * in, SoapEnv ** out, int gbk) { xmlDocPtr doc; if (gbk) doc = xmlReadIO(_soap_env_xml_io_read_gbk, _soap_env_xml_io_close, in, "", NULL, 0); else doc = xmlReadIO(_soap_env_xml_io_read, _soap_env_xml_io_close, in, "", NULL, 0); if (in->err != H_OK) return in->err; if (doc == NULL) return herror_new("soap_env_new_from_stream", XML_ERROR_PARSE, "Trying to parse not valid xml"); return soap_env_new_from_doc(doc, out); }
/*-------------------------------------------------- FUNCTION: httpc_talk_to_server DESC: This function is the heart of the httpc module. It will send the request and process the response. Here the parameters: method: the request method. This can be HTTP_REQUEST_POST and HTTP_REQUEST_GET. conn: the connection object (created with httpc_new()) urlstr: the complete url in string format. http://<host>:<port>/<context> where <port> is not mendatory. start_cb: a callback function, which will be called when the response header is completely arrives. cb: a callback function, which will be called everytime when data arrives. content_size: size of content to send. (only if method is HTTP_REQUEST_POST) content: the content data to send. (only if method is HTTP_REQUEST_POST) userdata: a user define data, which will be passed to the start_cb and cb callbacks as a parameter. This can also be NULL. If success, this function will return 0. >0 otherwise. ----------------------------------------------------*/ static herror_t httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, const char *urlstr) { hurl_t url; char buffer[4096]; herror_t status; int ssl; if (conn == NULL) { return herror_new("httpc_talk_to_server", GENERAL_INVALID_PARAM, "httpc_conn_t param is NULL"); } /* Build request header */ httpc_header_set_date(conn); if ((status = hurl_parse(&url, urlstr)) != H_OK) { log_error2("Can not parse URL '%s'", SAVE_STR(urlstr)); return status; } /* TODO (#1#): Check for HTTP protocol in URL */ /* Set hostname */ httpc_set_header(conn, HEADER_HOST, url.host); ssl = url.protocol == PROTOCOL_HTTPS ? 1 : 0; /* Open connection */ if ((status = hsocket_open(&conn->sock, url.host, url.port, ssl)) != H_OK) return status; switch(method) { case HTTP_REQUEST_GET: sprintf(buffer, "GET %s HTTP/%s\r\n", (url.context[0] != '\0') ? url.context : ("/"), (conn->version == HTTP_1_0) ? "1.0" : "1.1"); break; case HTTP_REQUEST_POST: sprintf(buffer, "POST %s HTTP/%s\r\n", (url.context[0] != '\0') ? url.context : ("/"), (conn->version == HTTP_1_0) ? "1.0" : "1.1"); break; default: log_error1("Unknown method type!"); return herror_new("httpc_talk_to_server", GENERAL_INVALID_PARAM, "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); } log_verbose1("Sending request..."); if ((status = hsocket_send(&(conn->sock), buffer)) != H_OK) { log_error2("Cannot send request (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } log_verbose1("Sending header..."); if ((status = httpc_send_header(conn)) != H_OK) { log_error2("Cannot send header (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } return H_OK; }
herror_t hurl_parse(hurl_t * url, const char *urlstr) { int iprotocol; int ihost; int iport; int len; int size; char tmp[8]; char protocol[1024]; iprotocol = 0; len = strlen(urlstr); /* find protocol */ while (urlstr[iprotocol] != ':' && urlstr[iprotocol] != '\0') { iprotocol++; } if (iprotocol == 0) { log_error1("no protocol"); return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol"); } if (iprotocol + 3 >= len) { log_error1("no host"); return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host"); } if (urlstr[iprotocol] != ':' && urlstr[iprotocol + 1] != '/' && urlstr[iprotocol + 2] != '/') { log_error1("no protocol"); return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol"); } /* find host */ ihost = iprotocol + 3; while (urlstr[ihost] != ':' && urlstr[ihost] != '/' && urlstr[ihost] != '\0') { ihost++; } if (ihost == iprotocol + 1) { log_error1("no host"); return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host"); } /* find port */ iport = ihost; if (ihost + 1 < len) { if (urlstr[ihost] == ':') { while (urlstr[iport] != '/' && urlstr[iport] != '\0') { iport++; } } } /* find protocol */ strncpy(protocol, urlstr, iprotocol); protocol[iprotocol] = '\0'; if (strcmpigcase(protocol, "http")) url->protocol = PROTOCOL_HTTP; else if (strcmpigcase(protocol, "https")) url->protocol = PROTOCOL_HTTPS; else if (strcmpigcase(protocol, "ftp")) url->protocol = PROTOCOL_FTP; else return herror_new("hurl_parse", URL_ERROR_UNKNOWN_PROTOCOL, "Unknown protocol '%s'", protocol); /* TODO (#1#): add max of size and URL_MAX_HOST_SIZE */ size = ihost - iprotocol - 3; strncpy(url->host, &urlstr[iprotocol + 3], size); url->host[size] = '\0'; if (iport > ihost) { size = iport - ihost; strncpy(tmp, &urlstr[ihost + 1], size); url->port = atoi(tmp); } else { switch (url->protocol) { case PROTOCOL_HTTP: url->port = URL_DEFAULT_PORT_HTTP; break; case PROTOCOL_HTTPS: url->port = URL_DEFAULT_PORT_HTTPS; break; case PROTOCOL_FTP: url->port = URL_DEFAULT_PORT_FTP; break; } } len = strlen(urlstr); if (len > iport) { /* TODO (#1#): find max of size and URL_MAX_CONTEXT_SIZE */ size = len - iport; strncpy(url->context, &urlstr[iport], size); url->context[size] = '\0'; } else { url->context[0] = '\0'; } hurl_dump(url); return H_OK; }
herror_t hurl_parse(struct hurl_t *url, const char *urlstr) { int iprotocol; int ihost; int iport; int len; int size; char tmp[8]; char protocol[1024]; struct servent *entry; iprotocol = 0; len = strlen(urlstr); /* find protocol */ while (urlstr[iprotocol] != ':' && urlstr[iprotocol] != '\0') { iprotocol++; } if (iprotocol == 0) { log_error("no protocol"); return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol"); } if (iprotocol + 3 >= len) { log_error("no host"); return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host"); } if (urlstr[iprotocol] != ':' && urlstr[iprotocol + 1] != '/' && urlstr[iprotocol + 2] != '/') { log_error("no protocol"); return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol"); } /* find host */ ihost = iprotocol + 3; while (urlstr[ihost] != ':' && urlstr[ihost] != '/' && urlstr[ihost] != '\0') { ihost++; } if (ihost == iprotocol + 1) { log_error("no host"); return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host"); } /* find port */ iport = ihost; if (ihost + 1 < len) { if (urlstr[ihost] == ':') { while (urlstr[iport] != '/' && urlstr[iport] != '\0') { iport++; } } } /* find protocol */ strncpy(protocol, urlstr, iprotocol); protocol[iprotocol] = '\0'; if (!strncasecmp(protocol, "http", 5)) url->protocol = PROTOCOL_HTTP; else if (!strncasecmp(protocol, "https", 6)) url->protocol = PROTOCOL_HTTPS; else return herror_new("hurl_parse", URL_ERROR_UNKNOWN_PROTOCOL, "Unknown protocol \"%s\"", protocol); /* find right port */ if (!(entry = getservbyname(protocol, "tcp"))) { log_warn("getservbyname(\"%s\", \"tcp\") returned NULL, please edit services database", protocol); switch (url->protocol) { case PROTOCOL_HTTP: url->port = HTTP_DEFAULT_PORT; break; case PROTOCOL_HTTPS: url->port = HTTPS_DEFAULT_PORT; break; } } else { url->port = ntohs(entry->s_port); } size = ihost - iprotocol - 3; if (!(url->host = (char *)malloc(size + 1))) { log_error("malloc failed (%s)", strerror(errno)); return herror_new("hurl_parse", URL_ERROR, "malloc failed (%s)", strerror(errno)); } strncpy(url->host, &urlstr[iprotocol + 3], size); url->host[size] = '\0'; if (iport > ihost) { size = iport - ihost; strncpy(tmp, &urlstr[ihost + 1], size); url->port = atoi(tmp); } /* find path */ len = strlen(urlstr); if (len > iport) { size = len - iport; if (!(url->context = (char *)malloc(size + 1))) { log_error("malloc failed (%s)", strerror(errno)); return herror_new("hurl_parse", URL_ERROR, "malloc failed (%s)", strerror(errno)); } strncpy(url->context, &urlstr[iport], size); url->context[size] = '\0'; } else { url->context = strdup(""); } _hurl_dump(url); return H_OK; }
herror_t hresponse_new_from_socket(hsocket_t *sock, hresponse_t ** out) { int i = 0, count; herror_t status; hresponse_t *res; attachments_t *mimeMessage; char buffer[MAX_HEADER_SIZE + 1]; read_header: /* for errorcode: 100 (continue) */ /* Read header */ while (i < MAX_HEADER_SIZE) { if ((status = hsocket_read(sock, &(buffer[i]), 1, 1, &count)) != H_OK) { log_error("Socket read error"); return status; } buffer[i + 1] = '\0'; /* for strmp */ if (i > 3) { if (!strcmp(&(buffer[i - 1]), "\n\n") || !strcmp(&(buffer[i - 2]), "\n\r\n")) break; } i++; } /* Create response */ res = _hresponse_parse_header(buffer); if (res == NULL) { log_error("Header parse error"); return herror_new("hresponse_new_from_socket", GENERAL_HEADER_PARSE_ERROR, "Can not parse response header"); } /* Chec for Errorcode: 100 (continue) */ if (res->errcode == 100) { hresponse_free(res); i = 0; goto read_header; } /* Create input stream */ res->in = http_input_stream_new(sock, res->header); /* Check for MIME message */ if ((res->content_type && !strcmp(res->content_type->type, "multipart/related"))) { status = mime_get_attachments(res->content_type, res->in, &mimeMessage); if (status != H_OK) { /* TODO (#1#): Handle error */ hresponse_free(res); return status; } else { res->attachments = mimeMessage; http_input_stream_free(res->in); res->in = http_input_stream_new_from_file(mimeMessage->root_part->filename); if (!res->in) { /* TODO (#1#): Handle error */ } else { /* res->in->deleteOnExit = 1; */ } } } *out = res; return H_OK; }
herror_t mime_get_attachments(content_type_t * ctype, http_input_stream_t * in, attachments_t ** dest) { /* MIME variables */ attachments_t *mimeMessage; part_t *part, *tmp_part = NULL; char *boundary, *root_id; /* Check for MIME message */ if (!(ctype && !strcmp(ctype->type, "multipart/related"))) return herror_new("mime_get_attachments", MIME_ERROR_NOT_MIME_MESSAGE, "Not a MIME message '%s'", ctype->type); boundary = hpairnode_get(ctype->params, "boundary"); root_id = hpairnode_get(ctype->params, "start"); if (boundary == NULL) { /* TODO (#1#): Handle Error in http form */ log_error1("'boundary' not set for multipart/related"); return herror_new("mime_get_attachments", MIME_ERROR_NO_BOUNDARY_PARAM, "'boundary' not set for multipart/related"); } if (root_id == NULL) { /* TODO (#1#): Handle Error in http form */ log_error1("'start' not set for multipart/related"); return herror_new("mime_get_attachments", MIME_ERROR_NO_START_PARAM, "'start' not set for multipart/related"); } mimeMessage = mime_message_parse(in, root_id, boundary, "."); if (mimeMessage == NULL) { /* TODO (#1#): Handle Error in http form */ log_error1("MIME Parse Error"); return herror_new("mime_get_attachments", MIME_ERROR_PARSE_ERROR, "MIME Parse Error"); } /* Find root */ if (!mimeMessage->root_part) { attachments_free(mimeMessage); return herror_new("mime_get_attachments", MIME_ERROR_NO_ROOT_PART, "No root part found!"); } /* delete root_part from list */ part = mimeMessage->parts; while (part) { if (part == mimeMessage->root_part) { if (tmp_part) tmp_part->next = part->next; else mimeMessage->parts = part->next; break; } tmp_part = part; part = part->next; } *dest = mimeMessage; return H_OK; }