Logo Search packages:      
Sourcecode: yics version File versions  Download package

http.c

/*
 * YICS: Connect a FICS interface to the Yahoo! Chess server.
 * Copyright (C) 2004  Chris Howie
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "http.h"
#include "sockets.h"
#include "network.h"

#define sendstr(s,str) send(s, str, strlen(str), 0)

static const char hextable[16] = "0123456789ABCDEF";

/* This set of characters is based on the "uric" set in RFC 2396/2732 as
 * explained in the URI::Escape manpage.
 */
#define IsLetter(x) ( \
      (((x) >= 'A') && ((x) <= 'Z')) || \
      (((x) >= 'a') && ((x) <= 'z')) \
)
#define IsNumber(x) (((x) >= '0') && ((x) <= '9'))
#define IsSpecial(x) ( \
      ((x) == '-') || ((x) == '_') || ((x) == '.') || ((x) == '!') || \
      ((x) == '~') || ((x) == '*') || ((x) == '\'') || ((x) == '(') || \
      ((x) == ')') \
)
#define IsUric(x) (IsLetter(x) || IsNumber(x) || IsSpecial(x))

static char *uri_escape(char *out, const char *in) {
      unsigned char c;

      while ((c = *(in++)) != '\0') {
            if (IsUric(c)) {
                  *(out++) = c;
            } else {
                  *(out++) = '%';
                  *(out++) = hextable[c >> 4];
                  *(out++) = hextable[c & 0x0F];
            }
      }

      *out = '\0';

      return out;
}

static void build_query(char *out, ValuePair data[]) {
      int gotone = 0;

      while (data->key) {
            if (gotone)
                  *(out++) = '&';

            out = uri_escape(out, data->key);
            *(out++) = '=';
            out = uri_escape(out, data->value);

            gotone = 1;

            data++;
      }

      *out = '\0';
}

int http_get(char *server, char *path, ValuePair form[], char *cookies[], int *sout) {
      int s, cp, i;
      int got_status = 0, status;
      static char tmp[8192], tmp2[256];
      char *cookie, *ch, *ckp;

      s = nconnect(server, 80);
      if (s < 0)
            return -1;

      if (form && form[0].key) {
            build_query(tmp2, form);
            snprintf(tmp, sizeof(tmp), "GET %s?%s HTTP/1.1\r\n", path, tmp2);
      } else {
            snprintf(tmp, sizeof(tmp), "GET %s HTTP/1.1\r\n", path);
      }

      sendstr(s, tmp);

      snprintf(tmp, sizeof(tmp), "Host: %s\r\n", server);
      sendstr(s, tmp);

#if (defined (linux) || defined (__linux) || defined (__linux__))
# define HTTP_OSNAME "; linux"
#elif (defined (unix) || defined (__unix) || defined (__unix__))
# define HTTP_OSNAME "; unix"
#elif (defined (WINNT) || defined (__WINNT) || defined (__WINNT__) || defined (_WIN32) || defined (_WINDOWS))
# define HTTP_OSNAME "; Windows"
#else
# define HTTP_OSNAME ""
#endif

      sendstr(s, "User-Agent: Mozilla/5.0 (compatible; YtoICS"
            HTTP_OSNAME
            ")\r\n"
            "Connection: Close\r\n");

      status = 0;
      for (cp = 0; cookies[cp]; cp++) {
            if (!status)
                  sendstr(s, "Cookie: ");
            else
                  sendstr(s, "; ");

            sendstr(s, cookies[cp]);

            status = 1;
      }

      if (status)
            sendstr(s, "\r\n");

      sendstr(s, "\r\n");

      while (ngets(tmp, sizeof(tmp), s) != NULL) {
            for (i = 0; tmp[i] != '\0'; i++);

            if ((i > 0) && (tmp[--i] == '\n'))
                  tmp[i] = '\0';

            if (!got_status) {
                  if (!sscanf(tmp, "HTTP/1.1 %d", &status)) {
                        closesock(s);
                        return -1;
                  }

                  got_status = 1;
            } else if (tmp[0] == '\0') {
                  if (!*sout) {
                        closesock(s);
                        return status;
                  }

                  *sout = s;
                  return status;
            } else {
                  /*
                   * XXX: Should check (somehow) the size of the cookie
                   * array.  Yahoo! could exploit this, if they wanted
                   * to cripple YICS.
                   */
                  if (!strncmp("Set-Cookie: ", tmp, 12)) {
                        cookie = malloc(strlen(tmp));
                        if (cookie) {
                              ckp = cookie;
                              for (ch = &tmp[12]; *ch && (*ch != ';'); ch++)
                                    *(ckp++) = *ch;
                              *ckp = '\0';
                              cookies[cp++] = cookie;
                              cookies[cp] = 0;
                        }
                  }
            }
      }

      closesock(s);
      return status;
}

Generated by  Doxygen 1.6.0   Back to index