Skip to content

Commit ecfb82e

Browse files
committed
scripts: Add upload_bugtool.py
Signed-off-by: Tu Dinh <[email protected]>
1 parent ae6b8f9 commit ecfb82e

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
# Upload a bugtool archive to Nextcloud.
5+
# This script should run on both Python 2 and 3.
6+
7+
from __future__ import print_function
8+
9+
import argparse
10+
import getpass
11+
import os
12+
import subprocess
13+
import sys
14+
15+
try:
16+
from itertools import zip_longest
17+
except ImportError:
18+
from itertools import izip_longest as zip_longest
19+
20+
try:
21+
import urllib.parse as urlparse
22+
from urllib.parse import quote as urlquote
23+
except ImportError:
24+
import urlparse
25+
from urllib import quote as urlquote
26+
27+
try:
28+
from xcp.branding import PLATFORM_VERSION
29+
except ImportError:
30+
PLATFORM_VERSION = "9999" # failsafe value, assume dev build
31+
32+
33+
def version_lt(a, b):
34+
for ai, bi in zip_longest(a, b, fillvalue=0):
35+
if ai < bi:
36+
return True
37+
elif ai > bi:
38+
return False
39+
return False
40+
41+
42+
def parse_share_link(share_link):
43+
"""
44+
Parses the Nextcloud/Owncloud share link to extract the base URL and token.
45+
Args:
46+
share_link (str): The share link URL.
47+
Returns:
48+
tuple: A tuple containing (base_url, token).
49+
"""
50+
parsed_url = urlparse.urlparse(share_link)._replace(query="", fragment="")
51+
path_segments = parsed_url.path.split("/")
52+
53+
if path_segments[-3:-1] == ["index.php", "s"]:
54+
base_url = urlparse.urljoin(share_link, "../..")
55+
token = path_segments[-1]
56+
elif path_segments[-2] == "s":
57+
base_url = urlparse.urljoin(share_link, "..")
58+
token = path_segments[-1]
59+
else:
60+
raise ValueError(
61+
"Invalid share link format. Could not determine base URL from: %s"
62+
% share_link
63+
)
64+
65+
return base_url, token
66+
67+
68+
def upload(base_url, folder_token, password, file):
69+
print("Uploading %s" % file, file=sys.stderr)
70+
71+
upload_filename = urlquote(os.path.basename(file))
72+
target_url = urlparse.urljoin(base_url, "public.php/webdav/%s" % upload_filename)
73+
cred = "%s:%s" % (folder_token, password)
74+
75+
# fmt: off
76+
curl_args = [
77+
"curl",
78+
"--show-error",
79+
"--fail",
80+
"--upload-file", file,
81+
"--user", cred,
82+
"--header", "X-Requested-With: XMLHttpRequest",
83+
target_url,
84+
]
85+
# fmt: on
86+
platform_version = tuple(int(x) for x in PLATFORM_VERSION.split("."))
87+
if version_lt(platform_version, (3, 3, 0)):
88+
curl_args += [
89+
"--ciphers",
90+
"ECDHE-RSA-AES256-SHA384,ECDHE-RSA-AES256-GCM-SHA384,AES256-SHA256,AES128-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256",
91+
]
92+
93+
try:
94+
subprocess.check_call(curl_args, stdout=sys.stdout, stderr=sys.stderr)
95+
except:
96+
print("curl failed, see output above.", file=sys.stderr)
97+
sys.exit(1)
98+
99+
100+
def main():
101+
parser = argparse.ArgumentParser(
102+
description="Uploads a file to a Nextcloud/Owncloud shared drop folder."
103+
)
104+
parser.add_argument(
105+
"-p", action="store_true", help="Prompt for password for the share link."
106+
)
107+
parser.add_argument("share_link", help="The Nextcloud/Owncloud share link URL.")
108+
parser.add_argument("files", nargs="+", help="Files to upload.")
109+
110+
args = parser.parse_args()
111+
112+
if any("://" in file for file in args.files):
113+
print(
114+
"Error: Given file path looks like a URL, did you mix up the syntax?",
115+
file=sys.stderr,
116+
)
117+
sys.exit(1)
118+
119+
password = ""
120+
if args.p:
121+
if sys.stdin.isatty():
122+
password = getpass.getpass("Enter password for share link: ")
123+
else:
124+
print(
125+
"Error: Cannot prompt for password when not on a TTY.", file=sys.stderr
126+
)
127+
sys.exit(1)
128+
129+
base_url, folder_token = parse_share_link(args.share_link)
130+
131+
for file in args.files:
132+
upload(base_url, folder_token, password, file)
133+
134+
135+
if __name__ == "__main__":
136+
main()

0 commit comments

Comments
 (0)