Exemple #1
0
// Parses the given PAC file.
//
// reads the given PAC file and evaluates it in the JavaScript context created
// by pacparser_init.
int                                     // 0 (=Failure) or 1 (=Success)
pacparser_parse_pac_file(const char *pacfile)
{
  char *script = NULL;

  if ((script = read_file_into_str(pacfile)) == NULL) {
    print_error("pacparser.c: pacparser_parse_pac: %s: %s: %s\n",
            "Could not read the pacfile: ", pacfile, strerror(errno));
    return 0;
  }

  int result = pacparser_parse_pac_string(script);
  if (script != NULL) free(script);

  if (_debug()) {
    if(result) print_error("DEBUG: Parsed the PAC file: %s\n", pacfile);
    else print_error("DEBUG: Could not parse the PAC file: %s\n", pacfile);
  }

  return result;
}
Exemple #2
0
int main(int argc, char* argv[])
{
  char *pacfile = NULL, *url = NULL, *host = NULL, *urlslist = NULL,
       *client_ip = NULL;

  if (argv[1] && (STREQ(argv[1], "--help") || STREQ(argv[1], "--helpshort"))) {
    usage(argv[0]);
  }

  signed char c;
  while ((c = getopt(argc, argv, "evp:u:h:f:c:")) != -1)
    switch (c)
    {
      case 'v':
        printf("%s\n", pacparser_version());
        return 0;
      case 'p':
        pacfile = optarg;
        break;
      case 'u':
        url = optarg;
        break;
      case 'h':
        host = optarg;
        break;
      case 'f':
        urlslist = optarg;
        break;
      case 'c':
        client_ip = optarg;
        break;
      case 'e':
        break;
      case '?':
        usage(argv[0]);
        /* fallthrough */
      default:
        abort ();
    }

  if (!pacfile) {
    fprintf(stderr, "pactester.c: You didn't specify the PAC file\n");
    usage(argv[0]);
  }
  if (!url && !urlslist) {
    fprintf(stderr, "pactester.c: You didn't specify the URL\n");
    usage(argv[0]);
  }

  // Initialize pacparser.
  if (!pacparser_init()) {
      fprintf(stderr, "pactester.c: Could not initialize pacparser\n");
      return 1;
  }

  // Read pacfile from stdin.
  if (STREQ("-", pacfile)) {
    char *script;
    size_t script_size = 1;  // for the null terminator
    char buffer[LINEMAX];

    script = (char *) malloc(sizeof(char) * LINEMAX);
    if (script == NULL) {
      perror("pactetser.c: Failed to allocate the memory for the script");
      return 1;
    }
    script[0] = '\0';                   // Null terminate to prepare for strcat

    while (fgets(buffer, LINEMAX, stdin)) {
      if (strlen(buffer) == 0)
        break;
      char *old = script;
      script_size += strlen(buffer);
      if (script_size > PACMAX) {
        fprintf(stderr, "Input file is too big. Maximum allowed size is: %d",
                PACMAX);
        free(script);
        return 1;
      }
      script = realloc(script, script_size);
      if (script == NULL) {
        perror("pactester.c: Failed to allocate the memory for the script");
        free(old);
        return 1;
      }
      strcat(script, buffer);
    }

    if (ferror(stdin)) {
      free(script);
      perror("pactester.c: Error reading from stdin");
      return 1;
    }

    if (!pacparser_parse_pac_string(script)) {
      fprintf(stderr, "pactester.c: Could not parse the pac script: %s\n",
              script);
      free(script);
      pacparser_cleanup();
      return 1;
    }
    free(script);
  }
  else {
    if (!pacparser_parse_pac_file(pacfile)) {
      fprintf(stderr, "pactester.c: Could not parse the pac file: %s\n",
              pacfile);
      pacparser_cleanup();
      return 1;
    }
  }

  if (client_ip)
    pacparser_setmyip(client_ip);

  char *proxy;

  if (url) {
    // If the host was not explicitly given, get it from the URL.
    // If that fails, return with error (the get_host_from_url()
    // function will print a proper error message in that case).
    host = host ? host: get_host_from_url(url);
    if (!host) {
      return 1;
    }
    proxy = pacparser_find_proxy(url, host);
    if (proxy == NULL) {
      fprintf(stderr, "pactester.c: %s %s.\n",
              "Problem in finding proxy for", url);
      pacparser_cleanup();
      return 1;
    }
    printf("%s\n", proxy);
  }

  else if (urlslist) {
    char line[LINEMAX];
    FILE *fp;
    if (!(fp = fopen(urlslist, "r"))) {
      fprintf(stderr, "pactester.c: Could not open urlslist: %s", urlslist);
      pacparser_cleanup();
      return 1;
    }
    while (fgets(line, sizeof(line), fp)) {
      char *url = line;
      // Remove spaces from the beginning.
      while (*url == ' ' || *url == '\t')
        url++;
      // Skip comment lines.
      if (*url == '#') {
        printf("%s", url);
        continue;
      }
      char *urlend = url;
      while (*urlend != '\r' && *urlend != '\n' && *urlend != '\0' &&
             *urlend != ' ' && *urlend != '\t')
        urlend++;  // keep moving till you hit space or end of string
      *urlend = '\0';
      if (!(host = get_host_from_url(url)) )
        continue;
      proxy = NULL;
      proxy = pacparser_find_proxy(url, host);
      if (proxy == NULL) {
        fprintf(stderr, "pactester.c: %s %s.\n",
                "Problem in finding proxy for", url);
        pacparser_cleanup();
        return 1;
      }
      if (proxy)
        printf("%s : %s\n", url, proxy);
    }
    fclose(fp);
  }

  pacparser_cleanup();
  return 0;
}
int frontierConfig_doProxyConfig(FrontierConfig *cfg)
 {
  FrontierHttpClnt *clnt;
  FrontierUrlInfo *fui=0;
  int curproxyconfig,nextproxyconfig;
  char *proxyconfig_url;
  int n,nbytes,ret=FRONTIER_OK;
  char err_last_buf[MAXPPERRORBUFSIZE];
  struct pp_errcontext err_context;
  char *pacstring=0;
  char *ipaddr,*proxylist;
  char *p,*endp,endc;
  int gotdirect=0;

  if(cfg->proxyconfig_num<=0)
    return FRONTIER_OK;

  clnt=frontierHttpClnt_create(&ret);
  if(ret!=FRONTIER_OK)
    return ret;
  if(!clnt)
   {
    frontier_setErrorMsg(__FILE__,__LINE__,
      "error creating http client object",0);
    return FRONTIER_ECFG;
   }
  frontierHttpClnt_setPreferIpFamily(clnt,
  		frontierConfig_getPreferIpFamily(cfg));
  frontierHttpClnt_setConnectTimeoutSecs(clnt,
  		frontierConfig_getConnectTimeoutSecs(cfg));
  frontierHttpClnt_setReadTimeoutSecs(clnt,
  		frontierConfig_getReadTimeoutSecs(cfg));
  frontierHttpClnt_setWriteTimeoutSecs(clnt,
  		frontierConfig_getWriteTimeoutSecs(cfg));
  frontierHttpClnt_setFrontierId(clnt,FNAPI_VERSION);

  for(curproxyconfig=0;curproxyconfig<cfg->proxyconfig_num;curproxyconfig++)
   {
    proxyconfig_url=cfg->proxyconfig[curproxyconfig];

    if(strncmp(proxyconfig_url,"file://",7)==0)
     {
      // don't consider any proxyconfig URLs after this one
      break;
     }

    if(strncmp(proxyconfig_url,"http://",7)!=0)
     {
      frontier_setErrorMsg(__FILE__,__LINE__,
	"proxyconfigurl %s does not begin with 'http://', 'file://', or 'auto'",proxyconfig_url);
      ret=FRONTIER_ECFG;
      goto cleanup;
     }

    // check for something beyond a server name because otherwise 
    //  frontierHttpClnt_addServer will give wrong message about missing servlet
    if(strchr(proxyconfig_url+7,'/')==0)
     {
      frontier_setErrorMsg(__FILE__,__LINE__,
	"config error: proxyconfigurl %s missing path on server",proxyconfig_url);
      ret=FRONTIER_ECFG;
      goto cleanup;
     }

    ret=frontierHttpClnt_addServer(clnt,proxyconfig_url);
    if(ret!=FRONTIER_OK) goto cleanup;
   }

  pacstring=frontier_mem_alloc(MAXPACSTRINGSIZE+1);
  if(!pacstring)
   {
    ret=FRONTIER_EMEM;
    goto cleanup;
   }

  // Messages below have either the http client servername or the current
  //  proxyconfig_url.  In general, warning messages should have the
  //  servername because that includes an IP address, and warning messages
  //  here are about server errors.  Error messages should show the
  //  proxyconfig_url because that's more relevant to the user.

  curproxyconfig=0;
  while(1)
   {
    proxyconfig_url=cfg->proxyconfig[curproxyconfig];

    if(strncmp(proxyconfig_url,"file://",7)==0)
     {
      char *fname;
      int fd;
      fname=strchr(proxyconfig_url+7,'/');
      if(fname==NULL)
       {
        frontier_setErrorMsg(__FILE__,__LINE__,
	     "bad format for file url %s, no path", proxyconfig_url);
	ret=FRONTIER_ECFG;
	goto cleanup;
       }
      fd=open(fname,O_RDONLY);
      if(fd<0)
       {
        frontier_setErrorMsg(__FILE__,__LINE__,
	     "error opening %s: %s",fname,strerror(errno));
	ret=FRONTIER_ECFG;
	goto cleanup;
       }
      nbytes=read(fd,pacstring,MAXPACSTRINGSIZE);
      if(nbytes<0)
       {
        frontier_setErrorMsg(__FILE__,__LINE__,
	     "error reading %s: %s",fname,strerror(errno));
	ret=FRONTIER_ECFG;
	close(fd);
	goto cleanup;
       }
      close(fd);
      if(nbytes==MAXPACSTRINGSIZE)
       {
	frontier_setErrorMsg(__FILE__,__LINE__,
	   "config error: proxyconfig file %s larger than limit of %d bytes",
	   	fname,MAXPACSTRINGSIZE);
	ret=FRONTIER_ECFG;
	goto cleanup;
       }
      frontier_log(FRONTIER_LOGLEVEL_DEBUG,__FILE__,__LINE__,
	"proxyconfig file from %s is %d bytes long",fname,nbytes);
      break;
     }

    frontier_turnErrorsIntoDebugs(1);

    ret=frontierHttpClnt_open(clnt);
    if(ret!=FRONTIER_OK)
     {
      frontier_log(FRONTIER_LOGLEVEL_WARNING,__FILE__,__LINE__,
	 "unable to connect to proxyconfig server %s: %s",
		frontierHttpClnt_curservername(clnt), frontier_getErrorMsg());
      goto trynext;
     }

    ret=frontierHttpClnt_get(clnt,"");
    if(ret!=FRONTIER_OK)
     {
      frontier_log(FRONTIER_LOGLEVEL_WARNING,__FILE__,__LINE__,
	 "unable to get proxyconfig from %s: %s",
	 	frontierHttpClnt_curservername(clnt), frontier_getErrorMsg());
      goto trynext;
     }

    nbytes=0;
    while((n=frontierHttpClnt_read(clnt,pacstring+nbytes,MAXPACSTRINGSIZE-nbytes))>0)
     {
      nbytes+=n;
      if(nbytes==MAXPACSTRINGSIZE)
       {
	frontier_turnErrorsIntoDebugs(0);
	frontier_setErrorMsg(__FILE__,__LINE__,
	   "config error: downloaded proxyconfig file from %s larger than limit of %d bytes",
	   	proxyconfig_url,MAXPACSTRINGSIZE);
	ret=FRONTIER_ECFG;
	goto cleanup;
       }
    }
    if(n<0)
     {
      frontier_log(FRONTIER_LOGLEVEL_WARNING,__FILE__,__LINE__,
	 "problem reading proxyconfig from %s: %s",
	    frontierHttpClnt_curservername(clnt), frontier_getErrorMsg());
      goto trynext;
     }
    pacstring[nbytes]='\0';

    frontier_turnErrorsIntoDebugs(0);

    // successfully read the proxy autoconfig file
    frontier_log(FRONTIER_LOGLEVEL_DEBUG,__FILE__,__LINE__,
      "proxyconfig file from %s is %d bytes long",
	 	frontierHttpClnt_curservername(clnt),nbytes);
    break;

trynext:
    strncpy(err_last_buf,frontier_getErrorMsg(),sizeof(err_last_buf)-1);
    err_last_buf[sizeof(err_last_buf)-1]='\0';
    
    frontierHttpClnt_close(clnt);
    frontier_turnErrorsIntoDebugs(0);
   
    if((nextproxyconfig=frontierHttpClnt_nextserver(clnt,1))<0)
     {
      curproxyconfig++;
      if ((curproxyconfig<cfg->proxyconfig_num)&&
	    (strncmp(cfg->proxyconfig[curproxyconfig],"file://",7)==0))
       {
        // there is a file:// URL still to try
        frontier_log(FRONTIER_LOGLEVEL_WARNING,__FILE__,__LINE__,
          "Trying next proxyconfig url %s", cfg->proxyconfig[curproxyconfig]);
       }
      else
       {
	frontier_setErrorMsg(__FILE__,__LINE__,
	  "config error: failed to read a proxyconfig url.  Last url was %s and last error was: %s",
		  proxyconfig_url,err_last_buf);
	goto cleanup;
       }
     }
    else
     {
      curproxyconfig=nextproxyconfig;
      frontier_log(FRONTIER_LOGLEVEL_WARNING,__FILE__,__LINE__,
        "Trying next proxyconfig server %s",
	 	frontierHttpClnt_curservername(clnt));
     }
   }

  ret=frontier_pacparser_init();
  if(ret!=FRONTIER_OK)
    goto cleanup;

  err_context.len=0;
  err_context.buf[0]='\0';
  pp_errorcontext=&err_context;
  pacparser_set_error_printer(&fn_pp_errorvprint);

  if(!pacparser_init())
   {
    frontier_setErrorMsg(__FILE__,__LINE__,
       "config error: cannot initialize pacparser%s",fn_pp_getErrorMsg());
    ret=FRONTIER_ECFG;
    goto cleanup;
   }

  if(strncmp(proxyconfig_url,"file://",7)!=0)
   {
    if((ipaddr=frontierHttpClnt_myipaddr(clnt))==NULL)
     {
      frontier_setErrorMsg(__FILE__,__LINE__,
	 "config error: error determining my IP address for proxyconfig server%s",
		  frontierHttpClnt_curservername(clnt),fn_pp_getErrorMsg());
      ret=FRONTIER_ECFG;
      goto cleanup;
     }

    pacparser_setmyip(ipaddr);
   }

  if(!pacparser_parse_pac_string(pacstring))
   {
    frontier_setErrorMsg(__FILE__,__LINE__,
       "config error: failure parsing %d byte proxyconfig from %s%s",
       		nbytes,proxyconfig_url,fn_pp_getErrorMsg());
    ret=FRONTIER_ECFG;
    goto cleanup;
   }

  if(cfg->server_num<1)
   {
    frontier_setErrorMsg(__FILE__,__LINE__,
       "config error: cannot process proxyconfigurl without a serverurl%s");
    ret=FRONTIER_ECFG;
    goto cleanup;
   }

  // need to parse the host out of the server URL, and in addition to
  //   other things, frontier_CreateUrlInfo happens to do that
  fui=frontier_CreateUrlInfo(cfg->server[0],&ret);
  if(!fui)goto cleanup;
  proxylist=pacparser_find_proxy(cfg->server[0],fui->host);

  if(proxylist==NULL)
   {
    frontier_setErrorMsg(__FILE__,__LINE__,
       "config error: proxyconfigurl %s FindProxyForURL(\"%s\",\"%s\") returned no match%s",
	    proxyconfig_url,cfg->server[0],fui->host,fn_pp_getErrorMsg());
    ret=FRONTIER_ECFG;
    goto cleanup;
   }

  frontier_log(FRONTIER_LOGLEVEL_DEBUG,__FILE__,__LINE__,
    "FindProxyForURL(\"%s\",\"%s\") returned \"%s\"",cfg->server[0],fui->host,proxylist);

  if(getNumNonBackupProxies(cfg)>0)
   {
    frontier_log(FRONTIER_LOGLEVEL_DEBUG,__FILE__,__LINE__,
      "Turning %d proxies into backup proxies so they will be after proxyconfig proxies",getNumNonBackupProxies(cfg));
    cfg->num_backupproxies=cfg->proxy_num;
   }

  if(cfg->proxies_balanced)
   {
    frontier_log(FRONTIER_LOGLEVEL_DEBUG,__FILE__,__LINE__,
      "Disabling loadbalance=proxies because of proxyconfigurl");
    cfg->proxies_balanced=0;
   }

  // Now parse the returned proxy list
  p=proxylist;
  endc=*p;
  while(endc!='\0')
   {
    while(*p==' ')
      p++;
    for(endp=p;*endp&&(*endp!=';')&&(*endp!=' ');endp++)
      ;
    endc=*endp;
    *endp='\0';
    if(strcmp(p,"PROXY")==0)
     {
      if((endc=='\0')||(endc==';'))
        p=endp;
      else
       {
	p=endp+1;
	while(*p==' ')
	  p++;
	for(endp=p;*endp&&(*endp!=';')&&(*endp!=' ');endp++)
	  ;
	endc=*endp;
	*endp='\0';
       }
      if(*p)
        frontierConfig_addProxy(cfg,p,0);
      else
       {
	frontier_setErrorMsg(__FILE__,__LINE__,
          "config error: proxyconfigurl %s FindProxyForURL(\"%s\",\"%s\") returned \"PROXY\" without a proxy",
	  	proxyconfig_url,cfg->server[0],fui->host);
	ret=FRONTIER_ECFG;
	goto cleanup;
       }
     }
    else if(strcmp(p,"DIRECT")==0)
     {
      gotdirect=1;
      break;
     }
    else if(*p)
     {
      frontier_setErrorMsg(__FILE__,__LINE__,
        "config error: proxyconfigurl %s FindProxyForURL(\"%s\",\"%s\") returned unrecognized type %s, expect PROXY or DIRECT",
		proxyconfig_url,cfg->server[0],fui->host,p);
      ret=FRONTIER_ECFG;
      goto cleanup;
     }
    p=endp+1;
   }

  if(!gotdirect)
   {
    frontier_log(FRONTIER_LOGLEVEL_DEBUG,__FILE__,__LINE__,
      "no DIRECT found in proxyconfig list, setting failovertoserver=no");
    frontierConfig_setFailoverToServer(cfg,0);
   }

  ret=FRONTIER_OK;

cleanup:
  if(pacstring) frontier_mem_free(pacstring);
  pacparser_cleanup();
  frontierHttpClnt_close(clnt);
  frontierHttpClnt_delete(clnt);
  if(fui) frontier_DeleteUrlInfo(fui);
  return ret;
 }