Skip to content
This repository was archived by the owner on May 30, 2023. It is now read-only.

proxy exceptions #12863

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static const struct QCommandLineConfigEntry flags[] =
{ QCommandLine::Option, '\0', "proxy", "Sets the proxy server, e.g. '--proxy=http://proxy.company.com:8080'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "proxy-auth", "Provides authentication information for the proxy, e.g. ''-proxy-auth=username:password'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "proxy-type", "Specifies the proxy type, 'http' (default), 'none' (disable completely), or 'socks5'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "no-proxy", "Specifies the proxy exceptions, '127.0.0.1, localhost' (default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "script-encoding", "Sets the encoding used for the starting script, default is 'utf8'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "script-language", "Sets the script language instead of detecting it: 'javascript'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "web-security", "Enables web security, 'true' (default) or 'false'", QCommandLine::Optional },
Expand Down Expand Up @@ -348,6 +349,11 @@ int Config::proxyPort() const
return m_proxyPort;
}

QString Config::proxyExceptions() const
{
return m_proxyExceptions;
}

QStringList Config::scriptArgs() const
{
return m_scriptArgs;
Expand Down Expand Up @@ -554,6 +560,7 @@ void Config::resetToDefaults()
m_proxyPort = 1080;
m_proxyAuthUser.clear();
m_proxyAuthPass.clear();
m_proxyExceptions.clear();
m_scriptArgs.clear();
m_scriptEncoding = "UTF-8";
m_scriptLanguage.clear();
Expand Down Expand Up @@ -616,6 +623,11 @@ void Config::setProxyPort(const int value)
m_proxyPort = value;
}

void Config::setProxyExceptions(const QString &value)
{
m_proxyExceptions = value;
}

bool Config::helpFlag() const
{
return m_helpFlag;
Expand Down Expand Up @@ -736,6 +748,10 @@ void Config::handleOption(const QString &option, const QVariant &value)
setProxyAuth(value.toString());
}

if (option == "no-proxy") {
setProxyExceptions(value.toString());
}

if (option == "script-encoding") {
setScriptEncoding(value.toString());
}
Expand Down
5 changes: 5 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class Config: public QObject
Q_PROPERTY(QString proxyType READ proxyType WRITE setProxyType)
Q_PROPERTY(QString proxy READ proxy WRITE setProxy)
Q_PROPERTY(QString proxyAuth READ proxyAuth WRITE setProxyAuth)
Q_PROPERTY(QString noProxy READ proxyExceptions WRITE setProxyExceptions)
Q_PROPERTY(QString scriptEncoding READ scriptEncoding WRITE setScriptEncoding)
Q_PROPERTY(bool webSecurityEnabled READ webSecurityEnabled WRITE setWebSecurityEnabled)
Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath)
Expand Down Expand Up @@ -120,6 +121,9 @@ class Config: public QObject
void setProxyAuthUser(const QString &value);
void setProxyAuthPass(const QString &value);

QString proxyExceptions() const;
void setProxyExceptions(const QString &value);

QStringList scriptArgs() const;
void setScriptArgs(const QStringList &value);

Expand Down Expand Up @@ -213,6 +217,7 @@ public slots:
int m_proxyPort;
QString m_proxyAuthUser;
QString m_proxyAuthPass;
QString m_proxyExceptions;
QStringList m_scriptArgs;
QString m_scriptEncoding;
QString m_scriptLanguage;
Expand Down
8 changes: 8 additions & 0 deletions src/networkaccessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "config.h"
#include "cookiejar.h"
#include "networkaccessmanager.h"
#include "networkproxyfactory.h"

// 10 MB
const qint64 MAX_REQUEST_POST_BODY_SIZE = 10 * 1000 * 1000;
Expand Down Expand Up @@ -161,6 +162,8 @@ NetworkAccessManager::NetworkAccessManager(QObject *parent, const Config *config
, m_networkDiskCache(0)
, m_sslConfiguration(QSslConfiguration::defaultConfiguration())
{
NetworkProxyFactory* proxyFactory = new NetworkProxyFactory();

if (config->diskCacheEnabled()) {
m_networkDiskCache = new QNetworkDiskCache(this);
m_networkDiskCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
Expand Down Expand Up @@ -214,6 +217,11 @@ NetworkAccessManager::NetworkAccessManager(QObject *parent, const Config *config
}
}

if (proxyFactory->initializeFromEnvironment(config)) {
setProxyFactory(proxyFactory);
}


connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(provideAuthentication(QNetworkReply*,QAuthenticator*)));
connect(this, SIGNAL(finished(QNetworkReply*)), SLOT(handleFinished(QNetworkReply*)));
}
Expand Down
132 changes: 132 additions & 0 deletions src/networkproxyfactory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
This file is part of the PhantomJS project from Ofi Labs.

Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@gmail.com>
Copyright (C) 2014 Jef le Ponot <jef_le_ponot@voila.fr>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <QNetworkProxyFactory>
#include <QNetworkProxy>
#include <QUrl>
#include <QList>
#include <QString>
#include <QStringList>

