[Forensics-changes] [vinetto] 01/05: Imported Upstream version 0.6.0~alpha
Joao Eriberto Mota Filho
eriberto at moszumanska.debian.org
Thu Dec 11 17:18:17 UTC 2014
This is an automated email from the git hooks/post-receive script.
eriberto pushed a commit to branch debian
in repository vinetto.
commit b05adbac23e48516df5bd35d03a85ca5fce1f4c5
Author: Joao Eriberto Mota Filho <eriberto at debian.org>
Date: Thu Dec 11 15:11:45 2014 -0200
Imported Upstream version 0.6.0~alpha
---
COPYING | 280 +++++++++++++++++++++++++++++++++++++
INSTALL | 35 +++++
README | 108 +++++++++++++++
res/HtRepTemplate.html | 88 ++++++++++++
res/header | Bin 0 -> 158 bytes
res/huffman | Bin 0 -> 216 bytes
res/quantization | Bin 0 -> 69 bytes
setup.py | 15 ++
vinetto | 365 +++++++++++++++++++++++++++++++++++++++++++++++++
vinreport.py | 225 ++++++++++++++++++++++++++++++
vinutils.py | 161 ++++++++++++++++++++++
11 files changed, 1277 insertions(+)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5a965fb
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..3075595
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,35 @@
+ Vinetto
+
+ http://vinetto.sourceforge.net
+
+ Michel Roukine <rukin at users.sf.net>
+
+
+
+
+
+Prerequisites
+-------------
+
+a) Python-2.3 or later.
+
+b) PIL (Python Imaging Library) 1.1.5 or later.
+
+ To download PIL, go to :
+ http://www.pythonware.com/products/pil/
+
+
+Installation
+------------
+
+This is a standard Python Distutils distribution. To install vinetto, run the
+following commands as a super user:
+
+1) tar xvzf vinetto-XXX.tar.gz
+
+2) cd vinetto-XXX
+
+3) python setup.py install
+
+This will install vinetto in appropriated path and resource files in /usr/share/vinetto.
+
diff --git a/README b/README
new file mode 100644
index 0000000..b206003
--- /dev/null
+++ b/README
@@ -0,0 +1,108 @@
+ Vinetto
+
+ http://vinetto.sourceforge.net
+
+ Michel Roukine <rukin at users.sf.net>
+
+
+
+Version alpha 0.06 (7 may 2006)
+------------------
+
+Introduction
+------------
+
+Vinetto is a forensics tool to examine Thumbs.db files.
+It is a command line python script that works on Linux, Mac OS X and
+Cygwin(win32).
+
+
+License
+-------
+
+This program is distributed under the GNU General Public License - see the
+accompanying COPYING file for more details.
+
+
+Thanks
+------
+Many thanks to Christophe Monniez (d-fence.be) for the idea of this tool and
+for his encouragements.
+
+The vinetto code was written with grateful thanks to Martin Schwartz, author of
+Laola and its Hacking guide to the binary structure of Ole / Compound Documents.
+
+
+Project overview
+----------------
+1 - Context : The Windows systems (98, ME, 2000 and XP) can store thumbnails
+and metadata of the picture files contained in the directories of its FAT32 or
+NTFS filesystems.
+Thumbnails and associated metadata are stored in Thumbs.db files.
+Thumbs.db files are undocumented OLE structured files.
+
+Once a picture file has been deleted from the filesystem, the related thumbnail
+and associated metada remain stored in the Thumbs.db file. So, the data
+contained in those thumbs.db files are an helpful source of information for the
+forensics investigator.
+
+2 - What the software is intended to do : Vinetto extracts thumbnails and
+associated metadata from the Thumbs.db files.
+
+Moreover [when vinetto will be 0.98 beta] it will function according to three
+modes:
+ -> elementary mode : in this mode vinetto will only extract thumbnails and
+ metadata from chosen Thumbs.db file.
+ -> directory mode : in this mode vinetto will check for consistency between
+ directory content and related Thumbs.db file i.e. it will report
+ thumbnails that have a missing associated file into the directory.
+ -> filesystem mode : in this mode vinetto will process whole FAT or NTFS
+ partition.
+
+3 - What purpose it will serve : Vinetto will help *nix-based forensics
+investigators to :
+ -> easily preview thumbnails of deleted pictures on Windows systems,
+ -> obtain informations (dates, path, ...) about those deleted images.
+
+4 - Misc. : Vinetto is intended to be integrated into forensics liveCD like
+FCCU GNU/Linux Forensic Boot CD.
+
+
+Requirements
+------------
+
+Python-2.3 or later.
+
+PIL (Python Imaging Library) 1.1.5 or later. PIL is used to attempt correct
+reconstitution the Type 1 thumbnails.
+
+
+Current known limitations
+-------------------------
+
+AFAIK Windows(R)(TM) uses two format types to store thumbnails in its Thumbs.db
+files.
+I called these formats Type 1 and Type 2.
+Type 2 is compliant to jpeg format. But Type 1 seems to be a family of
+jpeg-alike formats with special headers, huffman and quantization tables.
+
+*** Currently, vinetto does not manage to reconstitute correctly some Type 1
+thumbnails. ***
+
+
+Usage
+-----
+
+Usage: vinetto [OPTIONS] [-o DIR] file
+
+options:
+ --version show program's version number and exit
+ -h, --help show this help message and exit
+ -o DIR write thumbnails to DIR
+ -H write html report to DIR
+
+ Metadata list will be written on standard output.
+
+--------------
+7 may 2006
+Michel Roukine
diff --git a/res/HtRepTemplate.html b/res/HtRepTemplate.html
new file mode 100644
index 0000000..046984d
--- /dev/null
+++ b/res/HtRepTemplate.html
@@ -0,0 +1,88 @@
+<HTML>
+<HEAD>
+<TITLE>Vinetto -H report</TITLE>
+</HEAD>
+<BODY>
+<CENTER><H2>Vinetto -- thumbnails extraction report</H2></CENTER>
+<DIV ALIGN="CENTER">
+<TABLE WIDTH=720 CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD> </TD></TR>
+<TR><TD><P><B>__DATEREPORT__<BR> </B></P></TD></TR>
+<TR><TD> </TD></TR></TABLE>
+
+<HR ALIGN="CENTER" WIDTH="80%">
+
+<TABLE WIDTH=720 CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD> </TD></TR>
+<TR><TD><P><B>File metadata:<BR> </B></P></TD></TR>
+<TR><TD>
+ <TABLE CELLSPACING=1 CELLPADDING=2 BORDER=1>
+ <TR><TD><B>Directory: </B></TD><TD><TT><B>__TDBDIRNAME__</B></TT></TD></TR>
+ <TR><TD><B>Filename: </B></TD><TD><TT><B>__TDBFNAME__ </B></TT></TD></TR>
+ <TR><TD><B>Modification: </B></TD><TD><TT><B>__TDBMTIME__ </B></TT></TD></TR>
+ <TR><TD><B>File size: </B></TD><TD><TT><B>__FILESIZE__ </B></TT></TD></TR>
+ <TR><TD><B>MD5 digest:</B></TD><TD><TT><B>__MD5__ </B></TT></TD></TR>
+ </TABLE>
+</TD></TR></TABLE>
+
+<HR ALIGN="CENTER" WIDTH="80%">
+
+<TABLE WIDTH=720 CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD> </TD></TR>
+<TR><TD><P><B>__ROOTENTRYTST__</B></P></TD></TR>
+<TR><TD> </TD></TR></TABLE>
+
+<HR ALIGN="CENTER" WIDTH="80%">
+<!-- __ITS__ internal template separator 1 -->
+<TABLE WIDTH=720 CELLSPACING=0 CELLPADDING=0 BORDER=0>
+<TR>
+ <TD WIDTH=120 ALIGN="CENTER">__ROWNUMBER__ </TD>
+
+ <TD WIDTH=120 ALIGN="CENTER">
+ <TABLE BORDER="__TNfilled__0" CELLPADDING="0"><TR><TD>__IMGTAG__0</TD></TR></TABLE>
+ </TD>
+
+ <TD WIDTH=120 ALIGN="CENTER">
+ <TABLE BORDER="__TNfilled__1" CELLPADDING="0"><TR><TD>__IMGTAG__1</TD></TR></TABLE>
+ </TD>
+
+ <TD WIDTH=120 ALIGN="CENTER">
+ <TABLE BORDER="__TNfilled__2" CELLPADDING="0"><TR><TD>__IMGTAG__2</TD></TR></TABLE>
+ </TD>
+
+ <TD WIDTH=120 ALIGN="CENTER">
+ <TABLE BORDER="__TNfilled__3" CELLPADDING="0"><TR><TD>__IMGTAG__3</TD></TR></TABLE>
+ </TD>
+
+ <TD WIDTH=120 ALIGN="CENTER">
+ <TABLE BORDER="__TNfilled__4" CELLPADDING="0"><TR><TD>__IMGTAG__4</TD></TR></TABLE>
+ </TD>
+
+</TR>
+
+<TR>
+<TD WIDTH=120 ALIGN="CENTER"> </TD>
+ <TD WIDTH=120 ALIGN="CENTER"> __TNID__0 </TD>
+ <TD WIDTH=120 ALIGN="CENTER"> __TNID__1 </TD>
+ <TD WIDTH=120 ALIGN="CENTER"> __TNID__2 </TD>
+ <TD WIDTH=120 ALIGN="CENTER"> __TNID__3 </TD>
+ <TD WIDTH=120 ALIGN="CENTER"> __TNID__4 </TD>
+</TR>
+</TABLE>
+
+<!-- __ITS__ internal template separator 2 -->
+
+<HR ALIGN="CENTER" WIDTH="80%">
+
+<TABLE WIDTH=720 CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD> </TD></TR>
+<TR><TD><P><B>Orphan Catalog entries:<BR> </B></P></TD></TR>
+
+<TR><TD>__ORPHANENTRY__</TD></TR>
+</TABLE>
+
+<!-- __ITS__ internal template separator 3 -->
+<HR ALIGN="CENTER" WIDTH="80%">
+<TABLE WIDTH=720 CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD> </TD></TR>
+<TR><TD><P><B>__TYPEXTRACT__</B></P></TD></TR>
+<TR><TD> </TD></TR></TABLE>
+</DIV>
+<EM>__VVERSION__</EM>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/res/header b/res/header
new file mode 100644
index 0000000..dfb7b59
Binary files /dev/null and b/res/header differ
diff --git a/res/huffman b/res/huffman
new file mode 100644
index 0000000..277adef
Binary files /dev/null and b/res/huffman differ
diff --git a/res/quantization b/res/quantization
new file mode 100644
index 0000000..eab9220
Binary files /dev/null and b/res/quantization differ
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..4f4c7fb
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,15 @@
+from distutils.core import setup
+setup (name='vinetto',
+ version='0.06alpha',
+ scripts=['vinetto'],
+ py_modules=['vinutils', 'vinreport'],
+ data_files=[('/usr/share/vinetto', ['res/header', 'res/huffman', \
+ 'res/quantization', \
+ 'res/HtRepTemplate.html'])],
+ description='vinetto : a forensics tool to examine Thumbs.db files.',
+ author='Michel Roukine',
+ author_email='rukin at users.sf.net',
+ url='http://vinetto.sourceforge.net/',
+ license='GNU GPL',
+ platforms='LINUX',
+)
diff --git a/vinetto b/vinetto
new file mode 100755
index 0000000..ca2c859
--- /dev/null
+++ b/vinetto
@@ -0,0 +1,365 @@
+#!/usr/local/bin/python
+# -*- coding: UTF-8 -*-
+"""
+-----------------------------------------------------------------------------
+
+ Vinetto : a forensics tool to examine Thumbs.db files
+ Copyright (C) 2005, 2006 by Michel Roukine
+
+This file is part of Vinetto.
+
+ Vinetto is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
+
+ Vinetto is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with the vinetto package; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-----------------------------------------------------------------------------
+"""
+
+__revision__ = "$Revision: 56 $"
+__version__ = "0.06"
+__author__ = 'Michel Roukine'
+
+import sys
+import os
+import StringIO
+import md5
+import vinreport
+
+from optparse import OptionParser
+from struct import unpack
+from binascii import unhexlify
+from time import ctime
+from vinutils import addCatEntry, nbCatEnt, nbTNstr, TNfname, catIndxOutOfSeq, \
+ tnStreamOutOfSeq, addTNStream, extractStats
+
+PPS_TYPES = ["undefined", "storage", "stream", "undefined", "undefined", "root"]
+EOI = unhexlify('ffd9')
+HEADER1 = unhexlify('0c00')
+PIL = ""
+
+
+def getargs():
+ """Return arguments passed to vinetto on the command line. """
+ verstr = "%prog " + __version__ + " (r" + __revision__[11:-2] +")\n\n" +\
+ "Copyright (C) 2005-2006 Michel Roukine.\n" + \
+ "Vinetto is open source software," + \
+ " see http://vinetto.sourceforge.net/"
+ parser = OptionParser(usage="%prog [OPTIONS] [-o DIR] file", version=verstr)
+ parser.add_option("-o", dest="outputdir",
+ help="write thumbnails to DIR", metavar="DIR")
+ parser.set_defaults(htmlrep=False)
+ parser.add_option("-H", action="store_true", dest="htmlrep",
+ help="write html report to DIR")
+ opts, pargs = parser.parse_args()
+
+ if len(pargs) != 1:
+ parser.error("incorrect number of arguments")
+
+ if (opts.outputdir == None) and (opts.htmlrep == True):
+ parser.error("-H option requires -o with a directory name")
+
+ return (pargs[0], opts.outputdir, opts.htmlrep)
+
+
+def conv2pytime (win32filetime):
+ """Convert win32 timestamp to python time. """
+ SECS_BETWEEN_EPOCHS = 11644473600
+ SECS_TO_100NS = 10000000
+
+ if win32filetime == 0:
+ return 0
+ else:
+ return (win32filetime / SECS_TO_100NS) - SECS_BETWEEN_EPOCHS
+
+
+def nextBlock (TDB, Table, indx):
+ """Return next block. """
+ iFAT = indx / 128 # FAT block number to search in
+ iSECT = indx % 128 # SECTor to search in the FAT block
+ offst = Table [iFAT] * 512 + 0x200 + iSECT*4
+ return unpack("<l", TDB[offst:offst+4])[0]
+
+# Beginning ...
+tDBfname, outputdir, htmlrep = getargs()
+
+# Testing file and DIR parameters
+if not os.access(tDBfname, os.F_OK):
+ print >> sys.stderr, "Error: ", tDBfname, "does not exist"
+ sys.exit(1)
+elif not os.path.isfile(tDBfname):
+ print >> sys.stderr, "Error: ", tDBfname, "not a file"
+ sys.exit(1)
+elif not os.access(tDBfname, os.R_OK):
+ print >> sys.stderr, "Error: ", tDBfname, "not readable"
+ sys.exit(1)
+
+# Opening Thumbs.db file
+thumbsDB = open(tDBfname,"rb").read()
+longueur = len(thumbsDB)
+if (longueur % 512 ) != 0:
+ print >> sys.stderr, " ** Warning: length " + tDBfname + " : " \
+ + str(longueur) + ", non multiple 512"
+
+# Initializing extraction and optional html report
+if outputdir != None :
+ if not os.path.exists(outputdir):
+ try :
+ os.mkdir(outputdir)
+ print 'Note: ', outputdir, ' was created'
+ except EnvironmentError, e:
+ print >> sys.stderr, "Error creating", outputdir
+ sys.exit(1)
+ elif not os.path.isdir(outputdir):
+ print >> sys.stderr, 'Error: ', outputdir, ' is not a directory'
+ sys.exit(1)
+ elif not os.access(outputdir, os.W_OK):
+ print >> sys.stderr, 'Error: ', outputdir, ' not writable'
+ sys.exit(1)
+ outputdir += "/"
+
+ try:
+ import Image
+ PIL = "imported"
+ except ImportError, e:
+ print >> sys.stderr, ""
+ print >> sys.stderr, " ** Warning: Cannot find \"Image\" module."
+ print >> sys.stderr, " Vinetto will only extract Type 2 thumbnails."
+ print >> sys.stderr, ""
+
+ header = open("/usr/share/vinetto/header","rb").read()
+ quantization = open("/usr/share/vinetto/quantization","rb").read()
+ huffman = open("/usr/share/vinetto/huffman","rb").read()
+
+ if htmlrep == True:
+ report = vinreport.HtRep(tDBfname, outputdir, __version__ + " (r" + \
+ __revision__[11:-2] +")")
+ md5tDB = md5.new(thumbsDB).hexdigest()
+ report.SetFileSection(longueur, md5tDB)
+
+# -----------------------------------------------------------------------------
+# Analyzing header block ...
+
+if "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1" != thumbsDB[0:8] :
+ print >> sys.stderr, " *** Error " + tDBfname + ": header signature error "
+ sys.exit(8)
+
+nbFATblocks = unpack("<l", thumbsDB[0x2c:0x2c+4])[0]
+
+REfirstBlock = unpack("<l", thumbsDB[0x30:0x30+4])[0] #Root directory 1st block
+
+firstMiniFATblock = unpack("<l", thumbsDB[0x3c:0x3c+4])[0]
+
+FATblocks = []
+for i in range(nbFATblocks):
+ offset = 0x4c + i*4
+ FATblocks.append(unpack("<l", thumbsDB[offset:offset + 4])[0])
+
+# -----------------------------------------------------------------------------
+# Analyzing Root Entry directory ...
+
+currentBlock = REfirstBlock
+
+i = firstMiniFATblock
+MiniFATblocks = []
+while i != -2:
+ MiniFATblocks.append(i)
+ i = nextBlock (thumbsDB, FATblocks, i)
+
+offset = 0x200 + currentBlock * 0x200
+firstMiniFATstreamBlock = unpack("<l", thumbsDB[offset+0x74:offset+0x78])[0]
+
+i = firstMiniFATstreamBlock
+MiniFATstreamBlocks = []
+while i != -2:
+ MiniFATstreamBlocks.append(i)
+ i = nextBlock (thumbsDB, FATblocks, i)
+
+SID = 0
+
+while currentBlock != -2:
+ offset = 0x200 + currentBlock * 0x200
+ for i in range (offset, offset+0x200, 0x80):
+ pps_rawname = unpack("64s", thumbsDB[i :i+0x40])[0]
+ pps_sizeofname = unpack("<h", thumbsDB[i+0x40:i+0x42])[0]
+ pps_type = unpack("b", thumbsDB[i+0x42:i+0x43])[0]
+ pps_ts1 = unpack("<Q", thumbsDB[i+0x64:i+0x6c])[0]
+ pps_ts2 = unpack("<Q", thumbsDB[i+0x6c:i+0x74])[0]
+ pps_sb = unpack("<l", thumbsDB[i+0x74:i+0x78])[0]
+ pps_size = unpack("<l", thumbsDB[i+0x78:i+0x7c])[0]
+
+ if pps_type == 2: # stream files extraction
+ rawname = unicode(pps_rawname,"utf-16-le")[0:(pps_sizeofname/2 - 1)]
+ #SIDstr = "%04i" % SID
+ SIDstr = rawname [::-1]
+ if len(SIDstr) < 4:
+ SIDstr = "%04i" % int(SIDstr)
+ bytesToWrite = pps_size
+
+ if pps_size >= 4096 : # stream located in the FAT
+ sr = ""
+ currentStreamBlock = pps_sb
+ while currentStreamBlock != -2:
+ sOffset = 0x200 + currentStreamBlock * 0x200
+ if bytesToWrite >= 512:
+ sr = sr + thumbsDB[sOffset:sOffset + 512]
+ else:
+ sr = sr + thumbsDB[sOffset:sOffset + bytesToWrite]
+ bytesToWrite = bytesToWrite - 512
+ currentStreamBlock = nextBlock (thumbsDB, FATblocks,
+ currentStreamBlock)
+
+ else: # stream located in the MiniFAT
+ sr = ""
+ currentStreamMiniBlock = pps_sb
+ while currentStreamMiniBlock != -2 :
+ # computing offset of the miniBlock to copy
+ # 1 : which block of the miniFATstream ?
+ nb = currentStreamMiniBlock / 8
+ # 2 : where is this block ?
+ bl = MiniFATstreamBlocks[nb]
+ # 3 : which offset from the start of block ?
+ ioffset = (currentStreamMiniBlock % 8) * 64
+
+ sOffset = 0x200 + bl*0x200 + ioffset
+
+ if bytesToWrite >= 64:
+ sr = sr + thumbsDB[sOffset:sOffset + 64 ]
+ else:
+ sr = sr + thumbsDB[sOffset:sOffset + bytesToWrite]
+ bytesToWrite = bytesToWrite - 64
+ # computing next currentStreamMiniBlock
+ currentStreamMiniBlock = nextBlock (thumbsDB,
+ MiniFATblocks,
+ currentStreamMiniBlock)
+
+ # extraction stream processing ... ---------------------------------
+
+ longueur = len(sr)
+
+ # is this a Catalog ?
+ if rawname == "Catalog" :
+ # -------------------------------------------------------------
+ # Skipping catalog header block ...
+
+ recordLen = unpack("<h", sr[0:2])[0]
+ indcat = recordLen
+ SID = SID - 1
+
+ # -------------------------------------------------------------
+ # Analyzing Catalog entries ...
+
+ while indcat < longueur :
+ recordLen = unpack("<h", sr[indcat :indcat+2])[0]
+ num = unpack("<l", sr[indcat+4 :indcat+8])[0]
+ timestamp = unpack("<Q", sr[indcat+8 :indcat+16])[0]
+ nameLen = recordLen - 0x14
+
+ originame = sr[indcat+16 :indcat+16+nameLen]
+ TNid = "%04i" % num
+ TNtimestamp = ctime(conv2pytime(timestamp))
+ TNname = unicode(originame,
+ 'utf-16-le').encode('iso-8859-1', 'replace')
+ print " " + TNid, " ", TNtimestamp, " ", TNname
+ addCatEntry(num, TNtimestamp, TNname)
+ indcat = indcat + recordLen
+
+ else :
+
+ # is EOI = 0xffd9 ?
+ if sr[longueur-2:longueur] != EOI:
+ print >> sys.stderr, " *** Err: missing EOI in stream", SID
+ sys.exit(2)
+ # --------------------------- header 1 ------------------------
+ # is first header OK ?
+ if sr[0:2] != HEADER1:
+ print >> sys.stderr, \
+ " *** Err: unrecognized header in stream", SID
+ sys.exit(3)
+
+ # is length OK ?
+ if unpack("<H", sr[8:10])[0] != (longueur - 0x0c) :
+ print >> sys.stderr, " *** Err: length error in stream", SID
+ sys.exit(4)
+ # --------------------------- header 2 ------------------------
+ # is it a type 2 thumbnail ? (full jpeg)
+ if sr[0x0c:0x10] == "\xff\xd8\xff\xe0" :
+ if outputdir != None :
+ open(outputdir + TNfname(SIDstr, "2") + ".jpg", \
+ "wb").write(sr[0x0c:])
+ elif unpack("<L",sr[0x0c:0x10])[0] == 1 :
+ # is second header OK ?
+ if unpack("<H", sr[0x0c+4:0x0c+6])[0] != (longueur -
+ 0x0c - 0x10):
+ print >> sys.stderr, \
+ " *** Err : length(2) error in stream", SID
+ sys.exit(5)
+ # Type 1 TN processing ...
+ if (PIL == "imported") and (outputdir != None):
+ type1sr = header[:0x14]
+ type1sr = type1sr + quantization
+ type1sr = type1sr + sr[0x1e:0x34]
+ type1sr = type1sr + huffman
+ type1sr = type1sr + sr[0x34:]
+
+ im = Image.open(StringIO.StringIO(type1sr))
+ r, g, b, a = im.split()
+ im = Image.merge("RGB", (b, g, r))
+ im = im.transpose(Image.FLIP_TOP_BOTTOM)
+ im.save(outputdir + TNfname(SIDstr, "1") + ".jpg", \
+ "JPEG", quality=100)
+ elif outputdir != None: # Cannot extract : PIL not imported
+ addTNStream(int(SIDstr), "1", "")
+ else :
+ print >> sys.stderr, \
+ " *** Err : header (2) error in stream", SID
+ sys.exit(6)
+
+ # -----------------------------------------------------------------
+
+ elif pps_type == 5: # Root Entry
+ REtimestamp = pps_ts2
+ print
+ print " Root Entry modify timestamp :", \
+ ctime(conv2pytime(REtimestamp))
+ if htmlrep == True:
+ report.SetREtst (ctime(conv2pytime(REtimestamp)))
+ print
+ print " ------------------------------------------------------"
+ print
+
+ SID = SID + 1
+
+ currentBlock = nextBlock(thumbsDB, FATblocks, currentBlock)
+
+print
+print " ------------------------------------------------------"
+print
+
+if catIndxOutOfSeq() == True:
+ print >> sys.stderr, " * Info: ", tDBfname, "Catalog",\
+ " index number out of usual sequence"
+
+if tnStreamOutOfSeq() == True:
+ print >> sys.stderr, " * Info: ", tDBfname, \
+ "thumbnail stream index number out of usual sequence"
+
+if (outputdir != None) and (nbCatEnt() != nbTNstr()):
+ print >> sys.stderr, " ** Warning: ", tDBfname, " -- number of extracted ", \
+ "thumbnails does not match number of Catalog entries"
+
+statstring = extractStats(outputdir)
+print statstring
+
+if htmlrep == True:
+ report.flush(statstring)
+
\ No newline at end of file
diff --git a/vinreport.py b/vinreport.py
new file mode 100644
index 0000000..70fd7e0
--- /dev/null
+++ b/vinreport.py
@@ -0,0 +1,225 @@
+# -*- coding: UTF-8 -*-
+"""
+module vinreport.py
+-----------------------------------------------------------------------------
+
+ Vinetto : a forensics tool to examine Thumbs.db files
+ Copyright (C) 2005, 2006 by Michel Roukine
+
+This file is part of Vinetto.
+
+ Vinetto is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
+
+ Vinetto is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with the vinetto package; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-----------------------------------------------------------------------------
+"""
+
+__revision__ = "$Revision: 47 $"
+__version__ = "0.02"
+__author__ = 'Michel Roukine'
+
+HtHeader = []
+HtPicRow = []
+HtOrphans = []
+HtFooter = []
+IMGTAG = "<IMG SRC=\"./__TNFNAME__.jpg\" ALT=\"__TNNAME__\">"
+
+from time import time, ctime
+from os.path import dirname, basename, abspath, getmtime
+from vinutils import getCatEntry
+
+
+class Report:
+ """ Vinetto report SuperClass. """
+ def __init__ (self, target, outputdir, verstr):
+ """ Initialize a new Report instance. """
+ self.tDBfname = basename(target)
+ self.tDBdirname = abspath(dirname(target))
+ self.tDBmtime = getmtime(target)
+ self.outputdir = outputdir
+ self.verstr = verstr
+
+
+class HtRep(Report):
+ """ Html vinetto elementary mode report Class. """
+ def __init__ (self, tDBfname, outputdir, verstr):
+ """ Initialize a new HtRep instance. """
+ Report.__init__(self, tDBfname, outputdir, verstr)
+ self.rownumber = 0
+ separatorID = 0
+
+ for ligne in open("/usr/share/vinetto/HtRepTemplate.html",
+ "r").readlines():
+ if ligne.find("__ITS__") >= 0:
+ separatorID += 1
+ continue
+
+ if separatorID == 0:
+ HtHeader.append(ligne)
+ elif separatorID == 1:
+ HtPicRow.append(ligne)
+ elif separatorID == 2:
+ HtOrphans.append(ligne)
+ elif separatorID == 3:
+ HtFooter.append(ligne)
+
+ self.TNidList = []
+ self.TNtsList = []
+ self.TNnameList = []
+
+
+ def SetFileSection (self, FileSize, md5):
+ """ Initialize data of the report file section. """
+ self.FileSize = FileSize
+ self.md5 = md5
+
+
+ def SetREtst (self, REtst):
+ """ Initialize data of the report file section. """
+ self.REtst = REtst
+
+
+ def headwrite (self):
+ """ Writes report header. """
+ self.repfile = open(self.outputdir + "index.html", "w")
+ for ligne in HtHeader:
+ ligne = ligne.replace("__DATEREPORT__", "Report date : " + ctime(time()))
+ ligne = ligne.replace("__TDBDIRNAME__", self.tDBdirname)
+ ligne = ligne.replace("__TDBFNAME__", self.tDBfname)
+ ligne = ligne.replace("__TDBMTIME__", ctime(self.tDBmtime))
+ ligne = ligne.replace("__FILESIZE__", str(self.FileSize))
+ ligne = ligne.replace("__MD5__", self.md5)
+ ligne = ligne.replace("__ROOTENTRYTST__", \
+ "Root Entry modify timestamp : " + self.REtst)
+ self.repfile.write(ligne)
+
+
+ def close(self, statstring):
+ """ Terminate processing HtRep instance. """
+
+ for ligne in HtFooter:
+ ligne = ligne.replace("__TYPEXTRACT__", statstring)
+ ligne = ligne.replace("__VVERSION__", "Vinetto " + self.verstr)
+ self.repfile.write(ligne)
+ self.repfile.close()
+
+
+ def rowflush(self):
+ """ Process a report line. """
+ self.rownumber += 1
+ for ligne in HtPicRow:
+ ligne = ligne.replace("__ROWNUMBER__", str(self.rownumber))
+ for j in range(len(self.tnId)):
+ ligne = ligne.replace("__TNfilled__" + str(j), "1")
+ buff = IMGTAG.replace("__TNFNAME__", self.tnFname[j])
+ buff = buff.replace("__TNNAME__", self.tnName[j])
+ ligne = ligne.replace("__IMGTAG__" + str(j), buff)
+ ligne = ligne.replace("__TNID__" + str(j), self.tnId[j])
+ for j in range(len(self.tnId),5):
+ ligne = ligne.replace("__TNfilled__" + str(j), "0")
+ ligne = ligne.replace("__IMGTAG__" + str(j), " ")
+ ligne = ligne.replace("__TNID__" + str(j), " ")
+
+ self.repfile.write(ligne)
+
+ self.repfile.write("<TABLE WIDTH=\"720\"><TR><TD> </TD></TR>" + \
+ "<TR><TD><P ALIGN=\"LEFT\">")
+ for i in range(len(self.tnId)):
+ if self.tnName[i] != "":
+ self.repfile.write("<TT>" + self.tnId[i] + " -- " + \
+ self.tnTs[i].replace(" ", " ") + " -- " + \
+ self.tnName[i] + "</TT><BR>\n")
+ else:
+ self.repfile.write("<TT STYLE=\"color: blue\">" + self.tnId[i] + " ** " + \
+ " no matching Catalog entry found " + \
+ " ** " + "</TT><BR>\n")
+
+ self.repfile.write("</P></TD></TR><TR><TD> </TD></TR></TABLE>")
+
+ self.tnId = []
+ self.tnFname = []
+ self.tnTs = []
+ self.tnName = []
+
+
+ def printOrphanCatEnt(self, OrphanICat):
+ """ Print orphan catalog entry. """
+ if OrphanICat != []:
+ endOrphanSection = False
+ for ligne in HtOrphans:
+ if ligne.find("__ORPHANENTRY__") >= 0:
+ oprhanLine = ligne
+ break
+ else:
+ self.repfile.write(ligne)
+
+ for iCat in OrphanICat:
+ catEntry = getCatEntry (iCat)
+ Ts = catEntry[0][0]
+ Name = catEntry[0][1]
+ str = "<TT>" + ("%04i" % iCat) + " -- " + \
+ Ts.replace(" ", " ") + " -- " + Name + "</TT><BR>\n"
+ ligne = oprhanLine.replace("__ORPHANENTRY__", str)
+ self.repfile.write(ligne)
+
+ for ligne in HtOrphans:
+ if ligne.find("__ORPHANENTRY__") < 0:
+ if endOrphanSection:
+ self.repfile.write(ligne)
+ else:
+ endOrphanSection = True
+
+
+ def flush(self, statstring):
+ """ Process the report body and the report end. """
+ from vinutils import TNStreams
+ from vinutils import Catalog
+
+ self.headwrite()
+
+ self.rownumber = 0
+ self.tnId = []
+ self.tnFname = []
+ self.tnTs = []
+ self.tnName = []
+
+# for (iTN, vType, filename) in TNStreams:
+ for iTN in TNStreams:
+ for (vType, filename) in TNStreams[iTN]:
+ self.tnId.append("%04i" % iTN)
+ self.tnFname.append(filename)
+ catEntry = getCatEntry (iTN)
+ if len(catEntry) == 0:
+ Ts = ""
+ Name = ""
+ elif len(catEntry) >= 1:
+ # duplicate index numbers not properly handled !!!
+ Ts = catEntry[0][0]
+ Name = catEntry[0][1]
+ self.tnTs.append(Ts)
+ self.tnName.append(Name)
+ if len(self.tnId) >= 5:
+ self.rowflush()
+
+ if len(self.tnId) > 0:
+ self.rowflush()
+
+ # Scanning for orphan catalog entries
+ OrphanICat = []
+ for iCat in Catalog:
+ if not TNStreams.has_key(iCat):
+ OrphanICat.append(iCat)
+ self.printOrphanCatEnt(OrphanICat)
+
+ self.close(statstring)
diff --git a/vinutils.py b/vinutils.py
new file mode 100644
index 0000000..c70ca42
--- /dev/null
+++ b/vinutils.py
@@ -0,0 +1,161 @@
+# -*- coding: UTF-8 -*-
+"""
+module vinutils.py
+-----------------------------------------------------------------------------
+
+ Vinetto : a forensics tool to examine Thumbs.db files
+ Copyright (C) 2005, 2006 by Michel Roukine
+
+This file is part of Vinetto.
+
+ Vinetto is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
+
+ Vinetto is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with the vinetto package; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-----------------------------------------------------------------------------
+"""
+
+__revision__ = "$Revision: 47 $"
+__version__ = "0.01"
+__author__ = 'Michel Roukine'
+
+Catalog = {}
+catIndxOutOfSeqFlag = False
+iCatPrec = None
+
+TNStreams = {}
+tnStreamOutOfSeqFlag = False
+iTnsPrec = None
+
+
+def catIndxOutOfSeq():
+ """Return catIndxOutOfSeqFlag value. """
+ return catIndxOutOfSeqFlag
+
+
+def tnStreamOutOfSeq():
+ """Return tnStreamOutOfSeqFlag value. """
+ return tnStreamOutOfSeqFlag
+
+
+def addCatEntry (iCat, timestamp, TNname):
+ """Add a new Catalog entry. """
+ global catIndxOutOfSeqFlag, iCatPrec
+ if iCatPrec != None:
+ if iCat != (iCatPrec + 1) :
+ catIndxOutOfSeqFlag = True
+
+ if Catalog.has_key(iCat):
+ Catalog[iCat].append((timestamp, TNname))
+ else:
+ Catalog[iCat] = [(timestamp, TNname)]
+
+ iCatPrec = iCat
+ return
+
+
+def addTNStream (iTN, vType, filename):
+ """Add new thumbnail stream references. """
+ global tnStreamOutOfSeqFlag, iTnsPrec
+ if iTnsPrec != None:
+ if iTN != (iTnsPrec + 1) :
+ tnStreamOutOfSeqFlag = True
+
+ if TNStreams.has_key(iTN):
+ TNStreams[iTN].append((vType, filename))
+ else:
+ TNStreams[iTN] = [(vType, filename)]
+
+ iTnsPrec = iTN
+ return
+
+
+def nbCatEnt ():
+ """Return number of Catalog entry. """
+ nb = 0
+ for k in Catalog:
+ nb += len(Catalog[k])
+ return nb
+
+
+def nbTNstr (*vt):
+ """Return number of extracted/unextracted thumbnails. """
+ nb = 0
+ if len(vt) == 0:
+ for k in TNStreams:
+ nb += len(TNStreams[k])
+ return nb
+ else :
+ nb = 0
+ for k in TNStreams:
+ for (vType, filename) in TNStreams[k]:
+ if vt[0] == vType :
+ nb += 1
+ return nb
+
+
+def extractStats(outputdir):
+ """Return extraction statistics. """
+ extr = {"1":0, "2":0}
+ unextr = {"1":0, "2":0}
+ statstring = ""
+ odstr = ""
+ if outputdir != None:
+ odstr = " to " + outputdir
+
+ for k in TNStreams:
+ for (vType, filename) in TNStreams[k]:
+ if filename == "" :
+ unextr[vType] += 1
+ else:
+ extr[vType] += 1
+
+ for vt in extr:
+ if extr[vt] > 0:
+ statstring += str(extr[vt]) + " Type " + vt + \
+ " thumbnails extracted" + odstr + "\n"
+
+ for vt in unextr:
+ if unextr[vt] > 0:
+ statstring += str(unextr[vt]) + " Type " + vt + \
+ " thumbnails unextracted" + odstr + "\n"
+ return statstring
+
+
+def getCatEntry(iCat):
+ """Return iCat Catalog entry. """
+ if Catalog.has_key(iCat):
+ return Catalog[iCat]
+ return []
+
+
+def fincrement (filename):
+ """ Compute next "valid" filename for a given SID. """
+ if filename.find("_") < 0:
+ return filename + "_1"
+ else:
+ i = int(filename[filename.find('_') + 1:])
+ return filename[:filename.find('_') + 1] + str(i + 1)
+
+
+def TNfname(SIDstr, vType):
+ """ Compute filenames for thumbnails. """
+ computedfn = SIDstr
+ k = int(SIDstr)
+ if TNStreams.has_key(k):
+ # duplicate index numbers
+ for (vtyp, filename) in TNStreams[k]:
+ if computedfn == filename:
+ computedfn = fincrement (filename)
+ addTNStream(k, vType, computedfn)
+ return computedfn
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/vinetto.git
More information about the forensics-changes
mailing list