Exemple #1
0
void FileTransferHandler::ft_accepted()
{
	d->offset = d->ft->offset();
	d->length = d->ft->length();

	d->c = d->ft->bsConnection();

	if (dynamic_cast<S5BConnection*>(d->c)) {
		connect(d->c, SIGNAL(proxyQuery()), SLOT(s5b_proxyQuery()));
		connect(d->c, SIGNAL(proxyResult(bool)), SLOT(s5b_proxyResult(bool)));
		connect(d->c, SIGNAL(requesting()), SLOT(s5b_requesting()));
		connect(d->c, SIGNAL(accepted()), SLOT(s5b_accepted()));
		connect(d->c, SIGNAL(tryingHosts(const StreamHostList &)), SLOT(s5b_tryingHosts(const StreamHostList &)));
		connect(d->c, SIGNAL(proxyConnect()), SLOT(s5b_proxyConnect()));
		connect(d->c, SIGNAL(waitingForActivation()), SLOT(s5b_waitingForActivation()));
	}
Exemple #2
0
int main(int argc, char * argv[])
{
    /*
     * Before starting main application, need to set 'QT_X11_NO_MITSHM=1'
     * to make the runtime work with IBM PPC machine.
     */
#if defined (Q_OS_LINUX)
    QByteArray val("1");
    qputenv("QT_X11_NO_MITSHM", val);
#endif

    // Create the QT application
    QApplication app(argc, argv);
    app.setQuitOnLastWindowClosed(false);

    // Setup the settings management
    QCoreApplication::setOrganizationName("pgadmin");
    QCoreApplication::setOrganizationDomain("pgadmin.org");
    QCoreApplication::setApplicationName(PGA_APP_NAME.toLower().replace(" ", ""));

#if QT_VERSION >= 0x050000
    // Set high DPI pixmap to display icons clear on Qt widget.
    QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif

    // Create a hash of the executable path so we can run copies side-by-side
    QString homeDir = QDir::homePath();
    unsigned long exeHash = sdbm((unsigned char *)argv[0]);

    // Create the address file, that will be used to store the appserver URL for this instance
    addrFileName = homeDir + (QString("/.%1.%2.addr").arg(PGA_APP_NAME).arg(exeHash)).remove(" ");
    QFile addrFile(addrFileName);

    // Create a system-wide semaphore keyed by app name, exe hash and the username
    // to ensure instances are unique to the user and path
    QString userName = qgetenv("USER"); // *nix
    if (userName.isEmpty())
        userName = qgetenv("USERNAME"); // Windows

    QString semaName = QString("%1-%2-%3-sema").arg(PGA_APP_NAME).arg(userName).arg(exeHash);
    QString shmemName = QString("%1-%2-%3-shmem").arg(PGA_APP_NAME).arg(userName).arg(exeHash);

    QSystemSemaphore sema(semaName, 1);
    sema.acquire();

#ifndef Q_OS_WIN32
    // We may need to clean up stale shmem segments on *nix. Attaching and detaching
    // should remove the segment if it is orphaned.
    QSharedMemory stale_shmem(shmemName);
    if (stale_shmem.attach())
        stale_shmem.detach();
#endif

    QSharedMemory shmem(shmemName);
    bool is_running;
    if (shmem.attach())
    {
        is_running = true;
    }
    else
    {
        shmem.create(1);
        is_running = false;
    }
    sema.release();

    QSettings settings;

    if (is_running){
        addrFile.open(QIODevice::ReadOnly | QIODevice::Text);
        QTextStream in(&addrFile);
        QString addr = in.readLine();

        QString cmd = settings.value("BrowserCommand").toString();

        if (!cmd.isEmpty())
        {
            cmd.replace("%URL%", addr);
            QProcess::startDetached(cmd);
        }
        else
        {
            if (!QDesktopServices::openUrl(addr))
            {
                QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
                QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

                exit(1);
            }
        }

        return 0;
    }

    atexit(cleanup);

    // In windows and linux, it is required to set application level proxy
    // because socket bind logic to find free port gives socket creation error
    // when system proxy is configured. We are also setting
    // "setUseSystemConfiguration"=true to use the system proxy which will
    // override this application level proxy. As this bug is fixed in Qt 5.9 so
    // need to set application proxy for Qt version < 5.9.
    //
#if defined (Q_OS_WIN) && QT_VERSION <= 0x050800
    // Give dummy URL required to find proxy server configured in windows.
    QNetworkProxyQuery proxyQuery(QUrl("https://www.pgadmin.org"));
    QNetworkProxy l_proxy;
    QList<QNetworkProxy> listOfProxies = QNetworkProxyFactory::systemProxyForQuery(proxyQuery);

    if (listOfProxies.size())
    {
        l_proxy = listOfProxies[0];

        // If host name is not empty means proxy server is configured.
        if (!l_proxy.hostName().isEmpty()) {
            QNetworkProxy::setApplicationProxy(QNetworkProxy());
        }
    }
#endif

#if defined (Q_OS_LINUX) && QT_VERSION <= 0x050800
    QByteArray proxy_env;
    proxy_env = qgetenv("http_proxy");
    // If http_proxy environment is defined in linux then proxy server is configured.
    if (!proxy_env.isEmpty()) {
        QNetworkProxy::setApplicationProxy(QNetworkProxy());
    }
#endif

    // Display the spash screen
    QSplashScreen *splash = new QSplashScreen();
    splash->setPixmap(QPixmap(":/splash.png"));
    splash->show();
    app.processEvents(QEventLoop::AllEvents);

    quint16 port = 0L;

    // Find an unused port number. Essentially, we're just reserving one
    // here that Flask will use when we start up the server.
    // In order to use the socket, we need to free this socket ASAP.
    // Hence - putting this code in a code block so the scope of the socket
    // variable vanishes to make that socket available.
    {
#if QT_VERSION >= 0x050000
        QTcpSocket socket;

        #if QT_VERSION >= 0x050900
        socket.setProxy(QNetworkProxy::NoProxy);
        #endif

        socket.bind(0, QTcpSocket::ShareAddress);
#else
        QUdpSocket socket;
        socket.bind(0, QUdpSocket::ShareAddress);
#endif
        port = socket.localPort();
    }

    // Generate a random key to authenticate the client to the server
    QString key = QUuid::createUuid().toString();
    key = key.mid(1, key.length() - 2);

    // Generate the filename for the log
    logFileName = homeDir + (QString("/.%1.%2.log").arg(PGA_APP_NAME).arg(exeHash)).remove(" ");

    // Start the tray service
    TrayIcon *trayicon = new TrayIcon(logFileName);

    if (!trayicon->Init())
    {
        QString error = QString(QWidget::tr("An error occurred initialising the tray icon"));
        QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

        exit(1);
    }

    // Fire up the webserver
    Server *server;

    bool done = false;

    while (done != true)
    {
        server = new Server(port, key, logFileName);

        if (!server->Init())
        {
            splash->finish(NULL);

            qDebug() << server->getError();

            QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

            exit(1);
        }

        server->start();

        // This is a hack to give the server a chance to start and potentially fail. As
        // the Python interpreter is a synchronous call, we can't check for proper startup
        // easily in a more robust way - we have to rely on a clean startup not returning.
        // It should always fail pretty quickly, and take longer to start if it succeeds, so
        // we don't really get a visible delay here.
        delay(1000);

        // Any errors?
        if (server->isFinished() || server->getError().length() > 0)
        {
            splash->finish(NULL);

            qDebug() << server->getError();

            QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

            // Allow the user to tweak the Python Path if needed
            bool ok;

            ConfigWindow *dlg = new ConfigWindow();
            dlg->setWindowTitle(QWidget::tr("Configuration"));
            dlg->setBrowserCommand(settings.value("BrowserCommand").toString());
            dlg->setPythonPath(settings.value("PythonPath").toString());
            dlg->setApplicationPath(settings.value("ApplicationPath").toString());
            dlg->setModal(true);
            ok = dlg->exec();

            QString browsercommand = dlg->getBrowserCommand();
            QString pythonpath = dlg->getPythonPath();
            QString applicationpath = dlg->getApplicationPath();

            if (ok)
            {
                settings.setValue("BrowserCommand", browsercommand);
                settings.setValue("PythonPath", pythonpath);
                settings.setValue("ApplicationPath", applicationpath);
                settings.sync();
            }
            else
            {
                exit(1);
            }

            delete server;
        }
        else
            done = true;
    }

    // Ensure the server gets cleaned up later
    QObject::connect(server, SIGNAL(finished()), server, SLOT(deleteLater()));

    // Generate the app server URL
    QString appServerUrl = QString("http://127.0.0.1:%1/?key=%2").arg(port).arg(key);

    // Read the server connection timeout from the registry or set the default timeout.
    int timeout = settings.value("ConnectionTimeout", 30).toInt();

    // Now the server should be up, we'll attempt to connect and get a response.
    // We'll retry in a loop a few time before aborting if necessary.

    QTime endTime = QTime::currentTime().addSecs(timeout);
    bool alive = false;

    while(QTime::currentTime() <= endTime)
    {
        alive = PingServer(QUrl(appServerUrl));

        if (alive)
        {
            break;
        }

        delay(200);
    }

    // Attempt to connect one more time in case of a long network timeout while looping
    if (!alive && !PingServer(QUrl(appServerUrl)))
    {
        splash->finish(NULL);
        QString error(QWidget::tr("The application server could not be contacted."));
        QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

        exit(1);
    }

    // Stash the URL for any duplicate processes to open
    if (addrFile.open(QIODevice::WriteOnly))
    {
        addrFile.setPermissions(QFile::ReadOwner|QFile::WriteOwner);
        QTextStream out(&addrFile);
        out << appServerUrl << endl;
    }

    // Go!
    trayicon->setAppServerUrl(appServerUrl);
    // Enable the shutdown server menu as server started successfully.
    trayicon->enableShutdownMenu();

    QString cmd = settings.value("BrowserCommand").toString();

    if (!cmd.isEmpty())
    {
        cmd.replace("%URL%", appServerUrl);
        QProcess::startDetached(cmd);
    }
    else
    {
        if (!QDesktopServices::openUrl(appServerUrl))
        {
            QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
            QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);

            exit(1);
        }
    }

    QObject::connect(trayicon, SIGNAL(shutdownSignal(QUrl)), server, SLOT(shutdown(QUrl)));

    splash->finish(NULL);

    return app.exec();
}