/************************************************************************* Writes buf to socket and returns the response in an fz_FILE. Use only on blocking sockets. *************************************************************************/ fz_FILE *fc_querysocket(int sock, void *buf, size_t size) { FILE *fp; #ifdef HAVE_FDOPEN fp = fdopen(sock, "r+b"); if (fwrite(buf, 1, size, fp) != size) { log_error("socket %d: write error", sock); } fflush(fp); /* we don't use fc_closesocket on sock here since when fp is closed * sock will also be closed. fdopen doesn't dup the socket descriptor. */ #else /* HAVE_FDOPEN */ { char tmp[4096]; int n; #ifdef WIN32_NATIVE /* tmpfile() in mingw attempts to make a temp file in the root directory * of the current drive, which we may not have write access to. */ { char filename[MAX_PATH]; GetTempPath(sizeof(filename), filename); sz_strlcat(filename, "fctmp"); fp = fc_fopen(filename, "w+b"); } #else /* WIN32_NATIVE */ fp = tmpfile(); #endif /* WIN32_NATIVE */ if (fp == NULL) { return NULL; } fc_writesocket(sock, buf, size); while ((n = fc_readsocket(sock, tmp, sizeof(tmp))) > 0) { if (fwrite(tmp, 1, n, fp) != n) { log_error("socket %d: write error", sock); } } fflush(fp); fc_closesocket(sock); rewind(fp); } #endif /* HAVE_FDOPEN */ return fz_from_stream(fp); }
/**************************************************************************** Read the request string (or part of it) from the metaserver. ****************************************************************************/ static void meta_read_response(struct server_scan *scan) { char buf[4096]; int result; if (!scan->meta.fp) { #ifdef WIN32_NATIVE char filename[MAX_PATH]; GetTempPath(sizeof(filename), filename); cat_snprintf(filename, sizeof(filename), "fctmp%d", myrand(1000)); scan->meta.fp = fc_fopen(filename, "w+b"); #else scan->meta.fp = tmpfile(); #endif if (!scan->meta.fp) { scan->error_func(scan, _("Could not open temp file.")); } } while (1) { result = fc_readsocket(scan->sock, buf, sizeof(buf)); if (result < 0) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { /* Keep waiting. */ return; } scan->error_func(scan, fc_strerror(fc_get_errno())); return; } else if (result == 0) { fz_FILE *f; char str[4096]; /* We're done! */ rewind(scan->meta.fp); f = fz_from_stream(scan->meta.fp); assert(f != NULL); /* skip HTTP headers */ /* XXX: TODO check for magic Content-Type: text/x-ini -vasc */ while (fz_fgets(str, sizeof(str), f) && strcmp(str, "\r\n") != 0) { /* nothing */ } /* XXX: TODO check for magic Content-Type: text/x-ini -vasc */ /* parse HTTP message body */ scan->servers = parse_metaserver_data(f); scan->meta.state = META_DONE; /* 'f' (hence 'meta.fp') was closed in parse_metaserver_data(). */ scan->meta.fp = NULL; if (NULL == scan->servers) { my_snprintf(str, sizeof(str), _("Failed to parse the metaserver data from http://%s."), scan->meta.name); scan->error_func(scan, str); } return; } else { if (fwrite(buf, 1, result, scan->meta.fp) != result) { scan->error_func(scan, fc_strerror(fc_get_errno())); } } } }