// part:data(str[, type[, name[, filename]]][, headers]) static int lcurl_mime_part_data(lua_State *L){ lcurl_mime_part_t *p = lcurl_getmimepart(L); size_t len; const char *data; CURLcode ret; if(IS_FALSE(L, 2)){ data = NULL; len = 0; } else{ data = luaL_checklstring(L, 2, &len); /*string too long*/ if(len == CURL_ZERO_TERMINATED){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, CURLE_BAD_FUNCTION_ARGUMENT); } } /* curl_mime_data copies data */ ret = curl_mime_data(p->part, data, len); if(ret != CURLE_OK){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret); } if (lua_gettop(L) > 2){ int res = lcurl_mime_part_assing_ext(L, 1, 3); if (res) return res; } lua_settop(L, 1); return 1; }
int main(void) { CURL *curl; CURLM *multi_handle; int still_running; curl_mime *form = NULL; curl_mimepart *field = NULL; struct curl_slist *headerlist = NULL; static const char buf[] = "Expect:"; curl = curl_easy_init(); multi_handle = curl_multi_init(); if(curl && multi_handle) { /* Create the form */ form = curl_mime_init(curl); /* Fill in the file upload field */ field = curl_mime_addpart(form); curl_mime_name(field, "sendfile", CURL_ZERO_TERMINATED); curl_mime_filedata(field, "multi-post.c"); /* Fill in the filename field */ field = curl_mime_addpart(form); curl_mime_name(field, "filename", CURL_ZERO_TERMINATED); curl_mime_data(field, "multi-post.c", CURL_ZERO_TERMINATED); /* Fill in the submit field too, even if this is rarely needed */ field = curl_mime_addpart(form); curl_mime_name(field, "submit", CURL_ZERO_TERMINATED); curl_mime_data(field, "send", CURL_ZERO_TERMINATED); /* initialize custom header list (stating that Expect: 100-continue is not wanted */ headerlist = curl_slist_append(headerlist, buf); /* what URL that receives this POST */ curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/upload.cgi"); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_MIMEPOST, form); curl_multi_add_handle(multi_handle, curl); curl_multi_perform(multi_handle, &still_running); do { struct timeval timeout; int rc; /* select() return code */ CURLMcode mc; /* curl_multi_fdset() return code */ fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd = -1; long curl_timeo = -1; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); /* set a suitable timeout to play around with */ timeout.tv_sec = 1; timeout.tv_usec = 0; curl_multi_timeout(multi_handle, &curl_timeo); if(curl_timeo >= 0) { timeout.tv_sec = curl_timeo / 1000; if(timeout.tv_sec > 1) timeout.tv_sec = 1; else timeout.tv_usec = (curl_timeo % 1000) * 1000; } /* get file descriptors from the transfers */ mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); if(mc != CURLM_OK) { fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); break; } /* On success the value of maxfd is guaranteed to be >= -1. We call select(maxfd + 1, ...); specially in case of (maxfd == -1) there are no fds ready yet so we call select(0, ...) --or Sleep() on Windows-- to sleep 100ms, which is the minimum suggested value in the curl_multi_fdset() doc. */ if(maxfd == -1) { #ifdef _WIN32 Sleep(100); rc = 0; #else /* Portable sleep for platforms other than Windows. */ struct timeval wait = { 0, 100 * 1000 }; /* 100ms */ rc = select(0, NULL, NULL, NULL, &wait); #endif } else { /* Note that on some platforms 'timeout' may be modified by select(). If you need access to the original value save a copy beforehand. */ rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); } switch(rc) { case -1: /* select error */ break; case 0: default: /* timeout or readable/writable sockets */ printf("perform!\n"); curl_multi_perform(multi_handle, &still_running); printf("running: %d!\n", still_running); break; } } while(still_running); curl_multi_cleanup(multi_handle); /* always cleanup */ curl_easy_cleanup(curl); /* then cleanup the form */ curl_mime_free(form); /* free slist */ curl_slist_free_all(headerlist); } return 0; }
int main(void) { CURL *curl; CURLcode res = CURLE_OK; struct curl_slist *headers = NULL; struct curl_slist *recipients = NULL; struct curl_slist *slist = NULL; curl_mime *mime; curl_mime *alt; curl_mimepart *part; const char **cpp; curl = curl_easy_init(); if(curl) { /* This is the URL for your mailserver */ curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.example.com"); /* Note that this option isn't strictly required, omitting it will result * in libcurl sending the MAIL FROM command with empty sender data. All * autoresponses should have an empty reverse-path, and should be directed * to the address in the reverse-path which triggered them. Otherwise, * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more * details. */ curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM); /* Add two recipients, in this particular case they correspond to the * To: and Cc: addressees in the header, but they could be any kind of * recipient. */ recipients = curl_slist_append(recipients, TO); recipients = curl_slist_append(recipients, CC); curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); /* Build and set the message header list. */ for(cpp = headers_text; *cpp; cpp++) headers = curl_slist_append(headers, *cpp); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); /* Build the mime message. */ mime = curl_mime_init(curl); /* The inline part is an alternative proposing the html and the text versions of the e-mail. */ alt = curl_mime_init(curl); /* HTML message. */ part = curl_mime_addpart(alt); curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED); curl_mime_type(part, "text/html"); /* Text message. */ part = curl_mime_addpart(alt); curl_mime_data(part, inline_text, CURL_ZERO_TERMINATED); /* Create the inline part. */ part = curl_mime_addpart(mime); curl_mime_subparts(part, alt); curl_mime_type(part, "multipart/alternative"); slist = curl_slist_append(NULL, "Content-Disposition: inline"); curl_mime_headers(part, slist, 1); /* Add the current source program as an attachment. */ part = curl_mime_addpart(mime); curl_mime_filedata(part, "smtp-mime.c"); curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); /* Send the message */ res = curl_easy_perform(curl); /* Check for errors */ if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); /* Free lists. */ curl_slist_free_all(recipients); curl_slist_free_all(headers); /* curl won't send the QUIT command until you call cleanup, so you should * be able to re-use this connection for additional messages (setting * CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling * curl_easy_perform() again. It may not be a good idea to keep the * connection open for a very long time though (more than a few minutes * may result in the server timing out the connection), and you do want to * clean up in the end. */ curl_easy_cleanup(curl); /* Free multipart message. */ curl_mime_free(mime); } return (int)res; }
static int _piwigo_api_post_internal(_piwigo_api_context_t *ctx, GList *args, char *filename, gboolean isauth) { curl_mime *form = NULL; GString *url = g_string_new(ctx->url); // send the requests GString *response = g_string_new(""); dt_curl_init(ctx->curl_ctx, piwigo_EXTRA_VERBOSE); curl_easy_setopt(ctx->curl_ctx, CURLOPT_URL, url->str); curl_easy_setopt(ctx->curl_ctx, CURLOPT_POST, 1); curl_easy_setopt(ctx->curl_ctx, CURLOPT_WRITEFUNCTION, curl_write_data_cb); curl_easy_setopt(ctx->curl_ctx, CURLOPT_WRITEDATA, response); if(isauth) { /* construct a temporary file name */ char cookie_fmt[PATH_MAX] = { 0 }; dt_loc_get_tmp_dir(cookie_fmt, sizeof(cookie_fmt)); g_strlcat(cookie_fmt, "/cookies.%.4lf.txt", sizeof(cookie_fmt)); ctx->cookie_file = g_strdup_printf(cookie_fmt, dt_get_wtime()); // not that this is safe as the cookie file is written only when the curl context is finalized. // At this stage we unlink the file. curl_easy_setopt(ctx->curl_ctx, CURLOPT_COOKIEJAR, ctx->cookie_file); } else { curl_easy_setopt(ctx->curl_ctx, CURLOPT_COOKIEFILE, ctx->cookie_file); } if(filename) { curl_mimepart *field = NULL; form = curl_mime_init(ctx->curl_ctx); GList *a = args; while (a) { _curl_args_t *ca = (_curl_args_t *)a->data; field = curl_mime_addpart(form); curl_mime_name(field, ca->name); curl_mime_data(field, ca->value, CURL_ZERO_TERMINATED); a = g_list_next(a); } field = curl_mime_addpart(form); curl_mime_name(field, "image"); curl_mime_filedata(field, filename); curl_easy_setopt(ctx->curl_ctx, CURLOPT_MIMEPOST, form); } else { GString *gargs = g_string_new(""); GList *a = args; while (a) { _curl_args_t *ca = (_curl_args_t *)a->data; if(a!=args) g_string_append(gargs, "&"); g_string_append(gargs, ca->name); g_string_append(gargs, "="); g_string_append(gargs, ca->value); a = g_list_next(a); } curl_easy_setopt(ctx->curl_ctx, CURLOPT_COPYPOSTFIELDS, gargs->str); g_string_free(gargs, TRUE); } int res = curl_easy_perform(ctx->curl_ctx); #if piwigo_EXTRA_VERBOSE == TRUE g_printf("curl_easy_perform status %d\n", res); #endif if(filename) curl_mime_free(form); g_string_free(url, TRUE); ctx->response = NULL; if(res == CURLE_OK) { GError *error = NULL; gboolean ret = json_parser_load_from_data(ctx->json_parser, response->str, response->len, &error); if(!ret) goto cleanup; JsonNode *root = json_parser_get_root(ctx->json_parser); // we should always have a dict if(json_node_get_node_type(root) != JSON_NODE_OBJECT) goto cleanup; ctx->response = json_node_get_object(root); const char *status = json_object_get_string_member(ctx->response, "stat"); ctx->error_occured = (status && (strcmp(status,"fail")==0)); } else ctx->error_occured = TRUE; cleanup: g_string_free(response, TRUE); return res; }