Quellcode durchsuchen

Initial import of wkhtmltoimage

Jakob Truelsen vor 15 Jahren
Ursprung
Commit
938a0605c6
47 geänderte Dateien mit 2209 neuen und 67 gelöschten Zeilen
  1. 447 0
      src/image/arguments.cc
  2. 271 0
      src/image/commandlineparser.cc
  3. 40 0
      src/image/commandlineparser.hh
  4. 112 0
      src/image/commandlineparser_p.hh
  5. 204 0
      src/image/docparts.cc
  6. 125 0
      src/image/htmloutputter.cc
  7. 40 0
      src/image/image.pro
  8. 117 0
      src/image/manoutputter.cc
  9. 119 0
      src/image/outputter.cc
  10. 105 0
      src/image/pageloader.cc
  11. 23 0
      src/image/pageloader.hh
  12. 70 0
      src/image/settings.cc
  13. 130 0
      src/image/settings.hh
  14. 177 0
      src/image/textoutputter.cc
  15. 122 0
      src/image/utilities.cc
  16. 57 0
      src/image/wkhtmltoimage.cc
  17. 0 0
      src/pdf/arguments.cc
  18. 0 0
      src/pdf/commandlineparser.cc
  19. 0 0
      src/pdf/commandlineparser.hh
  20. 0 0
      src/pdf/commandlineparser_p.hh
  21. 0 0
      src/pdf/docparts.cc
  22. 0 0
      src/pdf/htmloutputter.cc
  23. 0 0
      src/pdf/manoutputter.cc
  24. 0 0
      src/pdf/multipageloader.cc
  25. 0 0
      src/pdf/multipageloader.hh
  26. 0 0
      src/pdf/multipageloader_p.hh
  27. 0 0
      src/pdf/outline.cc
  28. 0 0
      src/pdf/outline.hh
  29. 0 0
      src/pdf/outline_p.hh
  30. 0 0
      src/pdf/outputter.cc
  31. 0 0
      src/pdf/pageconverter.cc
  32. 0 0
      src/pdf/pageconverter.hh
  33. 0 0
      src/pdf/pageconverter_p.hh
  34. BIN
      src/pdf/pdf
  35. 46 0
      src/pdf/pdf.pro
  36. 0 0
      src/pdf/progressfeedback.cc
  37. 0 0
      src/pdf/progressfeedback.hh
  38. 0 0
      src/pdf/settings.cc
  39. 0 0
      src/pdf/settings.hh
  40. 0 0
      src/pdf/tempfile.cc
  41. 0 0
      src/pdf/tempfile.hh
  42. 0 0
      src/pdf/textoutputter.cc
  43. 0 0
      src/pdf/tocprinter.cc
  44. 0 0
      src/pdf/tocprinter.hh
  45. 0 0
      src/pdf/tocstylesheet.cc
  46. 0 0
      src/pdf/wkhtmltopdf.cc
  47. 4 67
      wkhtmltopdf.pro

+ 447 - 0
src/image/arguments.cc

