#ifdef HAVE_LIBWWW #include "hslibwww.h" #include #include static const char darcs_version[] = PACKAGE_VERSION; #include #include enum RESULT_CODES { RESULT_OK = 0, RESULT_REQUEST_NEW_FAIL, RESULT_NET_ADD_AFTER_FAIL, RESULT_REQUEST_ADD_CACHE_CONTROL_FAIL, RESULT_LOAD_TO_FILE_FAIL, RESULT_MALLOC_FAIL, RESULT_LIST_NEW_FAIL, RESULT_LIST_APPEND_OBJECT_FAIL, RESULT_EVENTLIST_NEW_LOOP }; static const char *error_strings[] = { "", "HTRequest_new() failed", "HTNet_addAfter() failed", "HTRequest_addCacheControl() failed", "HTLoadToFile() failed", "malloc() failed", "HTList_new() failed", "HTList_appendObject() failed", "HTEventList_newLoop() failed" }; struct Completed { int error; char *url; }; static BOOL init_done = NO; static int error; static HTList *completed_list = NULL; static char *last_url = NULL; static char libwww_error[80]; static const char libwww_error_fmt[] = "libwww error code: %i"; int terminate_handler(HTRequest *request, HTResponse *response, void *param, int status) { struct Completed *completed = malloc(sizeof(struct Completed)); if (completed == NULL) error = RESULT_MALLOC_FAIL; else { if (HTList_appendObject(completed_list, completed) == NO) { error = RESULT_LIST_APPEND_OBJECT_FAIL; free(completed); } else { error = RESULT_OK; completed->error = status; completed->url = HTRequest_context(request); } } HTRequest_delete(request); HTEventList_stopLoop(); // Return not HT_OK to stop executing after filters. return HT_ERROR; } const char *libwww_request_url(const char *url, const char *filename, int cache_time) { BOOL result; if (init_done == NO) { HTProfile_newNoCacheClient("darcs", darcs_version); HTProxy_getEnvVar(); HTAlert_setInteractive(NO); HTFormat_addCoding("*", NULL, HTIdentityCoding, 1.0); #ifdef LIBWWW_DEBUG HTSetTraceMessageMask("sop"); #endif init_done = YES; } if (completed_list == NULL) { completed_list = HTList_new(); if (completed_list == NULL) return error_strings[RESULT_LIST_NEW_FAIL]; } HTRequest *const request = HTRequest_new(); if (request == NULL) return error_strings[RESULT_REQUEST_NEW_FAIL]; HTRequest_setContext(request, strdup(url)); result = HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); if (result == NO) return error_strings[RESULT_NET_ADD_AFTER_FAIL]; if (cache_time == 0) { HTRequest_addGnHd(request, HT_G_PRAGMA_NO_CACHE); result = HTRequest_addCacheControl(request, "no-cache", ""); } else if (cache_time > 0) { char buf[8]; snprintf(buf, sizeof(buf), "%d", cache_time); buf[sizeof(buf) - 1] = '\0'; result = HTRequest_addCacheControl(request, "max-age", buf); } if (result == NO) return error_strings[RESULT_REQUEST_ADD_CACHE_CONTROL_FAIL]; result = HTLoadToFile(url, request, filename); if (result == NO) return error_strings[RESULT_LOAD_TO_FILE_FAIL]; return error_strings[RESULT_OK]; } const char *libwww_wait_next_url() { if (last_url != NULL) { free(last_url); last_url = NULL; } error = RESULT_OK; if (HTList_isEmpty(completed_list) == YES && HTNet_isEmpty() == NO && HTEventList_newLoop() != HT_OK) return error_strings[RESULT_EVENTLIST_NEW_LOOP]; if (HTList_isEmpty(completed_list) == NO) { struct Completed *completed = HTList_firstObject(completed_list); if (completed->error == HT_LOADED) libwww_error[0] = '\0'; else { snprintf(libwww_error, sizeof(libwww_error), libwww_error_fmt, completed->error); libwww_error[sizeof(libwww_error) - 1] = '\0'; } last_url = completed->url; HTList_removeFirstObject(completed_list); free(completed); return libwww_error; } return error_strings[error]; } const char *libwww_last_url() { return last_url != NULL ? last_url : ""; } #endif