1 Commits
r0.1 ... py27

Author SHA1 Message Date
shim_
4de04a3105 python2.7 deps 2018-07-19 22:01:04 +02:00
10 changed files with 224 additions and 416 deletions

View File

@@ -1,27 +1,9 @@
pipeline:
pretty:
image: unibeautify/autopep8
commands:
- autopep8 imports -r --in-place
- autopep8 main.py --in-place
modules:
image: python:3.5
image: python:2.7
commands:
- rm -rf modules
- mkdir -p .pip3
- ./make-modules.sh --cache-dir .pip3
- ./make-modules.sh
package:
image: kramos/alpine-zip
commands:
- zip seafile.zip -r modules icon.png main.py metadata.xml settings.ui
release:
image: plugins/gitea-release
settings:
api_key:
from_secret: gitea_token
base_url: https://git.shimun.net
files: seafile.zip
checksum:
- sha256
when:
event: tag

4
.gitignore vendored
View File

@@ -1,4 +0,0 @@
modules
.pip3
seafile.zip
lib

View File

@@ -1,28 +1,21 @@
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
import bson # , scrypt
import bson, scrypt
from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto.PublicKey import RSA
from Crypto.PublicKey import DSA
from salsa20 import Salsa20_keystream
import os
import struct
import time
import hashlib
import hashlib
import random
import binascii
import os, struct, time, hashlib, hashlib, random
class EncryptedScreenshot:
def __init__(self, metadata, password=None, id=None, signer=None, password_encryptor=None):
def __init__(self, metadata,id=None,signer=None,password_encryptor=None):
def rand(len):
return ''.join(
random.choice("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz") for _ in range(len))
self.password = (password or rand(16))
self.password = rand(16)
print("Passphrase %s" % str(bytearray(self.passphrase())).encode("hex"))
self.id = id
if id is None:
self.id = rand(8)
@@ -32,18 +25,16 @@ class EncryptedScreenshot:
self.password_encryptor = password_encryptor
def caesar_encrypted_password(self):
caesar_key = reduce(lambda sum, charcode: sum +
charcode, map(ord, list(self.id)))
caesar_key = reduce(lambda sum,charcode: sum+charcode, map(ord,list(self.id)))
caesar_plaintext = map(ord, self.password)
caesar_ciphertext = Caesar().encrypt(caesar_plaintext, caesar_key)
return ''.join(map(chr, caesar_ciphertext))
caesar_ciphertext = Caesar().encrypt(caesar_plaintext,caesar_key)
return ''.join(map(chr,caesar_ciphertext))
def passphrase(self):
# new ScryptParameters(64, 8, 1,32, new Uint8List.fromList(new List<int>()))
print("Password units: %s" %
(map(ord, self.password.encode("utf-8")),))
print("Password units: %s" % (map(ord, self.password.encode("utf-8")),))
sha = hashlib.sha256()
sha.update(self.password.encode("utf-8"))
sha.update(self.password)
return sha.digest() # scrypt.hash(self.password.encode("utf-8"), '', 64, 8, 1, 32)
def assemble(self, file):
@@ -51,51 +42,46 @@ class EncryptedScreenshot:
self.metadata["hash"] = image_digest
unencrypted_metadata = bson.dumps(self.metadata)
if len(unencrypted_metadata) % 16 != 0:
unencrypted_metadata += b' ' * \
(16 - len(unencrypted_metadata) % 16)
unencrypted_metadata += ' ' * (16 - len(unencrypted_metadata) % 16)
(encryptor, iv) = self.encryptor(len(unencrypted_metadata))
encrypted_metadata = b''
encrypted_metadata = []
encrypted_metadata += encryptor(unencrypted_metadata)
encrypted_metadata = iv + encrypted_metadata
encrypted_metadata = iv + str(bytearray(encrypted_metadata))
#print("Metadata: %s" % str(encrypted_metadata).encode("base64").replace("\n", ""))
#print("%s %s" % (str(encrypted_metadata[:16]).encode("hex"), str(encrypted_metadata[16:]).encode("hex")))
#print("Unencrypted: %s" % (unencrypted_metadata.encode("hex")))
#print("Password %s" % self.password)
print("Metadata: %s" % str(encrypted_metadata).encode("base64").replace("\n", ""))
print("%s %s" % (str(encrypted_metadata[:16]).encode("hex"), str(encrypted_metadata[16:]).encode("hex")))
print("Unencrypted: %s" % (unencrypted_metadata.encode("hex")))
print("Password %s" % self.password)
# print(bson.loads(unencrypted_metadata))
print(bson.loads(unencrypted_metadata))
fields = {
"image": encrypted_image,
"metadata_encryption": self.metadata_encryption,
"metadata": encrypted_metadata if self.metadata_encryption else self.metadata,
"public_metadata": self.metadata["public"]
"metadata": encrypted_metadata if self.metadata_encryption else self.metadata
}
if self.signer is not None:
fields["signature"] = self.signer.signature(
encrypted_metadata if self.metadata_encryption else bson.dumps(self.metadata))
fields["signature"] = self.signer.signature(encrypted_metadata if self.metadata_encryption else bson.dumps(self.metadata))
if self.password_encryptor is not None:
fields["password"] = self.password_encryptor.encrypt_password(
self.password)
fields["password"] = self.password_encryptor.encrypt_password(self.password)
return bson.dumps(fields)
def encryptor(self, length=0):
def encryptor(self,length=0):
iv = os.urandom(16)
nonce = int(binascii.hexlify(iv), 16)
ctr = Counter.new(128, initial_value=nonce) # initial_value = nonce)
print("IV: %s" % binascii.hexlify(iv))
ctr = Counter.new(128, initial_value=long(iv.encode("hex"), 16))
print("IV: %s" % iv.encode("hex"))
cipher = AES.new(self.passphrase(), AES.MODE_CTR, counter=ctr)
# salsa
#salsa
# keysstream = bytearray(Salsa20_keystream(length,iv[:8],self.passphrase()))
# offset={"offset": 0}
def encrypt(data):
# Salsa20
#Salsa20
# array = bytearray(data)
# for i in range(len(array)):
# array[i] ^= keysstream[i+offset["offset"]]
@@ -108,7 +94,7 @@ class EncryptedScreenshot:
def encrypt(self, file):
filesize = os.path.getsize(file)
(encryptor, iv) = self.encryptor(filesize)
binary = b''
binary = []
digest = hashlib.sha256()
with open(file, 'rb') as infile:
# binary += struct.pack('<Q', filesize)
@@ -120,16 +106,18 @@ class EncryptedScreenshot:
pass # chunk += ' ' * (16 - len(chunk) % 16)
digest.update(chunk)
binary += encryptor(chunk)
return (digest.digest(), iv + binary)
return (digest.digest(), iv + str(bytearray(binary)))
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
class Signer:
@staticmethod
def default():
return Signer(RSA.importKey("-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"), "PUBLIC")
return Signer(RSA.importKey("-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n"),"PUBLIC")
def __init__(self, privateKey, privateKeyId, mode=RSA):
def __init__(self,privateKey,privateKeyId, mode=RSA):
self.mode = mode
self.privateKeyId = privateKeyId
self._signer = PKCS1_v1_5.new(privateKey)
@@ -139,38 +127,37 @@ class Signer:
digest.update(data)
return self._signer.sign(digest)
def signature(self, data):
def signature(self,data):
signed = self.sign(data)
return {"signed-hash": signed,
"signature-algorithm": "SHA-256/%s" % ("RSA" if self.mode == RSA else "DSA"),
"key-id": (self.privateKeyId)
"signature-algorithm": "SHA-256/%s" % unicode("RSA" if self.mode == RSA else "DSA"),
"key-id": unicode(self.privateKeyId)
}
class EncryptedPassword:
def __init__(self, publicKey, publicKeyId, mode=RSA):
def __init__(self,publicKey,publicKeyId,mode=RSA):
assert mode == RSA
self.mode = mode
self.publicKey = publicKey
self.publicKeyId = publicKeyId
def encrypt(self, password):
def encrypt(self,password):
return self.publicKey.encrypt(password.encode("utf-8"), os.urandom(32))[0]
def encrypt_password(self, password):
return {"algorithm": unicode("RSA" if self.mode == RSA else "DSA"),
def encrypt_password(self,password):
return {"algorithm": unicode( "RSA" if self.mode == RSA else "DSA"),
"key-id": unicode(self.publicKeyId),
"password": self.encrypt(password)
}
class Caesar:
def __init__(self, charset=map(ord, list("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz"))):
def __init__(self,charset = map(ord,list("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz"))):
self.charset = charset
def encrypt(self, plaintext, key):
def encrypt(self,plaintext,key):
if key >= len(self.charset) or key < 0:
key = key % len(self.charset)
@@ -180,10 +167,10 @@ class Caesar:
return self.charset[pos+key - len(self.charset)]
else:
return self.charset[pos+key]
return map(addKey, plaintext)
return map(addKey,plaintext)
def decrypt(self, ciphertext, key):
return self.encrypt(ciphertext, key*-1)
def decrypt(self,ciphertext,key):
return self.encrypt(ciphertext,key*-1)
if __name__ == "__main__":
@@ -191,26 +178,22 @@ if __name__ == "__main__":
publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF1VEVIVldqdHdGeWRHL1ZtSEtyMQo1cXltSWt3WklhTm5RZUttQnp6bituODdaamRna0VEdENFWVNxM1cxVnhsZ1V3MURoOEtUVHIzSzFMUXdjRGZ4Cjh2ZEFyazk5T1g0bXhxcFlXUmJkZkVRazF3VUQ3Y3RyMkU1ZUtRY0NjYkFsL09LWUZhL1BrWTNLc0J1bnMwNlIKbGY4NXNIU1o3Q2ZpcnFINkZvZWZyWERaVkFKT21yUWhUaC8wcUdsQnkxZjEzYzJhMTJzRk5PbW5jTHM4VnA0Zgp0SnhMcjlHb0U0dnNRdlgvNm9Rdmk3UHFXWW12bHdtVVV2aENQUy9KU0Y4a0N1dm12ZmdjRjhPWE9qMVE2aXRPCkxaRHQ4L1p1WmVvazduUzhKeGhSNzNIekhSNGFIV25xQzhVa0l4MUNSL1Z2bFpocC83Z2JTL3kxRU9SUmFWbE8KM1lUa0YyVU1UdEYyQm9Dc1k1Z2xwZWFsRFY2Rmg5WVp3cTY4QVBiNS9jbGV1WHU4dGViWXBvNXl1d0g5RzhtMApicDdtSXJWVW5hQlBDRS9Xc2o2SEZVTG5pVWk4ME44MTQ5Y00ya0xtbTdjK0pOQzRRVXVwYzNpeTNxeWxxaDFLCkZsVTBTV1BBaW5EYk9EU0hxblBpV1YwSUhqQzltVmVBbU1EamcvNlI3dWFBdWJMejBySnNvL29kazBrZldZTzkKOEQ0M0h2N0MrVEcvSWY5b0U3SmRzZ1NDQ2ZlVHVhS0U1WEgzQzNHZWdjaURPeXI2U2QvMDhLcHJRd3Z5N25acApKSnh6cHlyMk1vSi9uOE82TzRJcUR0NzZFQVp6NzZuVXZKelBYU29VR3k3OTQyUU93eXdwUllCNk5iclZwUFVlCm1VQ3NVdHRVSnpoZ0hVNzBFbHFFMmhzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
encrypted = EncryptedScreenshot({"owner": u"test", "format": u"jpg", "title": u"5x5 Red", "timestamp": int(time.time()*1000)},
signer=Signer.default(),
password_encryptor=EncryptedPassword(RSA.importKey(publicKey.decode("base64")), "PUBLIC"))
fixed_id = encrypted.id # "W9u9Zm0u"
password_encryptor=EncryptedPassword(RSA.importKey(publicKey.decode("base64")),"PUBLIC"))
fixed_id = encrypted.id #"W9u9Zm0u"
print(len(encrypted.passphrase()))
out = open(
"/home/marvin/Dokumente/IdeaProjects/EncryptedScreencloud/Frontend/WebApp/web/data/" + fixed_id, 'wb')
out = open("/home/marvin/Dokumente/IdeaProjects/EncryptedScreencloud/Frontend/WebApp/web/data/" + fixed_id, 'wb')
assembled = encrypted.assemble("5x5red.png")
out.write(assembled)
b = bson.loads(assembled)
del b["image"]
print(b)
# print(assembled.encode("base64").replace("\n","")
#print(assembled.encode("base64").replace("\n","")
print("http://localhost:8080/#%s%s" % (fixed_id, encrypted.password))
caesar_key = reduce(lambda sum, charcode: sum +
charcode, map(ord, list(fixed_id)))
caesar_plaintext = map(ord, encrypted.password)
caesar_ciphertext = Caesar().encrypt(caesar_plaintext, caesar_key)
assert caesar_plaintext == Caesar().decrypt(caesar_ciphertext, caesar_key)
print("caesar_key=%s %s -> %s" %
(caesar_key, encrypted.password, ''.join(map(chr, caesar_ciphertext))))
print("http://localhost:8080/#%s%sC" %
(fixed_id, encrypted.caesar_encrypted_password()))
caesar_key = reduce(lambda sum,charcode: sum+charcode, map(ord,list(fixed_id)))
caesar_plaintext = map(ord,encrypted.password)
caesar_ciphertext = Caesar().encrypt(caesar_plaintext,caesar_key)
assert caesar_plaintext == Caesar().decrypt(caesar_ciphertext,caesar_key)
print("caesar_key=%s %s -> %s" % (caesar_key,encrypted.password,''.join(map(chr,caesar_ciphertext))))
print("http://localhost:8080/#%s%sC" % (fixed_id, encrypted.caesar_encrypted_password()))
print("http://localhost:8080/#%s" % (fixed_id, ))
out.close()