@@ -0,0 +1,447 @@
+/*
+ * File:   arguments.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser_p.hh"
+#include <qglobal.h>
+
+/*!
+  \class ArgHandler
+  \brief Class responsible for handling an argument
+*/
+
+/*!
+  \var ArgHandler::longName
+  \brief The long name of the argument, e.g. "help" for "--help"
+*/
+
+/*!
+  \var ArgHandler::desc
+  \brief A descriptive text of the argument
+*/
+
+/*!
+  \var ArgHandler::shortSwitch
+  \brief Sort name, e.g. 'h' for '-h', if 0 there is no short name
+*/
+
+/*!
+  \var ArgHandler::argn
+  \brief The names of the arguments to the switch
+*/
+
+/*!											  
+  \var ArgHandler::display
+  \brief Indicate that the argument is not hidden
+*/
+
+/*!
+  \var ArgHandler::extended
+  \brief Indicate if the argument is an extended argument
+*/
+
+/*!											  
+  \var ArgHandler::qthack
+  \brief Indicate that the argument is only available with hacked qt
+*/
+
+/*!
+  \fn ArgHandler::operator()(const char ** args, CommandLineParserPrivate & parser)
+  Callend when the switch was specified
+  \param args The arguments to the switch, guarantied to have size of argn
+  \param settings The settings to store the information in
+*/
+
+/*!
+  \fn ArgHandler::useDefault(CommandLineParserPrivate & parser)
+  Set give settings its default value
+
+  This is a NOOP for ArgHandler
+  \param parser The parser giving the request
+*/
+void ArgHandler::useDefault(CommandLineParserPrivate & parser) {
+	Q_UNUSED(parser);
+} 
+
+/*!
+  \fn ArgHandler::getDesc() const
+  Get the description of this switch
+*/  
+QString ArgHandler::getDesc() const {
+	return desc;
+}
+
+/*!
+  \fn ArgHandler::~ArgHandler()
+  Dummy virtual destructor
+*/  
+ArgHandler::~ArgHandler() {}
+
+/*!
+  \class CommandLineParserPrivate
+  Implementation details for CommandLineParser
+*/
+
+/*!
+  Sets a variable to some constant
+*/
+template <typename T> class ConstSetter: public ArgHandler {
+public:
+	T & dst;
+	const T src;
+	const T def;
+	ConstSetter(T & arg, const T s, const T d): dst(arg), src(s), def(d) {};
+	bool operator() (const char **, CommandLineParserPrivate &) {
+		dst=src;
+		return true;
+	}
+	virtual void useDefault(CommandLineParserPrivate &) {
+		dst=def;
+	}
+};
+
+struct StringPairCreator {
+	typedef QPair<QString, QString> T;
+	inline T operator()(const QString & key, const QString & value) const {
+		return T(key, value);
+	}
+};
+
+template <bool file> 
+struct PostItemCreator {
+	typedef typename Settings::PostItem T;
+	inline T operator()(const QString & key, const QString & value) const {
+		T p;
+		p.name = key;
+		p.value = value;
+		p.file = file;
+		return p;
+	}
+};
+
+
+struct StringListSetter: public ArgHandler {
+	QList<QString> & dst;
+	StringListSetter(QList<QString> & a, QString valueName) : dst(a) {
+		argn.push_back(valueName);
+	}
+	virtual bool operator() (const char ** args, CommandLineParserPrivate &) {
+		dst.append( args[0] );
+		return true;
+	}
+	virtual void useDefault() {
+		dst.clear();
+	}
+};
+
+
+/*!
+  Putting values into a map
+*/
+template <typename T=StringPairCreator>
+struct MapSetter: public ArgHandler {
+	QList< typename T::T > & dst;
+	MapSetter(QList<typename T::T > & a, QString keyName, QString valueName) : dst(a) {
+		argn.push_back(keyName);
+		argn.push_back(valueName);
+	}
+	virtual bool operator() (const char ** args, CommandLineParserPrivate &) {
+		dst.append( T()(args[0], args[1]) );
+		return true;
+	}
+	virtual void useDefault() {
+		dst.clear();
+	}
+};
+
+
+/*!
+  SomeSetter template method base
+*/
+template <typename TT> 
+struct SomeSetterTM {
+	typedef TT T;
+	//T strToT(const char * val, bool & ok);
+	static QString TToStr(const T &, bool & ok) {ok=false; return "";}
+};
+
+/*!
+  TemplateMethod class used to set a single variable of some type TT::T
+*/
+template <typename TT>
+struct SomeSetter: public ArgHandler {
+	typedef typename TT::T T;
+	T & val;
+	T def;
+	bool hasDef;
+
+	SomeSetter(T & a, QString an, T d): val(a), def(d), hasDef(true) {
+		argn.push_back(an);
+	}
+
+	SomeSetter(T & a, QString an): val(a), hasDef(false) {
+		argn.push_back(an);
+	}
+
+	virtual void useDefault(CommandLineParserPrivate &) {
+		if (hasDef)
+			val=def;
+	}
+
+	bool operator() (const char ** vals, CommandLineParserPrivate &) {
+		bool ok;
+		val = TT::strToT(vals[0], ok);
+		return ok;
+	}
+
+	virtual QString getDesc() const {
+		if (!hasDef) return desc;
+		bool ok;
+		QString x = TT::TToStr(def,ok);
+		if (!ok) return desc;
+		return desc + " (default " + x + ")";
+	}
+};
+
+struct IntTM: public SomeSetterTM<int> {
+	static int strToT(const char * val, bool & ok) {
+		return QString(val).toInt(&ok);
+	}
+	static QString TToStr(const int & t, bool & ok) {
+		ok=(t!=-1);
+		return QString::number(t);
+	}
+};
+/*!
+  Argument handler setting an int variable
+*/
+typedef SomeSetter<IntTM> IntSetter;
+
+struct FloatTM: public SomeSetterTM<float> {
+	static float strToT(const char * val, bool & ok) {
+		return QString(val).toFloat(&ok);
+	}
+	static QString TToStr(const float & t, bool & ok) {
+		ok=(t!=-1);
+		return QString::number(t);
+	}
+};
+/*!
+  Argument handler setting an float variable
+*/
+typedef SomeSetter<FloatTM> FloatSetter;
+
+struct StrTM: public SomeSetterTM<const char *> {
+	static const char * strToT(const char * val, bool & ok) {
+		ok=true;
+		return val;
+	}
+	static QString TToStr(const char * t, bool & ok) {
+		ok = (t[0] != '\0');
+		return QString(t);
+	}
+};
+/*!
+  Argument handler setting a string variable
+*/
+typedef SomeSetter<StrTM> StrSetter;
+
+struct QStrTM: public SomeSetterTM<QString> {
+	static QString strToT(const char * val, bool & ok) {
+		ok=true;
+		return QString::fromLocal8Bit(val);
+	}
+	static QString TToStr(QString t, bool & ok) {
+		ok=!t.isEmpty();
+		return t;
+	}
+};
+/*!
+  Argument handler setting a string variable
+*/
+typedef SomeSetter<QStrTM> QStrSetter;
+
+struct ProxyTM: public SomeSetterTM<Settings::ProxySettings> {
+	static Settings::ProxySettings strToT(const char * val, bool &ok) {
+		return Settings::strToProxy(val, &ok);
+	}
+};
+/*!
+  Argument handler setting a proxy variable  
+ */
+typedef SomeSetter<ProxyTM> ProxySetter;
+
+/*!
+  Argument handler responsible for calling a function
+*/
+template <typename T> struct Caller: public ArgHandler {
+	Caller() {}
+	Caller(QString a1) {
+		argn.push_back(a1);
+	}
+	bool operator() (const char **vals, CommandLineParserPrivate & s) {
+		return T()(vals,s);
+	}
+};
+
+//All these function would have been lambda function, had C++ supported them, now we are forced to write them here
+
+/*!
+  Lambda: Call the usage method
+*/
+template <bool v>
+struct HelpFunc {
+	bool operator()(const char **, CommandLineParserPrivate & p) {
+		p.usage(stdout,v);
+		exit(0);
+	}
+};
+
+/*!
+  Lambda: Call the man method
+*/
+struct ManPageFunc {
+	bool operator()(const char **, CommandLineParserPrivate & p) {
+		p.manpage(stdout);
+		exit(0);
+	}
+};
+
+/*!
+  Lambda: Call the man method
+*/
+template <bool T>
+struct ReadmeFunc {
+	bool operator()(const char **, CommandLineParserPrivate & p) {
+		p.readme(stdout, T);
+		exit(0);
+	}
+};
+
+/*!
+  Lambda: Call the version method
+*/
+struct VersionFunc {
+	bool operator()(const char **, CommandLineParserPrivate & p) {
+		p.version(stdout);
+		exit(0);
+	}
+};
+
+/*!
+  The next arguments we add will belong to this section
+  /param s The name of the section
+  /param desc A description of the section
+*/
+void CommandLineParserPrivate::section(QString s, QString desc) {
+	currentSection = s;
+	sectionDesc[s] = desc;
+	sections.push_back(s);
+}
+
+/*!
+  Indicate whether the next arguments we add are "extended" and should not 
+  be shown in a simple --help
+  \param e Are the arguments extended
+*/
+void CommandLineParserPrivate::extended(bool e) {
+	currentExtended = e;
+}
+
+/*!
+  Add an argument to the list of arguments
+  \param l The long "--" name of the argument
+  \param s The short '-' name of the argument or 0 if unspecified
+  \param d Description of the argument
+  \param h The handler for the argument
+  \param display Is the argument hidden
+*/
+void CommandLineParserPrivate::addarg(QString l, char s, QString d, ArgHandler * h, bool display) {
+	h->desc = d;
+	h->longName = l;
+	h->shortSwitch = s;
+	h->display = display;
+	h->qthack = currentHack;
+	h->extended = currentExtended;
+	longToHandler[l] = h;
+	if(s) shortToHandler[s] = h;
+	sectionArgumentHandles[currentSection].push_back(h);
+}
+
+/*!
+  Construct the commandline parser adding all the arguments
+  \param s The settings to store values in
+*/
+CommandLineParserPrivate::CommandLineParserPrivate(Settings & s):
+	settings(s)
+{
+	section("General Options");
+	extended(false);
+	addarg("help",'h',"Display help",new Caller<HelpFunc<false> >());
+	addarg("quiet",'q',"Be less verbose",new ConstSetter<bool>(s.quiet,true,false));
+	addarg("version",'V',"Output version information an exit", new Caller<VersionFunc>());
+	addarg("extended-help",0,"Display more extensive help, detailing less common command switches", new Caller<HelpFunc<true> >());
+	addarg("proxy",'p',"Use a proxy", new ProxySetter(s.proxy, "proxy"));
+	addarg("username",0,"HTTP Authentication username", new QStrSetter(s.username, "username",""));
+	addarg("password",0,"HTTP Authentication password", new QStrSetter(s.password, "password",""));
+	extended(true);
+	addarg("custom-header",0,"Set an additional HTTP header (repeatable)", new MapSetter<>(s.customHeaders, "name", "value"));
+	addarg("manpage", 0, "Output program man page", new Caller<ManPageFunc>());
+	addarg("htmldoc", 0, "Output program html help", new Caller<ReadmeFunc<true> >());
+	addarg("readme", 0, "Output program readme", new Caller<ReadmeFunc<false> >());
+	addarg("disable-javascript",'n',"Do not allow web pages to run javascript", new ConstSetter<bool>(s.enableJavascript,false,true));
+	addarg("grayscale",'g',"Image will be generated in grayscale", new ConstSetter<QPrinter::ColorMode>(s.colorMode,QPrinter::GrayScale,QPrinter::Color));
+	addarg("redirect-delay",0,"Wait some milliseconds for js-redirects", new IntSetter(s.jsredirectwait,"msec",200));
+	addarg("enable-plugins",0,"Enable installed plugins (such as flash)", new ConstSetter<bool>(s.enablePlugins,true,false));
+
+	addarg("scale-w",0,"Set width for resizing", new IntSetter(s.scale.width,"int",-1));
+	addarg("scale-h",0,"Set height for resizing", new IntSetter(s.scale.height,"int",-1));
+
+	addarg("crop-x",0,"Set x coordinate for croping", new IntSetter(s.crop.left,"int",0));
+	addarg("crop-y",0,"Set y coordinate for croping", new IntSetter(s.crop.top,"int",0));
+	addarg("crop-w",0,"Set width for croping", new IntSetter(s.crop.width,"int",-1));
+	addarg("crop-h",0,"Set height for croping", new IntSetter(s.crop.height,"int",-1));
+
+	addarg("minimum-font-size",0,"Minimum font size", new IntSetter(s.minimumFontSize,"int",5));
+	addarg("cookie-jar", 0, "Read and write cookies from and to the supplied cookie jar file", new QStrSetter(s.cookieJar, "path", "") );
+	addarg("cookie",0,"Set an additional cookie (repeatable)", new MapSetter<>(s.cookies, "name", "value"));
+	addarg("post", 0, "Add an additional post field (repeatable)", new MapSetter<PostItemCreator<false> >(s.post, "name", "value"));
+	addarg("post-file", 0, "Post an aditional file (repeatable)", new MapSetter<PostItemCreator<true> >(s.post, "name", "path"));
+	addarg("disallow-local-file-access", 0, "Do not allowed conversion of a local file to read in other local files, unless explecitily allowed with --allow", new ConstSetter<bool>(s.blockLocalFileAccess, true, false));
+	addarg("allow", 0, "Allow the file or files from the specified folder to be loaded (repeatable)", new StringListSetter(s.allowed,"path"));
+	addarg("format",0,"Sets the image output format (eg: PNG), if not set, it tries to determine it from output file ame", new QStrSetter(s.fmt, "ext"));
+	
+	addarg("disable-smart-shrinking", 0, "Disable the intelligent shrinking strategy used by WebKit that makes the pixel/dpi ratio none constant",new ConstSetter<bool>(s.enableIntelligentShrinking, false, true));
+	addarg("replace",0, "Replace [name] with value in header and footer (repeatable)", new MapSetter<>(s.replacements, "name", "value"));
+#ifdef Q_WS_X11
+	addarg("use-xserver",0,"Use the X server (some plugins and other stuff might not work without X11)", new ConstSetter<bool>(s.useGraphics,true,false));
+#endif
+
+#if QT_VERSION >= 0x040600
+	//qthack(false);
+#endif
+	addarg("encoding",0,"Set the default text encoding, for input", new QStrSetter(s.defaultEncoding,"encoding",""));
+	
+#if QT_VERSION >= 0x040500 //Not printing the background was added in QT4.5
+	addarg("no-background",0,"Do not print background", new ConstSetter<bool>(s.background,false,true));
+	addarg("user-style-sheet",0,"Specify a user style sheet, to load with every page", new QStrSetter(s.userStyleSheet,"url",""));
+#endif
+	addarg("debug-javascript", 0,"Show javascript debugging output", new ConstSetter<bool>(s.debugJavascript, true, false));
+#if QT_VERSION >= 0x040600
+	addarg("stop-slow-scripts", 0, "Stop slow running javascripts", new ConstSetter<bool>(s.stopSlowScripts, true, false));
+#endif	
+	extended(false);
+}

+ 271 - 0
src/image/commandlineparser.cc

