[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