Example #1
0
File: dpip.c Project: epitron/dillo
/*
 * Return a newlly allocated string with the next dpip token in the socket.
 * Return value: token string and length on success, NULL otherwise.
 * (useful for handling null characters in the data stream)
 */
char *a_Dpip_dsh_read_token2(Dsh *dsh, int blocking, int *DataSize)
{
   char *p, *ret = NULL;
   *DataSize = 0;

   /* Read all available data without blocking */
   Dpip_dsh_read(dsh, 0);

   /* switch mode upon request */
   if (dsh->mode & DPIP_LAST_TAG)
      dsh->mode = DPIP_RAW;

   if (blocking) {
      if (dsh->mode & DPIP_TAG) {
         /* Only wait for data when the tag is incomplete */
         if (!strstr(dsh->rdbuf->str, DPIP_TAG_END)) {
             do {
                Dpip_dsh_read(dsh, 1);
                p = strstr(dsh->rdbuf->str, DPIP_TAG_END);
             } while (!p && dsh->status == EAGAIN);
         }

      } else if (dsh->mode & DPIP_RAW) {
         /* Wait for data when the buffer is empty and there's no ERR/EOF */
         while (dsh->rdbuf->len == 0 &&
                dsh->status != DPIP_ERROR && dsh->status != DPIP_EOF)
            Dpip_dsh_read(dsh, 1);
      }
   }

   if (dsh->mode & DPIP_TAG) {
      /* return a full tag */
      if ((p = strstr(dsh->rdbuf->str, DPIP_TAG_END))) {
         ret = dStrndup(dsh->rdbuf->str, p - dsh->rdbuf->str + 3);
         *DataSize = p - dsh->rdbuf->str + 3;
         dStr_erase(dsh->rdbuf, 0, p - dsh->rdbuf->str + 3);
         if (strstr(ret, DPIP_MODE_SWITCH_TAG))
            dsh->mode |= DPIP_LAST_TAG;
      }
   } else {
      /* raw mode, return what we have "as is" */
      if (dsh->rdbuf->len > 0) {
         ret = dStrndup(dsh->rdbuf->str, dsh->rdbuf->len);
         *DataSize = dsh->rdbuf->len;
         dStr_truncate(dsh->rdbuf, 0);
      }
   }

   return ret;
}
Example #2
0
/*
 * Extract a single field from the header, allocating and storing the value
 * in 'field'. ('fieldname' must not include the trailing ':')
 * Return a new string with the field-content if found (NULL on error)
 * (This function expects a '\r'-stripped header, with one-line header fields)
 */
static char *Cache_parse_field(const char *header, const char *fieldname)
{
   char *field;
   uint_t i, j;

   for (i = 0; header[i]; i++) {
      /* Search fieldname */
      for (j = 0; fieldname[j]; j++)
        if (D_ASCII_TOLOWER(fieldname[j]) != D_ASCII_TOLOWER(header[i + j]))
           break;
      if (fieldname[j]) {
         /* skip to next line */
         for ( i += j; header[i] != '\n'; i++);
         continue;
      }

      i += j;
      if (header[i] == ':') {
        /* Field found! */
        while (header[++i] == ' ' || header[i] == '\t');
        for (j = 0; header[i + j] != '\n'; j++);
        while (j && (header[i + j - 1] == ' ' || header[i + j - 1] == '\t'))
           j--;
        field = dStrndup(header + i, j);
        return field;
      }
      while (header[i] != '\n') i++;
   }
   return NULL;
}
Example #3
0
/*
 * If the url belongs to a dpi server, return its name.
 */