@@ -0,0 +1,271 @@
+/*
+ * File:   commandlinesparser.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser_p.hh"
+#include <qwebframe.h>
+
+/*!
+  \file commandlineparser.hh
+  \brief Defines the CommandLineParser class
+*/
+
+/*!
+  \file commandlineparser_p.hh
+  \brief Defines the CommandLineParserPrivate, ArgHandler and Outputter class
+*/
+
+bool ahsort(const ArgHandler * a, const ArgHandler * b) {
+	return a->longName < b->longName;
+}
+
+/*!
+  Output description of switches to an outputter
+  \param o The outputter to output to
+  \param extended Should we also output extended arguments
+  \param doc Indicate to the outputter that it is writing documentation
+*/
+void CommandLineParserPrivate::outputSwitches(Outputter * o, bool extended, bool doc) const {
+	foreach(const QString & section, sections) {
+		QList<const ArgHandler *> display;
+		foreach(const ArgHandler * handler, sectionArgumentHandles[section]) {
+			if(!doc && handler->qthack) continue;
+			if(!extended && handler->extended) continue;
+			display.push_back(handler);
+		}
+		qSort(display.begin(), display.end(), ahsort);
+		if(display.size() == 0) continue;
+		o->beginSection(section);
+		if(!sectionDesc[section].isEmpty()) {
+			o->beginParagraph();
+			o->text(sectionDesc[section]);
+			o->endParagraph();
+		}
+		o->beginSwitch();
+		foreach(const ArgHandler * handler, display)
+			o->cswitch(handler);
+		o->endSwitch();
+		o->endSection();
+ 	}
+}
+
+/*!
+  Output the man page to a given file
+  \param fd The file to store the man page
+*/
+void CommandLineParserPrivate::manpage(FILE * fd) const {
+	Outputter * o = Outputter::man(fd);
+ 	outputManName(o);
+ 	outputSynopsis(o);
+ 	outputDescripton(o);
+	outputSwitches(o, true, false);
+ 	outputContact(o);
+ 	outputAuthors(o);
+	delete o;
+}
+
+/*!
+  Output usage information aka. --help
+  \param fd The file to output the information to
+  \param extended Should we show extended arguments
+*/
+void CommandLineParserPrivate::usage(FILE * fd, bool extended) const {
+	Outputter * o = Outputter::text(fd,false);
+	outputName(o);
+	outputSynopsis(o);
+ 	outputDescripton(o);
+	outputSwitches(o, extended, false);
+	if (extended) {
+		outputProxyDoc(o);
+	}
+ 	outputContact(o);
+	delete o;
+}
+
+/*!
+  Output version information aka. --version
+  \param fd The file to output to
+*/
+void CommandLineParserPrivate::version(FILE * fd) const {
+ 	Outputter * o = Outputter::text(fd,false);
+  	outputName(o);
+  	outputLicense(o);
+  	outputAuthors(o);
+	delete o;
+}
+
+/*!
+  Output the readme/manual
+  \param fd The file to output to
+  \param html Do we want the html manaul, or the README
+*/
+void CommandLineParserPrivate::readme(FILE * fd, bool html) const {
+	Outputter * o = html?Outputter::html(fd):Outputter::text(fd, true);
+	outputDocStart(o);
+	outputContact(o);
+	outputLicense(o);
+	outputAuthors(o);
+	outputSynopsis(o);
+	outputSwitches(o, true, true);
+ 	outputProxyDoc(o);
+	outputStaticProblems(o);
+	outputCompilation(o);
+	outputInstallation(o);
+	outputExamples(o);
+	delete o;
+}
+
+/*!
+  Output usage information aka. --help
+  \param fd The file to output the information to
+  \param extended Should we show extended arguments
+*/
+void CommandLineParser::usage(FILE * fd, bool extended) const {
+	d->usage(fd, extended);
+}
+
+/*!
+  Output version information aka. --version
+  \param fd The file to output to
+*/
+void CommandLineParser::version(FILE * fd) const {
+	d->version(fd);
+}
+
+/*!
+  Output the man page to a given file
+  \param fd The file to store the man page
+*/
+void CommandLineParser::manpage(FILE * fd) const {
+	d->manpage(fd);
+}
+
+/*!
+  Output the readme/manual
+  \param fd The file to output to
+  \param html Do we want the html manaul, or the README
+*/
+void CommandLineParser::readme(FILE * fd, bool html) const {
+	d->readme(fd,html);
+}
+
+/*!
+  Construct a commandline parser, storing its values in some settings
+  \param s The settings to store the values in.
+*/
+CommandLineParser::CommandLineParser(Settings & s):
+	d(new CommandLineParserPrivate(s))
+{
+}
+	
+CommandLineParser::~CommandLineParser() {
+	delete d;
+}
+
+/*!
+ * Load default arguments and put them in the settings structure
+ */
+void CommandLineParser::loadDefaults() {
+	d->settings.in = "-";
+	d->settings.proxy.host = "";
+	foreach(ArgHandler * h, d->longToHandler) 
+		h->useDefault(*d);
+
+	//Load configuration from enviornment
+	char * val;
+	const char * vars[] = {"proxy","all_proxy","http_proxy", NULL};
+	for(int i=0; vars[i]; ++i) {
+		if ((val = getenv("proxy"))) {
+			bool ok=false;
+			Settings::ProxySettings p = Settings::strToProxy(val, &ok);
+			if(ok) 
+				d->settings.proxy = p;
+		}
+	}
+}
+
+/*!
+ * Parse command line arguments, and set settings accordingly.
+ * \param argc the number of command line arguments
+ * \param argv a NULL terminated list with the arguments
+ */
+void CommandLineParser::parseArguments(int argc, const char ** argv, bool final) {
+    d->settings.in="";
+    d->settings.out="";
+	for (int i=1; i < argc; ++i) {
+        if(i==argc-2 && argv[i][1]!='-'){ // the arg before last (in)
+            d->settings.in = argv[i];
+        } else if (i==argc-1 && argv[i][1]!='-'){ // the last arg (out)
+            d->settings.out = argv[i];
+		} else if (argv[i][1] == '-') { //We have a long style argument
+			//Try to find a handler for this long switch
+			QHash<QString, ArgHandler*>::iterator j = d->longToHandler.find(argv[i]+2);
+			if (j == d->longToHandler.end()) { //Ups that argument did not exist
+				fprintf(stderr, "Unknown long argument %s\n\n", argv[i]);
+				d->usage(stderr, false);
+				exit(1);
+			}
+			//Check to see if there is enough arguments to the switch
+			if (argc-i < j.value()->argn.size()+1) {
+				fprintf(stderr, "Not enough arguments parsed to %s\n\n", argv[i]);
+				d->usage(stderr, false);
+				exit(1);
+			}
+			if (!(*(j.value()))(argv+i+1, *d)) {
+				fprintf(stderr, "Invalid argument(s) parsed to %s\n\n", argv[i]);
+				d->usage(stderr, false);
+				exit(1);
+			}
+			if (j.value()->qthack)
+				fprintf(stderr, "The switch %s, is not support using unpatched qt, and will be ignored.", argv[i]);
+			//Skip allredy handled switch arguments
+			i += j.value()->argn.size();
+		} else {
+			int c=i;//Remember the current argument we are parsing
+			for (int j=1; argv[c][j] != '\0'; ++j) {
+				QHash<char, ArgHandler*>::iterator k = d->shortToHandler.find(argv[c][j]);
+				//If the short argument is invalid print usage information and exit
+				if (k == d->shortToHandler.end()) {
+					fprintf(stderr, "Unknown switch -%c\n\n", argv[c][j]);
+					d->usage(stderr, false);
+					exit(1);
+				}
+				//Check to see if there is enough arguments to the switch
+				if (argc-i < k.value()->argn.size()+1) {
+					fprintf(stderr, "Not enough arguments parsed to -%c\n\n", argv[c][j]);
+					d->usage(stderr, false);
+					exit(1);
+				}
+				if (!(*(k.value()))(argv+i+1, *d)) {
+					fprintf(stderr, "Invalid argument(s) parsed to -%c\n\n", argv[c][j]);
+					d->usage(stderr, false);
+					exit(1);
+				}
+			if (k.value()->qthack)
+				fprintf(stderr, "The switch -%c, is not support using unpatched qt, and will be ignored.", argv[c][j]);
+				//Skip allredy handled switch arguments
+				i += k.value()->argn.size();
+			}
+		}
+	}
+
+	if(final || d->settings.in=="" || d->settings.out=="") {
+        fprintf(stderr, "You need to specify at least one input file, and exactly one output file\nUse - for stdin or stdout\n\n");
+        d->usage(stderr, false);
+        exit(1);
+    }
+}
+

+ 40 - 0
src/image/commandlineparser.hh

@@ -0,0 +1,40 @@
+/*
+ * File:   commandlineparser.hh
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __COMMMAND_LINE_PARSER_HH__
+#define __COMMMAND_LINE_PARSER_HH__
+#include "settings.hh"
+#include <cstdio>
+
+class CommandLineParserPrivate;
+
+/*! \brief The class is responcible for parsing command line information
+*/
+class CommandLineParser {
+public:
+	CommandLineParser(Settings & settings);
+	~CommandLineParser();
+	void version(FILE * fd) const;
+	void usage(FILE * fd, bool extended) const;
+	void manpage(FILE * fd) const;
+	void readme(FILE * fd, bool html) const;
+	void loadDefaults();
+	void parseArguments(int argc, const char ** argv, bool final=false);
+private:
+	CommandLineParserPrivate * d;
+};
+#endif //__COMMMAND_LINE_PARSER_HH__

+ 112 - 0
src/image/commandlineparser_p.hh

