/*********************************************************************** * * pop3_parse_url_path() * * Parse the URL path into separate path components. */ static CURLcode pop3_parse_url_path(struct connectdata *conn) { /* The POP3 struct is already initialised in pop3_connect() */ struct pop3_conn *pop3c = &conn->proto.pop3c; struct SessionHandle *data = conn->data; const char *path = data->state.path; /* URL decode the path and use this mailbox */ return Curl_urldecode(data, path, 0, &pop3c->mailbox, NULL, TRUE); }
/*********************************************************************** * * pop3_parse_url_path() * * Parse the URL path into separate path components. */ static CURLcode pop3_parse_url_path(struct connectdata *conn) { /* The POP3 struct is already initialised in pop3_connect() */ struct SessionHandle *data = conn->data; struct POP3 *pop3 = data->req.protop; const char *path = data->state.path; /* URL decode the path for the message ID */ return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE); }
/*********************************************************************** * * smtp_connect() * * This function should do everything that is to be considered a part of * the connection phase. * * The variable pointed to by 'done' will be TRUE if the protocol-layer * connect phase is done when this function returns, or FALSE if not. When * called as a part of the easy interface, it will always be TRUE. */ static CURLcode smtp_connect(struct connectdata *conn, bool *done) { CURLcode result; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; const char *path = conn->data->state.path; char localhost[HOSTNAME_MAX + 1]; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = smtp_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on smtp */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; /* Initialise the response reader stuff */ Curl_pp_init(pp); /* Set the default response time-out */ pp->response_time = RESP_TIMEOUT; pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; /* Calculate the path if necessary */ if(!*path) { if(!Curl_gethostname(localhost, sizeof(localhost))) path = localhost; else path = "localhost"; } /* URL decode the path and use it as the domain in our EHLO */ result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); if(result) return result; /* Start off waiting for the server greeting response */ state(conn, SMTP_SERVERGREET); result = smtp_multi_statemach(conn, done); return result; }
/*********************************************************************** * * smtp_parse_custom_request() * * Parse the custom request. */ static CURLcode smtp_parse_custom_request(struct connectdata *conn) { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.protop; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; /* URL decode the custom request */ if(custom) result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE); return result; }
/*********************************************************************** * * pop3_parse_custom_request() * * Parse the custom request. */ static CURLcode pop3_parse_custom_request(struct connectdata *conn) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; struct POP3 *pop3 = data->req.protop; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; /* URL decode the custom request */ if(custom) result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE); return result; }
/*********************************************************************** * * imap_parse_url_path() * * Parse the URL path into separate path components. * */ static CURLcode imap_parse_url_path(struct connectdata *conn) { /* The imap struct is already inited in imap_connect() */ struct imap_conn *imapc = &conn->proto.imapc; struct SessionHandle *data = conn->data; const char *path = data->state.path; if(!*path) path = "INBOX"; /* URL decode the path and use this mailbox */ return Curl_urldecode(data, path, 0, &imapc->mailbox, NULL, TRUE); }
/* * Unescapes the given URL escaped string of given length. Returns a * pointer to a malloced string with length given in *olen. * If length == 0, the length is assumed to be strlen(string). * If olen == NULL, no output length is stored. */ char *curl_easy_unescape(CURL *handle, const char *string, int length, int *olen) { char *str = NULL; size_t inputlen = length; size_t outputlen; CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen, FALSE); if(res) return NULL; if(olen) *olen = curlx_uztosi(outputlen); return str; }
/*********************************************************************** * * smtp_parse_url_path() * * Parse the URL path into separate path components. */ static CURLcode smtp_parse_url_path(struct connectdata *conn) { /* The SMTP struct is already initialised in smtp_connect() */ struct Curl_easy *data = conn->data; struct smtp_conn *smtpc = &conn->proto.smtpc; const char *path = data->state.path; char localhost[HOSTNAME_MAX + 1]; /* Calculate the path if necessary */ if(!*path) { if(!Curl_gethostname(localhost, sizeof(localhost))) path = localhost; else path = "localhost"; } /* URL decode the path and use it as the domain in our EHLO */ return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); }
static CURLcode gopher_do(struct connectdata *conn, bool *done) { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; curl_off_t *bytecount = &data->req.bytecount; char *path = data->state.up.path; char *sel = NULL; char *sel_org = NULL; ssize_t amount, k; size_t len; *done = TRUE; /* unconditionally */ /* Create selector. Degenerate cases: / and /1 => convert to "" */ if(strlen(path) <= 2) { sel = (char *)""; len = strlen(sel); } else { char *newp; /* Otherwise, drop / and the first character (i.e., item type) ... */ newp = path; newp += 2; /* ... and finally unescape */ result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE); if(result) return result; sel_org = sel; } /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is sent, which could be sizeable with long selectors. */ k = curlx_uztosz(len); for(;;) { result = Curl_write(conn, sockfd, sel, k, &amount); if(!result) { /* Which may not have written it all! */ result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount); if(result) break; k -= amount; sel += amount; if(k < 1) break; /* but it did write it all */ } else break; /* Don't busyloop. The entire loop thing is a work-around as it causes a BLOCKING behavior which is a NO-NO. This function should rather be split up in a do and a doing piece where the pieces that aren't possible to send now will be sent in the doing function repeatedly until the entire request is sent. Wait a while for the socket to be writable. Note that this doesn't acknowledge the timeout. */ if(SOCKET_WRITABLE(sockfd, 100) < 0) { result = CURLE_SEND_ERROR; break; } } free(sel_org); if(!result) /* We can use Curl_sendf to send the terminal \r\n relatively safely and save allocing another string/doing another _write loop. */ result = Curl_sendf(sockfd, conn, "\r\n"); if(result) { failf(data, "Failed sending Gopher request"); return result; } result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2); if(result) return result; Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL); /* no upload */ return CURLE_OK; }
/* * smtp_connect() should do everything that is to be considered a part of * the connection phase. * * The variable pointed to by 'done' will be TRUE if the protocol-layer * connect phase is done when this function returns, or FALSE if not. When * called as a part of the easy interface, it will always be TRUE. */ static CURLcode smtp_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct smtp_conn *smtpc = &conn->proto.smtpc; struct SessionHandle *data = conn->data; struct pingpong *pp = &smtpc->pp; const char *path = conn->data->state.path; char localhost[HOSTNAME_MAX + 1]; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = smtp_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on smtp */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if((conn->handler->protocol & CURLPROTO_SMTPS) && data->state.used_interface != Curl_if_multi) { /* SMTPS is simply smtp with SSL for the control channel */ /* now, perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init the response reader stuff */ pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if(!*path) { if(!Curl_gethostname(localhost, sizeof(localhost))) path = localhost; else path = "localhost"; } /* Url decode the path and use it as the domain in our EHLO */ result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); if(result) return result; /* Set the state as we are waiting the server greeting */ state(conn, SMTP_SERVERGREET); if(data->state.used_interface == Curl_if_multi) result = smtp_multi_statemach(conn, done); else { result = smtp_easy_statemach(conn); if(!result) *done = TRUE; } return result; }
/* * file_connect() gets called from Curl_protocol_connect() to allow us to * do protocol-specific actions at connect-time. We emulate a * connect-then-transfer protocol and "connect" to the file here */ static CURLcode file_connect(struct connectdata *conn, bool *done) { struct Curl_easy *data = conn->data; char *real_path; struct FILEPROTO *file = data->req.protop; int fd; #ifdef DOS_FILESYSTEM size_t i; char *actual_path; #endif size_t real_path_len; CURLcode result = Curl_urldecode(data, data->state.path, 0, &real_path, &real_path_len, FALSE); if(result) return result; #ifdef DOS_FILESYSTEM /* If the first character is a slash, and there's something that looks like a drive at the beginning of the path, skip the slash. If we remove the initial slash in all cases, paths without drive letters end up relative to the current directory which isn't how browsers work. Some browsers accept | instead of : as the drive letter separator, so we do too. On other platforms, we need the slash to indicate an absolute pathname. On Windows, absolute paths start with a drive letter. */ actual_path = real_path; if((actual_path[0] == '/') && actual_path[1] && (actual_path[2] == ':' || actual_path[2] == '|')) { actual_path[2] = ':'; actual_path++; real_path_len--; } /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ for(i=0; i < real_path_len; ++i) if(actual_path[i] == '/') actual_path[i] = '\\'; else if(!actual_path[i]) { /* binary zero */ Curl_safefree(real_path); return CURLE_URL_MALFORMAT; } fd = open_readonly(actual_path, O_RDONLY|O_BINARY); file->path = actual_path; #else if(memchr(real_path, 0, real_path_len)) { /* binary zeroes indicate foul play */ Curl_safefree(real_path); return CURLE_URL_MALFORMAT; } fd = open_readonly(real_path, O_RDONLY); file->path = real_path; #endif file->freepath = real_path; /* free this when done */ file->fd = fd; if(!data->set.upload && (fd == -1)) { failf(data, "Couldn't open file %s", data->state.path); file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); return CURLE_FILE_COULDNT_READ_FILE; } *done = TRUE; return CURLE_OK; }
/* * smtp_connect() should do everything that is to be considered a part of * the connection phase. * * The variable pointed to by 'done' will be TRUE if the protocol-layer * connect phase is done when this function returns, or FALSE if not. When * called as a part of the easy interface, it will always be TRUE. */ static CURLcode smtp_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct smtp_conn *smtpc = &conn->proto.smtpc; struct SessionHandle *data = conn->data; struct pingpong *pp = &smtpc->pp; const char *path = conn->data->state.path; char localhost[HOSTNAME_MAX + 1]; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = smtp_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on smtp */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* for SMTP over HTTP proxy */ struct HTTP http_proxy; struct FTP *smtp_save; /* BLOCKING */ /* We want "seamless" SMTP operations through HTTP proxy tunnel */ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member * conn->proto.http; we want SMTP through HTTP and we have to change the * member temporarily for connecting to the HTTP proxy. After * Curl_proxyCONNECT we have to set back the member to the original struct * SMTP pointer */ smtp_save = data->state.proto.smtp; memset(&http_proxy, 0, sizeof(http_proxy)); data->state.proto.http = &http_proxy; result = Curl_proxyCONNECT(conn, FIRSTSOCKET, conn->host.name, conn->remote_port); data->state.proto.smtp = smtp_save; if(CURLE_OK != result) return result; } if((conn->handler->protocol & CURLPROTO_SMTPS) && data->state.used_interface != Curl_if_multi) { /* SMTPS is simply smtp with SSL for the control channel */ /* now, perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init the response reader stuff */ pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if(!*path) { if(!Curl_gethostname(localhost, sizeof localhost)) path = localhost; else path = "localhost"; } /* url decode the path and use it as domain with EHLO */ result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); if(result) return result; /* When we connect, we start in the state where we await the server greeting */ state(conn, SMTP_SERVERGREET); if(data->state.used_interface == Curl_if_multi) result = smtp_multi_statemach(conn, done); else { result = smtp_easy_statemach(conn); if(!result) *done = TRUE; } return result; }