#include "networkproxyfactory.h"
#include "phantom.h"
#include "config.h"
#include "cookiejar.h"
#include "terminal.h"
NetworkProxyFactory::NetworkProxyFactory()
{
}

NetworkProxyFactory::~NetworkProxyFactory()
{
}

bool NetworkProxyFactory::initializeFromEnvironment(const Config *config)
{
QString proxyType = config->proxyType();

if (proxyType == "none")
return false;

if (config->proxyHost().isEmpty())
return false;

if (config->proxyExceptions().isEmpty())
return false;

QNetworkProxy::ProxyType networkProxyType;
if (proxyType == "socks5")
networkProxyType = QNetworkProxy::Socks5Proxy;
else
networkProxyType = QNetworkProxy::HttpProxy;

if(!config->proxyAuthUser().isEmpty() && !config->proxyAuthPass().isEmpty())
m_httpProxy << QNetworkProxy(networkProxyType, config->proxyHost(), config->proxyPort(), config->proxyAuthUser(), config->proxyAuthPass());
else
m_httpProxy << QNetworkProxy(networkProxyType, config->proxyHost(), config->proxyPort());

QByteArray exceptions = config->proxyExceptions().toLocal8Bit();
noProxyTokens = exceptions.split(',');

return true;
}


bool NetworkProxyFactory::ignoreProxyFor(const QNetworkProxyQuery &query)
{
foreach (const QByteArray rawToken, noProxyTokens) {
QByteArray token = rawToken.trimmed();
QString peerHostName = query.peerHostName();

// Since we use suffix matching, "*" is our 'default' behaviour
if (token.startsWith("*"))
token = token.mid(1);

// Harmonize trailing dot notation
if (token.endsWith('.') && !peerHostName.endsWith('.'))
token = token.left(token.length()-1);

// We prepend a dot to both values, so that when we do a suffix match,
// we don't match "donotmatch.com" with "match.com"
if (!token.startsWith('.'))
token.prepend('.');

if (!peerHostName.startsWith('.'))
peerHostName.prepend('.');

if (peerHostName.endsWith(QString::fromLatin1(token)))
{
return true;
}
}
return false;
}

QList<QNetworkProxy> NetworkProxyFactory::queryProxy(const QNetworkProxyQuery& query)
{
QString protocol = query.protocolTag().toLower();
/*bool localHost = false;*/
QList<QNetworkProxy> noproxy;
noproxy << QNetworkProxy::NoProxy;

//Terminal::instance()->cout(query.peerHostName());

if (!query.peerHostName().compare(QLatin1String("localhost"), Qt::CaseInsensitive) || !query.peerHostName().compare(QLatin1String("127.0.0.1"), Qt::CaseInsensitive))
return noproxy;
if (ignoreProxyFor(query))
return noproxy;

return m_httpProxy;
/*
if (protocol == QLatin1String("https") && !localHost)
return m_httpsProxy;
*/
}
77 changes: 77 additions & 0 deletions src/networkproxyfactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
This file is part of the PhantomJS project from Ofi Labs.

Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@gmail.com>
Copyright (C) 2014 Jef le Ponot <jef_le_ponot@voila.fr>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef NETWORKPROXYFACTORY_H
#define NETWORKPROXYFACTORY_H

#include <QNetworkProxyFactory>
#include <QNetworkProxy>
#include <QUrl>
#include <QList>
#include <QString>
#include <QStringList>
#include "config.h"

class NetworkProxyFactory : public QObject, public QNetworkProxyFactory
{
Q_OBJECT
public:
NetworkProxyFactory();
~NetworkProxyFactory();
/*
void setHttpProxy(const QString &userName);
void setHttpsProxy(const QString &password);
void setFtpProxy(int maxAttempts);
void setSocksProxy(int resourceTimeout);
void setNoProxy(const QVariantMap &headers);
*/
bool initializeFromEnvironment(const Config *config);

QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery& query = QNetworkProxyQuery());
protected:

signals:

private slots:

private:
bool ignoreProxyFor(const QNetworkProxyQuery &query);

QList<QNetworkProxy> m_httpProxy;
QList<QNetworkProxy> m_httpsProxy;
QList<QNetworkProxy> m_ftpProxy;
QList<QNetworkProxy> m_socksProxy;

QList<QByteArray> noProxyTokens;
};


#endif //NETWORKPROXYFACTORY_H
2 changes: 2 additions & 0 deletions src/phantomjs.pro
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ HEADERS += \
consts.h \
utils.h \
networkaccessmanager.h \
networkproxyfactory.h \
cookiejar.h \
filesystem.h \
system.h \
Expand All @@ -43,6 +44,7 @@ SOURCES += phantom.cpp \
main.cpp \
utils.cpp \
networkaccessmanager.cpp \
networkproxyfactory.cpp \
cookiejar.cpp \
filesystem.cpp \
system.cpp \
Expand Down