Exemple #1
1
std::string MsvcCompilerSupport::compileCppModule(const Pothos::Util::CompilerArgs &compilerArgs)
{
    std::vector<std::string> tempFilesToCleanup;

    //create compiler bat script
    const auto clBatPath = Poco::TemporaryFile::tempName() + ".bat";
    tempFilesToCleanup.push_back(clBatPath);
    std::ofstream clBatFile(clBatPath.c_str());
    clBatFile << "call \"" << _vcvars_path << "\"" << std::endl;
    clBatFile << "cl.exe %*" << std::endl;
    clBatFile << "exit /b %ERRORLEVEL%" << std::endl;
    clBatFile.close();

    //create args
    Poco::Process::Args args;
    args.push_back("/LD"); //Creates a dynamic-link library
    #ifdef _DEBUG
    args.push_back("/MDd"); //Creates a multithreaded DLL
    #else
    args.push_back("/MD"); //Creates a multithreaded DLL
    #endif

    //add libraries
    for (const auto &library : compilerArgs.libraries)
    {
        args.push_back("\""+library+"\"");
    }

    //add compiler flags
    for (const auto &flag : compilerArgs.flags)
    {
        args.push_back(flag);
    }

    //add include paths
    for (const auto &include : compilerArgs.includes)
    {
        args.push_back("/I");
        args.push_back("\""+include+"\"");
    }

    //add compiler sources
    for (const auto &source : compilerArgs.sources)
    {
        const auto filePath = Poco::TemporaryFile::tempName() + ".cpp";
        tempFilesToCleanup.push_back(filePath);
        std::ofstream(filePath.c_str()).write(source.data(), source.size());
        args.push_back("/Tp"); //Specifies a C++ source file
        args.push_back(filePath);
    }

    //create temp out file
    const auto outPath = Poco::TemporaryFile::tempName() + Poco::SharedLibrary::suffix();
    tempFilesToCleanup.push_back(outPath);
    args.push_back("/link");
    args.push_back("/out:"+outPath);

    //log the command
    std::string cmdToLog = "cl.exe ";
    for (const auto &a : args) cmdToLog += a + " ";
    //poco_information(Poco::Logger::get("Pothos.MsvcCompilerSupport.compileCppModule"), cmdToLog);

    //launch
    Poco::Pipe outPipe;
    Poco::Process::Env env;
    Poco::ProcessHandle ph(Poco::Process::launch(
        clBatPath, args, nullptr, &outPipe, &outPipe, env));

    //handle error case
    if (ph.wait() != 0 or not Poco::File(outPath.c_str()).exists())
    {
        Poco::PipeInputStream errStream(outPipe);
        const std::string errMsgBuff = std::string(
            std::istreambuf_iterator<char>(errStream),
            std::istreambuf_iterator<char>());
        cleanupTempFiles(tempFilesToCleanup);
        throw Pothos::Exception("MsvcCompilerSupport::compileCppModule", errMsgBuff);
    }

    //output file to string
    std::ifstream outFile(outPath.c_str(), std::ios::binary);
    const std::string outBuff = std::string(
        std::istreambuf_iterator<char>(outFile),
        std::istreambuf_iterator<char>());
    cleanupTempFiles(tempFilesToCleanup);
    return outBuff;
}
Exemple #2
0
/***********************************************************************
 * module safe load implementation
 **********************************************************************/
