diff -Nru cutycapt-0.0~svn6/CutyCapt.cpp cutycapt-0.0~svn10/CutyCapt.cpp --- cutycapt-0.0~svn6/CutyCapt.cpp 2010-06-08 18:12:11.000000000 +0000 +++ cutycapt-0.0~svn10/CutyCapt.cpp 2016-08-05 15:01:55.000000000 +0000 @@ -1,657 +1,719 @@ -//////////////////////////////////////////////////////////////////// -// -// CutyCapt - A Qt WebKit Web Page Rendering Capture Utility -// -// Copyright (C) 2003-2010 Bjoern Hoehrmann -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// $Id$ -// -//////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include "CutyCapt.hpp" - -#if QT_VERSION >= 0x040600 && 0 -#define CUTYCAPT_SCRIPT 1 -#endif - -#ifdef STATIC_PLUGINS - Q_IMPORT_PLUGIN(qjpeg) - Q_IMPORT_PLUGIN(qgif) - Q_IMPORT_PLUGIN(qtiff) - Q_IMPORT_PLUGIN(qsvg) - Q_IMPORT_PLUGIN(qmng) - Q_IMPORT_PLUGIN(qico) -#endif - -static struct _CutyExtMap { - CutyCapt::OutputFormat id; - const char* extension; - const char* identifier; -} const CutyExtMap[] = { - { CutyCapt::SvgFormat, ".svg", "svg" }, - { CutyCapt::PdfFormat, ".pdf", "pdf" }, - { CutyCapt::PsFormat, ".ps", "ps" }, - { CutyCapt::InnerTextFormat, ".txt", "itext" }, - { CutyCapt::HtmlFormat, ".html", "html" }, - { CutyCapt::RenderTreeFormat, ".rtree", "rtree" }, - { CutyCapt::JpegFormat, ".jpeg", "jpeg" }, - { CutyCapt::PngFormat, ".png", "png" }, - { CutyCapt::MngFormat, ".mng", "mng" }, - { CutyCapt::TiffFormat, ".tiff", "tiff" }, - { CutyCapt::GifFormat, ".gif", "gif" }, - { CutyCapt::BmpFormat, ".bmp", "bmp" }, - { CutyCapt::PpmFormat, ".ppm", "ppm" }, - { CutyCapt::XbmFormat, ".xbm", "xbm" }, - { CutyCapt::XpmFormat, ".xpm", "xpm" }, - { CutyCapt::OtherFormat, "", "" } -}; - -QString -CutyPage::chooseFile(QWebFrame* /*frame*/, const QString& /*suggestedFile*/) { - return QString::null; -} - -bool -CutyPage::javaScriptConfirm(QWebFrame* /*frame*/, const QString& /*msg*/) { - return true; -} - -bool -CutyPage::javaScriptPrompt(QWebFrame* /*frame*/, - const QString& /*msg*/, - const QString& /*defaultValue*/, - QString* /*result*/) { - return true; -} - -void -CutyPage::javaScriptConsoleMessage(const QString& /*message*/, - int /*lineNumber*/, - const QString& /*sourceID*/) { - // noop -} - -void -CutyPage::javaScriptAlert(QWebFrame* /*frame*/, const QString& msg) { - - if (mPrintAlerts) - qDebug() << "[alert]" << msg; - - if (mAlertString == msg) { - QTimer::singleShot(10, mCutyCapt, SLOT(Delayed())); - } -} - -QString -CutyPage::userAgentForUrl(const QUrl& url) const { - - if (!mUserAgent.isNull()) - return mUserAgent; - - return QWebPage::userAgentForUrl(url); -} - -void -CutyPage::setUserAgent(const QString& userAgent) { - mUserAgent = userAgent; -} - -void -CutyPage::setAlertString(const QString& alertString) { - mAlertString = alertString; -} - -QString -CutyPage::getAlertString() { - return mAlertString; -} - -void -CutyPage::setCutyCapt(CutyCapt* cutyCapt) { - mCutyCapt = cutyCapt; -} - -void -CutyPage::setPrintAlerts(bool printAlerts) { - mPrintAlerts = printAlerts; -} - -void -CutyPage::setAttribute(QWebSettings::WebAttribute option, - const QString& value) { - - if (value == "on") - settings()->setAttribute(option, true); - else if (value == "off") - settings()->setAttribute(option, false); - else - (void)0; // TODO: ... -} - -// TODO: Consider merging some of main() and CutyCap - -CutyCapt::CutyCapt(CutyPage* page, const QString& output, int delay, OutputFormat format, - const QString& scriptProp, const QString& scriptCode) { - mPage = page; - mOutput = output; - mDelay = delay; - mSawInitialLayout = false; - mSawDocumentComplete = false; - mFormat = format; - mScriptProp = scriptProp; - mScriptCode = scriptCode; - mScriptObj = new QObject(); - - // This is not really nice, but some restructuring work is - // needed anyway, so this should not be that bad for now. - mPage->setCutyCapt(this); -} - -void -CutyCapt::InitialLayoutCompleted() { - mSawInitialLayout = true; - - if (mSawInitialLayout && mSawDocumentComplete) - TryDelayedRender(); -} - -void -CutyCapt::DocumentComplete(bool /*ok*/) { - mSawDocumentComplete = true; - - if (mSawInitialLayout && mSawDocumentComplete) - TryDelayedRender(); -} - -void -CutyCapt::JavaScriptWindowObjectCleared() { - - if (!mScriptProp.isEmpty()) { - QVariant var = mPage->mainFrame()->evaluateJavaScript(mScriptProp); - QObject* obj = var.value(); - - if (obj == mScriptObj) - return; - - mPage->mainFrame()->addToJavaScriptWindowObject(mScriptProp, mScriptObj); - } - - mPage->mainFrame()->evaluateJavaScript(mScriptCode); - -} - -void -CutyCapt::TryDelayedRender() { - - if (!mPage->getAlertString().isEmpty()) - return; - - if (mDelay > 0) { - QTimer::singleShot(mDelay, this, SLOT(Delayed())); - return; - } - - saveSnapshot(); - QApplication::exit(); -} - -void -CutyCapt::Timeout() { - saveSnapshot(); - QApplication::exit(); -} - -void -CutyCapt::Delayed() { - saveSnapshot(); - QApplication::exit(); -} - -void -CutyCapt::saveSnapshot() { - QWebFrame *mainFrame = mPage->mainFrame(); - QPainter painter; - const char* format = NULL; - - for (int ix = 0; CutyExtMap[ix].id != OtherFormat; ++ix) - if (CutyExtMap[ix].id == mFormat) - format = CutyExtMap[ix].identifier; //, break; - - // TODO: sometimes contents/viewport can have size 0x0 - // in which case saving them will fail. This is likely - // the result of the method being called too early. So - // far I've been unable to find a workaround, except - // using --delay with some substantial wait time. I've - // tried to resize multiple time, make a fake render, - // check for other events... This is primarily a problem - // under my Ubuntu virtual machine. - - mPage->setViewportSize( mainFrame->contentsSize() ); - - switch (mFormat) { - case SvgFormat: { - QSvgGenerator svg; - svg.setFileName(mOutput); - svg.setSize(mPage->viewportSize()); - painter.begin(&svg); - mainFrame->render(&painter); - painter.end(); - break; - } - case PdfFormat: - case PsFormat: { - QPrinter printer; - printer.setPageSize(QPrinter::A4); - printer.setOutputFileName(mOutput); - // TODO: change quality here? - mainFrame->print(&printer); - break; - } - case RenderTreeFormat: - case InnerTextFormat: - case HtmlFormat: { - QFile file(mOutput); - file.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream s(&file); - s.setCodec("utf-8"); - s << (mFormat == RenderTreeFormat ? mainFrame->renderTreeDump() : - mFormat == InnerTextFormat ? mainFrame->toPlainText() : - mFormat == HtmlFormat ? mainFrame->toHtml() : - "bug"); - break; - } - default: { - QImage image(mPage->viewportSize(), QImage::Format_ARGB32); - painter.begin(&image); - mainFrame->render(&painter); - painter.end(); - // TODO: add quality - image.save(mOutput, format); - } - }; -} - -void -CaptHelp(void) { - printf("%s", - " -----------------------------------------------------------------------------\n" - " Usage: CutyCapt --url=http://www.example.org/ --out=localfile.png \n" - " -----------------------------------------------------------------------------\n" - " --help Print this help page and exit \n" - " --url= The URL to capture (http:...|file:...|...) \n" - " --out= The target file (.png|pdf|ps|svg|jpeg|...) \n" - " --out-format= Like extension in --out, overrides heuristic \n" -// " --out-quality= Output format quality from 1 to 100 \n" - " --min-width= Minimal width for the image (default: 800) \n" - " --min-height= Minimal height for the image (default: 600) \n" - " --max-wait= Don't wait more than (default: 90000, inf: 0)\n" - " --delay= After successful load, wait (default: 0) \n" -// " --user-styles= Location of user style sheet (deprecated) \n" - " --user-style-path= Location of user style sheet file, if any \n" - " --user-style-string= User style rules specified as text \n" - " --header=: request header; repeatable; some can't be set\n" - " --method= Specifies the request method (default: get) \n" - " --body-string= Unencoded request body (default: none) \n" - " --body-base64= Base64-encoded request body (default: none) \n" - " --app-name= appName used in User-Agent; default is none \n" - " --app-version= appVers used in User-Agent; default is none \n" - " --user-agent= Override the User-Agent header Qt would set \n" - " --javascript= JavaScript execution (default: on) \n" - " --java= Java execution (default: unknown) \n" - " --plugins= Plugin execution (default: unknown) \n" - " --private-browsing= Private browsing (default: unknown) \n" - " --auto-load-images= Automatic image loading (default: on) \n" - " --js-can-open-windows= Script can open windows? (default: unknown) \n" - " --js-can-access-clipboard= Script clipboard privs (default: unknown)\n" -#if QT_VERSION >= 0x040500 - " --print-backgrounds= Backgrounds in PDF/PS output (default: off) \n" - " --zoom-factor= Page zoom factor (default: no zooming) \n" - " --zoom-text-only= Whether to zoom only the text (default: off) \n" - " --http-proxy= Address for HTTP proxy server (default: none)\n" -#endif -#if CUTYCAPT_SCRIPT - " --inject-script= JavaScript that will be injected into pages \n" - " --script-object= Property to hold state for injected script \n" - " --expect-alert= Try waiting for alert(string) before capture \n" - " --debug-print-alerts Prints out alert(...) strings for debugging. \n" -#endif - " -----------------------------------------------------------------------------\n" - " is svg,ps,pdf,itext,html,rtree,png,jpeg,mng,tiff,gif,bmp,ppm,xbm,xpm \n" - " -----------------------------------------------------------------------------\n" -#if CUTYCAPT_SCRIPT - " The `inject-script` option can be used to inject script code into loaded web \n" - " pages. The code is called whenever the `javaScriptWindowObjectCleared` signal\n" - " is received. When `script-object` is set, an object under the specified name \n" - " will be available to the script to maintain state across page loads. When the\n" - " `expect-alert` option is specified, the shot will be taken when a script in- \n" - " vokes alert(string) with the string if that happens before `max-wait`. These \n" - " options effectively allow you to remote control the browser and the web page.\n" - " This an experimental and easily abused and misused feature. Use with caution.\n" - " -----------------------------------------------------------------------------\n" -#endif - " http://cutycapt.sf.net - (c) 2003-2010 Bjoern Hoehrmann - bjoern@hoehrmann.de\n" - ""); -} - -int -main(int argc, char *argv[]) { - - int argHelp = 0; - int argDelay = 0; - int argSilent = 0; - int argMinWidth = 800; - int argMinHeight = 600; - int argMaxWait = 90000; - int argVerbosity = 0; - - const char* argUrl = NULL; - const char* argUserStyle = NULL; - const char* argUserStylePath = NULL; - const char* argUserStyleString = NULL; - const char* argIconDbPath = NULL; - const char* argInjectScript = NULL; - const char* argScriptObject = NULL; - QString argOut; - - CutyCapt::OutputFormat format = CutyCapt::OtherFormat; - - QApplication app(argc, argv, true); - CutyPage page; - - QNetworkAccessManager::Operation method = - QNetworkAccessManager::GetOperation; - QByteArray body; - QNetworkRequest req; - QNetworkAccessManager manager; - - // Parse command line parameters - for (int ax = 1; ax < argc; ++ax) { - size_t nlen; - - const char* s = argv[ax]; - const char* value; - - // boolean options - if (strcmp("--silent", s) == 0) { - argSilent = 1; - continue; - - } else if (strcmp("--help", s) == 0) { - argHelp = 1; - break; - - } else if (strcmp("--verbose", s) == 0) { - argVerbosity++; - continue; - -#if CUTYCAPT_SCRIPT - } else if (strcmp("--debug-print-alerts", s) == 0) { - page.setPrintAlerts(true); - continue; -#endif - } - - value = strchr(s, '='); - - if (value == NULL) { - // TODO: error - argHelp = 1; - break; - } - - nlen = value++ - s; - - // --name=value options - if (strncmp("--url", s, nlen) == 0) { - argUrl = value; - - } else if (strncmp("--min-width", s, nlen) == 0) { - // TODO: add error checking here? - argMinWidth = (unsigned int)atoi(value); - - } else if (strncmp("--min-height", s, nlen) == 0) { - // TODO: add error checking here? - argMinHeight = (unsigned int)atoi(value); - - } else if (strncmp("--delay", s, nlen) == 0) { - // TODO: see above - argDelay = (unsigned int)atoi(value); - - } else if (strncmp("--max-wait", s, nlen) == 0) { - // TODO: see above - argMaxWait = (unsigned int)atoi(value); - - } else if (strncmp("--out", s, nlen) == 0) { - argOut = value; - - if (format == CutyCapt::OtherFormat) - for (int ix = 0; CutyExtMap[ix].id != CutyCapt::OtherFormat; ++ix) - if (argOut.endsWith(CutyExtMap[ix].extension)) - format = CutyExtMap[ix].id; //, break; - - } else if (strncmp("--user-styles", s, nlen) == 0) { - // This option is provided for backwards-compatibility only - argUserStyle = value; - - } else if (strncmp("--user-style-path", s, nlen) == 0) { - argUserStylePath = value; - - } else if (strncmp("--user-style-string", s, nlen) == 0) { - argUserStyleString = value; - - } else if (strncmp("--icon-database-path", s, nlen) == 0) { - argIconDbPath = value; - - } else if (strncmp("--auto-load-images", s, nlen) == 0) { - page.setAttribute(QWebSettings::AutoLoadImages, value); - - } else if (strncmp("--javascript", s, nlen) == 0) { - page.setAttribute(QWebSettings::JavascriptEnabled, value); - - } else if (strncmp("--java", s, nlen) == 0) { - page.setAttribute(QWebSettings::JavaEnabled, value); - - } else if (strncmp("--plugins", s, nlen) == 0) { - page.setAttribute(QWebSettings::PluginsEnabled, value); - - } else if (strncmp("--private-browsing", s, nlen) == 0) { - page.setAttribute(QWebSettings::PrivateBrowsingEnabled, value); - - } else if (strncmp("--js-can-open-windows", s, nlen) == 0) { - page.setAttribute(QWebSettings::JavascriptCanOpenWindows, value); - - } else if (strncmp("--js-can-access-clipboard", s, nlen) == 0) { - page.setAttribute(QWebSettings::JavascriptCanAccessClipboard, value); - - } else if (strncmp("--developer-extras", s, nlen) == 0) { - page.setAttribute(QWebSettings::DeveloperExtrasEnabled, value); - - } else if (strncmp("--links-included-in-focus-chain", s, nlen) == 0) { - page.setAttribute(QWebSettings::LinksIncludedInFocusChain, value); - -#if QT_VERSION >= 0x040500 - } else if (strncmp("--print-backgrounds", s, nlen) == 0) { - page.setAttribute(QWebSettings::PrintElementBackgrounds, value); - - } else if (strncmp("--zoom-factor", s, nlen) == 0) { - page.mainFrame()->setZoomFactor(QString(value).toFloat()); - - } else if (strncmp("--zoom-text-only", s, nlen) == 0) { - page.setAttribute(QWebSettings::ZoomTextOnly, value); - - } else if (strncmp("--http-proxy", s, nlen) == 0) { - QUrl p = QUrl::fromEncoded(value); - QNetworkProxy proxy = QNetworkProxy(QNetworkProxy::HttpProxy, - p.host(), p.port(80), p.userName(), p.password()); - manager.setProxy(proxy); - page.setNetworkAccessManager(&manager); -#endif - -#if CUTYCAPT_SCRIPT - } else if (strncmp("--inject-script", s, nlen) == 0) { - argInjectScript = value; - - } else if (strncmp("--script-object", s, nlen) == 0) { - argScriptObject = value; - - } else if (strncmp("--expect-alert", s, nlen) == 0) { - page.setAlertString(value); -#endif - - } else if (strncmp("--app-name", s, nlen) == 0) { - app.setApplicationName(value); - - } else if (strncmp("--app-version", s, nlen) == 0) { - app.setApplicationVersion(value); - - } else if (strncmp("--body-base64", s, nlen) == 0) { - body = QByteArray::fromBase64(value); - - } else if (strncmp("--body-string", s, nlen) == 0) { - body = QByteArray(value); - - } else if (strncmp("--user-agent", s, nlen) == 0) { - page.setUserAgent(value); - - } else if (strncmp("--out-format", s, nlen) == 0) { - for (int ix = 0; CutyExtMap[ix].id != CutyCapt::OtherFormat; ++ix) - if (strcmp(value, CutyExtMap[ix].identifier) == 0) - format = CutyExtMap[ix].id; //, break; - - if (format == CutyCapt::OtherFormat) { - // TODO: error - argHelp = 1; - break; - } - - } else if (strncmp("--header", s, nlen) == 0) { - const char* hv = strchr(value, ':'); - - if (hv == NULL) { - // TODO: error - argHelp = 1; - break; - } - - req.setRawHeader(QByteArray(value, hv - value), hv + 1); - - } else if (strncmp("--method", s, nlen) == 0) { - if (strcmp("value", "get") == 0) - method = QNetworkAccessManager::GetOperation; - else if (strcmp("value", "put") == 0) - method = QNetworkAccessManager::PutOperation; - else if (strcmp("value", "post") == 0) - method = QNetworkAccessManager::PostOperation; - else if (strcmp("value", "head") == 0) - method = QNetworkAccessManager::HeadOperation; - else - (void)0; // TODO: ... - - } else { - // TODO: error - argHelp = 1; - } - } - - if (argUrl == NULL || argOut == NULL || argHelp) { - CaptHelp(); - return EXIT_FAILURE; - } - - // This used to use QUrl(argUrl) but that escapes %hh sequences - // even though it should not, as URLs can assumed to be escaped. - req.setUrl( QUrl::fromEncoded(argUrl) ); - - QString scriptProp(argScriptObject); - QString scriptCode; - - if (argInjectScript) { - QFile file(argInjectScript); - if (file.open(QIODevice::ReadOnly)) { - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - stream.setAutoDetectUnicode(true); - scriptCode = stream.readAll(); - file.close(); - } - } - - CutyCapt main(&page, argOut, argDelay, format, scriptProp, scriptCode); - - app.connect(&page, - SIGNAL(loadFinished(bool)), - &main, - SLOT(DocumentComplete(bool))); - - app.connect(page.mainFrame(), - SIGNAL(initialLayoutCompleted()), - &main, - SLOT(InitialLayoutCompleted())); - - if (argMaxWait > 0) { - // TODO: Should this also register one for the application? - QTimer::singleShot(argMaxWait, &main, SLOT(Timeout())); - } - - if (argUserStyle != NULL) - // TODO: does this need any syntax checking? - page.settings()->setUserStyleSheetUrl( QUrl::fromEncoded(argUserStyle) ); - - if (argUserStylePath != NULL) { - page.settings()->setUserStyleSheetUrl( QUrl::fromLocalFile(argUserStylePath) ); - } - - if (argUserStyleString != NULL) { - QUrl data("data:text/css;charset=utf-8;base64," + - QByteArray(argUserStyleString).toBase64()); - page.settings()->setUserStyleSheetUrl( data ); - } - - if (argIconDbPath != NULL) - // TODO: does this need any syntax checking? - page.settings()->setIconDatabasePath(argUserStyle); - - // The documentation does not say, but it seems the mainFrame - // will never change, so we can set this here. Otherwise we'd - // have to set this in snapshot and trigger an update, which - // is not currently possible (Qt 4.4.0) as far as I can tell. - page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); - page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); - page.setViewportSize( QSize(argMinWidth, argMinHeight) ); - -#if CUTYCAPT_SCRIPT - // javaScriptWindowObjectCleared does not get called on the - // initial load unless some JavaScript has been executed. - page.mainFrame()->evaluateJavaScript(QString("")); - - app.connect(page.mainFrame(), - SIGNAL(javaScriptWindowObjectCleared()), - &main, - SLOT(JavaScriptWindowObjectCleared())); -#endif - - if (!body.isNull()) - page.mainFrame()->load(req, method, body); - else - page.mainFrame()->load(req, method); - - return app.exec(); -} +//////////////////////////////////////////////////////////////////// +// +// CutyCapt - A Qt WebKit Web Page Rendering Capture Utility +// +// Copyright (C) 2003-2013 Bjoern Hoehrmann +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// $Id: CutyCapt.cpp 10 2013-07-14 21:57:37Z hoehrmann $ +// +//////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#if QT_VERSION < 0x050000 +#include +#endif + +#include +#include +#include +#include +#include "CutyCapt.hpp" + +#if QT_VERSION >= 0x040600 && 0 +#define CUTYCAPT_SCRIPT 1 +#endif + +#ifdef STATIC_PLUGINS + Q_IMPORT_PLUGIN(qjpeg) + Q_IMPORT_PLUGIN(qgif) + Q_IMPORT_PLUGIN(qtiff) + Q_IMPORT_PLUGIN(qsvg) + Q_IMPORT_PLUGIN(qmng) + Q_IMPORT_PLUGIN(qico) +#endif + +static struct _CutyExtMap { + CutyCapt::OutputFormat id; + const char* extension; + const char* identifier; +} const CutyExtMap[] = { + { CutyCapt::SvgFormat, ".svg", "svg" }, + { CutyCapt::PdfFormat, ".pdf", "pdf" }, + { CutyCapt::PsFormat, ".ps", "ps" }, + { CutyCapt::InnerTextFormat, ".txt", "itext" }, + { CutyCapt::HtmlFormat, ".html", "html" }, +#if QT_VERSION < 0x050000 + { CutyCapt::RenderTreeFormat, ".rtree", "rtree" }, +#endif + { CutyCapt::JpegFormat, ".jpeg", "jpeg" }, + { CutyCapt::PngFormat, ".png", "png" }, + { CutyCapt::MngFormat, ".mng", "mng" }, + { CutyCapt::TiffFormat, ".tiff", "tiff" }, + { CutyCapt::GifFormat, ".gif", "gif" }, + { CutyCapt::BmpFormat, ".bmp", "bmp" }, + { CutyCapt::PpmFormat, ".ppm", "ppm" }, + { CutyCapt::XbmFormat, ".xbm", "xbm" }, + { CutyCapt::XpmFormat, ".xpm", "xpm" }, + { CutyCapt::OtherFormat, "", "" } +}; + +QString +CutyPage::chooseFile(QWebFrame* /*frame*/, const QString& /*suggestedFile*/) { + return QString::null; +} + +bool +CutyPage::javaScriptConfirm(QWebFrame* /*frame*/, const QString& /*msg*/) { + return true; +} + +bool +CutyPage::javaScriptPrompt(QWebFrame* /*frame*/, + const QString& /*msg*/, + const QString& /*defaultValue*/, + QString* /*result*/) { + return true; +} + +void +CutyPage::javaScriptConsoleMessage(const QString& /*message*/, + int /*lineNumber*/, + const QString& /*sourceID*/) { + // noop +} + +void +CutyPage::javaScriptAlert(QWebFrame* /*frame*/, const QString& msg) { + + if (mPrintAlerts) + qDebug() << "[alert]" << msg; + + if (mAlertString == msg) { + QTimer::singleShot(10, mCutyCapt, SLOT(Delayed())); + } +} + +QString +CutyPage::userAgentForUrl(const QUrl& url) const { + + if (!mUserAgent.isNull()) + return mUserAgent; + + return QWebPage::userAgentForUrl(url); +} + +void +CutyPage::setUserAgent(const QString& userAgent) { + mUserAgent = userAgent; +} + +void +CutyPage::setAlertString(const QString& alertString) { + mAlertString = alertString; +} + +QString +CutyPage::getAlertString() { + return mAlertString; +} + +void +CutyPage::setCutyCapt(CutyCapt* cutyCapt) { + mCutyCapt = cutyCapt; +} + +void +CutyPage::setPrintAlerts(bool printAlerts) { + mPrintAlerts = printAlerts; +} + +void +CutyPage::setAttribute(QWebSettings::WebAttribute option, + const QString& value) { + + if (value == "on") + settings()->setAttribute(option, true); + else if (value == "off") + settings()->setAttribute(option, false); + else + (void)0; // TODO: ... +} + +// TODO: Consider merging some of main() and CutyCap + +CutyCapt::CutyCapt(CutyPage* page, const QString& output, int delay, OutputFormat format, + const QString& scriptProp, const QString& scriptCode, bool insecure, + bool smooth) { + mPage = page; + mOutput = output; + mDelay = delay; + mInsecure = insecure; + mSmooth = smooth; + mSawInitialLayout = false; + mSawDocumentComplete = false; + mFormat = format; + mScriptProp = scriptProp; + mScriptCode = scriptCode; + mScriptObj = new QObject(); + + // This is not really nice, but some restructuring work is + // needed anyway, so this should not be that bad for now. + mPage->setCutyCapt(this); +} + +void +CutyCapt::InitialLayoutCompleted() { + mSawInitialLayout = true; + + if (mSawInitialLayout && mSawDocumentComplete) + TryDelayedRender(); +} + +void +CutyCapt::DocumentComplete(bool /*ok*/) { + mSawDocumentComplete = true; + + if (mSawInitialLayout && mSawDocumentComplete) + TryDelayedRender(); +} + +void +CutyCapt::JavaScriptWindowObjectCleared() { + + if (!mScriptProp.isEmpty()) { + QVariant var = mPage->mainFrame()->evaluateJavaScript(mScriptProp); + QObject* obj = var.value(); + + if (obj == mScriptObj) + return; + + mPage->mainFrame()->addToJavaScriptWindowObject(mScriptProp, mScriptObj); + } + + mPage->mainFrame()->evaluateJavaScript(mScriptCode); + +} + +void +CutyCapt::TryDelayedRender() { + + if (!mPage->getAlertString().isEmpty()) + return; + + if (mDelay > 0) { + QTimer::singleShot(mDelay, this, SLOT(Delayed())); + return; + } + + saveSnapshot(); + QApplication::exit(); +} + +void +CutyCapt::Timeout() { + saveSnapshot(); + QApplication::exit(); +} + +void +CutyCapt::Delayed() { + saveSnapshot(); + QApplication::exit(); +} + +void +CutyCapt::handleSslErrors(QNetworkReply* reply, QList errors) { + if (mInsecure) { + reply->ignoreSslErrors(); + } else { + // TODO: what to do here instead of hanging? + } +} + +void +CutyCapt::saveSnapshot() { + QWebFrame *mainFrame = mPage->mainFrame(); + QPainter painter; + const char* format = NULL; + + for (int ix = 0; CutyExtMap[ix].id != OtherFormat; ++ix) + if (CutyExtMap[ix].id == mFormat) + format = CutyExtMap[ix].identifier; //, break; + + // TODO: sometimes contents/viewport can have size 0x0 + // in which case saving them will fail. This is likely + // the result of the method being called too early. So + // far I've been unable to find a workaround, except + // using --delay with some substantial wait time. I've + // tried to resize multiple time, make a fake render, + // check for other events... This is primarily a problem + // under my Ubuntu virtual machine. + + mPage->setViewportSize( mainFrame->contentsSize() ); + + switch (mFormat) { + case SvgFormat: { + QSvgGenerator svg; + svg.setFileName(mOutput); + svg.setSize(mPage->viewportSize()); + painter.begin(&svg); + mainFrame->render(&painter); + painter.end(); + break; + } + case PdfFormat: + case PsFormat: { + QPrinter printer; + printer.setPageSize(QPrinter::A4); + printer.setOutputFileName(mOutput); + // TODO: change quality here? + mainFrame->print(&printer); + break; + } +#if QT_VERSION < 0x050000 + case RenderTreeFormat: { + QFile file(mOutput); + file.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream s(&file); + s.setCodec("utf-8"); + s << mainFrame->renderTreeDump(); + break; + } +#endif + case InnerTextFormat: + case HtmlFormat: { + QFile file(mOutput); + file.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream s(&file); + s.setCodec("utf-8"); + s << (mFormat == InnerTextFormat ? mainFrame->toPlainText() : + mFormat == HtmlFormat ? mainFrame->toHtml() : + "bug"); + break; + } + default: { + QImage image(mPage->viewportSize(), QImage::Format_ARGB32); + painter.begin(&image); +#if QT_VERSION >= 0x050000 + if (mSmooth) { + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.setRenderHint(QPainter::Antialiasing); + painter.setRenderHint(QPainter::TextAntialiasing); + painter.setRenderHint(QPainter::HighQualityAntialiasing); + } +#endif + mainFrame->render(&painter); + painter.end(); + // TODO: add quality + image.save(mOutput, format); + } + }; +} + +void +CaptHelp(void) { + printf("%s", + " -----------------------------------------------------------------------------\n" + " Usage: CutyCapt --url=http://www.example.org/ --out=localfile.png \n" + " -----------------------------------------------------------------------------\n" + " --help Print this help page and exit \n" + " --url= The URL to capture (http:...|file:...|...) \n" + " --out= The target file (.png|pdf|ps|svg|jpeg|...) \n" + " --out-format= Like extension in --out, overrides heuristic \n" +// " --out-quality= Output format quality from 1 to 100 \n" + " --min-width= Minimal width for the image (default: 800) \n" + " --min-height= Minimal height for the image (default: 600) \n" + " --max-wait= Don't wait more than (default: 90000, inf: 0)\n" + " --delay= After successful load, wait (default: 0) \n" +// " --user-styles= Location of user style sheet (deprecated) \n" + " --user-style-path= Location of user style sheet file, if any \n" + " --user-style-string= User style rules specified as text \n" + " --header=: request header; repeatable; some can't be set\n" + " --method= Specifies the request method (default: get) \n" + " --body-string= Unencoded request body (default: none) \n" + " --body-base64= Base64-encoded request body (default: none) \n" + " --app-name= appName used in User-Agent; default is none \n" + " --app-version= appVers used in User-Agent; default is none \n" + " --user-agent= Override the User-Agent header Qt would set \n" + " --javascript= JavaScript execution (default: on) \n" + " --java= Java execution (default: unknown) \n" + " --plugins= Plugin execution (default: unknown) \n" + " --private-browsing= Private browsing (default: unknown) \n" + " --auto-load-images= Automatic image loading (default: on) \n" + " --js-can-open-windows= Script can open windows? (default: unknown) \n" + " --js-can-access-clipboard= Script clipboard privs (default: unknown)\n" +#if QT_VERSION >= 0x040500 + " --print-backgrounds= Backgrounds in PDF/PS output (default: off) \n" + " --zoom-factor= Page zoom factor (default: no zooming) \n" + " --zoom-text-only= Whether to zoom only the text (default: off) \n" + " --http-proxy= Address for HTTP proxy server (default: none)\n" +#endif +#if CUTYCAPT_SCRIPT + " --inject-script= JavaScript that will be injected into pages \n" + " --script-object= Property to hold state for injected script \n" + " --expect-alert= Try waiting for alert(string) before capture \n" + " --debug-print-alerts Prints out alert(...) strings for debugging. \n" +#endif +#if QT_VERSION >= 0x050000 + " --smooth Attempt to enable Qt's high-quality settings.\n" +#endif + " --insecure Ignore SSL/TLS certificate errors \n" + " -----------------------------------------------------------------------------\n" + " is svg,ps,pdf,itext,html,rtree,png,jpeg,mng,tiff,gif,bmp,ppm,xbm,xpm \n" + " -----------------------------------------------------------------------------\n" +#if CUTYCAPT_SCRIPT + " The `inject-script` option can be used to inject script code into loaded web \n" + " pages. The code is called whenever the `javaScriptWindowObjectCleared` signal\n" + " is received. When `script-object` is set, an object under the specified name \n" + " will be available to the script to maintain state across page loads. When the\n" + " `expect-alert` option is specified, the shot will be taken when a script in- \n" + " vokes alert(string) with the string if that happens before `max-wait`. These \n" + " options effectively allow you to remote control the browser and the web page.\n" + " This an experimental and easily abused and misused feature. Use with caution.\n" + " -----------------------------------------------------------------------------\n" +#endif + " http://cutycapt.sf.net - (c) 2003-2013 Bjoern Hoehrmann - bjoern@hoehrmann.de\n" + ""); +} + +int +main(int argc, char *argv[]) { + + int argHelp = 0; + int argDelay = 0; + int argSilent = 0; + int argInsecure = 0; + int argMinWidth = 800; + int argMinHeight = 600; + int argMaxWait = 90000; + int argVerbosity = 0; + int argSmooth = 0; + + const char* argUrl = NULL; + const char* argUserStyle = NULL; + const char* argUserStylePath = NULL; + const char* argUserStyleString = NULL; + const char* argIconDbPath = NULL; + const char* argInjectScript = NULL; + const char* argScriptObject = NULL; + QString argOut; + + CutyCapt::OutputFormat format = CutyCapt::OtherFormat; + + QApplication app(argc, argv, true); + CutyPage page; + + QNetworkAccessManager::Operation method = + QNetworkAccessManager::GetOperation; + QByteArray body; + QNetworkRequest req; + QNetworkAccessManager manager; + + // Parse command line parameters + for (int ax = 1; ax < argc; ++ax) { + size_t nlen; + + const char* s = argv[ax]; + const char* value; + + // boolean options + if (strcmp("--silent", s) == 0) { + argSilent = 1; + continue; + + } else if (strcmp("--help", s) == 0) { + argHelp = 1; + break; + + } else if (strcmp("--verbose", s) == 0) { + argVerbosity++; + continue; + + } else if (strcmp("--insecure", s) == 0) { + argInsecure = 1; + continue; + +#if QT_VERSION >= 0x050000 + } else if (strcmp("--smooth", s) == 0) { + argSmooth = 1; + continue; +#endif + +#if CUTYCAPT_SCRIPT + } else if (strcmp("--debug-print-alerts", s) == 0) { + page.setPrintAlerts(true); + continue; +#endif + } + + value = strchr(s, '='); + + if (value == NULL) { + // TODO: error + argHelp = 1; + break; + } + + nlen = value++ - s; + + // --name=value options + if (strncmp("--url", s, nlen) == 0) { + argUrl = value; + + } else if (strncmp("--min-width", s, nlen) == 0) { + // TODO: add error checking here? + argMinWidth = (unsigned int)atoi(value); + + } else if (strncmp("--min-height", s, nlen) == 0) { + // TODO: add error checking here? + argMinHeight = (unsigned int)atoi(value); + + } else if (strncmp("--delay", s, nlen) == 0) { + // TODO: see above + argDelay = (unsigned int)atoi(value); + + } else if (strncmp("--max-wait", s, nlen) == 0) { + // TODO: see above + argMaxWait = (unsigned int)atoi(value); + + } else if (strncmp("--out", s, nlen) == 0) { + argOut = value; + + if (format == CutyCapt::OtherFormat) + for (int ix = 0; CutyExtMap[ix].id != CutyCapt::OtherFormat; ++ix) + if (argOut.endsWith(CutyExtMap[ix].extension)) + format = CutyExtMap[ix].id; //, break; + + } else if (strncmp("--user-styles", s, nlen) == 0) { + // This option is provided for backwards-compatibility only + argUserStyle = value; + + } else if (strncmp("--user-style-path", s, nlen) == 0) { + argUserStylePath = value; + + } else if (strncmp("--user-style-string", s, nlen) == 0) { + argUserStyleString = value; + + } else if (strncmp("--icon-database-path", s, nlen) == 0) { + argIconDbPath = value; + + } else if (strncmp("--auto-load-images", s, nlen) == 0) { + page.setAttribute(QWebSettings::AutoLoadImages, value); + + } else if (strncmp("--javascript", s, nlen) == 0) { + page.setAttribute(QWebSettings::JavascriptEnabled, value); + + } else if (strncmp("--java", s, nlen) == 0) { + page.setAttribute(QWebSettings::JavaEnabled, value); + + } else if (strncmp("--plugins", s, nlen) == 0) { + page.setAttribute(QWebSettings::PluginsEnabled, value); + + } else if (strncmp("--private-browsing", s, nlen) == 0) { + page.setAttribute(QWebSettings::PrivateBrowsingEnabled, value); + + } else if (strncmp("--js-can-open-windows", s, nlen) == 0) { + page.setAttribute(QWebSettings::JavascriptCanOpenWindows, value); + + } else if (strncmp("--js-can-access-clipboard", s, nlen) == 0) { + page.setAttribute(QWebSettings::JavascriptCanAccessClipboard, value); + + } else if (strncmp("--developer-extras", s, nlen) == 0) { + page.setAttribute(QWebSettings::DeveloperExtrasEnabled, value); + + } else if (strncmp("--links-included-in-focus-chain", s, nlen) == 0) { + page.setAttribute(QWebSettings::LinksIncludedInFocusChain, value); + +#if QT_VERSION >= 0x040500 + } else if (strncmp("--print-backgrounds", s, nlen) == 0) { + page.setAttribute(QWebSettings::PrintElementBackgrounds, value); + + } else if (strncmp("--zoom-factor", s, nlen) == 0) { + page.mainFrame()->setZoomFactor(QString(value).toFloat()); + + } else if (strncmp("--zoom-text-only", s, nlen) == 0) { + page.setAttribute(QWebSettings::ZoomTextOnly, value); + + } else if (strncmp("--http-proxy", s, nlen) == 0) { + QUrl p = QUrl::fromEncoded(value); + QNetworkProxy proxy = QNetworkProxy(QNetworkProxy::HttpProxy, + p.host(), p.port(80), p.userName(), p.password()); + manager.setProxy(proxy); + page.setNetworkAccessManager(&manager); +#endif + +#if CUTYCAPT_SCRIPT + } else if (strncmp("--inject-script", s, nlen) == 0) { + argInjectScript = value; + + } else if (strncmp("--script-object", s, nlen) == 0) { + argScriptObject = value; + + } else if (strncmp("--expect-alert", s, nlen) == 0) { + page.setAlertString(value); +#endif + + } else if (strncmp("--app-name", s, nlen) == 0) { + app.setApplicationName(value); + + } else if (strncmp("--app-version", s, nlen) == 0) { + app.setApplicationVersion(value); + + } else if (strncmp("--body-base64", s, nlen) == 0) { + body = QByteArray::fromBase64(value); + + } else if (strncmp("--body-string", s, nlen) == 0) { + body = QByteArray(value); + + } else if (strncmp("--user-agent", s, nlen) == 0) { + page.setUserAgent(value); + + } else if (strncmp("--out-format", s, nlen) == 0) { + for (int ix = 0; CutyExtMap[ix].id != CutyCapt::OtherFormat; ++ix) + if (strcmp(value, CutyExtMap[ix].identifier) == 0) + format = CutyExtMap[ix].id; //, break; + + if (format == CutyCapt::OtherFormat) { + // TODO: error + argHelp = 1; + break; + } + + } else if (strncmp("--header", s, nlen) == 0) { + const char* hv = strchr(value, ':'); + + if (hv == NULL) { + // TODO: error + argHelp = 1; + break; + } + + req.setRawHeader(QByteArray(value, hv - value), hv + 1); + + } else if (strncmp("--method", s, nlen) == 0) { + if (strcmp("value", "get") == 0) + method = QNetworkAccessManager::GetOperation; + else if (strcmp("value", "put") == 0) + method = QNetworkAccessManager::PutOperation; + else if (strcmp("value", "post") == 0) + method = QNetworkAccessManager::PostOperation; + else if (strcmp("value", "head") == 0) + method = QNetworkAccessManager::HeadOperation; + else + (void)0; // TODO: ... + + } else { + // TODO: error + argHelp = 1; + } + } + + if (argUrl == NULL || argOut == NULL || argHelp) { + CaptHelp(); + return EXIT_FAILURE; + } + + // This used to use QUrl(argUrl) but that escapes %hh sequences + // even though it should not, as URLs can assumed to be escaped. + req.setUrl( QUrl::fromEncoded(argUrl) ); + + QString scriptProp(argScriptObject); + QString scriptCode; + + if (argInjectScript) { + QFile file(argInjectScript); + if (file.open(QIODevice::ReadOnly)) { + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + stream.setAutoDetectUnicode(true); + scriptCode = stream.readAll(); + file.close(); + } + } + + CutyCapt main(&page, argOut, argDelay, format, scriptProp, scriptCode, + !!argInsecure, !!argSmooth); + + app.connect(&page, + SIGNAL(loadFinished(bool)), + &main, + SLOT(DocumentComplete(bool))); + + app.connect(page.mainFrame(), + SIGNAL(initialLayoutCompleted()), + &main, + SLOT(InitialLayoutCompleted())); + + if (argMaxWait > 0) { + // TODO: Should this also register one for the application? + QTimer::singleShot(argMaxWait, &main, SLOT(Timeout())); + } + + if (argUserStyle != NULL) + // TODO: does this need any syntax checking? + page.settings()->setUserStyleSheetUrl( QUrl::fromEncoded(argUserStyle) ); + + if (argUserStylePath != NULL) { + page.settings()->setUserStyleSheetUrl( QUrl::fromLocalFile(argUserStylePath) ); + } + + if (argUserStyleString != NULL) { + QUrl data("data:text/css;charset=utf-8;base64," + + QByteArray(argUserStyleString).toBase64()); + page.settings()->setUserStyleSheetUrl( data ); + } + + if (argIconDbPath != NULL) + // TODO: does this need any syntax checking? + page.settings()->setIconDatabasePath(argUserStyle); + + // The documentation does not say, but it seems the mainFrame + // will never change, so we can set this here. Otherwise we'd + // have to set this in snapshot and trigger an update, which + // is not currently possible (Qt 4.4.0) as far as I can tell. + page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); + page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); + page.setViewportSize( QSize(argMinWidth, argMinHeight) ); + +#if CUTYCAPT_SCRIPT + // javaScriptWindowObjectCleared does not get called on the + // initial load unless some JavaScript has been executed. + page.mainFrame()->evaluateJavaScript(QString("")); + + app.connect(page.mainFrame(), + SIGNAL(javaScriptWindowObjectCleared()), + &main, + SLOT(JavaScriptWindowObjectCleared())); +#endif + + app.connect(page.networkAccessManager(), + SIGNAL(sslErrors(QNetworkReply*, QList)), + &main, + SLOT(handleSslErrors(QNetworkReply*, QList))); + + if (!body.isNull()) + page.mainFrame()->load(req, method, body); + else + page.mainFrame()->load(req, method); + + return app.exec(); +} diff -Nru cutycapt-0.0~svn6/CutyCapt.hpp cutycapt-0.0~svn10/CutyCapt.hpp --- cutycapt-0.0~svn6/CutyCapt.hpp 2010-06-08 18:12:11.000000000 +0000 +++ cutycapt-0.0~svn10/CutyCapt.hpp 2016-08-05 15:01:55.000000000 +0000 @@ -1,66 +1,75 @@ -#include - -class CutyCapt; -class CutyPage : public QWebPage { - Q_OBJECT - -public: - void setAttribute(QWebSettings::WebAttribute option, const QString& value); - void setUserAgent(const QString& userAgent); - void setAlertString(const QString& alertString); - void setPrintAlerts(bool printAlerts); - void setCutyCapt(CutyCapt* cutyCapt); - QString getAlertString(); - -protected: - QString chooseFile(QWebFrame *frame, const QString& suggestedFile); - void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID); - bool javaScriptPrompt(QWebFrame* frame, const QString& msg, const QString& defaultValue, QString* result); - void javaScriptAlert(QWebFrame* frame, const QString& msg); - bool javaScriptConfirm(QWebFrame* frame, const QString& msg); - QString userAgentForUrl(const QUrl& url) const; - QString mUserAgent; - QString mAlertString; - bool mPrintAlerts; - CutyCapt* mCutyCapt; -}; - -class CutyCapt : public QObject { - Q_OBJECT - -public: - - // TODO: This should really be elsewhere and be named differently - enum OutputFormat { SvgFormat, PdfFormat, PsFormat, InnerTextFormat, HtmlFormat, - RenderTreeFormat, PngFormat, JpegFormat, MngFormat, TiffFormat, GifFormat, - BmpFormat, PpmFormat, XbmFormat, XpmFormat, OtherFormat }; - - CutyCapt(CutyPage* page, - const QString& output, - int delay, - OutputFormat format, - const QString& scriptProp, - const QString& scriptCode); - -private slots: - void DocumentComplete(bool ok); - void InitialLayoutCompleted(); - void JavaScriptWindowObjectCleared(); - void Timeout(); - void Delayed(); - -private: - void TryDelayedRender(); - void saveSnapshot(); - bool mSawInitialLayout; - bool mSawDocumentComplete; - -protected: - QString mOutput; - int mDelay; - CutyPage* mPage; - OutputFormat mFormat; - QObject* mScriptObj; - QString mScriptProp; - QString mScriptCode; -}; +#include + +#if QT_VERSION >= 0x050000 +#include +#endif + +class CutyCapt; +class CutyPage : public QWebPage { + Q_OBJECT + +public: + void setAttribute(QWebSettings::WebAttribute option, const QString& value); + void setUserAgent(const QString& userAgent); + void setAlertString(const QString& alertString); + void setPrintAlerts(bool printAlerts); + void setCutyCapt(CutyCapt* cutyCapt); + QString getAlertString(); + +protected: + QString chooseFile(QWebFrame *frame, const QString& suggestedFile); + void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID); + bool javaScriptPrompt(QWebFrame* frame, const QString& msg, const QString& defaultValue, QString* result); + void javaScriptAlert(QWebFrame* frame, const QString& msg); + bool javaScriptConfirm(QWebFrame* frame, const QString& msg); + QString userAgentForUrl(const QUrl& url) const; + QString mUserAgent; + QString mAlertString; + bool mPrintAlerts; + CutyCapt* mCutyCapt; +}; + +class CutyCapt : public QObject { + Q_OBJECT + +public: + + // TODO: This should really be elsewhere and be named differently + enum OutputFormat { SvgFormat, PdfFormat, PsFormat, InnerTextFormat, HtmlFormat, + RenderTreeFormat, PngFormat, JpegFormat, MngFormat, TiffFormat, GifFormat, + BmpFormat, PpmFormat, XbmFormat, XpmFormat, OtherFormat }; + + CutyCapt(CutyPage* page, + const QString& output, + int delay, + OutputFormat format, + const QString& scriptProp, + const QString& scriptCode, + bool insecure, + bool smooth); + +private slots: + void DocumentComplete(bool ok); + void InitialLayoutCompleted(); + void JavaScriptWindowObjectCleared(); + void Timeout(); + void Delayed(); + void handleSslErrors(QNetworkReply* reply, QList errors); + +private: + void TryDelayedRender(); + void saveSnapshot(); + bool mSawInitialLayout; + bool mSawDocumentComplete; + +protected: + QString mOutput; + int mDelay; + CutyPage* mPage; + OutputFormat mFormat; + QObject* mScriptObj; + QString mScriptProp; + QString mScriptCode; + bool mInsecure; + bool mSmooth; +}; diff -Nru cutycapt-0.0~svn6/CutyCapt.pro cutycapt-0.0~svn10/CutyCapt.pro --- cutycapt-0.0~svn6/CutyCapt.pro 2008-06-11 06:01:28.000000000 +0000 +++ cutycapt-0.0~svn10/CutyCapt.pro 2016-08-05 15:01:55.000000000 +0000 @@ -1,10 +1,14 @@ -QT += webkit svg network -SOURCES = CutyCapt.cpp -HEADERS = CutyCapt.hpp -CONFIG += qt console - -contains(CONFIG, static): { - QTPLUGIN += qjpeg qgif qsvg qmng qico qtiff - DEFINES += STATIC_PLUGINS -} - +QT += webkit svg network +SOURCES = CutyCapt.cpp +HEADERS = CutyCapt.hpp +CONFIG += qt console + +greaterThan(QT_MAJOR_VERSION, 4): { + QT += webkitwidgets +} + +contains(CONFIG, static): { + QTPLUGIN += qjpeg qgif qsvg qmng qico qtiff + DEFINES += STATIC_PLUGINS +} + diff -Nru cutycapt-0.0~svn6/debian/changelog cutycapt-0.0~svn10/debian/changelog --- cutycapt-0.0~svn6/debian/changelog 2014-09-09 20:33:23.000000000 +0000 +++ cutycapt-0.0~svn10/debian/changelog 2016-08-05 18:36:58.000000000 +0000 @@ -1,3 +1,21 @@ +cutycapt (0.0~svn10-0.1) unstable; urgency=medium + + * Non-maintainer upload. + * Merged lastest upstream svn version. (Closes: #652969, #784459) + * debian/control: + - Bump debhelper version to 9. + - Change B-D to qt5. + - Bump Standards-Version to 3.9.8. + - Use secured links for VCS. + * debian/compat: Bump to 9. + * debian/rules: + - Set QT_SELECT to 5. + - Add perl oneliner to convert files to unix format. + - Enable hardening. + * debian/patches: Refresh exists. + + -- Mateusz Łukasik Fri, 05 Aug 2016 20:36:58 +0200 + cutycapt (0.0~svn6-3.1) unstable; urgency=medium * Non-maintainer upload. diff -Nru cutycapt-0.0~svn6/debian/compat cutycapt-0.0~svn10/debian/compat --- cutycapt-0.0~svn6/debian/compat 2014-09-09 20:28:19.000000000 +0000 +++ cutycapt-0.0~svn10/debian/compat 2016-08-05 14:46:11.000000000 +0000 @@ -1 +1 @@ -7 +9 diff -Nru cutycapt-0.0~svn6/debian/control cutycapt-0.0~svn10/debian/control --- cutycapt-0.0~svn6/debian/control 2014-09-09 20:28:19.000000000 +0000 +++ cutycapt-0.0~svn10/debian/control 2016-08-05 18:14:18.000000000 +0000 @@ -2,21 +2,16 @@ Section: web Priority: optional Maintainer: David Paleino -Build-Depends: - debhelper (>= 7.4.12~) - , libqt4-dev (>= 4.4.0) - , libqtwebkit-dev - , qt4-qmake -Standards-Version: 3.9.1 +Build-Depends: debhelper (>= 9), qtbase5-dev, libqt5webkit5-dev, qt5-qmake, + libqt5svg5-dev +Standards-Version: 3.9.8 Homepage: http://cutycapt.sourceforge.net/ -Vcs-Git: git://git.debian.org/collab-maint/cutycapt.git -Vcs-Browser: http://git.debian.org/?p=collab-maint/cutycapt.git;a=summary +Vcs-Git: https://anonscm.debian.org/git/collab-maint/cutycapt.git +Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/cutycapt.git Package: cutycapt Architecture: any -Depends: - ${shlibs:Depends} - , ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends} Suggests: xvfb Description: utility to capture WebKit's rendering of a web page CutyCapt is a small cross-platform command-line utility to capture WebKit's diff -Nru cutycapt-0.0~svn6/debian/patches/01-assume_http_as_default.patch cutycapt-0.0~svn10/debian/patches/01-assume_http_as_default.patch --- cutycapt-0.0~svn6/debian/patches/01-assume_http_as_default.patch 2014-09-09 20:32:26.000000000 +0000 +++ cutycapt-0.0~svn10/debian/patches/01-assume_http_as_default.patch 2016-08-05 15:09:21.000000000 +0000 @@ -3,59 +3,55 @@ Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=611900 Forwarded: no ---- - CutyCapt.cpp | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - --- a/CutyCapt.cpp +++ b/CutyCapt.cpp -@@ -363,7 +363,7 @@ - int argMaxWait = 90000; - int argVerbosity = 0; - -- const char* argUrl = NULL; -+ QByteArray argUrl = NULL; - const char* argUserStyle = NULL; - const char* argUserStylePath = NULL; - const char* argUserStyleString = NULL; -@@ -371,6 +371,7 @@ - const char* argInjectScript = NULL; - const char* argScriptObject = NULL; - QString argOut; -+ QUrl parsedUrl; - - CutyCapt::OutputFormat format = CutyCapt::OtherFormat; - -@@ -422,7 +423,7 @@ - - // --name=value options - if (strncmp("--url", s, nlen) == 0) { -- argUrl = value; -+ argUrl = QByteArray(value); - - } else if (strncmp("--min-width", s, nlen) == 0) { - // TODO: add error checking here? -@@ -572,14 +573,21 @@ - } - } - -- if (argUrl == NULL || argOut == NULL || argHelp) { -+ if (argUrl.isNull() || argOut == NULL || argHelp) { - CaptHelp(); - return EXIT_FAILURE; - } - -+ // Check if a scheme is present, if not, assume http. -+ parsedUrl = QUrl::fromEncoded(argUrl); -+ if (parsedUrl.scheme() == "") { -+ argUrl = "http://" + argUrl; -+ parsedUrl = QUrl::fromEncoded(argUrl); -+ } -+ - // This used to use QUrl(argUrl) but that escapes %hh sequences - // even though it should not, as URLs can assumed to be escaped. -- req.setUrl( QUrl::fromEncoded(argUrl) ); -+ req.setUrl(parsedUrl); - - QString scriptProp(argScriptObject); - QString scriptCode; +@@ -409,7 +409,7 @@ main(int argc, char *argv[]) { + int argVerbosity = 0; + int argSmooth = 0; + +- const char* argUrl = NULL; ++ QByteArray argUrl = NULL; + const char* argUserStyle = NULL; + const char* argUserStylePath = NULL; + const char* argUserStyleString = NULL; +@@ -417,6 +417,7 @@ main(int argc, char *argv[]) { + const char* argInjectScript = NULL; + const char* argScriptObject = NULL; + QString argOut; ++ QUrl parsedUrl; + + CutyCapt::OutputFormat format = CutyCapt::OtherFormat; + +@@ -478,7 +479,7 @@ main(int argc, char *argv[]) { + + // --name=value options + if (strncmp("--url", s, nlen) == 0) { +- argUrl = value; ++ argUrl = QByteArray(value); + + } else if (strncmp("--min-width", s, nlen) == 0) { + // TODO: add error checking here? +@@ -628,14 +629,21 @@ main(int argc, char *argv[]) { + } + } + +- if (argUrl == NULL || argOut == NULL || argHelp) { ++ if (argUrl.isNull() || argOut == NULL || argHelp) { + CaptHelp(); + return EXIT_FAILURE; + } + ++ // Check if a scheme is present, if not, assume http. ++ parsedUrl = QUrl::fromEncoded(argUrl); ++ if (parsedUrl.scheme() == "") { ++ argUrl = "http://" + argUrl; ++ parsedUrl = QUrl::fromEncoded(argUrl); ++ } ++ + // This used to use QUrl(argUrl) but that escapes %hh sequences + // even though it should not, as URLs can assumed to be escaped. +- req.setUrl( QUrl::fromEncoded(argUrl) ); ++ req.setUrl(parsedUrl); + + QString scriptProp(argScriptObject); + QString scriptCode; diff -Nru cutycapt-0.0~svn6/debian/patches/02-add-missing-include.patch cutycapt-0.0~svn10/debian/patches/02-add-missing-include.patch --- cutycapt-0.0~svn6/debian/patches/02-add-missing-include.patch 2014-09-09 20:42:02.000000000 +0000 +++ cutycapt-0.0~svn10/debian/patches/02-add-missing-include.patch 2016-08-05 17:46:32.000000000 +0000 @@ -1,14 +1,47 @@ Description: Add missing #include to fix FTBFS. Forwarded: no Author: Julián Moreno Patiño -Last-Update: 2014-09-09 +Last-Update: 2016-08-05 + --- a/CutyCapt.cpp +++ b/CutyCapt.cpp -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - #include "CutyCapt.hpp" - +@@ -27,15 +27,13 @@ + #include + #include + #include +- +-#if QT_VERSION < 0x050000 + #include +-#endif +- + #include + #include ++#include + #include + #include ++#include + #include "CutyCapt.hpp" + + #if QT_VERSION >= 0x040600 && 0 + +--- a/CutyCapt.pro ++++ b/CutyCapt.pro +@@ -4,7 +4,7 @@ HEADERS = CutyCapt.hpp + CONFIG += qt console + + greaterThan(QT_MAJOR_VERSION, 4): { +- QT += webkitwidgets ++ QT += webkitwidgets printsupport + } + + contains(CONFIG, static): { + +--- a/CutyCapt.hpp ++++ b/CutyCapt.hpp +@@ -1,4 +1,6 @@ + #include ++#include ++#include + + #if QT_VERSION >= 0x050000 + #include diff -Nru cutycapt-0.0~svn6/debian/rules cutycapt-0.0~svn10/debian/rules --- cutycapt-0.0~svn6/debian/rules 2014-09-09 20:28:19.000000000 +0000 +++ cutycapt-0.0~svn10/debian/rules 2016-08-05 18:15:20.000000000 +0000 @@ -4,6 +4,9 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 +export QT_SELECT=5 +export DEB_BUILD_MAINT_OPTIONS = hardening=+all + CURVER=$(shell dpkg-parsechangelog | grep ^Version | cut -d\ -f2 | cut -d- -f1) SVNREV=$(shell echo $(CURVER) | awk -F'svn' '{print $$2}' ) @@ -16,6 +19,7 @@ get-orig-source: svn checkout -r $(SVNREV) https://cutycapt.svn.sourceforge.net/svnroot/cutycapt/CutyCapt cutycapt find cutycapt -name ".svn" | xargs -r rm -rf + perl -pi -e 's/\r\n/\n/g' cutycapt/CutyCapt.* tar cf cutycapt_$(CURVER).orig.tar cutycapt/ gzip -9 cutycapt_$(CURVER).orig.tar rm -rf cutycapt/