@@ -0,0 +1,112 @@
+/*
+ * File:   commandlineparser_p.hh
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __COMMMAND_LINE_PARSER_P_HH__
+#define __COMMMAND_LINE_PARSER_P_HH__
+
+#include <cstdio>
+#include <QString>
+#include "commandlineparser.hh"
+#include "settings.hh"
+
+class CommandLineParserPrivate;
+
+class ArgHandler {
+public:
+	QString longName;
+	QString desc;
+	char shortSwitch;
+	QVector<QString> argn;
+	bool display;
+	bool extended;
+	bool qthack;
+	virtual bool operator() (const char ** args, CommandLineParserPrivate & parser) = 0;
+	virtual void useDefault(CommandLineParserPrivate & parser);
+	virtual QString getDesc() const;
+	virtual ~ArgHandler();
+};
+ 
+
+class Outputter {
+public:
+	virtual ~Outputter() {}
+	virtual void beginSection(const QString & name) = 0;
+	virtual void endSection() = 0;
+	virtual void beginParagraph() = 0;
+	virtual void text(const QString & t) = 0;
+	virtual void bold(const QString & t) =  0;
+	virtual void italic(const QString & t) = 0;
+	virtual void link(const QString & l) = 0;
+	virtual void endParagraph() = 0;
+	virtual void verbatim(const QString & t) = 0;
+ 	virtual void beginList(bool ordered=false) = 0;
+ 	virtual void endList() = 0;
+ 	virtual void listItem(const QString & t) = 0;
+	virtual void beginSwitch() = 0;
+	virtual void cswitch(const ArgHandler * h) = 0;
+	virtual void endSwitch() = 0;
+	void paragraph(const QString & t);
+	static Outputter * text(FILE * fd, bool doc=false, bool extended=false);
+	static Outputter * man(FILE * fd);
+	static Outputter * html(FILE * fd);
+};
+
+class CommandLineParserPrivate {
+public:
+	QString currentSection;
+	Settings & settings;
+	bool currentExtended;
+	bool currentHack;
+
+	QList<QString> sections;
+	QHash<QString, ArgHandler *> longToHandler;
+	QHash<char, ArgHandler *> shortToHandler;
+	QHash<QString, QList<ArgHandler *> > sectionArgumentHandles;
+	QHash<QString, QString> sectionDesc;
+
+	//arguments.cc
+	CommandLineParserPrivate(Settings & s);
+	void section(QString s, QString desc="");
+	void extended(bool);
+	void addarg(QString, char, QString, ArgHandler * h, bool display=true);
+
+	//docparts.cc
+	void outputManName(Outputter * o) const;
+	void outputName(Outputter * o) const;
+	void outputLicense(Outputter * o) const;
+	void outputAuthors(Outputter * o) const;
+	void outputSynopsis(Outputter * o) const;
+	void outputDescripton(Outputter * o) const;
+	void outputProxyDoc(Outputter * o) const;
+	void outputArgsFromStdin(Outputter * o) const;
+	void outputNotPatched(Outputter * o, bool sure) const;
+	void outputPageBreakDoc(Outputter * o) const;
+	void outputContact(Outputter * o) const;
+	void outputDocStart(Outputter * o) const;
+	void outputCompilation(Outputter * o) const;
+	void outputInstallation(Outputter * o) const;
+	void outputExamples(Outputter * o) const;
+	void outputStaticProblems(Outputter * o) const;
+	//commandlineparser.cc
+	void outputSwitches(Outputter * o, bool extended, bool doc) const;
+	void version(FILE * fd) const;
+	void usage(FILE * fd, bool extended) const;
+	void manpage(FILE * fd) const;
+	void readme(FILE * fd, bool html) const;
+};
+
+#endif //__COMMMAND_LINE_PARSER_P_HH__

+ 204 - 0
src/image/docparts.cc

@@ -0,0 +1,204 @@
+/*
+ * File:   docparts.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser_p.hh"
+#include <QWebFrame>
+
+#define STRINGIZE_(x) #x
+#define STRINGIZE(x) STRINGIZE_(x)
+
+/*!
+  Output the name and version of the program, and also whether we are using a patched qt
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputName(Outputter * o) const {
+	o->beginSection("Name");
+	o->paragraph(QString("wkhtmltoimage ")+QString::number(MAJOR_VERSION)+"."+QString::number(MINOR_VERSION)+"."+QString::number(PATCH_VERSION)+(QString(STRINGIZE(BUILD)).isEmpty()?"":" ")+STRINGIZE(BUILD));
+	o->endSection();
+}
+
+
+/*!
+  Output name and a short description
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputManName(Outputter * o) const {
+	o->beginSection("Name");
+	o->paragraph("wkhtmltoimage - html to image converter");
+	o->endSection();
+}
+
+/*!
+  Output copyright stuff
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputLicense(Outputter * o) const {
+	o->beginSection("License");
+	o->paragraph("Copyright (C) 2010 wkhtmltoimage Authors.");
+	o->paragraph("Copyright (C) 1989, 1991 by Jef Poskanzer.");
+	o->endParagraph();
+	o->beginParagraph();
+	o->text("License GPLv3+: GNU GPL version 3 or later ");
+	o->link("http://gnu.org/licenses/gpl.html");
+	o->text(". This is free software: you are free to change and redistribute it. "
+			"There is NO WARRANTY, to the extent permitted by law.");
+	o->endParagraph();
+}
+
+/*!
+  Output list of authors
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputAuthors(Outputter * o) const {
+	o->beginSection("Authors");
+	o->paragraph(
+		QString::fromUtf8(
+			"Written by Christian Sciberras. "
+			"Adopted code from wkhtmltopdf by Jakob Truelsen."));
+	o->endSection();
+}
+
+/*!
+  Output a short synopsis on how to call the command line program
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputSynopsis(Outputter * o) const {
+	o->beginSection("Synopsis");
+	o->verbatim("wkhtmltoimage [OPTIONS]... <input file> <output file>\n");
+	o->endSection();
+}
+
+/*!
+  Explain what the program does
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputDescripton(Outputter * o) const {
+	o->beginSection("Description");
+	o->beginParagraph();
+	o->text("Converts an HTML page into an image, ");
+	o->endParagraph();
+	o->endSection();
+}
+
+/*!
+  Output documentation about the proxy settings
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputProxyDoc(Outputter * o) const {
+	o->beginSection("Specifying A Proxy");
+	o->paragraph(
+		"By default proxy information will be read from the environment"
+		" variables: proxy, all_proxy and http_proxy, proxy options can"
+		" also by specified with the -p switch");
+	o->verbatim(
+		"<type> := \"http://\" | \"socks5://\"\n"
+		"<serif> := <username> (\":\" <password>)? \"@\"\n"
+		"<proxy> := \"None\" | <type>? <sering>? <host> (\":\" <port>)?\n");
+	o->paragraph("Here are some examples (In case you are unfamiliar with the BNF):");
+	o->verbatim("http://user:password@myproxyserver:8080\n"
+				"socks5://myproxyserver\n"
+				"None\n");
+	o->endSection();
+}
+
+/*!
+  Output contact information
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputContact(Outputter * o) const {
+	o->beginSection("Contact");
+	o->beginParagraph();
+	o->text("If you experience bugs or want to request new features please visit ");
+	o->link("http://code.google.com/p/wkhtmltoimage/issues/list");
+	o->text(", if you have any problems or comments please feel free to contact me: ");
+	o->link("uuf6429@gmail.com");
+	o->endParagraph();
+	o->endSection();
+}
+
+/*!
+  Output beginning of the readme
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputDocStart(Outputter * o) const {
+	o->beginSection(QString("wkhtmltoimage ")+QString::number(MAJOR_VERSION)+"."+QString::number(MINOR_VERSION)+"."+QString::number(PATCH_VERSION)+(QString(STRINGIZE(BUILD)).isEmpty()?"":" ")+STRINGIZE(BUILD) + " Manual");
+	o->paragraph("This file documents wkhtmltoimage, a program capable of converting HTML "
+				 "documents into images.");
+	o->endSection();
+}
+
+/*!
+  Output information on how to compile
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputCompilation(Outputter * o) const {
+	o->beginSection("Compilation");
+	o->paragraph("It can happen that the static binary does not work for your system "
+				 "for one reason or the other, in that case you might need to compile "
+				 "wkhtmltoimage yourself.");
+	o->endParagraph();
+	o->endSection();
+}
+
+/*!
+  Output information on how to install
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputInstallation(Outputter * o) const {
+	o->beginSection("Installation");
+	o->paragraph(
+		"There are several ways to install wkhtmltoimage.  You can download a "
+		"already compiled binary, or you can compile wkhtmltoimage yourself. ");
+	o->endSection(); 
+}
+
+/*!
+  Output examples on how to use wkhtmltoimage
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputExamples(Outputter * o) const {
+	o->beginSection("Examples");
+	o->paragraph("This section presents a number of examples of how to invoke wkhtmltoimage.");
+	o->paragraph("To convert a remote HTML file to PNG:");
+	o->verbatim("wkhtmltoimage http://www.google.com google.png\n");
+	o->paragraph("To convert a local HTML file to PNG:");
+	o->verbatim("wkhtmltoimage my.html my.png\n");
+	o->endSection();
+}
+
+/*!
+  Output information on the problems with the static version
+  \param o The outputter to output to
+*/
+void CommandLineParserPrivate::outputStaticProblems(Outputter * o) const {
+	o->beginSection("Static version");
+	o->beginParagraph();
+	o->text("On the wkhtmltoimage website you can download a static version of wkhtmltoimage ");
+	o->link("http://code.google.com/p/wkhtmltoimage/downloads/list");
+	o->text(". This static binary will work on most systems and comes with a build in patched QT.");
+	o->endParagraph();
+
+	o->beginParagraph();
+	o->text("Unfortunately the static binary is not particularly static, on Linux it depends "
+			"on both glibc and openssl, furthermore you will need to have an xserver installed "
+			"but not necessary running. You will need to have different fonts install including "
+			"xfonts-scalable (Type1), and msttcorefonts.  See ");
+	o->link("http://code.google.com/p/wkhtmltopdf/wiki/static");
+	o->text(" for trouble shooting.");
+	o->endParagraph();
+	o->endSection();
+}

