/** * Lecture de la réponse jusqu'à un certain caractère (exclu) ou la fin de ligne * Le caractère '\r' est ignoré * @return int nb de caractères lus (0 signifie que le premier caractère était ce caractère ou une fin de ligne) * HTTP_ERROR s'il y a eu une erreur * HTTP_ERROR_TIMEOUT si le timeout a été dépassé */ int HttpClient::readLineToChar(char sep, char* key,int maxlen){ if(debug) Serial.println(F("HttpClient.readLineToChar")); for(int nbChars=0;;){ char c = httpRead(); if(c==sep || c==0) return nbChars; //Séparateur ou fin de fichier if(c<0) return c; //httpRead a renvoyé une erreur if(c==10) continue; //on ignore le '\r' if(c==13 && nbChars==0 && status!=HTTP_STATUS_RESP_BODY){ //C'est la fin des en-têtes status = HTTP_STATUS_RESP_BODY; return 0; } if(status==HTTP_STATUS_RESP_HEADER && !(c>='A' && c<='Z' || c>='a' && c<='z' || c>='0' && c<='9' || c=='_' || c=='-')){ //Caractère invalide if(debug){ Serial.print(F("Caractere invalide:")); Serial.print(c); Serial.println(c,DEC); } return error(HTTP_ERROR); } nbChars++; if(nbChars>maxlen) return error(HTTP_ERROR_BUFFER_OVERFLOW); key[nbChars-1] = c; key[nbChars] = '\0'; } }
/* Read the required number of bytes into the response content buffer. Count < 0 means transfer the entire content. Returns the number of bytes read. Returns null on EOF. */ static ssize readHttpData(Ejs *ejs, EjsHttp *hp, ssize count) { MprBuf *buf; HttpConn *conn; ssize len, space, nbytes; conn = hp->conn; buf = hp->responseContent; mprResetBufIfEmpty(buf); while (count < 0 || mprGetBufLength(buf) < count) { len = (count < 0) ? BIT_MAX_BUFFER : (count - mprGetBufLength(buf)); space = mprGetBufSpace(buf); if (space < len) { mprGrowBuf(buf, len - space); } if ((nbytes = httpRead(conn, mprGetBufEnd(buf), len)) < 0) { ejsThrowIOError(ejs, "Cannot read required data"); return MPR_ERR_CANT_READ; } mprAdjustBufEnd(buf, nbytes); if (hp->conn->async || (nbytes == 0 && conn->state > HTTP_STATE_CONTENT)) { break; } } if (count < 0) { return mprGetBufLength(buf); } return min(count, mprGetBufLength(buf)); }
static void readBody(HttpConn *conn, MprFile *outFile) { char buf[BIT_MAX_BUFFER]; cchar *result; ssize bytes; while (!conn->error && conn->sock && (bytes = httpRead(conn, buf, sizeof(buf))) > 0) { if (!app->noout) { result = formatOutput(conn, buf, &bytes); if (result) { mprWriteFile(outFile, result, bytes); } } #if FUTURE // This should be pushed into a range filter. // Buffer all output and then parsing can work type = httpGetHeader(conn, "Content-Type"); if (scontains(type, "multipart/byteranges")) { if ((boundary = scontains(type, "boundary=")) != 0) { boundary += 9; if (*boundary) { boundary = sfmt("--%s\r\n", boundary); } } } #endif } }
static void _get_read_data (GtkCupsRequest *request) { char buffer[_GTK_CUPS_MAX_CHUNK_SIZE]; gsize bytes; gsize bytes_written; GIOStatus io_status; GError *error; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s\n", G_STRFUNC)); error = NULL; request->poll_state = GTK_CUPS_HTTP_READ; #if HAVE_CUPS_API_1_2 bytes = httpRead2 (request->http, buffer, sizeof (buffer)); #else bytes = httpRead (request->http, buffer, sizeof (buffer)); #endif /* HAVE_CUPS_API_1_2 */ request->bytes_received += bytes; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %" G_GSIZE_FORMAT " bytes read\n", bytes)); io_status = g_io_channel_write_chars (request->data_io, buffer, bytes, &bytes_written, &error); if (io_status == G_IO_STATUS_ERROR) { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_IO, io_status, error->code, error->message); g_error_free (error); } /* Stop if we do not expect any more data or EOF was received. */ #if HAVE_CUPS_API_1_2 if (httpGetLength2 (request->http) <= request->bytes_received || bytes == 0) #else if (httpGetLength (request->http) <= request->bytes_received || bytes == 0) #endif /* HAVE_CUPS_API_1_2 */ { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; return; } }
static void readBody(HttpConn *conn) { char buf[HTTP_BUFSIZE]; ssize bytes; while (!conn->error && conn->sock && (bytes = httpRead(conn, buf, sizeof(buf))) > 0) { showOutput(conn, buf, bytes); } }
PUBLIC char *httpReadString(HttpStream *stream) { HttpRx *rx; ssize sofar, nbytes, remaining; char *content; rx = stream->rx; if (rx->length < 0) { return 0; } remaining = (ssize) min(MAXSSIZE, rx->length); if (remaining > 0) { if ((content = mprAlloc(remaining + 1)) == 0) { return 0; } sofar = 0; while (remaining > 0) { nbytes = httpRead(stream, &content[sofar], remaining); if (nbytes < 0) { return 0; } sofar += nbytes; remaining -= nbytes; } } else { content = NULL; sofar = 0; while (1) { if ((content = mprRealloc(content, sofar + ME_BUFSIZE)) == 0) { return 0; } nbytes = httpRead(stream, &content[sofar], ME_BUFSIZE); if (nbytes < 0) { return 0; } else if (nbytes == 0) { break; } sofar += nbytes; } } content[sofar] = '\0'; return content; }
static void _get_read_data (GtkCupsRequest *request) { char buffer[_GTK_CUPS_MAX_CHUNK_SIZE]; gsize bytes; gsize bytes_written; GIOStatus io_status; GError *error; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s\n", G_STRFUNC)); error = NULL; request->poll_state = GTK_CUPS_HTTP_READ; #if HAVE_CUPS_API_1_2 bytes = httpRead2 (request->http, buffer, sizeof (buffer)); #else bytes = httpRead (request->http, buffer, sizeof (buffer)); #endif /* HAVE_CUPS_API_1_2 */ GTK_NOTE (PRINTING, g_print ("CUPS Backend: %i bytes read\n", bytes)); if (bytes == 0) { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; return; } io_status = g_io_channel_write_chars (request->data_io, buffer, bytes, &bytes_written, &error); if (io_status == G_IO_STATUS_ERROR) { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_IO, io_status, error->code, error->message); g_error_free (error); } }
/* Read data as a string */ PUBLIC char *httpReadString(HttpConn *conn) { HttpRx *rx; ssize sofar, nbytes, remaining; char *content; rx = conn->rx; remaining = (ssize) min(MAXSSIZE, rx->length); if (remaining > 0) { if ((content = mprAlloc(remaining + 1)) == 0) { return 0; } sofar = 0; while (remaining > 0) { nbytes = httpRead(conn, &content[sofar], remaining); if (nbytes < 0) { return 0; } sofar += nbytes; remaining -= nbytes; } } else { content = mprAlloc(BIT_MAX_BUFFER); sofar = 0; while (1) { nbytes = httpRead(conn, &content[sofar], BIT_MAX_BUFFER); if (nbytes < 0) { return 0; } else if (nbytes == 0) { break; } sofar += nbytes; content = mprRealloc(content, sofar + BIT_MAX_BUFFER); } } content[sofar] = '\0'; return content; }
int HttpClient::moveToEOL(){ if(status==HTTP_STATUS_IDLE){ //La réponse n'a pas commencé if(debug) Serial.println("Error: Status not IDLE"); return error(HTTP_ERROR_STATUS); } for(int nbChars=0;;nbChars++){ int c = httpRead(); if(c<0) return c; //httpRead a renvoyé une erreur if(c=='\n'){ return 0; } } }
static void readBody(HttpConn *conn, MprFile *outFile) { char buf[ME_MAX_BUFFER]; cchar *result; ssize bytes; while (!conn->error && (bytes = httpRead(conn, buf, sizeof(buf))) > 0) { if (!app->noout) { result = formatOutput(conn, buf, &bytes); if (result) { mprWriteFile(outFile, result, bytes); } } } }
/* Eat remaining input incase last request did not consume all data */ static void consumeLastRequest(HttpConn *conn) { char junk[4096]; if (conn->state >= HTTP_STATE_FIRST) { while (!httpIsEof(conn) && !httpRequestExpired(conn, 0)) { if (httpRead(conn, junk, sizeof(junk)) <= 0) { break; } } } if (HTTP_STATE_CONNECTED <= conn->state && conn->state < HTTP_STATE_COMPLETE) { conn->keepAliveCount = 0; } }
/** * Attend le début de la réponse, lit la première ligne de la réponse, avec le code réponse * Fait suite à l'envoi d'une requête. * @return int code réponse * HTTP_ERROR s'il y a eu une erreur * HTTP_ERROR_TIMEOUT si le timeout a été dépassé * HTTP_ERROR_STATUS status du client est anormal */ int HttpClient::readResponseCode(){ if(debug) Serial.print(F("HttpClient.readResponseCode...")); if(status!=HTTP_STATUS_RESP_WAIT){ if(debug) Serial.println(F("Excepted status:WAIT")); return error(HTTP_ERROR_STATUS); } char* intro = "HTTP/1.1 "; int result = 0; startMillis = millis(); for(int charIdx=0;;charIdx++){ char c = httpRead(); if(c<0) return c; //C'est une erreur if(charIdx<=8){ if(debug) Serial.print(c); //Vérification du "HTTP/1.1 " if(c==intro[charIdx] || (charIdx==7 && c=='0')){ //OK } else{ if(debug) Serial.print(F(": HTTP/1.1 not verified")); return error(HTTP_ERROR); } } else if(charIdx<=11){ //Lecture du code réponse if(c<'0' || c >'9'){ if(debug) Serial.print(F("Invalid char (")); Serial.print(charIdx); Serial.print("):"); Serial.print(c); return error(HTTP_ERROR); } int tmp = 1; for(uint8_t i=0;i<11-charIdx;i++) tmp = tmp*10; tmp = (c-48)*tmp; result += tmp; //Serial.print("c=");Serial.print(c-48,DEC);Serial.print(" ");Serial.print(tmp);Serial.print(" idx=");Serial.print(charIdx,DEC);Serial.print(" ->");Serial.println(result,DEC); //if(debug) Serial.println(result); } else{ //On passe le reste de la ligne, et on renvoie le résultat if(int res=moveToEOL()<0) return error(res); status = HTTP_STATUS_RESP_HEADER; //La ligne suivante est une en-tête if(debug) Serial.println(result); return result; } } }
/** * Passe la suites des en-têtes HTTP * @return 0 si tout s'est bien passé * HTTP_ERROR s'il y a eu une erreur * HTTP_ERROR_TIMEOUT si le timeout a été dépassé */ int HttpClient::skipHeaders(){ if(debug) Serial.println(F("HttpClient.skipHeaders")); if(status!=HTTP_STATUS_RESP_HEADER){ //On n'est pas dans les en-têtes if(debug) Serial.println("Excepted status:RESP_HEADER"); return error(HTTP_ERROR_STATUS); } char prevChar; char c = 0; while(c!=13 || prevChar!=13) //tant qu'il n'y a pas deux caractères '\n' consécutifs { prevChar = c; c = httpRead(); if(c<0) return error(c); //httpRead a renvoyé une erreur if(c==10){ c = prevChar; prevChar = 0; continue; } } status = HTTP_STATUS_RESP_BODY; return 0; }
void FQTermHttp::getLink(const QUrl& url, bool preview) { QUrl u=url; isExisting_ = false; isPreview_ = preview; previewEmitted = false; lastPercent_ = 0; if (u.isRelative() || u.scheme() == "file") { emit previewImage(cacheFileName_, false, true); emit done(this); return ; } if (QFile::exists(getPath(USER_CONFIG) + "hosts.cfg")) { config_ = new FQTermConfig(getPath(USER_CONFIG) + "hosts.cfg"); QString strTmp = config_->getItemValue("hosts", u.host().toLocal8Bit()); if (!strTmp.isEmpty()) { QString strUrl = u.toString(); strUrl.replace(QRegExp(u.host(), Qt::CaseInsensitive), strTmp); u = strUrl; } } if (!(netreply_ && netreply_->hasRawHeader("Location"))) { cacheFileName_ = QFileInfo(u.path()).fileName(); } if(netreply_){ netreply_->blockSignals(true); netreply_.take()->deleteLater(); } netreply_.reset(nam_->get(QNetworkRequest(u))); FQ_VERIFY(connect(netreply_.data(), SIGNAL(finished()), this, SLOT(httpDone()))); FQ_VERIFY(connect(netreply_.data(), SIGNAL(downloadProgress(qint64, qint64)),this, SLOT(httpRead(qint64, qint64)))); FQ_VERIFY(connect(netreply_.data(), SIGNAL(error( QNetworkReply::NetworkError)), this, SLOT(httpError(QNetworkReply::NetworkError)))); FQ_VERIFY(connect(netreply_.data(), SIGNAL(metaDataChanged()), this, SLOT(httpResponse()))); }
PUBLIC ssize receive(char *buf, ssize len) { return httpRead(getStream(), buf, len); }
static void httpGetObject(App *app, HTTP *http, int sock) { Buf *buf; HTTPNameValue *h; app->printHTML(app, "<h4>Request</h4>"); app->printHTML(app, "<pre>"); buf = bufAlloc(sock); bufMark(buf, 0); bufPutString(buf, (unsigned char *) "GET "); if (http->url->path) { bufPutString(buf, http->url->path); } if (http->url->params) { bufPutString(buf, http->url->params); } if (http->url->query) { bufPutString(buf, http->url->query); } bufPutChar(buf, ' '); bufPutString(buf, http->version); bufPutString(buf, (unsigned char *) "\r\n"); bufMark(buf, 0); app->httpRequest(app, buf); h = http->headers; if (h) { while (h->name) { httpPutHeader(app, buf, (char *) h->name, (char *) h->value); h++; } } httpPutHeader(app, buf, "Connection", "close"); httpPutHeader(app, buf, "Host", (char *) http->url->host); bufPutString(buf, (unsigned char *) "\r\n"); bufMark(buf, 0); app->httpRequest(app, buf); app->printHTML(app, "</pre>"); if (bufError(buf)) { return; } bufSend(buf); bufFree(buf); httpRead(app, http, sock); }
ssize espReceive(HttpConn *conn, char *buf, ssize len) { return httpRead(conn, buf, len); }
void translate_messages(const char *language)/* I - Output language... */ { /* * Google provides a simple translation/language tool for translating * from one language to another. It is far from perfect, however it * can be used to get a basic translation done or update an existing * translation when no other resources are available. * * Translation requests are sent as HTTP POSTs to * "http://translate.google.com/translate_t" with the following form * variables: * * Name Description Value * -------- ---------------------------------- ---------------- * hl Help language? "en" * ie Input encoding "UTF8" * langpair Language pair "en|" + language * oe Output encoding "UTF8" * text Text to translate translation string */ int i; /* Looping var */ message_t *m; /* Current message */ int tries; /* Number of tries... */ http_t *http; /* HTTP connection */ http_status_t status; /* Status of POST request */ char *idptr, /* Pointer into msgid */ *strptr, /* Pointer into msgstr */ buffer[65536], /* Input/output buffer */ *bufptr, /* Pointer into buffer */ *bufend, /* Pointer to end of buffer */ length[16]; /* Content length */ unsigned char *utf8; /* UTF-8 string */ int ch; /* Current decoded character */ int bytes; /* Number of bytes read */ /* * Connect to translate.google.com... */ puts("Connecting to translate.google.com..."); if ((http = httpConnect("translate.google.com", 80)) == NULL) { perror("Unable to connect to translate.google.com"); return; } /* * Scan the current messages, requesting a translation of any untranslated * messages... */ for (i = num_messages, m = messages; i > 0; i --, m ++) { /* * Skip messages that are already translated... */ if (m->str && m->str[0]) continue; /* * Encode the form data into the buffer... */ snprintf(buffer, sizeof(buffer), "hl=en&ie=UTF8&langpair=en|%s&oe=UTF8&text=", language); bufptr = buffer + strlen(buffer); bufend = buffer + sizeof(buffer) - 5; for (idptr = m->id; *idptr && bufptr < bufend; idptr ++) if (*idptr == ' ') *bufptr++ = '+'; else if (*idptr < ' ' || *idptr == '%') { sprintf(bufptr, "%%%02X", *idptr & 255); bufptr += 3; } else if (*idptr != '&') *bufptr++ = *idptr; *bufptr++ = '&'; *bufptr = '\0'; sprintf(length, "%d", bufptr - buffer); /* * Send the request... */ printf("\"%s\" = ", m->id); fflush(stdout); tries = 0; do { httpClearFields(http); httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/x-www-form-urlencoded"); httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); if (httpPost(http, "/translate_t")) { httpReconnect(http); httpPost(http, "/translate_t"); } httpWrite(http, buffer, bufptr - buffer); while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status != HTTP_OK && status != HTTP_ERROR) httpFlush(http); tries ++; } while (status == HTTP_ERROR && tries < 10); if (status == HTTP_OK) { /* * OK, read the translation back... */ bufptr = buffer; bufend = buffer + sizeof(buffer) - 1; while ((bytes = httpRead(http, bufptr, bufend - bufptr)) > 0) bufptr += bytes; if (bytes < 0) { /* * Read error, abort! */ puts("READ ERROR!"); break; } *bufptr = '\0'; /* * Find the first textarea element - that will have the translation data... */ if ((bufptr = strstr(buffer, "<textarea")) == NULL) { /* * No textarea, abort! */ puts("NO TEXTAREA!"); break; } if ((bufptr = strchr(bufptr, '>')) == NULL) { /* * textarea doesn't end, abort! */ puts("TEXTAREA SHORT DATA!"); break; } utf8 = (unsigned char *)bufptr + 1; if ((bufend = strstr(bufptr, "</textarea>")) == NULL) { /* * textarea doesn't close, abort! */ puts("/TEXTAREA SHORT DATA!"); break; } *bufend = '\0'; /* * Copy the UTF-8 translation to ISO-8859-1 (for now)... */ m->str = malloc(bufend - bufptr); for (strptr = m->str; *utf8;) if (*utf8 < 0x80) *strptr++ = *utf8++; else { if ((*utf8 & 0xe0) == 0xc0) { /* * Two-byte encoding... */ ch = ((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f); utf8 += 2; } else if ((ch & 0xf0) == 0xe0) { /* * Three-byte encoding... */ ch = ((((utf8[0] & 0x0f) << 6) | (utf8[1] & 0x3f)) << 6) | (utf8[2] & 0x3f); utf8 += 3; } if (ch < 256) /* ISO-8859-1 */ *strptr++ = ch; else if (ch == 0x20ac) /* Euro */ *strptr++ = 0xA4; /* ISO-8859-15 mapping */ } *strptr = '\0'; printf("\"%s\"\n", m->str); } else if (status == HTTP_ERROR) { printf("NETWORK ERROR (%s)!\n", strerror(httpError(http))); break; } else { printf("HTTP ERROR %d!\n", status); break; } } httpClose(http); }
std::string TcpServer::getRequest(int clientFd) const { return httpRead(clientFd); }
char * /* O - Pathname or NULL */ file_find(const char *path, /* I - Path "dir;dir;dir" */ const char *s) /* I - File to find */ { int i; /* Looping var */ int retry; /* Current retry */ char *temp, /* Current position in filename */ method[HTTP_MAX_URI], /* Method/scheme */ username[HTTP_MAX_URI], /* Username:password */ hostname[HTTP_MAX_URI], /* Hostname */ resource[HTTP_MAX_URI]; /* Resource */ int port; /* Port number */ const char *connhost; /* Host to connect to */ int connport; /* Port to connect to */ char connpath[HTTP_MAX_URI], /* Path for GET */ connauth[HTTP_MAX_VALUE];/* Auth string */ http_status_t status; /* Status of request... */ FILE *fp; /* Web file */ int bytes, /* Bytes read */ count, /* Number of bytes so far */ total; /* Total bytes in file */ static char filename[HTTP_MAX_URI]; /* Current filename */ /* * If the filename is NULL, return NULL... */ if (s == NULL) return (NULL); if (strncmp(s, "http:", 5) == 0 || (path != NULL && strncmp(path, "http:", 5) == 0)) strcpy(method, "http"); #ifdef HAVE_LIBSSL else if (strncmp(s, "https:", 6) == 0 || (path != NULL && strncmp(path, "https:", 6) == 0)) strcpy(method, "https"); #endif /* HAVE_LIBSSL */ else strcpy(method, "file"); if (strcmp(method, "file") == 0) { /* * If the path is NULL or empty, return the filename... */ if (path == NULL || !path[0]) return ((char *)s); /* * Else loop through the path string until we reach the end... */ while (*path != '\0') { /* * Copy the path directory... */ temp = filename; while (*path != ';' && *path && temp < (filename + sizeof(filename) - 1)) *temp++ = *path++; if (*path == ';') path ++; /* * Append a slash as needed... */ if (temp > filename && temp < (filename + sizeof(filename) - 1) && s[0] != '/') *temp++ = '/'; /* * Append the filename... */ strncpy(temp, s, sizeof(filename) - (temp - filename)); filename[sizeof(filename) - 1] = '\0'; /* * See if the file exists... */ if (!access(filename, 0)) return (filename); } } else { /* * Remote file; look it up in the web cache, and then try getting it * from the remote system... */ for (i = 0; i < web_files; i ++) if (web_cache[i].url && strcmp(web_cache[i].url, s) == 0) return (web_cache[i].name); #ifdef HAVE_LIBSSL if (strncmp(s, "http:", 5) == 0 || strncmp(s, "https:", 6) == 0) #else if (strncmp(s, "http:", 5) == 0) #endif /* HAVE_LIBSSL */ httpSeparate(s, method, username, hostname, &port, resource); else if (s[0] == '/') { httpSeparate(path, method, username, hostname, &port, resource); strcpy(resource, s); } else { if (strncmp(s, "./", 2) == 0) snprintf(filename, sizeof(filename), "%s/%s", path, s + 2); else snprintf(filename, sizeof(filename), "%s/%s", path, s); httpSeparate(filename, method, username, hostname, &port, resource); } for (status = HTTP_ERROR, retry = 0; status == HTTP_ERROR && retry < 5; retry ++) { if (proxy_port) { /* * Send request to proxy host... */ connhost = proxy_host; connport = proxy_port; snprintf(connpath, sizeof(connpath), "%s://%s:%d%s", method, hostname, port, resource); } else { /* * Send request to host directly... */ connhost = hostname; connport = port; strcpy(connpath, resource); } if (http != NULL && strcasecmp(http->hostname, hostname) != 0) { httpClose(http); http = NULL; } if (http == NULL) { progress_show("Connecting to %s...", connhost); atexit(file_cleanup); #ifdef HAVE_LIBSSL if (strcmp(method, "http") == 0) http = httpConnect(connhost, connport); else http = httpConnectEncrypt(connhost, connport, HTTP_ENCRYPT_ALWAYS); #else http = httpConnect(connhost, connport); #endif /* HAVE_LIBSSL */ if (http == NULL) { progress_hide(); progress_error("Unable to connect to %s!", connhost); return (NULL); } } progress_show("Getting %s...", connpath); httpClearFields(http); httpSetField(http, HTTP_FIELD_HOST, hostname); httpSetField(http, HTTP_FIELD_USER_AGENT, "HTMLDOC v" SVERSION); httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive"); if (username[0]) { strcpy(connauth, "Basic "); httpEncode64(connauth + 6, username); httpSetField(http, HTTP_FIELD_AUTHORIZATION, connauth); } if (!httpGet(http, connpath)) while ((status = httpUpdate(http)) == HTTP_CONTINUE); else status = HTTP_ERROR; if (status >= HTTP_MOVED_PERMANENTLY && status <= HTTP_SEE_OTHER) { /* * Flush text... */ httpFlush(http); /* * Grab new location from HTTP data... */ httpSeparate(httpGetField(http, HTTP_FIELD_LOCATION), method, username, hostname, &port, resource); status = HTTP_ERROR; } } if (status != HTTP_OK) { progress_hide(); progress_error("HTTP error %d: %s!", status, httpStatus(status)); httpFlush(http); return (NULL); } if ((fp = file_temp(filename, sizeof(filename))) == NULL) { progress_hide(); progress_error("Unable to create temporary file \"%s\": %s", filename, strerror(errno)); httpFlush(http); return (NULL); } if ((total = atoi(httpGetField(http, HTTP_FIELD_CONTENT_LENGTH))) == 0) total = 8192; count = 0; while ((bytes = httpRead(http, resource, sizeof(resource))) > 0) { count += bytes; progress_update((100 * count / total) % 101); fwrite(resource, 1, bytes, fp); } progress_hide(); fclose(fp); web_cache[web_files - 1].name = strdup(filename); web_cache[web_files - 1].url = strdup(s); return (filename); } return (NULL); }