static int Capi_url_uses_dpi(DilloUrl *url, char **server_ptr)
{
   char *p, *server = NULL, *url_str = URL_STR(url);
   Dstr *tmp;

   if ((dStrncasecmp(url_str, "http:", 5) == 0) ||
       (dStrncasecmp(url_str, "about:", 6) == 0)) {
      /* URL doesn't use dpi (server = NULL) */
   } else if (dStrncasecmp(url_str, "dpi:/", 5) == 0) {
      /* dpi prefix, get this server's name */
      if ((p = strchr(url_str + 5, '/')) != NULL) {
         server = dStrndup(url_str + 5, (uint_t)(p - url_str - 5));
      } else {
         server = dStrdup("?");
      }
      if (strcmp(server, "bm") == 0) {
         dFree(server);
         server = dStrdup("bookmarks");
      }
   } else if ((p = strchr(url_str, ':')) != NULL) {
      tmp = dStr_new("proto.");
      dStr_append_l(tmp, url_str, p - url_str);
      server = tmp->str;
      dStr_free(tmp, 0);
   }

   return ((*server_ptr = server) ? 1 : 0);
}
Example #4
0
File: dpip.c Project: epitron/dillo
/*
 * Task: given a tag, its size and an attribute name, return the
 * attribute value (stuffing of ' is removed here).
 *
 * Return value: the attribute value, or NULL if not present or malformed.
 */
char *a_Dpip_get_attr_l(const char *tag, size_t tagsize, const char *attrname)
{
   uint_t i, n = 0, found = 0;
   const char *p, *q, *start;
   char *r, *s, *val = NULL;
   DpipTagParsingState state = SEEK_NAME;

   if (!tag || !tagsize || !attrname || !*attrname)
      return NULL;

   for (i = 1; i < tagsize && !found; ++i) {
      switch (state) {
      case SEEK_NAME:
         if (tag[i] == attrname[0] && (tag[i-1] == ' ' || tag[i-1] == '<')) {
            n = 1;
            state = MATCH_NAME;
         } else if (tag[i] == Quote && tag[i-1] == '=')
            state = SKIP_VALUE;
         break;
      case MATCH_NAME:
         if (tag[i] == attrname[n])
            ++n;
         else if (tag[i] == '=' && !attrname[n])
            state = FOUND;
         else
            state = SEEK_NAME;
         break;
      case SKIP_VALUE:
         if (tag[i] == Quote)
            state = (tag[i+1] == Quote) ? SKIP_QUOTE : SEEK_NAME;
         break;
      case SKIP_QUOTE:
         state = SKIP_VALUE;
         break;
      case FOUND:
         found = 1;
         break;
      }
   }

   if (found) {
      p = start = tag + i;
      while ((q = strchr(p, Quote)) && q[1] == Quote)
         p = q + 2;
      if (q && q[1] == ' ') {
         val = dStrndup(start, (uint_t)(q - start));
         for (r = s = val; (*r = *s); ++r, ++s)
            if (s[0] == Quote && s[0] == s[1])
               ++s;
      }
   }
   return val;
}
Example #5
0
/*
 * Extract multiple fields from the header.
 */
static Dlist *Cache_parse_multiple_fields(const char *header,
                                          const char *fieldname)
{
   uint_t i, j;
   Dlist *fields = dList_new(8);
   char *field;

   for (i = 0; header[i]; i++) {
      /* Search fieldname */
      for (j = 0; fieldname[j]; j++)
         if (D_ASCII_TOLOWER(fieldname[j]) != D_ASCII_TOLOWER(header[i + j]))
            break;
      if (fieldname[j]) {
         /* skip to next line */
         for (i += j; header[i] != '\n'; i++);
         continue;
      }

      i += j;
      if (header[i] == ':') {
         /* Field found! */
         while (header[++i] == ' ' || header[i] == '\t');
         for (j = 0; header[i + j] != '\n'; j++);
         while (j && (header[i + j - 1] == ' ' || header[i + j - 1] == '\t'))
            j--;
         field = dStrndup(header + i, j);
         dList_append(fields, field);
      } else {
         while (header[i] != '\n') i++;
      }
   }

   if (dList_length(fields) == 0) {
      dList_free(fields);
      fields = NULL;
   }
   return fields;
}
Example #6
0
/*
 * Receive new data, update the reception buffer (for next read), update the
 * cache, and service the client queue.
 *
 * This function gets called whenever the IO has new data.
 *  'Op' is the operation to perform
 *  'VPtr' is a (void) pointer to the IO control structure
 */
