void HumdrumFileBasic::readFromHttpURI(const char* webaddress) { Array<char> hostname; Array<char> location; location.setSize(0); const char* ptr = webaddress; const char* filename = NULL; if (strncmp(webaddress, "http://", strlen("http://")) == 0) { // remove the "http://" portion of the webaddress ptr += strlen("http://"); } hostname.setSize(strlen(ptr)+1); hostname.setGrowth(0); strcpy(hostname.getBase(), ptr); char* pot; if ((pot = strchr(hostname.getBase(), '/')) != NULL) { *pot = '\0'; } if ((filename = strchr(ptr, '/')) != NULL) { location.setSize(strlen(filename)+1); strcpy(location.getBase(), filename); location.allowGrowth(0); } if (location.getSize() == 0) { location.setSize(2); location.allowGrowth(0); strcpy(location.getBase(), "/"); } char newline[3] = {0x0d, 0x0a, 0}; SSTREAM request; request << "GET " << location.getBase() << " HTTP/1.1" << newline; request << "Host: " << hostname.getBase() << newline; request << "User-Agent: HumdrumFile Downloader 1.0 (" << __DATE__ << ")" << newline; request << "Connection: close" << newline; // this line is necessary request << newline; request << ends; // cout << "HOSTNAME: " << hostname.getBase() << endl; // cout << "LOCATION: " << location.getBase() << endl; // cout << request.CSTRING << endl; // cout << "-------------------------------------------------" << endl; int socket_id = open_network_socket(hostname.getBase(), 80); ::write(socket_id, request.CSTRING, strlen(request.CSTRING)); #define URI_BUFFER_SIZE (10000) char buffer[URI_BUFFER_SIZE]; int message_len; SSTREAM inputdata; SSTREAM header; int foundcontent = 0; int i; int newlinecounter = 0; // read the response header: while ((message_len = ::read(socket_id, buffer, 1)) != 0) { header << buffer[0]; if ((buffer[0] == 0x0a) || (buffer[0] == 0x0d)) { newlinecounter++; } else { newlinecounter = 0; } if (newlinecounter == 4) { foundcontent = 1; break; } } if (foundcontent == 0) { cerr << "Funny error trying to read server response" << endl; exit(1); } // now read the size of the rest of the data which is expected int datalength = -1; // also, check for chunked transfer encoding: int chunked = 0; header << ends; // cout << header.CSTRING << endl; // cout << "-------------------------------------------------" << endl; while (header.getline(buffer, URI_BUFFER_SIZE)) { int len = strlen(buffer); for (i=0; i<len; i++) { buffer[i] = tolower(buffer[i]); } if (strstr(buffer, "content-length") != NULL) { for (i=14; i<len; i++) { if (isdigit(buffer[i])) { sscanf(&buffer[i], "%d", &datalength); if (datalength == 0) { cerr << "Error: no data found for URI, probably invalid\n"; exit(1); } break; } } } else if ((strstr(buffer, "transfer-encoding") != NULL) && (strstr(buffer, "chunked") != NULL)) { chunked = 1; } // if (datalength >= 0) { // break; // } } // once the length of the remaining data is known (or not), read it: if (datalength > 0) { getFixedDataSize(socket_id, datalength, inputdata, buffer, URI_BUFFER_SIZE); } else if (chunked) { int chunksize; int totalsize = 0; do { chunksize = getChunk(socket_id, inputdata, buffer, URI_BUFFER_SIZE); totalsize += chunksize; } while (chunksize > 0); if (totalsize == 0) { cerr << "Error: no data found for URI (probably invalid)\n"; exit(1); } } else { // if the size of the rest of the data cannot be found in the // header, then just keep reading until done (but this will // probably cause a 5 second delay at the last read). while ((message_len = ::read(socket_id, buffer, URI_BUFFER_SIZE)) != 0) { if (foundcontent) { inputdata.write(buffer, message_len); } else { for (i=0; i<message_len; i++) { if (foundcontent) { inputdata << buffer[i]; } else { header << buffer[i]; if ((buffer[i] == 0x0a) || (buffer[i] == 0x0d)) { newlinecounter++; } else { newlinecounter = 0; } if (newlinecounter == 4) { foundcontent = 1; continue; } } } } } } close(socket_id); inputdata << ends; // cout << "CONTENT:=======================================" << endl; // cout << inputdata.CSTRING; // cout << "===============================================" << endl; HumdrumFileBasic::read(inputdata); }