View File

@@ -1,33 +0,0 @@
import hashlib
import binascii
class HashDerivedKey:
@staticmethod
def from_hex(hex_str):
return HashDerivedKey(bytes(bytearray.fromhex(hex_str)))
def __init__(self, master):
def ensure_bytes(b):
assert isinstance(b, bytes)
return b
ensure_bytes(master)
def derive(seed):
ensure_bytes(seed)
sha = hashlib.sha256()
sha.update(master)
sha.update(seed)
return sha.digest()
def hex(b): return binascii.hexlify(b).decode("utf-8")
self.master = master
self.master_hex = lambda: hex(master)
self.derive = derive
self.derive_hex = lambda seed: hex(derive(seed))
def derive_metadata(self, seed):
key = self.derive(seed)
return (key, {"key_seed": binascii.hexlify(seed).decode("utf-8")})

View File

@@ -1,123 +1,86 @@
import time
from encryptedscreenshot import EncryptedScreenshot, Signer
from hashderive import HashDerivedKey
import getpass
import os
import sys
import getpass, os
from PythonQt.QtGui import QInputDialog
from PythonQt.QtCore import QSettings
from seafapi import *
class Processor:
def name(self):
pass
def configure(self, parent):
def configure(self,parent):
pass
def is_configured(self):
return True
def load_settings(self, settings):
def upload(self,file):
pass
def save_settings(self, settings):
pass
def upload(self, file, name):
pass
class DummyProcessor(Processor):
def name(self):
return None
def is_configured(self):
return False
class DefaultProcessor(Processor):
def name(self):
return "default"
def __init__(self, seaf_lib, lib_path):
def __init__(self,seaf_lib,lib_path):
self.seaf_lib = seaf_lib
self.lib_path = lib_path
def upload(self, file, name):
return self.seaf_lib.upload(file, name, self.lib_path).share()
def upload(self,file,name):
return self.seaf_lib.upload(file,name,self.lib_path).share()
class EncryptedProcessor(Processor):
def name(self):
return "enc"
def __init__(self, seaf_lib, lib_path):
def __init__(self,seaf_lib,lib_path):
self.seaf_lib = seaf_lib
self.lib_path = lib_path
self.host = None
self.derived_key = HashDerivedKey(os.urandom(32))
self.load_settings()
self.host = ""
def load_settings(self, settings=QSettings()):
self.host = settings.value("encscreen-url", None)
if settings.value("encscreen-derived-key", None):
self.derived_key = HashDerivedKey.from_hex(
settings.value("encscreen-derived-key", None))
def load_settings(self):
settings = QSettings()
settings.beginGroup("uploaders")
settings.beginGroup("seafile")
self.host = settings.value("encscreen-url", "")
settings.endGroup()
settings.endGroup()
def save_settings(self, settings=QSettings()):
def save_settings(self):
settings = QSettings()
settings.beginGroup("uploaders")
settings.beginGroup("seafile")
settings.setValue("encscreen-url", self.host)
if self.derived_key:
settings.setValue(self.derived_key.master_hex())
settings.endGroup()
settings.endGroup()
def is_configured(self):
return self.host is not None and self.host != ""
def configure(self, parent):
self.host = QInputDialog.getText(parent, 'Encscreen Server Setup', 'Enter server url (ex. https://servertld/s#%id%key):',
text=(self.host or "https://screens.shimun.net/s#%id%key"))
master = QInputDialog.getText(parent, 'Encscreen Master Key Setup', 'Enter master key (hex encoded):', text=(
self.derived_key.master_hex() if self.derived_key else "<random>"))
try:
self.derived_key = HashDerivedKey.from_hex(master)
except:
self.derived_key = HashDerivedKey(os.urandom(32))
def configure(self,parent):
self.host = QInputDialog.getText(parent, 'Encscreen Server Setup', 'Enter server url (ex. https://servertld/s#%id%key):', text="https://screens.shimun.net/s#%id%key")
self.save_settings()
def upload(self, file, name):
def derive():
seed = os.urandom(16)
(_, key_meta) = self.derived_key.derive_metadata(seed)
return (self.derived_key.derive_hex(seed)[0:16], key_meta)
(key, key_meta) = derive()
enrypted = EncryptedScreenshot(metadata={
"owner": getpass.getuser(),
"format": str(file).split('.')[-1],
"title": name,
def upload(self,file,name):
enrypted = EncryptedScreenshot({
"owner": unicode(getpass.getuser()),
"format": unicode(str(file).split('.')[-1]),
"title": unicode(name),
"timestamp": int(time.time() * 1000),
"size": os.stat(file).st_size,
"public": key_meta
}, password=key, signer=Signer.default())
"size": os.stat(file).st_size
},signer=Signer.default())
tmpHandle = open(file + "c", 'wb')
tmpHandle.write(enrypted.assemble(file))
tmpHandle.close()
seaf_file = self.seaf_lib.upload(
file + "c", name + ".enc", self.lib_path)
seaf_file = self.seaf_lib.upload(file + "c",name + ".enc",self.lib_path)
if not seaf_file:
return
seaf_link = seaf_file.share()
if seaf_link:
id = str(seaf_link).split('/')[-2]
return self.host.replace('%id', id).replace('%key', "%s" % enrypted.password)
return self.host.replace('%id', id).replace('%key',"%s" % enrypted.password)
else:
return False

