commit 8d2cd78d41c2cfe07dd3f55af1f3d9e13ad383fb Author: yutent Date: Tue Aug 8 17:52:42 2023 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b187fbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +*.txt \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2683834 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# debian 软件源管理 + +一个简单的软件源管理工具, 允许用户自动切换主站软件源(国内镜像地址及debian官方源), 以及自行添加/删除第三方软件源。 + + +## Build +``` +Build +``` +dpkg-buildpackage --no-sign +``` \ No newline at end of file diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..2ee8ed1 --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ + +Package: debian-sources +Section: admin +Priority: optional +Maintainer: Yutent +Build-Depends: debhelper (>= 9), python3 +Architecture: all +Depends: python3-apt, + python3-gi, + gir1.2-gdkpixbuf-2.0, + gir1.2-glib-2.0, + gir1.2-gtk-3.0, + inxi, + lsb-release +Description: 一个简单的软件源管理工具. + 允许用户自动切换主站软件源(国内镜像地址及debian官方源), 以及自行添加/删除第三方软件源。 diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..8b7e45d --- /dev/null +++ b/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +export RUN_ENV='development' + +if [ $UID == 0 ]; then + ./usr/lib/debian-sources/debian-sources.py +else + export SUDO_ASKPASS=${HOME}/.local/bin/scripts/rofi_password.sh + sudo -E -A $0 +fi diff --git a/usr/bin/debian-sources b/usr/bin/debian-sources new file mode 100755 index 0000000..f68e97d --- /dev/null +++ b/usr/bin/debian-sources @@ -0,0 +1,7 @@ +#!/bin/bash + +if [ $UID == 0 ]; then + /usr/lib/debian-sources/debian-sources.py +else + pkexec /usr/bin/debian-sources +fi diff --git a/usr/lib/debian-sources/debian-sources.py b/usr/lib/debian-sources/debian-sources.py new file mode 100755 index 0000000..802df48 --- /dev/null +++ b/usr/lib/debian-sources/debian-sources.py @@ -0,0 +1,66 @@ +#!/usr/bin/python3 + +import gi, os, signal, threading, sys, subprocess + +gi.require_version('Gtk', '3.0') + + +from gi.repository import Gtk, Gdk, GLib, Gio, GObject +from gi.repository.GdkPixbuf import Pixbuf +from aptsources.sourceslist import SourcesList + + +from webengine.webview import WebviewEngine +from window import Window + + + +# Used as a decorator to run things in the background +def run_async(func): + def wrapper(*args, **kwargs): + thread = threading.Thread(target=func, args=args, kwargs=kwargs) + thread.daemon = True + thread.start() + return thread + return wrapper + +# Used as a decorator to run things in the main loop, from another thread +def idle(func): + def wrapper(*args): + GObject.idle_add(func, *args) + return wrapper + +def signal_handler(signum, _): + print("") + sys.exit(128 + signum) + +signal.signal(signal.SIGINT, signal_handler) + + +class Application(object): + def __init__(self): + self.window = Window() + self.webview = WebviewEngine(self) + + self.window.add(self.webview) + + def run(self): + self.window.connect("destroy", self.close) + self.window.show_all() + Gtk.main() + + def close(self, win = None): + print('朕要休息了~~~') + Gtk.main_quit() + + + +if __name__ == "__main__": + codename = subprocess.getoutput("lsb_release -sc") + + + print ("LSB codename: '%s'." % codename) + # sys.exit(1) + + Application().run() + diff --git a/usr/lib/debian-sources/webapp/app.js b/usr/lib/debian-sources/webapp/app.js new file mode 100644 index 0000000..728ad1e --- /dev/null +++ b/usr/lib/debian-sources/webapp/app.js @@ -0,0 +1,36 @@ +/** + * {} + * @author yutent + * @date 2023/07/20 14:19:13 + */ + +import 'es.shim' +import { html, css, Component } from 'wkit' + +class App extends Component { + static props = { + input: '', + img: '', + content: '' + } + + static styles = [ + css` + .output { + max-width: 100%; + white-space: pre-wrap; + word-break: break-all; + } + ` + ] + + render() { + return html`

it works

