Skip to content

Commit 6bae1c2

Browse files
committed
Fix for uploading data packages from iTAK
1 parent 3ea6497 commit 6bae1c2

3 files changed

Lines changed: 64 additions & 27 deletions

File tree

opentakserver/blueprints/marti_api/data_package_marti_api.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,57 @@
2626
data_package_marti_api = Blueprint("data_package_marti_api", __name__)
2727

2828

29+
def save_data_package_file(file, filename: str = None, username: str = None, eud_uid: str = None):
30+
file_hash = request.args.get("hash")
31+
if not file_hash:
32+
sha256 = hashlib.sha256()
33+
if type(file) == bytes:
34+
sha256.update(file)
35+
file_hash = sha256.hexdigest()
36+
filename, extension = os.path.splitext(secure_filename(filename))
37+
with open(os.path.join(app.config.get("UPLOAD_FOLDER"), f"{file_hash}.zip"), "wb") as f:
38+
f.write(file)
39+
else:
40+
sha256.update(file.stream.read())
41+
file.stream.seek(0)
42+
file_hash = sha256.hexdigest()
43+
file.save(os.path.join(app.config.get("UPLOAD_FOLDER"), f"{file_hash}.zip"))
44+
filename, extension = os.path.splitext(secure_filename(file.filename))
45+
logger.debug("Got file: {} - {}".format(file.filename, file_hash))
46+
47+
file_size = os.path.getsize(os.path.join(app.config.get("UPLOAD_FOLDER"), f"{file_hash}.zip"))
48+
save_data_package_to_db(
49+
f"{filename}.zip", file_hash, "application/x-zip-compressed", file_size, username, eud_uid
50+
)
51+
52+
return file_hash
53+
54+
2955
def save_data_package_to_db(
3056
filename: str = None,
3157
sha256_hash: str = None,
3258
mimetype: str = "application/zip",
3359
file_size: int = 0,
60+
username: str = None,
61+
eud_uid: str = None,
3462
):
3563
try:
3664
data_package = DataPackage()
3765
data_package.filename = filename
3866
data_package.hash = sha256_hash
39-
data_package.creator_uid = (
40-
request.args.get("creatorUid") if request.args.get("creatorUid") else None
41-
)
67+
data_package.creator_uid = request.args.get("CreatorUid") # iTAK
68+
data_package.creator_uid = request.args.get("creatorUid") # All other TAK clients
4269
data_package.submission_user = current_user.id if current_user.is_authenticated else None
4370
data_package.submission_time = datetime.now(timezone.utc)
4471
data_package.mime_type = mimetype
4572
data_package.size = file_size
73+
data_package.creator_uid = eud_uid
74+
75+
if username:
76+
user = app.security.datastore.find_user(username=username)
77+
if user:
78+
data_package.submission_user = user.id
79+
4680
db.session.add(data_package)
4781
db.session.commit()
4882
except sqlalchemy.exc.IntegrityError as e:
@@ -169,25 +203,8 @@ def data_package_share():
169203

170204
if extension != "zip":
171205
file_hash = create_data_package_zip(file)
172-
173206
else:
174-
file_hash = request.args.get("hash")
175-
if not file_hash:
176-
sha256 = hashlib.sha256()
177-
sha256.update(file.stream.read())
178-
file.stream.seek(0)
179-
file_hash = sha256.hexdigest()
180-
logger.debug("got sha256 {}".format(file_hash))
181-
182-
logger.debug("Got file: {} - {}".format(file.filename, file_hash))
183-
184-
file.save(os.path.join(app.config.get("UPLOAD_FOLDER"), f"{file_hash}.zip"))
185-
186-
filename, extension = os.path.splitext(secure_filename(file.filename))
187-
file_size = os.path.getsize(
188-
os.path.join(app.config.get("UPLOAD_FOLDER"), f"{file_hash}.zip")
189-
)
190-
save_data_package_to_db(f"{filename}.zip", file_hash, file.content_type, file_size)
207+
file_hash = save_data_package_file(file)
191208

192209
url = urlparse(request.url_root)
193210
return (

opentakserver/blueprints/marti_api/mission_marti_api.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from sqlalchemy import insert, or_, update
2323
from werkzeug.utils import secure_filename
2424

25+
from opentakserver.blueprints.marti_api.data_package_marti_api import save_data_package_file
2526
from opentakserver.blueprints.marti_api.marti_api import verify_client_cert
2627
from opentakserver.extensions import db, logger
2728
from opentakserver.functions import datetime_from_iso8601_string, iso8601_string_from_datetime
@@ -1697,11 +1698,30 @@ def upload_content():
16971698
if not file_name:
16981699
return jsonify({"success": False, "error": gettext("File name cannot be blank")}), 400
16991700

1700-
filename, extension = os.path.splitext(secure_filename(file_name))
1701+
# When uploading data packages, iTAK doesn't include an extension. If the user agent is iTAK and
1702+
# the content type is zip, assume that iTAK is uploading a data package
1703+
if (
1704+
"iTAK" in request.user_agent.string
1705+
and request.content_type == "application/x-zip-compressed"
1706+
):
1707+
file_hash = save_data_package_file(
1708+
request.data, secure_filename(file_name) + ".zip", username, creator_uid
1709+
)
1710+
1711+
response = {
1712+
"UID": str(uuid.uuid4()),
1713+
"SubmissionDateTime": iso8601_string_from_datetime(),
1714+
"MIMEType": "application/x-zip-compressed",
1715+
"SubmissionUser": username,
1716+
"PrimaryKey": 0,
1717+
"Hash": file_hash,
1718+
"CreatorUid": creator_uid,
1719+
"Name": file_name,
1720+
}
1721+
1722+
return jsonify(response)
17011723

1702-
# In some cases iTAK doesn't include the file extension. If the user agent includes iTAK and there's no extension we'll assume it's a zip
1703-
if not extension and "iTAK" in request.user_agent.string:
1704-
extension = "zip"
1724+
filename, extension = os.path.splitext(secure_filename(file_name))
17051725

17061726
if extension.replace(".", "").lower() not in app.config.get("ALLOWED_EXTENSIONS"):
17071727
logger.error(f"{extension} is not an allowed file extension")

opentakserver/functions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,11 @@ def datetime_from_iso8601_string(datetime_string: str | None) -> datetime:
142142
return dt
143143

144144

145-
def iso8601_string_from_datetime(datetime_object):
145+
def iso8601_string_from_datetime(datetime_object: datetime | None = None) -> str:
146146
if datetime_object:
147147
return datetime_object.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-2] + "Z"
148148
else:
149-
return None
149+
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-2] + "Z"
150150

151151

152152
def iso8601_string_from_datetime_no_ms(datetime_object):

0 commit comments

Comments
 (0)