View File

@@ -1,139 +1,118 @@
import time
import os
import time, os
import requests
class SeafileClient:
def __init__(self, server, username, password=None, token=None):
def __init__(self,server,username,password=None,token=None):
self.server = server
self.token = token
self.session = requests.Session()
if token:
self.session.headers.update(
{'Authorization': "Token %s" % self.token.token})
self.login = (username, password)
self.login = (username,password)
def api_endpoint(self):
return "%s/api2" % self.server
return "%s/api2/" % self.server
def ping(self, auth=False):
def ping(self):
try:
return self.session.get("%s%s/ping" % (self.api_endpoint(), "/auth" if auth else "")).text == "\"pong\""
return requests.get("%s/ping" % self.api_endpoint()).text == "pong"
except:
return False
def obtain_token(self):
user, passw = self.login
user,passw = self.login
try:
req = requests.post("%s/auth-token/" % self.api_endpoint(),
data={'username': user, 'password': passw})
req=requests.post("%s/auth-token/" % self.api_endpoint(), data = {'username': user, 'password': passw })
json = req.json()
if "non_field_errors" in json:
print(json["non_field_errors"])
return False
return SeafileToken(user, json["token"])
return SeafileToken(user,json["token"])
except:
return False
def authorize(self):
self.token = self.obtain_token()
if self.token:
self.session.headers.update(
{'Authorization': "Token %s" % self.token.token})
return self.token != False
# curl -H 'Authorization: Token 24fd3c026886e3121b2ca630805ed425c272cb96' -H 'Accept: application/json; indent=4' https://cloud.seafile.com/api2/repos/
#curl -H 'Authorization: Token 24fd3c026886e3121b2ca630805ed425c272cb96' -H 'Accept: application/json; indent=4' https://cloud.seafile.com/api2/repos/
def libraries(self):
resp = self.session.get("%s/repos/" % self.api_endpoint(), headers={
'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4'})
if not resp.status_code == 200:
return
libraries = []
resp=requests.get("%s/repos/" % self.api_endpoint(), headers = {'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4' })
if not resp.status_code == 200: return
libraries=[]
for lib in resp.json():
if not lib['encrypted']:
libraries.append(SeafileLibrary(
self, lib['id'], lib['name'], lib['owner']))
libraries.append(SeafileLibrary(self,lib['id'],lib['name'],lib['owner']))
return libraries
class SeafileLibrary:
def __init__(self, client, id, name, owner):
def __init__(self,client,id,name,owner):
self.client = client
self.session = client.session
self.id = id
self.name = name
self.owner = owner
def api_endpoint(self):
return "%s/repos/%s" % (self.client.api_endpoint(), self.id)
return "%s/repos/%s" % (self.client.api_endpoint(),self.id)
def upload(self, file, file_name, directory, link=None):
def upload(self,file,file_name,directory,link=None):
def obtain_link():
# curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" https://cloud.seafile.com/api2/repos/99b758e6-91ab-4265-b705-925367374cf0/upload-link/
#curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" https://cloud.seafile.com/api2/repos/99b758e6-91ab-4265-b705-925367374cf0/upload-link/
print("%s/upload-link" % self.api_endpoint())
quoted = self.session.get("%s/upload-link" % self.api_endpoint(), headers={
'Authorization': "Token %s" % self.client.token.token, }).text
quoted = requests.get("%s/upload-link" % self.api_endpoint(), headers = {'Authorization': "Token %s" % self.client.token.token,}).text
return quoted[1:-1]
# curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" -F file=@test.txt -F filename=test.txt -F parent_dir=/ http://cloud.seafile.com:8082/upload-api/73c5d117-3bcf-48a0-aa2a-3f48d5274ae3
resp = self.session.post(link or obtain_link(),
files={'file': (file_name, open(
file, 'rb')), 'parent_dir': directory, 'target_file': "%s/%s" % (directory, file_name)},
headers={
'Authorization': "Token %s" % self.client.token.token, }
#curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" -F file=@test.txt -F filename=test.txt -F parent_dir=/ http://cloud.seafile.com:8082/upload-api/73c5d117-3bcf-48a0-aa2a-3f48d5274ae3
resp = requests.post(link or obtain_link() ,
files={'file': (file_name,open(file, 'rb')), 'parent_dir': directory, 'target_file': "%s/%s" % (directory,file_name)},
headers = {'Authorization': "Token %s" % self.client.token.token,}
)
if resp.status_code == 200:
return SeafileFile(self, ("%s/%s" % (directory, file_name)).replace('//', '/').replace('//', '/'), resp.text)
return SeafileFile(self,("%s/%s" % (directory,file_name)).replace('//','/').replace('//','/'),resp.text)
return False
# curl -H 'Authorization: Token f2210dacd3606d94ff8e61d99b477fd' -H 'Accept: application/json; charset=utf-8; indent=4' https://cloud.seafile.com/api2/repos/dae8cecc-2359-4d33-aa42-01b7846c4b32/file/detail/?p=/foo.c
def file_info(self, path):
resp = self.session.get("%s/file/detail/?p=%s" % (self.api_endpoint(), path), headers={
'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4'})
#curl -H 'Authorization: Token f2210dacd3606d94ff8e61d99b477fd' -H 'Accept: application/json; charset=utf-8; indent=4' https://cloud.seafile.com/api2/repos/dae8cecc-2359-4d33-aa42-01b7846c4b32/file/detail/?p=/foo.c
def file_info(self,path):
resp=requests.get("%s/file/detail/?p=%s" % (self.api_endpoint(),path), headers = {'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4' })
if resp.status_code == 200:
json = resp.json()
return SeafileFile(self, path, json['id'], json['size'])
return SeafileFile(self,path,json['id'],json['size'])
return False
def __str__(self):
return "%s on %s by %s" % (self.name, self.client.server, self.owner)
return "%s on %s by %s" % (self.name,self.client.server,self.owner)
class SeafileFile:
def __init__(self, library, path, id, size=0):
def __init__(self,library,path,id,size=0):
self.id = id
self.path = path
self.library = library
self.session = library.session
self.size = size
# curl -v -X PUT -d "p=/foo.md" -H 'Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd' -H 'Accept: application/json; indent=4' https://cloud.seafile.com/api2/repos/afc3b694-7d4c-4b8a-86a4-89c9f3261b12/file/shared-link/
#curl -v -X PUT -d "p=/foo.md" -H 'Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd' -H 'Accept: application/json; indent=4' https://cloud.seafile.com/api2/repos/afc3b694-7d4c-4b8a-86a4-89c9f3261b12/file/shared-link/
def share(self):
resp = self.session.put("%s/repos/%s/file/shared-link/" % (self.library.client.api_endpoint(), self.library.id),
headers={'Authorization': "Token %s" % self.library.client.token.token,
'Accept': 'application/json; indent=4'},
data={'p': self.path}
resp = requests.put("%s/repos/%s/file/shared-link/" % (self.library.client.api_endpoint(),self.library.id),
headers = {'Authorization': "Token %s" % self.library.client.token.token, 'Accept': 'application/json; indent=4'},
data = {'p': self.path}
)
return resp.headers.get("location")
def update(self, file):
def update(self,file):
def obtain_link():
# curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" https://cloud.seafile.com/api2/repos/99b758e6-91ab-4265-b705-925367374cf0/upload-link/
quoted = self.session.get("%s/update-link" % self.library.api_endpoint(), headers={
'Authorization': "Token %s" % self.library.client.token.token, }).text
#curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" https://cloud.seafile.com/api2/repos/99b758e6-91ab-4265-b705-925367374cf0/upload-link/
quoted = requests.get("%s/update-link" % self.library.api_endpoint(), headers = {'Authorization': "Token %s" % self.library.client.token.token,}).text
return quoted[1:-1]
directory, name = os.path.split(self.path)
return self.library.upload(file, name, directory, obtain_link())
return self.library.upload(file,name,directory,obtain_link())
class SeafileToken:
def __init__(self, username, token):
def __init__(self,username,token):
self.username = username
self.token = token
def __str__(self):
return "%s@%s" % (self.token, self.username)
return "%s@%s" % (self.token,self.username)

View File

@@ -1,72 +0,0 @@
from processors import DummyProcessor, DefaultProcessor, EncryptedProcessor
from seafapi import *
class SeafScreencloudSettings:
def __init__(self):
self.processor = DummyProcessor()
self.library = None # (Id, Name)
self.library_path = "/"
self.token = None # SefileToken
self.upload_scheme = "regular"
self.url = None
def _client(self):
if self.token and self.url:
client = SeafileClient(
self.url, self.token.username, token=self.token)
def c():
return client
self.client = c
return c()
return None
def load(self, settings):
self.client = self._client
self.url = settings.value("seafile-url", None)
lib = tuple(settings.value("library", "/").split("/"))
(id, name) = lib
if len(id) == 0 or self.client() == None:
self.library = None
else:
self.library = SeafileLibrary(self.client(), id, name, name)
self.library_path = settings.value("library-path", "/")
(user, tkn) = (settings.value("auth-username", None),
settings.value("auth-token", None))
if user == None or tkn == None:
self.token = None
else:
self.token = SeafileToken(user, tkn)
processors = {
"default": DefaultProcessor,
"enc": EncryptedProcessor
}
if settings.value("processor", None) in processors:
self.processor = processors[settings.value("processor", None)](
self.library, self.library_path)
self.processor.load_settings(settings)
elif self.library:
self.processor = DefaultProcessor(self.library, self.library_path)
else:
self.processor = DummyProcessor()
# TODO:
self.upload_scheme = "regular"
def save(self, settings):
settings.setValue("seafile-url", self.url)
if self.library is not None:
settings.setValue("library", "%s/%s" %
(self.library.id, self.library.name))
settings.setValue("library-path", self.library_path)
if self.token != None:
settings.setValue("auth-username", self.token.username)
settings.setValue("auth-token", self.token.token)
settings.setValue("processor", self.processor.name())
self.processor.save_settings(settings)

151
main.py
View File

@@ -3,10 +3,9 @@ import time
from PythonQt.QtCore import QFile, QSettings
from PythonQt.QtGui import QDesktopServices, QMessageBox
from PythonQt.QtUiTools import QUiLoader
from multiprocessing import Pool, Process
from multiprocessing import Pool,Process
from seafapi import *
from settings import SeafScreencloudSettings
from processors import DummyProcessor, DefaultProcessor, EncryptedProcessor
###############################
## This is a temporary fix, should be removed when a newer python version is used ##
@@ -14,10 +13,11 @@ import logging
logging.captureWarnings(True)
###############################
class SeafileUploader():
def __init__(self):
self.set = SeafScreencloudSettings()
self.processor = DummyProcessor()
self.seaf_lib = None
self.seaf_path = "/"
self.libs = None
self.uil = QUiLoader()
self.loadSettings()
@@ -25,16 +25,11 @@ class SeafileUploader():
def showSettingsUI(self, parentWidget):
self.parentWidget = parentWidget
# self.set.processor.configure(parentWidget)
self.settingsDialog = self.uil.load(
QFile(workingDir + "/settings.ui"), parentWidget)
self.settingsDialog.group_account.widget_loggedIn.loginButton.connect(
"clicked()", self.startAuthenticationProcess)
self.settingsDialog = self.uil.load(QFile(workingDir + "/settings.ui"), parentWidget)
self.settingsDialog.group_account.widget_loggedIn.loginButton.connect("clicked()", self.startAuthenticationProcess)
#self.settingsDialog.group_name.input_name.connect("textChanged(QString)", self.nameFormatEdited)
self.settingsDialog.group_location.widget_location.pathEdit.connect(
"textChanged(QString)", self.locationUpdate)
self.settingsDialog.group_location.widget_location.libraryEditDrop.connect(
"currentIndexChanged(QString)", self.locationUpdate)
self.settingsDialog.group_location.widget_location.pathEdit.connect("textChanged(QString)", self.locationUpdate)
self.settingsDialog.group_location.widget_location.libraryEditDrop.connect("currentIndexChanged(QString)", self.locationUpdate)
self.settingsDialog.connect("accepted()", self.saveSettings)
self.loadSettings()
@@ -46,35 +41,29 @@ class SeafileUploader():
drop.clear()
drop.setEnabled(False)
select = 0
if self.set.client() and self.set.client().ping():
self.libs = self.set.client().libraries()
i = 0
if self.seaf_client:
self.libs = (self.seaf_client or self.seaf_lib.client).libraries()
i=0
for lib in self.libs:
if self.set.library is not None and (lib.id == self.set.library.id or lib.name == self.set.library.name):
if self.seaf_lib is not None and lib.id == self.seaf_lib.id:
select = i
print("set %s" % lib.name)
print "set %s" % lib.name
drop.addItem(lib.name)
i = i+1
i=i+1
drop.setCurrentIndex(select)
drop.setEnabled(True)
def updateUi(self):
self.settingsDialog.group_account.widget_loggedIn.usernameEdit.setText(
self.set.token.username if not (self.set.token is None) else "")
self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.setText(
self.set.url or "https://seaf.shimun.net")
self.settingsDialog.group_account.widget_loggedIn.loginButton.setText(
"Logout" if self.set.token is not None else "Login")
self.settingsDialog.group_account.widget_loggedIn.usernameEdit.setText(self.access_token.username if not (self.access_token is None) else "")
self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.setText(self.seaf_url or "https://seaf.shimun.net")
self.settingsDialog.group_account.widget_loggedIn.loginButton.setText("Logout" if self.access_token is not None else "Login")
#
if self.set.token is None and len(self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) > 0:
self.settingsDialog.group_account.widget_loggedIn.passwordEdit.setText(
"X" * 8)
if self.access_token is None and len(self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) > 0:
self.settingsDialog.group_account.widget_loggedIn.passwordEdit.setText("X" * 8)
for elm in [self.settingsDialog.group_account.widget_loggedIn.usernameEdit, self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit, self.settingsDialog.group_account.widget_loggedIn.passwordEdit]:
elm.setEnabled(self.set.token is None)
self.settingsDialog.group_location.setEnabled(
self.set.token is not None)
self.settingsDialog.group_location.widget_location.pathEdit.setText(
self.set.library_path or "/")
elm.setEnabled(self.access_token is None)
self.settingsDialog.group_location.setEnabled(self.access_token is not None)
self.settingsDialog.group_location.widget_location.pathEdit.setText(self.lib_path or "/")
self.settingsDialog.linkCopyCheck.setChecked(self.copyLink)
self.populateLibrarySelector()
self.settingsDialog.adjustSize()
@@ -83,30 +72,52 @@ class SeafileUploader():
settings = QSettings()
settings.beginGroup("uploaders")
settings.beginGroup("seafile")
self.set.load(settings)
self.seaf_url = settings.value("seafile-url", "")
(self.lib_id,self.lib_name) = str(settings.value("library", "/")).split("/")
self.lib_path = settings.value("library-path", "")
self.copyLink = settings.value("copy-link", "true") in ['true', True]
self.nameFormat = settings.value(
"name-format", "Screenshot %Y-%m-%d %H_%M_%S")
if settings.value("auth-token", False) and settings.value("auth-username", False):
self.access_token = SeafileToken(settings.value("auth-username", False),settings.value("auth-token", False))
else:
self.access_token = None
self.nameFormat = settings.value("name-format", "Screenshot %Y-%m-%d %H_%M_%S")
self.upload_scheme = settings.value("upload-scheme", "regular")
settings.endGroup()
settings.endGroup()
if self.seaf_url and self.access_token:
self.seaf_client = SeafileClient(self.seaf_url,self.access_token.username,token=self.access_token)
for lib in self.seaf_client.libraries():
if lib.id == self.lib_id:
self.seaf_lib = lib
if self.seaf_lib and self.seaf_path:
self.processor = EncryptedProcessor(self.seaf_lib,self.lib_path)#DefaultProcessor(self.seaf_lib,self.lib_path)
def saveSettings(self):
settings = QSettings()
settings.beginGroup("uploaders")
settings.beginGroup("seafile")
self.set.save(settings)
try:
self.copyLink = self.settingsDialog.linkCopyCheck.checked
except:
pass
settings.setValue("copy-link", self.copyLink)
if self.access_token is not None:
settings.setValue("auth-username", self.access_token.username )
settings.setValue("auth-token", self.access_token.token)
settings.setValue("seafile-url", self.seaf_url)
if self.seaf_lib is not None:
settings.setValue("library", "%s/%s" % (self.seaf_lib.id,self.seaf_lib.name))
settings.setValue("library-path", self.lib_path)
settings.setValue("name-format", self.nameFormat)
settings.setValue("upload-scheme", self.upload_scheme)
#settings.setValue("name-format", self.settingsDialog.group_name.input_name.text)
print self.seaf_lib, self.lib_path
settings.endGroup()
settings.endGroup()
def isConfigured(self):
return self.set.library and self.set.processor.is_configured()
return self.access_token and self.seaf_url and self.processor.is_configured()
def getFilename(self):
self.loadSettings()
@@ -114,55 +125,52 @@ class SeafileUploader():
def upload(self, screenshot, name):
self.loadSettings()
# Make sure we have a up to date token
if not self.set.library:
#Make sure we have a up to date token
if not self.seaf_lib:
ScreenCloud.setError("Not configured properly")
return False
# Save to a temporary file
#Save to a temporary file
timestamp = time.time()
def tempfile(name):
try:
return QDesktopServices.storageLocation(QDesktopServices.TempLocation) + "/" + name
except AttributeError:
from PythonQt.QtCore import QStandardPaths # fix for Qt5
from PythonQt.QtCore import QStandardPaths #fix for Qt5
return QStandardPaths.writableLocation(QStandardPaths.TempLocation) + "/" + name
tmpFilename = tempfile(ScreenCloud.formatFilename(str(timestamp)))
screenshot.save(QFile(tmpFilename), ScreenCloud.getScreenshotFormat())
# Upload!
link = None
# if True:
try:
link = self.set.processor.upload(tmpFilename, self.getFilename())
#Upload!
link=None
if True:
#try:
link = self.processor.upload(tmpFilename,self.getFilename())
if self.copyLink:
ScreenCloud.setUrl(link)
except Exception as e:
ScreenCloud.setError("Failed to upload to seafile. Using: %s\n\n%s" % (
self.set.processor.name(), e.message))
return False
#except Exception as e:
# ScreenCloud.setError("Failed to upload to seafile. " + e.message)
# return False
return True
def startAuthenticationProcess(self):
self.saveSettings()
self.loadSettings()
if self.set.token is not None:
if self.access_token is not None:
self.logOut()
return
if self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text \
and self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text \
and self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text:
self.set.url = self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text
self.seaf_url = self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text
if True:
# try:
self.login(self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text,
self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text)
#try:
self.login(self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text,self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text)
self.saveSettings()
self.loadSettings()
self.populateLibrarySelector()
# except Exception as e:
#except Exception as e:
#QMessageBox.critical(self.settingsDialog, "Failed to login", "Verify your server url and credentials" + e.message)
self.saveSettings()
self.updateUi()
@@ -170,32 +178,31 @@ class SeafileUploader():
def locationUpdate(self):
drop = self.settingsDialog.group_location.widget_location.libraryEditDrop
selected_lib = drop.currentText
if not drop.isEnabled():
return # not populated
self.set.library_path = self.settingsDialog.group_location.widget_location.pathEdit.text
print(self.set.library_path, selected_lib)
if self.libs is None:
return
if not drop.isEnabled(): return #not populated
self.lib_path = self.settingsDialog.group_location.widget_location.pathEdit.text
print self.lib_path, selected_lib
if self.libs is None: return
for lib in self.libs:
if lib.name == selected_lib:
self.set.library = lib
print("%s user selected" % selected_lib)
self.seaf_lib = lib
print "%s user selected" % selected_lib
def login(self, user, password):
cli = SeafileClient(self.set.url, user, password)
self.set.token = cli.obtain_token()
def login(self,user,password):
cli = SeafileClient(self.seaf_url,user,password)
self.access_token = cli.obtain_token()
def logOut(self):
settings = QSettings()
settings.beginGroup("uploaders")
settings.beginGroup("seafile")
settings.remove("auth-token")
self.set.token = None
self.access_token = None
settings.endGroup()
settings.endGroup()
self.loadSettings()
self.updateUi()
def nameFormatEdited(self, nameFormat):
self.settingsDialog.group_name.label_example.setText(
ScreenCloud.formatFilename(nameFormat, False))
self.settingsDialog.group_name.label_example.setText(ScreenCloud.formatFilename(nameFormat, False))

View File

@@ -1,4 +1,8 @@
mkdir -p modules
pip3 install --install-option="--prefix=$PWD" -r requirements.txt "$@"
mv lib/python3.*/site-packages/* modules/
set -e
rm -rf modules
mkdir modules
pip install --install-option="--prefix=$PWD" -r requirements.txt
mv lib/python2.7/site-packages/* modules/
cp imports/* -r modules/

View File

@@ -1,6 +1,5 @@
asn1crypto==0.24.0
pycrypto
#scrypt
scrypt
bson==0.5.6
salsa20
requests