/** * @brief serve_file try to serve a request via filesystem. Using webroot as root. * @param connection * @param client * @return */ static int serve_file(struct MHD_Connection *connection, t_client *client, const char *url) { s_config *config = config_get_config(); struct MHD_Response *response; char filename[PATH_MAX]; int ret = MHD_NO; const char *mimetype = NULL; size_t size; snprintf(filename, PATH_MAX, "%s/%s", config->webroot, url); int fd = open(filename, O_RDONLY); if (fd < 0) return send_error(connection, 404); mimetype = lookup_mimetype(filename); /* serving file and creating response */ size = lseek(fd, 0, SEEK_END); response = MHD_create_response_from_fd(size, fd); if (!response) return send_error(connection, 503); MHD_add_response_header(response, "Content-Type", mimetype); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; }
//-------------------------------------------------------------------------- int HTTPDServer::page (struct MHD_Connection *connection, const char * page) { int ret = 0; // char * root = getenv("FAUSTDocumentRoot"); string file = "."; file += page; const char* type = getMIMEType (file); int fd; #if defined(_WIN32) && !defined(__MINGW32__) int fhd; fd = _sopen_s(&fhd, file.c_str(), _O_RDONLY, _SH_DENYNO, _S_IREAD); #else fd = open (file.c_str(), O_RDONLY); #endif if (fd != -1) { int length = lseek(fd, (long)0, SEEK_END); lseek(fd, 0, SEEK_SET); struct MHD_Response *response = MHD_create_response_from_fd (length, fd); if (!response ) { cerr << "MHD_create_response_from_fd error: null response\n"; return MHD_NO; } MHD_add_response_header (response, "Content-Type", type ? type : "text/plain"); MHD_add_response_header (response, "Access-Control-Allow-Origin", "*"); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); } else { ret = send (connection, "", 0, MHD_HTTP_NOT_FOUND); } return ret; }
inline int check_authentication(struct MHD_Connection *connection) { struct MHD_Response *response; const char *ver = NULL; int fd; int file_fd = 0, file_size = 0; uint64_t cookie_value = 0; //get request cookie by cookie name ver = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, AUTHENTICATE_COOKIE_NAME); if (ver) { cookie_value = atoll(ver); if (cookie_value != last_cookie) goto __AUTH_FAILED; return 0; } else { __AUTH_FAILED: get_file_information (&file_fd, LOGIN_HTML_PATH, &file_size); response = MHD_create_response_from_fd (file_size, file_fd); MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return (-1); } }
/** * @brief serve_file try to serve a request via filesystem. Using webroot as root. * @param connection * @param client * @return */ static int serve_file(struct MHD_Connection *connection, t_client *client, const char *url) { struct stat stat_buf; s_config *config = config_get_config(); struct MHD_Response *response; char filename[PATH_MAX]; int ret = MHD_NO; const char *mimetype = NULL; off_t size; snprintf(filename, PATH_MAX, "%s/%s", config->webroot, url); /* check if file exists and is not a directory */ ret = stat(filename, &stat_buf); if (ret) { /* stat failed */ return send_error(connection, 404); } if (!S_ISREG(stat_buf.st_mode)) { #ifdef S_ISLNK /* ignore links */ if (!S_ISLNK(stat_buf.st_mode)) #endif /* S_ISLNK */ return send_error(connection, 404); } int fd = open(filename, O_RDONLY); if (fd < 0) return send_error(connection, 404); mimetype = lookup_mimetype(filename); /* serving file and creating response */ size = lseek(fd, 0, SEEK_END); if (size < 0) return send_error(connection, 404); response = MHD_create_response_from_fd(size, fd); if (!response) return send_error(connection, 503); MHD_add_response_header(response, "Content-Type", mimetype); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; }
MHD_Response* file_response::get_raw_response() { int fd = open(filename.c_str(), O_RDONLY); size_t size = lseek(fd, 0, SEEK_END); if(size) { return MHD_create_response_from_fd(size, fd); } else { return MHD_create_response_from_buffer( 0, (void*) "", MHD_RESPMEM_PERSISTENT ); } }
void http_response::get_raw_response_file( MHD_Response** response, webserver* ws ) { int fd = open(filename.c_str(), O_RDONLY); size_t size = lseek(fd, 0, SEEK_END); if(size) { *response = MHD_create_response_from_fd(size, fd); } else { *response = MHD_create_response_from_buffer( 0, (void*) "", MHD_RESPMEM_PERSISTENT ); } }
/** * process http get request * @param url [request url string] * @param connection [http connect handle] */ inline void process_get_url_requert(const char *url, struct MHD_Connection * connection) { struct MHD_Response *response; int fd, size, type; if (url_to_file(url, &fd, &size, &type)) { response = MHD_create_response_from_fd(size, fd); set_mime(response, type); MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return; } else if (url_to_api(url, connection, false, NULL, 0, NULL)) return; else return_404(connection); }
/** * Main callback from MHD, used to generate the page. * * @param cls NULL * @param connection connection handle * @param url requested URL * @param method GET, PUT, POST, etc. * @param version HTTP version * @param upload_data data from upload (PUT/POST) * @param upload_data_size number of bytes in "upload_data" * @param ptr our context * @return MHD_YES on success, MHD_NO to drop connection */ static int generate_page (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { struct MHD_Response *response; int ret; int fd; struct stat buf; if (0 != strcmp (url, "/")) { /* should be file download */ char file_data[MAGIC_HEADER_SIZE]; ssize_t got; const char *mime; if ( (0 != strcmp (method, MHD_HTTP_METHOD_GET)) && (0 != strcmp (method, MHD_HTTP_METHOD_HEAD)) ) return MHD_NO; /* unexpected method (we're not polite...) */ if ( (0 == stat (&url[1], &buf)) && (NULL == strstr (&url[1], "..")) && ('/' != url[1])) fd = open (&url[1], O_RDONLY); else fd = -1; if (-1 == fd) return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, file_not_found_response); /* read beginning of the file to determine mime type */ got = read (fd, file_data, sizeof (file_data)); if (-1 != got) mime = magic_buffer (magic, file_data, got); else mime = NULL; (void) lseek (fd, 0, SEEK_SET); if (NULL == (response = MHD_create_response_from_fd (buf.st_size, fd))) { /* internal error (i.e. out of memory) */ (void) close (fd); return MHD_NO; } /* add mime type if we had one */ if (NULL != mime) (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, mime); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; } if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { /* upload! */ struct UploadContext *uc = *ptr; if (NULL == uc) { if (NULL == (uc = malloc (sizeof (struct UploadContext)))) return MHD_NO; /* out of memory, close connection */ memset (uc, 0, sizeof (struct UploadContext)); uc->fd = -1; uc->connection = connection; uc->pp = MHD_create_post_processor (connection, 64 * 1024 /* buffer size */, &process_upload_data, uc); if (NULL == uc->pp) { /* out of memory, close connection */ free (uc); return MHD_NO; } *ptr = uc; return MHD_YES; } if (0 != *upload_data_size) { if (NULL == uc->response) (void) MHD_post_process (uc->pp, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } /* end of upload, finish it! */ MHD_destroy_post_processor (uc->pp); uc->pp = NULL; if (-1 != uc->fd) { close (uc->fd); uc->fd = -1; } if (NULL != uc->response) { return MHD_queue_response (connection, MHD_HTTP_FORBIDDEN, uc->response); } else { update_directory (); return return_directory_response (connection); } } if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) { return return_directory_response (connection); } /* unexpected request, refuse */ return MHD_queue_response (connection, MHD_HTTP_FORBIDDEN, request_refused_response); }
/** * Main request handler. */ static int access_handler_callback (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **con_cls) { static int dummy; static const struct Entry map[] = { { "prefix", "prefix" }, { "name", "name" }, { "suffix", "suffix" }, { "street", "street" }, { "city", "city" }, { "phone", "phone" }, { "fax", "fax" }, { "email", "email"}, { "homepage", "homepage" }, { "orga", "orga"}, { "departmenti18n", "departmentde"}, { "departmenten", "departmenten"}, { "subdepartmenti18n", "subdepartmentde"}, { "subdepartmenten", "subdepartmenten"}, { "jobtitlei18n", "jobtitlegerman"}, { "jobtitleen", "jobtitleenglish"}, { "subdepartmenten", "subdepartmenten"}, { NULL, NULL } }; if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Refusing `%s' request to HTTP server\n"), method); return MHD_NO; } if (NULL == *con_cls) { (*con_cls) = &dummy; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n"); return MHD_YES; /* send 100 continue */ } if (0 == strcasecmp (url, "/")) return MHD_queue_response (connection, MHD_HTTP_OK, main_response); if (0 == strcasecmp (url, "/submit.pdf")) { unsigned int i; char *p; char *tmp; char *deffile; struct GNUNET_CRYPTO_EcdsaPublicKey pub; size_t slen; FILE *f; struct stat st; struct MHD_Response *response; int fd; int ret; const char *gpg_fp = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gpgfingerprint"); const char *gns_nick = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnsnick"); const char *gnskey = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey"); if ( (NULL == gnskey) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (gnskey, strlen (gnskey), &pub))) { return MHD_queue_response (connection, MHD_HTTP_OK, invalid_gnskey_response); } tmp = GNUNET_DISK_mkdtemp (gnskey); if (NULL == tmp) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey); return MHD_NO; } GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "def.tex"); f = FOPEN (deffile, "w"); if (NULL == f) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } for (i=0; NULL != map[i].formname; i++) { const char *val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, map[i].formname); if (NULL != val) FPRINTF (f, "\\def\\%s{%s}\n", map[i].texname, val); else FPRINTF (f, "\\def\\%s{}\n", map[i].texname); } if (NULL != gpg_fp) { char *gpg1; char *gpg2; slen = strlen (gpg_fp); gpg1 = GNUNET_strndup (gpg_fp, slen / 2); gpg2 = GNUNET_strdup (&gpg_fp[slen / 2]); FPRINTF (f, "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", gpg1, gpg2); GNUNET_free (gpg2); GNUNET_free (gpg1); } FPRINTF (f, "\\def\\gns{%s/%s}\n", gnskey, (NULL == gns_nick) ? "" : gns_nick); FCLOSE (f); GNUNET_asprintf (&p, "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null", tmp, resfile); GNUNET_free (deffile); ret = system (p); if (WIFSIGNALED (ret) || (0 != WEXITSTATUS(ret))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", p); GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "gns-bcd.pdf"); fd = OPEN (deffile, O_RDONLY); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } GNUNET_break (0 == STAT (deffile, &st)); if (NULL == (response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) { GNUNET_break (0); GNUNET_break (0 == CLOSE (fd)); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/pdf"); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return ret; } return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, not_found_response); }
/** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct stat st; char *dir; char *fn; int fd; cfg = c; dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); GNUNET_assert (NULL != dir); GNUNET_asprintf (&fn, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.html"); GNUNET_asprintf (&resfile, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.tex"); GNUNET_free (dir); fd = OPEN (fn, O_RDONLY); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); GNUNET_free (fn); return; } if (0 != STAT (fn, &st)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); GNUNET_free (fn); CLOSE (fd); return; } GNUNET_free (fn); if (NULL == (main_response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) { GNUNET_break (0); GNUNET_break (0 == CLOSE (fd)); return; } (void) MHD_add_response_header (main_response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); invalid_gnskey_response = MHD_create_response_from_buffer (strlen (INVALID_GNSKEY), INVALID_GNSKEY, MHD_RESPMEM_PERSISTENT); (void) MHD_add_response_header (invalid_gnskey_response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); not_found_response = MHD_create_response_from_buffer (strlen (NOT_FOUND), NOT_FOUND, MHD_RESPMEM_PERSISTENT); (void) MHD_add_response_header (not_found_response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); if (GNUNET_OK != server_start ()) return; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &server_stop, NULL); }
int ApiServerMHD::accessHandlerCallback(MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) { // is this call a continuation for an existing request? if(*con_cls) { return ((MHDHandlerBase*)(*con_cls))->handleRequest(connection, url, method, version, upload_data, upload_data_size); } // these characters are not allowe in the url, raise an error if they occur // reason: don't want to serve files outside the current document root const char *double_dots = ".."; if(strstr(url, double_dots)) { const char *error = "<html><body><p>Fatal error: found double dots (\"..\") in the url. This is not allowed</p></body></html>"; struct MHD_Response* resp = MHD_create_response_from_data(strlen(error), (void*)error, 0, 1); MHD_add_response_header(resp, "Content-Type", "text/html"); secure_queue_response(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, resp); MHD_destroy_response(resp); return MHD_YES; } // if no path is given, redirect to index.html in static files directory if(strlen(url) == 1 && url[0] == '/') { std::string location = std::string(STATIC_FILES_ENTRY_PATH) + "index.html"; std::string errstr = "<html><body><p>Webinterface is at <a href=\""+location+"\">"+location+"</a></p></body></html>"; const char *error = errstr.c_str(); struct MHD_Response* resp = MHD_create_response_from_data(strlen(error), (void*)error, 0, 1); MHD_add_response_header(resp, "Content-Type", "text/html"); MHD_add_response_header(resp, "Location", location.c_str()); secure_queue_response(connection, MHD_HTTP_FOUND, resp); MHD_destroy_response(resp); return MHD_YES; } // is it a call to the resource api? if(strstr(url, API_ENTRY_PATH) == url) { // create a new handler and store it in con_cls MHDHandlerBase* handler = new MHDApiHandler(mApiServer); *con_cls = (void*) handler; return handler->handleRequest(connection, url, method, version, upload_data, upload_data_size); } // is it a call to the filestreamer? if(strstr(url, FILESTREAMER_ENTRY_PATH) == url) { #ifdef ENABLE_FILESTREAMER // create a new handler and store it in con_cls MHDHandlerBase* handler = new MHDFilestreamerHandler(); *con_cls = (void*) handler; return handler->handleRequest(connection, url, method, version, upload_data, upload_data_size); #else sendMessage(connection, MHD_HTTP_NOT_FOUND, "The filestreamer is not available, because this executable was compiled with a too old version of libmicrohttpd."); return MHD_YES; #endif } // is it a path to the static files? if(strstr(url, STATIC_FILES_ENTRY_PATH) == url) { url = url + strlen(STATIC_FILES_ENTRY_PATH); // else server static files std::string filename = mRootDir + url; // important: binary open mode (windows) // else libmicrohttpd will replace crlf with lf and add garbage at the end of the file #ifdef O_BINARY int fd = open(filename.c_str(), O_RDONLY | O_BINARY); #else int fd = open(filename.c_str(), O_RDONLY); #endif if(fd == -1) { #warning sending untrusted string to the browser std::string msg = "<html><body><p>Error: can't open the requested file. Path is ""+filename+""</p></body></html>"; sendMessage(connection, MHD_HTTP_NOT_FOUND, msg); return MHD_YES; } struct stat s; if(fstat(fd, &s) == -1) { close(fd); const char *error = "<html><body><p>Error: file was opened but stat failed.</p></body></html>"; struct MHD_Response* resp = MHD_create_response_from_data(strlen(error), (void*)error, 0, 1); MHD_add_response_header(resp, "Content-Type", "text/html"); secure_queue_response(connection, MHD_HTTP_NOT_FOUND, resp); MHD_destroy_response(resp); return MHD_YES; } // find the file extension and the content type std::string extension; int i = filename.size()-1; while(i >= 0 && filename[i] != '.') { extension = filename[i] + extension; i--; } const char* type = 0; if(extension == "html") type = "text/html"; else if(extension == "css") type = "text/css"; else if(extension == "js") type = "text/javascript"; else if(extension == "jsx") // react.js jsx files type = "text/jsx"; else if(extension == "png") type = "image/png"; else if(extension == "jpg" || extension == "jpeg") type = "image/jpeg"; else if(extension == "gif") type = "image/gif"; else type = "application/octet-stream"; struct MHD_Response* resp = MHD_create_response_from_fd(s.st_size, fd); MHD_add_response_header(resp, "Content-Type", type); secure_queue_response(connection, MHD_HTTP_OK, resp); MHD_destroy_response(resp); return MHD_YES; } if(strstr(url, UPLOAD_ENTRY_PATH) == url) { // create a new handler and store it in con_cls MHDHandlerBase* handler = new MHDUploadHandler(mApiServer); *con_cls = (void*) handler; return handler->handleRequest(connection, url, method, version, upload_data, upload_data_size); } // if url is not a valid path, then serve a help page sendMessage(connection, MHD_HTTP_NOT_FOUND, "This address is invalid. Try one of the adresses below:<br/>" "<ul>" "<li>/ <br/>Retroshare webinterface</li>" "<li>"+std::string(API_ENTRY_PATH)+" <br/>JSON over http api</li>" "<li>"+std::string(FILESTREAMER_ENTRY_PATH)+" <br/>file streamer</li>" "<li>"+std::string(STATIC_FILES_ENTRY_PATH)+" <br/>static files</li>" "</ul>" ); return MHD_YES; }
static int cws_response (void * cls, struct MHD_Connection * connection, const char * url, const char * method, const char * version, const char * upload_data, size_t * upload_data_size, void ** ptr) { int ret = MHD_NO; static int dummy; const char *webfile; char *page; char *basedir = ((cws_conn *) cls)->basedir; cws_astring *pathfile; struct MHD_Response *response; cws_handler *hdlr = ((cws_conn *) cls)->hdlr; const union MHD_ConnectionInfo *info; /* if (0 != strcmp(method, "GET")) return MHD_NO; */ webfile = url; if (&dummy != *ptr) { *ptr = &dummy; return MHD_YES; } *ptr = NULL; response = NULL; if (0 != *upload_data_size) { cws_handler *h = cws_handler_lookup (hdlr, webfile); if (h != NULL) { cws_dict *dict = NULL; struct MHD_PostProcessor *pp = MHD_create_post_processor(connection, 65536, post_processor, &dict); MHD_post_process(pp, upload_data, *upload_data_size); MHD_destroy_post_processor(pp); page = h->f(dict); printf("Page: %s\n", page); response = MHD_create_response_from_data (strlen (page), page, MHD_NO, MHD_YES); if (response) { printf("sending response\n"); MHD_add_response_header (response, "Content-Type", h->mimetype); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); printf("if? %d\n", ret == MHD_YES ? 1 : 0); } MHD_destroy_response (response); free (page); cws_dict_free (&dict); } return MHD_NO; } info = MHD_get_connection_info (connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); log_connections (inet_ntoa(((struct sockaddr_in *) info->client_addr)->sin_addr), url); if (strcmp (webfile, "/") == 0) webfile = "/index.html"; pathfile = cws_astring_new(basedir); cws_astring_cat(pathfile, webfile); if (access (CWS_ASTRING(pathfile), F_OK) != -1) { int fd = open (CWS_ASTRING(pathfile), O_RDONLY); struct stat sbuf; fstat (fd, &sbuf); response = MHD_create_response_from_fd (sbuf.st_size, fd); MHD_add_response_header (response, "Content-Type", cws_mime_type(CWS_ASTRING(pathfile))); } else { cws_handler *h = cws_handler_lookup (hdlr, webfile); if (h != NULL) { cws_dict *dict = NULL; MHD_get_connection_values (connection, MHD_GET_ARGUMENT_KIND, get_keys, &dict); page = h->f(dict); response = MHD_create_response_from_data (strlen (page), page, MHD_NO, MHD_YES); MHD_add_response_header (response, "Content-Type", h->mimetype); free (page); cws_dict_free (&dict); } else { response = MHD_create_response_from_data (strlen (ERROR_ANSWER), ERROR_ANSWER, MHD_NO, MHD_YES); MHD_add_response_header (response, "Content-Type", cws_mime_type("html")); } } if (response != NULL) { ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response (response); } cws_astring_free(pathfile); return ret; }