diff --git a/.travis.yml b/.travis.yml index e1a639ac5..3664b5a0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ script: sed -i 's/-W3/-w/g' qt/mkspecs/win32-msvc2015/qmake.conf && \ C:/Python27/python ../packaging/build vagrant msvc2015-win64 --version - - $PWD; elif [[ $TARGET == "custom-qt4-macos" ]]; then - sudo -H pip install -q conan --ignore-installed six && sudo gem install fpm --no-ri --no-rdoc && \ + brew install conan && sudo -H pip install pyyaml --ignore-installed six && sudo gem install fpm --no-ri --no-rdoc && \ sudo xcode-select --switch /Library/Developer/CommandLineTools && \ MACOSX_DEPLOYMENT_TARGET=10.7 ../packaging/build vagrant macos-cocoa --clean --version - - $PWD; fi diff --git a/src/lib/pdfconverter.cc b/src/lib/pdfconverter.cc index c3c86a57b..277e74fb8 100644 --- a/src/lib/pdfconverter.cc +++ b/src/lib/pdfconverter.cc @@ -39,6 +39,7 @@ #include #endif +#include "utilities.hh" #include "dllbegin.inc" using namespace wkhtmltopdf; using namespace wkhtmltopdf::settings; @@ -560,6 +561,11 @@ void PdfConverterPrivate::findLinks(QWebFrame * frame, QVectorbaseUrl().resolved(href); QString key = QUrl::fromPercentEncoding(href.toString(QUrl::RemoveFragment).toLocal8Bit()); + QString decodedFragement = QUrl::fromPercentEncoding(href.fragment().toLocal8Bit()); + + QString escapedFragement = escapeCSS(href.fragment()); + QString escapedDecodedFragement = escapeCSS(decodedFragement); + if (urlToPageObj.contains(key)) { if (ulocal) { PageObject * p = urlToPageObj[key]; @@ -567,11 +573,13 @@ void PdfConverterPrivate::findLinks(QWebFrame * frame, QVectorpage->mainFrame()->findFirstElement("body"); else { - e = p->page->mainFrame()->findFirstElement("a[name=\""+href.fragment()+"\"]"); + e = p->page->mainFrame()->findFirstElement("#"+escapedFragement); + if (e.isNull()) + e = p->page->mainFrame()->findFirstElement("a[name=\""+escapedFragement+"\"]"); if (e.isNull()) - e = p->page->mainFrame()->findFirstElement("*[id=\""+href.fragment()+"\"]"); + e = p->page->mainFrame()->findFirstElement("#"+escapedDecodedFragement); if (e.isNull()) - e = p->page->mainFrame()->findFirstElement("*[name=\""+href.fragment()+"\"]"); + e = p->page->mainFrame()->findFirstElement("a[name=\""+escapedDecodedFragement+"\"]"); } if (!e.isNull()) { p->anchors[href.toString()] = e; diff --git a/src/lib/utilities.cc b/src/lib/utilities.cc index 14c1cc10e..2ffeb7ebb 100644 --- a/src/lib/utilities.cc +++ b/src/lib/utilities.cc @@ -25,6 +25,9 @@ #include #include +#define CSS_ESCAPE_CHARACTER(character) (QString("\\") + character) +#define CSS_ESCAPE_UNICODE_AS_CODEPOINT(unicode) QString("\\%1").arg(unicode, 0, 16) + void loadSvg(QSvgRenderer * & ptr, const QString & path, const char * def, int w, int h) { delete ptr; ptr = 0; @@ -179,6 +182,48 @@ int handleError(bool success, int errorCode) { return success?EXIT_SUCCESS:EXIT_FAILURE; } +// Escape a CSS selector as per CSS.escape() in CSS Object Model spec +// see https://www.w3.org/TR/cssom-1/#the-css.escape()-method +QString escapeCSS(QString input) { + QString output; + QTextStream outputStream(&output); + + if (input == "-") + return QString("\\-"); + + for (int i=0; i= 0x30 && unicode <= 0x39 + ) + ) + outputStream << CSS_ESCAPE_UNICODE_AS_CODEPOINT(unicode); + + else if ( + unicode >= 0x80 || unicode == 0x2D || unicode == 0x5F || + (unicode >= 0x30 && unicode <= 0x39) || + (unicode >= 0x41 && unicode <= 0x5A) || + (unicode >= 0x61 && unicode <= 0x7A) + ) + outputStream << character; + + else + outputStream << CSS_ESCAPE_CHARACTER(character); + + } + + return output; +} + + QSvgRenderer * MyLooksStyle::checkbox = 0; QSvgRenderer * MyLooksStyle::checkbox_checked = 0; QSvgRenderer * MyLooksStyle::radiobutton = 0; diff --git a/src/lib/utilities.hh b/src/lib/utilities.hh index b0796d327..15e14e7f3 100644 --- a/src/lib/utilities.hh +++ b/src/lib/utilities.hh @@ -56,5 +56,7 @@ public slots: DLL_PUBLIC int handleError(bool success, int errorCode); +QString escapeCSS(QString input); + #include #endif //__UTILITIES_HH__