Pothos::PluginModule Pothos::PluginModule::safeLoad(const std::string &path)
{
    if (previousLoadWasSuccessful(path)) return PluginModule(path);

    const int success = 200;

    //create args
    Poco::Process::Args args;
    args.push_back("--load-module");
    args.push_back("\""+path+"\""); //add quotes for paths with spaces
    args.push_back("--success-code");
    args.push_back(std::to_string(success));

    //launch
    Poco::Pipe outPipe, errPipe;
    Poco::Process::Env env;
    Poco::ProcessHandle ph(Poco::Process::launch(
        Pothos::System::getPothosUtilExecutablePath(),
        args, nullptr, &outPipe, &errPipe, env));

    //close pipes to not overfill and backup
    outPipe.close();
    errPipe.close();

    //wait, check error condition, and throw
    if (ph.wait() != success)
    {
        throw Pothos::PluginModuleError("Pothos::PluginModule("+path+")", "failed safe load");
    }

    //it was safe, load into this process now
    markCurrentLoadSuccessful(path);
    return PluginModule(path);
}
Exemple #3
0
static bool spawnSelfTestOneProcess(const std::string &path)
{
    std::cout << "Testing " << path << "... " << std::flush;
    const int success = 200;

    //create args
    Poco::Process::Args args;
    args.push_back("--self-test1");
    args.push_back(path);
    args.push_back("--success-code");
    args.push_back(std::to_string(success));

    //launch
    Poco::Process::Env env;
    Poco::Pipe outPipe; //no fwd stdio
    Poco::ProcessHandle ph(Poco::Process::launch(
        Pothos::System::getPothosUtilExecutablePath(),
        args, nullptr, &outPipe, &outPipe, env));

    std::future<std::string> verboseFuture(std::async(std::launch::async, &collectVerbose, outPipe));
    const bool ok = (ph.wait() == success);
    std::cout << ((ok)? "success!" : "FAIL!") << std::endl;

    outPipe.close();
    verboseFuture.wait();
    if (not ok) std::cout << verboseFuture.get();

    return ok;
}
void GraphEditor::handleShowFlattenedDialog(void)
{
    if (not this->isVisible()) return;

    std::string errorMsg;
    try
    {
        //temp file
        auto tempFile = Poco::TemporaryFile::tempName();
        Poco::TemporaryFile::registerForDeletion(tempFile);

        //create args
        Poco::Process::Args args;
        args.push_back("-Tpng"); //yes png
        args.push_back("-o"); //output to file
        args.push_back(tempFile);

        //launch
        Poco::Pipe inPipe, outPipe, errPipe;
        Poco::Process::Env env;
        Poco::ProcessHandle ph(Poco::Process::launch(
            Poco::Environment::get("DOT_EXECUTABLE", "dot"),
            args, &inPipe, &outPipe, &errPipe, env));

        //write the markup into dot
        Poco::PipeOutputStream os(inPipe);
        os << _topologyEngine->getTopology().toDotMarkup();
        os.close();
        outPipe.close();

        //check for errors
        if (ph.wait() != 0 or not QFile(QString::fromStdString(tempFile)).exists())
        {
            Poco::PipeInputStream es(errPipe);
            std::string errMsg;
            es >> errMsg;
            throw Pothos::Exception("PothosGui.GraphEditor.showFlattenedGraphDialog()", "png failed: " + errMsg);
        }

        //create the image from file
        QImage image(QString::fromStdString(tempFile), "png");

        //create the dialog
        auto dialog = new QDialog(this);
        dialog->setWindowTitle(tr("Flattened graph"));
        dialog->setMinimumSize(800, 600);
        auto layout = new QVBoxLayout(dialog);
        dialog->setLayout(layout);
        auto scroll = new QScrollArea(dialog);
        layout->addWidget(scroll);
        auto label = new QLabel(scroll);
        scroll->setWidget(label);
        scroll->setWidgetResizable(true);
        label->setPixmap(QPixmap::fromImage(image));
        dialog->exec();
        delete dialog;
    }
 bool test(void)
 {
     Poco::Process::Args args;
     args.push_back("--version");
     Poco::Process::Env env;
     Poco::Pipe outPipe;
     Poco::ProcessHandle ph(Poco::Process::launch(
         "clang++", args, nullptr, &outPipe, &outPipe, env));
     return ph.wait() == 0;
 }
Exemple #6
0
		bool sendCommand(const Poco::Process::Args & extraArguments, std::string & output)
		{
			// Build arguments
			Poco::Process::Args arguments;
			arguments.push_back("-n");
			arguments.push_back("-o"); arguments.push_back("ServerIp=127.0.0.1");
			arguments.push_back("-o"); arguments.push_back("ServerPort=" + Poco::NumberFormatter::format(port_));
			arguments.push_back("-o"); arguments.push_back("OutputMode=loggable");
			for (Poco::Process::Args::const_iterator it = extraArguments.begin(); it != extraArguments.end(); ++it)
			{
				arguments.push_back(*it);
			}
			
			// Run
			Poco::Pipe out, err;
			if (Poco::Process::launch(config().getString("options.nzbgetBin", "/usr/bin/nzbget"), arguments, 0, &out, &err).wait() != 0)
			{
				// Read error
				Poco::PipeInputStream stream(err);
				Poco::StreamCopier::copyToString(stream, output);
				
				return false;
			}
			else
			{
				// Read out
				Poco::PipeInputStream stream(out);
				Poco::StreamCopier::copyToString(stream, output);
				
				return true;
			}
		}
Exemple #7
0
      void CProcess::start()
      {
         boost::lock_guard<boost::recursive_mutex> lock(m_processMutex);

         try
         {
            Poco::Process::Args args;
            for (auto cmdLineArg = m_commandLine->args().begin(); cmdLineArg != m_commandLine->args().end(); ++cmdLineArg)
               args.push_back(*cmdLineArg);


            YADOMS_LOG(debug) << "Start process " << m_commandLine->executable() << " from " << m_commandLine->workingDirectory();

            if (!m_logger)
            {
               m_process = boost::make_shared<Poco::ProcessHandle>(Poco::Process::launch(m_commandLine->executable().string(),
                                                                                         args,
                                                                                         m_commandLine->workingDirectory().string()));
            }
            else
            {
               Poco::Pipe outPipe, errPipe;
               m_process = boost::make_shared<Poco::ProcessHandle>(Poco::Process::launch(m_commandLine->executable().string(),
                                                                                         args,
                                                                                         m_commandLine->workingDirectory().string(),
                                                                                         nullptr,
                                                                                         &outPipe,
                                                                                         &errPipe));

               auto moduleStdOut = boost::make_shared<Poco::PipeInputStream>(outPipe);
               auto moduleStdErr = boost::make_shared<Poco::PipeInputStream>(errPipe);
               m_StdOutRedirectingThread = boost::make_shared<boost::thread>(&CProcess::stdOutRedirectWorker,
                                                                             moduleStdOut,
                                                                             m_logger);
               m_StdErrRedirectingThread = boost::make_shared<boost::thread>(&CProcess::stdErrRedirectWorker,
                                                                             moduleStdErr,
                                                                             m_logger,
                                                                             m_lastError);
            }

            if (!!m_processObserver)
               createProcessObserver();
         }
         catch (Poco::Exception& ex)
         {
            throw CProcessException(std::string("Unable to start process, ") + ex.what());
         }
      }
Exemple #8
0
bool PlayCmd::LaunchPlayerProcess(const String& command, const Vector<String>& args, const String& initialDirectory)
{
    Poco::Process::Args pargs;

    for (unsigned i = 0; i < args.Size(); i++)
        pargs.push_back(args[i].CString());

    std::string pcommand = command.CString();
    std::string pinitialDirectory = initialDirectory.CString();

    // this can take an ENV as well, may come in useful
    Poco::ProcessHandle handle(Poco::Process::launch(pcommand, pargs, pinitialDirectory));

    if (!Poco::Process::isRunning(handle))
    {
        Error(ToString("Unable to launch player process: %s", command.CString()));
        return false;
    }

    handle.wait();

    return true;

}
Exemple #9
0
		void initDownload()
		{
			// Find server port
			for (port_ = 6800; port_ < 7800; ++port_)
			{
				try
				{
					// Can bind to IP?
					Poco::Net::ServerSocket socket(Poco::Net::SocketAddress("127.0.0.1", port_));
					socket.close();
					
					// Stop, found port
					break;
				}
				catch (...)
				{}
			}
			
			// Build arguments
			Poco::Process::Args arguments;
			arguments.push_back("-n");
			arguments.push_back("-o"); arguments.push_back("ParCheck=yes");
			arguments.push_back("-o"); arguments.push_back("ParRepair=yes");
			arguments.push_back("-o"); arguments.push_back("LockFile=" + dataFolder() + "nzbget.lock");
			arguments.push_back("-o"); arguments.push_back("LogFile=" + dataFolder() + "nzbget.log");
			arguments.push_back("-o"); arguments.push_back("NzbDir=" + dataFolder() + "nzb");
			arguments.push_back("-o"); arguments.push_back("QueueDir=" + dataFolder() + "queue");
			arguments.push_back("-o"); arguments.push_back("DestDir=" + dataFolder() + "done");
			arguments.push_back("-o"); arguments.push_back("TempDir=" + dataFolder() + "temp");
			arguments.push_back("-o"); arguments.push_back("ServerIp=0.0.0.0"); // 127.0.0.1");
			arguments.push_back("-o"); arguments.push_back("ServerPort=" + Poco::NumberFormatter::format(port_));
			arguments.push_back("-o"); arguments.push_back("OutputMode=loggable");
			arguments.push_back("-o"); arguments.push_back("DownloadRate=" + config().getString("downloadRate", "0"));
			arguments.push_back("-o"); arguments.push_back("Server1.Level=0");
			arguments.push_back("-o"); arguments.push_back("Server1.Host=" + config().getString("options.server", "usenet.server"));
			arguments.push_back("-o"); arguments.push_back("Server1.Port=" + config().getString("options.port", "119"));
			arguments.push_back("-o"); arguments.push_back("Server1.Username="******"options.username", "username"));
			arguments.push_back("-o"); arguments.push_back("Server1.Password="******"options.password", ""));
			arguments.push_back("-o"); arguments.push_back("Server1.Encryption=" + config().getString("options.encryption", "no"));
			arguments.push_back("-o"); arguments.push_back("Server1.Connections=" + config().getString("options.connections", "1"));
			arguments.push_back("-s");
			
			// Start download server
			Poco::Pipe p1, p2;
			Poco::Process::launch(config().getString("options.nzbgetBin", "/usr/bin/nzbget"), arguments, 0, &p1, &p2);
			
			// Add download?
			if (config().getString("download", "-") != "-")
			{
				// Start download
				Poco::Process::Args arguments; arguments.push_back("-A"); arguments.push_back(config().getString("download"));
				sendCommand(arguments);
			}
		}
