From fa25e816a792a6e5dbac8cc32235eba9a3c51af2 Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Mon, 28 Sep 2020 21:58:28 -0700 Subject: [PATCH] moved old folder to separate repo --- old/README | 9 - old/picidae.py | 392 ------------------- old/webkit2png.py | 506 ------------------------- old/webrender.py | 212 ----------- old/wrp.py | 931 ---------------------------------------------- 5 files changed, 2050 deletions(-) delete mode 100644 old/README delete mode 100644 old/picidae.py delete mode 100644 old/webkit2png.py delete mode 100644 old/webrender.py delete mode 100644 old/wrp.py diff --git a/old/README b/old/README deleted file mode 100644 index 5f5bdad..0000000 --- a/old/README +++ /dev/null @@ -1,9 +0,0 @@ -Historical versions of WRP and prior art - -License: GNU - -Copyright (c) 2013-2018 Antoni Sawicki -Copyright (c) 2012-2013 picidae.net -Copyright (c) 2004-2013 Paul Hammond -Copyright (c) 2017-2018 Natalia Portillo -Copyright (c) 2018 //gir.st/ \ No newline at end of file diff --git a/old/picidae.py b/old/picidae.py deleted file mode 100644 index 3ddbd10..0000000 --- a/old/picidae.py +++ /dev/null @@ -1,392 +0,0 @@ -#!/usr/bin/env python - -# picidae.py - makes screenshots of webpages -# and analyzes the webpage structure and writes image-maps of the links -# as well as forms that are placed on the exact position of the old form. -# It is a part of the art project www.picidae.net -# http://www.picidae.net - -# -# This script is based on webkit2png from Paul Hammond. -# It was extended by picidae.net -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -__version__ = "1.0" - - -import sys - - -#print "hello ... " - - -try: - import Foundation - import WebKit - import AppKit - import objc - import urllib -except ImportError: - print "Cannot find pyobjc library files. Are you sure it is installed?" - sys.exit() - - - - - -#try: -# from optparse import OptionParser -#except ImportError: -# print "OptionParser not imported" -# sys.exit() - -from optparse import OptionParser - - -class AppDelegate (Foundation.NSObject): - # what happens when the app starts up - def applicationDidFinishLaunching_(self, aNotification): - webview = aNotification.object().windows()[0].contentView() - webview.frameLoadDelegate().getURL(webview) - - -class WebkitLoad (Foundation.NSObject, WebKit.protocols.WebFrameLoadDelegate): - # what happens if something goes wrong while loading - def webView_didFailLoadWithError_forFrame_(self,webview,error,frame): - print " ... something went wrong 1" - self.getURL(webview) - def webView_didFailProvisionalLoadWithError_forFrame_(self,webview,error,frame): - print " ... something went wrong 2" - self.getURL(webview) - - def makeFilename(self,URL,options): - # make the filename - if options.filename: - filename = options.filename - elif options.md5: - try: - import md5 - except ImportError: - print "--md5 requires python md5 library" - AppKit.NSApplication.sharedApplication().terminate_(None) - filename = md5.new(URL).hexdigest() - else: - import re - filename = re.sub('\W','',URL); - filename = re.sub('^http','',filename); - if options.datestamp: - import time - now = time.strftime("%Y%m%d") - filename = now + "-" + filename - import os - dir = os.path.abspath(os.path.expanduser(options.dir)) - return os.path.join(dir,filename) - - def saveImages(self,bitmapdata,filename,options): - # save the fullsize png - if options.fullsize: - bitmapdata.representationUsingType_properties_(AppKit.NSPNGFileType,None).writeToFile_atomically_(filename + ".png",objc.YES) - - if options.thumb or options.clipped: - # work out how big the thumbnail is - width = bitmapdata.pixelsWide() - height = bitmapdata.pixelsHigh() - thumbWidth = (width * options.scale) - thumbHeight = (height * options.scale) - - # make the thumbnails in a scratch image - scratch = AppKit.NSImage.alloc().initWithSize_( - Foundation.NSMakeSize(thumbWidth,thumbHeight)) - scratch.lockFocus() - AppKit.NSGraphicsContext.currentContext().setImageInterpolation_( - AppKit.NSImageInterpolationHigh) - thumbRect = Foundation.NSMakeRect(0.0, 0.0, thumbWidth, thumbHeight) - clipRect = Foundation.NSMakeRect(0.0, - thumbHeight-options.clipheight, - options.clipwidth, options.clipheight) - bitmapdata.drawInRect_(thumbRect) - thumbOutput = AppKit.NSBitmapImageRep.alloc().initWithFocusedViewRect_(thumbRect) - clipOutput = AppKit.NSBitmapImageRep.alloc().initWithFocusedViewRect_(clipRect) - scratch.unlockFocus() - - # save the thumbnails as pngs - if options.thumb: - thumbOutput.representationUsingType_properties_( - AppKit.NSPNGFileType,None - ).writeToFile_atomically_(filename + "-thumb.png",objc.YES) - if options.clipped: - clipOutput.representationUsingType_properties_( - AppKit.NSPNGFileType,None - ).writeToFile_atomically_(filename + "-clipped.png",objc.YES) - - def getURL(self,webview): - if self.urls: - if self.urls[0] == '-': - url = sys.stdin.readline().rstrip() - if not url: AppKit.NSApplication.sharedApplication().terminate_(None) - else: - url = self.urls.pop(0) - else: - AppKit.NSApplication.sharedApplication().terminate_(None) - #print "", url, "..." - #print "" % (url) - self.resetWebview(webview) - webview.mainFrame().loadRequest_(Foundation.NSURLRequest.requestWithURL_(Foundation.NSURL.URLWithString_(url))) - if not webview.mainFrame().provisionalDataSource(): - print "" - self.getURL(webview) - - def resetWebview(self,webview): - rect = Foundation.NSMakeRect(0,0,self.options.initWidth,self.options.initHeight) - webview.window().setContentSize_((self.options.initWidth,self.options.initHeight)) - webview.setFrame_(rect) - - def resizeWebview(self,view): - view.window().display() - view.window().setContentSize_(view.bounds().size) - view.setFrame_(view.bounds()) - - def captureView(self,view): - view.lockFocus() - bitmapdata = AppKit.NSBitmapImageRep.alloc() - bitmapdata.initWithFocusedViewRect_(view.bounds()) - view.unlockFocus() - return bitmapdata - - # what happens when the page has finished loading - def webView_didFinishLoadForFrame_(self,webview,frame): - # don't care about subframes - if (frame == webview.mainFrame()): - view = frame.frameView().documentView() - - self.resizeWebview(view) - - URL = frame.dataSource().initialRequest().URL().absoluteString() - filename = self.makeFilename(URL, self.options) - - bitmapdata = self.captureView(view) - self.saveImages(bitmapdata,filename,self.options) - - # ---------------------------------- - # picidae my stuff - - - #print "url" - print "" - print frame.dataSource().request().URL().absoluteString() - print "" - - - # Analyse HTML and get links - xmloutput = "\r"; - - domdocument = frame.DOMDocument() - domnodelist = domdocument.getElementsByTagName_('A') - i = 0 - while i < domnodelist.length(): - # linkvalue - value = domnodelist.item_(i).valueForKey_('href') - - # position-rect - myrect = domnodelist.item_(i).boundingBox() - - xmin = Foundation.NSMinX(myrect) - ymin = Foundation.NSMinY(myrect) - xmax = Foundation.NSMaxX(myrect) - ymax = Foundation.NSMaxY(myrect) - - # print Link - prefix = "" - xmloutput += "\"\"\r" % (xmin, ymin, xmax, ymax, prefix, value) - i += 1 - - #print "" - xmloutput += "" - f = open(filename +'.xml', 'w+') - f.write(xmloutput) - f.close() - - # ---------------------------------- - # get forms - xmloutput = "\r"; - xmloutput += "\r" - - domdocument = frame.DOMDocument() - domnodelist = domdocument.getElementsByTagName_('form') - i = 0 - while i < domnodelist.length(): - # form - action = domnodelist.item_(i).valueForKey_('action') - method = domnodelist.item_(i).valueForKey_('method') - xmloutput += "
\r" % (method, action) - - # form fields - fieldlist = domnodelist.item_(i).getElementsByTagName_('input') - j=0 - while j < fieldlist.length(): - # values - type = fieldlist.item_(j).valueForKey_('type') - name = fieldlist.item_(j).valueForKey_('name') - formvalue = fieldlist.item_(j).valueForKey_('value') - size = fieldlist.item_(j).valueForKey_('size') - checked = fieldlist.item_(j).valueForKey_('checked') - # write output - xmloutput += "\toptions.initWidth: - options.initWidth = options.width - if options.height>options.initHeight: - options.initHeight = options.height - - - app = AppKit.NSApplication.sharedApplication() - - # create an app delegate - delegate = AppDelegate.alloc().init() - AppKit.NSApp().setDelegate_(delegate) - - # create a window - rect = Foundation.NSMakeRect(-16000,-16000,100,100) - win = AppKit.NSWindow.alloc() - win.initWithContentRect_styleMask_backing_defer_ (rect, - AppKit.NSBorderlessWindowMask, 2, 0) - - # create a webview object - webview = WebKit.WebView.alloc() - webview.initWithFrame_(rect) - # turn off scrolling so the content is actually x wide and not x-15 - webview.mainFrame().frameView().setAllowsScrolling_(objc.NO) - # add the webview to the window - win.setContentView_(webview) - - - # create a LoadDelegate - loaddelegate = WebkitLoad.alloc().init() - loaddelegate.options = options - loaddelegate.urls = args - webview.setFrameLoadDelegate_(loaddelegate) - - app.run() - -if __name__ == '__main__' : main() - diff --git a/old/webkit2png.py b/old/webkit2png.py deleted file mode 100644 index 7241be2..0000000 --- a/old/webkit2png.py +++ /dev/null @@ -1,506 +0,0 @@ -#!/usr/bin/python - -# webkit2png - makes screenshots of web pages -# http://www.paulhammond.org/webkit2png - -__version__ = "dev" - -# Copyright (c) 2004-2013 Paul Hammond -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -import sys -import optparse -import re -import os - -try: - import Foundation - import WebKit - import AppKit - import Quartz - import objc -except ImportError: - print "Cannot find pyobjc library files. Are you sure it is installed?" - sys.exit() - - -class AppDelegate(Foundation.NSObject): - # what happens when the app starts up - def applicationDidFinishLaunching_(self, aNotification): - webview = aNotification.object().windows()[0].contentView() - webview.frameLoadDelegate().getURL(webview) - self.performSelector_withObject_afterDelay_("timeout:", None, - self.timeout) - - def timeout_(self, obj): - Foundation.NSLog("timed out!") - AppKit.NSApplication.sharedApplication().terminate_(None) - - -class Webkit2PngScriptBridge(Foundation.NSObject): - def init(self): - self = super(Webkit2PngScriptBridge, self).init() - self.is_stopped = False - self.start_callback = False - return self - - def stop(self): - self.is_stopped = True - - def start(self): - self.is_stopped = False - self.start_callback() - - def isSelectorExcludedFromWebScript_(self, sel): - if sel in ['stop', 'start']: - return False - else: - return True - - -class WebkitLoad (Foundation.NSObject, WebKit.protocols.WebFrameLoadDelegate): - - # what happens if something goes wrong while loading - def webView_didFailLoadWithError_forFrame_(self, webview, error, frame): - if error.code() == Foundation.NSURLErrorCancelled: - return - print " ... something went wrong: "+error.localizedDescription() - self.getURL(webview) - - def webView_didFailProvisionalLoadWithError_forFrame_(self, webview, error, - frame): - if error.code() == Foundation.NSURLErrorCancelled: - return - print " ... something went wrong: "+error.localizedDescription() - self.getURL(webview) - - def makeFilename(self, URL, options): - # make the filename - if options.filename: - filename = options.filename - elif options.md5: - try: - import md5 - except ImportError: - print "--md5 requires python md5 library" - AppKit.NSApplication.sharedApplication().terminate_(None) - filename = md5.new(URL).hexdigest() - else: - filename = re.sub('^https?', '', URL) - filename = re.sub('\W', '', filename) - if options.datestamp: - import time - now = time.strftime("%Y%m%d") - filename = now + "-" + filename - dir = os.path.abspath(os.path.expanduser(options.dir)) - if not os.path.exists(options.dir): - os.makedirs(dir) - return os.path.join(dir, filename) - - def saveImages(self, bitmapdata, filename, options): - # save the fullsize png - if options.fullsize: - bitmapdata.representationUsingType_properties_( - AppKit.NSPNGFileType, - None - ).writeToFile_atomically_(filename + "-full.png", objc.YES) - - if options.thumb or options.clipped: - # work out how big the thumbnail is - width = bitmapdata.pixelsWide() - height = bitmapdata.pixelsHigh() - thumbWidth = (width * options.scale) - thumbHeight = (height * options.scale) - - # make the thumbnails in a scratch image - scratch = AppKit.NSImage.alloc().initWithSize_( - Foundation.NSMakeSize(thumbWidth, thumbHeight)) - scratch.lockFocus() - AppKit.NSGraphicsContext.currentContext().setImageInterpolation_( - AppKit.NSImageInterpolationHigh) - thumbRect = Foundation.NSMakeRect(0.0, 0.0, thumbWidth, - thumbHeight) - clipRect = Foundation.NSMakeRect( - 0.0, - thumbHeight-options.clipheight, - options.clipwidth, - options.clipheight) - bitmapdata.drawInRect_(thumbRect) - thumbOutput = AppKit.NSBitmapImageRep.alloc()\ - .initWithFocusedViewRect_(thumbRect) - clipOutput = AppKit.NSBitmapImageRep.alloc()\ - .initWithFocusedViewRect_(clipRect) - scratch.unlockFocus() - - # save the thumbnails as pngs - if options.thumb: - thumbOutput.representationUsingType_properties_( - AppKit.NSPNGFileType, None).writeToFile_atomically_( - filename + "-thumb.png", objc.YES) - if options.clipped: - clipOutput.representationUsingType_properties_( - AppKit.NSPNGFileType, None).writeToFile_atomically_( - filename + "-clipped.png", objc.YES) - - def getURL(self, webview): - if self.urls: - if self.urls[0] == '-': - url = sys.stdin.readline().rstrip() - if not url: - AppKit.NSApplication.sharedApplication().terminate_(None) - else: - url = self.urls.pop(0) - else: - AppKit.NSApplication.sharedApplication().terminate_(None) - - nsurl = Foundation.NSURL.URLWithString_(url) - if not (nsurl and nsurl.scheme()): - nsurl = Foundation.NSURL.alloc().initFileURLWithPath_(url) - nsurl = nsurl.absoluteURL() - - if self.options.ignore_ssl_check: - Foundation.NSURLRequest.setAllowsAnyHTTPSCertificate_forHost_(objc.YES, nsurl.host()) - - print "Fetching", nsurl, "..." - self.resetWebview(webview) - scriptobject = webview.windowScriptObject() - scriptobject.setValue_forKey_(Webkit2PngScriptBridge.alloc().init(), - 'webkit2png') - - webview.mainFrame().loadRequest_(Foundation.NSURLRequest.requestWithURL_(nsurl)) - if not webview.mainFrame().provisionalDataSource(): - print " ... not a proper url?" - self.getURL(webview) - - def resetWebview(self, webview): - rect = Foundation.NSMakeRect(0, 0, self.options.initWidth, - self.options.initHeight) - window = webview.window() - window.setContentSize_((self.options.initWidth, - self.options.initHeight)) - - if self.options.transparent: - window.setOpaque_(objc.NO) - window.setBackgroundColor_(AppKit.NSColor.clearColor()) - webview.setDrawsBackground_(objc.NO) - - webview.setFrame_(rect) - - def captureView(self, view): - bounds = view.bounds() - if bounds.size.height > self.options.UNSAFE_max_height: - print >> sys.stderr, "Error: page height greater than %s, " \ - "clipping to avoid crashing windowserver." % \ - self.options.UNSAFE_max_height - bounds.size.height = self.options.UNSAFE_max_height - if bounds.size.width > self.options.UNSAFE_max_width: - print >> sys.stderr, "Error: page width greater than %s, " \ - "clipping to avoid crashing windowserver." % \ - self.options.UNSAFE_max_width - bounds.size.width = self.options.UNSAFE_max_width - - view.window().display() - view.window().setContentSize_( - Foundation.NSSize(self.options.initWidth, self.options.initHeight)) - view.setFrame_(bounds) - - if hasattr(view, "bitmapImageRepForCachingDisplayInRect_"): - bitmapdata = view.bitmapImageRepForCachingDisplayInRect_(bounds) - view.cacheDisplayInRect_toBitmapImageRep_(bounds, bitmapdata) - else: - view.lockFocus() - bitmapdata = AppKit.NSBitmapImageRep.alloc() - bitmapdata.initWithFocusedViewRect_(bounds) - view.unlockFocus() - return bitmapdata - - # what happens when the page has finished loading - def webView_didFinishLoadForFrame_(self, webview, frame): - # don't care about subframes - if (frame == webview.mainFrame()): - scriptobject = webview.windowScriptObject() - if self.options.js: - scriptobject.evaluateWebScript_(self.options.js) - - bridge = scriptobject.valueForKey_('webkit2png') - - def doGrab(): - Foundation.NSTimer.\ - scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_( - self.options.delay, self, self.doGrab, webview, False) - - if bridge.is_stopped: - bridge.start_callback = doGrab - else: - doGrab() - - def doGrab(self, timer): - webview = timer.userInfo() - frame = webview.mainFrame() - view = frame.frameView().documentView() - - URL = webview.mainFrame().dataSource().initialRequest().URL()\ - .absoluteString() - filename = self.makeFilename(URL, self.options) - - bitmapdata = self.captureView(view) - - if self.options.selector: - doc = frame.DOMDocument() - el = doc.querySelector_(self.options.selector) - - if not el: - print " ... no element matching %s found?" % \ - self.options.selector - self.getURL(webview) - return - - left, top = 0, 0 - parent = el - while parent: - left += parent.offsetLeft() - top += parent.offsetTop() - parent = parent.offsetParent() - - zoom = self.options.zoom - - cropRect = view.window().convertRectToBacking_(Foundation.NSMakeRect( - zoom * left, zoom * top, - zoom * el.offsetWidth(), zoom * el.offsetHeight())) - - cropped = Quartz.CGImageCreateWithImageInRect( - bitmapdata.CGImage(), cropRect) - bitmapdata = AppKit.NSBitmapImageRep.alloc().initWithCGImage_( - cropped) - Quartz.CGImageRelease(cropped) - - self.saveImages(bitmapdata, filename, self.options) - - print " ... done" - self.getURL(webview) - - -def main(): - - # parse the command line - usage = """%prog [options] [http://example.net/ ...] - -Examples: -%prog http://google.com/ # screengrab google -%prog -W 1000 -H 1000 http://google.com/ # bigger screengrab of google -%prog -T http://google.com/ # just the thumbnail screengrab -%prog -TF http://google.com/ # just thumbnail and fullsize grab -%prog -o foo http://google.com/ # save images as "foo-thumb.png" etc -%prog - # screengrab urls from stdin -%prog /path/to/file.html # screengrab local html file -%prog -h | less # full documentation""" - - cmdparser = optparse.OptionParser(usage, - version=("webkit2png " + __version__)) - # TODO: add quiet/verbose options - cmdparser.add_option("--debug", action="store_true", - help=optparse.SUPPRESS_HELP) - - # warning: setting these too high can crash your window server - cmdparser.add_option("--UNSAFE-max-height", type="int", default=30000, - help=optparse.SUPPRESS_HELP) - cmdparser.add_option("--UNSAFE-max-width", type="int", default=30000, - help=optparse.SUPPRESS_HELP) - - group = optparse.OptionGroup(cmdparser, "Network Options") - group.add_option("--timeout", type="float", default=60.0, - help="page load timeout (default: 60)") - group.add_option("--user-agent", type="string", default=False, - help="set user agent header") - group.add_option("--ignore-ssl-check", action="store_true", default=False, - help="ignore SSL Certificate name mismatches") - cmdparser.add_option_group(group) - - group = optparse.OptionGroup(cmdparser, "Browser Window Options") - group.add_option( - "-W", "--width", type="float", default=800.0, - help="initial (and minimum) width of browser (default: 800)") - group.add_option( - "-H", "--height", type="float", default=600.0, - help="initial (and minimum) height of browser (default: 600)") - group.add_option( - "-z", "--zoom", type="float", default=1.0, - help='zoom level of browser, equivalent to "Zoom In" and "Zoom Out" ' - 'in "View" menu (default: 1.0)') - group.add_option( - "--selector", type="string", - help="CSS selector for a single element to capture (first matching " - "element will be used)") - cmdparser.add_option_group(group) - - group = optparse.OptionGroup(cmdparser, "Output size options") - group.add_option( - "-F", "--fullsize", action="store_true", - help="only create fullsize screenshot") - group.add_option( - "-T", "--thumb", action="store_true", - help="only create thumbnail sreenshot") - group.add_option( - "-C", "--clipped", action="store_true", - help="only create clipped thumbnail screenshot") - group.add_option( - "--clipwidth", type="float", default=200.0, - help="width of clipped thumbnail (default: 200)", - metavar="WIDTH") - group.add_option( - "--clipheight", type="float", default=150.0, - help="height of clipped thumbnail (default: 150)", - metavar="HEIGHT") - group.add_option( - "-s", "--scale", type="float", default=0.25, - help="scale factor for thumbnails (default: 0.25)") - cmdparser.add_option_group(group) - - group = optparse.OptionGroup(cmdparser, "Output filename options") - group.add_option( - "-D", "--dir", type="string", default="./", - help="directory to place images into") - group.add_option( - "-o", "--filename", type="string", default="", - metavar="NAME", help="save images as NAME-full.png,NAME-thumb.png etc") - group.add_option( - "-m", "--md5", action="store_true", - help="use md5 hash for filename (like del.icio.us)") - group.add_option( - "-d", "--datestamp", action="store_true", - help="include date in filename") - cmdparser.add_option_group(group) - - group = optparse.OptionGroup(cmdparser, "Web page functionality") - group.add_option( - "--delay", type="float", default=0, - help="delay between page load finishing and screenshot") - group.add_option( - "--js", type="string", default=None, - help="JavaScript to execute when the window finishes loading" - "(example: --js='document.bgColor=\"red\";'). " - "If you need to wait for asynchronous code to finish before " - "capturing the screenshot, call webkit2png.stop() before the " - "async code runs, then webkit2png.start() to capture the image.") - group.add_option( - "--noimages", action="store_true", - help=optparse.SUPPRESS_HELP) - group.add_option( - "--no-images", action="store_true", - help="don't load images") - group.add_option( - "--nojs", action="store_true", - help=optparse.SUPPRESS_HELP) - group.add_option( - "--no-js", action="store_true", - help="disable JavaScript support") - group.add_option( - "--transparent", action="store_true", - help="render output on a transparent background (requires a web " - "page with a transparent background)", default=False) - cmdparser.add_option_group(group) - - (options, args) = cmdparser.parse_args() - if len(args) == 0: - cmdparser.print_usage() - return - if options.filename: - if len(args) != 1 or args[0] == "-": - print "--filename option requires exactly one url" - return - - # deprecated options - if options.nojs: - print >> sys.stderr, 'Warning: --nojs will be removed in ' \ - 'webkit2png 1.0. Please use --no-js.' - options.no_js = True - if options.noimages: - print >> sys.stderr, 'Warning: --noimages will be removed in ' \ - 'webkit2png 1.0. Please use --no-images.' - options.no_images = True - - if options.scale == 0: - cmdparser.error("scale cannot be zero") - # make sure we're outputing something - if not (options.fullsize or options.thumb or options.clipped): - options.fullsize = True - options.thumb = True - options.clipped = True - # work out the initial size of the browser window - # (this might need to be larger so clipped image is right size) - options.initWidth = (options.clipwidth / options.scale) - options.initHeight = (options.clipheight / options.scale) - options.width *= options.zoom - if options.width > options.initWidth: - options.initWidth = options.width - if options.height > options.initHeight: - options.initHeight = options.height - - # Hide the dock icon (needs to run before NSApplication.sharedApplication) - AppKit.NSBundle.mainBundle().infoDictionary()['LSBackgroundOnly'] = '1' - - app = AppKit.NSApplication.sharedApplication() - - # create an app delegate - delegate = AppDelegate.alloc().init() - delegate.timeout = options.timeout - AppKit.NSApp().setDelegate_(delegate) - - # create a window - rect = Foundation.NSMakeRect(0, 0, 100, 100) - win = AppKit.NSWindow.alloc() - win.initWithContentRect_styleMask_backing_defer_( - rect, AppKit.NSBorderlessWindowMask, 2, 0) - if options.debug: - win.orderFrontRegardless() - # create a webview object - webview = WebKit.WebView.alloc() - webview.initWithFrame_(rect) - # turn off scrolling so the content is actually x wide and not x-15 - webview.mainFrame().frameView().setAllowsScrolling_(objc.NO) - - if options.user_agent: - webview.setCustomUserAgent_(options.user_agent) - else: - webkit_version = Foundation.NSBundle.bundleForClass_(WebKit.WebView)\ - .objectForInfoDictionaryKey_(WebKit.kCFBundleVersionKey)[1:] - webview.setApplicationNameForUserAgent_( - "Like-Version/6.0 Safari/%s webkit2png/%s" % (webkit_version, __version__)) - webview.setPreferencesIdentifier_('webkit2png') - webview.preferences().setLoadsImagesAutomatically_(not options.no_images) - webview.preferences().setJavaScriptEnabled_(not options.no_js) - - if options.zoom != 1.0: - webview._setZoomMultiplier_isTextOnly_(options.zoom, False) - - # add the webview to the window - win.setContentView_(webview) - - # create a LoadDelegate - loaddelegate = WebkitLoad.alloc().init() - loaddelegate.options = options - loaddelegate.urls = args - webview.setFrameLoadDelegate_(loaddelegate) - - app.run() - -if __name__ == '__main__': - main() diff --git a/old/webrender.py b/old/webrender.py deleted file mode 100644 index 10d062a..0000000 --- a/old/webrender.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env python - -# webrender.py - recursively render web pages to a gif+imagemap of clickable links -# caveat: this script requires to be run as a regular user and cannot run as a daemon -# from apache cgi-bin, you can use python built in http server instead -# usage: -# create cgi-bin directory, copy webrender.py to cgi-bin and chmod 755 -# python -m CGIHTTPServer 8000 -# navigate web browser to http://x.x.x.x:8000/cgi-bin/webrender.py -# the webrender-xxx.gif images are created in the CWD of the http server - - -__version__ = "1.0" - -# -# This program is based on the software picidae.py 1.0 from http://www.picidae.net -# It was modified by Antoni Sawicki -# -# This program is based on the software webkit2png 0.4 from Paul Hammond. -# It was extended by picidae.net -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -try: - import sys - import os - import glob - import random - import Foundation - import WebKit - import AppKit - import objc - import string - import urllib - import socket - import cgi - import cgitb; cgitb.enable() # for trubleshooting -except ImportError: - print "Cannot find pyobjc library files. Are you sure it is installed?" - sys.exit() - - -from optparse import OptionParser - - -class AppDelegate (Foundation.NSObject): - # what happens when the app starts up - def applicationDidFinishLaunching_(self, aNotification): - webview = aNotification.object().windows()[0].contentView() - webview.frameLoadDelegate().getURL(webview) - - -class WebkitLoad (Foundation.NSObject, WebKit.protocols.WebFrameLoadDelegate): - # what happens if something goes wrong while loading - def webView_didFailLoadWithError_forFrame_(self,webview,error,frame): - print " ... something went wrong 1: " + error.localizedDescription() - self.getURL(webview) - def webView_didFailProvisionalLoadWithError_forFrame_(self,webview,error,frame): - print " ... something went wrong 2: " + error.localizedDescription() - self.getURL(webview) - - def getURL(self,webview): - if self.urls: - if self.urls[0] == '-': - url = sys.stdin.readline().rstrip() - if not url: AppKit.NSApplication.sharedApplication().terminate_(None) - else: - url = self.urls.pop(0) - else: - AppKit.NSApplication.sharedApplication().terminate_(None) - - self.resetWebview(webview) - webview.mainFrame().loadRequest_(Foundation.NSURLRequest.requestWithURL_(Foundation.NSURL.URLWithString_(url))) - if not webview.mainFrame().provisionalDataSource(): - print "" - self.getURL(webview) - - def resetWebview(self,webview): - rect = Foundation.NSMakeRect(0,0,1024,768) - webview.window().setContentSize_((1024,768)) - webview.setFrame_(rect) - - def resizeWebview(self,view): - view.window().display() - view.window().setContentSize_(view.bounds().size) - view.setFrame_(view.bounds()) - - def captureView(self,view): - view.lockFocus() - bitmapdata = AppKit.NSBitmapImageRep.alloc() - bitmapdata.initWithFocusedViewRect_(view.bounds()) - view.unlockFocus() - return bitmapdata - - # what happens when the page has finished loading - def webView_didFinishLoadForFrame_(self,webview,frame): - # don't care about subframes - if (frame == webview.mainFrame()): - view = frame.frameView().documentView() - - self.resizeWebview(view) - - URL = frame.dataSource().initialRequest().URL().absoluteString() - - for fl in glob.glob("webrender-*.gif"): - os.remove(fl) - - GIF = "webrender-%s.gif" % (random.randrange(0,1000)) - - bitmapdata = self.captureView(view) - bitmapdata.representationUsingType_properties_(AppKit.NSGIFFileType,None).writeToFile_atomically_(GIF,objc.YES) - - myurl = "http://%s:%s%s" % (socket.gethostbyname(socket.gethostname()), os.getenv("SERVER_PORT"), os.getenv("SCRIPT_NAME")) - - print "Content-type: text/html\r\n\r\n" - print "" - print "Webrender - %s" % (URL) - print "
" % (myurl) - print "" % (URL) - print "" - print "" - print "
" % (myurl) - print "" - print "" - print "
" - print "\"webrender\"" % (GIF) - - - # Analyse HTML and get links - print ""; - - domdocument = frame.DOMDocument() - domnodelist = domdocument.getElementsByTagName_('A') - i = 0 - while i < domnodelist.length(): - # linkvalue - value = domnodelist.item_(i).valueForKey_('href') - - # position-rect - myrect = domnodelist.item_(i).boundingBox() - - xmin = Foundation.NSMinX(myrect) - ymin = Foundation.NSMinY(myrect) - xmax = Foundation.NSMaxX(myrect) - ymax = Foundation.NSMaxY(myrect) - - # print Link - escval = string.replace( string.replace(value, "?", "TNXQUE"), "&", "TNXAMP" ) - print "\"\"" % (xmin, ymin, xmax, ymax, myurl, escval) - i += 1 - - print "" - print "" - self.getURL(webview) - - -def main(): - - # obtain url from cgi input - form = cgi.FieldStorage() - rawurl = form.getfirst("url", "http://www.google.com") - rawsearch = form.getfirst("search") - if rawsearch: - url = "http://www.google.com/search?q=%s" % (rawsearch) - else: - url = string.replace( string.replace(rawurl, "TNXAMP", "&"), "TNXQUE", "?") - - - AppKit.NSApplicationLoad(); - - app = AppKit.NSApplication.sharedApplication() - - # create an app delegate - delegate = AppDelegate.alloc().init() - AppKit.NSApp().setDelegate_(delegate) - - # create a window - rect = Foundation.NSMakeRect(-16000,-16000,100,100) - win = AppKit.NSWindow.alloc() - win.initWithContentRect_styleMask_backing_defer_ (rect, AppKit.NSBorderlessWindowMask, 2, 0) - - # create a webview object - webview = WebKit.WebView.alloc() - webview.initWithFrame_(rect) - # turn off scrolling so the content is actually x wide and not x-15 - webview.mainFrame().frameView().setAllowsScrolling_(objc.NO) - # add the webview to the window - win.setContentView_(webview) - - - # create a LoadDelegate - loaddelegate = WebkitLoad.alloc().init() - loaddelegate.options = [""] - loaddelegate.urls = [url] - webview.setFrameLoadDelegate_(loaddelegate) - - app.run() - -if __name__ == '__main__' : main() - diff --git a/old/wrp.py b/old/wrp.py deleted file mode 100644 index ac3f061..0000000 --- a/old/wrp.py +++ /dev/null @@ -1,931 +0,0 @@ -#!/usr/bin/env python2.7 - -# wrp.py - Web Rendering Proxy - https://github.com/tenox7/wrp -# A HTTP proxy service that renders the requested URL in to a image associated -# with an imagemap of clickable links. This is an adaptation of previous works by -# picidae.net and Paul Hammond. - -__version__ = "2.0" - -# -# This program is based on the software picidae.py from picidae.net -# It was modified by Antoni Sawicki and Natalia Portillo -# -# This program is based on the software webkit2png from Paul Hammond. -# It was extended by picidae.net -# -# Copyright (c) 2013-2018 Antoni Sawicki -# Copyright (c) 2012-2013 picidae.net -# Copyright (c) 2004-2013 Paul Hammond -# Copyright (c) 2017-2018 Natalia Portillo -# Copyright (c) 2018 //gir.st/ -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -# Configuration options: -PORT = 8080 -WIDTH = 1024 -HEIGHT = 768 -ISMAP = False # ISMAP=True is Server side for Mosaic 1.1 and up. HTML 3.2 supports Client side maps (ISMAP=False) -WAIT = 1 # sleep for 1 second to allow javascript renders -QUALITY = 75 # For JPEG: image quality 0-100; For PNG: sets compression level (leftmost digit 0 fastest, 9 best) -AUTOWIDTH = True # Check for browser width using javascript -FORMAT = "AUTO" # AUTO = GIF for mac OS, JPG for rest; PNG, GIF, JPG as supported values. -SSLSTRIP = True # enable to automatically downgrade secure requests - -# PythonMagick configuration options -MK_MONOCHROME = False # Convert the render to a black and white dithered image -MK_GRAYSCALE = False # Convert the render to a grayscal dithered image -MK_COLORS = 0 # Reduce number of colors in the image. 0 for not reducing. Less than 256 works in grayscale also. -MK_DITHER = False # Dither the image to reduce size. GIFs will always be dithered. Ignored if MK_COLORS is not set. - -import re -import random -import os -import time -import string -import urllib -import socket -import SocketServer -import SimpleHTTPServer -import threading -import Queue -import sys -import logging -import StringIO -import subprocess - -try: - import PythonMagick - HasMagick = True -except ImportError: - HasMagick = False - -# Request queue (URLs go in here) -REQ = Queue.Queue() -# Response queue (dummy response objects) -RESP = Queue.Queue() -# Renders dictionary -RENDERS = {} - -####################### -### Linux CODEPATH ### -####################### - -if sys.platform.startswith('linux') or sys.platform.startswith('freebsd'): - try: - from PyQt5.QtCore import * - from PyQt5.QtGui import * - from PyQt5.QtWebKit import * - from PyQt5.QtWebKitWidgets import * - from PyQt5.QtNetwork import * - from PyQt5.QtWidgets import * - IsPyQt5 = True - except ImportError: - from PyQt4.QtCore import * - from PyQt4.QtGui import * - from PyQt4.QtWebKit import * - from PyQt4.QtNetwork import * - IsPyQt5 = False - - # claunia: Check how to use this in macOS - logging.basicConfig(filename='/dev/stdout', level=logging.WARN, ) - logger = logging.getLogger('wrp') - - # Class for Website-Rendering. Uses QWebPage, which - # requires a running QtGui to work. - class WebkitRenderer(QObject): - def __init__(self, **kwargs): - """Sets default values for the properties.""" - - if not QApplication.instance(): - raise RuntimeError(self.__class__.__name__ + \ - " requires a running QApplication instance") - QObject.__init__(self) - - # Initialize default properties - self.width = kwargs.get('width', 0) - self.height = kwargs.get('height', 0) - self.timeout = kwargs.get('timeout', 0) - self.wait = kwargs.get('wait', 0) - self.logger = kwargs.get('logger', None) - # Set this to true if you want to capture flash. - # Not that your desktop must be large enough for - # fitting the whole window. - self.grabWholeWindow = kwargs.get('grabWholeWindow', False) - - # Set some default options for QWebPage - self.qWebSettings = { - QWebSettings.JavascriptEnabled : True, - QWebSettings.PluginsEnabled : True, - QWebSettings.PrivateBrowsingEnabled : True, - QWebSettings.JavascriptCanOpenWindows : False - } - - def render(self, url): - """Renders the given URL into a QImage object""" - # We have to use this helper object because - # QApplication.processEvents may be called, causing - # this method to get called while it has not returned yet. - helper = _WebkitRendererHelper(self) - helper._window.resize(self.width, self.height) - image = helper.render(url) - - # Bind helper instance to this image to prevent the - # object from being cleaned up (and with it the QWebPage, etc) - # before the data has been used. - image.helper = helper - - return image - - class _WebkitRendererHelper(QObject): - """This helper class is doing the real work. It is required to - allow WebkitRenderer.render() to be called "asynchronously" - (but always from Qt's GUI thread). - """ - - def __init__(self, parent): - """Copies the properties from the parent (WebkitRenderer) object, - creates the required instances of QWebPage, QWebView and QMainWindow - and registers some Slots. - """ - QObject.__init__(self) - - # Copy properties from parent - for key, value in parent.__dict__.items(): - setattr(self, key, value) - - # Create and connect required PyQt4 objects - self._page = CustomWebPage(logger=self.logger) - self._view = QWebView() - self._view.setPage(self._page) - self._window = QMainWindow() - self._window.setCentralWidget(self._view) - - # Import QWebSettings - for key, value in self.qWebSettings.iteritems(): - self._page.settings().setAttribute(key, value) - - # Connect required event listeners - if IsPyQt5: - self._page.loadFinished.connect(self._on_load_finished) - self._page.loadStarted.connect(self._on_load_started) - self._page.networkAccessManager().sslErrors.connect(self._on_ssl_errors) - self._page.networkAccessManager().finished.connect(self._on_each_reply) - else: - self.connect(self._page, SIGNAL("loadFinished(bool)"), self._on_load_finished) - self.connect(self._page, SIGNAL("loadStarted()"), self._on_load_started) - self.connect(self._page.networkAccessManager(), - SIGNAL("sslErrors(QNetworkReply *,const QList&)"), - self._on_ssl_errors) - self.connect(self._page.networkAccessManager(), - SIGNAL("finished(QNetworkReply *)"), - self._on_each_reply) - - # The way we will use this, it seems to be unesseccary to have Scrollbars enabled - self._page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) - self._page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) - self._page.settings().setUserStyleSheetUrl( - QUrl("data:text/css,html,body{overflow-y:hidden !important;}")) - - # Show this widget - # self._window.show() - - def __del__(self): - """Clean up Qt4 objects. """ - self._window.close() - del self._window - del self._view - del self._page - - def render(self, url): - """The real worker. Loads the page (_load_page) and awaits - the end of the given 'delay'. While it is waiting outstanding - QApplication events are processed. - After the given delay, the Window or Widget (depends - on the value of 'grabWholeWindow' is drawn into a QPixmap - """ - self._load_page(url, self.width, self.height, self.timeout) - # Wait for end of timer. In this time, process - # other outstanding Qt events. - if self.wait > 0: - if self.logger: self.logger.debug("Waiting %d seconds " % self.wait) - waitToTime = time.time() + self.wait - while time.time() < waitToTime: - if QApplication.hasPendingEvents(): - QApplication.processEvents() - - if self.grabWholeWindow: - # Note that this does not fully ensure that the - # window still has the focus when the screen is - # grabbed. This might result in a race condition. - self._view.activateWindow() - if IsPyQt5: - image = QScreen.grabWindow(self._window.winId()) - else: - image = QPixmap.grabWindow(self._window.winId()) - else: - if IsPyQt5: - image = QWidget.grab(self._window) - else: - image = QPixmap.grabWidget(self._window) - - httpout = WebkitRenderer.httpout - - frame = self._view.page().currentFrame() - web_url = frame.url().toString() - - # Write URL map - httpout.write("\n" - % (__version__)) - httpout.write("\n" - % (WebkitRenderer.req_url, web_url)) - # Get title - httpout.write("") - for ttl in frame.findAllElements('title'): - httpout.write((u"%s" - % ttl.toPlainText()).encode('utf-8', errors='ignore')) - break # Don't repeat bad HTML coding with several title marks - httpout.write("\n\n") - - if AUTOWIDTH: - httpout.write("\n") - - if ISMAP == True: - httpout.write("" - "\"wrp-render\"\n" - "\n" % (WebkitRenderer.req_map, WebkitRenderer.req_img)) - mapfile = StringIO.StringIO() - mapfile.write("default %s\n" % (web_url)) - else: - httpout.write("\"wrp-render\"\n" - "\n" % (WebkitRenderer.req_img)) - - for x in frame.findAllElements('a'): - turl = QUrl(web_url).resolved(QUrl(x.attribute('href'))).toString() - xmin, ymin, xmax, ymax = x.geometry().getCoords() - if ISMAP == True: - mapfile.write("rect %s %i,%i %i,%i\n".decode('utf-8', errors='ignore') % (turl, xmin, ymin, xmax, ymax)) - else: - httpout.write(("\"%s\"\n".decode('utf-8', errors='ignore') - % (xmin, ymin, xmax, ymax, turl, turl)).encode("utf-8")) - - if ISMAP != True: - httpout.write("\n") - - httpout.write("\n\n") - - if ISMAP == True: - RENDERS[WebkitRenderer.req_map] = mapfile - - return image - - def _load_page(self, url, width, height, timeout): - """ - This method implements the logic for retrieving and displaying - the requested page. - """ - - # This is an event-based application. So we have to wait until - # "loadFinished(bool)" raised. - cancelAt = time.time() + timeout - self.__loading = True - self.__loadingResult = False # Default - self._page.mainFrame().load(QUrl(url)) - while self.__loading: - if timeout > 0 and time.time() >= cancelAt: - raise RuntimeError("Request timed out on %s" % url) - while QApplication.hasPendingEvents() and self.__loading: - QCoreApplication.processEvents() - - if self.logger: self.logger.debug("Processing result") - - if self.__loading_result == False: - if self.logger: self.logger.warning("Failed to load %s" % url) - - # Set initial viewport (the size of the "window") - size = self._page.mainFrame().contentsSize() - if self.logger: self.logger.debug("contentsSize: %s", size) - if width > 0: - size.setWidth(width) - if height > 0: - size.setHeight(height) - - self._window.resize(size) - - def _on_each_reply(self, reply): - """Logs each requested uri""" - self.logger.debug("Received %s" % (reply.url().toString())) - - # Eventhandler for "loadStarted()" signal - def _on_load_started(self): - """Slot that sets the '__loading' property to true.""" - if self.logger: self.logger.debug("loading started") - self.__loading = True - - # Eventhandler for "loadFinished(bool)" signal - def _on_load_finished(self, result): - """Slot that sets the '__loading' property to false and stores - the result code in '__loading_result'. - """ - if self.logger: self.logger.debug("loading finished with result %s", result) - self.__loading = False - self.__loading_result = result - - # Eventhandler for "sslErrors(QNetworkReply *,const QList&)" signal - def _on_ssl_errors(self, reply, errors): - """Slot that writes SSL warnings into the log but ignores them.""" - for e in errors: - if self.logger: self.logger.warn("SSL: " + e.errorString()) - reply.ignoreSslErrors() - - class CustomWebPage(QWebPage): - def __init__(self, **kwargs): - super(CustomWebPage, self).__init__() - self.logger = kwargs.get('logger', None) - - def javaScriptAlert(self, frame, message): - if self.logger: self.logger.debug('Alert: %s', message) - - def javaScriptConfirm(self, frame, message): - if self.logger: self.logger.debug('Confirm: %s', message) - return False - - def javaScriptPrompt(self, frame, message, default, result): - """This function is called whenever a JavaScript program running inside frame tries to - prompt the user for input. The program may provide an optional message, msg, as well - as a default value for the input in defaultValue. - - If the prompt was cancelled by the user the implementation should return false; - otherwise the result should be written to result and true should be returned. - If the prompt was not cancelled by the user, the implementation should return true and - the result string must not be null. - """ - if self.logger: self.logger.debug('Prompt: %s (%s)' % (message, default)) - return False - - def shouldInterruptJavaScript(self): - """This function is called when a JavaScript program is running for a long period of - time. If the user wanted to stop the JavaScript the implementation should return - true; otherwise false. - """ - if self.logger: self.logger.debug("WebKit ask to interrupt JavaScript") - return True - - #=============================================================================== - - def init_qtgui(display=None, style=None, qtargs=None): - """Initiates the QApplication environment using the given args.""" - if QApplication.instance(): - logger.debug("QApplication has already been instantiated. \ - Ignoring given arguments and returning existing QApplication.") - return QApplication.instance() - - qtargs2 = [sys.argv[0]] - - if display: - qtargs2.append('-display') - qtargs2.append(display) - # Also export DISPLAY var as this may be used - # by flash plugin - os.environ["DISPLAY"] = display - - if style: - qtargs2.append('-style') - qtargs2.append(style) - - qtargs2.extend(qtargs or []) - - return QApplication(qtargs2) - - # Technically, this is a QtGui application, because QWebPage requires it - # to be. But because we will have no user interaction, and rendering can - # not start before 'app.exec_()' is called, we have to trigger our "main" - # by a timer event. - def __main_qt(): - # Render the page. - # If this method times out or loading failed, a - # RuntimeException is thrown - try: - while True: - req = REQ.get() - WebkitRenderer.httpout = req[0] - WebkitRenderer.req_url = req[1] - WebkitRenderer.req_img = req[2] - WebkitRenderer.req_map = req[3] - if WebkitRenderer.req_url == "http://wrp.stop/" or WebkitRenderer.req_url == "http://www.wrp.stop/": - print ">>> Terminate Request Received" - QApplication.exit(0) - break - - # Initialize WebkitRenderer object - renderer = WebkitRenderer() - renderer.logger = logger - renderer.width = WIDTH - renderer.height = HEIGHT - renderer.timeout = 60 - renderer.wait = WAIT - renderer.grabWholeWindow = False - - image = renderer.render(WebkitRenderer.req_url) - qBuffer = QBuffer() - - if HasMagick: - image.save(qBuffer, 'png', QUALITY) - blob = PythonMagick.Blob(qBuffer.buffer().data()) - mimg = PythonMagick.Image(blob) - mimg.quality(QUALITY) - - if FORMAT=="GIF" and not MK_MONOCHROME and not MK_GRAYSCALE and not MK_DITHER and MK_COLORS != 0 and not MK_COLORS <= 256: - mimg.quantizeColors(256) - mimg.quantizeDither() - mimg.quantize() - - if MK_MONOCHROME: - mimg.quantizeColorSpace(PythonMagick.ColorspaceType.GRAYColorspace) - mimg.quantizeColors(2) - mimg.quantizeDither() - mimg.quantize() - mimg.monochrome() - elif MK_GRAYSCALE: - mimg.quantizeColorSpace(PythonMagick.ColorspaceType.GRAYColorspace) - if MK_COLORS > 0 and MK_COLORS < 256: - mimg.quantizeColors(MK_COLORS) - else: - mimg.quantizeColors(256) - mimg.quantizeDither() - mimg.quantize() - else: - if MK_COLORS > 0: - mimg.quantizeColors(MK_COLORS) - if MK_DITHER: - mimg.quantizeDither() - mimg.quantize() - - if FORMAT=="AUTO" or FORMAT=="JPG": - mimg.write(blob, "jpg") - elif FORMAT=="PNG": - mimg.write(blob, "png") - elif FORMAT=="GIF": - mimg.write(blob, "gif") - output = StringIO.StringIO() - output.write(blob.data) - else: - if FORMAT=="AUTO" or FORMAT=="JPG": - image.save(qBuffer, 'jpg', QUALITY) - elif FORMAT=="PNG": - image.save(qBuffer, 'png', QUALITY) - - output = StringIO.StringIO() - output.write(qBuffer.buffer().data()) - - RENDERS[req[2]] = output - - del renderer - print ">>> done: %s [%d kb]..." % (WebkitRenderer.req_img, output.len/1024) - - RESP.put('') - - QApplication.exit(0) - except RuntimeError, e: - logger.error("main: %s" % e) - print >> sys.stderr, e - QApplication.exit(1) - -###################### -### macOS CODEPATH ### -###################### - -elif sys.platform == "darwin": - import Foundation - import WebKit - import AppKit - import objc - - class AppDelegate(Foundation.NSObject): - # what happens when the app starts up - def applicationDidFinishLaunching_(self, aNotification): - webview = aNotification.object().windows()[0].contentView() - webview.frameLoadDelegate().getURL(webview) - - class WebkitLoad(Foundation.NSObject, WebKit.protocols.WebFrameLoadDelegate): - # what happens if something goes wrong while loading - def webView_didFailLoadWithError_forFrame_(self, webview, error, frame): - if error.code() == Foundation.NSURLErrorCancelled: - return - print " ... something went wrong 1: " + error.localizedDescription() - AppKit.NSApplication.sharedApplication().terminate_(None) - - def webView_didFailProvisionalLoadWithError_forFrame_(self, webview, error, frame): - if error.code() == Foundation.NSURLErrorCancelled: - return - print " ... something went wrong 2: " + error.localizedDescription() - AppKit.NSApplication.sharedApplication().terminate_(None) - - def getURL(self, webview): - req = REQ.get() - WebkitLoad.httpout = req[0] - WebkitLoad.req_url = req[1] - WebkitLoad.req_img = req[2] - WebkitLoad.req_map = req[3] - - if WebkitLoad.req_url == "http://wrp.stop/" or WebkitLoad.req_url == "http://www.wrp.stop/": - print ">>> Terminate Request Received" - AppKit.NSApplication.sharedApplication().terminate_(None) - - nsurl = Foundation.NSURL.URLWithString_(WebkitLoad.req_url) - if not (nsurl and nsurl.scheme()): - nsurl = Foundation.NSURL.alloc().initFileURLWithPath_(WebkitLoad.req_url) - nsurl = nsurl.absoluteURL() - - Foundation.NSURLRequest.setAllowsAnyHTTPSCertificate_forHost_(objc.YES, nsurl.host()) - - self.resetWebview(webview) - webview.mainFrame().loadRequest_(Foundation.NSURLRequest.requestWithURL_(nsurl)) - if not webview.mainFrame().provisionalDataSource(): - print " ... not a proper url?" - RESP.put('') - self.getURL(webview) - - def resetWebview(self, webview): - rect = Foundation.NSMakeRect(0, 0, WIDTH, HEIGHT) - webview.window().setContentSize_((WIDTH, HEIGHT)) - webview.setFrame_(rect) - - def captureView(self, view): - view.window().display() - view.window().setContentSize_(view.bounds().size) - view.setFrame_(view.bounds()) - - if hasattr(view, "bitmapImageRepForCachingDisplayInRect_"): - bitmapdata = view.bitmapImageRepForCachingDisplayInRect_(view.bounds()) - view.cacheDisplayInRect_toBitmapImageRep_(view.bounds(), bitmapdata) - else: - view.lockFocus() - bitmapdata = AppKit.NSBitmapImageRep.alloc() - bitmapdata.initWithFocusedViewRect_(view.bounds()) - view.unlockFocus() - return bitmapdata - - # what happens when the page has finished loading - def webView_didFinishLoadForFrame_(self, webview, frame): - # don't care about subframes - if frame == webview.mainFrame(): - view = frame.frameView().documentView() - - output = StringIO.StringIO() - - if HasMagick: - output.write(self.captureView(view).representationUsingType_properties_( - AppKit.NSPNGFileType, None)) - blob = PythonMagick.Blob(output) - mimg = PythonMagick.Image(blob) - mimg.quality(QUALITY) - - if FORMAT=="GIF" and not MK_MONOCHROME and not MK_GRAYSCALE and not MK_DITHER and MK_COLORS != 0 and not MK_COLORS <= 256: - mimg.quantizeColors(256) - mimg.quantizeDither() - mimg.quantize() - - if MK_MONOCHROME: - mimg.quantizeColorSpace(PythonMagick.ColorspaceType.GRAYColorspace) - mimg.quantizeColors(2) - mimg.quantizeDither() - mimg.quantize() - mimg.monochrome() - elif MK_GRAYSCALE: - mimg.quantizeColorSpace(PythonMagick.ColorspaceType.GRAYColorspace) - if MK_COLORS > 0 and MK_COLORS < 256: - mimg.quantizeColors(MK_COLORS) - else: - mimg.quantizeColors(256) - mimg.quantizeDither() - mimg.quantize() - else: - if MK_COLORS > 0: - mimg.quantizeColors(MK_COLORS) - if MK_DITHER: - mimg.quantizeDither() - mimg.quantize() - - if FORMAT=="JPG": - mimg.write(blob, "jpg") - elif FORMAT=="PNG": - mimg.write(blob, "png") - elif FORMAT=="AUTO" or FORMAT=="GIF": - mimg.write(blob, "gif") - output = StringIO.StringIO() - output.write(blob.data) - else: - if FORMAT=="AUTO" or FORMAT=="GIF": - output.write(self.captureView(view).representationUsingType_properties_( - AppKit.NSGIFFileType, None)) - elif FORMAT=="JPG": - output.write(self.captureView(view).representationUsingType_properties_( - AppKit.NSJPEGFileType, None)) - elif FORMAT=="PNG": - output.write(self.captureView(view).representationUsingType_properties_( - AppKit.NSPNGFileType, None)) - - RENDERS[WebkitLoad.req_img] = output - - # url of the rendered page - web_url = frame.dataSource().initialRequest().URL().absoluteString() - - httpout = WebkitLoad.httpout - - httpout.write("\n" - % (__version__)) - httpout.write("\n" - % (WebkitLoad.req_url, web_url)) - - domdocument = frame.DOMDocument() - # Get title - httpout.write("") - httpout.write((u"%s" - % domdocument.title()).encode('utf-8', errors='ignore')) - httpout.write("\n\n") - - if AUTOWIDTH: - httpout.write("\n") - - if ISMAP == True: - httpout.write("" - "\"wrp-render\"\n" - "\n" % (WebkitLoad.req_map, WebkitLoad.req_img)) - mapfile = StringIO.StringIO() - mapfile.write("default %s\n" % (web_url)) - else: - httpout.write("\"wrp-render\"\n" - "\n" % (WebkitLoad.req_img)) - - domnodelist = domdocument.getElementsByTagName_('A') - i = 0 - while i < domnodelist.length(): - turl = domnodelist.item_(i).valueForKey_('href') - #TODO: crashes? validate url? insert web_url if wrong? - myrect = domnodelist.item_(i).boundingBox() - - xmin = Foundation.NSMinX(myrect) - ymin = Foundation.NSMinY(myrect) - xmax = Foundation.NSMaxX(myrect) - ymax = Foundation.NSMaxY(myrect) - - if ISMAP == True: - mapfile.write("rect %s %i,%i %i,%i\n".decode('utf-8', errors='ignore') % (turl, xmin, ymin, xmax, ymax)) - else: - httpout.write("\"%s\"\n".decode('utf-8', errors='ignore') - % (xmin, ymin, xmax, ymax, turl, turl)) - - i += 1 - - if ISMAP != True: - httpout.write("\n") - - httpout.write("\n\n") - - if ISMAP == True: - RENDERS[WebkitLoad.req_map] = mapfile - - # Return to Proxy thread and Loop... - RESP.put('') - self.getURL(webview) - - def main_cocoa(): - # Launch NS Application - AppKit.NSApplicationLoad() - app = AppKit.NSApplication.sharedApplication() - delegate = AppDelegate.alloc().init() - AppKit.NSApp().setDelegate_(delegate) - AppKit.NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] = \ - dict(NSAllowsArbitraryLoads=True) - rect = Foundation.NSMakeRect(-16000, -16000, 100, 100) - win = AppKit.NSWindow.alloc() - win.initWithContentRect_styleMask_backing_defer_(rect, AppKit.NSBorderlessWindowMask, 2, 0) - webview = WebKit.WebView.alloc() - webview.initWithFrame_(rect) - webview.mainFrame().frameView().setAllowsScrolling_(objc.NO) - webkit_version = Foundation.NSBundle.bundleForClass_(WebKit.WebView). \ - objectForInfoDictionaryKey_(WebKit.kCFBundleVersionKey)[1:] - webview.setApplicationNameForUserAgent_("Like-Version/6.0 Safari/%s wrp/%s" - % (webkit_version, __version__)) - win.setContentView_(webview) - loaddelegate = WebkitLoad.alloc().init() - loaddelegate.options = [""] - webview.setFrameLoadDelegate_(loaddelegate) - app.run() - -####################### -### COMMON CODEPATH ### -####################### -class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler): - def do_GET(self): - req_url = self.path - httpout = self.wfile - - map_re = re.match(r"http://(wrp-\d+\.map).*?(\d+),(\d+)", req_url) - wid_re = re.match(r"http://(width-[0-9]+-px\.jpg).*", req_url) - gif_re = re.match(r"http://(wrp-\d+\.gif).*", req_url) - jpg_re = re.match(r"http://(wrp-\d+\.jpg).*", req_url) - png_re = re.match(r"http://(wrp-\d+\.png).*", req_url) - - # Serve Rendered GIF - if gif_re: - img = gif_re.group(1) - print ">>> request for rendered gif image... %s [%d kb]" \ - % (img, RENDERS[img].len/1024) - self.send_response(200, 'OK') - self.send_header('Content-type', 'image/gif') - self.end_headers() - httpout.write(RENDERS[img].getvalue()) - del RENDERS[img] - - elif jpg_re: - img = jpg_re.group(1) - print ">>> request for rendered jpg image... %s [%d kb]" \ - % (img, RENDERS[img].len/1024) - self.send_response(200, 'OK') - self.send_header('Content-type', 'image/jpeg') - self.end_headers() - httpout.write(RENDERS[img].getvalue()) - del RENDERS[img] - - elif png_re: - img = png_re.group(1) - print ">>> request for rendered png image... %s [%d kb]" \ - % (img, RENDERS[img].len/1024) - self.send_response(200, 'OK') - self.send_header('Content-type', 'image/png') - self.end_headers() - httpout.write(RENDERS[img].getvalue()) - del RENDERS[img] - - elif wid_re: - global WIDTH - try: - wid = req_url.split("-") - WIDTH = int(wid[1]) - print ">>> width request: %d" % WIDTH - except: - print ">>> width request error" % WIDTH - - self.send_error(404, "Width request") - self.end_headers() - - # Process ISMAP Request - elif map_re: - map = map_re.group(1) - req_x = int(map_re.group(2)) - req_y = int(map_re.group(3)) - print ">>> ISMAP request... %s [%d,%d] " % (map, req_x, req_y) - - mapf = RENDERS[map] - mapf.seek(0) - goto_url = "none" - for line in mapf.readlines(): - if re.match(r"(\S+)", line).group(1) == "default": - default_url = re.match(r"\S+\s+(\S+)", line).group(1) - - elif re.match(r"(\S+)", line).group(1) == "rect": - try: - rect = re.match(r"(\S+)\s+(\S+)\s+(\d+),(\d+)\s+(\d+),(\d+)", line) - min_x = int(rect.group(3)) - min_y = int(rect.group(4)) - max_x = int(rect.group(5)) - max_y = int(rect.group(6)) - if (req_x >= min_x) and \ - (req_x <= max_x) and \ - (req_y >= min_y) and \ - (req_y <= max_y): - goto_url = rect.group(2) - except AttributeError: - pass - - if goto_url == "none": - goto_url = default_url - - print ">>> ISMAP redirect: %s\n" % (goto_url) - - self.send_response(302, "Found") - self.send_header("Location", goto_url) - self.send_header("Content-type", "text/html") - self.end_headers() - httpout.write("%s\n" - % (goto_url, goto_url)) - - # Process a web page request and generate image - else: - print ">>> URL request... " + req_url - - if req_url == "http://wrp.stop/" or req_url == "http://www.wrp.stop/": - REQ.put((httpout, req_url, "", "")) - RESP.get() - else: - reqst = urllib.urlopen(req_url) - - if reqst.info().type == "text/html" or reqst.info().type == "application/xhtml+xml": - # If an error occurs, send error headers to the requester - if reqst.getcode() >= 400: - self.send_response(reqst.getcode()) - for hdr in reqst.info(): - self.send_header(hdr, reqst.info()[hdr]) - self.end_headers() - else: - self.send_response(200, 'OK') - self.send_header('Content-type', 'text/html') - self.end_headers() - - rnd = random.randrange(0, 1000) - - if FORMAT == "GIF": - req_extension = ".gif" - elif FORMAT == "JPG": - req_extension = ".jpg" - elif FORMAT == "PNG": - req_extension = ".png" - elif (sys.platform.startswith('linux') or sys.platform.startswitch('freebsd')) and FORMAT == "AUTO": - req_extension = ".jpg" - elif sys.platform == "darwin" and FORMAT == "AUTO": - req_extension = ".gif" - - req_img = "wrp-%s%s" % (rnd, req_extension) - req_map = "wrp-%s.map" % (rnd) - - # To WebKit Thread - REQ.put((httpout, req_url, req_img, req_map)) - # Wait for completition - RESP.get() - # If the requested file is not HTML or XHTML, just return it as is. - else: - self.send_response(reqst.getcode()) - for hdr in reqst.info(): - self.send_header(hdr, reqst.info()[hdr]) - self.end_headers() - httpout.write(reqst.read()) - -def run_proxy(): - httpd = SocketServer.TCPServer(('', PORT), Proxy) - print "Web Rendering Proxy v%s serving at port: %s" % (__version__, PORT) - while 1: - httpd.serve_forever() - -def main(): - if(FORMAT != "AUTO" and FORMAT != "GIF" and FORMAT != "JPG" and FORMAT != "PNG"): - sys.exit("Unsupported image format \"%s\". Exiting." % FORMAT) - - if (sys.platform.startswith('linux') or sys.platform.startswith('freebsd')) and FORMAT == "GIF" and not HasMagick: - sys.exit("GIF format is not supported on this platform. Exiting.") - - # run traffic through sslstrip as a quick workaround for getting SSL webpages to work - # NOTE: modern browsers are doing their best to stop this kind of 'attack'. Firefox - # supports an about:config flag test.currentTimeOffsetSeconds(int) = 12000000, which - # you can use to circumvent those checks. - if SSLSTRIP: - try: - subprocess.check_output(["pidof", "sslstrip"]) - except: - subprocess.Popen(["sslstrip"], stdout=open(os.devnull,'w'), stderr=subprocess.STDOUT) # runs on port 10000 by default - QNetworkProxy.setApplicationProxy(QNetworkProxy(QNetworkProxy.HttpProxy, "localhost", 10000)) - # Launch Proxy Thread - threading.Thread(target=run_proxy).start() - - if sys.platform.startswith('linux') or sys.platform.startswith('freebsd'): - import signal - try: - import PyQt5.QtCore - except ImportError: - import PyQt4.QtCore - # Initialize Qt-Application, but make this script - # abortable via CTRL-C - app = init_qtgui(display=None, style=None) - signal.signal(signal.SIGINT, signal.SIG_DFL) - - QTimer.singleShot(0, __main_qt) - sys.exit(app.exec_()) - elif sys.platform == "darwin": - main_cocoa() - else: - sys.exit("Unsupported platform: %s. Exiting." % sys.platform) - -if __name__ == '__main__': main()