⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 qADSL is an auto-login & keep-alive daemon for Internet connections. It was created to automate the
💻 C
字号:
/* http.c -   */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <netdb.h>#include <netinet/in.h>#include <stdio.h>#include <string.h>#include <sys/socket.h>#include <sys/time.h>#include <time.h>#include <errno.h>#include <stdlib.h>#include <unistd.h>#include "http.h"#include "log.h"/** * url_encode - Hexifies a character string for URL use. * @dest: A destination buffer. * @src:  The string to be encoded. * @len:  Length of @src. * * This function scans @src for unsafe characters and converts * them into %XX entries. This means that @dest must be large * enough to hold this expanded string from @src. * * Returns: Number of bytes written to @dest, should be >= @len *          any number less than or zero indicates an error. */static unsigned inturl_encode (char *dest, const char *src, unsigned int len) {  const char unsafe[]=" %<>\"#{}|\\^~[]`;/?:@=&";  register const char* s = src;  unsigned long written = 0, i;  /* Nested because its a cool GNU feature and because noone else   * really needs this function ... now, why can't it be inline?   */  inline char tohex (const unsigned char c)  {    return c > 9 ? c - 10 + 'A' : c + '0';  }  if (!dest)    {      /* Eh, no destination? */      return 0;    }  for (i = 0; i < len; i++)     {      /* Upper half of ASCII table or one of the unsafe chars? */      /* if (s[i] & 0x7F || strchr (unsafe, s[i])) */      /* Simple, just trap unsafe characters */      if (strchr (unsafe, s[i]))        {          if (' ' == s[i])            {              /* Spaces to plus */              dest[written++] = '+';            }          else            {              dest [written++] = '%';              dest [written++] = tohex (s [i] >> 4);              dest [written++] = tohex (s [i] & 15);            }        }       else         {          dest [written++] = s [i];        }    }  return written;}/** * open_server -  * @name:  * @port: * @verbose:  * * Returns: -1 and errno on error, otherwise *          socket descriptior. * */int open_server (char *name, short port, int verbose){  int result, sockfd;  struct hostent *he;  struct sockaddr_in address;    /* Try to find the login host */  LOG("Looking up %s ... ", name);  he = gethostbyname (name);  if (he == NULL)    {      ERROR("Cannot find login host: %s\n", name);      result = -1;    }  else    {      /* Setup a socket */      LOG("0x%X\n", (int)he->h_addr);      sockfd = socket (PF_INET, SOCK_STREAM, 0);      if (-1 == sockfd)        {          ERROR("Failed to create a socket: %s\n", strerror (errno));          result = -1;        }      else        {          /* Setup address to connecto to ... */          address.sin_family = PF_INET;          address.sin_port   = htons (port);          address.sin_addr   = *((struct in_addr *) he->h_addr);          memset (&(address.sin_zero), 0, sizeof (address.sin_zero));	            /* Connect to login server */          if (verbose)            {              LOG("Connecting to %s(0x%X)\n", name, (int)he->h_addr);            }          result = connect (sockfd, (struct sockaddr *) &address, sizeof (address));          if (-1 == result && verbose)            {              ERROR("Failed to connect to login host: %s\n\t==>%s",                    name, strerror (errno));            }          else            {              result = sockfd;            }        }    }  return result;}/** * pre_login - Bring up Orbyte login screen * @config: Pointer to config data area. * @sockfd: Socket we are connected to. * * This function serves as a sort of "ping" to ensure that * the login server is alive and accepting connections. * * In reality the %PRELOGIN_MSG must be sent to initiate the * actual login page at the server. * * Returns: 0 if login server alive, otherwise a negative value. */intpre_login (config_data_t *config, int verbose){  int result, tries;  /* Open a connection to the login server */  config->sockfd = open_server (config->login_server, config->server_port, verbose);  if (config->sockfd < 0)    {      ERROR ("Failed to connect to login server: %s\n",             strerror (errno));      return -1;    }  /* Register and get login page */  sprintf (config->send_msg, PRELOGIN_MSG,           config->init_page,           config->login_server,           config->login_server);#ifdef DEBUG  if (verbose)    {      LOG ("Sent:\n%s\n", config->send_msg);    }#endif  result = send (config->sockfd,                 config->send_msg,                 strlen (config->send_msg), 0);  /* Read reply */  /* In a not so distant future this function will be extended to   * include a very small HTML parser. It will wait for completion   * of the send() command and then parse the file at sockfd to   * find the username, password and any extra data to the login   * string used later by internet_login()   */  tries = 0;  do     {      sleep (2 * tries);      result = read (config->sockfd, config->get_msg, sizeof (config->get_msg));    }  while (-1 == result && tries++ < MAX_RETRIES);  if (-1 == result)    {      ERROR("Read reply: %s\n", strerror (errno));    }  else    {#ifdef DEBUG      if (verbose)        {          LOG ("Received:\n%s", config->get_msg);        }#endif      result = 0;    }  close (config->sockfd);  return result;}/** * internet_login - Handles the login phase. * @config:  Pointer to config data area. * @sockfd:  Socket we are connected to. * @verbose: Log as much as possible. *  * This is the function that handles the logging in to the * Internet gateway of the ISP. * * Returns: 0 if login was successful, otherwise -1. */intinternet_login (config_data_t *config, int verbose){  int result, tries, length;  char *login_string, *temp;  /* Open a connection to the login server */  config->sockfd = open_server (config->login_server, config->server_port, verbose);  if (config->sockfd < 0)    {      ERROR("Failed to connect to login server: %s\n",            strerror (errno));      return -1;    }#if 0  result = sprintf (login_string, LOGIN_STRING,                    config->username, config->password);#endif  length = (config->login_string_header ? strlen (config->login_string_header) : 0)    + strlen (config->username_key) + strlen (config->username)    + strlen (config->password_key) + strlen (config->password)     + strlen (config->login_string_footer) + strlen ("Plus approximately 10%");  temp = (char *) malloc (length);  if (!temp)    {      ERROR ("Failed to allocate memory: %s\n",             strerror (errno));      return -1;    }  result = 0;  if (config->login_string_header)    result = sprintf (temp, "%s&", config->login_string_header);    result += sprintf (&temp[result], "%s=%s&%s=%s",                     config->username_key,                     config->username,                     config->password_key,                     config->password);  if (config->login_string_footer)    result += sprintf (&temp[result], "&%s", config->login_string_footer);  #ifdef DEBUG  if (verbose)    {      LOG("Non-url-encoded login string:\n%s\n", temp);    }#endif  login_string = (char *) malloc (length);  if (!login_string)    {      free (temp);      ERROR ("Failed to allocate memory: %s\n",             strerror (errno));      return -1;    }#if 0  length = url_encode (login_string, temp, strlen (temp));#else  {    int i;    length = strlen (temp);    for (i = 0; i < length; i++)      {	if (' ' == temp [i])	  login_string [i] = '+';	else	  login_string [i] = temp [i];      }  }#endif  sprintf (config->send_msg, LOGIN_MSG,           config->login_page,           config->login_server,           config->login_server,           config->init_page,           length,           login_string);  free (login_string);  free (temp);#ifdef DEBUG  if (verbose)    {      LOG("Sent:\n%s\n", config->send_msg);    }#endif  tries = 0;  do    {      sleep (2 * tries);      result = send (config->sockfd, config->send_msg,                     strlen (config->send_msg), 0);    }  while (-1 == result && tries++ < MAX_RETRIES);  if (-1 == result)    {      ERROR("Send login request: %s\n", strerror(errno));      close (config->sockfd);      return -1;    }  /* Wait for a while before reading the server   * result. Maybe we could find another way to   * synchronize with the server ... ?   */  tries = 0;  do     {      sleep (2 * tries);      result = read (config->sockfd, config->get_msg, sizeof (config->get_msg));      /* Zero terminate the read string */      if (result >= 0)        config->get_msg [result] = 0;    }  while (-1 == result && tries++ < MAX_RETRIES);  if (-1 == result)    {      ERROR("Read login reply: %s\n", strerror (errno));      close (config->sockfd);      return -1;    }#ifdef DEBUG  if (verbose)    {      LOG ("Received:\n%s", config->get_msg);    }#endif  close (config->sockfd);  return 0;}intinternet_logout (config_data_t *config, int verbose){  fd_set check_sockfd;  struct timeval c_tv;  int result;  result = pre_login (config, verbose);  if (-1 == result)    return result;  /* Are we logged in? */  if (strstr (config->get_msg, config->logged_in_string) != NULL)    {      /* Open a connection to the login server */      config->sockfd = open_server (config->login_server, config->server_port, verbose);      if (config->sockfd < 0)        {          perror ("Failed to connect to login server");          return -1;        }      /* Send logout request */      sprintf (config->send_msg,                LOGOUT_MSG,                config->logout_page, config->login_server,               config->init_page, config->login_server);#ifdef DEBUG      if (verbose)        {          LOG ("Sent:\n%s\n", config->send_msg);        }#endif      result = send (config->sockfd, config->send_msg,                     strlen (config->send_msg), 0);            if (-1 == result)        {          ERROR("Send logout request: %s\n", strerror(errno));          close (config->sockfd);          return -1;        }      FD_ZERO (&check_sockfd);      FD_SET (config->sockfd, &check_sockfd);            c_tv.tv_sec  = 5;      c_tv.tv_usec = 0;      LOG("Trying to logout, %d second timeout ...\n", (int)c_tv.tv_sec);      result = select (1, &check_sockfd, NULL, NULL, &c_tv);      if (-1 == result)        {          ERROR("%s does not respond, cannot log out!\n", config->logout_page);          close (config->sockfd);          return -1;        }      result = read (config->sockfd, config->get_msg, sizeof (config->get_msg));      if (-1 == result)        {          ERROR("Read logout reply: %s\n", strerror (errno));          close (config->sockfd);          return -1;        }#ifdef DEBUG      if (verbose)        {          LOG ("Received:\n%s", config->get_msg);        }#endif      if (strstr (config->get_msg, config->logged_out_string) == NULL)        {          ERROR("%s: LOGOUT FAILED\n", PACKAGE_NAME);          return -1;        }      LOG("%s: SUCCESSFUL LOGOUT\n", PACKAGE_NAME);    }  close (config->sockfd);  return 0;}intlog_login (config_data_t *config, int verbose){  int i;  struct tm *timep;  time_t the_time;  (void) time (&the_time);  timep = localtime (&the_time);  if (internet_login (config, verbose))    {      /* If login fails, try three times with increasingly       * longer delays between each.       */      for (i = 0; i < MAX_RETRIES; i++)        {          /* Sleep for a while if it is not the first try... */          sleep (5 * i);          /* If we cannot get the login or csw pages we sleep some more */          if (-1 == pre_login (config, verbose))            {              ERROR("%s: Failed to bring up login page.\n", PACKAGE_NAME);              continue;            }                    /* Test if we're logged in already. */          if (strstr (config->get_msg, config->logged_in_string))            {              config->logged_in = 1;              break;            }                    if (!internet_login (config, verbose))            {              config->logged_in = 1;              break;            }        }    }  /* Tell those who want to know why we failed. */  if (!config->logged_in)    {      ERROR("%s: login failed after %d retries - aborting!\n",             PACKAGE_NAME, MAX_RETRIES);    }  return config->logged_in;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -