// Finds proxy for the given PAC file, url and host. // // This function is a wrapper around functions pacparser_init, // pacparser_parse_pac, pacparser_find_proxy and pacparser_cleanup. If you just // want to find out proxy a given set of pac file, url and host, this is the // function to call. char * // Proxy string or NULL if failed. pacparser_just_find_proxy(const char *pacfile, const char *url, const char *host) { char *proxy; char *out; int initialized_here = 0; char *error_prefix = "pacparser.c: pacparser_just_find_proxy:"; if (!global) { if (!pacparser_init()) { print_error("%s %s\n", error_prefix, "Could not initialize pacparser"); return NULL; } initialized_here = 1; } if (!pacparser_parse_pac(pacfile)) { print_error("%s %s %s\n", error_prefix, "Could not parse pacfile", pacfile); if (initialized_here) pacparser_cleanup(); return NULL; } if (!(out = pacparser_find_proxy(url, host))) { print_error("%s %s %s\n", error_prefix, "Could not determine proxy for url", url); if (initialized_here) pacparser_cleanup(); return NULL; } proxy = (char*) malloc(strlen(out) + 1); strcpy(proxy, out); if (initialized_here) pacparser_cleanup(); return proxy; }
std::string DimdimHelpers::ParsePACFile(std::string filePath, std::string url) { // filePath is the location of PAC File in %APPDATA% // Assuming that url is of the form http://ip:port/screenshare/.... pacparser_init(); char *proxy = NULL; pacparser_parse_pac(filePath.c_str()); std::string host(url); host.assign(host.substr(7, host.length())); host.assign(host.substr(0, host.find_first_of('/'))); proxy = pacparser_find_proxy(url.c_str(), host.c_str()); std::string proxyURL(""); if(proxy) { proxyURL.assign(proxy); } pacparser_cleanup(); return proxyURL; }
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; }