Skip to content

Instantly share code, notes, and snippets.

@bradley219
Created April 8, 2014 02:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradley219/10084028 to your computer and use it in GitHub Desktop.
Save bradley219/10084028 to your computer and use it in GitHub Desktop.
diff -rupN wkhtmltopdf-0.11.0_rc1/common.pri wkhtmltopdf-0.11.0_rc1-patched/common.pri
--- wkhtmltopdf-0.11.0_rc1/common.pri 2011-10-02 10:21:02.000000000 -0700
+++ wkhtmltopdf-0.11.0_rc1-patched/common.pri 2012-09-28 09:45:49.772000005 -0700
@@ -17,7 +17,7 @@
unix {
TEMP = $$[QT_INSTALL_LIBS] libQtGui.prl
- PRL = $$[QT_INSTALL_LIBS] QtGui.framework/QtGui.prl
+ PRL = $$[QT_INSTALL_LIBS] libQtGui.prl
include($$join(TEMP, "/"))
include($$join(PRL, "/"))
}
diff -rupN wkhtmltopdf-0.11.0_rc1/common.pri.rej wkhtmltopdf-0.11.0_rc1-patched/common.pri.rej
--- wkhtmltopdf-0.11.0_rc1/common.pri.rej 1969-12-31 16:00:00.000000000 -0800
+++ wkhtmltopdf-0.11.0_rc1-patched/common.pri.rej 2012-09-28 09:45:49.780000005 -0700
@@ -0,0 +1,11 @@
+--- common.pri 2011-10-02 10:21:02.000000000 -0700
++++ common.pri 2012-09-26 10:22:30.764000002 -0700
+@@ -17,7 +17,7 @@
+
+ unix {
+ TEMP = $$[QT_INSTALL_LIBS] libQtGui.prl
+- PRL = $$[QT_INSTALL_LIBS] QtGui.framework/QtGui.prl
++ PRL = $$[QT_INSTALL_LIBS] libQtGui.prl
+ include($$join(TEMP, "/"))
+ include($$join(PRL, "/"))
+ }
diff -rupN wkhtmltopdf-0.11.0_rc1/include/wkhtmltox/loadsettings.hh wkhtmltopdf-0.11.0_rc1-patched/include/wkhtmltox/loadsettings.hh
--- wkhtmltopdf-0.11.0_rc1/include/wkhtmltox/loadsettings.hh 2011-10-02 10:21:02.000000000 -0700
+++ wkhtmltopdf-0.11.0_rc1-patched/include/wkhtmltox/loadsettings.hh 2012-09-28 09:45:49.776000005 -0700
@@ -118,6 +118,8 @@ struct DLL_PUBLIC LoadPage {
QString checkboxCheckedSvg;
QString radiobuttonSvg;
QString radiobuttonCheckedSvg;
+
+ QList< QString > basePaths;
};
DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);
diff -rupN wkhtmltopdf-0.11.0_rc1/include/wkhtmltox/loadsettings.hh.rej wkhtmltopdf-0.11.0_rc1-patched/include/wkhtmltox/loadsettings.hh.rej
--- wkhtmltopdf-0.11.0_rc1/include/wkhtmltox/loadsettings.hh.rej 1969-12-31 16:00:00.000000000 -0800
+++ wkhtmltopdf-0.11.0_rc1-patched/include/wkhtmltox/loadsettings.hh.rej 2012-09-28 09:45:49.776000005 -0700
@@ -0,0 +1,11 @@
+--- include/wkhtmltox/loadsettings.hh 2011-10-02 10:21:02.000000000 -0700
++++ include/wkhtmltox/loadsettings.hh 2012-09-19 13:25:21.000000000 -0700
+@@ -118,6 +118,8 @@
+ QString checkboxCheckedSvg;
+ QString radiobuttonSvg;
+ QString radiobuttonCheckedSvg;
++
++ QList< QString > basePaths;
+ };
+
+ DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/lib.pri wkhtmltopdf-0.11.0_rc1-patched/src/lib/lib.pri
--- wkhtmltopdf-0.11.0_rc1/src/lib/lib.pri 2011-10-02 10:21:02.000000000 -0700
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/lib.pri 2012-09-28 09:45:49.784000004 -0700
@@ -18,13 +18,13 @@
DEFINES += BUILDING_DLL
#Shared
-PUBLIC_HEADERS += ../lib/converter.hh ../lib/multipageloader.hh ../lib/dllbegin.inc
+PUBLIC_HEADERS += ../lib/converter.hh ../lib/multipageloader.hh ../lib/dllbegin.inc ../lib/synchttp.h
PUBLIC_HEADERS += ../lib/dllend.inc ../lib/loadsettings.hh ../lib/websettings.hh
PUBLIC_HEADERS += ../lib/utilities.hh
HEADERS += ../lib/multipageloader_p.hh ../lib/converter_p.hh
SOURCES += ../lib/loadsettings.cc ../lib/multipageloader.cc ../lib/tempfile.cc \
../lib/converter.cc ../lib/websettings.cc \
- ../lib/reflect.cc ../lib/utilities.cc
+ ../lib/reflect.cc ../lib/utilities.cc ../lib/synchttp.cc
#Pdf
PUBLIC_HEADERS += ../lib/pdfconverter.hh ../lib/pdfsettings.hh
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/lib.pri.rej wkhtmltopdf-0.11.0_rc1-patched/src/lib/lib.pri.rej
--- wkhtmltopdf-0.11.0_rc1/src/lib/lib.pri.rej 1969-12-31 16:00:00.000000000 -0800
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/lib.pri.rej 2012-09-28 09:45:49.788000003 -0700
@@ -0,0 +1,18 @@
+--- src/lib/lib.pri 2011-10-02 10:21:02.000000000 -0700
++++ src/lib/lib.pri 2012-09-19 13:25:21.000000000 -0700
+@@ -18,13 +18,13 @@
+ DEFINES += BUILDING_DLL
+
+ #Shared
+-PUBLIC_HEADERS += ../lib/converter.hh ../lib/multipageloader.hh ../lib/dllbegin.inc
++PUBLIC_HEADERS += ../lib/converter.hh ../lib/multipageloader.hh ../lib/dllbegin.inc ../lib/synchttp.h
+ PUBLIC_HEADERS += ../lib/dllend.inc ../lib/loadsettings.hh ../lib/websettings.hh
+ PUBLIC_HEADERS += ../lib/utilities.hh
+ HEADERS += ../lib/multipageloader_p.hh ../lib/converter_p.hh
+ SOURCES += ../lib/loadsettings.cc ../lib/multipageloader.cc ../lib/tempfile.cc \
+ ../lib/converter.cc ../lib/websettings.cc \
+- ../lib/reflect.cc ../lib/utilities.cc
++ ../lib/reflect.cc ../lib/utilities.cc ../lib/synchttp.cc
+
+ #Pdf
+ PUBLIC_HEADERS += ../lib/pdfconverter.hh ../lib/pdfsettings.hh
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/loadsettings.hh wkhtmltopdf-0.11.0_rc1-patched/src/lib/loadsettings.hh
--- wkhtmltopdf-0.11.0_rc1/src/lib/loadsettings.hh 2011-10-02 10:21:02.000000000 -0700
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/loadsettings.hh 2012-09-28 09:45:49.788000003 -0700
@@ -121,6 +121,9 @@ struct DLL_PUBLIC LoadPage {
QString checkboxCheckedSvg;
QString radiobuttonSvg;
QString radiobuttonCheckedSvg;
+
+ //! Base path list for resolving relative URLs
+ QList< QString > basePaths;
};
DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/loadsettings.hh.rej wkhtmltopdf-0.11.0_rc1-patched/src/lib/loadsettings.hh.rej
--- wkhtmltopdf-0.11.0_rc1/src/lib/loadsettings.hh.rej 1969-12-31 16:00:00.000000000 -0800
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/loadsettings.hh.rej 2012-09-28 09:45:49.788000003 -0700
@@ -0,0 +1,12 @@
+--- src/lib/loadsettings.hh 2011-10-02 10:21:02.000000000 -0700
++++ src/lib/loadsettings.hh 2012-09-19 13:25:21.000000000 -0700
+@@ -121,6 +121,9 @@
+ QString checkboxCheckedSvg;
+ QString radiobuttonSvg;
+ QString radiobuttonCheckedSvg;
++
++ //! Base path list for resolving relative URLs
++ QList< QString > basePaths;
+ };
+
+ DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/multipageloader.cc wkhtmltopdf-0.11.0_rc1-patched/src/lib/multipageloader.cc
--- wkhtmltopdf-0.11.0_rc1/src/lib/multipageloader.cc 2011-10-02 10:21:02.000000000 -0700
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/multipageloader.cc 2012-09-28 09:47:37.444000006 -0700
@@ -30,6 +30,12 @@
#include <QNetworkCookie>
#include <QTimer>
#include <QUuid>
+#include <QWebPage>
+#include <QWebFrame>
+#include <QWebElementCollection>
+
+#include "synchttp.h"
+
namespace wkhtmltopdf {
/*!
@@ -54,6 +60,7 @@ void MyNetworkAccessManager::allow(QStri
}
QNetworkReply * MyNetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData) {
+
if (req.url().scheme() == "file" && settings.blockLocalFileAccess) {
bool ok=false;
QString path = QFileInfo(req.url().toLocalFile()).canonicalFilePath();
@@ -73,6 +80,53 @@ QNetworkReply * MyNetworkAccessManager::
return QNetworkAccessManager::createRequest(op, r2, outgoingData);
}
}
+ else if( req.url().scheme() == "file" ) {
+
+ // Remove query string from the end of a path, including the question mark
+ QString fname(req.url().toLocalFile().toAscii());
+ int idx = -1;
+ if( ( idx = fname.indexOf("?") ) >= 0 )
+ {
+ fname = fname.left(idx);
+ }
+
+ // search for file
+ bool ok = false;
+ QFile fn(fname.toAscii());
+ if( fn.exists() )
+ {
+ ok = true;
+ fname = QString(fn.fileName());
+ }
+ else
+ {
+ if(!settings.basePaths.isEmpty()) {
+ foreach(const QString &bp, settings.basePaths) {
+ QString c(bp);
+ c = c.append("/").append(req.url().toLocalFile().toAscii());
+ QFile fn(c);
+ if (fn.exists()) {
+ ok = true;
+ fname = QString(c);
+ break;
+ }
+ }
+ }
+ if( ok )
+ {
+ QNetworkRequest r4 = req;
+ if (settings.repeatCustomHeaders) {
+ typedef QPair<QString, QString> HT;
+ foreach (const HT & j, settings.customHeaders)
+ r4.setRawHeader(j.first.toAscii(), j.second.toAscii());
+ }
+ QUrl u(fname);
+ u.setScheme("file");
+ r4.setUrl(u);
+ return QNetworkAccessManager::createRequest(op, r4, outgoingData);
+ }
+ }
+ }
QNetworkRequest r3 = req;
if (settings.repeatCustomHeaders) {
typedef QPair<QString, QString> HT;
@@ -212,6 +266,100 @@ void ResourceObject::loadFinished(bool o
warning(QString("Failed loading page ") + url.toString() + " (ignored)");
}
+ SyncHTTP *http = new SyncHTTP(this);
+
+ QWebElementCollection coll = webPage.mainFrame()->findAllElements("img");
+ for (int i = 0; i < coll.count(); i++) { // loop collection
+ QWebElement elem = coll.at(i);
+ if (elem.hasAttribute("src")) {
+ bool ok = false;
+ if (!elem.attribute("src").startsWith("http")) { // doesn't start with http
+
+ // Remove query string from the end of a path, including the question mark
+ QString srcString(elem.attribute("src"));
+ int idx = -1;
+ if( ( idx = srcString.indexOf("?") ) >= 0 )
+ {
+ srcString = srcString.left(idx);
+ elem.setAttribute("src", srcString.toAscii().data());
+ }
+
+ QString *fname = NULL;
+ QFile fn(elem.attribute("src"));
+ if (fn.exists()) {
+ ok = true;
+ fname = new QString(elem.attribute("src"));
+ }
+
+ if (!ok && !settings.basePaths.isEmpty()) {
+ foreach(const QString &bp, settings.basePaths) {
+ QString c(bp);
+ c = c.append("/").append(elem.attribute("src"));
+
+ QFile fn(c);
+ if (fn.exists()) {
+ ok = true;
+ fname = new QString(c);
+ break;
+ }
+ }
+ }
+ if( ok )
+ {
+ elem.setAttribute("src", fname->toAscii().data() );
+ continue;
+ }
+
+
+ if (!settings.basePaths.isEmpty()) {
+ foreach(const QString &bp, settings.basePaths) {
+ QString c(bp);
+ c = c.append("/");
+
+ QUrl url(c.append(elem.attribute("src"))); // create appended url
+ int port = url.port(80);
+ QHttp::ConnectionMode mode = QHttp::ConnectionModeHttp;
+ if (url.toString().toLower().startsWith("https")) {
+ port = url.port(443);
+ mode = QHttp::ConnectionModeHttps;
+ }
+
+ http->setHost(url.host(), mode, port);
+ http->setUser(url.userName(), url.password());
+ http->syncGet(url.encodedPath());
+ if (http->lastResponse().statusCode() == 200) {
+ elem.setAttribute("src", url.toString());
+ ok = true;
+ break;
+ }
+ }
+ }
+ } else { // does start with http
+ QUrl url(elem.attribute("src"));
+ int port = url.port(80);
+ QHttp::ConnectionMode mode = QHttp::ConnectionModeHttp;
+ if (url.toString().toLower().startsWith("https")) {
+ port = url.port(443);
+ mode = QHttp::ConnectionModeHttps;
+ }
+ http->setHost(url.host(), mode, port);
+ http->setUser(url.userName(), url.password());
+ http->syncGet(url.encodedPath());
+ if (http->lastResponse().statusCode() == 200) {
+ ok = true;
+ }
+ }
+ if (!ok) {
+ elem.removeAttribute("src");
+ elem.setAttribute("style", "display:none;");
+ }
+ }
+ }
+
+ delete http;
+
+ //printf("HTML %s\n", webPage.mainFrame()->toHtml().toAscii().data());
+
// Evaluate extra user supplied javascript
foreach (const QString & str, settings.runScript)
webPage.mainFrame()->evaluateJavaScript(str);
@@ -446,7 +594,9 @@ void MultiPageLoaderPrivate::load() {
loading=0;
for (int i=0; i < resources.size(); ++i)
+ {
resources[i]->load();
+ }
if (resources.size() == 0) loadDone();
}
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/synchttp.cc wkhtmltopdf-0.11.0_rc1-patched/src/lib/synchttp.cc
--- wkhtmltopdf-0.11.0_rc1/src/lib/synchttp.cc 1969-12-31 16:00:00.000000000 -0800
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/synchttp.cc 2012-09-28 09:45:49.784000004 -0700
@@ -0,0 +1,44 @@
+#ifdef __WKHTMLTOX_UNDEF_QT_DLL__
+#ifdef QT_DLL
+#undef QT_DLL
+#endif
+#endif
+
+#include "synchttp.h"
+
+namespace wkhtmltopdf {
+
+bool SyncHTTP::syncGet ( const QString & path, QIODevice * to)
+{
+ ///connect the requestFinished signal to our finished slot
+ connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool)));
+ /// start the request and store the requestID
+ requestID = get(path, to );
+ /// block until the request is finished
+ loop.exec();
+ /// return the request status
+ return status;
+}
+
+/// send POST request and wait until finished
+bool SyncHTTP::syncPost ( const QString & path, QIODevice * data, QIODevice * to)
+{
+ ///connect the requestFinished signal to our finished slot
+ connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool)));
+ /// start the request and store the requestID
+ requestID = post(path, data , to );
+ /// block until the request is finished
+ loop.exec();
+ /// return the request status
+ return status;
+}
+
+bool SyncHTTP::syncPost ( const QString & path, const QByteArray& data, QIODevice * to)
+{
+ /// create io device from QByteArray
+ QBuffer buffer;
+ buffer.setData(data);
+ return syncPost(path,&buffer,to);
+}
+
+};
diff -rupN wkhtmltopdf-0.11.0_rc1/src/lib/synchttp.h wkhtmltopdf-0.11.0_rc1-patched/src/lib/synchttp.h
--- wkhtmltopdf-0.11.0_rc1/src/lib/synchttp.h 1969-12-31 16:00:00.000000000 -0800
+++ wkhtmltopdf-0.11.0_rc1-patched/src/lib/synchttp.h 2012-09-28 09:45:49.792000003 -0700
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Iulian M *
+ * eti@erata.net *
+ ***************************************************************************/
+#ifndef ETKSYNCHTTP_H
+#define ETKSYNCHTTP_H
+
+#include <QHttp>
+#include <QEventLoop>
+#include <QBuffer>
+
+/**
+ * Provide a synchronous api over QHttp
+ * Uses a QEventLoop to block until the request is completed
+ * @author Iulian M <eti@erata.net>
+*/
+namespace wkhtmltopdf {
+class SyncHTTP: public QHttp
+{
+ Q_OBJECT
+ public:
+ /// structors
+ SyncHTTP( QObject * parent = 0 )
+ :QHttp(parent),requestID(-1),status(false){}
+
+ SyncHTTP( const QString & hostName, quint16 port = 80, QObject * parent = 0 )
+ :QHttp(hostName,port,parent),requestID(-1),status(false){}
+
+ virtual ~SyncHTTP(){}
+
+ /// send GET request and wait until finished
+ bool syncGet ( const QString & path, QIODevice * to = 0 );
+ /*
+ bool syncGet ( const QString & path, QIODevice * to = 0 )
+ {
+ ///connect the requestFinished signal to our finished slot
+ connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool)));
+ /// start the request and store the requestID
+ requestID = get(path, to );
+ /// block until the request is finished
+ loop.exec();
+ /// return the request status
+ return status;
+ }
+ */
+
+ /// send POST request and wait until finished
+ bool syncPost ( const QString & path, QIODevice * data, QIODevice * to = 0 );
+ /*
+ bool syncPost ( const QString & path, QIODevice * data, QIODevice * to = 0 )
+ {
+ ///connect the requestFinished signal to our finished slot
+ connect(this,SIGNAL(requestFinished(int,bool)),SLOT(finished(int,bool)));
+ /// start the request and store the requestID
+ requestID = post(path, data , to );
+ /// block until the request is finished
+ loop.exec();
+ /// return the request status
+ return status;
+ }
+ */
+
+ bool syncPost ( const QString & path, const QByteArray& data, QIODevice * to = 0 );
+ /*
+ bool syncPost ( const QString & path, const QByteArray& data, QIODevice * to = 0 )
+ {
+ /// create io device from QByteArray
+ QBuffer buffer;
+ buffer.setData(data);
+ return syncPost(path,&buffer,to);
+ }
+ */
+
+ protected slots:
+ virtual void finished(int idx, bool err)
+ {
+ /// check to see if it's the request we made
+ if(idx!=requestID)
+ return;
+ /// set status of the request
+ status = !err;
+ /// end the loop
+ loop.exit();
+ }
+
+ private:
+ /// id of current request
+ int requestID;
+ /// error status of current request
+ bool status;
+ /// event loop used to block until request finished
+ QEventLoop loop;
+};
+};
+
+#endif
diff -rupN wkhtmltopdf-0.11.0_rc1/src/shared/commonarguments.cc wkhtmltopdf-0.11.0_rc1-patched/src/shared/commonarguments.cc
--- wkhtmltopdf-0.11.0_rc1/src/shared/commonarguments.cc 2011-10-02 10:21:02.000000000 -0700
+++ wkhtmltopdf-0.11.0_rc1-patched/src/shared/commonarguments.cc 2012-09-28 09:45:49.796000004 -0700
@@ -219,6 +219,8 @@ void CommandLineParserBase::addPageLoadA
addarg("enable-local-file-access", 0, "Allowed conversion of a local file to read in other local files.", new ConstSetter<bool>(s.blockLocalFileAccess, false));
addarg("allow", 0, "Allow the file or files from the specified folder to be loaded (repeatable)", new StringListSetter(s.allowed,"path"));
+ addarg("basepath", 0, "Add HTML Path to search for relative links", new StringListSetter(s.basePaths,"value"));
+
addarg("debug-javascript", 0,"Show javascript debugging output", new ConstSetter<bool>(s.debugJavascript, true));
addarg("no-debug-javascript", 0,"Do not show javascript debugging output", new ConstSetter<bool>(s.debugJavascript, false));
#if QT_VERSION >= 0x040600
@bradley219
Copy link
Author

https://code.google.com/p/wkhtmltopdf/issues/detail?id=353#c14

Patch built on top of jlama's most recent patch, which improves upon the basepath functionality for implementations using local image files. In particular, it tries removing the query string from the end of the path in order to try to find the local file, and applies the basepath-based file search to files specified in locations other than the src attribute of tags. Has been tested with and successfully loads images specified by the html background attribute (i.e. <td background="path/to/image" ... >) and background images specified within CSS (i.e. background: url(path/to/image)), and probably will work for images specified by other standard means as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment