Commit 1d84cb21 authored by Hilko Bengen's avatar Hilko Bengen

Imported Upstream version 20160323

parents
Acknowledgements: dfdatetime
Copyright 2016 The dfDateTime Project Authors.
Please see the AUTHORS file for details on individual authors.
dfDateTime, or Digital Forensics date and time, provides date and time objects
to preserve accuracy and precision.
dfDateTime, originates from the dfVFS project [https://github.com/log2timeline/dfvfs]
and the dfWinReg project [//github.com/log2timeline/dfvfs]. It was largely
rewritten and made into a stand-alone project to provide more flexibility and
allow other projects to make use of the Digital Forensics date and time objects.
dfDateTime is currently developed and maintained by:
* Daniel White
* Joachim Metz
# Names should be added to this file with this pattern:
#
# For individuals:
# Name (email address)
#
# For organizations:
# Organization (fnmatch pattern)
#
# See python fnmatch module documentation for more information.
Google Inc. (*@google.com)
Kristinn Gudjonsson (kiddi@kiddaland.net)
Joachim Metz (joachim.metz@gmail.com)
Daniel White (onager@deerpie.com)
This diff is collapsed.
include ACKNOWLEDGEMENTS AUTHORS LICENSE README
include run_tests.py
exclude .gitignore
exclude *.pyc
recursive-include config *
recursive-exclude dfdatetime *.pyc
# The example scripts are not required in a binary distribution package they
# are considered source distribution files and excluded in find_package()
# in setup.py.
recursive-include examples *.py
recursive-include test_data *
# The test scripts are not required in a binary distribution package they
# are considered source distribution files and excluded in find_package()
# in setup.py.
recursive-include tests *.py
Metadata-Version: 1.1
Name: dfdatetime
Version: 20160323
Summary: Digital Forensics Date and Time (dfDateTime).
Home-page: https://github.com/log2timeline/dfdatetime
Author: dfDateTime development team
Author-email: log2timeline-dev@googlegroups.com
License: Apache License, Version 2.0
Description: dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision.
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
dfDateTime, or Digital Forensics date and time, provides date and time objects
to preserve accuracy and precision.
For more information see:
* Project documentation: https://github.com/log2timeline/dfdatetime/wiki/Home
* How to build from source: https://github.com/log2timeline/dfdatetime/wiki/Building
dfdatetime (20160323-1) unstable; urgency=low
* Auto-generated
-- Log2Timeline <log2timeline-dev@googlegroups.com> Wed, 23 Mar 2016 22:00:46 +0100
\ No newline at end of file
Source: dfdatetime
Section: python
Priority: extra
Maintainer: log2timeline development team <log2timeline-dev@googlegroups.com>
Build-Depends: debhelper (>= 7), python-all (>= 2.7~), python-setuptools, python3-all (>= 3.4~), python3-setuptools
Standards-Version: 3.9.5
X-Python-Version: >= 2.7
X-Python3-Version: >= 3.4
Homepage: https://github.com/log2timeline/dfdatetime/
Package: python-dfdatetime
Architecture: all
Depends: ${python:Depends}, ${misc:Depends}
Description: Digital Forensics date and time (dfDateTime).
dfDateTime, or Digital Forensics date and time, provides date and time objects
to preserve accuracy and precision.
Package: python3-dfdatetime
Architecture: all
Depends: ${python3:Depends}, ${misc:Depends}
Description: Digital Forensics date and time (dfDateTime).
dfDateTime, or Digital Forensics date and time, provides date and time objects
to preserve accuracy and precision.
Format: http://dep.debian.net/deps/dep5
Upstream-Name: dfdatetime
Source: https://github.com/log2timeline/dfdatetime/
Files: *
Copyright: 2016 The dfWinReg project authors.
License: Apache-2.0
Files: debian/*
Copyright: 2016 The dfWinReg project authors.
License: Apache-2.0
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
.
On Debian systems, the complete text of the Apache version 2.0 license
can be found in "/usr/share/common-licenses/Apache-2.0".
ACKNOWLEDGEMENTS
AUTHORS
LICENSE
README
ACKNOWLEDGEMENTS
AUTHORS
LICENSE
README
#!/usr/bin/make -f
# debian/rules that uses debhelper >= 7.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# This has to be exported to make some magic below work.
export DH_OPTIONS
%:
dh $@ --buildsystem=python_distutils --with=python2,python3
.PHONY: override_dh_auto_clean
override_dh_auto_clean:
dh_auto_clean
rm -rf build dfdatetime.egg-info/SOURCES.txt dfdatetime.egg-info/PKG-INFO
.PHONY: override_dh_auto_build
override_dh_auto_build:
dh_auto_build
set -ex; for python in $(shell py3versions -r); do \
$$python setup.py build; \
done;
.PHONY: override_dh_auto_install
override_dh_auto_install:
dh_auto_install --destdir $(CURDIR)/debian/python-dfdatetime
set -ex; for python in $(shell py3versions -r); do \
$$python setup.py install --root=$(CURDIR)/debian/python3-dfdatetime --install-layout=deb; \
done;
# The shared doc files are provided via python-dfdatetime.docs and python3-dfdatetime.docs
rm -rf $(CURDIR)/debian/python-dfdatetime/usr/share/doc/dfdatetime
rm -rf $(CURDIR)/debian/python3-dfdatetime/usr/share/doc/dfdatetime
.PHONY: override_dh_auto_test
override_dh_auto_test:
.PHONY: override_dh_installmenu
override_dh_installmenu:
.PHONY: override_dh_installmime
override_dh_installmime:
.PHONY: override_dh_installmodules
override_dh_installmodules:
.PHONY: override_dh_installlogcheck
override_dh_installlogcheck:
.PHONY: override_dh_installlogrotate
override_dh_installlogrotate:
.PHONY: override_dh_installpam
override_dh_installpam:
.PHONY: override_dh_installppp
override_dh_installppp:
.PHONY: override_dh_installudev
override_dh_installudev:
.PHONY: override_dh_installwm
override_dh_installwm:
.PHONY: override_dh_installxfonts
override_dh_installxfonts:
.PHONY: override_dh_gconf
override_dh_gconf:
.PHONY: override_dh_icons
override_dh_icons:
.PHONY: override_dh_perl
override_dh_perl:
Metadata-Version: 1.1
Name: dfdatetime
Version: 20160323
Summary: Digital Forensics Date and Time (dfDateTime).
Home-page: https://github.com/log2timeline/dfdatetime
Author: dfDateTime development team
Author-email: log2timeline-dev@googlegroups.com
License: Apache License, Version 2.0
Description: dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision.
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
ACKNOWLEDGEMENTS
AUTHORS
LICENSE
MANIFEST.in
README
run_tests.py
setup.cfg
setup.py
config/dpkg/changelog
config/dpkg/compat
config/dpkg/control
config/dpkg/copyright
config/dpkg/python-dfdatetime.docs
config/dpkg/python3-dfdatetime.docs
config/dpkg/rules
config/dpkg/source/format
dfdatetime/__init__.py
dfdatetime/fake_time.py
dfdatetime/filetime.py
dfdatetime/interface.py
dfdatetime/posix_time.py
dfdatetime/time_elements.py
dfdatetime.egg-info/PKG-INFO
dfdatetime.egg-info/SOURCES.txt
dfdatetime.egg-info/dependency_links.txt
dfdatetime.egg-info/top_level.txt
tests/__init__.py
tests/fake_time.py
tests/filetime.py
tests/interface.py
tests/posix_time.py
tests/time_elements.py
\ No newline at end of file
# -*- coding: utf-8 -*-
"""Digital Forensics Date and Time (dfDateTime).
dfDateTime, or Digital Forensics date and time, provides date and time
objects to preserve accuracy and precision.
"""
__version__ = '20160323'
# -*- coding: utf-8 -*-
"""Fake timestamp implementation."""
import calendar
import time
from dfdatetime import interface
class FakeTime(interface.DateTimeValues):
"""Class that implements a fake timestamp."""
def CopyToStatTimeTuple(self):
"""Copies the timestamp to a stat timestamp tuple.
Returns:
A tuple of an integer containing a POSIX timestamp in seconds
and an integer containing the remainder in 100 nano seconds.
Currently the remainder will always be 0.
"""
time_elements = time.gmtime()
return calendar.timegm(time_elements), 0
# -*- coding: utf-8 -*-
"""FILETIME timestamp implementation."""
import calendar
from dfdatetime import interface
class Filetime(interface.DateTimeValues):
"""Class that implements a FILETIME timestamp.
The FILETIME timestamp is a 64-bit integer that contains the number
of 100th nano seconds since 1601-01-01 00:00:00.
Do not confuse this with the FILETIME structure that consists of
2 x 32-bit integers and is presumed to be unsigned.
Attributes:
timestamp: the FILETIME timestamp.
"""
# The difference between Jan 1, 1601 and Jan 1, 1970 in seconds.
_FILETIME_TO_POSIX_BASE = 11644473600
_INT64_MAX = (1 << 63) - 1
def __init__(self, timestamp=None):
"""Initializes a FILETIME object.
Args:
timestamp: optional FILETIME timestamp.
"""
super(Filetime, self).__init__()
self.timestamp = timestamp
def CopyFromString(self, time_string):
"""Copies a FILETIME from a string containing a date and time value.
Args:
time_string: a string containing a date and time value formatted as:
YYYY-MM-DD hh:mm:ss.######[+-]##:##
Where # are numeric digits ranging from 0 to 9 and the
seconds fraction can be either 3 or 6 digits. The time
of day, seconds fraction and timezone offset are optional.
The default timezone is UTC.
Returns:
An integer containing the timestamp.
Raises:
ValueError: if the time string is invalid or not supported.
"""
if not time_string:
raise ValueError(u'Invalid time string.')
time_string_length = len(time_string)
year, month, day_of_month = self._CopyDateFromString(time_string)
hours = 0
minutes = 0
seconds = 0
micro_seconds = 0
timezone_offset = 0
if time_string_length > 10:
# If a time of day is specified the time string it should at least
# contain 'YYYY-MM-DD hh:mm:ss'.
if time_string[10] != u' ':
raise ValueError(u'Invalid time string.')
hours, minutes, seconds, micro_seconds, timezone_offset = (
self._CopyTimeFromString(time_string[11:]))
self.timestamp = int(calendar.timegm((
year, month, day_of_month, hours, minutes, seconds)))
self.timestamp += timezone_offset + self._FILETIME_TO_POSIX_BASE
self.timestamp = (self.timestamp * 1000000) + micro_seconds
self.timestamp *= 10
def CopyToStatTimeTuple(self):
"""Copies the timestamp to a stat timestamp tuple.
Returns:
A tuple of an integer containing a POSIX timestamp in seconds
and an integer containing the remainder in 100 nano seconds or
None on error.
"""
if self.timestamp < 0:
return None, None
timestamp, remainder = divmod(self.timestamp, 10000000)
timestamp -= self._FILETIME_TO_POSIX_BASE
if timestamp > self._INT64_MAX:
return None, None
return timestamp, remainder
# -*- coding: utf-8 -*-
"""Date and time values interface."""
import abc
class DateTimeValues(object):
"""Class that defines the date time values interface."""
_DAYS_PER_MONTH = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
def _CopyDateFromString(self, date_string):
"""Copies a date from a string.
Args:
date_string: a string containing a date value formatted as:
YYYY-MM-DD
Returns:
A tuple of integers containing year, month, day of month.
Raises:
ValueError: if the date string is invalid or not supported.
"""
date_string_length = len(date_string)
# The date string should at least contain 'YYYY-MM-DD'.
if (date_string_length < 10 or date_string[4] != u'-' or
date_string[7] != u'-'):
raise ValueError(u'Invalid date string.')
try:
year = int(date_string[0:4], 10)
except ValueError:
raise ValueError(u'Unable to parse year.')
try:
month = int(date_string[5:7], 10)
except ValueError:
raise ValueError(u'Unable to parse month.')
try:
day_of_month = int(date_string[8:10], 10)
except ValueError:
raise ValueError(u'Unable to parse day of month.')
days_per_month = self._GetDaysPerMonth(year, month)
if day_of_month < 1 or day_of_month > days_per_month:
raise ValueError(u'Day of month value out of bounds.')
return year, month, day_of_month
def _CopyTimeFromString(self, time_string):
"""Copies a time from a string.
Args:
time_string: a string containing a time value formatted as:
hh:mm:ss.######[+-]##:##
Where # are numeric digits ranging from 0 to 9 and the
seconds fraction can be either 3 or 6 digits. The seconds
fraction and timezone offset are optional.
Returns:
A tuple of integers containing hours, minutes, seconds, microseconds,
timezone offset in seconds.
Raises:
ValueError: if the time string is invalid or not supported.
"""
time_string_length = len(time_string)
# The time string should at least contain 'hh:mm:ss'.
if (time_string_length < 8 or time_string[2] != u':' or
time_string[5] != u':'):
raise ValueError(u'Invalid time string.')
try:
hours = int(time_string[0:2], 10)
except ValueError:
raise ValueError(u'Unable to parse hours.')
if hours not in range(0, 24):
raise ValueError(u'Hours value out of bounds.')
try:
minutes = int(time_string[3:5], 10)
except ValueError:
raise ValueError(u'Unable to parse minutes.')
if minutes not in range(0, 60):
raise ValueError(u'Minutes value out of bounds.')
try:
seconds = int(time_string[6:8], 10)
except ValueError:
raise ValueError(u'Unable to parse day of seconds.')
if seconds not in range(0, 60):
raise ValueError(u'Seconds value out of bounds.')
micro_seconds = 0
timezone_offset = 0
if time_string_length > 8:
if time_string[8] != u'.':
timezone_index = 8
else:
for timezone_index in range(8, time_string_length):
if time_string[timezone_index] in (u'+', u'-'):
break
# The calculation that follow rely on the timezone index to point
# beyond the string in case no timezone offset was defined.
if timezone_index == time_string_length - 1:
timezone_index += 1
if timezone_index > 8:
fraction_of_seconds_length = timezone_index - 9
if fraction_of_seconds_length not in (3, 6):
raise ValueError(u'Invalid time string.')
try:
micro_seconds = int(time_string[9:timezone_index], 10)
except ValueError:
raise ValueError(u'Unable to parse fraction of seconds.')
if fraction_of_seconds_length == 3:
micro_seconds *= 1000
if timezone_index < time_string_length:
if (time_string_length - timezone_index != 6 or
time_string[timezone_index + 3] != u':'):
raise ValueError(u'Invalid time string.')
try:
timezone_offset = int(
time_string[timezone_index + 1:timezone_index + 3])
except ValueError:
raise ValueError(u'Unable to parse timezone hours offset.')
if timezone_offset not in range(0, 24):
raise ValueError(u'Timezone hours offset value out of bounds.')
timezone_offset *= 60
try:
timezone_offset += int(
time_string[timezone_index + 4:timezone_index + 6])
except ValueError:
raise ValueError(u'Unable to parse timezone minutes offset.')
# Note that when the sign of the timezone offset is negative
# the difference needs to be added. We do so by flipping the sign.
if time_string[timezone_index] == u'-':
timezone_offset *= 60
else:
timezone_offset *= -60
return hours, minutes, seconds, micro_seconds, timezone_offset
def _GetDaysPerMonth(self, year, month):
"""Retrieves the number of days in a month of a specific year.
Args:
year: an integer containing the year.
month: an integer containing the month ranging from 1 to 12.
Returns:
An integer containing the number of days in the month.
Raises:
ValueError: if the month value is out of bounds.
"""
if month not in range(1, 13):
raise ValueError(u'Month value out of bounds.')
days_per_month = self._DAYS_PER_MONTH[month - 1]
if month == 2 and self._IsLeapYear(year):
days_per_month += 1
return days_per_month
def _IsLeapYear(self, year):
"""Determines if a year is a leap year.
Args:
year: an integer containing the year.
Returns:
A boolean value indicating if the year is a leap year.
"""
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
@abc.abstractmethod
def CopyToStatTimeTuple(self):
"""Copies the timestamp to a stat timestamp tuple.
Returns:
A tuple of an integer containing a POSIX timestamp in seconds
and an integer containing the remainder in 100 nano seconds or
None on error.
"""
# -*- coding: utf-8 -*-
"""POSIX timestamp implementation."""
from dfdatetime import interface
class PosixTime(interface.DateTimeValues):
"""Class that implements a POSIX timestamp.
The POSIX timestamp is a signed integer that contains the number of
seconds since 1970-01-01 00:00:00 (also known as the POSIX epoch).
Negative values represent date and times predating the POSIX epoch.
The POSIX timestamp was initially 32-bit though 64-bit variants
are known to be used.
Attributes:
timestamp: the POSIX timestamp.
micro_seconds: the number of micro seconds
"""
def __init__(self, timestamp, micro_seconds=0):
"""Initializes the POSIX timestamp object.
Args:
timestamp: the FILETIME timestamp.
micro_seconds: optional number of micro seconds.
"""
super(PosixTime, self).__init__()
self.micro_seconds = micro_seconds
self.timestamp = timestamp
def CopyToStatTimeTuple(self):
"""Copies the timestamp to a stat timestamp tuple.
Returns:
A tuple of an integer containing a POSIX timestamp in seconds
and an integer containing the remainder in 100 nano seconds or
None on error.
"""
return self.timestamp, self.micro_seconds * 10
# -*- coding: utf-8 -*-
"""Time elements implementation."""
import calendar
from dfdatetime import interface
class TimeElements(interface.DateTimeValues):
"""Class that implements time elements."""
def __init__(self, time_elements_tuple):
"""Initializes a time elements object.
Args:
time_elements_tuple: a named tuple containg the time elements.
"""
super(TimeElements, self).__init__()
self._time_elements_tuple = time_elements_tuple
def CopyToStatTimeTuple(self):
"""Copies the timestamp to a stat timestamp tuple.
Returns:
A tuple of an integer containing a POSIX timestamp in seconds
and an integer containing the remainder in 100 nano seconds or
Currently the remainder will always be 0.
"""
return calendar.timegm(self._time_elements_tuple), 0
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""Script to run the tests."""
import sys
import unittest
# Change PYTHONPATH to include dfDateTime.
sys.path.insert(0, u'.')
if __name__ == '__main__':
test_suite = unittest.TestLoader().discover('tests', pattern='*.py')
test_results = unittest.TextTestRunner(verbosity=2).run(test_suite)
if not test_results.wasSuccessful():
sys.exit(1)
[bdist_rpm]
release = 1
packager = log2timeline development team <log2timeline-dev@googlegroups.com>
doc_files = ACKNOWLEDGEMENTS
AUTHORS
LICENSE
README
build_requires = python-setuptools
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""Installation and deployment script."""
from __future__ import print_function
import os
import sys
import run_tests
try:
from setuptools import find_packages, setup, Command
except ImportError:
from distutils.core import find_packages, setup, Command
try:
from setuptools.commands.bdist_rpm import bdist_rpm
except ImportError:
from distutils.command.bdist_rpm import bdist_rpm
if sys.version < '2.7':
print('Unsupported Python version: {0:s}.'.format(sys.version))
print('Supported Python versions are 2.7 or a later 2.x version.')
sys.exit(1)
# Change PYTHONPATH to include dfdatetime so that we can get the version.
sys.path.insert(0, '.')
import dfdatetime
class BdistRPMCommand(bdist_rpm):
"""Custom handler for the bdist_rpm command."""
def _make_spec_file(self):