void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size,
                          const DilloUrl *Url)
{
   int offset, len;
   const char *str;
   Dstr *dstr1, *dstr2, *dstr3;
   CacheEntry_t *entry = Cache_entry_search(Url);

   /* Assert a valid entry (not aborted) */
   dReturn_if_fail (entry != NULL);

   _MSG("__a_Cache_process_dbuf__\n");

   if (Op == IORead) {
      /*
       * Cache_get_header() will set CA_GotHeader if it has a full header, and
       * Cache_parse_header() will unset it if the header ends being
       * merely an informational response from the server (i.e., 100 Continue)
       */
      for (offset = 0; !(entry->Flags & CA_GotHeader) &&
           (len = Cache_get_header(entry, buf + offset, buf_size - offset));
           Cache_parse_header(entry) ) {
         offset += len;
      }

      if (entry->Flags & CA_GotHeader) {
         str = buf + offset;
         len = buf_size - offset;
         entry->TransferSize += len;
         dstr1 = dstr2 = dstr3 = NULL;

         /* Decode arrived data (<= 3 stages) */
         if (entry->TransferDecoder) {
            dstr1 = a_Decode_process(entry->TransferDecoder, str, len);
            str = dstr1->str;
            len = dstr1->len;
         }
         if (entry->ContentDecoder) {
            dstr2 = a_Decode_process(entry->ContentDecoder, str, len);
            str = dstr2->str;
            len = dstr2->len;
         }
         dStr_append_l(entry->Data, str, len);
         if (entry->CharsetDecoder && entry->UTF8Data) {
            dstr3 = a_Decode_process(entry->CharsetDecoder, str, len);
            dStr_append_l(entry->UTF8Data, dstr3->str, dstr3->len);
         }
         dStr_free(dstr1, 1);
         dStr_free(dstr2, 1);
         dStr_free(dstr3, 1);

         if (entry->Data->len)
            entry->Flags &= ~CA_IsEmpty;

         entry = Cache_process_queue(entry);
      }
   } else if (Op == IOClose) {
      if ((entry->ExpectedSize || entry->TransferSize) &&
          entry->TypeHdr == NULL) {
         MSG_HTTP("Message with a body lacked Content-Type header.\n");
      }
      if ((entry->Flags & CA_GotLength) &&
          (entry->ExpectedSize != entry->TransferSize)) {
         MSG_HTTP("Content-Length does NOT match message body,\n"
                  " at: %s\n", URL_STR_(entry->Url));
         MSG("entry->ExpectedSize = %d, entry->TransferSize = %d\n",
             entry->ExpectedSize, entry->TransferSize);
      }
      if (!entry->TransferSize && !(entry->Flags & CA_Redirect) &&
          (entry->Flags & WEB_RootUrl)) {
         char *eol = strchr(entry->Header->str, '\n');
         if (eol) {
            char *status_line = dStrndup(entry->Header->str,
                                         eol - entry->Header->str);
            MSG_HTTP("Body was empty. Server sent status: %s\n", status_line);
            dFree(status_line);
         }
      }
      entry->Flags |= CA_GotData;
      entry->Flags &= ~CA_Stopped;          /* it may catch up! */
      if (entry->TransferDecoder) {
         a_Decode_free(entry->TransferDecoder);
         entry->TransferDecoder = NULL;
      }
      if (entry->ContentDecoder) {
         a_Decode_free(entry->ContentDecoder);
         entry->ContentDecoder = NULL;
      }
      dStr_fit(entry->Data);                /* fit buffer size! */

      if ((entry = Cache_process_queue(entry))) {
         if (entry->Flags & CA_GotHeader) {
            Cache_unref_data(entry);
         }
      }
   } else if (Op == IOAbort) {
      /* unused */
      MSG("a_Cache_process_dbuf Op = IOAbort; not implemented!\n");
   }
}