` + } + + quit() { + native.quit() + } +} + +App.reg('app') diff --git a/usr/lib/debian-sources/webapp/index.html b/usr/lib/debian-sources/webapp/index.html new file mode 100644 index 0000000..6341378 --- /dev/null +++ b/usr/lib/debian-sources/webapp/index.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/usr/lib/debian-sources/webapp/lib/crypto.js b/usr/lib/debian-sources/webapp/lib/crypto.js new file mode 100644 index 0000000..5f11a5e --- /dev/null +++ b/usr/lib/debian-sources/webapp/lib/crypto.js @@ -0,0 +1 @@ +var F=new TextEncoder,D=new TextDecoder;function d(a){return F.encode(a)}function S(a){return D.decode(a)}function C(a){return Object.prototype.toString.call(a).slice(8,-1)}var c=[],s=[],O=typeof Uint8Array!="undefined"?Uint8Array:Array,b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(y=0,U=b.length;y0;)a+="=",n++;var r=a.indexOf("=");r===-1&&(r=n);var t=r===n?0:4-r%4;return[r,t]}function E(a,n,r){return(n+r)*3/4-r}function K(a){var n,r=$(a),t=r[0],f=r[1],e=new O(E(a,t,f)),o=0,h=f>0?t-4:t,u;for(u=0;u>16&255,e[o++]=n>>8&255,e[o++]=n&255;return f===2&&(n=s[a.charCodeAt(u)]<<2|s[a.charCodeAt(u+1)]>>4,e[o++]=n&255),f===1&&(n=s[a.charCodeAt(u)]<<10|s[a.charCodeAt(u+1)]<<4|s[a.charCodeAt(u+2)]>>2,e[o++]=n>>8&255,e[o++]=n&255),e}function N(a){return c[a>>18&63]+c[a>>12&63]+c[a>>6&63]+c[a&63]}function R(a,n,r){for(var t,f=[],e=n;eh?h:o+e));return t===1?(n=a[r-1],f.push(c[n>>2]+c[n<<4&63]+"==")):t===2&&(n=(a[r-2]<<8)+a[r-1],f.push(c[n>>10]+c[n>>4&63]+c[n<<2&63]+"=")),f.join("")}function z(a){return q(d(a))}function G(a){return S(K(a))}var J=function(a,n){return a+n&4294967295},L=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];function p(a,n){var r=a[0],t=a[1],f=a[2],e=a[3];r+=(t&f|~t&e)+n[0]-680876936|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&f)+n[1]-389564586|0,e=(e<<12|e>>>20)+r|0,f+=(e&r|~e&t)+n[2]+606105819|0,f=(f<<17|f>>>15)+e|0,t+=(f&e|~f&r)+n[3]-1044525330|0,t=(t<<22|t>>>10)+f|0,r+=(t&f|~t&e)+n[4]-176418897|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&f)+n[5]+1200080426|0,e=(e<<12|e>>>20)+r|0,f+=(e&r|~e&t)+n[6]-1473231341|0,f=(f<<17|f>>>15)+e|0,t+=(f&e|~f&r)+n[7]-45705983|0,t=(t<<22|t>>>10)+f|0,r+=(t&f|~t&e)+n[8]+1770035416|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&f)+n[9]-1958414417|0,e=(e<<12|e>>>20)+r|0,f+=(e&r|~e&t)+n[10]-42063|0,f=(f<<17|f>>>15)+e|0,t+=(f&e|~f&r)+n[11]-1990404162|0,t=(t<<22|t>>>10)+f|0,r+=(t&f|~t&e)+n[12]+1804603682|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&f)+n[13]-40341101|0,e=(e<<12|e>>>20)+r|0,f+=(e&r|~e&t)+n[14]-1502002290|0,f=(f<<17|f>>>15)+e|0,t+=(f&e|~f&r)+n[15]+1236535329|0,t=(t<<22|t>>>10)+f|0,r+=(t&e|f&~e)+n[1]-165796510|0,r=(r<<5|r>>>27)+t|0,e+=(r&f|t&~f)+n[6]-1069501632|0,e=(e<<9|e>>>23)+r|0,f+=(e&t|r&~t)+n[11]+643717713|0,f=(f<<14|f>>>18)+e|0,t+=(f&r|e&~r)+n[0]-373897302|0,t=(t<<20|t>>>12)+f|0,r+=(t&e|f&~e)+n[5]-701558691|0,r=(r<<5|r>>>27)+t|0,e+=(r&f|t&~f)+n[10]+38016083|0,e=(e<<9|e>>>23)+r|0,f+=(e&t|r&~t)+n[15]-660478335|0,f=(f<<14|f>>>18)+e|0,t+=(f&r|e&~r)+n[4]-405537848|0,t=(t<<20|t>>>12)+f|0,r+=(t&e|f&~e)+n[9]+568446438|0,r=(r<<5|r>>>27)+t|0,e+=(r&f|t&~f)+n[14]-1019803690|0,e=(e<<9|e>>>23)+r|0,f+=(e&t|r&~t)+n[3]-187363961|0,f=(f<<14|f>>>18)+e|0,t+=(f&r|e&~r)+n[8]+1163531501|0,t=(t<<20|t>>>12)+f|0,r+=(t&e|f&~e)+n[13]-1444681467|0,r=(r<<5|r>>>27)+t|0,e+=(r&f|t&~f)+n[2]-51403784|0,e=(e<<9|e>>>23)+r|0,f+=(e&t|r&~t)+n[7]+1735328473|0,f=(f<<14|f>>>18)+e|0,t+=(f&r|e&~r)+n[12]-1926607734|0,t=(t<<20|t>>>12)+f|0,r+=(t^f^e)+n[5]-378558|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^f)+n[8]-2022574463|0,e=(e<<11|e>>>21)+r|0,f+=(e^r^t)+n[11]+1839030562|0,f=(f<<16|f>>>16)+e|0,t+=(f^e^r)+n[14]-35309556|0,t=(t<<23|t>>>9)+f|0,r+=(t^f^e)+n[1]-1530992060|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^f)+n[4]+1272893353|0,e=(e<<11|e>>>21)+r|0,f+=(e^r^t)+n[7]-155497632|0,f=(f<<16|f>>>16)+e|0,t+=(f^e^r)+n[10]-1094730640|0,t=(t<<23|t>>>9)+f|0,r+=(t^f^e)+n[13]+681279174|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^f)+n[0]-358537222|0,e=(e<<11|e>>>21)+r|0,f+=(e^r^t)+n[3]-722521979|0,f=(f<<16|f>>>16)+e|0,t+=(f^e^r)+n[6]+76029189|0,t=(t<<23|t>>>9)+f|0,r+=(t^f^e)+n[9]-640364487|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^f)+n[12]-421815835|0,e=(e<<11|e>>>21)+r|0,f+=(e^r^t)+n[15]+530742520|0,f=(f<<16|f>>>16)+e|0,t+=(f^e^r)+n[2]-995338651|0,t=(t<<23|t>>>9)+f|0,r+=(f^(t|~e))+n[0]-198630844|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~f))+n[7]+1126891415|0,e=(e<<10|e>>>22)+r|0,f+=(r^(e|~t))+n[14]-1416354905|0,f=(f<<15|f>>>17)+e|0,t+=(e^(f|~r))+n[5]-57434055|0,t=(t<<21|t>>>11)+f|0,r+=(f^(t|~e))+n[12]+1700485571|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~f))+n[3]-1894986606|0,e=(e<<10|e>>>22)+r|0,f+=(r^(e|~t))+n[10]-1051523|0,f=(f<<15|f>>>17)+e|0,t+=(e^(f|~r))+n[1]-2054922799|0,t=(t<<21|t>>>11)+f|0,r+=(f^(t|~e))+n[8]+1873313359|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~f))+n[15]-30611744|0,e=(e<<10|e>>>22)+r|0,f+=(r^(e|~t))+n[6]-1560198380|0,f=(f<<15|f>>>17)+e|0,t+=(e^(f|~r))+n[13]+1309151649|0,t=(t<<21|t>>>11)+f|0,r+=(f^(t|~e))+n[4]-145523070|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~f))+n[11]-1120210379|0,e=(e<<10|e>>>22)+r|0,f+=(r^(e|~t))+n[2]+718787259|0,f=(f<<15|f>>>17)+e|0,t+=(e^(f|~r))+n[9]-343485551|0,t=(t<<21|t>>>11)+f|0,a[0]=r+a[0]|0,a[1]=t+a[1]|0,a[2]=f+a[2]|0,a[3]=e+a[3]|0}function I(a){var n=[],r;for(r=0;r<64;r+=4)n[r>>2]=a.charCodeAt(r)+(a.charCodeAt(r+1)<<8)+(a.charCodeAt(r+2)<<16)+(a.charCodeAt(r+3)<<24);return n}function H(a){var n=[],r;for(r=0;r<64;r+=4)n[r>>2]=a[r]+(a[r+1]<<8)+(a[r+2]<<16)+(a[r+3]<<24);return n}function M(a){var n=a.length,r=[1732584193,-271733879,-1732584194,271733878],t,f,e,o,h,u;for(t=64;t<=n;t+=64)p(r,I(a.substring(t-64,t)));for(a=a.substring(t-64),f=a.length,e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t=0;t>2]|=a.charCodeAt(t)<<(t%4<<3);if(e[t>>2]|=128<<(t%4<<3),t>55)for(p(r,e),t=0;t<16;t+=1)e[t]=0;return o=n*8,o=o.toString(16).match(/(.*?)(.{0,8})$/),h=parseInt(o[2],16),u=parseInt(o[1],16)||0,e[14]=h,e[15]=u,p(r,e),r}function P(a){var n=a.length,r=[1732584193,-271733879,-1732584194,271733878],t,f,e,o,h,u;for(t=64;t<=n;t+=64)p(r,H(a.subarray(t-64,t)));for(a=t-64>2]|=a[t]<<(t%4<<3);if(e[t>>2]|=128<<(t%4<<3),t>55)for(p(r,e),t=0;t<16;t+=1)e[t]=0;return o=n*8,o=o.toString(16).match(/(.*?)(.{0,8})$/),h=parseInt(o[2],16),u=parseInt(o[1],16)||0,e[14]=h,e[15]=u,p(r,e),r}function Q(a){var n="",r;for(r=0;r<4;r+=1)n+=L[a>>r*8+4&15]+L[a>>r*8&15];return n}function l(a){var n;for(n=0;n>16)+(n>>16)+(r>>16);return t<<16|r&65535});typeof ArrayBuffer!="undefined"&&!ArrayBuffer.prototype.slice&&function(){function a(n,r){return n=n|0||0,n<0?Math.max(n+r,0):Math.min(n,r)}ArrayBuffer.prototype.slice=function(n,r){var t=this.byteLength,f=a(n,t),e=t,o,h,u,B;return r!==void 0&&(e=a(r,t)),f>e?new ArrayBuffer(0):(o=e-f,h=new ArrayBuffer(o),u=new Uint8Array(h),B=new Uint8Array(this,f,o),u.set(B),h)}}();function j(a){return/[\u0080-\uFFFF]/.test(a)&&(a=unescape(encodeURIComponent(a))),a}function V(a,n){var r=a.length,t=new ArrayBuffer(r),f=new Uint8Array(t),e;for(e=0;e>2]|=n.charCodeAt(t)<<(t%4<<3);return this._finish(f,r),e=l(this._hash),a&&(e=g(e)),this.reset(),e};i.prototype.reset=function(){return this._buff="",this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this};i.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}};i.prototype.setState=function(a){return this._buff=a.buff,this._length=a.length,this._hash=a.hash,this};i.prototype.destroy=function(){delete this._hash,delete this._buff,delete this._length};i.prototype._finish=function(a,n){var r=n,t,f,e;if(a[r>>2]|=128<<(r%4<<3),r>55)for(p(this._hash,a),r=0;r<16;r+=1)a[r]=0;t=this._length*8,t=t.toString(16).match(/(.*?)(.{0,8})$/),f=parseInt(t[2],16),e=parseInt(t[1],16)||0,a[14]=f,a[15]=e,p(this._hash,a)};i.hash=function(a,n){return i.hashBinary(j(a),n)};i.hashBinary=function(a,n){var r=M(a),t=l(r);return n?g(t):t};i.ArrayBuffer=function(){this.reset()};i.ArrayBuffer.prototype.append=function(a){var n=X(this._buff.buffer,a,!0),r=n.length,t;for(this._length+=a.byteLength,t=64;t<=r;t+=64)p(this._hash,H(n.subarray(t-64,t)));return this._buff=t-64>2]|=n[f]<<(f%4<<3);return this._finish(t,r),e=l(this._hash),a&&(e=g(e)),this.reset(),e};i.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this};i.ArrayBuffer.prototype.getState=function(){var a=i.prototype.getState.call(this);return a.buff=W(a.buff),a};i.ArrayBuffer.prototype.setState=function(a){return a.buff=V(a.buff,!0),i.prototype.setState.call(this,a)};i.ArrayBuffer.prototype.destroy=i.prototype.destroy;i.ArrayBuffer.prototype._finish=i.prototype._finish;i.ArrayBuffer.hash=function(a,n){var r=P(new Uint8Array(a)),t=l(r);return n?g(t):t};function Y(a){var n=new i;return n.append(a+""),n.end()}function Z(a){var n=new i.ArrayBuffer;return n.append(a),n.end()}var m=window.crypto.subtle,v=0,_=0;function T(a){let n=a!=null?a:"";switch(C(n)){case"Uint8Array":break;case"ArrayBuffer":n=new Uint8Array(n);break;case"Number":case"String":case"Boolean":n=d(n);break;default:n=n.toString();break}return n}function k(a="-"){var n=Math.random().toString(16).slice(2)+Math.random().toString(16).slice(2),r=(~~(Date.now()/1e3)).toString(16);return v===r?_++:(v=r,_=0),n=_.toString(16)+n,v+a+n.slice(0,4)+a+n.slice(4,8)+a+n.slice(-8)}function w(a){var n=new Uint8Array(a);return[...n].map(r=>r.toString(16).padStart(2,"0")).join("")}function x(a){for(var n="",r=new Uint8Array(a),t=0;tw(r))}function rr(a){return A("SHA-1",a)}function tr(a){return A("SHA-256",a)}function er(a){return A("SHA-512",a)}function nr(a,n="",r="",t){return r?typeof r=="string"&&(r=d(r)):r=new Uint8Array(16),m.importKey("raw",r,{name:"HMAC",hash:{name:a}},!0,["sign","verify"]).then(f=>m.sign("HMAC",f,T(n))).then(f=>{var e=f;switch(t){case"binary":e=x(f);break;case"hex":e=w(f);break;case"base64":e=window.btoa(x(f));break;case"buffer":e=new Uint8Array(f);break}return e})}export{x as ab2bin,w as ab2hex,G as base64decode,z as base64encode,A as hash,nr as hmac,Y as md5,Z as md5Sum,rr as sha1,tr as sha256,er as sha512,k as uuid}; diff --git a/usr/lib/debian-sources/webapp/lib/es.shim.js b/usr/lib/debian-sources/webapp/lib/es.shim.js new file mode 100644 index 0000000..fb3a7f5 --- /dev/null +++ b/usr/lib/debian-sources/webapp/lib/es.shim.js @@ -0,0 +1 @@ +(()=>{Object.empty||Object.defineProperty(Object,"empty",{value:function(e){try{for(let t in e)return!1}catch(t){}return!0}});Object.prototype.toParams||Object.defineProperty(Object.prototype,"toParams",{value:function(){let e="";for(let t in this)this[t]!==void 0&&(e+=`&${t}=${this[t]}`);return e.slice(1)}});Object.defineProperty(Array.prototype,"flat",{value:function(e=1,t=[]){for(let r of this)Array.isArray(r)&&e>0?r.flat(e-1,t):t.push(r);return t},writable:!0});Object.defineProperty(Array.prototype,"flatMap",{value:function(e){return this.map(e).flat()},writable:!0});Array.prototype.at||Object.defineProperty(Array.prototype,"at",{value:function(e){let t=+e;return t<0&&(t+=this.length),this[t]},writable:!0});Array.prototype.findLast||(Object.defineProperty(Array.prototype,"findLast",{value:function(e){let t=this.length;for(;t>0;){let r=this[--t];if(e(r,t))return r}},writable:!0}),Object.defineProperty(Array.prototype,"findLastIndex",{value:function(e){let t=this.length;for(;t>0;){let r=this[--t];if(e(r,t))return t}return-1},writable:!0}));Array.prototype.toSorted||(Object.defineProperty(Array.prototype,"toSorted",{value:function(e){return[...this].sort(e)},writable:!0}),Object.defineProperty(Array.prototype,"toReversed",{value:function(){return[...this].reverse()},writable:!0}),Object.defineProperty(Array.prototype,"toSpliced",{value:function(...e){return[...this].splice(...e)},writable:!0}),Object.defineProperty(Array.prototype,"with",{value:function(e,t){let r=+e,i=[...this];return r<0&&(r+=i.length),i[r]=t,i},writable:!0}));Array.prototype.group||(Object.defineProperty(Array.prototype,"group",{value:function(e){let t={};if(typeof e=="function"){for(let r of this){let i=e(r);t[i]?t[i].push(r):t[i]=[r]}return t}else throw Error("argument callback must be a function.")},writable:!0}),Object.defineProperty(Array.prototype,"groupToMap",{value:function(e){let t=new Map;if(typeof e=="function"){for(let r of this){let i=e(r);t.has(i)?t.get(i).push(r):t.set(i,[r])}return t}else throw Error("argument callback must be a function.")},writable:!0}));function n(e,t){if(e+="",t+="",e===t)return 0;{e=e.split("."),t=t.split(".");let r=Math.max(e.length,t.length);for(let i=0;iu)return 1;if(o=i?e=0:e=i+e),o===1)return this.slice(0,e);{t-=0;let u=this.slice(0,e),p=this.slice(e+t);return u+r+p}}});String.prototype.htmlspecialchars||Object.defineProperty(String.prototype,"htmlspecialchars",{value:function(e){let t=this.replace(/&(?!\w+;)/g,"&").replace(//g,">");return e==="ENT_QUOTES"?t.replace(/"/g,""").replace(/'/g,"'"):e==="ENT_NOQUOTES"?t:t.replace(/"/g,""")}});String.prototype.tohtml||Object.defineProperty(String.prototype,"tohtml",{value:function(){return this.replace(/</gi,"<").replace(/>/gi,">").replace(/"/gi,'"').replace(/'/g,"'").replace(/&/gi,"&")}});String.prototype.xss||Object.defineProperty(String.prototype,"xss",{value:function(){let e=this.htmlspecialchars("ENT_QUOTES");return e=e.replace(/(document\.cookie)|(document\.write)|(\.parentNode)|(window\.location)|(\.innerHTML)/g,"").replace(/(%0[0-8bcef])|(%1[0-9a-f])/g,""),e}});String.prototype.escape||Object.defineProperty(String.prototype,"escape",{value:function(){return this.replace(/('|"|&|\\|\}|\{|\(|\)|;|=|\,|&)/g,"\\$1")}});String.prototype.at||Object.defineProperty(String.prototype,"at",{value:function(e){let t=+e;return t<0&&(t+=this.length),this[t]},writable:!0});String.prototype.toJson||Object.defineProperty(String.prototype,"toJson",{value:function(){let e=this.replace(/^\?/,""),t=decodeURIComponent(e).split("&").filter(i=>i).map(i=>i.split("=")),r={};for(let i of t)r[i[0]]=i[1]||"";return r}});String.prototype.lt||(Object.defineProperty(String.prototype,"lt",{value:function(e){return n(this,e)===-1}}),Object.defineProperty(String.prototype,"lte",{value:function(e){return n(this,e)<1}}),Object.defineProperty(String.prototype,"gt",{value:function(e){return n(this,e)===1}}),Object.defineProperty(String.prototype,"gte",{value:function(e){return n(this,e)>-1}}),Object.defineProperty(String.prototype,"eq",{value:function(e){return n(this,e)===0}}));Number.parse||Object.defineProperty(Number,"parse",{value:function(e){return typeof e=="number"||typeof e=="string"?(e+="",e.startsWith("0")&&!e.startsWith("0.")?e==="0"?0:e:(isFinite(e)&&e>=Number.MIN_SAFE_INTEGER&&e<=Number.MAX_SAFE_INTEGER&&(e=+e),e)):e}});Number.fromString||Object.defineProperty(Number,"fromString",{value:function(e){return+e||0}});Date.isDate||Object.defineProperty(Date,"isDate",{value:function(e){return!!(e&&typeof e=="object"&&e.getTime)},writable:!0});Date.prototype.getFullWeek||(Object.defineProperty(Date.prototype,"getFullWeek",{value:function(){let e=this.getFullYear(),t=new Date(e,0,1),r=t.getDay(),i=(this-t)/24/360/1e3;return Math.ceil((i+r)/7)}}),Object.defineProperty(Date.prototype,"getWeek",{value:function(){let e=this.getDate(),t=this.getMonth(),r=this.getFullYear(),i=new Date(r,t,1).getDay();return Math.ceil((e+i)/7)}}));Date.prototype.format||Object.defineProperty(Date.prototype,"format",{value:function(e){let t={fullyear:this.getFullYear(),year:this.getYear(),fullweek:this.getFullWeek(),week:this.getWeek(),month:this.getMonth()+1,date:this.getDate(),day:this.getDay()+1,hours:this.getHours(),minutes:this.getMinutes(),seconds:this.getSeconds()},r=null;e=e||"Y-m-d H:i:s",t.g=t.hours>12?t.hours-12:t.hours,r={Y:t.fullyear,y:t.year,m:t.month<10?"0"+t.month:t.month,n:t.month,d:t.date<10?"0"+t.date:t.date,j:t.date,H:t.hours<10?"0"+t.hours:t.hours,h:t.g<10?"0"+t.g:t.g,G:t.hours,g:t.g,i:t.minutes<10?"0"+t.minutes:t.minutes,s:t.seconds<10?"0"+t.seconds:t.seconds,W:t.fullweek,w:t.week,D:t.day};for(let i in r)e=e.replace(new RegExp(i,"g"),r[i]);return e}});Promise.defer||(Promise.defer=function(){let e={};return e.promise=new Promise((t,r)=>{e.resolve=t,e.reject=r}),e});})(); diff --git a/usr/lib/debian-sources/webapp/lib/fetch.js b/usr/lib/debian-sources/webapp/lib/fetch.js new file mode 100644 index 0000000..1748dc2 --- /dev/null +++ b/usr/lib/debian-sources/webapp/lib/fetch.js @@ -0,0 +1 @@ +var h=encodeURIComponent;function a(n){return Object.prototype.toString.call(n).slice(8,-1)}function u(n,e,r){var i;if(Array.isArray(e))e.forEach(function(t,s){i=n?`${n}[${Array.isArray(t)?s:""}]`:s,typeof t=="object"?u(i,t,r):r(i,t)});else for(let t in e)i=n?`${n}[${t}]`:t,typeof e[t]=="object"?u(i,e[t],r):r(i,e[t])}var c={parseForm(n){let e={},r=!1;for(let i=0,t;t=n.elements[i++];)switch(t.type){case"select-one":case"select-multiple":if(t.name.length&&!t.disabled)for(let s=0,o;o=t.options[s++];)o.selected&&(e[t.name]=o.value||o.text);break;case"file":t.name.length&&!t.disabled&&(e[t.name]=t.files[0],r=!0);break;case void 0:case"submit":case"reset":case"button":break;case"radio":case"checkbox":if(!t.checked)break;default:t.name.length&&!t.disabled&&(e[t.name]=t.value)}return r?this.mkFormData(e):e},mkFormData(n){let e=new FormData;for(let r in n){let i=n[r];Array.isArray(i)?i.forEach(function(t){e.append(r+"[]",t)}):e.append(r,n[r])}return e},param(n){if(!n||typeof n=="string"||typeof n=="number")return n;let e=[];return typeof n=="object"&&u("",n,function(i,t){if(/native code/.test(t))return;let s=a(t);t=typeof t=="function"?t():t,t=s==="File"||s==="Blob"?t:h(t),e.push(h(i)+"="+t)}),e.join("&")}};var _=window.fetch,F=["GET","HEAD"],y={form:"application/x-www-form-urlencoded; charset=UTF-8",json:"application/json; charset=UTF-8",text:"text/plain; charset=UTF-8"},g={10001:"Argument url is required",10012:"Parse error",10100:"Request canceled",10104:"Request pending...",10200:"Ok",10204:"No content",10304:"Not modified",10500:"Internal Server Error",10504:"Connected timeout"},d=class{constructor(e="",r={},i){if(!e)throw new Error(g[10001]);if(e=e.replace(/#.*$/,""),i.BASE_URL&&(/^([a-z]+:|\/\/)/.test(e)||(e=i.BASE_URL+e)),r.method=(r.method||"get").toUpperCase(),this._owner=i,this.options={headers:{"content-type":y.form},body:null,cache:"default",signal:null,timeout:3e4},r.signal||(this.control=new AbortController,r.signal=this.control.signal),r.headers){let t=this.options.headers;Object.assign(t,r.headers),r.headers=t}return Object.assign(this.options,r,{url:e}),i._inject_req&&i._inject_req(this.options),this.__next__()}__next__(){var e=this.options,r=!1,i=F.includes(e.method);if(e.body){var t=typeof e.body;switch(t){case"number":case"string":this.__type__("text");break;case"object":if(e.body.nodeName==="FORM")e.method=e.body.method.toUpperCase()||"POST",e.body=c.parseForm(e.body),r=e.body.constructor===FormData;else if(e.body.constructor===FormData)r=!0,i&&(e.method="POST");else{for(let o in e.body)if(Array.isArray(e.body[o])||a(e.body[o])==="FileList")e.body[o]=Array.from(e.body[o]),r=e.body[o].some(l=>a(l)==="File"||a(l)==="Blob");else if(a(e.body[o])==="File"||a(e.body[o])==="Blob"){r=!0;break}r&&(i&&(e.method="POST"),e.body=c.mkFormData(e.body))}break}}else delete e.headers["content-type"];if(r&&delete e.headers["content-type"],i){let o=c.param(e.body);o&&(e.url+=(~e.url.indexOf("?")?"&":"?")+o),delete e.body}else e.body&&!r&&(~e.headers["content-type"].indexOf("json")?e.body=JSON.stringify(e.body):e.body=c.param(e.body));e.timeout&&e.timeout>0&&(this.timer=setTimeout(o=>{this.abort()},e.timeout),delete e.timeout);var s=e.url;delete e.url;for(let o in e)(e[o]===null||e[o]===void 0||e[o]==="")&&delete e[o];return _(s,e).then(o=>{clearTimeout(this.timer);let l=o.status>=200&&o.status<400,m;return this._owner._inject_res&&(o=this._owner._inject_res(o),m=a(o)),l?o:m==="Promise"?o.then(b=>Promise.reject(b)):Promise.reject(o)}).catch(o=>(clearTimeout(this.timer),Promise.reject(o)))}abort(){this.control.abort()}__type__(e){this.options.headers["content-type"]=y[e]}};function p(n){n.inject={request(e){n._inject_req=e},response(e){n._inject_res=e}}}var f=function(n,e){return new d(n,e,f)};f.create=function(){var n=function(e,r){return new d(e,r,n)};return p(n),n};p(f);var O=f;export{O as default}; diff --git a/usr/lib/debian-sources/webapp/lib/wkit.js b/usr/lib/debian-sources/webapp/lib/wkit.js new file mode 100644 index 0000000..3063769 --- /dev/null +++ b/usr/lib/debian-sources/webapp/lib/wkit.js @@ -0,0 +1,3 @@ +var y=Object.create(null);["autofocus","autoplay","async","allowTransparency","checked","controls","declare","disabled","defer","defaultChecked","defaultSelected","contentEditable","isMap","loop","multiple","noHref","noResize","noShade","open","readOnly","selected","loading"].forEach(function(i){y[i.toLowerCase()]=i});var H=Symbol("wc_path"),p=Symbol("wc-nothing"),z=Symbol("finalized"),x=Symbol("props"),N=Symbol("changed_props"),w=Symbol("mounted"),g=Symbol("pending"),V=Symbol("children"),oe="* {box-sizing: border-box;margin: 0;padding: 0;}::before,::after {box-sizing: border-box;}";function re(i){switch(i){case Number:return 0;case Boolean:return!1;case Object:return{};case Array:return[];default:return""}}function Ee(i){switch(typeof i){case"number":return{type:Number,default:i};case"boolean":return{type:Boolean,default:i};case"object":return Array.isArray(i)?{type:Array,default:i}:{type:Object,default:i};default:return{type:String,default:i+""}}}function le(i){if(i&&typeof i=="object"&&i.hasOwnProperty("type"))return Object.assign({attribute:!0,default:re(i.type)},i);switch(i){case Number:i={type:Number};break;case Boolean:i={type:Boolean};break;case Object:i={type:Object};break;case Array:i={type:Array};break;default:i=Ee(i);break}return i.default=i.hasOwnProperty("default")?i.default:re(i.type),i.attribute=!0,i}function B(i,e){switch(e.type){case Number:return i===null?null:+i||0;case Boolean:return i===!1?!1:i!==null;case Object:if(typeof i=="object")return i;try{return JSON.parse(i)}catch{return{}}case Array:if(typeof i=="object")return i;try{return JSON.parse(i)}catch{return[]}default:return i==null?null:i+""}}var ae=CSSStyleSheet;document.adoptedStyleSheets||(ae=class{elem=document.createElement("style");replaceSync(i){this.elem.textContent=i.replace(/\s+/g," ")}});function Se(i,...e){let t="",s=Array.from(i);for(;s.length;)t+=s.shift()+(e.shift()||"");return t}function ce(i,e=""){let t=new ae;typeof e=="string"?e=[e]:e=e.flat(1/0),e=(oe+e.join(" ")).trim(),t.replaceSync(e),i.adoptedStyleSheets?i.adoptedStyleSheets=[t]:i.appendChild(t.elem)}function O(i=200,e=[],t=!1){t===!1&&(this.style.display="");let s=this.animate(e,{duration:i,direction:t?"reverse":"normal",fill:"forwards"});return new Promise(n=>{s.addEventListener("finish",o=>{t&&(this.style.display="none"),s.cancel(),n()},{once:!0})})}var C={fade:[{opacity:0},{opacity:1}],scale:[{transform:"scale(0)"},{transform:"scale(1)"}],"micro-bounce":[{opacity:0,transform:"scale(0.8)"},{transform:"scale(1.05)",opacity:1},{transform:"scale(1)"}],slide:[{opacity:0,transform:"translateY(-50px)"},{opacity:1,transform:"translateY(0)"}],bounce:[{transform:"scale(0)"},{transform:"scale(1.2)"},{transform:"scale(1)"}],rotate:[{transform:"rotate(0)"},{transform:"rotate(360deg)"}]};var Y="$wc$",_=`wc$${String(Math.random()).slice(9)}$`,ye="?"+_,Ce=`<${ye}>`,k=(i="")=>document.createComment(i),R=i=>i===null||typeof i!="object"&&typeof i!="function",ge=Array.isArray,Te=i=>ge(i)||typeof(i==null?!1:i[Symbol.iterator])=="function",D=`[ +\f\r]`,ke=`[^ +\f\r"'\`<>=]`,Ve=`[^\\s"'>=/]`,T=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,he=1,U=2,Oe=3,fe=/-->/g,de=/>/g,$=new RegExp(`>|${D}(?:(${Ve}+)(${D}*=${D}*(?:${ke}|("|')|))|$)`,"g"),Re=0,ue=1,Me=2,pe=3,me=/'/g,_e=/"/g,$e=/^(?:script|style|textarea|title)$/i,ve=1,M=2,X=1,v=2,Pe=5,F=6,Ie=7,be=new WeakMap,b=document.createTreeWalker(document,129,null,!1);function W(){}function Le(i,e){let t=i.length-1,s=[],n=e===M?"":"",o,r=T;for(let a=0;a"?(r=o??T,u=-1):h[ue]===void 0?u=-2:(u=r.lastIndex-h[Me].length,d=h[ue],r=h[pe]===void 0?$:h[pe]==='"'?_e:me):r===_e||r===me?r=$:r===fe||r===de?r=T:(r=$,o=void 0);let L=r===$&&i[a+1].startsWith("/>")?" ":"";n+=r===T?c+Ce:u>=0?(s.push(d),c.slice(0,u)+Y+c.slice(u)+_+L):c+_+(u===-2?(s.push(void 0),a):L)}let l=n+(i[t]||"")+(e===M?"":"");if(!Array.isArray(i)||!i.hasOwnProperty("raw"))throw new Error("invalid html ast");return[l,s]}var A=class{constructor({strings:e,["__dom_type__"]:t},s){this.parts=[];let n,o=0,r=0,l=e.length-1,a=this.parts,[c,u]=Le(e,t);if(this.el=A.createElement(c),b.currentNode=this.el.content,t===M){let d=this.el.content,f=d.firstChild;f.remove(),d.append(...f.childNodes)}for(;(n=b.nextNode())!==null&&a.length0){n.textContent="";for(let h=0;h2||s[0]!==""||s[1]!==""?(this._$committedValue=new Array(s.length-1).fill(new String),this.strings=s):this._$committedValue=p}get tagName(){return this.element.tagName}get _$isConnected(){return this._$parent._$isConnected}_$setValue(e,t){let s=this.strings,n=!1;if(s===void 0)n=!R(e)||e!==this._$committedValue,n&&(this._$committedValue=e);else{let o=e;e=s[0];for(let r=0;rr.stopPropagation();break;case"prevent":this.#t=r=>r.preventDefault();break;case"self":this.#s=r=>r.target===this.element;break;case"capture":case"once":case"passive":s[o]=!0;break}let n=e!==this.#e;if(this.#e&&t.$events[this.name]){for(let o of t.$events[this.name])if(o.el===this.element){n=s.capture!==o.capture||s.once!==o.once||s.passive!==o.passive,n&&this.element.removeEventListener(this.name,o.listener,o.options);break}}e&&n&&(this.element.addEventListener(this.name,this,s),this.#e=e,t.$events[this.name]?t.$events[this.name].push({el:this.element,listener:this,options:s}):t.$events[this.name]=[{el:this.element,listener:this,options:s}])}handleEvent(e){this.#i(e),this.#t(e),this.#s(e)!==!1&&this.#e.call(this.options.host,e)}},J=class{constructor(e,t,s){this.element=e,this.type=F,this._$disconnectableChildren=void 0,this._$parent=t,this.options=s}get _$isConnected(){return this._$parent._$isConnected}_$setValue(e){}};function xe(i,e,t={}){let s=e[H];return s===void 0&&(e[H]=s=new E(e.insertBefore(k(),null),null,void 0,t)),s._$setValue(i),s}function K(i,...e){return{__dom_type__:ve,strings:i,values:e}}function je(i){let e=[i];return e.raw=e,K(e)}function He(i,...e){return{__dom_type__:M,strings:i,values:e}}function P(){}function ee(i,e,t){let s=t?"querySelectorAll":"querySelector";return e?e[s](i):document.body[s](i)}function ze(i,e){return ee(i,e,!0)}var te=function(){let i=[],e=document.createTextNode(""),t=!1;function s(){let n=i.length;for(let o=0;ot.toUpperCase())}function Be(i){try{let e=i.getBoundingClientRect();if(e.width||e.height||i.getClientRects().length){let t=i.ownerDocument,s=t.documentElement,n=t.defaultView;return{top:e.top+n.pageYOffset-s.clientTop,left:e.left+n.pageXOffset-s.clientLeft}}}catch{return{left:0,top:0}}}function ne(i,e,t,s,n=!0){let o=e.split(","),r,l=i.host===i,a=l?i:null;if(typeof t=="function"?(n=s,s=t,t=null):(typeof t!="string"&&(t=null),s=s||P),l===!1){let c=i;for(;c&&c!==document.body&&c!==document;){if(c.ownHost){l=!0,a=c.ownHost;break}c=c.parentNode}}return t?r=function(c){let u=ee(t,i),d=c.target;if(u)for(;d!==i;)if(u.contains(d)){s(c);break}else d=d.parentNode}:r=s,o.forEach(function(c){c=c.trim(),l&&(a.$events[c]?a.$events[c].push({el:i,listener:r,options:n}):a.$events[c]=[{el:i,listener:r,options:n}]),i.addEventListener(c,r,n)}),r}function I(i,e,t=P,s=!1){e.split(",").forEach(function(o){i.removeEventListener(o.trim(),t,s)})}function De(i,e=P){return ne(document,"mousedown",t=>{let s=t.composedPath?t.composedPath():t.path;if(s){for(;s.length>3;)if(s.shift()===i)return}else{let n=t.explicitOriginalTarget||t.target;if(i===n||i.contains(n)||i.root&&i.root.contains(n))return}e(t)})}function Ue(i=P){I(document,"mousedown",i)}function Ne(i,e="click",t={},s){let n=new Event(e,{bubbles:!s,cancelable:!0});Object.assign(n,t),i.dispatchEvent(n)}function nt(i={}){let e="";for(let t in i)i[t]&&(e+=" "+t);return e.slice(1)}function rt(i={}){let e="";for(let t in i)(i[t]||i[t]===0)&&(e+=ie(t)+":"+i[t]+";");return e}var we=class extends HTMLElement{static get observedAttributes(){let e=[];return this.finalize(),this.parseAnim(),this[x].forEach((t,s)=>{e.push(t.attrName)}),e}static createProperty(e,t){let s=Symbol(e),n={get(){return this[s]},set(o){let r=this[s];o=B(o,t),r!==o&&(this[s]=o,this.$requestUpdate(e,r),t.observer&&t.observer.call(this,o,r))},enumerable:!1};this[x].set(e,t),Object.defineProperty(this.prototype,e,n)}static parseAnim(){if(this.hasOwnProperty("animation")){let{type:e="fade",duration:t}=this.animation;Object.defineProperty(this.prototype,"$animate",{value(s){if(this[w])return O.call(this,t,C[e],s)},enumerable:!1}),delete this.animation}}static finalize(){if(this[z])return!1;if(this[z]=!0,this[x]=new Map,this.hasOwnProperty("props"))for(let e in this.props){let t=le(this.props[e]),s=e.toLowerCase();t.attrName=s,y[s]?e=y[s]:(t.attrName=ie(e),e=se(e)),this.createProperty(e,t)}delete this.props}static reg(e=""){e="wc-"+e,customElements.get(e)||customElements.define(e,this)}constructor(){super(),this[g]=!1,this[w]=!1,this[N]=new Map,this.host=this,this.root=this.shadowRoot||this.attachShadow({mode:"open"}),this.root.ownHost=this,Object.defineProperty(this,"$refs",{value:Object.create(null),enumerable:!1}),Object.defineProperty(this,"$events",{value:Object.create(null),enumerable:!1}),this.created()}#e(){this[N]=new Map,this.constructor[x].forEach((e,t)=>{this[t]=this[t]===void 0?e.default:this[t]}),this[g]===!1&&(this[g]=!0,te(e=>this.#n()))}#t(e){return this.constructor[x].get(e)}connectedCallback(){this.$animate&&(this.style.display="none"),this.#e(),ce(this.root,this.constructor.styles),this[V]?.setConnected(!0)}disconnectedCallback(){if(this[V]?.setConnected(!1),!document.body?.contains(this)){let e=this.$events;if(e)for(let t in e)for(let s of e[t])I(s.el,t,s.listener,s.options)}this.unmounted()}attributeChangedCallback(e,t,s){t!==s&&this.#s(e,s,t)}#i(e,t){let s=this.#t(e),n=s.attrName;if(s.attribute===!1){this.removeAttribute(n);return}switch(s.type){case Number:case String:t===null?this.removeAttribute(n):this.setAttribute(n,t);break;case Boolean:t===null||t===!1?this.removeAttribute(n):this.setAttribute(n,"");break}}#s(e,t,s){let n=y[e],o,r;if(n&&(e=n),r=se(e),o=this.#t(r),t=B(t,o),o.attribute===!1){if(t===null)return;if(t===this[r]){this.removeAttribute(e);return}}this[r]=t}$requestUpdate(e,t){e!==void 0&&(this[N].set(e,this[e]),this.#i(e,this[e])),this[g]===!1&&(this[g]=!0,te(s=>this.#n()))}#n(){let e=this[N];this.#l(),this.#r(e),this.#o()}#r(e){this[w]===!1?(this[w]=!0,this.mounted()):this.updated(e)}#o(){this[N]=new Map,this[g]=!1}#l(){let e=this.render();this[V]=xe(e,this.root,{host:this,isConnected:!this[w]&&this.isConnected})}created(){}mounted(){}unmounted(){}updated(){}render(){return K``}$on(e,t,s){return ne(this,e,t,s)}$off(e,t,s){I(this,e,t,s)}$emit(e,t={},s=!1){return Ne(this,e,t,s)}};export{ee as $,ze as $$,we as Component,ne as bind,se as camelize,nt as classMap,Ue as clearOutsideClick,Se as css,Ne as fire,K as html,ie as hyphen,te as nextTick,Be as offset,De as outsideClick,je as raw,rt as styleMap,He as svg,I as unbind}; diff --git a/usr/lib/debian-sources/webengine/_inject.py b/usr/lib/debian-sources/webengine/_inject.py new file mode 100644 index 0000000..1c73b32 --- /dev/null +++ b/usr/lib/debian-sources/webengine/_inject.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# @author yutent +# @date 2023/08/08 15:00:27 + + +import os, gi + +gi.require_version("WebKit2", "4.1") + +from gi.repository import WebKit2 + + +class Inject: + def __init__(self, webview): + + self.manager = webview.get_user_content_manager() + + script = open(self.abspath('./inject.js'), 'r').read() + frame = WebKit2.UserContentInjectedFrames.ALL_FRAMES + time = WebKit2.UserScriptInjectionTime.END + script = WebKit2.UserScript(script, frame, time, None, None) + + self.manager.add_script(script) + + + def connect(self, callback): + self.manager.connect('script-message-received::app', callback) + self.manager.register_script_message_handler('app') + + + def abspath(self, filepath): + root = os.path.dirname(os.path.realpath(__file__)) + return os.path.join(root, filepath) \ No newline at end of file diff --git a/usr/lib/debian-sources/webengine/_mimetypes.py b/usr/lib/debian-sources/webengine/_mimetypes.py new file mode 100644 index 0000000..813186f --- /dev/null +++ b/usr/lib/debian-sources/webengine/_mimetypes.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +mime_types = { + 'html': 'text/html', + 'txt': 'text/plain', + 'css': 'text/css', + 'xml': 'text/xml', + 'gif': 'image/gif', + 'jpg': 'image/jpeg', + 'webp': 'image/webp', + 'tiff': 'image/tiff', + 'png': 'image/png', + 'svg': 'image/svg+xml', + 'ico': 'image/x-icon', + 'bmp': 'image/x-ms-bmp', + 'js': 'application/javascript', + 'json': 'application/json', + 'mp3': 'audio/mpeg', + 'ogg': 'audio/ogg', + 'm4a': 'audio/x-m4a', + 'mp4': 'video/mp4', + 'webm': 'video/webm', + 'ttf': 'font/font-ttf', + 'woff': 'font/font-woff', + 'woff2': 'font/font-woff2', + 'wast': 'application/wast', + 'wasm': 'application/wasm', + 'other': 'application/octet-stream' +} + +def get_mimetype(name): + return mime_types.get(name) or mime_types['html'] \ No newline at end of file diff --git a/usr/lib/debian-sources/webengine/_protocal.py b/usr/lib/debian-sources/webengine/_protocal.py new file mode 100644 index 0000000..1ba5af8 --- /dev/null +++ b/usr/lib/debian-sources/webengine/_protocal.py @@ -0,0 +1,48 @@ + +import os +from gi.repository import Gio, WebKit2 +from ._mimetypes import get_mimetype + + + + +class Protocal: + def __init__(self, webview, webroot = ''): + self.webview = webview + self.root = os.path.realpath(webroot) + + def register(self, name = 'app'): + self.protocal = name + ctx = self.webview.get_context() + ctx.register_uri_scheme(name, self.handle_response) + # 允许网页通知权限 + ctx.initialize_notification_permissions([WebKit2.SecurityOrigin.new_for_uri('app:///index.html')], []) + + + def abspath(self, filepath): + return os.path.join(self.root, filepath) + + + def handle_response(self, req): + schema = req.get_scheme() + pathname = req.get_path()[1:] + ext = pathname.split('.')[-1] + + # print('----------------------------------------') + # print(req.get_uri(),schema, pathname, ext, get_mimetype(ext)) + # print('----------------------------------------') + + if schema == self.protocal: + data = open(self.abspath(pathname)).read() + data = Gio.MemoryInputStream.new_from_data(data.encode()) + + # ------- 更多功能的reponse ---------------- + # res = WebKit2.URISchemeResponse.new(data, -1) + # res.set_content_type(get_mimetype(ext)) + # res.set_http_headers('text/html') + # res.set_status(200) + # req.finish_with_response(res) + # ---------------------------------------- + + # 简单的response + req.finish(data, -1, get_mimetype(ext)) \ No newline at end of file diff --git a/usr/lib/debian-sources/webengine/_settings.py b/usr/lib/debian-sources/webengine/_settings.py new file mode 100644 index 0000000..3025c0d --- /dev/null +++ b/usr/lib/debian-sources/webengine/_settings.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# @author yutent +# @date 2023/08/08 14:07:26 + + +import gi, os + +gi.require_version("WebKit2", "4.1") + +from gi.repository import WebKit2 + + +class Settings(WebKit2.Settings): + def __init__(self, disable_security = True, fullscreen = True): + + WebKit2.Settings.__init__(self) + + self.set_enable_page_cache(True) + self.set_enable_offline_web_application_cache(True) + + self.set_javascript_can_access_clipboard(True) + self.set_javascript_can_open_windows_automatically(True) + + self.set_user_agent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) weapp/1.0.0 Version/16.4 Safari/605.1.15") + + + # indexedDB 和 localStorage 和 离线缓存 + self.set_enable_html5_database(True) + self.set_enable_html5_local_storage(True) + self.set_enable_offline_web_application_cache(True) + + # 平滑滚动 + self.set_enable_smooth_scrolling(True) + + + self.set_enable_fullscreen(fullscreen) + + # 媒体播放是否需要 用户主动行为 + self.set_media_playback_requires_user_gesture(False) + + # 允许视频播放窗口不强制全屏 + self.set_media_playback_allows_inline(True) + + + # 关闭之后, 可以随便跨域请求, 但是有安全隐患(不过, 只要保证你页面只运行你自己的代码, 及信任的代码, 就不会有任何问题) + self.set_disable_web_security(disable_security) + + + print('<><><><>', os.environ.get('RUN_ENV')) + + if os.environ.get('RUN_ENV') == 'development': + self.set_enable_developer_extras(True) + # 是用于启用或禁用模拟捕获设备的设置选项。 + # 在开发网页应用程序时,经常需要使用摄像头或麦克风等捕获设备进行测试和调试。但是,在某些情况下,可能无法直接访问实际的物理捕获设备,或者不希望在开发过程中实际使用这些设备。 + # 通过启用WebKit2.Settings:enable-mock-capture-devices设置选项,可以使用虚拟的模拟捕获设备来替代实际的物理设备。这样,开发人员可以在没有真实设备的情况下进行捕获设备相关的功能测试和调试,提高开发效率并简化开发流程。 + self.set_enable_mock_capture_devices(True) \ No newline at end of file diff --git a/usr/lib/debian-sources/webengine/_utils.py b/usr/lib/debian-sources/webengine/_utils.py new file mode 100644 index 0000000..8c7f2a3 --- /dev/null +++ b/usr/lib/debian-sources/webengine/_utils.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# @author yutent +# @date 2023/07/28 14:39:33 + +import gi +from gi.repository.GdkPixbuf import Pixbuf + +def get_monitor_info(monitor): + return { + "model": monitor.props.model, + "scale_factor": monitor.props.scale_factor, + "manufacturer": monitor.props.manufacturer, + "refresh_rate": monitor.props.refresh_rate, + "is_primary": monitor.is_primary(), + "geometry": { + "width": monitor.props.geometry.width, + "height": monitor.props.geometry.height, + "x": monitor.props.geometry.x, + "y": monitor.props.geometry.y, + } + } + + +def pixbuf_to_dict(pixbuf, filename = ''): + + if pixbuf: + has_alpha = pixbuf.get_has_alpha() + + # 没有apha通道时, get_pixels() 得到像素矩阵会出现极个别像素出现alpha通道 + # 所以, 这里强制设置alpha通道为false, 补全像素矩阵的数据 + if not has_alpha: + pixbuf = pixbuf.add_alpha(False, 0, 0, 0) + + data = { + "width": pixbuf.get_width(), + "height": pixbuf.get_height(), + "colorspace": pixbuf.get_colorspace(), + "has_alpha": has_alpha, + "bits_per_sample": pixbuf.get_bits_per_sample(), + "rowstride": pixbuf.get_rowstride(), + "filepath": filename, + "bytes": list(pixbuf.get_pixels()) + } + else: + data = None + + return data + + +def dict_to_pixbuf(data): + if data: + image = Pixbuf.new_from_data( + data = bytes(data['bytes']), + colorspace = data['colorspace'], + has_alpha = data['has_alpha'], + bits_per_sample = data['bits_per_sample'], + width = data['width'], + height = data['height'], + rowstride = data['rowstride'] + ) + else: + image = None + + return image \ No newline at end of file diff --git a/usr/lib/debian-sources/webengine/inject.js b/usr/lib/debian-sources/webengine/inject.js new file mode 100644 index 0000000..91ab9c4 --- /dev/null +++ b/usr/lib/debian-sources/webengine/inject.js @@ -0,0 +1,391 @@ +/** + * {注入的js} + * @author yutent + * @date 2023/07/21 17:38:11 + */ + +const MIME_TYPES = { + html: 'text/html', + json: 'application/json', + js: 'application/javascript', + htm: 'text/html', + txt: 'text/plain', + css: 'text/css', + webp: 'image/webp', + jpg: 'image/jpg', + jpeg: 'image/jpeg', + png: 'image/png', + gif: 'image/gif', + svg: 'image/svg+xml', + ico: 'image/ico', + mp3: 'audio/mpeg', + ogg: 'audio/ogg', + m4a: 'audio/m4a', + amr: 'audio/amr', + mp4: 'video/mp4', + webm: 'video/webm', + wasm: 'application/wasm', + asm: 'application/asm', + zip: 'application/zip', + '7z': 'application/x-7z-compressed', + eot: 'application/vnd.ms-fontobject', + ttf: 'font/ttf', + otf: 'font/otf', + woff: 'font/woff', + woff2: 'font/woff2', + xls: 'application/vnd.ms-excel', + doc: 'application/msword', + xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' +} +const KEYS_MAP = { + shift: '', + ctrl: '', + alt: '', + super: '' +} + +function defer() { + let obj = {} + obj.promise = new Promise((resolve, reject) => { + obj.resolve = resolve + obj.reject = reject + }) + return obj +} + +function rand(prefix = 'cb_') { + return prefix + Math.random().toString().slice(2) +} + +function handler(event, data = {}, once = true) { + let _ = defer() + let callback + + if (typeof once === 'boolean') { + callback = rand() + native[once ? '$once' : '$on'](callback, _.resolve) + } else { + _.resolve(true) + } + window.webkit.messageHandlers.app.postMessage({ + event, + data, + callback + }) + return _.promise +} + +function base64(str = '') { + return btoa(str).replace(/[+=\/]/g, '') +} + +class NativeImage { + #origin + + constructor(obj) { + this.#origin = obj + this.width = obj.width + this.height = obj.height + this.type = MIME_TYPES[obj.filepath.split('.').pop()] + } + + toJSON() { + return this.#origin + } + + export(type, base64) { + let _ = defer() + let canvas = document.createElement('canvas') + canvas.width = this.width + canvas.height = this.height + let ctx = canvas.getContext('2d') + let imgData = ctx.getImageData(0, 0, this.width, this.height) + let data = imgData.data + + for (let i = 0; i < this.#origin.bytes.length; i += 4) { + imgData.data[i] = this.#origin.bytes[i] + imgData.data[i + 1] = this.#origin.bytes[i + 1] + imgData.data[i + 2] = this.#origin.bytes[i + 2] + imgData.data[i + 3] = this.#origin.bytes[i + 3] + } + + ctx.putImageData(imgData, 0, 0) + + if (base64) { + return canvas.toDataURL(type || this.type, 1) + } else { + canvas.toBlob(_.resolve, type || this.type, 1) + return _.promise + } + } + + toPNG() { + return this.export('image/png') + } + + toJPEG() { + return this.export('image/jpeg') + } + + toDataURL(type) { + return this.export(type, true) + } +} + +class EventEmitter { + // + __events__ = Object.create(null) + + $on(name, fn) { + if (this.__events__[name]) { + this.__events__[name].push(fn) + } else { + this.__events__[name] = [fn] + } + } + + $once(name, fn) { + fn.__once__ = true + this.$on(name, fn) + } + + $off(name, fn) { + if (this.__events__[name]) { + if (fn) { + this.__events__[name] = this.__events__[name].filter(it => it !== fn) + } else { + this.__events__[name] = [] + } + } + } + + $emit(name, ...args) { + if (this.__events__[name]) { + for (let fn of this.__events__[name]) { + try { + fn.apply(this, args) + if (fn.__once__) { + this.$off(name, fn) + } + } catch (e) { + console.error(e) + } + } + } + } + + $destroy() { + this.__events__ = Object.create(null) + } +} + +window.native = new EventEmitter() + +Object.assign(native, { + quit() { + return handler('quit', {}, null) + }, + fs: { + read(filepath, mode = 'r') { + return handler('fs', { action: 'read', mode, filepath }).then(r => + mode.includes('b') ? new Uint8Array(r) : r + ) + }, + write(filepath, content = '', mode = 'w') { + return handler('fs', { + action: 'write', + append: false, + filepath, + content + }) + }, + append(filepath, content = '', mode = 'w') { + return handler('fs', { + action: 'write', + append: true, + filepath, + content + }) + }, + exists(filepath) { + return handler('fs', { action: 'exists', filepath }) + }, + list(filepath) { + return handler('fs', { action: 'list', filepath }) + }, + isfile(filepath) { + return handler('fs', { action: 'isfile', filepath }) + }, + isdir(filepath) { + return handler('fs', { action: 'isdir', filepath }) + }, + remove(filepath) { + return handler('fs', { action: 'remove', filepath }) + }, + rename(filepath, target) { + return handler('fs', { action: 'rename', filepath, target }) + }, + copy(filepath, target) { + return handler('fs', { action: 'copy', filepath, target }) + } + }, + image(filepath) { + return handler('image', { value: filepath }).then(r => new NativeImage(r)) + }, + clipboard: { + readText() { + return handler('clipboard', { action: 'wait_for_text' }) + }, + writeText(value) { + return handler('clipboard', { action: 'set_text', value }, null) + }, + readImage() { + return handler('clipboard', { action: 'wait_for_image' }).then(r => + r ? new NativeImage(r) : r + ) + }, + writeImage(value) { + // 暂不知原因, postMessage传给Gtk后, JSON.stringify()并未读取toJSON的结果 + if (typeof value === 'object') { + value = value.toJSON() + } + return handler('clipboard', { action: 'set_image', value }, null) + }, + clear() { + return handler('clipboard', { action: 'clear' }) + } + }, + screen: { + getAllDisplays() { + return handler('monitor', { action: 'get-all' }) + }, + getPrimaryDisplay() { + return handler('monitor', { action: 'get-primary' }) + } + }, + globalShortcut: { + get enabled() { + return handler('keybinder', { action: 'supported' }) + }, + register(keyMap, callback) { + let shortcut_callback = base64(keyMap) + native.$off(shortcut_callback) + native.$on(shortcut_callback, callback) + return handler('keybinder', { + action: 'register', + value: keyMap, + shortcut_callback + }) + }, + unregister(keyMap) { + let shortcut_callback = base64(keyMap) + native.$off(shortcut_callback) + return handler('keybinder', { action: 'unregister', value: keyMap }) + }, + unregisterAll(keyMaps) { + for (let it of keyMaps) { + this.unregister(it) + } + } + }, + tray: { + create() { + // + }, + remove() { + // + }, + + /** + * 设置普通状态的tray图标, 只需要传名称, 自动会去当前主题下去找 + */ + set_icon(name) { + return handler('tray', { action: 'set_icon', value: name }) + }, + + /** + * 设置警示图标, 同上 + */ + set_attention_icon(name) { + return handler('tray', { action: 'set_attention_icon', value: name }) + }, + + /** + * + */ + set_title(title) { + return handler('tray', { action: 'set_title', value: title }) + }, + + /** + * 修改tray图标状态 + * @param status 0: 隐藏, 1: 显示, 2: 重要(对应上面的attention_icon) + */ + set_status(status) { + return handler('tray', { action: 'set_status', value: status }) + } + }, + window: { + isVisible() { + return handler('window', { action: 'is_visible' }) + }, + toggleVisible() { + handler('window', { action: 'toggle_visible' }, null) + }, + hide() { + handler('window', { action: 'hide' }, null) + }, + show() { + handler('window', { action: 'show' }, null) + }, + fullscreen() { + handler('window', { action: 'fullscreen' }, null) + }, + unfullscreen() { + handler('window', { action: 'unfullscreen' }, null) + }, + maximize() { + handler('window', { action: 'maximize' }, null) + }, + unmaximize() { + handler('window', { action: 'unmaximize' }, null) + }, + setTitle(title = '') { + handler('window', { action: 'set_title', value: title }, null) + }, + resize(width = 0, height = 0) { + handler('window', { action: 'resize', value: { width, height } }, null) + }, + move(x = 0, y = 0) { + handler('window', { action: 'resize', value: { x, y } }, null) + }, + setOpacity(opacity = 1) { + handler('window', { action: 'set_opacity', value: opacity }, null) + }, + alwayOnTop(setting = true) { + handler('window', { action: 'set_keep_above', value: setting }, null) + }, + alwayOnBotttom(setting = true) { + handler('window', { action: 'set_keep_below', value: setting }, null) + } + }, + notify({ title, summary, icon, progress = 0, urgency = 0, callback }) { + let eventName + if (callback) { + eventName = rand() + native.$once(eventName, callback) + } + handler( + 'notify', + { title, summary, icon, progress, urgency, callback: eventName }, + null + ) + }, + + md5(value = '') { + return handler('md5', { value }) + }, + + handler +}) diff --git a/usr/lib/debian-sources/webengine/webview.py b/usr/lib/debian-sources/webengine/webview.py new file mode 100644 index 0000000..00d0484 --- /dev/null +++ b/usr/lib/debian-sources/webengine/webview.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# @author yutent +# @date 2023/08/08 14:07:26 + + +import gi, os, json, shutil,hashlib + +gi.require_version("WebKit2", "4.1") + +from gi.repository import Gtk, Gdk, WebKit2, GLib, Gio +from gi.repository.GdkPixbuf import Pixbuf + +from ._settings import Settings +from ._protocal import Protocal +from ._inject import Inject +from ._utils import get_monitor_info, pixbuf_to_dict, dict_to_pixbuf + +__dir__ = os.path.dirname(os.path.realpath(__file__)) + + +class WebviewEngine(WebKit2.WebView): + def __init__(self, App): + + WebKit2.WebView.__init__(self) + + self.app = App + self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + self.display = Gdk.Display.get_default() + + settings = Settings(True, False) + + self.set_settings(settings) + + Inject(self).connect(self.call_by_js) + + Protocal(self, os.path.join(__dir__, '../webapp')).register() + + im = self.get_input_method_context() + im.set_enable_preedit(True) + + # 解决输入法候选框跟随问题 + im.connect('preedit-started', self.on_preedit_changed) + im.connect('preedit-changed', self.on_preedit_changed) + im.connect('preedit-finished', self.on_preedit_changed) + + self.load_uri("app:///index.html") + + def on_preedit_changed(self, im): + seat = self.display.get_default_seat() + p = seat.get_pointer().get_position() # 光标位置 + x, y = self.get_position() # 窗口位置 + + im.notify_focus_in() + im.notify_cursor_area(p.x - x, p.y - y, 0, 0) # 修正输入法跟随 + + + def call_js(self, method, data = None): + scripts = 'native.$emit("' + method + '",' + json.dumps(data) + ')' + self.evaluate_javascript(scripts, -1) + + + def call_by_js(self, webview, message): + + data = json.loads(message.get_js_value().to_json(0)) + + event = data.get('event') + callback = data.get('callback') + params = data.get('data') + output = None + + + match event: + case 'fs': + filepath = params.get('filepath') + + if params['action'] == 'read': + with open(filepath, params.get('mode')) as file: + output = file.read() + if params.get('mode').find('b') > -1: + output = list(output) + + if params['action'] == 'write': + + # 调整以支持二进制数据写入 + with open(filepath, params.get('mode')) as file: + buff = params['content'] + + if params.get('mode').find('b') > -1: + buff = bytes(buff) + + output = file.write(buff) + + if params['action'] == 'exists': + output = os.path.exists(filepath) + + if params['action'] == 'list': + with os.scandir(filepath) as entries: + output = [{ + "name": it.name, + "path": os.path.join(filepath, it.name), + "is_dir": it.is_dir(), + "size": it.stat().st_size, + "atime": int(it.stat().st_atime), + "mtime": int(it.stat().st_mtime), + } for it in entries] + + if params['action'] == 'remove': + if os.path.isfile(filepath): + output = os.remove(filepath) + elif os.path.isdir(filepath): + output = os.removedirs(filename) + + if params['action'] == 'rename': + if os.path.exists(filepath): + output = shutil.move(filepath, params['target']) + + if params['action'] == 'copy': + if os.path.exists(filepath): + output = shutil.copy2(filepath, params['target']) + + if params['action'] == 'isfile': + output = os.path.isfile(filepath) + + if params['action'] == 'isdir': + output = os.path.isdir(filepath) + + + case 'clipboard': + # 读文本 + if params['action'] == 'wait_for_text': + output = self.clipboard.wait_for_text() + + # 写文本 + elif params['action'] == 'set_text': + self.clipboard.set_text(params['value'], -1) + + # 写图片 + elif params['action'] == 'set_image': + image = params['value'] + # 前端传进来的值, 如果是路径的话, 直接读取 + if type(image) == str: + image = Pixbuf.new_from_file(image) + else: + image = dict_to_pixbuf(image) + + self.clipboard.set_image(image) + self.clipboard.store() + + # 读图片 + elif params['action'] == 'wait_for_image': + output = self.clipboard.wait_for_image() + output = pixbuf_to_dict(output, 'noname.png') + + # 清除剪切板 + elif params['action'] == 'clear': + self.clipboard.clear() + + # 退出app + case 'quit': + self.app.close() + + # 读取图片, 返回图片像素数据 + case 'image': + filename = params['value'] + pixbuf = Pixbuf.new_from_file(filename) + output = pixbuf_to_dict(pixbuf, filename) + + case 'md5': + output = hashlib.md5(str(params.get('value'))).hexdigest() + + # 有回调则返回结果 + if callback: + self.call_js(callback, output) + \ No newline at end of file diff --git a/usr/lib/debian-sources/window.py b/usr/lib/debian-sources/window.py new file mode 100644 index 0000000..9886b9e --- /dev/null +++ b/usr/lib/debian-sources/window.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import gi + +gi.require_version('Gtk', '3.0') + +from gi.repository import Gtk + +class Window(Gtk.Window): + def __init__(self, title = 'Untitled window', width = 800, height = 600): + Gtk.Window.__init__(self, title = title) + self.set_default_size(width, height) + + + def toggle_visible(self, icon): + if self.is_visible(): + self.hide() + else: + self.present() \ No newline at end of file diff --git a/usr/share/applications/debian-sources.desktop b/usr/share/applications/debian-sources.desktop new file mode 100644 index 0000000..4e835e3 --- /dev/null +++ b/usr/share/applications/debian-sources.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Name=Software Sources +Comment[zh_CN]=配置用于安装和升级软件的源 +Comment[zh_HK]=設定可安裝軟件與更新的來源組態 +Comment[zh_TW]=設定可安裝軟體與更新的來源組態 +Exec=pkexec debian-sources +Icon=debian-sources +Terminal=false +X-MultipleArgs=false +Type=Application +Categories=GNOME;GTK;System;Settings;X-GNOME-SystemSettings;X-GNOME-Settings-Panel;XFCE;X-XFCE-SettingsDialog;X-XFCE-SystemSettings; +X-GNOME-Settings-Panel=software-properties +MimeType=text/x-apt-sources-list; diff --git a/usr/share/icons/hicolor/48x48/apps/debian-sources.png b/usr/share/icons/hicolor/48x48/apps/debian-sources.png new file mode 100644 index 0000000..4c0b72b Binary files /dev/null and b/usr/share/icons/hicolor/48x48/apps/debian-sources.png differ diff --git a/usr/share/icons/hicolor/scalable/apps/debian-sources.svg b/usr/share/icons/hicolor/scalable/apps/debian-sources.svg new file mode 100644 index 0000000..e1e7a1a --- /dev/null +++ b/usr/share/icons/hicolor/scalable/apps/debian-sources.svg @@ -0,0 +1,737 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file