<s> import hashlib <EOL> import io <EOL> import json <EOL> import logging <EOL> import struct <EOL> import os <EOL> from StringIO import StringIO <EOL> from textwrap import dedent <EOL> from zipfile import ZipFile <EOL> import requests <EOL> from bs4 import BeautifulSoup <EOL> from cryptography . hazmat . backends import default_backend <EOL> from cryptography . hazmat . primitives import hashes , serialization <EOL> from cryptography . hazmat . primitives . asymmetric import padding <EOL> from PIL import Image <EOL> from requests . exceptions import RequestException <EOL> from flask import Flask , render_template , request , url_for <EOL> __version__ = '<STR_LIT>' <EOL> app = Flask ( __name__ ) <EOL> app . config . from_object ( '<STR_LIT>' ) <EOL> app . config . from_pyfile ( '<STR_LIT>' , silent = True ) <EOL> app . config . from_envvar ( '<STR_LIT>' , silent = True ) <EOL> app . logger . addHandler ( logging . StreamHandler ( ) ) <EOL> ROOT = os . path . dirname ( os . path . abspath ( __file__ ) ) <EOL> def path ( * parts ) : <EOL> return os . path . join ( ROOT , * parts ) <EOL> @ app . route ( '<STR_LIT:/>' ) <EOL> def index ( ) : <EOL> return render_template ( '<STR_LIT>' ) <EOL> @ app . route ( '<STR_LIT>' ) <EOL> def manifest ( ) : <EOL> url = request . args . get ( '<STR_LIT:url>' ) <EOL> name = request . args . get ( '<STR_LIT:name>' ) <EOL> icon_url = request . args . get ( '<STR_LIT>' ) <EOL> app = OpenWebApp ( url , name = name , icon_url = icon_url ) <EOL> return app . mini_manifest ( ) , <NUM_LIT:200> , { '<STR_LIT:Content-Type>' : '<STR_LIT>' } <EOL> @ app . route ( '<STR_LIT>' ) <EOL> def open_web_app_zip ( ) : <EOL> url = request . args . get ( '<STR_LIT:url>' ) <EOL> name = request . args . get ( '<STR_LIT:name>' ) <EOL> icon_url = request . args . get ( '<STR_LIT>' ) <EOL> app = OpenWebApp ( url , name = name , icon_url = icon_url ) <EOL> return app . zipfile ( ) , <NUM_LIT:200> , { '<STR_LIT:Content-Type>' : '<STR_LIT>' } <EOL> @ app . route ( '<STR_LIT>' ) <EOL> def chrome_app_crx ( ) : <EOL> url = request . args . get ( '<STR_LIT:url>' ) <EOL> name = request . args . get ( '<STR_LIT:name>' ) <EOL> icon_url = request . args . get ( '<STR_LIT>' ) <EOL> app = ChromeApp ( url , name = name , icon_url = icon_url ) <EOL> return app . crxfile ( ) , <NUM_LIT:200> , { '<STR_LIT:Content-Type>' : '<STR_LIT>' } <EOL> class WebApp ( object ) : <EOL> def __init__ ( self , url , name = None , icon_url = None ) : <EOL> self . url = url <EOL> self . id = hashlib . sha1 ( url ) . hexdigest ( ) <EOL> self . _name = name <EOL> self . _icon = None <EOL> self . icon_url = icon_url <EOL> self . _soup = None <EOL> def soup ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . _soup : <EOL> try : <EOL> response = requests . get ( self . url ) <EOL> response . raise_for_status ( ) <EOL> except RequestException : <EOL> return None <EOL> self . _soup = BeautifulSoup ( response . text ) <EOL> return self . _soup <EOL> def icon ( self ) : <EOL> if not self . _icon : <EOL> self . _icon = resize_square ( self . fetch_icon ( ) , <NUM_LIT> ) <EOL> return self . _icon <EOL> def icon_bytes ( self ) : <EOL> icon_bytes = io . BytesIO ( ) <EOL> self . icon ( ) . save ( icon_bytes , '<STR_LIT>' ) <EOL> value = icon_bytes . getvalue ( ) <EOL> icon_bytes . close ( ) <EOL> return value <EOL> def fetch_icon ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . icon_url : <EOL> image = download_image ( self . icon_url ) <EOL> if image : <EOL> return image <EOL> soup = self . soup ( ) <EOL> if soup : <EOL> for tag in soup . findAll ( '<STR_LIT>' ) : <EOL> if tag . get ( '<STR_LIT>' ) == '<STR_LIT>' : <EOL> image = download_image ( tag [ '<STR_LIT:content>' ] ) <EOL> if image : <EOL> return image <EOL> return Image . open ( path ( '<STR_LIT>' ) ) <EOL> def name ( self ) : <EOL> if not self . _name : <EOL> self . _name = self . fetch_name ( ) . strip ( ) <EOL> return self . _name <EOL> def fetch_name ( self ) : <EOL> """<STR_LIT>""" <EOL> soup = self . soup ( ) <EOL> if soup : <EOL> for tag in soup . findAll ( '<STR_LIT>' ) : <EOL> if tag . get ( '<STR_LIT>' ) == '<STR_LIT>' : <EOL> return tag [ '<STR_LIT:content>' ] <EOL> title_tag = soup . find ( '<STR_LIT:title>' ) <EOL> if title_tag : <EOL> return unicode ( title_tag . string ) <EOL> return '<STR_LIT>' <EOL> class OpenWebApp ( WebApp ) : <EOL> def mini_manifest ( self ) : <EOL> """<STR_LIT>""" <EOL> package_path = url_for ( '<STR_LIT>' , url = self . url , name = self . name ( ) , <EOL> icon_url = self . icon_url ) <EOL> return json . dumps ( { <EOL> '<STR_LIT:name>' : self . name ( ) , <EOL> '<STR_LIT:description>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : package_path , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:name>' : '<STR_LIT>' <EOL> } <EOL> } ) <EOL> def manifest ( self ) : <EOL> return json . dumps ( { <EOL> '<STR_LIT:name>' : self . name ( ) , <EOL> '<STR_LIT:description>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : { <EOL> <NUM_LIT> : '<STR_LIT>' <EOL> } , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:name>' : '<STR_LIT>' <EOL> } <EOL> } ) <EOL> def index_html ( self ) : <EOL> return render_template ( '<STR_LIT>' , app_url = self . url ) <EOL> def zipfile ( self ) : <EOL> return build_zipfile ( { <EOL> '<STR_LIT>' : self . manifest ( ) . encode ( '<STR_LIT:utf8>' ) , <EOL> '<STR_LIT>' : self . index_html ( ) . encode ( '<STR_LIT:utf8>' ) , <EOL> '<STR_LIT>' : self . icon_bytes ( ) , <EOL> } ) <EOL> class ChromeApp ( WebApp ) : <EOL> def manifest ( self ) : <EOL> return json . dumps ( { <EOL> '<STR_LIT>' : <NUM_LIT:2> , <EOL> '<STR_LIT:name>' : self . name ( ) , <EOL> '<STR_LIT:description>' : '<STR_LIT>' , <EOL> '<STR_LIT:version>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : [ '<STR_LIT>' ] <EOL> } <EOL> } , <EOL> '<STR_LIT>' : { <EOL> <NUM_LIT> : '<STR_LIT>' <EOL> } <EOL> } ) <EOL> def background_js ( self ) : <EOL> return render_template ( '<STR_LIT>' ) <EOL> def index_html ( self ) : <EOL> return render_template ( '<STR_LIT>' , app_url = self . url ) <EOL> def crxfile ( self ) : <EOL> zip_data = build_zipfile ( { <EOL> '<STR_LIT>' : self . manifest ( ) . encode ( '<STR_LIT:utf8>' ) , <EOL> '<STR_LIT>' : self . background_js ( ) . encode ( '<STR_LIT:utf8>' ) , <EOL> '<STR_LIT>' : self . index_html ( ) . encode ( '<STR_LIT:utf8>' ) , <EOL> '<STR_LIT>' : self . icon_bytes ( ) , <EOL> } ) <EOL> with open ( app . config [ '<STR_LIT>' ] , '<STR_LIT:rb>' ) as f : <EOL> private_key = serialization . load_pem_private_key ( <EOL> f . read ( ) , <EOL> password = None , <EOL> backend = default_backend ( ) <EOL> ) <EOL> signer = private_key . signer ( <EOL> padding . PKCS1v15 ( ) , <EOL> hashes . SHA1 ( ) <EOL> ) <EOL> signer . update ( zip_data ) <EOL> sig = signer . finalize ( ) <EOL> der = private_key . public_key ( ) . public_bytes ( <EOL> encoding = serialization . Encoding . DER , <EOL> format = serialization . PublicFormat . SubjectPublicKeyInfo <EOL> ) <EOL> der_len = struct . pack ( "<STR_LIT>" , len ( der ) ) <EOL> sig_len = struct . pack ( "<STR_LIT>" , len ( sig ) ) <EOL> out = StringIO ( ) <EOL> MAGIC = "<STR_LIT>" <EOL> VERSION = struct . pack ( "<STR_LIT>" , <NUM_LIT:2> ) <EOL> data = [ MAGIC , VERSION , der_len , sig_len , der , sig , zip_data ] <EOL> for d in data : <EOL> out . write ( d ) <EOL> crx = out . getvalue ( ) <EOL> out . close ( ) <EOL> return crx <EOL> def resize_square ( image , size ) : <EOL> width , height = image . size <EOL> if width != size or height != size : <EOL> return image . resize ( ( size , size ) , Image . BILINEAR ) <EOL> else : <EOL> return image <EOL> def download_image ( image_url ) : <EOL> if image_url . startswith ( '<STR_LIT>' ) : <EOL> image_url = '<STR_LIT>' + image_url <EOL> response = requests . get ( image_url ) <EOL> if response . status_code != <NUM_LIT:200> : <EOL> return None <EOL> return Image . open ( StringIO ( response . content ) ) <EOL> def build_zipfile ( files ) : <EOL> """<STR_LIT>""" <EOL> out = StringIO ( ) <EOL> with ZipFile ( out , '<STR_LIT:w>' ) as zipf : <EOL> for filename , file_contents in files . items ( ) : <EOL> zipf . writestr ( filename , file_contents ) <EOL> zip_contents = out . getvalue ( ) <EOL> out . close ( ) <EOL> return zip_contents </s>
