Base code merged to SPIN 2.4
[platform/upstream/curl.git] / lib / gopher.c
index 2fab6da..f3fd065 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  *
  ***************************************************************************/
 
-#include "setup.h"
+#include "curl_setup.h"
 
 #ifndef CURL_DISABLE_GOPHER
 
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#else
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#include <netinet/in.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <netdb.h>
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-
-#endif
-
 #include "urldata.h"
 #include <curl/curl.h>
 #include "transfer.h"
 #include "strequal.h"
 #include "gopher.h"
 #include "rawstr.h"
+#include "select.h"
+#include "url.h"
+#include "warnless.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
 
+#include "curl_memory.h"
 /* The last #include file should be: */
 #include "memdebug.h"
 
-
 /*
  * Forward declarations.
  */
@@ -107,10 +67,13 @@ const struct Curl_handler Curl_handler_gopher = {
   ZERO_NULL,                            /* doing */
   ZERO_NULL,                            /* proto_getsock */
   ZERO_NULL,                            /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
   ZERO_NULL,                            /* perform_getsock */
   ZERO_NULL,                            /* disconnect */
+  ZERO_NULL,                            /* readwrite */
   PORT_GOPHER,                          /* defport */
-  PROT_GOPHER                           /* protocol */
+  CURLPROTO_GOPHER,                     /* protocol */
+  PROTOPT_NONE                          /* flags */
 };
 
 static CURLcode gopher_do(struct connectdata *conn, bool *done)
@@ -122,16 +85,18 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   curl_off_t *bytecount = &data->req.bytecount;
   char *path = data->state.path;
   char *sel;
+  char *sel_org = NULL;
   ssize_t amount, k;
 
   *done = TRUE; /* unconditionally */
 
   /* Create selector. Degenerate cases: / and /1 => convert to "" */
-  if (strlen(path) <= 2)
+  if(strlen(path) <= 2)
     sel = (char *)"";
   else {
     char *newp;
-    int i, j, len;
+    size_t j, i;
+    int len;
 
     /* Otherwise, drop / and the first character (i.e., item type) ... */
     newp = path;
@@ -139,38 +104,63 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
 
     /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
     j = strlen(newp);
-    if (j)
-      for(i=0; i<j; i++)
-        newp[i] = ((newp[i] == '?') ? '\x09' : newp[i]);
+    for(i=0; i<j; i++)
+      if(newp[i] == '?')
+        newp[i] = '\x09';
 
     /* ... and finally unescape */
     sel = curl_easy_unescape(data, newp, 0, &len);
-    if (!sel)
+    if(!sel)
       return CURLE_OUT_OF_MEMORY;
+    sel_org = sel;
   }
 
-  /* We use Curl_write instead of Curl_sendf to make sure the entire buffer
-     is sent, which could be sizeable with long selectors. */
-  k = strlen(sel);
+  /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is
+     sent, which could be sizeable with long selectors. */
+  k = curlx_uztosz(strlen(sel));
+
   for(;;) {
     result = Curl_write(conn, sockfd, sel, k, &amount);
-    if (CURLE_OK == result) { /* Which may not have written it all! */
+    if(!result) { /* Which may not have written it all! */
+      result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
+      if(result) {
+        Curl_safefree(sel_org);
+        return result;
+      }
       k -= amount;
       sel += amount;
-      if (k < 1)
+      if(k < 1)
         break; /* but it did write it all */
-    } else {
+    }
+    else {
       failf(data, "Failed sending Gopher request");
+      Curl_safefree(sel_org);
       return result;
     }
+    /* Don't busyloop. The entire loop thing is a work-around as it causes a
+       BLOCKING behavior which is a NO-NO. This function should rather be
+       split up in a do and a doing piece where the pieces that aren't
+       possible to send now will be sent in the doing function repeatedly
+       until the entire request is sent.
+
+       Wait a while for the socket to be writable. Note that this doesn't
+       acknowledge the timeout.
+    */
+    Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100);
   }
+
+  Curl_safefree(sel_org);
+
   /* We can use Curl_sendf to send the terminal \r\n relatively safely and
      save allocing another string/doing another _write loop. */
   result = Curl_sendf(sockfd, conn, "\r\n");
-  if (result != CURLE_OK) {
+  if(result) {
     failf(data, "Failed sending Gopher request");
     return result;
   }
+  result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
+  if(result)
+    return result;
 
   Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
                       -1, NULL); /* no upload */