1+ import std/ [ options, strutils, os, osproc, strformat, json ], ../ trace/ replay, ../ codetracerconf, zip/ zipfiles, nimcrypto
2+ import ../../ common/ [ config, trace_index, lang ]
3+ import ../ utilities/ language_detection
4+ import ../ trace/ [ storage_and_import, record ]
5+ import security_upload
6+
7+ proc uploadCommand * (
8+ patternArg: Option [string ],
9+ traceIdArg: Option [int ],
10+ traceFolderArg: Option [string ],
11+ interactive: bool
12+ ) =
13+ discard internalReplayOrUpload (patternArg, traceIdArg, traceFolderArg, interactive, command= StartupCommand .upload)
14+
15+
16+ proc decryptZip (encryptedFile: string , password: string , outputFile: string ) =
17+ var encData = readFile (encryptedFile).toBytes ()
18+ if encData.len < 16 :
19+ raise newException (ValueError , " Invalid encrypted data (too short)" )
20+
21+ let iv = password.toBytes ()[0 ..< 16 ]
22+ let ciphertext = encData[16 .. ^ 1 ]
23+ let key = password.toBytes ()
24+
25+ var aes: CBC [aes256]
26+ aes.init (key, iv)
27+
28+ var decrypted = newSeq [byte ](encData.len)
29+ aes.decrypt (encData, decrypted.toOpenArray (0 , len (decrypted) - 1 ))
30+
31+ var depaddedData = pkcs7Unpad (decrypted)
32+ writeFile (outputFile, depaddedData)
33+
34+ proc unzipDecryptedFile (zipFile: string , outputDir: string ): (string , int ) =
35+ var zip: ZipArchive
36+ if not zip.open (zipFile, fmRead):
37+ raise newException (IOError , " Failed to open decrypted ZIP: " & zipFile)
38+
39+ let traceId = trace_index.newID (false )
40+ let outPath = outputDir / " trace-" & $ traceId
41+
42+ createDir (outPath)
43+ zip.extractAll (outPath)
44+
45+ zip.close ()
46+ return (outPath, traceId)
47+
48+ proc downloadCommand * (traceRegistryId: string ) =
49+ # We expect a traceRegistryId to have <downloadId>::<passwordKey>
50+ let stringSplit = traceRegistryId.split (" //" )
51+ if stringSplit.len () != 3 :
52+ quit (1 )
53+ else :
54+ let downloadId = stringSplit[1 ]
55+ let password = stringSplit[2 ]
56+ let zipPath = " /tmp/tmp.zip"
57+ let config = loadConfig (folder= getCurrentDir (), inTest= false )
58+ let localPath = " /tmp" / " tmp.zip.enc"
59+ # TODO : Plug in an http client
60+ let cmd = & " curl -s -o { localPath} { config.webApiRoot} /download?DownloadId={ downloadId} "
61+ let (output, exitCode) = execCmdEx (cmd)
62+
63+ decryptZip (localPath, password, zipPath)
64+
65+ let (traceFolder, traceId) = unzipDecryptedFile (zipPath, os.getHomeDir () / " .local" / " share" / " codetracer" )
66+ let tracePath = traceFolder / " trace.json"
67+ let traceJson = parseJson (readFile (tracePath))
68+ let traceMetadataPath = traceFolder / " trace_metadata.json"
69+
70+ var pathValue = " "
71+
72+ for item in traceJson:
73+ if item.hasKey (" Path" ):
74+ pathValue = item[" Path" ].getStr (" " )
75+ break
76+
77+ let lang = detectLang (pathValue, LangUnknown )
78+ discard importDbTrace (traceMetadataPath, traceId, lang, DB_SELF_CONTAINED_DEFAULT , traceRegistryId)
79+
80+ removeFile (localPath)
81+ removeFile (zipPath)
82+
83+ echo traceId
84+
85+ quit (exitCode)
86+
87+ proc deleteAndResetFields (id: int , test: bool ) =
88+ updateField (id, " remoteShareDownloadId" , " " , test)
89+ updateField (id, " remoteShareControlId" , " " , test)
90+ updateField (id, " remoteShareExpireTime" , - 1 , test)
91+
92+ proc deleteTraceCommand * (id: int , controlId: string ) =
93+ let config = loadConfig (folder= getCurrentDir (), inTest= false )
94+ let cmd = & " curl -s { config.webApiRoot} /delete?ControlId={ controlId} "
95+ let (output, exitCode) = execCmdEx (cmd)
96+
97+ if exitCode == 0 :
98+ deleteAndResetFields (id, false )
99+
100+ quit (exitCode)
0 commit comments