Esempio n. 1
0
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);
}