+ 125 - 0
src/image/htmloutputter.cc

@@ -0,0 +1,125 @@
+/*
+ * File:   htmloutputter.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser_p.hh"
+#include <QTextDocument>
+
+#define S(x) Qt::escape(x).toUtf8().constData()
+
+class HtmlOutputter: public Outputter {
+private:
+	FILE * fd;
+	bool ordered;
+public:
+	HtmlOutputter(FILE * _): fd(_) {
+		fprintf(fd,
+				"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
+				"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n"
+				"<head>\n"
+				"  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"
+				"  <title>wkhtmltoimage - Manual</title>\n"
+				"  <style type=\"text/css\">\n"
+				"    body {width: 70em}\n"
+				"    .short {font-weight: bold; width:2em}\n"
+				"    .long {font-weight: bold; width: 15em}\n"
+				"    .arg {font-style: italic; width: 12em}\n"
+				"    tr {vertical-align: top}\n"
+				"  </style>\n"
+				"</head><body>");
+	}
+
+	~HtmlOutputter() {
+		fprintf(fd,"</body></html>\n");
+	}
+
+	void beginSection(const QString & name) {
+		fprintf(fd, "<h1>%s</h1>\n", S(name));
+	}
+
+	void endSection() {
+	}
+
+	void beginParagraph() {
+		fprintf(fd,"<p>");
+	}
+
+	void endParagraph() {
+		fprintf(fd,"</p>\n");
+	}
+
+	void text(const QString & t) {
+		fprintf(fd, "%s", S(t));
+	}
+	
+	void bold(const QString & t) {
+		fprintf(fd, "<b>%s</b>", S(t));
+	}
+	
+	void italic(const QString & t) {
+		fprintf(fd, "<i>%s</i>", S(t));
+	}
+
+	void link(const QString & t) {
+		fprintf(fd, "<a href=\"%s\">%s</a>", S(t),S(t));
+	}
+	
+	void verbatim(const QString & t) {
+		fprintf(fd, "<pre>%s</pre>", S(t));
+	}
+
+	void beginList(bool o) {
+		ordered = o;
+		fprintf(fd, ordered?"<ol>":"<ul>");
+	}
+	
+	void endList() {
+		fprintf(fd, ordered?"</ol>":"</ul>");
+	}
+	
+	void listItem(const QString & s) {
+		fprintf(fd, "<li>%s</li>\n", S(s));
+	}
+	
+	void beginSwitch() {
+		fprintf(fd, "<table>\n");
+	}
+
+	void cswitch(const ArgHandler * h) {
+		fprintf(fd, "<tr><td class=\"short\">");
+		if(h->shortSwitch)
+			fprintf(fd, "-%c,",h->shortSwitch);
+		fprintf(fd, "</td><td class=\"long\">--%s%s</td><td class=\"arg\">",S(h->longName),
+				(h->qthack?"<span style=\"font-weight: normal; font-size: 80%; color:red;\">*</span>":""));
+		foreach(const QString & arg, h->argn)
+			fprintf(fd, "&lt;%s&gt; ",S(arg));
+		fprintf(fd, "</td><td class=\"desc\">%s</td></tr>\n",S(h->getDesc()));
+	}
+
+	void endSwitch() {
+		fprintf(fd, "</table>\n");
+		fprintf(fd, "<p>Items marked <span style=\"font-weight: normal; font-size: 80%%; color:red;\">*</span> are only available using patched QT.</p>");
+	}
+	
+};
+
+/*!
+  Create a Html outputter
+  \param fd A file description to output to
+*/
+  Outputter * Outputter::html(FILE * fd) {
+	return new HtmlOutputter(fd);
+}

+ 40 - 0
src/image/image.pro

@@ -0,0 +1,40 @@
+include(../../common.pri)
+
+MOC_DIR = ../../build/image
+OBJECTS_DIR = ../../build/image
+UI_DIR = ../../build/image
+
+TEMPLATE = app
+TARGET = wkhtmltoimage
+DESTDIR = ../../bin
+DEPENDPATH += . src
+INCLUDEPATH += . src
+
+readme.target=README_WKHTMLTOIMAGE
+readme.commands=./wkhtmltoimage --readme > README_WKHTMLTOIMAGE
+readme.depends=wkhtmltoimage
+
+QMAKE_EXTRA_TARGETS += readme
+
+unix {
+    man.target=wkhtmltoimage.1.gz
+    man.commands=./wkhtmltoimage --manpage | gzip > $@
+    man.depends=wkhtmltoimage
+
+    manins.target=manins
+    manins.depends=man
+    manins.files=wkhtmltoimage.1.gz
+    manins.path=$$INSTALLBASE/share/man/man1
+
+    QMAKE_EXTRA_TARGETS += manins man
+    INSTALLS += manins
+}
+
+INSTALLS += target
+target.path=$$INSTALLBASE/bin
+
+# Input
+HEADERS += pageloader.hh settings.hh
+SOURCES += wkhtmltoimage.cc arguments.cc commandlineparser.cc docparts.cc      \
+           textoutputter.cc outputter.cc manoutputter.cc pageloader.cc         \
+           settings.cc utilities.cc htmloutputter.cc

+ 117 - 0
src/image/manoutputter.cc

@@ -0,0 +1,117 @@
+/*
+ * File:   manoutputter.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser_p.hh"
+#include <QStringList>
+#define S(x) ((x).toUtf8().constData())
+
+class ManOutputter: public Outputter {
+private:
+	FILE * fd;
+	int order;
+public:
+	ManOutputter(FILE * _): fd(_) {
+		fprintf(fd,".TH wkhtmltoimage 1 \"2010 May 21\"\n\n");
+	}
+
+	void beginSection(const QString & name) {
+		fprintf(fd, ".SH %s\n", S(name));
+	}
+
+	void endSection() {
+		fprintf(fd, "\n");
+	}
+
+	void beginParagraph() {
+	}
+
+	void endParagraph() {
+		fprintf(fd, "\n\n");
+	}
+	
+	void text(const QString & t) {
+		QString str = QString(t).replace("-", "\\-");
+		fprintf(fd, "%s", S(str));
+	}
+	
+	void bold(const QString & t) {
+		fprintf(fd, "\\fB%s\\fP", S(t));
+	}
+	
+	void italic(const QString & t) {
+		fprintf(fd, "\\fB%s\\fP", S(t));
+	}
+
+	void link(const QString & t) {
+		fprintf(fd, "<%s>", S(t));
+	}
+
+	void verbatim(const QString & t) {
+		QString str = QString(t).replace("-", "\\-");
+		QStringList l = str.split('\n');
+		while ( l.back() == "") l.pop_back();
+		foreach(const QString & line, l)
+			fprintf(fd, "  %s\n", S(line));
+		fprintf(fd, "\n");
+	}
+	
+	void beginSwitch() {
+		fprintf(fd, ".PD 0\n");
+	}
+
+	void beginList(bool ordered) {
+		order=(ordered?1:-1);
+	}
+
+	void endList() {
+		fprintf(fd, "\n");
+	}
+	
+	void listItem(const QString & s) {
+		if (order < 0) fprintf(fd, " * ");
+		else fprintf(fd, "%3d ", order++);
+		fprintf(fd,"%s\n",S(s));
+	}
+	
+	void cswitch(const ArgHandler * h) {
+		fprintf(fd, ".TP\n");
+		fprintf(fd, "\\fB");
+		if(h->shortSwitch != 0)
+			fprintf(fd, "\\-%c, ", h->shortSwitch);
+		else
+			fprintf(fd, "    ");
+		fprintf(fd,"\\-\\-%s\\fR", S(h->longName));
+		
+		for(QVector<QString>::const_iterator i = h->argn.constBegin(); i != h->argn.constEnd(); ++i)
+			fprintf(fd," \\fI<%s>\\fR", S(*i));
+		
+		fprintf(fd, "\n%s\n",S(h->desc));
+	}
+	
+	void endSwitch() {
+		fprintf(fd, ".PD\n");
+		fprintf(fd, "\n");
+	}
+};
+
+/*!
+  Create a man page outputter
+  \param fd A file description to output to
+*/
+Outputter * Outputter::man(FILE * fd) {
+  return new ManOutputter(fd);
+}

+ 119 - 0
src/image/outputter.cc

