time-decode 7.0.0__tar.gz → 7.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,39 @@
1
1
  Metadata-Version: 2.1
2
- Name: time_decode
3
- Version: 7.0.0
2
+ Name: time-decode
3
+ Version: 7.0.2
4
4
  Summary: Python 3 timestamp decode/encode tool
5
- Home-page: https://github.com/digitalsleuth/time_decode
6
- Author: Corey Forman
7
- License: MIT
5
+ Author-email: "Corey Forman (digitalsleuth)" <github@digitalsleuth.ca>
6
+ Maintainer-email: "Corey Forman (digitalsleuth)" <github@digitalsleuth.ca>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2023 Corey Forman
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/digitalsleuth/time_decode
30
+ Project-URL: References, https://github.com/digitalsleuth/time_decode/blob/master/REFERENCES.md
31
+ Keywords: digital forensics,dfir,timestamp,decode,encode
32
+ Classifier: Development Status :: 5 - Production/Stable
8
33
  Classifier: Programming Language :: Python :: 3
9
34
  Classifier: License :: OSI Approved :: MIT License
10
35
  Classifier: Operating System :: OS Independent
36
+ Requires-Python: >=3.6
11
37
  Description-Content-Type: text/markdown
12
38
  License-File: LICENSE
13
39
  Requires-Dist: PyQt6
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools >= 61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.setuptools.packages.find]
6
+ exclude = ["debian*", "binaries*", "build*", "dist*"]
7
+
8
+ [project]
9
+ name = "time-decode"
10
+ version = "7.0.2"
11
+ dependencies = [
12
+ "PyQt6",
13
+ "python-dateutil",
14
+ "colorama"
15
+ ]
16
+ requires-python = ">=3.6"
17
+ authors = [
18
+ {name = "Corey Forman (digitalsleuth)", email = "github@digitalsleuth.ca"}
19
+ ]
20
+ maintainers = [
21
+ {name = "Corey Forman (digitalsleuth)", email = "github@digitalsleuth.ca"}
22
+ ]
23
+ description = "Python 3 timestamp decode/encode tool"
24
+ readme = "README.md"
25
+ license = {file = "LICENSE"}
26
+ keywords = ["digital forensics", "dfir", "timestamp", "decode", "encode"]
27
+ classifiers = [
28
+ "Development Status :: 5 - Production/Stable",
29
+ "Programming Language :: Python :: 3",
30
+ "License :: OSI Approved :: MIT License",
31
+ "Operating System :: OS Independent"
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/digitalsleuth/time_decode"
36
+ References = "https://github.com/digitalsleuth/time_decode/blob/master/REFERENCES.md"
37
+
38
+ [project.scripts]
39
+ time-decode = "time_decode.time_decode:main"
@@ -49,8 +49,8 @@ from PyQt6.QtWidgets import (
49
49
  init(autoreset=True)
50
50
 
51
51
  __author__ = "Corey Forman (digitalsleuth)"
52
- __date__ = "23 Dec 2023"
53
- __version__ = "7.0.0"
52
+ __date__ = "14 Jan 2024"
53
+ __version__ = "7.0.2"
54
54
  __description__ = "Python 3 CLI Date Time Conversion Tool"
55
55
  __fmt__ = "%Y-%m-%d %H:%M:%S.%f"
56
56
  __red__ = "\033[1;31m"
@@ -272,6 +272,9 @@ class ExampleWindow(QWidget):
272
272
  QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding
273
273
  )
274
274
  self.timestampTable.setStyleSheet("border: none")
275
+ self.timestampTable.setVerticalScrollBarPolicy(
276
+ Qt.ScrollBarPolicy.ScrollBarAlwaysOn
277
+ )
275
278
  layout.addWidget(self.timestampTable)
276
279
  layout.addWidget(self.examplesLabel)
277
280
  self.setLayout(layout)
@@ -291,7 +294,7 @@ class AboutWindow(QWidget):
291
294
  layout.addWidget(self.logoLabel, 0, 2)
292
295
  self.setStyleSheet("background-color: white; color: black;")
293
296
  self.setFixedHeight(100)
294
- self.setFixedWidth(335)
297
+ self.setFixedWidth(350)
295
298
  self.setLayout(layout)
296
299
 
297
300
 
@@ -299,14 +302,14 @@ class UiDialog:
299
302
  def setupUi(self, Dialog):
300
303
  if not Dialog.objectName():
301
304
  Dialog.setObjectName(__appname__)
302
- d_width = 500
305
+ d_width = 560
303
306
  d_height = 100
304
307
  Dialog.setFixedWidth(d_width)
305
308
  Dialog.setMinimumHeight(d_height)
306
309
  Dialog.setStyleSheet(
307
310
  """
308
- QMainWindow {
309
- background-color: white; color: black;
311
+ QMainWindow {
312
+ background-color: white; color: black;
310
313
  }
311
314
  """
312
315
  )
@@ -348,15 +351,13 @@ class UiDialog:
348
351
  self.timestampFormats.view().setVerticalScrollBarPolicy(
349
352
  Qt.ScrollBarPolicy.ScrollBarAsNeeded
350
353
  )
351
- types = []
352
- for type in ts_types:
353
- types.append(ts_types[type][0])
354
- types.sort(key=str.casefold)
355
- for type in types:
356
- self.timestampFormats.addItem(type)
357
- structures = []
358
- for structure in ts_types:
359
- structures.append(f"{ts_types[structure][1]}: {ts_types[structure][2]}")
354
+ types = {}
355
+ for this_type in ts_types:
356
+ types[ts_types[this_type][0]] = ts_types[this_type][1]
357
+ types = dict(sorted(types.items(), key=lambda item: item[0].casefold()))
358
+ for k, v in enumerate(types.items()):
359
+ self.timestampFormats.addItem(v[0])
360
+ self.timestampFormats.setItemData(k, v[1], Qt.ItemDataRole.ToolTipRole)
360
361
  self.outputTable = QTableWidget(Dialog)
361
362
  self.outputTable.setSizePolicy(
362
363
  QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding
@@ -367,7 +368,7 @@ class UiDialog:
367
368
  )
368
369
  self.outputTable.setVisible(False)
369
370
  self.outputTable.setVerticalScrollBarPolicy(
370
- Qt.ScrollBarPolicy.ScrollBarAlwaysOff
371
+ Qt.ScrollBarPolicy.ScrollBarAlwaysOn
371
372
  )
372
373
  self.outputTable.setHorizontalScrollBarPolicy(
373
374
  Qt.ScrollBarPolicy.ScrollBarAlwaysOff
@@ -376,24 +377,24 @@ class UiDialog:
376
377
  self.guessButton.setObjectName("guessButton")
377
378
  self.guessButton.setEnabled(True)
378
379
  self.guessButton.setHidden(False)
379
- self.guessButton.setGeometry(QRect(405, 28, 70, 24))
380
+ self.guessButton.setGeometry(QRect(440, 28, 70, 24))
380
381
  self.guessButton.setStyleSheet("background-color: white; color: black;")
381
382
  self.guessButton.clicked.connect(self.guess_decode)
382
383
  self.toallButton = QPushButton(Dialog)
383
384
  self.toallButton.setObjectName("toallButton")
384
385
  self.toallButton.setEnabled(False)
385
386
  self.toallButton.setHidden(True)
386
- self.toallButton.setGeometry(QRect(405, 28, 70, 24))
387
+ self.toallButton.setGeometry(QRect(440, 28, 70, 24))
387
388
  self.toallButton.setStyleSheet("background-color: white; color: black;")
388
389
  self.toallButton.clicked.connect(self.encode_toall)
389
390
  self.encodeRadio = QRadioButton(Dialog)
390
391
  self.encodeRadio.setObjectName("encodeRadio")
391
- self.encodeRadio.setGeometry(QRect(320, 30, 70, 20))
392
+ self.encodeRadio.setGeometry(QRect(340, 30, 72, 20))
392
393
  self.encodeRadio.setStyleSheet("background-color: white; color: black;")
393
394
  self.encodeRadio.toggled.connect(self._encode_select)
394
395
  self.decodeRadio = QRadioButton(Dialog)
395
396
  self.decodeRadio.setObjectName("decodeRadio")
396
- self.decodeRadio.setGeometry(QRect(245, 30, 70, 20))
397
+ self.decodeRadio.setGeometry(QRect(245, 30, 72, 20))
397
398
  self.decodeRadio.setChecked(True)
398
399
  self.decodeRadio.setStyleSheet("background-color: white; color: black;")
399
400
  self.decodeRadio.toggled.connect(self._decode_select)
@@ -453,7 +454,8 @@ class UiDialog:
453
454
 
454
455
  def _reset_table(self):
455
456
  self.adjustSize()
456
- self.setFixedWidth(500)
457
+ self.setFixedWidth(560)
458
+ self.setFixedHeight(100)
457
459
  self.outputTable.setVisible(False)
458
460
  self.outputTable.clearContents()
459
461
  self.outputTable.setColumnCount(0)
@@ -479,7 +481,6 @@ class UiDialog:
479
481
 
480
482
  def display_output(self, ts_list):
481
483
  self._reset_table()
482
- self.setFixedWidth(540)
483
484
  self.outputTable.setVisible(True)
484
485
  self.outputTable.setColumnCount(2)
485
486
  self.outputTable.setAlternatingRowColors(True)
@@ -503,7 +504,7 @@ class UiDialog:
503
504
  )
504
505
  self.outputTable.horizontalHeader().setFixedHeight(1)
505
506
  self.outputTable.verticalHeader().setFixedWidth(1)
506
- self.outputTable.setFixedWidth(530)
507
+ self.outputTable.setFixedWidth(540)
507
508
  self.outputTable.setColumnWidth(0, 220)
508
509
  self.outputTable.setColumnWidth(1, 300)
509
510
  self.outputTable.resizeRowsToContents()
@@ -512,8 +513,14 @@ class UiDialog:
512
513
  self.outputTable.rowHeight(row)
513
514
  for row in range(self.outputTable.rowCount())
514
515
  )
