still WIP
This commit is contained in:
parent
68a15dbfc8
commit
1b9d432af9
@ -7,6 +7,7 @@ pipeline:
|
|||||||
modules:
|
modules:
|
||||||
image: python:3.5
|
image: python:3.5
|
||||||
commands:
|
commands:
|
||||||
|
- rm -rf modules
|
||||||
- mkdir -p .pip3
|
- mkdir -p .pip3
|
||||||
- ./make-modules.sh --cache-dir .pip3
|
- ./make-modules.sh --cache-dir .pip3
|
||||||
package:
|
package:
|
||||||
@ -24,7 +25,3 @@ pipeline:
|
|||||||
- sha256
|
- sha256
|
||||||
when:
|
when:
|
||||||
event: tag
|
event: tag
|
||||||
clean:
|
|
||||||
image: kramos/alpine-zip
|
|
||||||
commands:
|
|
||||||
- rm -rf modules
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
modules
|
modules
|
||||||
.pip3
|
.pip3
|
||||||
seafile.zip
|
seafile.zip
|
||||||
|
lib
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
import bson#, scrypt
|
from Crypto.Signature import PKCS1_v1_5
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
import bson # , scrypt
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Crypto.Util import Counter
|
from Crypto.Util import Counter
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from Crypto.PublicKey import DSA
|
from Crypto.PublicKey import DSA
|
||||||
from salsa20 import Salsa20_keystream
|
from salsa20 import Salsa20_keystream
|
||||||
import os, struct, time, hashlib, hashlib, random, binascii
|
import os
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
import hashlib
|
||||||
|
import hashlib
|
||||||
|
import random
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
|
||||||
class EncryptedScreenshot:
|
class EncryptedScreenshot:
|
||||||
def __init__(self, metadata,password=None,id=None,signer=None,password_encryptor=None):
|
def __init__(self, metadata, password=None, id=None, signer=None, password_encryptor=None):
|
||||||
def rand(len):
|
def rand(len):
|
||||||
return ''.join(
|
return ''.join(
|
||||||
random.choice("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz") for _ in range(len))
|
random.choice("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz") for _ in range(len))
|
||||||
@ -24,14 +32,16 @@ class EncryptedScreenshot:
|
|||||||
self.password_encryptor = password_encryptor
|
self.password_encryptor = password_encryptor
|
||||||
|
|
||||||
def caesar_encrypted_password(self):
|
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_plaintext = map(ord, self.password)
|
||||||
caesar_ciphertext = Caesar().encrypt(caesar_plaintext,caesar_key)
|
caesar_ciphertext = Caesar().encrypt(caesar_plaintext, caesar_key)
|
||||||
return ''.join(map(chr,caesar_ciphertext))
|
return ''.join(map(chr, caesar_ciphertext))
|
||||||
|
|
||||||
def passphrase(self):
|
def passphrase(self):
|
||||||
# new ScryptParameters(64, 8, 1,32, new Uint8List.fromList(new List<int>()))
|
# 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 = hashlib.sha256()
|
||||||
sha.update(self.password.encode("utf-8"))
|
sha.update(self.password.encode("utf-8"))
|
||||||
return sha.digest() # scrypt.hash(self.password.encode("utf-8"), '', 64, 8, 1, 32)
|
return sha.digest() # scrypt.hash(self.password.encode("utf-8"), '', 64, 8, 1, 32)
|
||||||
@ -41,7 +51,8 @@ class EncryptedScreenshot:
|
|||||||
self.metadata["hash"] = image_digest
|
self.metadata["hash"] = image_digest
|
||||||
unencrypted_metadata = bson.dumps(self.metadata)
|
unencrypted_metadata = bson.dumps(self.metadata)
|
||||||
if len(unencrypted_metadata) % 16 != 0:
|
if len(unencrypted_metadata) % 16 != 0:
|
||||||
unencrypted_metadata += b' ' * (16 - len(unencrypted_metadata) % 16)
|
unencrypted_metadata += b' ' * \
|
||||||
|
(16 - len(unencrypted_metadata) % 16)
|
||||||
(encryptor, iv) = self.encryptor(len(unencrypted_metadata))
|
(encryptor, iv) = self.encryptor(len(unencrypted_metadata))
|
||||||
encrypted_metadata = b''
|
encrypted_metadata = b''
|
||||||
|
|
||||||
@ -54,7 +65,7 @@ class EncryptedScreenshot:
|
|||||||
#print("Unencrypted: %s" % (unencrypted_metadata.encode("hex")))
|
#print("Unencrypted: %s" % (unencrypted_metadata.encode("hex")))
|
||||||
#print("Password %s" % self.password)
|
#print("Password %s" % self.password)
|
||||||
|
|
||||||
#print(bson.loads(unencrypted_metadata))
|
# print(bson.loads(unencrypted_metadata))
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
"image": encrypted_image,
|
"image": encrypted_image,
|
||||||
@ -64,25 +75,27 @@ class EncryptedScreenshot:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.signer is not None:
|
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:
|
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)
|
return bson.dumps(fields)
|
||||||
|
|
||||||
def encryptor(self,length=0):
|
def encryptor(self, length=0):
|
||||||
iv = os.urandom(16)
|
iv = os.urandom(16)
|
||||||
nonce = int(binascii.hexlify(iv), 16)
|
nonce = int(binascii.hexlify(iv), 16)
|
||||||
ctr = Counter.new(128,initial_value = nonce)# initial_value = nonce)
|
ctr = Counter.new(128, initial_value=nonce) # initial_value = nonce)
|
||||||
print("IV: %s" % binascii.hexlify(iv))
|
print("IV: %s" % binascii.hexlify(iv))
|
||||||
cipher = AES.new(self.passphrase(), AES.MODE_CTR, counter=ctr)
|
cipher = AES.new(self.passphrase(), AES.MODE_CTR, counter=ctr)
|
||||||
|
|
||||||
#salsa
|
# salsa
|
||||||
# keysstream = bytearray(Salsa20_keystream(length,iv[:8],self.passphrase()))
|
# keysstream = bytearray(Salsa20_keystream(length,iv[:8],self.passphrase()))
|
||||||
# offset={"offset": 0}
|
# offset={"offset": 0}
|
||||||
def encrypt(data):
|
def encrypt(data):
|
||||||
#Salsa20
|
# Salsa20
|
||||||
# array = bytearray(data)
|
# array = bytearray(data)
|
||||||
# for i in range(len(array)):
|
# for i in range(len(array)):
|
||||||
# array[i] ^= keysstream[i+offset["offset"]]
|
# array[i] ^= keysstream[i+offset["offset"]]
|
||||||
@ -109,16 +122,14 @@ class EncryptedScreenshot:
|
|||||||
binary += encryptor(chunk)
|
binary += encryptor(chunk)
|
||||||
return (digest.digest(), iv + binary)
|
return (digest.digest(), iv + binary)
|
||||||
|
|
||||||
from Crypto.Signature import PKCS1_v1_5
|
|
||||||
from Crypto.Hash import SHA256
|
|
||||||
|
|
||||||
class Signer:
|
class Signer:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def default():
|
def default():
|
||||||
return Signer(RSA.importKey("-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEAuTEHVWjtwFydG/VmHKr15qymIkwZIaNnQeKmBzzn+n87Zjdg\nkEDtCEYSq3W1VxlgUw1Dh8KTTr3K1LQwcDfx8vdArk99OX4mxqpYWRbdfEQk1wUD\n7ctr2E5eKQcCcbAl/OKYFa/PkY3KsBuns06Rlf85sHSZ7CfirqH6FoefrXDZVAJO\nmrQhTh/0qGlBy1f13c2a12sFNOmncLs8Vp4ftJxLr9GoE4vsQvX/6oQvi7PqWYmv\nlwmUUvhCPS/JSF8kCuvmvfgcF8OXOj1Q6itOLZDt8/ZuZeok7nS8JxhR73HzHR4a\nHWnqC8UkIx1CR/VvlZhp/7gbS/y1EORRaVlO3YTkF2UMTtF2BoCsY5glpealDV6F\nh9YZwq68APb5/cleuXu8tebYpo5yuwH9G8m0bp7mIrVUnaBPCE/Wsj6HFULniUi8\n0N8149cM2kLmm7c+JNC4QUupc3iy3qylqh1KFlU0SWPAinDbODSHqnPiWV0IHjC9\nmVeAmMDjg/6R7uaAubLz0rJso/odk0kfWYO98D43Hv7C+TG/If9oE7JdsgSCCfeT\nuaKE5XH3C3GegciDOyr6Sd/08KprQwvy7nZpJJxzpyr2MoJ/n8O6O4IqDt76EAZz\n76nUvJzPXSoUGy7942QOwywpRYB6NbrVpPUemUCsUttUJzhgHU70ElqE2hsCAwEA\nAQKCAgBVyMZS5BYt4zjLuLMiWHcr8ZHLlWCW2nB8bpbmB2qV+NX1FXXfnJOwH3WK\ngy4LOLAMCLrdal5+PSB1wzok4WVsXOhTVnL1bOBdao8eRZ83bwF5sNMPFgnQ2wx3\nCM4zB5uxNu2oLhaCoCHhzg2y25RI3T9F491hLWCt8E4+nXh0CTBC4Aa1VveOjvLw\nCEH4BbjYk+NEIkj5J7ruV20t2nVpXnUY7o9i7o/0vKtdYPn9RswpycPSvRc+D83v\nNfGRWrEBdiEeoo2w3GNzEPAoaQL/zIDNX7vn7bxJ0T1PBs79kdVCCa2jLmrCJQIG\nWglX9/NGYqHHWOscGeVt+7VSjZIf8+q32khXcheBUP++wsDC1YoxiT2aDwV7zX8d\nBhB6MMi7QUqkkwnuvXdyUIUy4J7lJHDsC5l4EYDmbhViTax8Qp42MobJ32tHoS1c\nhfN5w4Usqx7yGRL0vUQmbGrh7JbyayD6CFYiZOinhN0ma7dMqglQ4ch3HPeMct9T\nLskF+gSlol2gTCMYjl9Zwb2rG8uSthjXFd2CDCHbiqzzRhskHG2vWuhxvASP4yeD\nNbm85H8ZKqhejcWL4XlJIZK2ZbWUjdMDPCDDd3ipwQ/GUmSo6IaNxEFMCFLsk/xl\n2BGg99xDuacldKNUtf+aMv4HglW6at+TasVsmWXsF/cWR1JusQKCAQEA88JECQTE\nm8AIOaHY5rOWxkYCsVzVw9zRHOfIXbvMMr9k3OTE/9gNy35QTee5UYVEnjRuWP/r\n2hRJhbTfwP5LmcvsxN3cE3SkrlNCulo0TWD4O78W+PnEkSzN+1h39QOfA/TTN9pV\nnqh7Bf5u9kBioooPeUe6yU/eMlVa+mzwNfDC9ogS7o1/1Zy4ui4beo0XpIv5KNtV\nU5K2uEcx0jnAzhcd+IKzDNm7HuU82KCsYNUCdHIJOpoq0WqPTqa350LPWHqbZA9n\nOa+5Yo1ADMn/rMFohErWq2zjUlO3qFjyGBaVAQCYCeprmk56vk4gP44X2YkW524G\nHg/CWYITF42W7QKCAQEAwn3UDzS1LeCZq82TSlFPWO3dojh4fMwssQWzJkrkJg4N\nNlAGGteh7K2eIFjACk7bLe037F2RhPxk+RZEIy4Adr5oAcNLKXMIcaAx9Xca+JrX\nRjLAGsBuoOJFYBVm+/ZlwoVkhOnX1VOJ4Zt4TNOYcImrhZyeVjVfJI7ijTU61v5M\n2+6Ekc2pq6WI7/2hmM+UOw6xvroNvCx0neWVgAVdCWfWWmCkUqjsS8FJ2z9q/8or\nnFPKeAT/kcDg2N+8LiPeVfAqdl6GZ3SY3lZ+Q+JEJMAZEsFsbh0x5OT4750Y/MBz\nqQF1oU2HkV5xah5tAqECp37/FSIxPG2e/qklGqbMJwKCAQA/qkSUym8DcvNzAgeh\nsdQ2cwCvDF00q87eKteVS8B4nK6eVw3w+KAZvyMARf6MAS+71lvf2O/j5JqTVnt+\nb6yVPcLYZE3fsv50HYD3JSo175bGHBHG841YkYg3FpM2Jjz5Do/ALcFhEAYZuauH\nm6dnZoHGHmr1u2uAX/TEJYHTxM9XDpFLRx/VTfqdff9lUcaUDo8EEc1GZ7JbjRTB\nIJ5v9W+5gYF8YL3TwvHSbpy3KctbWJF6gdufGKLXWwn7V+LJ7DP7vV4rne7gg53v\n+S5TE6zVqKpK2cTBsuXsDVcl3XgLa/lJ1bVG9ypt2//mOZmXEowt4/mrDlingia0\nZyG9AoIBAAvBQSTeIakxLviER0exnGMalU+trBKW4IieeJJy6lEmfkPvGD9dEwtT\n/v+jfY/h7jtbYAroKNhpzMyFPP8HU73Zij25CPzrV/JOJVbZqQanjSVQAe5b/RO6\nOUkyYfQOk13rZATogUQCdY3uMJosG8WJfJVpvuQk+6gg/q5cLj86RXjxdI+/Z2bZ\nbWpb4P10ZlgfbjzBz/y0jyPP8XY4XMQpw3nY53WbghSeDRG0RopJNNOQ+ObCHpQ3\nnR9efmgngNOe3WIkGml8UZT2k1EVBttVxO4uRJhvKUnVUPpie1UjaJopXWuvXOc7\nVw1740jKZHetJEupsmIdmgN4Q6bVt/cCggEBAILm8bfc2OGbZgN4RT4315EkWekb\nMngMFETDDgn6p2jmkVjXDGku1oX502X7BKteZ+gD4Oqy8BtrvshyzvzoBerthrDj\nJ4M3t7uFC14mvRfdelRcKyed13SGzZNJxxxL7vNq2Me81yzBaMPiAZpDIN4awEzV\nPQwWMmogo6sEp2ND2NhvbP4Hxl8WXoI+3hH5hetE31kvBzDlWek4Wj059BeeIhjF\nBNUxIwbqlSwt+2VuY17LBzCe4Tnp3Ns+ptD9Fn2vm+Azl9qBY2VvqOcdp0R8tmeo\nwpjrWKwP9LkwCt9ZxVzCQBiIFYtpZ8a2EahqTbOlFEsvcDbTfQlf/lykhjA=\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.mode = mode
|
||||||
self.privateKeyId = privateKeyId
|
self.privateKeyId = privateKeyId
|
||||||
self._signer = PKCS1_v1_5.new(privateKey)
|
self._signer = PKCS1_v1_5.new(privateKey)
|
||||||
@ -128,7 +139,7 @@ class Signer:
|
|||||||
digest.update(data)
|
digest.update(data)
|
||||||
return self._signer.sign(digest)
|
return self._signer.sign(digest)
|
||||||
|
|
||||||
def signature(self,data):
|
def signature(self, data):
|
||||||
signed = self.sign(data)
|
signed = self.sign(data)
|
||||||
return {"signed-hash": signed,
|
return {"signed-hash": signed,
|
||||||
"signature-algorithm": "SHA-256/%s" % ("RSA" if self.mode == RSA else "DSA"),
|
"signature-algorithm": "SHA-256/%s" % ("RSA" if self.mode == RSA else "DSA"),
|
||||||
@ -138,40 +149,41 @@ class Signer:
|
|||||||
|
|
||||||
class EncryptedPassword:
|
class EncryptedPassword:
|
||||||
|
|
||||||
def __init__(self,publicKey,publicKeyId,mode=RSA):
|
def __init__(self, publicKey, publicKeyId, mode=RSA):
|
||||||
assert mode == RSA
|
assert mode == RSA
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.publicKey = publicKey
|
self.publicKey = publicKey
|
||||||
self.publicKeyId = publicKeyId
|
self.publicKeyId = publicKeyId
|
||||||
|
|
||||||
def encrypt(self,password):
|
def encrypt(self, password):
|
||||||
return self.publicKey.encrypt(password.encode("utf-8"), os.urandom(32))[0]
|
return self.publicKey.encrypt(password.encode("utf-8"), os.urandom(32))[0]
|
||||||
|
|
||||||
def encrypt_password(self,password):
|
def encrypt_password(self, password):
|
||||||
return {"algorithm": unicode( "RSA" if self.mode == RSA else "DSA"),
|
return {"algorithm": unicode("RSA" if self.mode == RSA else "DSA"),
|
||||||
"key-id": unicode(self.publicKeyId),
|
"key-id": unicode(self.publicKeyId),
|
||||||
"password": self.encrypt(password)
|
"password": self.encrypt(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Caesar:
|
class Caesar:
|
||||||
|
|
||||||
def __init__(self,charset = map(ord,list("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz"))):
|
def __init__(self, charset=map(ord, list("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz"))):
|
||||||
self.charset = charset
|
self.charset = charset
|
||||||
|
|
||||||
def encrypt(self,plaintext,key):
|
def encrypt(self, plaintext, key):
|
||||||
if key >= len(self.charset) or key < 0:
|
if key >= len(self.charset) or key < 0:
|
||||||
key = key % len(self.charset)
|
key = key % len(self.charset)
|
||||||
|
|
||||||
def addKey(charcode):
|
def addKey(charcode):
|
||||||
pos = self.charset.index(charcode)
|
pos = self.charset.index(charcode)
|
||||||
if pos + key >= len(self.charset):
|
if pos + key >= len(self.charset):
|
||||||
return self.charset[pos+key - len(self.charset)]
|
return self.charset[pos+key - len(self.charset)]
|
||||||
else:
|
else:
|
||||||
return self.charset[pos+key]
|
return self.charset[pos+key]
|
||||||
return map(addKey,plaintext)
|
return map(addKey, plaintext)
|
||||||
|
|
||||||
def decrypt(self,ciphertext,key):
|
def decrypt(self, ciphertext, key):
|
||||||
return self.encrypt(ciphertext,key*-1)
|
return self.encrypt(ciphertext, key*-1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -179,22 +191,26 @@ if __name__ == "__main__":
|
|||||||
publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF1VEVIVldqdHdGeWRHL1ZtSEtyMQo1cXltSWt3WklhTm5RZUttQnp6bituODdaamRna0VEdENFWVNxM1cxVnhsZ1V3MURoOEtUVHIzSzFMUXdjRGZ4Cjh2ZEFyazk5T1g0bXhxcFlXUmJkZkVRazF3VUQ3Y3RyMkU1ZUtRY0NjYkFsL09LWUZhL1BrWTNLc0J1bnMwNlIKbGY4NXNIU1o3Q2ZpcnFINkZvZWZyWERaVkFKT21yUWhUaC8wcUdsQnkxZjEzYzJhMTJzRk5PbW5jTHM4VnA0Zgp0SnhMcjlHb0U0dnNRdlgvNm9Rdmk3UHFXWW12bHdtVVV2aENQUy9KU0Y4a0N1dm12ZmdjRjhPWE9qMVE2aXRPCkxaRHQ4L1p1WmVvazduUzhKeGhSNzNIekhSNGFIV25xQzhVa0l4MUNSL1Z2bFpocC83Z2JTL3kxRU9SUmFWbE8KM1lUa0YyVU1UdEYyQm9Dc1k1Z2xwZWFsRFY2Rmg5WVp3cTY4QVBiNS9jbGV1WHU4dGViWXBvNXl1d0g5RzhtMApicDdtSXJWVW5hQlBDRS9Xc2o2SEZVTG5pVWk4ME44MTQ5Y00ya0xtbTdjK0pOQzRRVXVwYzNpeTNxeWxxaDFLCkZsVTBTV1BBaW5EYk9EU0hxblBpV1YwSUhqQzltVmVBbU1EamcvNlI3dWFBdWJMejBySnNvL29kazBrZldZTzkKOEQ0M0h2N0MrVEcvSWY5b0U3SmRzZ1NDQ2ZlVHVhS0U1WEgzQzNHZWdjaURPeXI2U2QvMDhLcHJRd3Z5N25acApKSnh6cHlyMk1vSi9uOE82TzRJcUR0NzZFQVp6NzZuVXZKelBYU29VR3k3OTQyUU93eXdwUllCNk5iclZwUFVlCm1VQ3NVdHRVSnpoZ0hVNzBFbHFFMmhzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
|
publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF1VEVIVldqdHdGeWRHL1ZtSEtyMQo1cXltSWt3WklhTm5RZUttQnp6bituODdaamRna0VEdENFWVNxM1cxVnhsZ1V3MURoOEtUVHIzSzFMUXdjRGZ4Cjh2ZEFyazk5T1g0bXhxcFlXUmJkZkVRazF3VUQ3Y3RyMkU1ZUtRY0NjYkFsL09LWUZhL1BrWTNLc0J1bnMwNlIKbGY4NXNIU1o3Q2ZpcnFINkZvZWZyWERaVkFKT21yUWhUaC8wcUdsQnkxZjEzYzJhMTJzRk5PbW5jTHM4VnA0Zgp0SnhMcjlHb0U0dnNRdlgvNm9Rdmk3UHFXWW12bHdtVVV2aENQUy9KU0Y4a0N1dm12ZmdjRjhPWE9qMVE2aXRPCkxaRHQ4L1p1WmVvazduUzhKeGhSNzNIekhSNGFIV25xQzhVa0l4MUNSL1Z2bFpocC83Z2JTL3kxRU9SUmFWbE8KM1lUa0YyVU1UdEYyQm9Dc1k1Z2xwZWFsRFY2Rmg5WVp3cTY4QVBiNS9jbGV1WHU4dGViWXBvNXl1d0g5RzhtMApicDdtSXJWVW5hQlBDRS9Xc2o2SEZVTG5pVWk4ME44MTQ5Y00ya0xtbTdjK0pOQzRRVXVwYzNpeTNxeWxxaDFLCkZsVTBTV1BBaW5EYk9EU0hxblBpV1YwSUhqQzltVmVBbU1EamcvNlI3dWFBdWJMejBySnNvL29kazBrZldZTzkKOEQ0M0h2N0MrVEcvSWY5b0U3SmRzZ1NDQ2ZlVHVhS0U1WEgzQzNHZWdjaURPeXI2U2QvMDhLcHJRd3Z5N25acApKSnh6cHlyMk1vSi9uOE82TzRJcUR0NzZFQVp6NzZuVXZKelBYU29VR3k3OTQyUU93eXdwUllCNk5iclZwUFVlCm1VQ3NVdHRVSnpoZ0hVNzBFbHFFMmhzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
|
||||||
encrypted = EncryptedScreenshot({"owner": u"test", "format": u"jpg", "title": u"5x5 Red", "timestamp": int(time.time()*1000)},
|
encrypted = EncryptedScreenshot({"owner": u"test", "format": u"jpg", "title": u"5x5 Red", "timestamp": int(time.time()*1000)},
|
||||||
signer=Signer.default(),
|
signer=Signer.default(),
|
||||||
password_encryptor=EncryptedPassword(RSA.importKey(publicKey.decode("base64")),"PUBLIC"))
|
password_encryptor=EncryptedPassword(RSA.importKey(publicKey.decode("base64")), "PUBLIC"))
|
||||||
fixed_id = encrypted.id #"W9u9Zm0u"
|
fixed_id = encrypted.id # "W9u9Zm0u"
|
||||||
print(len(encrypted.passphrase()))
|
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")
|
assembled = encrypted.assemble("5x5red.png")
|
||||||
out.write(assembled)
|
out.write(assembled)
|
||||||
b = bson.loads(assembled)
|
b = bson.loads(assembled)
|
||||||
del b["image"]
|
del b["image"]
|
||||||
print(b)
|
print(b)
|
||||||
#print(assembled.encode("base64").replace("\n","")
|
# print(assembled.encode("base64").replace("\n","")
|
||||||
print("http://localhost:8080/#%s%s" % (fixed_id, encrypted.password))
|
print("http://localhost:8080/#%s%s" % (fixed_id, encrypted.password))
|
||||||
caesar_key = reduce(lambda sum,charcode: sum+charcode, map(ord,list(fixed_id)))
|
caesar_key = reduce(lambda sum, charcode: sum +
|
||||||
caesar_plaintext = map(ord,encrypted.password)
|
charcode, map(ord, list(fixed_id)))
|
||||||
caesar_ciphertext = Caesar().encrypt(caesar_plaintext,caesar_key)
|
caesar_plaintext = map(ord, encrypted.password)
|
||||||
assert caesar_plaintext == Caesar().decrypt(caesar_ciphertext,caesar_key)
|
caesar_ciphertext = Caesar().encrypt(caesar_plaintext, caesar_key)
|
||||||
print("caesar_key=%s %s -> %s" % (caesar_key,encrypted.password,''.join(map(chr,caesar_ciphertext))))
|
assert caesar_plaintext == Caesar().decrypt(caesar_ciphertext, caesar_key)
|
||||||
print("http://localhost:8080/#%s%sC" % (fixed_id, encrypted.caesar_encrypted_password()))
|
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, ))
|
print("http://localhost:8080/#%s" % (fixed_id, ))
|
||||||
out.close()
|
out.close()
|
||||||
|
@ -2,6 +2,7 @@ import hashlib
|
|||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
|
|
||||||
|
|
||||||
class HashDerivedKey:
|
class HashDerivedKey:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -13,18 +14,20 @@ class HashDerivedKey:
|
|||||||
assert isinstance(b, bytes)
|
assert isinstance(b, bytes)
|
||||||
return b
|
return b
|
||||||
ensure_bytes(master)
|
ensure_bytes(master)
|
||||||
|
|
||||||
def derive(seed):
|
def derive(seed):
|
||||||
ensure_bytes(seed)
|
ensure_bytes(seed)
|
||||||
sha = hashlib.sha256()
|
sha = hashlib.sha256()
|
||||||
sha.update(master)
|
sha.update(master)
|
||||||
sha.update(seed)
|
sha.update(seed)
|
||||||
return sha.digest()
|
return sha.digest()
|
||||||
hex = lambda b: binascii.hexlify(b).decode("utf-8")
|
|
||||||
|
def hex(b): return binascii.hexlify(b).decode("utf-8")
|
||||||
self.master = master
|
self.master = master
|
||||||
self.master_hex = lambda: hex(master)
|
self.master_hex = lambda: hex(master)
|
||||||
self.derive = derive
|
self.derive = derive
|
||||||
self.derive_hex = lambda seed: hex(derive(seed))
|
self.derive_hex = lambda seed: hex(derive(seed))
|
||||||
|
|
||||||
def derive_metadata(self,seed):
|
def derive_metadata(self, seed):
|
||||||
key = self.derive(seed)
|
key = self.derive(seed)
|
||||||
return (key,{"key_seed": binascii.hexlify(seed).decode("utf-8")})
|
return (key, {"key_seed": binascii.hexlify(seed).decode("utf-8")})
|
||||||
|
@ -2,101 +2,122 @@ import time
|
|||||||
|
|
||||||
from encryptedscreenshot import EncryptedScreenshot, Signer
|
from encryptedscreenshot import EncryptedScreenshot, Signer
|
||||||
from hashderive import HashDerivedKey
|
from hashderive import HashDerivedKey
|
||||||
import getpass, os, sys
|
import getpass
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
from PythonQt.QtGui import QInputDialog
|
from PythonQt.QtGui import QInputDialog
|
||||||
from PythonQt.QtCore import QSettings
|
from PythonQt.QtCore import QSettings
|
||||||
from seafapi import *
|
from seafapi import *
|
||||||
|
|
||||||
|
|
||||||
class Processor:
|
class Processor:
|
||||||
|
|
||||||
def configure(self,parent):
|
def name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure(self, parent):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def is_configured(self):
|
def is_configured(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def upload(self,file):
|
def load_settings(self, settings):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def save_settings(self, settings):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def upload(self, file, name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class DummyProcessor(Processor):
|
class DummyProcessor(Processor):
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return None
|
||||||
|
|
||||||
def is_configured(self):
|
def is_configured(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class DefaultProcessor(Processor):
|
class DefaultProcessor(Processor):
|
||||||
|
|
||||||
def __init__(self,seaf_lib,lib_path):
|
def name(self):
|
||||||
|
return "default"
|
||||||
|
|
||||||
|
def __init__(self, seaf_lib, lib_path):
|
||||||
self.seaf_lib = seaf_lib
|
self.seaf_lib = seaf_lib
|
||||||
self.lib_path = lib_path
|
self.lib_path = lib_path
|
||||||
|
|
||||||
def upload(self,file,name):
|
def upload(self, file, name):
|
||||||
return self.seaf_lib.upload(file,name,self.lib_path).share()
|
return self.seaf_lib.upload(file, name, self.lib_path).share()
|
||||||
|
|
||||||
|
|
||||||
class EncryptedProcessor(Processor):
|
class EncryptedProcessor(Processor):
|
||||||
|
|
||||||
def __init__(self,seaf_lib,lib_path):
|
def name(self):
|
||||||
|
return "enc"
|
||||||
|
|
||||||
|
def __init__(self, seaf_lib, lib_path):
|
||||||
self.seaf_lib = seaf_lib
|
self.seaf_lib = seaf_lib
|
||||||
self.lib_path = lib_path
|
self.lib_path = lib_path
|
||||||
self.host = None
|
self.host = None
|
||||||
self.derived_key = HashDerivedKey(os.urandom(32))
|
self.derived_key = HashDerivedKey(os.urandom(32))
|
||||||
self.load_settings()
|
self.load_settings()
|
||||||
|
|
||||||
def load_settings(self):
|
def load_settings(self, settings=QSettings()):
|
||||||
settings = QSettings()
|
|
||||||
settings.beginGroup("uploaders")
|
|
||||||
settings.beginGroup("seafile")
|
|
||||||
self.host = settings.value("encscreen-url", None)
|
self.host = settings.value("encscreen-url", None)
|
||||||
if settings.value("encscreen-derived-key", None):
|
if settings.value("encscreen-derived-key", None):
|
||||||
self.derived_key = HashDerivedKey.from_hex(settings.value("encscreen-derived-key", None))
|
self.derived_key = HashDerivedKey.from_hex(
|
||||||
|
settings.value("encscreen-derived-key", None))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def save_settings(self):
|
def save_settings(self, settings=QSettings()):
|
||||||
settings = QSettings()
|
|
||||||
settings.beginGroup("uploaders")
|
|
||||||
settings.beginGroup("seafile")
|
|
||||||
settings.setValue("encscreen-url", self.host)
|
settings.setValue("encscreen-url", self.host)
|
||||||
if self.derived_key: settings.setValue(self.derived_key.master_hex())
|
if self.derived_key:
|
||||||
|
settings.setValue(self.derived_key.master_hex())
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def is_configured(self):
|
def is_configured(self):
|
||||||
return self.host is not None and self.host != ""
|
return self.host is not None and self.host != ""
|
||||||
|
|
||||||
def configure(self,parent):
|
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"))
|
self.host = QInputDialog.getText(parent, 'Encscreen Server Setup', 'Enter server url (ex. https://servertld/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>"))
|
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:
|
try:
|
||||||
self.derived_key = HashDerivedKey.from_hex(master)
|
self.derived_key = HashDerivedKey.from_hex(master)
|
||||||
except:
|
except:
|
||||||
self.derived_key = HashDerivedKey(os.urandom(32))
|
self.derived_key = HashDerivedKey(os.urandom(32))
|
||||||
self.save_settings()
|
self.save_settings()
|
||||||
|
|
||||||
def upload(self,file,name):
|
def upload(self, file, name):
|
||||||
def derive():
|
def derive():
|
||||||
seed = os.urandom(16)
|
seed = os.urandom(16)
|
||||||
(_, key_meta) = self.derived_key.derive_metadata(seed)
|
(_, key_meta) = self.derived_key.derive_metadata(seed)
|
||||||
return (self.derived_key.derive_hex(seed)[0:16], key_meta)
|
return (self.derived_key.derive_hex(seed)[0:16], key_meta)
|
||||||
(key, key_meta) = derive()
|
(key, key_meta) = derive()
|
||||||
enrypted = EncryptedScreenshot(metadata = {
|
enrypted = EncryptedScreenshot(metadata={
|
||||||
"owner": getpass.getuser(),
|
"owner": getpass.getuser(),
|
||||||
"format": str(file).split('.')[-1],
|
"format": str(file).split('.')[-1],
|
||||||
"title": name,
|
"title": name,
|
||||||
"timestamp": int(time.time() * 1000),
|
"timestamp": int(time.time() * 1000),
|
||||||
"size": os.stat(file).st_size,
|
"size": os.stat(file).st_size,
|
||||||
"public": key_meta
|
"public": key_meta
|
||||||
},password=key,signer=Signer.default())
|
}, password=key, signer=Signer.default())
|
||||||
tmpHandle = open(file + "c", 'wb')
|
tmpHandle = open(file + "c", 'wb')
|
||||||
tmpHandle.write(enrypted.assemble(file))
|
tmpHandle.write(enrypted.assemble(file))
|
||||||
tmpHandle.close()
|
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:
|
if not seaf_file:
|
||||||
return
|
return
|
||||||
seaf_link = seaf_file.share()
|
seaf_link = seaf_file.share()
|
||||||
if seaf_link:
|
if seaf_link:
|
||||||
id = str(seaf_link).split('/')[-2]
|
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:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,57 +1,65 @@
|
|||||||
import time, os
|
import time
|
||||||
|
import os
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
class SeafileClient:
|
class SeafileClient:
|
||||||
|
|
||||||
def __init__(self,server,username,password=None,token=None):
|
def __init__(self, server, username, password=None, token=None):
|
||||||
self.server = server
|
self.server = server
|
||||||
self.token = token
|
self.token = token
|
||||||
self.session = requests.Session()
|
self.session = requests.Session()
|
||||||
if token:
|
if token:
|
||||||
self.session.headers.update({'Authorization': "Token %s" % self.token.token})
|
self.session.headers.update(
|
||||||
self.login = (username,password)
|
{'Authorization': "Token %s" % self.token.token})
|
||||||
|
self.login = (username, password)
|
||||||
|
|
||||||
def api_endpoint(self):
|
def api_endpoint(self):
|
||||||
return "%s/api2" % self.server
|
return "%s/api2" % self.server
|
||||||
|
|
||||||
def ping(self,auth=False):
|
def ping(self, auth=False):
|
||||||
try:
|
try:
|
||||||
return self.session.get("%s%s/ping" % (self.api_endpoint(),"/auth" if auth else "")).text == "\"pong\""
|
return self.session.get("%s%s/ping" % (self.api_endpoint(), "/auth" if auth else "")).text == "\"pong\""
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def obtain_token(self):
|
def obtain_token(self):
|
||||||
user,passw = self.login
|
user, passw = self.login
|
||||||
try:
|
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()
|
json = req.json()
|
||||||
if "non_field_errors" in json:
|
if "non_field_errors" in json:
|
||||||
print(json["non_field_errors"])
|
print(json["non_field_errors"])
|
||||||
return False
|
return False
|
||||||
return SeafileToken(user,json["token"])
|
return SeafileToken(user, json["token"])
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def authorize(self):
|
def authorize(self):
|
||||||
self.token = self.obtain_token()
|
self.token = self.obtain_token()
|
||||||
if self.token:
|
if self.token:
|
||||||
self.session.headers.update({'Authorization': "Token %s" % self.token.token})
|
self.session.headers.update(
|
||||||
|
{'Authorization': "Token %s" % self.token.token})
|
||||||
return self.token != False
|
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):
|
def libraries(self):
|
||||||
resp=self.session.get("%s/repos/" % self.api_endpoint(), headers = {'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4' })
|
resp = self.session.get("%s/repos/" % self.api_endpoint(), headers={
|
||||||
if not resp.status_code == 200: return
|
'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4'})
|
||||||
libraries=[]
|
if not resp.status_code == 200:
|
||||||
|
return
|
||||||
|
libraries = []
|
||||||
for lib in resp.json():
|
for lib in resp.json():
|
||||||
if not lib['encrypted']:
|
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
|
return libraries
|
||||||
|
|
||||||
|
|
||||||
class SeafileLibrary:
|
class SeafileLibrary:
|
||||||
|
|
||||||
def __init__(self,client,id,name,owner):
|
def __init__(self, client, id, name, owner):
|
||||||
self.client = client
|
self.client = client
|
||||||
self.session = client.session
|
self.session = client.session
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -59,67 +67,73 @@ class SeafileLibrary:
|
|||||||
self.owner = owner
|
self.owner = owner
|
||||||
|
|
||||||
def api_endpoint(self):
|
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():
|
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())
|
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 = self.session.get("%s/upload-link" % self.api_endpoint(), headers={
|
||||||
|
'Authorization': "Token %s" % self.client.token.token, }).text
|
||||||
return quoted[1:-1]
|
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
|
# 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() ,
|
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)},
|
files={'file': (file_name, open(
|
||||||
headers = {'Authorization': "Token %s" % self.client.token.token,}
|
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:
|
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
|
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
|
# 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):
|
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' })
|
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'})
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
json = resp.json()
|
json = resp.json()
|
||||||
return SeafileFile(self,path,json['id'],json['size'])
|
return SeafileFile(self, path, json['id'], json['size'])
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
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:
|
class SeafileFile:
|
||||||
|
|
||||||
def __init__(self,library,path,id,size=0):
|
def __init__(self, library, path, id, size=0):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.path = path
|
self.path = path
|
||||||
self.library = library
|
self.library = library
|
||||||
self.session = library.session
|
self.session = library.session
|
||||||
self.size = size
|
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):
|
def share(self):
|
||||||
resp = self.session.put("%s/repos/%s/file/shared-link/" % (self.library.client.api_endpoint(),self.library.id),
|
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'},
|
headers={'Authorization': "Token %s" % self.library.client.token.token,
|
||||||
data = {'p': self.path}
|
'Accept': 'application/json; indent=4'},
|
||||||
)
|
data={'p': self.path}
|
||||||
|
)
|
||||||
return resp.headers.get("location")
|
return resp.headers.get("location")
|
||||||
|
|
||||||
def update(self,file):
|
def update(self, file):
|
||||||
def obtain_link():
|
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/
|
||||||
quoted = self.session.get("%s/update-link" % self.library.api_endpoint(), headers = {'Authorization': "Token %s" % self.library.client.token.token,}).text
|
quoted = self.session.get("%s/update-link" % self.library.api_endpoint(), headers={
|
||||||
|
'Authorization': "Token %s" % self.library.client.token.token, }).text
|
||||||
return quoted[1:-1]
|
return quoted[1:-1]
|
||||||
directory, name = os.path.split(self.path)
|
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:
|
class SeafileToken:
|
||||||
|
|
||||||
def __init__(self,username,token):
|
def __init__(self, username, token):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.token = token
|
self.token = token
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s@%s" % (self.token,self.username)
|
return "%s@%s" % (self.token, self.username)
|
||||||
|
|
||||||
|
|
||||||
|
72
imports/settings.py
Normal file
72
imports/settings.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
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)
|
158
main.py
158
main.py
@ -3,9 +3,10 @@ import time
|
|||||||
from PythonQt.QtCore import QFile, QSettings
|
from PythonQt.QtCore import QFile, QSettings
|
||||||
from PythonQt.QtGui import QDesktopServices, QMessageBox
|
from PythonQt.QtGui import QDesktopServices, QMessageBox
|
||||||
from PythonQt.QtUiTools import QUiLoader
|
from PythonQt.QtUiTools import QUiLoader
|
||||||
from multiprocessing import Pool,Process
|
from multiprocessing import Pool, Process
|
||||||
|
|
||||||
from seafapi import *
|
from seafapi import *
|
||||||
|
from settings import SeafScreencloudSettings
|
||||||
from processors import DummyProcessor, DefaultProcessor, EncryptedProcessor
|
from processors import DummyProcessor, DefaultProcessor, EncryptedProcessor
|
||||||
###############################
|
###############################
|
||||||
## This is a temporary fix, should be removed when a newer python version is used ##
|
## This is a temporary fix, should be removed when a newer python version is used ##
|
||||||
@ -13,27 +14,29 @@ import logging
|
|||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
###############################
|
###############################
|
||||||
|
|
||||||
|
|
||||||
class SeafileUploader():
|
class SeafileUploader():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.processor = DummyProcessor()
|
self.set = SeafScreencloudSettings()
|
||||||
self.seaf_lib = None
|
|
||||||
self.seaf_path = "/"
|
|
||||||
self.libs = None
|
self.libs = None
|
||||||
self.uil = QUiLoader()
|
self.uil = QUiLoader()
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
self.pool = Pool(2)
|
self.pool = Pool(2)
|
||||||
self.seaf_client = None
|
|
||||||
|
|
||||||
def showSettingsUI(self, parentWidget):
|
def showSettingsUI(self, parentWidget):
|
||||||
self.parentWidget = parentWidget
|
self.parentWidget = parentWidget
|
||||||
#self.processor.configure(parentWidget)
|
# self.set.processor.configure(parentWidget)
|
||||||
self.settingsDialog = self.uil.load(QFile(workingDir + "/settings.ui"), parentWidget)
|
self.settingsDialog = self.uil.load(
|
||||||
self.settingsDialog.group_account.widget_loggedIn.loginButton.connect("clicked()", self.startAuthenticationProcess)
|
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_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.pathEdit.connect(
|
||||||
self.settingsDialog.group_location.widget_location.libraryEditDrop.connect("currentIndexChanged(QString)", self.locationUpdate)
|
"textChanged(QString)", self.locationUpdate)
|
||||||
|
self.settingsDialog.group_location.widget_location.libraryEditDrop.connect(
|
||||||
|
"currentIndexChanged(QString)", self.locationUpdate)
|
||||||
self.settingsDialog.connect("accepted()", self.saveSettings)
|
self.settingsDialog.connect("accepted()", self.saveSettings)
|
||||||
|
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
self.updateUi()
|
self.updateUi()
|
||||||
self.settingsDialog.open()
|
self.settingsDialog.open()
|
||||||
@ -43,29 +46,35 @@ class SeafileUploader():
|
|||||||
drop.clear()
|
drop.clear()
|
||||||
drop.setEnabled(False)
|
drop.setEnabled(False)
|
||||||
select = 0
|
select = 0
|
||||||
if self.seaf_client and self.seaf_client.ping():
|
if self.set.client() and self.set.client().ping():
|
||||||
self.libs = (self.seaf_client or self.seaf_lib.client).libraries()
|
self.libs = self.set.client().libraries()
|
||||||
i=0
|
i = 0
|
||||||
for lib in self.libs:
|
for lib in self.libs:
|
||||||
if self.seaf_lib is not None and lib.id == self.seaf_lib.id:
|
if self.set.library is not None and (lib.id == self.set.library.id or lib.name == self.set.library.name):
|
||||||
select = i
|
select = i
|
||||||
print("set %s" % lib.name)
|
print("set %s" % lib.name)
|
||||||
drop.addItem(lib.name)
|
drop.addItem(lib.name)
|
||||||
i=i+1
|
i = i+1
|
||||||
drop.setCurrentIndex(select)
|
drop.setCurrentIndex(select)
|
||||||
drop.setEnabled(True)
|
drop.setEnabled(True)
|
||||||
|
|
||||||
def updateUi(self):
|
def updateUi(self):
|
||||||
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.usernameEdit.setText(
|
||||||
self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.setText(self.seaf_url or "https://seaf.shimun.net")
|
self.set.token.username if not (self.set.token is None) else "")
|
||||||
self.settingsDialog.group_account.widget_loggedIn.loginButton.setText("Logout" if self.access_token is not None else "Login")
|
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")
|
||||||
#
|
#
|
||||||
if self.access_token is None and len(self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text) > 0:
|
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)
|
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]:
|
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.access_token is None)
|
elm.setEnabled(self.set.token is None)
|
||||||
self.settingsDialog.group_location.setEnabled(self.access_token is not None)
|
self.settingsDialog.group_location.setEnabled(
|
||||||
self.settingsDialog.group_location.widget_location.pathEdit.setText(self.lib_path or "/")
|
self.set.token is not None)
|
||||||
|
self.settingsDialog.group_location.widget_location.pathEdit.setText(
|
||||||
|
self.set.library_path or "/")
|
||||||
self.settingsDialog.linkCopyCheck.setChecked(self.copyLink)
|
self.settingsDialog.linkCopyCheck.setChecked(self.copyLink)
|
||||||
self.populateLibrarySelector()
|
self.populateLibrarySelector()
|
||||||
self.settingsDialog.adjustSize()
|
self.settingsDialog.adjustSize()
|
||||||
@ -74,106 +83,86 @@ class SeafileUploader():
|
|||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
settings.beginGroup("uploaders")
|
settings.beginGroup("uploaders")
|
||||||
settings.beginGroup("seafile")
|
settings.beginGroup("seafile")
|
||||||
self.seaf_url = settings.value("seafile-url", "")
|
self.set.load(settings)
|
||||||
(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.copyLink = settings.value("copy-link", "true") in ['true', True]
|
||||||
if settings.value("auth-token", False) and settings.value("auth-username", False):
|
self.nameFormat = settings.value(
|
||||||
self.access_token = SeafileToken(settings.value("auth-username", False),settings.value("auth-token", False))
|
"name-format", "Screenshot %Y-%m-%d %H_%M_%S")
|
||||||
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")
|
self.upload_scheme = settings.value("upload-scheme", "regular")
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
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)
|
|
||||||
if self.seaf_client.ping():
|
|
||||||
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):
|
def saveSettings(self):
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
settings.beginGroup("uploaders")
|
settings.beginGroup("uploaders")
|
||||||
settings.beginGroup("seafile")
|
settings.beginGroup("seafile")
|
||||||
|
self.set.save(settings)
|
||||||
try:
|
try:
|
||||||
self.copyLink = self.settingsDialog.linkCopyCheck.checked
|
self.copyLink = self.settingsDialog.linkCopyCheck.checked
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
settings.setValue("copy-link", self.copyLink)
|
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("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()
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def isConfigured(self):
|
def isConfigured(self):
|
||||||
return self.access_token and self.seaf_url and self.processor.is_configured()
|
return self.set.library and self.set.processor.is_configured()
|
||||||
|
|
||||||
def getFilename(self):
|
def getFilename(self):
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
return ScreenCloud.formatFilename(self.nameFormat)
|
return ScreenCloud.formatFilename(self.nameFormat)
|
||||||
|
|
||||||
def upload(self, screenshot, name):
|
def upload(self, screenshot, name):
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
#Make sure we have a up to date token
|
# Make sure we have a up to date token
|
||||||
if not self.seaf_lib:
|
if not self.set.library:
|
||||||
ScreenCloud.setError("Not configured properly")
|
ScreenCloud.setError("Not configured properly")
|
||||||
return False
|
return False
|
||||||
#Save to a temporary file
|
# Save to a temporary file
|
||||||
timestamp = time.time()
|
timestamp = time.time()
|
||||||
|
|
||||||
def tempfile(name):
|
def tempfile(name):
|
||||||
try:
|
try:
|
||||||
return QDesktopServices.storageLocation(QDesktopServices.TempLocation) + "/" + name
|
return QDesktopServices.storageLocation(QDesktopServices.TempLocation) + "/" + name
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
from PythonQt.QtCore import QStandardPaths #fix for Qt5
|
from PythonQt.QtCore import QStandardPaths # fix for Qt5
|
||||||
return QStandardPaths.writableLocation(QStandardPaths.TempLocation) + "/" + name
|
return QStandardPaths.writableLocation(QStandardPaths.TempLocation) + "/" + name
|
||||||
|
|
||||||
tmpFilename = tempfile(ScreenCloud.formatFilename(str(timestamp)))
|
tmpFilename = tempfile(ScreenCloud.formatFilename(str(timestamp)))
|
||||||
screenshot.save(QFile(tmpFilename), ScreenCloud.getScreenshotFormat())
|
screenshot.save(QFile(tmpFilename), ScreenCloud.getScreenshotFormat())
|
||||||
#Upload!
|
# Upload!
|
||||||
link=None
|
link = None
|
||||||
if True:
|
# if True:
|
||||||
#try:
|
try:
|
||||||
link = self.processor.upload(tmpFilename,self.getFilename())
|
link = self.set.processor.upload(tmpFilename, self.getFilename())
|
||||||
if self.copyLink:
|
if self.copyLink:
|
||||||
ScreenCloud.setUrl(link)
|
ScreenCloud.setUrl(link)
|
||||||
#except Exception as e:
|
except Exception as e:
|
||||||
# ScreenCloud.setError("Failed to upload to seafile. " + e.message)
|
ScreenCloud.setError("Failed to upload to seafile. Using: %s\n\n%s" % (
|
||||||
# return False
|
self.set.processor.name(), e.message))
|
||||||
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def startAuthenticationProcess(self):
|
def startAuthenticationProcess(self):
|
||||||
self.saveSettings()
|
self.saveSettings()
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
|
|
||||||
if self.access_token is not None:
|
if self.set.token is not None:
|
||||||
self.logOut()
|
self.logOut()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text \
|
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.usernameEdit.text \
|
||||||
and self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text:
|
and self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text:
|
||||||
self.seaf_url = self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text
|
self.set.url = self.settingsDialog.group_account.widget_loggedIn.serverUrlEdit.text
|
||||||
if True:
|
if True:
|
||||||
#try:
|
# try:
|
||||||
self.login(self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text,self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text)
|
self.login(self.settingsDialog.group_account.widget_loggedIn.usernameEdit.text,
|
||||||
|
self.settingsDialog.group_account.widget_loggedIn.passwordEdit.text)
|
||||||
self.saveSettings()
|
self.saveSettings()
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
self.populateLibrarySelector()
|
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)
|
#QMessageBox.critical(self.settingsDialog, "Failed to login", "Verify your server url and credentials" + e.message)
|
||||||
self.saveSettings()
|
self.saveSettings()
|
||||||
self.updateUi()
|
self.updateUi()
|
||||||
@ -181,31 +170,32 @@ class SeafileUploader():
|
|||||||
def locationUpdate(self):
|
def locationUpdate(self):
|
||||||
drop = self.settingsDialog.group_location.widget_location.libraryEditDrop
|
drop = self.settingsDialog.group_location.widget_location.libraryEditDrop
|
||||||
selected_lib = drop.currentText
|
selected_lib = drop.currentText
|
||||||
if not drop.isEnabled(): return #not populated
|
if not drop.isEnabled():
|
||||||
self.lib_path = self.settingsDialog.group_location.widget_location.pathEdit.text
|
return # not populated
|
||||||
print(self.lib_path, selected_lib)
|
self.set.library_path = self.settingsDialog.group_location.widget_location.pathEdit.text
|
||||||
if self.libs is None: return
|
print(self.set.library_path, selected_lib)
|
||||||
|
if self.libs is None:
|
||||||
|
return
|
||||||
for lib in self.libs:
|
for lib in self.libs:
|
||||||
if lib.name == selected_lib:
|
if lib.name == selected_lib:
|
||||||
self.seaf_lib = lib
|
self.set.library = lib
|
||||||
print("%s user selected" % selected_lib)
|
print("%s user selected" % selected_lib)
|
||||||
|
|
||||||
|
def login(self, user, password):
|
||||||
def login(self,user,password):
|
cli = SeafileClient(self.set.url, user, password)
|
||||||
cli = SeafileClient(self.seaf_url,user,password)
|
self.set.token = cli.obtain_token()
|
||||||
self.access_token = cli.obtain_token()
|
|
||||||
|
|
||||||
def logOut(self):
|
def logOut(self):
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
settings.beginGroup("uploaders")
|
settings.beginGroup("uploaders")
|
||||||
settings.beginGroup("seafile")
|
settings.beginGroup("seafile")
|
||||||
settings.remove("auth-token")
|
settings.remove("auth-token")
|
||||||
self.access_token = None
|
self.set.token = None
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
self.updateUi()
|
self.updateUi()
|
||||||
|
|
||||||
def nameFormatEdited(self, nameFormat):
|
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))
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
rm -rf modules
|
mkdir -p modules
|
||||||
mkdir modules
|
pip3 install --install-option="--prefix=$PWD" -r requirements.txt "$@"
|
||||||
pip3 install --install-option="--prefix=$PWD" -r requirements.txt
|
mv lib/python3.*/site-packages/* modules/
|
||||||
mv lib/python3.5/site-packages/* modules/
|
|
||||||
cp imports/* -r modules/
|
cp imports/* -r modules/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user