@@ -0,0 +1,119 @@
+/*
+ * File:   outputter.hh
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <commandlineparser_p.hh>
+
+/*!
+  \class Outputter
+  \brief Interface for classes used to output documentation
+*/
+
+/*!
+  \fn Outputter::beginSection(const QString & name)
+  Add a new section to the output
+  \param name The name of the section
+*/
+
+/*!
+  \fn Outputter::endSection()
+  End the current section
+*/
+
+/*!
+  \fn Outputter::beginParagraph()
+  Begin a text paragraph
+*/
+
+/*!
+  \fn Outputter::text(const QString & t)
+  Add some text to the current paragraph
+  \param t The text to add
+*/
+
+/*!
+  \fn Outputter::bold(const QString & t) =  0;
+  Add some bold text to the current paragraph
+  \param t The text to add
+*/
+
+/*!
+  \fn Outputter::italic(const QString & t)
+  Add some italic text tho the current paragraph
+  \param t The text to add
+*/
+
+/*!
+  \fn Outputter::link(const QString & l)
+  Add a hyperlink to somewhere
+  \param l The url to link to
+*/
+
+/*!
+  \fn Outputter::endParagraph()
+  End the current paragraph
+*/
+
+/*!
+  \fn Outputter::verbatim(const QString & t)
+  Add a pice of code or verbatime text
+  \param t The text to add
+*/
+
+/*!
+  \fn Outputter::beginList(bool ordered=false)
+  Begin a ordered or unordered listing
+  \param ordered Should the list be ordered
+*/
+
+/*!
+  \fn Outputter::endList()
+  End the current listing
+*/
+
+/*!
+  \fn Outputter::listItem(QString & t)
+  Add an item to the current listing
+  \param t The text to add
+*/
+
+/*!
+  \fn Outputter::beginSwitch()
+  Begin a section with command line switches
+*/
+
+	
+/*!
+  \fn Outputter::cswitch(const ArgHandler * h, bool doc)
+  Output a switch description
+  \param h The switch to add
+  \param doc Are we outputting to documentation
+*/
+
+/*!
+  \fn Outputter::endSwitch()
+  End a switch section
+*/
+
+
+/*!
+  Output a paragraph of simple text
+*/
+void Outputter::paragraph(const QString & t) {
+	beginParagraph();
+	text(t);
+	endParagraph();
+}

+ 105 - 0
src/image/pageloader.cc