515
- self.outputTable.setFixedHeight(total_row_height + 1)
516
- self.resize(self.width(), self.height() + int(total_row_height + 1))
516
+ self.outputTable.setFixedHeight(400)
517
+ if total_row_height > 500:
518
+ self.setFixedHeight(500)
519
+ self.outputTable.verticalScrollBar().show()
520
+ else:
521
+ self.setFixedHeight(self.height() + int(total_row_height + 1))
522
+ self.outputTable.verticalScrollBar().hide()
523
+ self.setFixedWidth(560)
517
524
 
518
525
  def go_function(self):
519
526
  results = {}
@@ -663,7 +670,7 @@ class UiDialog:
663
670
  ts_types[structure][1],
664
671
  ts_types[structure][2],
665
672
  )
666
- structures = sorted(structures.items(), key=lambda item: item[1][0].lower())
673
+ structures = sorted(structures.items(), key=lambda item: item[1][0].casefold())
667
674
  self.examplesWindow = ExampleWindow()
668
675
  self.examplesWindow.examplesLabel.setGeometry(QRect(0, 0, 200, 24))
669
676
  self.examplesWindow.examplesLabel.setText(
@@ -679,12 +686,14 @@ class UiDialog:
679
686
  self.examplesWindow.timestampTable.insertRow(row)
680
687
  widget0 = QTableWidgetItem(example[1][0])
681
688
  widget0.setFlags(widget0.flags() & ~Qt.ItemFlag.ItemIsEditable)
689
+ widget0.setToolTip(example[0])
682
690
  widget1 = QTableWidgetItem(example[1][1])
683
691
  widget1.setFlags(widget1.flags() & ~Qt.ItemFlag.ItemIsEditable)
684
692
  self.examplesWindow.timestampTable.setItem(row, 0, widget0)
685
693
  self.examplesWindow.timestampTable.item(row, 0).setTextAlignment(
686
694
  int(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
687
695
  )
696
+ self.examplesWindow.timestampTable.item(row, 0)
688
697
  self.examplesWindow.timestampTable.setItem(row, 1, widget1)
689
698
  self.examplesWindow.timestampTable.item(row, 1).setTextAlignment(
690
699
  int(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
@@ -704,8 +713,8 @@ class UiDialog:
704
713
  self.examplesWindow.timestampTable.setShowGrid(True)
705
714
  self.examplesWindow.timestampTable.setAlternatingRowColors(True)
706
715
  self.examplesWindow.setFixedSize(
707
- self.examplesWindow.timestampTable.horizontalHeader().length() + 24,
708
- self.examplesWindow.timestampTable.verticalHeader().length() + 48,
716
+ self.examplesWindow.timestampTable.horizontalHeader().length() + 48,
717
+ 400,
709
718
  )
710
719
  self.examplesWindow.show()
711
720
  else:
@@ -2062,16 +2071,19 @@ def from_systemtime(timestamp):
2062
2071
  for i in converted:
2063
2072
  dec = int(i, 16)
2064
2073
  stamp.append(dec)
2065
- dt_obj = dt(
2066
- stamp[0],
2067
- stamp[1],
2068
- stamp[3],
2069
- stamp[4],
2070
- stamp[5],
2071
- stamp[6],
2072
- stamp[7] * 1000,
2073
- )
2074
- in_systemtime = dt_obj.strftime(__fmt__)
2074
+ if (stamp[0] > 3000) or (stamp[1] > 12) or (stamp[2] > 31):
2075
+ in_systemtime = indiv_output = combined_output = False
2076
+ else:
2077
+ dt_obj = dt(
2078
+ stamp[0],
2079
+ stamp[1],
2080
+ stamp[3],
2081
+ stamp[4],
2082
+ stamp[5],
2083
+ stamp[6],
2084
+ stamp[7] * 1000,
2085
+ )
2086
+ in_systemtime = dt_obj.strftime(__fmt__)
2075
2087
  indiv_output = str(f"{ts_type}: {in_systemtime} UTC")
2076
2088
  combined_output = str(f"{__red__}{ts_type}:\t{in_systemtime} UTC{__clr__}")
2077
2089
  except Exception:
@@ -2844,7 +2856,10 @@ def from_tiktok(timestamp):
2844
2856
  in_tiktok = indiv_output = combined_output = False
2845
2857
  else:
2846
2858
  unix_ts = int(timestamp) >> 32
2847
- in_tiktok = dt.utcfromtimestamp(float(unix_ts)).strftime(__fmt__)
2859
+ if unix_ts > 32536850399:
2860
+ in_tiktok = indiv_output = combined_output = False
2861
+ else:
2862
+ in_tiktok = dt.utcfromtimestamp(float(unix_ts)).strftime(__fmt__)
2848
2863
  indiv_output = str(f"{ts_type}: {in_tiktok}")
2849
2864
  combined_output = str(f"{__red__}{ts_type}:\t\t\t{in_tiktok} UTC{__clr__}")
2850
2865
  except Exception:
@@ -2861,7 +2876,10 @@ def from_twitter(timestamp):
2861
2876
  in_twitter = indiv_output = combined_output = False
2862
2877
  else:
2863
2878
  unix_ts = (int(timestamp) >> 22) + 1288834974657
2864
- in_twitter = dt.utcfromtimestamp(float(unix_ts) / 1000.0).strftime(__fmt__)
2879
+ if unix_ts > 32536850399:
2880
+ in_twitter = indiv_output = combined_output = False
2881
+ else:
2882
+ in_twitter = dt.utcfromtimestamp(float(unix_ts) / 1000.0).strftime(__fmt__)
2865
2883
  indiv_output = str(f"{ts_type}: {in_twitter}")
2866
2884
  combined_output = str(f"{__red__}{ts_type}:\t\t\t{in_twitter} UTC{__clr__}")
2867
2885
  except Exception:
@@ -2878,7 +2896,10 @@ def from_discord(timestamp):
2878
2896
  in_discord = indiv_output = combined_output = False
2879
2897
  else:
2880
2898
  unix_ts = (int(timestamp) >> 22) + 1420070400000
2881
- in_discord = dt.utcfromtimestamp(float(unix_ts) / 1000.0).strftime(__fmt__)
2899
+ if unix_ts > 32536850399:
2900
+ in_discord = indiv_output = combined_output = False
2901
+ else:
2902
+ in_discord = dt.utcfromtimestamp(float(unix_ts) / 1000.0).strftime(__fmt__)
2882
2903
  indiv_output = str(f"{ts_type}: {in_discord}")
2883
2904
  combined_output = str(f"{__red__}{ts_type}:\t\t\t{in_discord} UTC{__clr__}")
2884
2905
  except Exception:
@@ -3107,7 +3128,10 @@ def from_dotnet(timestamp):
3107
3128
  else:
3108
3129
  dotnet_offset = int((epochs[1970] - epochs[1]).total_seconds()) * 10000000
3109
3130
  dotnet_to_umil = (int(timestamp) - dotnet_offset) / 10000000
3110
- in_dotnet = dt.utcfromtimestamp(dotnet_to_umil).strftime(__fmt__)
3131
+ if dotnet_to_umil < 0:
3132
+ in_dotnet = indiv_output = combined_output = False
3133
+ else:
3134
+ in_dotnet = dt.utcfromtimestamp(dotnet_to_umil).strftime(__fmt__)
3111
3135
  indiv_output = str(f"{ts_type}: {in_dotnet} UTC")
3112
3136
  combined_output = str(f"{__red__}{ts_type}:\t{in_dotnet} UTC{__clr__}")
3113
3137
  except Exception:
@@ -3447,7 +3471,7 @@ def from_ns40le(timestamp):
3447
3471
  """Convert a little-endian Nokia S40 7-byte value to a date/time"""
3448
3472
  ts_type, reason, _ = ts_types["ns40le"]
3449
3473
  try:
3450
- if len(str(timestamp)) != 14 or not all(
3474
+ if not len(str(timestamp)) == 14 or not all(
3451
3475
  char in hexdigits for char in timestamp
3452
3476
  ):
3453
3477
  in_ns40le = indiv_output = combined_output = False
@@ -3466,6 +3490,8 @@ def from_ns40le(timestamp):
3466
3490
  ns40_val[str(each_key)] = int(ns40_val[str(each_key)], 16)
3467
3491
  if ns40_val["yr"] > 9999:
3468
3492
  in_ns40le = indiv_output = combined_output = False
3493
+ if (int(ns40_val["mon"]) > 12) or (int(ns40_val["mon"] < 1)):
3494
+ in_ns40 = indiv_output = combined_output = False
3469
3495
  else:
3470
3496
  in_ns40le = dt(
3471
3497
  ns40_val["yr"],
@@ -1,13 +1,39 @@
1
1
  Metadata-Version: 2.1
2
- Name: time_decode
3
- Version: 7.0.0
2
+ Name: time-decode
3
+ Version: 7.0.2
4
4
  Summary: Python 3 timestamp decode/encode tool
5
- Home-page: https://github.com/digitalsleuth/time_decode
6
- Author: Corey Forman
7
- License: MIT
5
+ Author-email: "Corey Forman (digitalsleuth)" <github@digitalsleuth.ca>
6
+ Maintainer-email: "Corey Forman (digitalsleuth)" <github@digitalsleuth.ca>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2023 Corey Forman
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/digitalsleuth/time_decode
30
+ Project-URL: References, https://github.com/digitalsleuth/time_decode/blob/master/REFERENCES.md
31
+ Keywords: digital forensics,dfir,timestamp,decode,encode
32
+ Classifier: Development Status :: 5 - Production/Stable
8
33
  Classifier: Programming Language :: Python :: 3
9
34
  Classifier: License :: OSI Approved :: MIT License
10
35
  Classifier: Operating System :: OS Independent
36
+ Requires-Python: >=3.6
11
37
  Description-Content-Type: text/markdown
12
38
  License-File: LICENSE
13
39
  Requires-Dist: PyQt6
@@ -1,6 +1,6 @@
1
1
  LICENSE
2
2
  README.md
3
- setup.py
3
+ pyproject.toml
4
4
  time_decode/__init__.py
5
5
  time_decode/time_decode.py
6
6
  time_decode.egg-info/PKG-INFO
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env python3
2
- from setuptools import setup, find_packages
3
-
4
- with open("README.md", encoding='utf8') as readme:
5
- long_description = readme.read()
6
-
7
- setup(
8
- name="time_decode",
9
- version="7.0.0",
10
- author="Corey Forman",
11
- license="MIT",
12
- url="https://github.com/digitalsleuth/time_decode",
13
- description=("Python 3 timestamp decode/encode tool"),
14
- long_description=long_description,
15
- long_description_content_type="text/markdown",
16
- packages=find_packages(),
17
- classifiers=[
18
- "Programming Language :: Python :: 3",
19
- "License :: OSI Approved :: MIT License",
20
- "Operating System :: OS Independent",
21
- ],
22
- install_requires=[
23
- "PyQt6",
24
- "python-dateutil",
25
- "colorama"
26
- ],
27
- entry_points={
28
- 'console_scripts': [
29
- 'time-decode = time_decode.time_decode:main'
30
- ]
31
- },
32
- package_data={'': ['README.md, LICENSE, REFERENCES.md']}
33
- )
File without changes
File without changes
File without changes