void TskCarveExtractScalpel::carveFile(const std::string &unallocImgPath, const std::string &outputFolderPath, const std::string &stdOutFilePath, const std::string &stdErrFilePath) const
{
    try
    {
        // Find out where Scalpel is installed.
        std::string scalpelDirPath = GetSystemProperty("SCALPEL_DIR");
        if (scalpelDirPath.empty())
        {
            throw TskException("TskCarveExtractScalpel::configure : Scalpel directory not set");
        }

        if (!Poco::File(scalpelDirPath).exists())
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::configure : specified Scalpel directory '" << scalpelDirPath << "' does not exist";
            throw TskException(msg.str());
        }

        // Get the path to the Scalpel executable.
        std::stringstream pathBuilder;
        pathBuilder << scalpelDirPath << Poco::Path::separator() << SCALPEL_EXE_FILE_NAME;
        std::string scalpelExePath = pathBuilder.str();
        if (!Poco::File(scalpelExePath).exists())
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::configure : Scalpel executable '" << scalpelExePath << "' does not exist";
            throw TskException(msg.str());
        }

        // Get the path to the Scalpel config file.
        std::string scalpelConfigFilePath = GetSystemProperty("SCALPEL_CONFIG_FILE");
        if (!Poco::File(scalpelConfigFilePath).exists())
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::TskCarveExtractScalpel : Scalpel config file '" << scalpelConfigFilePath << "' does not exist";
            throw TskException(msg.str());
        }

        // Set the Scalpel command line: specify the Scalpel config file.
        Poco::Process::Args args;
        args.push_back("-c");
        args.push_back(scalpelConfigFilePath);

        // Set the Scalpel command line: allow for nested headers and footers.
        args.push_back("-e");
        
        // Set the Scalpel command line: put any carved files directly into the output folder.
        args.push_back("-o");
        args.push_back(outputFolderPath);
        args.push_back("-O");

        // Set the Scalpel command line: specify the file to carve.
        args.push_back(unallocImgPath);

        // Launch Scalpel with console output redirects.
        Poco::Pipe outPipe;
        Poco::Pipe errPipe;
        Poco::ProcessHandle handle = Poco::Process::launch(scalpelExePath, args, NULL, &outPipe, &errPipe);

        // Capture the console output. Note that Scalpel may block at times as it waits for this loop to empty the stream buffers.
        Poco::PipeInputStream stdOutInputStream(outPipe);
        Poco::FileOutputStream stdOutOutputStream(stdOutFilePath);
        Poco::PipeInputStream stdErrInputStream(errPipe);
        Poco::FileOutputStream stdErrOutputStream(stdErrFilePath);
        while (stdOutInputStream || stdErrInputStream)
        {
            if (stdOutInputStream)
            {
                Poco::StreamCopier::copyStream(stdOutInputStream, stdOutOutputStream);
            }

            if (stdErrInputStream)
            {
                Poco::StreamCopier::copyStream(stdErrInputStream, stdErrOutputStream);
            }
        }
    
        // Scalpel should be finished since the console output streams are closed.
        int exitCode = Poco::Process::wait(handle);

        stdOutOutputStream.flush();
        stdErrOutputStream.flush();

        // On the first invocation of Scalpel, record its use in the image database.
        static bool toolInfoRecorded = false;
        if (!toolInfoRecorded)
        {
            std::ifstream stdOutStream(stdOutFilePath.c_str());
            if (stdOutStream)
            {
                std::string versionString;
                std::getline(stdOutStream, versionString);
                Poco::StringTokenizer tokenizer(versionString, "\t ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); 
                if (tokenizer[0] == "Scalpel" && tokenizer[1] == "version")
                {
                    TskServices::Instance().getImgDB().addToolInfo("Scalpel", tokenizer[2].c_str());
                    toolInfoRecorded = true;
                }
                else
                {
                    LOGWARN("TskCarveExtractScalpel::carveFile : Scalpel stdout output format changed, cannot record tool info");
                }
            }
            else
            {
                LOGWARN("TskCarveExtractScalpel::carveFile : failed to open stdout stream, cannot record tool info");
            }
        }

        // Delete input files by default.
        std::string option = GetSystemProperty("CARVE_EXTRACT_KEEP_INPUT_FILES");
        std::transform(option.begin(), option.end(), option.begin(), ::toupper);
        bool deleteInputFiles = (option != "TRUE");

        if (deleteInputFiles)
        {
            Poco::File file(unallocImgPath);
            file.remove();
        }

        if (exitCode != 0)
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::carveFile : Scalpel exited with error exit code " << exitCode << " when carving '" << unallocImgPath.c_str() << "'";
            throw TskException(msg.str());
        }
    }
    catch (Poco::Exception &ex)
    {
        std::stringstream msg;
        msg << "TskCarveExtractScalpel::carveFile : Poco exception: " << ex.displayText();
        throw TskException(msg.str());
    }
}
std::string ClangCompilerSupport::compileCppModule(const Pothos::Util::CompilerArgs &compilerArgs)
{
    std::vector<std::string> tempFilesToCleanup;

    //create args
    Poco::Process::Args args;

    //add libraries
    for (const auto &library : compilerArgs.libraries)
    {
        args.push_back(library);
    }

    //add compiler flags
    args.push_back("-std=c++11");
    args.push_back("-stdlib=libc++");
    args.push_back("-shared");
    args.push_back("-fPIC");
    for (const auto &flag : compilerArgs.flags)
    {
        args.push_back(flag);
    }

    //add include paths
    for (const auto &include : compilerArgs.includes)
    {
        args.push_back("-I");
        args.push_back(include);
    }

    //add compiler sources
    args.push_back("-x");
    args.push_back("c++");
    if (compilerArgs.sources.size() == 1)
    {
        args.push_back("-"); //stdin optimization for single source
    }
    else for (const auto &source : compilerArgs.sources)
    {
        const auto filePath = Poco::TemporaryFile::tempName() + ".cpp";
        tempFilesToCleanup.push_back(filePath);
        std::ofstream(filePath.c_str()).write(source.data(), source.size());
        args.push_back(filePath);
    }

    //create temp out file
    const auto outPath = Poco::TemporaryFile::tempName() + Poco::SharedLibrary::suffix();
    tempFilesToCleanup.push_back(outPath);
    args.push_back("-o");
    args.push_back(outPath);

    //launch
    Poco::Pipe inPipe, outPipe;
    Poco::Process::Env env;
    Poco::ProcessHandle ph(Poco::Process::launch(
        "clang++", args, &inPipe, &outPipe, &outPipe, env));

    //dump single source into stdin
    if (compilerArgs.sources.size() == 1)
    {
        Poco::PipeOutputStream inStream(inPipe);
        inStream.write(compilerArgs.sources[0].data(), compilerArgs.sources[0].size());
        inStream.close();
    }

    //handle error case
    if (ph.wait() != 0)
    {
        Poco::PipeInputStream errStream(outPipe);
        const std::string errMsgBuff = std::string(
            std::istreambuf_iterator<char>(errStream),
            std::istreambuf_iterator<char>());
        cleanupTempFiles(tempFilesToCleanup);
        throw Pothos::Exception("ClangCompilerSupport::compileCppModule", errMsgBuff);
    }

    //output file to string
    std::ifstream outFile(outPath.c_str(), std::ios::binary);
    const std::string outBuff = std::string(
        std::istreambuf_iterator<char>(outFile),
        std::istreambuf_iterator<char>());
    cleanupTempFiles(tempFilesToCleanup);
    return outBuff;
}
std::string ClangCompilerSupport::compileCppModule(const Pothos::Util::CompilerArgs &compilerArgs)
{
    //create args
    Poco::Process::Args args;

    //add libraries
    for (const auto &library : compilerArgs.libraries)
    {
        args.push_back(library);
    }

    //add compiler flags
    args.push_back("-std=c++11");
    args.push_back("-stdlib=libc++");
    args.push_back("-shared");
    args.push_back("-fPIC");
    for (const auto &flag : compilerArgs.flags)
    {
        args.push_back(flag);
    }

    //add include paths
    for (const auto &include : compilerArgs.includes)
    {
        args.push_back("-I");
        args.push_back(include);
    }

    //add compiler sources
    args.push_back("-x");
    args.push_back("c++");
    for (const auto &source : compilerArgs.sources)
    {
        args.push_back(source);
    }

    //create temp out file
    const auto outPath = this->createTempFile(Poco::SharedLibrary::suffix());
    args.push_back("-o");
    args.push_back(outPath);

    //launch
    Poco::Pipe inPipe, outPipe;
    Poco::Process::Env env;
    Poco::ProcessHandle ph(Poco::Process::launch(
        "clang++", args, &inPipe, &outPipe, &outPipe, env));

    //handle error case
    if (ph.wait() != 0)
    {
        Poco::PipeInputStream errStream(outPipe);
        const std::string errMsgBuff = std::string(
            std::istreambuf_iterator<char>(errStream),
            std::istreambuf_iterator<char>());
        throw Pothos::Exception("ClangCompilerSupport::compileCppModule", errMsgBuff);
    }

    //return output file path
    return outPath;
}
	int main(const std::vector<std::string>& args)
	{
		int rc = Poco::Util::Application::EXIT_OK;
		if (_helpRequested || args.empty())
		{
			displayHelp();
		}
		else
		{
			Poco::Timespan connectTimeout = Poco::Timespan(config().getInt("webtunnel.connectTimeout", 30), 0);
			Poco::Timespan remoteTimeout = Poco::Timespan(config().getInt("webtunnel.remoteTimeout", 300), 0);
			Poco::Timespan localTimeout = Poco::Timespan(config().getInt("webtunnel.localTimeout", 7200), 0);

#if defined(WEBTUNNEL_ENABLE_TLS)
			bool acceptUnknownCert = config().getBool("tls.acceptUnknownCertificate", true);
			std::string cipherList = config().getString("tls.ciphers", "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
			bool extendedVerification = config().getBool("tls.extendedCertificateVerification", false);
			std::string caLocation = config().getString("tls.caLocation", "");

			Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> pCertificateHandler;
			if (acceptUnknownCert)
				pCertificateHandler = new Poco::Net::AcceptCertificateHandler(false);
			else
				pCertificateHandler = new Poco::Net::RejectCertificateHandler(false);
			Poco::Net::Context::Ptr pContext = new Poco::Net::Context(Poco::Net::Context::TLSV1_CLIENT_USE, "", "", caLocation, Poco::Net::Context::VERIFY_RELAXED, 5, true, cipherList);
			pContext->enableExtendedCertificateVerification(extendedVerification);
			Poco::Net::SSLManager::instance().initializeClient(0, pCertificateHandler, pContext);
#endif

			if (config().getBool("http.proxy.enable", false))
			{
				logger().information("Proxy enable");
				Poco::Net::HTTPClientSession::ProxyConfig proxyConfig;
				proxyConfig.host = config().getString("http.proxy.host", "");
				proxyConfig.port = static_cast<Poco::UInt16>(config().getInt("http.proxy.port", 80));
				proxyConfig.username = config().getString("http.proxy.username", "");
				proxyConfig.password = config().getString("http.proxy.password", "");
				Poco::Net::HTTPClientSession::setGlobalProxyConfig(proxyConfig);
			}

			promptLogin();

			Poco::URI uri(args[0]);
			Poco::WebTunnel::LocalPortForwarder forwarder(_localPort, _remotePort, uri, new Poco::WebTunnel::DefaultWebSocketFactory(_username, _password, connectTimeout));
			forwarder.setRemoteTimeout(remoteTimeout);
			forwarder.setLocalTimeout(localTimeout);
			
			Poco::UInt16 localPort = forwarder.localPort();
			std::string defaultVNCExecutable;
#if defined(__APPLE__)
			defaultVNCExecutable = "open";
#else
			defaultVNCExecutable = "vncviewer";
#endif
			std::string vncExecutable = config().getString("vncviewer.executable", defaultVNCExecutable);
			Poco::Process::Args vncArgs;
			if (vncExecutable == "open")
			{
				vncArgs.push_back("-W");
				vncArgs.push_back("-n");
				vncArgs.push_back("vnc://localhost:" + Poco::NumberFormatter::format(static_cast<unsigned>(localPort)));
			}
			else
			{
				vncArgs.push_back("localhost:" + Poco::NumberFormatter::format(static_cast<unsigned>(localPort)));
			}
			vncArgs.insert(vncArgs.end(), ++args.begin(), args.end());
			
			logger().debug(Poco::format("Launching VNC client: %s", vncExecutable));
			Poco::ProcessHandle ph = Poco::Process::launch(vncExecutable, vncArgs);
			rc = ph.wait();
			logger().debug(Poco::format("VNC client terminated with exit code %d", rc));
		}
		return rc;
	}