@@ -0,0 +1,105 @@
+/* 
+ * File:   pageloader.cpp
+ * Author: Christian Sciberras
+ * 
+ * Created on 20 ta’ Mejju 2010, 00:21
+ */
+
+#include "pageloader.hh"
+
+#include <QObject>
+#include <QWebPage>
+#include <QWebFrame>
+#include <QUrl>
+#include <QImage>
+#include <QPainter>
+#include <QObject>
+#include <QEventLoop>
+#include <QFileInfo>
+#include <QDebug>
+
+void PageLoader::loaded(bool ok) {
+
+}
+
+PageLoader::PageLoader(Settings & s){
+	httpErrorCode=0;
+	settings=s;
+}
+
+PageLoader::~PageLoader() {
+}
+
+bool PageLoader::convert() {
+	// init error code
+	httpErrorCode=0;
+	// quickfix; if out is "-", set quiet to ON
+	if(settings.out=="-")settings.quiet=true;
+	// if fmt is empty try to get it from file extension in out
+	if(settings.fmt==""){
+		QFileInfo fi(settings.out);
+        settings.fmt = fi.suffix();
+	}
+	// check whether image format is supported (for writing)
+//	QImageWriter test;
+//	test.setFormat(settings.fmt);
+//	if(!test.canWrite()){
+//		if(!settings.quiet)printf("error: file format not supported\n");
+//		httpErrorCode=EFAULT;
+//		return false;
+//	}
+	// create webkit frame and load website
+	QWebPage page;
+	if(settings.in!="-"){
+		// get html from url/file
+		if(!settings.quiet)printf("loading from url...\n");
+		page.mainFrame()->load(settings.in);
+	}else{
+		// get html from stdin
+		// TODO: grab from stdin
+	}
+	// begin looping till loadFinished is encountered
+	QEventLoop loop;
+	QObject::connect(&page, SIGNAL(loadFinished(bool)), &loop, SLOT( quit( )));
+	loop.exec( );
+	// paint image
+	if(!settings.quiet)printf("downloading complete, converting...\n");
+	page.setViewportSize(page.mainFrame()->contentsSize());
+
+	
+	QImage image(page.viewportSize(), QImage::Format_ARGB32_Premultiplied);
+	QPainter painter(&image);
+	//painter.begin();
+	page.mainFrame()->render(&painter);
+	painter.end();
+	// perform filter(s)
+	if(settings.crop.width!=-1 && settings.crop.height!=-1){
+		if(!settings.quiet)printf("cropping...\n");
+		// note: the returned image object is a copy; is this a memleak? does c++ have a GC?
+		image=image.copy(settings.crop.left,settings.crop.top,settings.crop.width,settings.crop.height);
+	}
+	if(settings.scale.width!=-1 && settings.scale.height!=-1){
+		if(!settings.quiet)printf("scaling...\n");
+		// todo: perhaps get more user options to change aspect ration and scaling mode?
+		// note: the returned image object is a copy; is this a memleak? does c++ have a GC?
+		image=image.scaled(settings.scale.width,settings.scale.height,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
+	}
+	// output image
+	if(settings.out!="-"){
+		// save to file
+		if(!settings.quiet)printf("saving image...\n");
+		QByteArray ba=settings.fmt.toLatin1();
+		if(!image.save(QString(settings.out),ba.data(),-1)){
+			if(!settings.quiet)printf("error: couldn't save image\n");
+			httpErrorCode=402; //EACCES; // file could not be written
+			return false;
+		}else{
+			if(!settings.quiet)printf("finished.\n");
+			return true;
+		}
+	}else{
+		// save to stdout
+		// TODO: print to stdout
+	}
+	return false;
+}

+ 23 - 0
src/image/pageloader.hh

@@ -0,0 +1,23 @@
+/* 
+ * File:   pageloader.h
+ * Author: Christian Sciberras
+ *
+ * Created on 20 ta’ Mejju 2010, 00:21
+ */
+
+#include <QObject>
+#include <QWebPage>
+#include "settings.hh"
+
+class PageLoader: public QObject {
+	Q_OBJECT
+public:
+	PageLoader(Settings & s);
+	~PageLoader();
+	int httpErrorCode;
+	Settings settings;
+	bool convert();
+public slots:
+	void loaded(bool ok);
+};
+

+ 70 - 0
src/image/settings.cc

@@ -0,0 +1,70 @@
+/*
+ * File:   settings.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <settings.hh>
+
+/*!
+  Read proxy settings from a string, the grammar is described in the manual
+  \param proxy the proxy string to parse
+  \param ok If supplied indicates whether the proxy was valid
+*/
+Settings::ProxySettings Settings::strToProxy(const char * proxy, bool * ok) {
+	Settings::ProxySettings p;
+	if(ok) *ok=true;
+	//Allow users to use no proxy, even if one is specified in the env
+	if (!strcmp(proxy,"none")) {
+		p.host = "";
+		return p;
+	}
+	
+	p.type = QNetworkProxy::HttpProxy;
+	//Read proxy type bit "http://" or "socks5://"
+	if (!strncmp(proxy,"http://",7)) {
+		proxy += 7;
+	} else if (!strncmp(proxy,"socks5://",9)) {
+		p.type = QNetworkProxy::Socks5Proxy;
+		proxy += 9;
+	}
+
+	//Read username and password
+	char * val = (char *) strchr(proxy,'@');
+	p.user = p.password = "";
+	if (val != NULL) {
+		p.user = QString(proxy).left(val-proxy);
+		proxy = val+1;
+		
+		int idx = p.user.indexOf(':');
+		if(idx != -1) {
+			p.password = p.user.mid(idx+1);
+			p.user = p.user.left(idx);
+		}
+	}
+
+ 	//Read hostname and port
+ 	val = (char *) strchr(proxy,':');
+ 	p.port = 1080; //Default proxy port
+ 	if (val == NULL) p.host = proxy;
+ 	else {
+		p.port = QString(val+1).toInt(ok);
+		if(p.port < 0 || p.port > 65535) {
+			p.port = 1080;
+			*ok = false;
+		}
+		p.host = QString(proxy).left(val-proxy);
+ 	}
+	if(ok && p.host.size() == 0) *ok = false;
+	return p;
+}

+ 130 - 0
src/image/settings.hh

@@ -0,0 +1,130 @@
+/*
+ * File:   convert.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SETTINGS_HH__
+#define __SETTINGS_HH__
+#include <QString>
+#include <qnetworkproxy.h>
+#include <QPrinter>
+
+/*! \brief Class holding all user settings.
+
+    This class holds all the user settings, settings can be filled in by hand,
+    or with other methods. 
+    \sa CommandLineParser::parse()
+*/
+struct Settings {
+	/*! \brief Settings for proxy */
+	struct ProxySettings {
+		//! Type of proxy to use
+		QNetworkProxy::ProxyType type; 
+		//! The port of the proxy to use
+		int port; 
+		//! The host name of the proxy to use or NULL
+		QString host; 
+		//! Username for the said proxy or NULL
+		QString user; 
+		//! Password for the said proxy or NULL
+		QString password; 
+	};
+
+	// @dep: what is this for?
+	struct PostItem {
+		QString name;
+		QString value;
+		bool file;
+	};
+
+	/*! \brief Settings for cropping image */
+	struct CropSettings {
+		//! Cropping left/x coord
+		int left;
+		//! Cropping top/y coord
+		int top;
+		//! Cropping width/w dime
+		int width;
+		//! Cropping height/h dime
+		int height;
+	};
+
+	/*! \brief Settings for scaling image */
+	struct ScaleSettings {
+		//! Scale width/w dime
+		int width;
+		//! Scale height/h dime
+		int height;
+	};
+	
+	//! Proxy related settings
+	ProxySettings proxy;
+	//! Crop related settings
+	CropSettings crop;
+	//! Scale related settings
+	ScaleSettings scale;
+
+	//! Username used for http auth login
+	QString username;
+	//! Password used for http auth login
+	QString password;
+	//! Be less verbose
+	bool quiet; 
+	//! Should we print background images
+	bool background;
+	//! Should plugins be allowed
+	bool enablePlugins;
+	//! Should we use the graphics system
+	bool useGraphics;
+	//! Should we enable Java Script
+	bool enableJavascript; 
+	//! Should the horrible intelligent shrking feature be enabled?
+	bool enableIntelligentShrinking;
+	//! How many milliseconds should we wait for a javascrit redirect
+	int jsredirectwait;
+	//! Color or grayscale
+	QPrinter::ColorMode colorMode;
+	//! Minimum font size
+	int minimumFontSize;
+	//! Encoding used to enterpit a document which doesn't supply encoding
+	QString defaultEncoding;
+	//! Stylesheet supplied by the user
+	QString userStyleSheet;
+	//! The file/url for input
+	QString in;
+	//! The file for output
+	QString out;
+	//! The output format
+	QString fmt;
+	//! Map of custum header valiabels
+	QList< QPair<QString, QString> > customHeaders;
+	//! Map of cookies
+	QList< QPair<QString, QString> > cookies;
+	//! Replacements
+	QList< QPair<QString, QString> > replacements;
+	//! Path of the cookie jar file
+	QString cookieJar;
+	
+	QList< PostItem > post;
+	bool stopSlowScripts;
+	bool debugJavascript;
+	bool blockLocalFileAccess;
+	QList< QString > allowed;
+	bool produceForms;
+
+	static ProxySettings strToProxy(const char * s, bool * ok=0);
+};
+
+#endif //__SETTINGS_HH__

+ 177 - 0
src/image/textoutputter.cc

@@ -0,0 +1,177 @@
+/*
+ * File:   textoutputter.cc
+ * Author: Christian Sciberras
+ * Created: 20 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser_p.hh"
+#include <qstringlist.h>
+
+#define S(t) (doc?(t).toUtf8().constData():(t).toLocal8Bit().constData())
+
+class TextOutputter: public Outputter {
+public:
+	FILE * fd;
+	static const int lw = 80;
+	int w;
+	bool doc;
+	bool extended;
+	bool first;
+	int order;
+	TextOutputter(FILE * _, bool d, bool e): fd(_), doc(d), extended(e) {}
+
+	void beginSection(const QString & name) {
+		if(doc) {
+			int x= 80 - name.size() - 4;
+			if(x < 6) x = 60;
+			for(int i=0; i < x/2; ++i) 
+				fprintf(fd, "=");
+			fprintf(fd, "> %s <", S(name) );
+			for(int i=0; i < (x+1)/2; ++i) 
+				fprintf(fd, "=");
+			fprintf(fd, "\n");
+		} else 
+			fprintf(fd, "%s:\n", S(name) );
+	}
+	
+	void endSection() {
+	}
+
+	void beginParagraph() {
+		first=true;
+		if(doc) {
+			w=0;
+		} else {
+			w=2;
+			fprintf(fd,"  ");
+		}
+	}
+
+	void text(const QString & t) {
+		first=true;
+		QStringList list = t.split(" ");
+		foreach(const QString & s, list) {
+			if( w + s.size() + (first?0:1) > lw) {
+				fprintf(fd, "\n");
+				if(doc) {
+					w=0;
+				} else {
+					w=2;
+					fprintf(fd,"  ");
+				}
+				first=true;
+			}
+			if(first) first=false;
+			else {
+				fprintf(fd, " ");
+				++w;
+			}
+			w += s.size();
+			fprintf(fd, "%s", S(s));
+		}
+	}
+	
+	void bold(const QString & t) {
+		text("*"+t+"*");
+	}
+	
+	void italic(const QString & t) {
+		text("_"+t+"_");
+	}
+	
+	void link(const QString & t) {
+		text("<"+t+">");
+	}
+
+	void endParagraph() {
+		fprintf(fd,"\n\n");
+	}
+
+	void verbatim(const QString & t) {
+		if(doc)
+			fprintf(fd,"%s\n", S(t));
+		else {
+			foreach(const QString & s, t.split("\n"))
+				fprintf(fd,"  %s\n",S(s));
+		}
+	}
+
+	void beginList(bool ordered) {
+		order=ordered?1:-1;
+	}
+	void endList() {
+		fprintf(fd,"\n");
+	}
+	void listItem(const QString & s) {
+		if (order < 0) fprintf(fd, " * ");
+		else fprintf(fd, "%3d ", order++);
+		fprintf(fd,"%s\n",S(s));
+	}
+	
+	void beginSwitch() {}
+
+	void cswitch(const ArgHandler * h) {
+		w=0;
+		if(!doc) {fprintf(fd,"  "); w=2;}
+		if(h->shortSwitch != 0)
+			fprintf(fd,"-%c, ",h->shortSwitch);
+		else
+			fprintf(fd,"    ");
+		fprintf(fd,"--%s",S(h->longName));
+		w+=4 + 2 + h->longName.size();
+		if (doc && h->qthack) { 
+			fprintf(fd, " *");
+			w += 2;
+		}
+				
+		foreach(const QString & arg, h->argn) {
+			fprintf(fd," <%s>",S(arg));
+			w+=3+arg.size();
+		}
+		while(w < 37) {
+			fprintf(fd," ");
+			++w;
+		}
+		foreach(const QString & s, h->getDesc().split(" ")) {
+			if(w+1+s.size() > lw) {
+				printf("\n");
+				w=0;
+				while(w < 37) {
+					fprintf(fd," ");
+					++w;
+				}
+			}
+			fprintf(fd, " %s", S(s));
+			w += s.size() + 1;
+		}
+		fprintf(fd,"\n");
+	}
+
+	void endSwitch() {
+		if (doc)
+			fprintf(fd, "\nItems marked * are only available using patched QT.\n");
+		printf("\n");
+	}		
+	
+};
+
+/*!
+  Create a raw text outputter, used for outputting --help and readme
+  \param fd A file description to output to
+  \param doc Ouput in readme format
+  \param extended Output extended options
+*/
+Outputter * Outputter::text(FILE * fd, bool doc, bool extended) {
+	return new TextOutputter(fd, doc, extended);
+}

+ 122 - 0
src/image/utilities.cc

@@ -0,0 +1,122 @@
+/*
+ * File:   main.cpp
+ * Author: Christian Sciberras
+ *
+ * Created on 18 ta’ Mejju 2010, 20:43
+ */
+
+#include <QCleanlooksStyle>
+#include <QCommonStyle>
+#include <QPainter>
+#include <QStyleOption>
+#include <QUrl>
+#include <QFile>
+#include <QFileInfo>
+#include <QImageWriter>
+
+/**
+ * Custom simplistic style, borrowed from WKHTMLTOPDF
+ */
+class MyLooksStyle: public QCleanlooksStyle {
+public:
+	Settings & settings;
+
+	typedef QCleanlooksStyle parent_t;
+
+	MyLooksStyle(Settings & s): settings(s) {}
+
+	void drawPrimitive( PrimitiveElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget = 0 ) const {
+		painter->setBrush(Qt::white);
+		painter->setPen(QPen(Qt::black, 0.7));
+		QRect r = option->rect;
+		if (element == QStyle::PE_PanelLineEdit) {
+			painter->drawRect(r);
+		} else if(element == QStyle::PE_IndicatorCheckBox) {
+			painter->drawRect(r);
+			if (!settings.produceForms && (option->state & QStyle::State_On)) {
+				r.translate(int(r.width()*0.075), int(r.width()*0.075));
+				painter->drawLine(r.topLeft(), r.bottomRight());
+				painter->drawLine(r.topRight(), r.bottomLeft());
+			}
+		} else if(element == QStyle::PE_IndicatorRadioButton) {
+			painter->drawEllipse(r);
+			if (!settings.produceForms && (option->state & QStyle::State_On)) {
+				r.translate(int(r.width()*0.20), int(r.width()*0.20));
+				r.setWidth(int(r.width()*0.70));
+				r.setHeight(int(r.height()*0.70));
+				painter->setBrush(Qt::black);
+				painter->drawEllipse(r);
+			}
+		} else {
+			parent_t::drawPrimitive(element, option, painter, widget);
+		}
+	}
+};
+
+/*!
+  \brief Guess a url, by looking at a string
+  (shamelessly copied from Arora Project)
+  \param string The string the is suppose to be some kind of url
+*/
+QUrl guessUrlFromString(const QString &string) {
+	QString urlStr = string.trimmed();
+
+	// check if the string is just a host with a port
+	QRegExp hostWithPort(QLatin1String("^[a-zA-Z\\.]+\\:[0-9]*$"));
+	if (hostWithPort.exactMatch(urlStr))
+		urlStr = QLatin1String("http://") + urlStr;
+
+	// Check if it looks like a qualified URL. Try parsing it and see.
+	QRegExp test(QLatin1String("^[a-zA-Z]+\\:.*"));
+	bool hasSchema = test.exactMatch(urlStr);
+	if (hasSchema) {
+		bool isAscii = true;
+		foreach (const QChar &c, urlStr) {
+			if (c >= 0x80) {
+				isAscii = false;
+				break;
+			}
+		}
+
+		QUrl url;
+		if (isAscii) {
+			url = QUrl::fromEncoded(urlStr.toAscii(), QUrl::TolerantMode);
+		} else {
+			url = QUrl(urlStr, QUrl::TolerantMode);
+		}
+		if (url.isValid())
+			return url;
+	}
+
+	// Might be a file.
+	if (QFile::exists(urlStr)) {
+		QFileInfo info(urlStr);
+		return QUrl::fromLocalFile(info.absoluteFilePath());
+	}
+
+	// Might be a shorturl - try to detect the schema.
+	if (!hasSchema) {
+		int dotIndex = urlStr.indexOf(QLatin1Char('.'));
+		if (dotIndex != -1) {
+			QString prefix = urlStr.left(dotIndex).toLower();
+			QString schema = (prefix == QLatin1String("ftp")) ? prefix : QLatin1String("http");
+			QUrl url(schema + QLatin1String("://") + urlStr, QUrl::TolerantMode);
+			if (url.isValid())
+				return url;
+		}
+	}
+
+	// Fall back to QUrl's own tolerant parser.
+	QUrl url = QUrl(string, QUrl::TolerantMode);
+
+	// finally for cases where the user just types in a hostname add http
+	if (url.scheme().isEmpty())
+		url = QUrl(QLatin1String("http://") + string, QUrl::TolerantMode);
+	return url;
+}
+
+void printSupportedWriteformats(){
+	QList<QByteArray> formats = QImageWriter::supportedImageFormats();
+	for ( QList<QByteArray>::Iterator f = formats.begin(); f != formats.end(); ++ f )
+	printf("%s , ", f->constData() );
+}

+ 57 - 0
src/image/wkhtmltoimage.cc

@@ -0,0 +1,57 @@
+																													/*
+ * File:   wkhtmltoimage.cc
+ * Author: Christian Sciberras
+ * Created: 18 May 2010
+ *   This file is part of wkhtmltoimage.
+ *   wkhtmltoimage 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 3 of the License, or
+ *   (at your option) any later version.
+ *   wkhtmltoimage 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.
+ *   You should have received a copy of the GNU General Public License
+ *   along with wkhtmltoimage.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "commandlineparser.hh"
+#include "settings.hh"
+#include "utilities.cc"
+#include "pageloader.hh"
+#include <QApplication>
+
+int main(int argc, char** argv) {
+	//This will store all our settings
+	Settings settings;
+	//Create a command line parser to parse commandline arguments
+	CommandLineParser parser(settings);
+	//Setup default values in settings
+	parser.loadDefaults();
+	//Parse the arguments
+	parser.parseArguments(argc, (const char**)argv);
+
+	//Construct QApplication required for printing
+	QApplication a( argc, argv );
+	a.setStyle(new MyLooksStyle(settings));
+
+	//Create the actual page converter to convert the pages
+	PageLoader converter(settings);
+
+	if (!converter.convert()) return EXIT_FAILURE;
+
+	switch(converter.httpErrorCode) {
+
+		case 401:
+			return 3;
+
+		case 404:
+			return 2;
+
+		case 0:
+			return EXIT_SUCCESS;
+
+		default:
+			return EXIT_FAILURE;
+	}
+}

+ 0 - 0
src/arguments.cc → src/pdf/arguments.cc


+ 0 - 0
src/commandlineparser.cc → src/pdf/commandlineparser.cc


+ 0 - 0
src/commandlineparser.hh → src/pdf/commandlineparser.hh


+ 0 - 0
src/commandlineparser_p.hh → src/pdf/commandlineparser_p.hh


+ 0 - 0
src/docparts.cc → src/pdf/docparts.cc


+ 0 - 0
src/htmloutputter.cc → src/pdf/htmloutputter.cc


+ 0 - 0
src/manoutputter.cc → src/pdf/manoutputter.cc


+ 0 - 0
src/multipageloader.cc → src/pdf/multipageloader.cc


+ 0 - 0
src/multipageloader.hh → src/pdf/multipageloader.hh


+ 0 - 0
src/multipageloader_p.hh → src/pdf/multipageloader_p.hh


+ 0 - 0
src/outline.cc → src/pdf/outline.cc


+ 0 - 0
src/outline.hh → src/pdf/outline.hh


+ 0 - 0
src/outline_p.hh → src/pdf/outline_p.hh


+ 0 - 0
src/outputter.cc → src/pdf/outputter.cc


+ 0 - 0
src/pageconverter.cc → src/pdf/pageconverter.cc


+ 0 - 0
src/pageconverter.hh → src/pdf/pageconverter.hh


+ 0 - 0
src/pageconverter_p.hh → src/pdf/pageconverter_p.hh


BIN
src/pdf/pdf


+ 46 - 0
src/pdf/pdf.pro

@@ -0,0 +1,46 @@
+include(../../common.pri)
+
+TEMPLATE = app
+DESTDIR = ../../bin
+TARGET = wkhtmltopdf
+DEPENDPATH += . src
+INCLUDEPATH += . src
+
+readme.target=README
+readme.commands=./wkhtmltopdf --readme > README
+readme.depends=wkhtmltopdf
+
+QMAKE_EXTRA_TARGETS += readme
+
+unix {
+    man.target=wkhtmltopdf.1.gz
+    man.commands=./wkhtmltopdf --manpage | gzip > $@
+    man.depends=wkhtmltopdf
+
+    manins.target=manins
+    manins.depends=man
+    manins.files=wkhtmltopdf.1.gz
+    manins.path=$$INSTALLBASE/share/man/man1
+
+    QMAKE_EXTRA_TARGETS += manins man
+    INSTALLS += manins
+}
+
+INSTALLS += target
+target.path=$$INSTALLBASE/bin
+
+#Libaray part
+HEADERS += pageconverter.hh pageconverter_p.hh \
+           multipageloader_p.hh multipageloader.hh
+
+SOURCES += tempfile.cc settings.cc pageconverter.cc \
+           multipageloader.cc outline.cc tocstylesheet.cc
+
+#Application part
+
+HEADERS += progressfeedback.hh
+
+SOURCES += wkhtmltopdf.cc arguments.cc commandlineparser.cc \
+           docparts.cc outputter.cc manoutputter.cc \
+           htmloutputter.cc textoutputter.cc progressfeedback.cc
+           

+ 0 - 0
src/progressfeedback.cc → src/pdf/progressfeedback.cc


+ 0 - 0
src/progressfeedback.hh → src/pdf/progressfeedback.hh


+ 0 - 0
src/settings.cc → src/pdf/settings.cc


+ 0 - 0
src/settings.hh → src/pdf/settings.hh


+ 0 - 0
src/tempfile.cc → src/pdf/tempfile.cc


+ 0 - 0
src/tempfile.hh → src/pdf/tempfile.hh


+ 0 - 0
src/textoutputter.cc → src/pdf/textoutputter.cc


+ 0 - 0
src/tocprinter.cc → src/pdf/tocprinter.cc


+ 0 - 0
src/tocprinter.hh → src/pdf/tocprinter.hh


+ 0 - 0
src/tocstylesheet.cc → src/pdf/tocstylesheet.cc


+ 0 - 0
src/wkhtmltopdf.cc → src/pdf/wkhtmltopdf.cc


+ 4 - 67
wkhtmltopdf.pro

@@ -13,71 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with wkhtmltopdf.  If not, see <http:#www.gnu.org/licenses/>.
 
-DEFINES += MAJOR_VERSION=0 MINOR_VERSION=9 PATCH_VERSION=9 BUILD=""
+# src/shared /src/image
+TEMPLATE = subdirs
 
-TEMP = $$[QT_INSTALL_LIBS] libQtGui.prl
-PRL  = $$[QT_INSTALL_LIBS] QtGui.framework/QtGui.prl
-include($$join(TEMP, "/"))
-include($$join(PRL, "/"))
-
-contains(QMAKE_PRL_CONFIG, shared) {
-    DEFINES += QT_SHARED
-} else {
-    DEFINES += QT_STATIC
-    QTPLUGIN += qjpeg qgif qtiff qmng
-}
-
-TEMPLATE = app
-TARGET = 
-DEPENDPATH += . src
-INCLUDEPATH += . src
-
-MOC_DIR = build
-OBJECTS_DIR = build
-UI_DIR = build
-
-readme.target=README
-readme.commands=./wkhtmltopdf --readme > README
-readme.depends=wkhtmltopdf
-
-QMAKE_EXTRA_TARGETS += readme
-
-unix {
-    man.target=wkhtmltopdf.1.gz
-    man.commands=./wkhtmltopdf --manpage | gzip > $@
-    man.depends=wkhtmltopdf
-
-    manins.target=manins
-    manins.depends=man
-    manins.files=wkhtmltopdf.1.gz
-    manins.path=$$INSTALLBASE/share/man/man1
-
-    QMAKE_EXTRA_TARGETS += manins man
-    INSTALLS += manins
-}
-
-
-win32 {
-    CONFIG += console
-}
-
-INSTALLS += target
-target.path=$$INSTALLBASE/bin
-
-QT += webkit network xmlpatterns
-
-#Libaray part
-HEADERS += src/pageconverter.hh src/pageconverter_p.hh \
-           src/multipageloader_p.hh src/multipageloader.hh
-
-SOURCES += src/tempfile.cc src/settings.cc src/pageconverter.cc \
-           src/multipageloader.cc src/outline.cc src/tocstylesheet.cc
-
-#Application part
-
-HEADERS += src/progressfeedback.hh
-
-SOURCES += src/wkhtmltopdf.cc src/arguments.cc src/commandlineparser.cc \
-           src/docparts.cc src/outputter.cc src/manoutputter.cc \
-           src/htmloutputter.cc src/textoutputter.cc src/progressfeedback.cc
-           
+CONFIG += ordered
+SUBDIRS = src/pdf src/image