This commit is contained in:
Luca 2022-05-07 13:46:14 +01:00
commit c0ae08acc1
147 changed files with 18846 additions and 0 deletions

9
FilesToAdd.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "FilesToAdd.h"
FilesToAdd::FilesToAdd(QString path){
filepath=path;
file=new QFileInfo(filepath);
filesize_byte=file->size();
filesize_megabyte=filesize_byte/(1000*1000);
filesize=QString::number(filesize_megabyte, 'f', 3 );
filename=file->fileName().section("/",-1,-1);
}

19
FilesToAdd.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef FILESTOADD_H
#define FILESTOADD_H
#include <QObject>
#include <QFileInfo>
class FilesToAdd
{
public:
FilesToAdd(QString path);
QString filepath;
QString filename;
double filesize_byte;
double filesize_megabyte;
QString filesize;
QFileInfo *file;
};
#endif // FILESTOADD_H

64
FilesToAddListModel.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "FilesToAddListModel.h"
FilesToAddListModel::FilesToAddListModel(QStringList filepaths, QObject *parent) : QAbstractListModel(parent) {
sum_size=0;
filepaths.clear();
setStringList(filepaths);
}
void FilesToAddListModel::setStringList(QStringList filepaths, const QModelIndex &parent) {
for(int i=0; i<filepaths.size(); i++){
beginInsertRows(parent, (int)FilesToAdd_.size(), (int)FilesToAdd_.size());
FilesToAdd_.push_back(FilesToAdd(filepaths.at(i)));
sum_size+=FilesToAdd_.back().filesize_byte;
endInsertRows();
}
}
int FilesToAddListModel::rowCount(const QModelIndex& parent) const {
return FilesToAdd_.size();
}
int FilesToAddListModel::columnCount(const QModelIndex& parent) const {
return 2;
}
QVariant FilesToAddListModel::data(const QModelIndex& index, int role) const {
// Check that the index is valid and within the correct range first:
if (!index.isValid()) return QVariant();
if (role == Qt::DisplayRole)
{
if(index.column()==0){ return QVariant(FilesToAdd_.at(index.row()).filename);}
if(index.column()==1){ return QVariant(FilesToAdd_.at(index.row()).filesize);}
}
else {
return QVariant();
}
return QVariant();
}
QVariant FilesToAddListModel::headerData(int section, Qt::Orientation orientation,int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal){
if(section==0) return QString("Secret file name");
if(section==1) return QString("Size in MB");
else return QString("Column %1").arg(section);
}
else
return QString("X");
}
void FilesToAddListModel::removeRow(int row, const QModelIndex &parent)
{
beginRemoveRows(parent, row, row);
FilesToAdd_.erase(FilesToAdd_.begin()+row);
endRemoveRows();
}
unsigned long FilesToAddListModel::get_sum_size(){
return sum_size;
}

29
FilesToAddListModel.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef FILESTOADDLISTMODEL_H
#define FILESTOADDLISTMODEL_H
#include <QObject>
#include <QAbstractListModel>
#include <FilesToAdd.h>
#include <vector>
class FilesToAddListModel : public QAbstractListModel {
Q_OBJECT
public:
explicit FilesToAddListModel(QStringList filepaths, QObject* parent = 0);
void setStringList(QStringList filepaths, const QModelIndex& parent = QModelIndex());
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,int role = Qt::DisplayRole) const;
void removeRow(int row, const QModelIndex& parent = QModelIndex());
unsigned long get_sum_size();
private:
std::vector<FilesToAdd> FilesToAdd_;
unsigned long sum_size;
};
#endif // FILESTOADDLISTMODEL_H

340
LICENSE Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program 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.
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

30
README.md Normal file
View File

@ -0,0 +1,30 @@
Steghide-GUI is unofficial graphical frontend for steghide (http://steghide.sourceforge.net/) written in Qt and steghide is a steganography program that is able to hide data in various kinds of image- and audio-files. The color- respectivly sample-frequencies are not changed thus making the embedding resistant against first-order statistical tests.
HOW TO COMPILE AND INSTALL
Required packages:
##Debian : qmake libmhash-dev libmcrypt-dev
##Arch : mhash mcrypt
# Old :
To generate makefile just create folder where you wants to build and use command:
qmake -spec linux-g++ -o Makefile ../Steghide-GUI/Steghide-GUI.pro
Where last path it's path to .pro file from Steghide-GUI source;
After you generate makefile just type:
make
to build it and get compiled Steghide-GUI binary (Run ./Steghide-GUI).
If you want to install Steghide-GUI via 'make install' after 'make' command add this lines in *.pro files and repeat all commands listed above (in this example install path will be /usr/local/bin/):
target.path = /usr/local/bin/
INSTALLS += target
LAZY WAY: Just install QT Creator and open .pro file ;)
# Note :
make sure that you have folder named ~/.local/bin/
# New :
qmake -spec linux-g++ -o Makefile Steghide-GUI.pro
make && make install

65
StdRedirection.h Normal file
View File

@ -0,0 +1,65 @@
#ifndef STD_REDIRECTOR
#define STD_REDIRECTOR
#include <cstdlib>
#include <cstdio>
#include <streambuf>
template< class Elem = char, class Tr = std::char_traits< Elem > >
class StdRedirector : public std::basic_streambuf< Elem, Tr >
{
/**
* Callback Function.
*/
typedef void (*pfncb) ( const Elem*, std::streamsize _Count, void* pUsrData );
public:
/**
* Constructor.
* @param a_Stream the stream to redirect
* @param a_Cb the callback function
* @param a_pUsrData user data passed to callback
*/
StdRedirector( std::ostream& a_Stream, pfncb a_Cb, void* a_pUsrData ) :
m_Stream( a_Stream ),
m_pCbFunc( a_Cb ),
m_pUserData( a_pUsrData )
{
//redirect stream
m_pBuf = m_Stream.rdbuf( this );
};
/**
* Destructor.
* Restores the original stream.
*/
~StdRedirector()
{
m_Stream.rdbuf( m_pBuf );
}
/**
* Override xsputn and make it forward data to the callback function.
*/
std::streamsize xsputn( const Elem* _Ptr, std::streamsize _Count )
{
m_pCbFunc( _Ptr, _Count, m_pUserData );
return _Count;
}
/**
* Override overflow and make it forward data to the callback function.
*/
typename Tr::int_type overflow( typename Tr::int_type v )
{
Elem ch = Tr::to_char_type( v );
m_pCbFunc( &ch, 1, m_pUserData );
return Tr::not_eof( v );
}
protected:
std::basic_ostream<Elem, Tr>& m_Stream;
std::streambuf* m_pBuf;
pfncb m_pCbFunc;
void* m_pUserData;
};
#endif

174
Steghide-GUI.pro Normal file
View File

@ -0,0 +1,174 @@
#-------------------------------------------------
#
# Project created by QtCreator 2015-08-17T15:07:41
#
#-------------------------------------------------
# Make executable :
target.path = ~/.local/bin/
INSTALLS += target
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Steghide-GUI
TEMPLATE = app
DEFINES += "USE_LIBJPEG=1"\
"USE_LIBMCRYPT=1"\
"USE_ZLIB=1"\
"HAVE_CONFIG_H=1"\
"_FORTIFY_SOURCE=2"\
LOCALEDIR=\\\"/usr/local/share/locale\\\"
QMAKE_CC = "/usr/bin/gcc -E"
QMAKE_CFLAGS = "-O2 -pipe -fstack-protector-strong -fpermissive --param=ssp-buffer-size=4"
QMAKE_CXXFLAGS = "-O2 -pipe -fstack-protector -fpermissive"
QMAKE_CXX= "/usr/bin/g++"
QMAKE_LFLAGS = "-Wl,-O1,--sort-common,--as-needed,-z,relro"
LIBS += -lz\
-lmhash\
-lmcrypt\
-ljpeg
SOURCES += main.cpp\
mainwindow.cpp \
dialog.cpp \
FilesToAddListModel.cpp \
FilesToAdd.cpp \
steghide-src/Arg.cc \
steghide-src/Arguments.cc \
steghide-src/AssertionFailed.cc \
steghide-src/AuFile.cc \
steghide-src/AuSampleValues.cc \
steghide-src/BFSAPHeuristic.cc \
steghide-src/BinaryIO.cc \
steghide-src/BitString.cc \
steghide-src/BmpFile.cc \
steghide-src/BmpPaletteSampleValue.cc \
steghide-src/BmpRGBSampleValue.cc \
steghide-src/BmpSampleValue.cc \
steghide-src/CvrStgFile.cc \
steghide-src/DFSAPHeuristic.cc \
steghide-src/DMDConstructionHeuristic.cc \
steghide-src/Edge.cc \
steghide-src/EdgeIterator.cc \
steghide-src/EmbData.cc \
steghide-src/Embedder.cc \
steghide-src/EncryptionAlgorithm.cc \
steghide-src/EncryptionMode.cc \
steghide-src/error.cc \
steghide-src/Extractor.cc \
steghide-src/Graph.cc \
steghide-src/JpegFile.cc \
steghide-src/JpegSampleValue.cc \
steghide-src/Matching.cc \
steghide-src/MatchingAlgorithm.cc \
steghide-src/MCryptPP.cc \
steghide-src/MHashKeyGen.cc \
steghide-src/MHashPP.cc \
steghide-src/msg.cc \
steghide-src/ProgressOutput.cc \
steghide-src/PseudoRandomSource.cc \
steghide-src/RandomSource.cc \
steghide-src/RGBTriple.cc \
steghide-src/SampleValue.cc \
steghide-src/SampleValueAdjacencyList.cc \
steghide-src/Selector.cc \
steghide-src/Session.cc \
steghide-src/SMDConstructionHeuristic.cc \
steghide-src/SteghideError.cc \
steghide-src/Terminal.cc \
steghide-src/Utils.cc \
steghide-src/Vertex.cc \
steghide-src/WavChunk.cc \
steghide-src/WavChunkHeader.cc \
steghide-src/WavChunkUnused.cc \
steghide-src/WavFile.cc \
steghide-src/WavFormatChunk.cc \
steghide-src/WavPCMSampleValue.cc \
steghide-src/WKSConstructionHeuristic.cc \
extractdialog.cpp
HEADERS += mainwindow.h \
dialog.h \
FilesToAddListModel.h \
FilesToAdd.h \
steghide-src/Arg.h \
steghide-src/Arguments.h \
steghide-src/AssertionFailed.h \
steghide-src/AuData.h \
steghide-src/AudioData.h \
steghide-src/AudioSampleValue.h \
steghide-src/AuFile.h \
steghide-src/AuSampleValues.h \
steghide-src/AUtils.h \
steghide-src/BFSAPHeuristic.h \
steghide-src/BinaryIO.h \
steghide-src/BitString.h \
steghide-src/BmpFile.h \
steghide-src/BmpPaletteSampleValue.h \
steghide-src/BmpRGBSampleValue.h \
steghide-src/BmpSampleValue.h \
steghide-src/ColorPalette.h \
steghide-src/common.h \
steghide-src/CvrStgFile.h \
steghide-src/CvrStgObject.h \
steghide-src/DFSAPHeuristic.h \
steghide-src/DMDConstructionHeuristic.h \
steghide-src/Edge.h \
steghide-src/EdgeIterator.h \
steghide-src/EmbData.h \
steghide-src/Embedder.h \
steghide-src/EncryptionAlgorithm.h \
steghide-src/EncryptionMode.h \
steghide-src/error.h \
steghide-src/Extractor.h \
steghide-src/gettext.h \
steghide-src/Globals.h \
steghide-src/Graph.h \
steghide-src/JpegFile.h \
steghide-src/JpegSampleValue.h \
steghide-src/Matching.h \
steghide-src/MatchingAlgorithm.h \
steghide-src/MCryptPP.h \
steghide-src/MHashKeyGen.h \
steghide-src/MHashPP.h \
steghide-src/msg.h \
steghide-src/ProgressOutput.h \
steghide-src/PseudoRandomSource.h \
steghide-src/RandomSource.h \
steghide-src/RGBTriple.h \
steghide-src/SampleOccurence.h \
steghide-src/SampleValue.h \
steghide-src/SampleValueAdjacencyList.h \
steghide-src/Selector.h \
steghide-src/Session.h \
steghide-src/SMDConstructionHeuristic.h \
steghide-src/SteghideError.h \
steghide-src/Terminal.h \
steghide-src/Utils.h \
steghide-src/Vertex.h \
steghide-src/WavChunk.h \
steghide-src/WavChunkHeader.h \
steghide-src/WavChunkUnused.h \
steghide-src/WavFile.h \
steghide-src/WavFormatChunk.h \
steghide-src/WavPCMSampleValue.h \
steghide-src/WKSConstructionHeuristic.h \
steghide-src/wrapper_hash_map.h \
steghide-src/wrapper_hash_set.h \
extractdialog.h \
config.h \
StdRedirection.h
FORMS += mainwindow.ui \
dialog.ui \
extractdialog.ui
DISTFILES +=
RESOURCES += \
imageresources.qrc

271
Steghide-GUI.pro.user Normal file
View File

@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.4.2, 2015-08-26T22:37:21. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{4f3d9da6-c8cd-47cc-a91c-0c417aef0f5c}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3b1352d0-24f4-46ae-8342-f69905434e71}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/rryk/GIT/build-Steghide-GUI-Desktop-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">budowania</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">czyszczenia</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/rryk/GIT/build-Steghide-GUI-Desktop-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">budowania</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">czyszczenia</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">instalacji</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Zainstaluj lokalnie</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Steghide-GUI</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/rryk/GIT/Steghide-GUI/Steghide-GUI.pro</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">Steghide-GUI.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>

View File

@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.4.2, 2015-08-19T22:19:29. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{381ec203-8cce-4f86-b5d8-f9caa7e5a73e}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{2dfa4a71-7a71-4789-a466-382a28638310}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/rryk/build-Steghide-GUI-Desktop-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">budowania</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">czyszczenia</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/rryk/build-Steghide-GUI-Desktop-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">budowania</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">czyszczenia</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">instalacji</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Zainstaluj lokalnie</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Steghide-GUI</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/rryk/Steghide-GUI/Steghide-GUI.pro</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">Steghide-GUI.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>

View File

@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.4.2, 2015-08-22T14:59:33. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{4f3d9da6-c8cd-47cc-a91c-0c417aef0f5c}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3b1352d0-24f4-46ae-8342-f69905434e71}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/rryk/GIT/build-Steghide-GUI-Desktop-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">budowania</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">czyszczenia</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/rryk/GIT/build-Steghide-GUI-Desktop-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">budowania</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">czyszczenia</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">instalacji</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Zainstaluj lokalnie</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Steghide-GUI</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/rryk/GIT/Steghide-GUI/Steghide-GUI.pro</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">Steghide-GUI.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>

244
categoryitemmodel.cpp Normal file
View File

@ -0,0 +1,244 @@
/* *********************************************************************** *
* XINX *
* Copyright (C) 2009 by Ulrich Van Den Hekke *
* ulrich.vdh@shadoware.org *
* *
* This program 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 3 of the License, or *
* (at your option) any later version. *
* *
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
* *********************************************************************** */
// Xinx header
#include "categoryitemmodel.h"
#include "snipetmanager.h"
// Qt header
#include <QIcon>
#include <QColor>
#include <QFont>
#include <QVariant>
#include <QSqlRecord>
#include <QSqlError>
/* CategoryItemModel */
CategoryItemModel::CategoryItemModel( QSqlDatabase db, QObject * parent ) : QAbstractProxyModel( parent ), m_db( db ) {
// This will be automatically deleted.
m_sourceModel = new QSqlQueryModel( this );
setSourceModel( m_sourceModel );
createMapping();
}
CategoryItemModel::~CategoryItemModel() {
qDeleteAll( m_sourcesIndexMapping );
}
void CategoryItemModel::select() {
// Set the query used all snipet
m_sourceModel->setQuery(
"SELECT id, parent_id, name "
"FROM categories "
"ORDER BY name", m_db
);
// Define name for header column
m_sourceModel->setHeaderData( list_id, Qt::Horizontal, tr("Id") );
m_sourceModel->setHeaderData( list_parentid, Qt::Horizontal, tr("Parent") );
m_sourceModel->setHeaderData( list_name, Qt::Horizontal, tr("Name") );
// Initialize the mapping
createMapping();
// Reset the layout
reset();
}
/*! \internal
Create the mapping of all index in the table.
*/
void CategoryItemModel::createMapping() {
qDeleteAll( m_sourcesIndexMapping );
m_sourcesIndexMapping.clear();
m_categoryIdMapping.clear();
int source_rows = m_sourceModel->rowCount();
for( int i = -1; i < source_rows; ++i ) {
Mapping * m = new Mapping;
IndexMap::const_iterator it = IndexMap::const_iterator( m_sourcesIndexMapping.insert( i, m ) );
m->index = i;
m->parrentId = 0;
m->parentIndex = 0;
if( i >= 0 ) {
QSqlRecord record = m_sourceModel->record( i );
m_categoryIdMapping[ record.value( list_id ).toInt() ] = i;
m->id = record.value( list_id ).toInt();
} else { // Create the root Item
m->id = 0;
m_categoryIdMapping[ 0 ] = -1;
}
}
for( int i = 0; i < source_rows; ++i ) {
QSqlRecord record = m_sourceModel->record( i );
int parentCategoryId = record.value( list_parentid ).toInt();
int parentCategoryIndex = m_categoryIdMapping.value( parentCategoryId, -2 );
Q_ASSERT( parentCategoryIndex > -2 );
Mapping * mapping = m_sourcesIndexMapping.value( i );
mapping->parentIndex = parentCategoryIndex;
mapping->parrentId = parentCategoryId;
Mapping * categoryMapping = m_sourcesIndexMapping.value( parentCategoryIndex );
categoryMapping->source_rows.append( i );
}
}
int CategoryItemModel::proxyColumnToSource( int proxyColumn ) const {
if( proxyColumn == 0 )
return list_name;
return -1;
}
int CategoryItemModel::sourceColumnToProxy( int sourceColumn ) const {
if( sourceColumn == list_name )
return 0;
return -1;
}
/// For the given source index, this method return the corresponding index in the proxy
QModelIndex CategoryItemModel::mapFromSource ( const QModelIndex & sourceIndex ) const {
if( ! sourceIndex.isValid() ) return QModelIndex();
if( sourceIndex.model() != m_sourceModel ) {
qWarning( "CategoryItemModel: index from wrong model passed to mapFromSource" );
return QModelIndex();
}
int row = sourceIndex.row();
IndexMap::const_iterator it = m_sourcesIndexMapping.constFind( row );
Q_ASSERT( it != m_sourcesIndexMapping.constEnd() );
int parentRow = it.value()->parentIndex;
IndexMap::const_iterator parentIt = m_sourcesIndexMapping.constFind( parentRow );
Q_ASSERT( parentIt != m_sourcesIndexMapping.constEnd() );
Mapping * m = parentIt.value();
int proxyRow = m->source_rows.indexOf( row ), proxyColumn = sourceColumnToProxy( sourceIndex.column() );
if( proxyColumn == -1 ) return QModelIndex();
return createIndex( proxyRow, proxyColumn, *parentIt );
}
QModelIndex CategoryItemModel::mapToSource ( const QModelIndex & proxyIndex ) const {
if( ! proxyIndex.isValid() ) return QModelIndex();
if( proxyIndex.model() != this ) {
qWarning( "CategoryItemModel: index from wrong model passed to mapToSource" );
return QModelIndex();
}
Mapping * m = static_cast<Mapping*>( proxyIndex.internalPointer() );
int sourceColumn = proxyColumnToSource( proxyIndex.column() );
if( sourceColumn == -1 ) return QModelIndex();
int sourceRow = m->source_rows.at( proxyIndex.row() );
return m_sourceModel->index( sourceRow, sourceColumn );
}
QModelIndex CategoryItemModel::index( int row, int column, const QModelIndex & parent ) const {
if( ( row < 0 ) || ( column < 0 ) ) return QModelIndex();
IndexMap::const_iterator it = m_sourcesIndexMapping.constFind( -1 );
QModelIndex sourceParent = mapToSource( parent );
if( sourceParent.isValid() ) {
it = m_sourcesIndexMapping.constFind( sourceParent.row() );
}
Q_ASSERT( it != m_sourcesIndexMapping.constEnd() );
if( it.value()->source_rows.count() <= row )
return QModelIndex();
return createIndex( row, column, *it );
}
QModelIndex CategoryItemModel::index( int categoryId ) {
int sourceRow = m_categoryIdMapping.value( categoryId, -1 );
if( sourceRow >= 0 ) {
Mapping * m = m_sourcesIndexMapping.value( sourceRow );
int parentRow = m->parentIndex;
IndexMap::const_iterator parentIt = m_sourcesIndexMapping.constFind( parentRow );
Q_ASSERT( parentIt != m_sourcesIndexMapping.constEnd() );
Mapping * parrentMapping = parentIt.value();
int proxyRow = parrentMapping->source_rows.indexOf( m->index );
return createIndex( proxyRow, 0, *parentIt );
}
return QModelIndex();
}
QModelIndex CategoryItemModel::parent( const QModelIndex & index ) const {
if( ! index.isValid() ) return QModelIndex();
Mapping * m = static_cast<Mapping*>( index.internalPointer() );
int sourceRow = m->index;
if( sourceRow == -1 ) return QModelIndex();
QModelIndex sourceParent = m_sourceModel->index( sourceRow, proxyColumnToSource( 0 ) );
QModelIndex proxyParent = mapFromSource( sourceParent );
return proxyParent;
}
int CategoryItemModel::rowCount( const QModelIndex & index ) const {
if( index.column() > 0 ) return 0;
if( ! index.isValid() ) {
Mapping * rootMapping = m_sourcesIndexMapping.value( -1 );
return rootMapping->source_rows.count();
} else {
Mapping * parrentMapping = static_cast<Mapping*>( index.internalPointer() );
int sourceRowIndex = parrentMapping->source_rows.at( index.row() );
Mapping * rowMapping = m_sourcesIndexMapping.value( sourceRowIndex );
return rowMapping->source_rows.count();
}
}
int CategoryItemModel::columnCount( const QModelIndex & index ) const {
Q_UNUSED( index );
return 1;
}
QVariant CategoryItemModel::data( const QModelIndex & index, int role ) const {
if( ! index.isValid() ) return QVariant();
if( role == Qt::DecorationRole ) {
if( index.column() == 0 ) {
return QIcon( ":/images/folder.png" );
}
} else if( role == CategoryItemModel::CategoryIdRole ) {
QModelIndex sourceIndex = mapToSource( index );
QSqlRecord record = m_sourceModel->record( sourceIndex.row() );
return record.value( list_id );
}
return QAbstractProxyModel::data( index, role );
}

327
config.h Normal file
View File

@ -0,0 +1,327 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.in by autoheader. */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* enable code used only for debugging */
/* #undef DEBUG */
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#define ENABLE_NLS 1
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define to 1 if you have the <argz.h> header file. */
#define HAVE_ARGZ_H 1
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
#define HAVE_DCGETTEXT 1
/* /dev/random is available */
#define HAVE_DEV_RANDOM 1
/* /dev/urandom is available */
#define HAVE_DEV_URANDOM 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the `feof_unlocked' function. */
#define HAVE_FEOF_UNLOCKED 1
/* Define to 1 if you have the `fgets_unlocked' function. */
#define HAVE_FGETS_UNLOCKED 1
/* Define to 1 if you have the `getcwd' function. */
#define HAVE_GETCWD 1
/* Define to 1 if you have the `getc_unlocked' function. */
#define HAVE_GETC_UNLOCKED 1
/* Define to 1 if you have the `getegid' function. */
#define HAVE_GETEGID 1
/* Define to 1 if you have the `geteuid' function. */
#define HAVE_GETEUID 1
/* Define to 1 if you have the `getgid' function. */
#define HAVE_GETGID 1
/* Define to 1 if you have the `getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define if the GNU gettext() function is already present or preinstalled. */
#define HAVE_GETTEXT 1
/* Define to 1 if you have the `getuid' function. */
#define HAVE_GETUID 1
/* Define if you have the iconv() function. */
#define HAVE_ICONV 1
/* Define if <inttypes.h> exists and doesn't clash with <sys/types.h>. */
#define HAVE_INTTYPES_H 1
/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
declares uintmax_t. */
#define HAVE_INTTYPES_H_WITH_UINTMAX 1
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#define HAVE_LANGINFO_CODESET 1
/* Define if your <locale.h> file defines LC_MESSAGES. */
#define HAVE_LC_MESSAGES 1
/* Define to 1 if you have the `jpeg' library (-ljpeg). */
#define HAVE_LIBJPEG 1
/* Define to 1 if you have the `mcrypt' library (-lmcrypt). */
#define HAVE_LIBMCRYPT 1
/* Define to 1 if you have the `mhash' library (-lmhash). */
#define HAVE_LIBMHASH 1
/* Define to 1 if you have the `z' library (-lz). */
#define HAVE_LIBZ 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if you have the <malloc.h> header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mempcpy' function. */
#define HAVE_MEMPCPY 1
/* Define to 1 if you have a working `mmap' system call. */
#define HAVE_MMAP 1
/* Define to 1 if you have the `munmap' function. */
#define HAVE_MUNMAP 1
/* Define to 1 if you have the <nl_types.h> header file. */
#define HAVE_NL_TYPES_H 1
/* Define to 1 if you have the `putenv' function. */
#define HAVE_PUTENV 1
/* Define to 1 if you have the `setenv' function. */
#define HAVE_SETENV 1
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
uintmax_t. */
#define HAVE_STDINT_H_WITH_UINTMAX 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `stpcpy' function. */
#define HAVE_STPCPY 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#define HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the `tcgetattr' function. */
#define HAVE_TCGETATTR 1
/* Define to 1 if you have the `tcsetattr' function. */
#define HAVE_TCSETATTR 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the `tsearch' function. */
#define HAVE_TSEARCH 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the unsigned long long type. */
#define HAVE_UNSIGNED_LONG_LONG 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the `__argz_count' function. */
#define HAVE___ARGZ_COUNT 1
/* Define to 1 if you have the `__argz_next' function. */
#define HAVE___ARGZ_NEXT 1
/* Define to 1 if you have the `__argz_stringify' function. */
#define HAVE___ARGZ_STRINGIFY 1
/* Define as const if the declaration of iconv() needs const. */
#define ICONV_CONST
/* Define if integer division by zero raises signal SIGFPE. */
#define INTDIV0_RAISES_SIGFPE 1
/* disable randomness making every run exactly reproducible */
/* #undef NORANDOM */
/* Name of package */
#define PACKAGE "steghide"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
/* #undef PRI_MACROS_BROKEN */
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* The size of `long int', as computed by sizeof. */
#define SIZEOF_LONG_INT 8
/* The size of `short int', as computed by sizeof. */
#define SIZEOF_SHORT_INT 2
/* The size of `signed char', as computed by sizeof. */
#define SIZEOF_SIGNED_CHAR 1
/* The size of `unsigned char', as computed by sizeof. */
#define SIZEOF_UNSIGNED_CHAR 1
/* The size of `unsigned int', as computed by sizeof. */
#define SIZEOF_UNSIGNED_INT 4
/* The size of `unsigned long int', as computed by sizeof. */
#define SIZEOF_UNSIGNED_LONG_INT 8
/* The size of `unsigned short int', as computed by sizeof. */
#define SIZEOF_UNSIGNED_SHORT_INT 2
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* type of unsigned byte */
#define TYPE_BYTE unsigned char
/* type of signed byte */
#define TYPE_SBYTE signed char
/* type of signed word with 16 bits */
#define TYPE_SWORD16 short int
/* type of signed word with 32 bits */
#define TYPE_SWORD32 int
/* type of unsigned word with 16 bits */
#define TYPE_UWORD16 unsigned short int
/* type of unsigned word with 32 bits */
#define TYPE_UWORD32 unsigned int
/* use the libjpeg library (header and lib are present) */
#define USE_LIBJPEG 1
/* use the libmcrypt library (header and lib are present) */
#define USE_LIBMCRYPT 1
/* use the z compression library (header and lib are present) */
#define USE_ZLIB 1
/* Version number of package */
#define VERSION "0.5.1"
/* target system is win32 */
/* #undef WIN32 */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to `long int' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to unsigned long or unsigned long long if <inttypes.h> and
<stdint.h> don't define. */
/* #undef uintmax_t */

18
dialog.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::setlabeltext(QString new_text){
ui->label->setText(new_text);
}

22
dialog.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
void setlabeltext(QString new_text);
~Dialog();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H

86
dialog.ui Normal file
View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Test</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>TEXT</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

27
extractdialog.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "extractdialog.h"
#include "ui_extractdialog.h"
ExtractDialog::ExtractDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ExtractDialog)
{
ui->setupUi(this);
}
ExtractDialog::~ExtractDialog()
{
delete ui;
}
void ExtractDialog::setlabeltext(QString new_text){
ui->label->setText(new_text);
}
void ExtractDialog::setprogressbarvalue(int k){
ui->progressBar->setValue(k);
}
void ExtractDialog::on_pushButton_clicked()
{
delete this;
}

27
extractdialog.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef EXTRACTDIALOG_H
#define EXTRACTDIALOG_H
#include <QDialog>
namespace Ui {
class ExtractDialog;
}
class ExtractDialog : public QDialog
{
Q_OBJECT
public:
explicit ExtractDialog(QWidget *parent = 0);
void setlabeltext(QString new_text);
void setprogressbarvalue(int k);
~ExtractDialog();
private slots:
void on_pushButton_clicked();
private:
Ui::ExtractDialog *ui;
};
#endif // EXTRACTDIALOG_H

66
extractdialog.ui Normal file
View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExtractDialog</class>
<widget class="QDialog" name="ExtractDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>200</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>260</x>
<y>150</y>
<width>95</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>401</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Extracting...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QProgressBar" name="progressBar">
<property name="geometry">
<rect>
<x>30</x>
<y>70</y>
<width>341</width>
<height>41</height>
</rect>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

11
imageresources.qrc Normal file
View File

@ -0,0 +1,11 @@
<RCC>
<qresource prefix="/resources">
<file>images/add.png</file>
<file>images/convert.png</file>
<file>images/encode.png</file>
<file>images/extract.png</file>
<file>images/help.png</file>
<file>images/reload.png</file>
<file>images/settings.png</file>
</qresource>
</RCC>

BIN
images/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/convert.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
images/encode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
images/extract.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
images/help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
images/reload.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
images/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

126
main.cpp Normal file
View File

@ -0,0 +1,126 @@
#include "mainwindow.h"
#include <QApplication>
#include <clocale>
#include "steghide-src/common.h"
#include "steghide-src/Session.h"
#include "steghide-src/SteghideError.h"
#ifdef WIN32 // locale support on Windows
#include <windows.h>
typedef struct struct_LCIDENTRY {
LCID localeID ;
char language[3] ;
} LCIDENTRY ;
LCIDENTRY LCIDTable[] = {
// french
{ 0x040c, "fr" }, // France
{ 0x080c, "fr" }, // Belgium
{ 0x0c0c, "fr" }, // Canada
{ 0x100c, "fr" }, // Switzerland
{ 0x140c, "fr" }, // Luxembourg
{ 0x180c, "fr" }, // Monaco
// german
{ 0x0407, "de" }, // Germany
{ 0x0807, "de" }, // Switzerland
{ 0x0c07, "de" }, // Austria
{ 0x1007, "de" }, // Luxembourg
{ 0x1407, "de" }, // Liechtenstein
// spanish
{ 0x040a, "es" }, // Spain - Traditional
{ 0x080a, "es" }, // Mexico
{ 0x0c0a, "es" }, // Spain - Modern Sort
{ 0x100a, "es" }, // Guatemala
{ 0x140a, "es" }, // Costa Rica
{ 0x180a, "es" }, // Panama
{ 0x1c0a, "es" }, // Dominican Republic
{ 0x200a, "es" }, // Venezuela
{ 0x240a, "es" }, // Colombia
{ 0x280a, "es" }, // Peru
{ 0x2c0a, "es" }, // Argentinia
{ 0x300a, "es" }, // Ecuador
{ 0x340a, "es" }, // Chile
{ 0x380a, "es" }, // Uruguay
{ 0x3c0a, "es" }, // Paraguay
{ 0x400a, "es" }, // Bolivia
{ 0x440a, "es" }, // El Salvador
{ 0x480a, "es" }, // Honduras
{ 0x4c0a, "es" }, // Nicaragua
{ 0x500a, "es" }, // Puerto Rico
// romanian
{ 0x0418, "ro" }, // Romanian
{ 0x0818, "ro" }, // Romanian (Moldova)
// end of LCIDTable
{ 0x0000, "__" }
} ;
#undef LOCALEDIR
#define LOCALEDIR "./locale/"
#endif // WIN32
static void gettext_init (void) ;
int main(int argc, char *argv[])
{
if(argc==1){
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
else{
try {
gettext_init() ;
Args = Arguments (argc, argv) ;
Args.parse() ;
Session s ;
s.run() ;
}
catch (SteghideError& e) {
e.printMessage() ;
exit(EXIT_FAILURE) ;
}
exit(EXIT_SUCCESS) ;
}
}
static void gettext_init (void)
{
#ifndef DEBUG
/* initialize gettext */
setlocale (LC_ALL, "") ;
bindtextdomain (PACKAGE, LOCALEDIR) ;
bind_textdomain_codeset (PACKAGE, "ISO-8859-1") ;
textdomain (PACKAGE) ;
#ifdef WIN32
/* using the Windows API to find out which language should be used
(as there is no environment variable indicating the language) */
{
LCID localeID = GetThreadLocale () ;
int i = 0 ;
while (LCIDTable[i].localeID != 0x0000) {
if (localeID == LCIDTable[i].localeID) {
setenv ("LANG", LCIDTable[i].language, 1) ;
/* Make Change known (see gettext manual) */
{
extern int _nl_msg_cat_cntr ;
++_nl_msg_cat_cntr;
}
break ;
}
i++ ;
}
}
#endif // ndef WIN32
#endif // ndef DEBUG
}

186
mainwindow.cpp Normal file
View File

@ -0,0 +1,186 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QFileDialog"
#include "QStringListModel"
#include "QMessageBox"
#include "QInputDialog"
#include <QTextStream>
#include <QLabel>
#include <QTextBrowser>
void outcallback( const char* ptr, std::streamsize count, void* pString )
{
(void) count;
QString* p = static_cast< QString* >( pString );
p->append(ptr);
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->FreeSpaceProgressBar->setFormat("Select file in left section.");
ui->centralWidget->setLayout(ui->gridLayout);
sPath="/home/rryk/Pulpit/Discotest";
selected_file=NULL;
dirmodel = new QFileSystemModel(this);
dirmodel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files);
dirmodel->setNameFilters(QStringList() << "*.jpg" << "*.JPG" << "*.jpeg" << "*.JPEG" << "*.bmp" << "*.BMP" << "*.wav" << "*.WAV" << "*.au" << "*.AU");
dirmodel->setRootPath(sPath);
ui->FilesAndFoldersTreeView->setModel(dirmodel);
ui->FilesAndFoldersTreeView->setRootIndex(dirmodel->index(sPath));
filesmodel = new FilesToAddListModel(filenames);
ui->FileTableView->setModel(filesmodel);
files_v_header= ui->FileTableView->verticalHeader();
connect(files_v_header, SIGNAL(sectionClicked(int)), this, SLOT(on_sectionClicked(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_ReloadButton_clicked()
{
sPath=ui->FilesAndFolders_MainPath->text();
if(QDir(sPath).exists()){
dirmodel->setRootPath(sPath);
ui->FilesAndFoldersTreeView->setRootIndex(dirmodel->index(sPath));
}
else{
QWidget tmp;
QMessageBox::critical(&tmp,"Error","WRONG PATH!");
}
}
void MainWindow::on_AddFilesButton_clicked()
{
filenames.clear();
filenames=QFileDialog::getOpenFileNames(this, tr("Open File"), "/", "All files *.*");
filesmodel->setStringList(filenames);
update_FreeSpaceProgressBar();
}
void MainWindow::on_sectionClicked ( int logicalIndex )
{
filesmodel->removeRow(logicalIndex);
update_FreeSpaceProgressBar();
}
void MainWindow::on_SettingsButton_clicked()
{
dialog = new Dialog(this);
dialog->setWindowTitle("Settings");
dialog->setlabeltext("There will be some Settings.");
dialog->setModal(true);
dialog->show();
}
void MainWindow::on_HelpButton_clicked()
{
dialog = new Dialog(this);
dialog->setWindowTitle("Help");
dialog->setlabeltext("There will be some Help.");
dialog->setModal(true);
dialog->show();
}
void MainWindow::on_EncodeButton_clicked()
{
passphrase=QInputDialog::getText(this,"Specify passphrase","Enter passphrase:",QLineEdit::Password);
}
void MainWindow::on_FilesAndFoldersTreeView_clicked(const QModelIndex &index)
{
if((ui->FilesAndFoldersTreeView->selectionModel()->isSelected(index))&&(QFileInfo(dirmodel->filePath(index)).isFile())){
selected_file = CvrStgFile::readFile ((dirmodel->filePath(index)).toUtf8().constData()) ;
update_FreeSpaceProgressBar();
ui->ExtractButton->setEnabled(true);
}
else
{
ui->ExtractButton->setEnabled(false);
selected_file = NULL;
}
}
void MainWindow::update_FreeSpaceProgressBar(){
if(selected_file!=NULL){
int temp=((filesmodel->get_sum_size())/(selected_file->getCapacity()))*100;
ui->FreeSpaceProgressBar->setValue(temp);
ui->FreeSpaceProgressBar->setFormat(QString::number(filesmodel->get_sum_size())+" / "+QString::number(selected_file->getCapacity()));
}
}
void MainWindow::on_FilesAndFolders_MainPath_returnPressed()
{
on_ReloadButton_clicked();
}
void MainWindow::on_ExtractButton_clicked()
{
if(selected_file!=NULL){
ExtractDialog *extract_dialog;
extract_dialog=new ExtractDialog(this);
extract_dialog->setModal(true);
extract_dialog->show();
passphrase=QInputDialog::getText(this,"Specify passphrase","Enter passphrase:",QLineEdit::Password);
QModelIndex index=ui->FilesAndFoldersTreeView->selectionModel()->selectedIndexes().at(0);
std::string dirmodel_path=(dirmodel->filePath(index)).toUtf8().constData();
Extractor ext (dirmodel_path, passphrase.toUtf8().constData()) ;
EmbData* embdata = ext.extract() ;
// write data
std::string fn ;
// write extracted data to file with embedded file name
fn = embdata->getFileName() ;
if (fn.length() == 0) {
fn=(QInputDialog::getText(this,"Please specify a file name for the extracted data (there is no name embedded in the stego file).","Enter filename:",QLineEdit::Normal)).toUtf8().constData();
}
extract_dialog->setlabeltext( QString::fromStdString("Writing extracted data to: "+fn));
QString * myString = new QString();
myString->clear();
StdRedirector<>* myRedirector = new StdRedirector<>( std::cerr, outcallback, myString );
BinaryIO *io;
try{
io = new BinaryIO (dirmodel_path.substr(0,dirmodel_path.find_last_of("//"))+"/"+fn, BinaryIO::WRITE) ;
}
catch(SteghideError e){
QMessageBox::StandardButton reply = QMessageBox::question(this, "Existing file?", myString->toUtf8().constData(),
QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes) {
Args.Force.setValue(true);
io = new BinaryIO (fn, BinaryIO::WRITE) ;
Args.Force.setValue(false);
}
delete myRedirector;
myString->clear();
}
if(io->is_open()){
std::vector<BYTE> data = embdata->getData() ;
float progress=0;
unsigned long k;
unsigned long size=data.size();
for (std::vector<BYTE>::iterator i = data.begin() ; i != data.end() ; i++) {
io->write8 (*i) ;
k=((i-data.begin())/100);
progress=((k/(data.size()/100))*100);
extract_dialog->setprogressbarvalue(progress);
}
io->close() ;
extract_dialog->setlabeltext( QString::fromStdString("wrote extracted data to \""+fn+"\"."));
}
else{
extract_dialog->setlabeltext( "ERROR" );
}
}
}

63
mainwindow.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileSystemModel>
#include <QHeaderView>
#include <dialog.h>
#include <extractdialog.h>
#include "FilesToAddListModel.h"
#include "steghide-src/CvrStgFile.h"
#include "steghide-src/Session.h"
#include "steghide-src/EmbData.h"
#include "steghide-src/Extractor.h"
#include "steghide-src/Selector.h"
#include "steghide-src/error.h"
#include "steghide-src/common.h"
#include "StdRedirection.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_sectionClicked ( int logicalIndex );
void on_ReloadButton_clicked();
void on_AddFilesButton_clicked();
void on_SettingsButton_clicked();
void on_HelpButton_clicked();
void on_EncodeButton_clicked();
void on_FilesAndFoldersTreeView_clicked(const QModelIndex &index);
void update_FreeSpaceProgressBar();
void on_FilesAndFolders_MainPath_returnPressed();
void on_ExtractButton_clicked();
private:
Ui::MainWindow *ui;
Dialog *dialog;
QFileSystemModel *dirmodel;
FilesToAddListModel* filesmodel;
QHeaderView *files_v_header;
QStringList filenames;
QString sPath;
QString passphrase;
CvrStgFile *selected_file;
};
#endif // MAINWINDOW_H

390
mainwindow.ui Normal file
View File

@ -0,0 +1,390 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="windowTitle">
<string>Steghide-GUI</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>574</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0" colspan="2">
<widget class="QLineEdit" name="FilesAndFolders_MainPath">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>13</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Free space for secret files:</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="label_1">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>13</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Secret files:</string>
</property>
</widget>
</item>
<item row="4" column="0" rowspan="3" colspan="2">
<widget class="QTreeView" name="FilesAndFoldersTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="headerCascadingSectionResizes">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_0">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>13</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Carrier files:</string>
</property>
</widget>
</item>
<item row="6" column="2" colspan="2">
<widget class="QProgressBar" name="FreeSpaceProgressBar">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2" rowspan="2" colspan="2">
<widget class="QTableView" name="FileTableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>180</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>30</number>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>30</number>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<layout class="QGridLayout" name="MenuGridLayout">
<item row="0" column="1">
<widget class="QToolButton" name="AddFilesButton">
<property name="text">
<string>Add Files</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/add.png</normaloff>:/resources/images/add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QToolButton" name="SettingsButton">
<property name="text">
<string>Settings</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/settings.png</normaloff>:/resources/images/settings.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QToolButton" name="ConverButton">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>Audio Converter</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/convert.png</normaloff>:/resources/images/convert.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QToolButton" name="ReloadButton">
<property name="text">
<string>Reload</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/reload.png</normaloff>:/resources/images/reload.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="ExtractButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Extract files</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/extract.png</normaloff>:/resources/images/extract.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QToolButton" name="HelpButton">
<property name="text">
<string>Help</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/help.png</normaloff>:/resources/images/help.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="EncodeButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Encode</string>
</property>
<property name="icon">
<iconset resource="imageresources.qrc">
<normaloff>:/resources/images/encode.png</normaloff>:/resources/images/encode.png</iconset>
</property>
<property name="iconSize">
<size>
<width>100</width>
<height>40</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>70</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
<zorder>FreeSpaceProgressBar</zorder>
<zorder>label_2</zorder>
<zorder>line</zorder>
<zorder>FileTableView</zorder>
<zorder>label_1</zorder>
<zorder>FilesAndFoldersTreeView</zorder>
<zorder>FilesAndFolders_MainPath</zorder>
<zorder>label_0</zorder>
<zorder></zorder>
</widget>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="imageresources.qrc"/>
</resources>
<connections/>
</ui>

177
steghide-src/AUtils.h Normal file
View File

@ -0,0 +1,177 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_AUTILS_H
#define SH_AUTILS_H
#include <cmath>
#ifndef log2
// this is in an #ifndef because some cmath implementations #define log2 and some not
# define log2(x) (log(x) / log(2.0))
#endif
/**
* \class AUtils
* \brief provides some generic functions for non-standard arithmetic operations
**/
class AUtils {
public:
/**
* return the maximum of a and b (needs >)
**/
template<class T> static T max (T a, T b) ;
/**
* return the minimum of a and b (needs <)
**/
template<class T> static T min (T a, T b) ;
/**
* returns a divided through b rounded up to nearest "integer" (needs =, --, +, /)
**/
template<class T> static T div_roundup (T a, T b) ;
/**
* substraction with the modification to return 0 (T()) for negative difference (needs >, -, T())
**/
template<class T> static T bminus (T a, T b) ;
/**
* addition with the modification to return top for sums that are larger than top
**/
template<class T, T top> static T bplus (T a, T b) ;
template<class T> static T bplus (T a, T b, T top) ;
/**
* calculate the sum s[0]+...s[n-1] modulo m (needs =, +, % for T and =, CTYPE(), <, ++ for CTYPE)
**/
template<class T, class CTYPE> static T modsum (T* s, CTYPE n, T m) ;
/**
* round up x to nearest integer
**/
template<class IT, class FT> static IT roundup (FT x) ;
/**
* compute 2-logarithm of n (rounded up to nearest int), i.e. number of bits needed to store values from {0,...,n-1}
**/
template<class T> static T log2_ceil (T n) ;
} ;
template<class T>
T AUtils::max (T a, T b)
{
if (a > b) {
return a ;
}
else {
return b ;
}
}
template<class T>
T AUtils::min (T a, T b)
{
if (a < b) {
return a ;
}
else {
return b ;
}
}
template<class T>
T AUtils::div_roundup (T a, T b)
{
T c = b-- ;
return ((a + b) / c) ;
}
template<class T>
T AUtils::bminus (T a, T b)
{
if (a > b) {
return (a - b) ;
}
else {
return T() ;
}
}
template<class T, T top>
T AUtils::bplus (T a, T b)
{
a += b ;
if (a > top) {
return top ;
}
else {
return a ;
}
}
template<class T>
T AUtils::bplus (T a, T b, T top)
{
a += b ;
if (a > top) {
return top ;
}
else {
return a ;
}
}
template<class T, class CTYPE>
T AUtils::modsum (T* s, CTYPE n, T m)
{
T retval = 0 ;
for (CTYPE i = CTYPE() ; i < n ; ++i) {
retval = (retval + s[i]) % m ;
}
return retval ;
}
template<class IT, class FT>
IT AUtils::roundup (FT x)
{
IT retval = 0 ;
FT intpart = (FT) ((IT) x) ;
if (x - intpart == (FT) 0.0) {
retval = (IT) x ;
}
else {
retval = ((IT) x) + 1 ;
}
return retval ;
}
template<class T>
T AUtils::log2_ceil (T n)
{
T retval = 0 ;
while (n > 1) {
n = div_roundup<T> (n, 2) ;
++retval ;
}
return retval ;
}
#endif // ndef SH_AUTILS_H

35
steghide-src/Arg.cc Normal file
View File

@ -0,0 +1,35 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "Arg.h"
template<class T> Arg<T>::Arg (T v, bool setbyuser)
{
set = false ;
setValue (v, setbyuser) ;
}
template<class T> void Arg<T>::setValue (T v, bool setbyuser)
{
Value = v ;
if (setbyuser) {
set = true ;
}
}

70
steghide-src/Arg.h Normal file
View File

@ -0,0 +1,70 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_ARG_H
#define SH_ARG_H
#include <list>
#include <string>
#include "EncryptionAlgorithm.h"
#include "EncryptionMode.h"
// to include DEBUG if defined
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
template<class T> class Arg {
public:
Arg (void) : set(false) {} ;
Arg (T v, bool setbyuser = true) ;
T getValue (void) const
{ return Value ; } ;
void setValue (T v, bool setbyuser = true) ;
bool is_set (void) const
{ return set ; } ;
private:
T Value ;
bool set ;
} ;
enum COMMAND { EMBED, EXTRACT, INFO, ENCINFO, SHOWVERSION, SHOWLICENSE, SHOWHELP, PRINTFREQS } ;
enum VERBOSITY { QUIET, NORMAL, VERBOSE, STATS } ;
enum DEBUGCOMMAND { NONE, PRINTGRAPH, PRINTGMLGRAPH, PRINTGMLVERTEX } ;
typedef Arg<COMMAND> ArgCommand ;
typedef Arg<VERBOSITY> ArgVerbosity ;
typedef Arg<bool> ArgBool ;
typedef Arg<std::string> ArgString ;
typedef Arg<unsigned long> ArgULong ;
typedef Arg<int> ArgInt ;
typedef Arg<float> ArgFloat ;
typedef Arg<EncryptionAlgorithm> ArgEncAlgo ;
typedef Arg<EncryptionMode> ArgEncMode ;
typedef Arg<unsigned int> ArgUInt ;
typedef Arg<std::list<std::string> > ArgStringList ;
typedef Arg<DEBUGCOMMAND> ArgDebugCommand ;
#endif // ndef SH_ARG_H

823
steghide-src/Arguments.cc Normal file
View File

@ -0,0 +1,823 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstring>
#include <iostream>
#include <string>
#include "MCryptPP.h"
#include "Terminal.h"
#include "common.h"
#include "error.h"
#include "msg.h"
// the global Arguments object
Arguments Args ;
Arguments::Arguments (int argc, char* argv[])
{
bool delete_next = false ;
for (int i = 1 ; i < argc ; ++i) {
TheArguments.push_back (std::string(argv[i])) ;
if (delete_next) {
// overwrite passphrase in argv in order to avoid that it can be read with the ps command
unsigned int len = strlen(argv[i]) ;
for (unsigned int j = 0 ; j < len ; j++) {
argv[i][j] = ' ' ;
}
delete_next = false ;
}
if (std::string(argv[i]) == "-p" || std::string(argv[i]) == "--passphrase") {
delete_next = true ;
}
}
}
void Arguments::parse ()
{
// if there are no arguments -> show help
if (TheArguments.empty()) {
Command.setValue (SHOWHELP) ;
return ;
}
ArgIt curarg = TheArguments.begin() ;
parse_Command (curarg) ;
// parse rest of arguments
while (curarg != TheArguments.end()) {
if (parse_EmbFn(curarg)) continue ;
if (parse_ExtFn(curarg)) continue ;
if (parse_CvrFn(curarg)) continue ;
if (parse_StgFn(curarg)) continue ;
if (parse_Passphrase(curarg)) continue ;
if (parse_Checksum(curarg)) continue ;
if (parse_Compression(curarg)) continue ;
if (parse_EmbedEmbFn(curarg)) continue ;
if (parse_Encryption(curarg)) continue ;
if (parse_Radius(curarg)) continue ;
if (parse_Goal(curarg)) continue ;
if (parse_Force(curarg)) continue ;
if (parse_Verbosity(curarg)) continue ;
if (parse_Debug(curarg)) continue ; // TODO - rename Debug -> Undocumented
throw ArgError (_("unknown argument \"%s\"."), curarg->c_str()) ;
}
// (command-specific) argument post-processing
if (Command.getValue() == EMBED) {
if ((CvrFn.getValue() == "") && (EmbFn.getValue() == "")) {
throw ArgError (_("standard input cannot be used for cover data AND data to be embedded.")) ;
}
if (!StgFn.is_set() && CvrFn.is_set()) {
StgFn.setValue (CvrFn.getValue()) ;
Force.setValue (true) ;
}
}
if (Command.getValue() == EMBED || Command.getValue() == EXTRACT) {
if (!Passphrase.is_set()) {
// prompt for passphrase
if (Command.getValue() == EMBED) {
if ((CvrFn.getValue() == "") || (EmbFn.getValue() == "")) {
throw ArgError (_("if standard input is used, the passphrase must be specified on the command line.")) ;
}
Passphrase.setValue (getPassphrase (true)) ;
}
else if (Command.getValue() == EXTRACT) {
if (StgFn.getValue() == "") {
throw ArgError (_("if standard input is used, the passphrase must be specified on the command line.")) ;
}
Passphrase.setValue (getPassphrase()) ;
}
}
}
}
void Arguments::parse_Command (ArgIt& curarg)
{
CommandString = *curarg ;
if (*curarg == "embed" || *curarg == "--embed") {
Command.setValue (EMBED) ;
setDefaults () ;
++curarg ;
}
else if (*curarg == "extract" || *curarg == "--extract") {
Command.setValue (EXTRACT) ;
setDefaults () ;
++curarg ;
}
else if (*curarg == "info" || *curarg == "--info") {
Command.setValue (INFO) ;
setDefaults() ;
++curarg ;
if (curarg == TheArguments.end()) {
throw ArgError (_("you have to suppy a filename to the \"%s\" command."), CommandString.c_str()) ;
}
else {
parse_Passphrase (curarg) ; // try: maybe -p is first argument
if (*curarg == "-") {
CvrFn.setValue ("") ;
}
else {
CvrFn.setValue (*curarg) ;
}
++curarg ;
if (curarg != TheArguments.end()) {
parse_Passphrase (curarg) ;
}
}
}
else if (*curarg == "encinfo" || *curarg == "--encinfo") {
Command.setValue (ENCINFO) ;
if (TheArguments.size() > 1) {
throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
}
++curarg ;
}
else if (*curarg == "version" || *curarg == "--version") {
Command.setValue (SHOWVERSION) ;
if (TheArguments.size() > 1) {
throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
}
++curarg ;
}
else if (*curarg == "license" || *curarg == "--license") {
Command.setValue (SHOWLICENSE) ;
if (TheArguments.size() > 1) {
throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
}
++curarg ;
}
else if (*curarg == "help" || *curarg == "--help") {
Command.setValue (SHOWHELP) ;
if (TheArguments.size() > 1) {
throw ArgError (_("you cannot use arguments with the \"%s\" command."), CommandString.c_str()) ;
}
++curarg ;
}
#ifdef DEBUG
else if (*curarg == "printfreqs" || *curarg == "--printfreqs") {
Command.setValue (PRINTFREQS) ;
std::list<std::string> flist ;
while ((++curarg) != TheArguments.end()) {
flist.push_back (*curarg) ;
}
FileList.setValue (flist) ;
}
#endif
else {
throw ArgError (_("unknown command \"%s\"."), CommandString.c_str()) ;
}
}
bool Arguments::parse_EmbFn (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-ef" || *curarg == "--embedfile") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (EmbFn.is_set()) {
throw ArgError (_("the \"%s\" argument can be used only once."), (curarg - 1)->c_str()) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the embed file name."), (curarg - 1)->c_str()) ;
}
if (*curarg == "-") {
EmbFn.setValue ("") ;
}
else {
EmbFn.setValue (*curarg) ;
}
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_ExtFn (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-xf" || *curarg == "--extractfile") {
if (Command.getValue() != EXTRACT) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "extract") ;
}
if (ExtFn.is_set()) {
throw ArgError (_("the \"%s\" argument can be used only once."), (curarg - 1)->c_str()) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the extract file name."), (curarg - 1)->c_str()) ;
}
if (*curarg == "-") {
ExtFn.setValue ("") ;
}
else {
ExtFn.setValue (*curarg) ;
}
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_CvrFn (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-cf" || *curarg == "--coverfile") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (CvrFn.is_set()) {
throw ArgError (_("the cover file name argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the cover file name."), (curarg - 1)->c_str()) ;
}
if (*curarg == "-") {
CvrFn.setValue ("") ;
}
else {
CvrFn.setValue (*curarg) ;
}
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_StgFn (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-sf" || *curarg == "--stegofile") {
if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
}
if (StgFn.is_set()) {
throw ArgError (_("the \"%s\" argument can be used only once."), (curarg - 1)->c_str()) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the stego file name."), (curarg - 1)->c_str()) ;
}
if (*curarg == "-") {
StgFn.setValue ("") ;
}
else {
StgFn.setValue (*curarg) ;
}
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Passphrase (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-p" || *curarg == "--passphrase") {
if (Passphrase.is_set()) {
throw ArgError (_("the passphrase argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the passphrase."), (curarg - 1)->c_str());
}
Passphrase.setValue (*curarg) ;
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Checksum (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-K" || *curarg == "--nochecksum") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (Checksum.is_set()) {
throw ArgError (_("the checksum argument can be used only once.")) ;
}
Checksum.setValue (false) ;
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Compression (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-z" || *curarg == "--compress") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"embed\" command."), curarg->c_str()) ;
}
if (Compression.is_set()) {
throw ArgError (_("the compression argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the compression level."), (curarg - 1)->c_str()) ;
}
int tmp = 0 ;
sscanf (curarg->c_str(), "%d", &tmp) ;
if (tmp < 1 || tmp > 9) {
throw ArgError (_("\"%s\" is not a valid compression level."), curarg->c_str()) ;
}
Compression.setValue (tmp) ;
found = true ;
curarg++ ;
}
else if (*curarg == "-Z" || *curarg == "--dontcompress") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (Compression.is_set()) {
throw ArgError (_("the compression argument can be used only once.")) ;
}
Compression.setValue (NoCompression) ;
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_EmbedEmbFn (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-N" || *curarg == "--dontembedname") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"embed\" command."), curarg->c_str()) ;
}
if (EmbedEmbFn.is_set()) {
throw ArgError (_("the file name embedding argument can be used only once.")) ;
}
EmbedEmbFn.setValue (false) ;
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Encryption (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-e" || *curarg == "--encryption") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (EncAlgo.is_set() || EncMode.is_set()) {
throw ArgError (_("the encryption argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by encryption parameters."), (curarg - 1)->c_str()) ;
}
std::string s1, s2 ;
if ((*curarg)[0] == '-') {
throw ArgError (_("the \"%s\" argument must be followed by encryption parameters."), (curarg - 1)->c_str()) ;
}
else {
s1 = *curarg ;
if (curarg + 1 == TheArguments.end()) {
s2 = "" ;
}
else {
if ((*(curarg + 1))[0] == '-') {
s2 = "" ;
}
else {
++curarg ; // set to second encryption specifier
s2 = *curarg ;
}
}
}
if (s1 == "none" && s2 == "") {
EncAlgo.setValue (s1) ;
}
#ifdef USE_LIBMCRYPT
else {
bool s1_isalgo = false, s1_ismode = false ;
bool s2_isalgo = false, s2_ismode = false ;
if (s1 != "") {
s1_isalgo = EncryptionAlgorithm::isValidStringRep (s1) ;
s1_ismode = EncryptionMode::isValidStringRep (s1) ;
myassert (!(s1_isalgo && s1_ismode)) ;
if (!(s1_isalgo || s1_ismode)) {
throw SteghideError (_("\"%s\" is neither an algorithm nor a mode supported by libmcrypt."), s1.c_str()) ;
}
}
if (s2 != "") {
s2_isalgo = EncryptionAlgorithm::isValidStringRep (s2) ;
s2_ismode = EncryptionMode::isValidStringRep (s2) ;
myassert (!(s2_isalgo && s2_ismode)) ;
if (!(s2_isalgo || s2_ismode)) {
throw SteghideError (_("\"%s\" is neither an algorithm nor a mode supported by libmcrypt."), s2.c_str()) ;
}
}
if (s1_isalgo && s2_isalgo) {
throw SteghideError (_("\"%s\" and \"%s\" are both libmcrypt algorithms. please specify only one."), s1.c_str(), s2.c_str()) ;
}
if (s1_ismode && s2_ismode) {
throw SteghideError (_("\"%s\" and \"%s\" are both libmcrypt modes. please specify only one."), s1.c_str(), s2.c_str()) ;
}
if (s1_isalgo) {
EncAlgo.setValue (s1) ;
}
if (s1_ismode) {
EncMode.setValue (s1) ;
}
if (s2_isalgo) {
EncAlgo.setValue (s2) ;
}
if (s2_ismode) {
EncMode.setValue (s2) ;
}
if (!MCryptPP::AlgoSupportsMode (EncAlgo.getValue(), EncMode.getValue())) {
throw SteghideError (_("the encryption algorithm \"%s\" can not be used with the mode \"%s\"."),
EncAlgo.getValue().getStringRep().c_str(), EncMode.getValue().getStringRep().c_str()) ;
}
}
#else
else {
throw SteghideError (_("steghide has been compiled without support for encryption.")) ;
}
#endif // def USE_LIBMCRYPT
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Radius (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-r" || *curarg == "--radius") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (Radius.is_set()) {
throw ArgError (_("the radius argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the neighbourhood radius."), (curarg - 1)->c_str()) ;
}
unsigned long tmp = 0 ;
sscanf (curarg->c_str(), "%lu", &tmp) ;
Radius.setValue (tmp) ;
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Goal (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-g" || *curarg == "--goal") {
if (Command.getValue() != EMBED) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" command."), curarg->c_str(), "embed") ;
}
if (Goal.is_set()) {
throw ArgError (_("the goal argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by a number between 0 and 100."), (curarg - 1)->c_str()) ;
}
float tmp = 0 ;
sscanf (curarg->c_str(), "%f", &tmp) ;
if (tmp < 0 || tmp > 100) {
throw ArgError (_("the \"%s\" argument must be followed by a number between 0 and 100."), (curarg - 1)->c_str()) ;
}
Goal.setValue (tmp) ;
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Force (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-f" || *curarg == "--force") {
if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
}
if (Force.is_set()) {
throw ArgError (_("the force argument can be used only once.")) ;
}
Force.setValue (true);
found = true ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Verbosity (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "-q" || *curarg == "--quiet") {
found = true ;
if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
}
if (Verbosity.is_set()) {
throw ArgError (_("the \"%s\" argument cannot be used here because the verbosity has already been set."), curarg->c_str()) ;
}
Verbosity.setValue (QUIET) ;
curarg++ ;
}
else if (*curarg == "-v" || *curarg == "--verbose") {
found = true ;
if (Command.getValue() != EMBED && Command.getValue() != EXTRACT) {
throw ArgError (_("the argument \"%s\" can only be used with the \"%s\" and \"%s\" commands."), curarg->c_str(), "embed", "extract") ;
}
if (Verbosity.is_set()) {
throw ArgError (_("the \"%s\" argument cannot be used here because the verbosity has already been set."), curarg->c_str()) ;
}
Verbosity.setValue (VERBOSE) ;
curarg++ ;
}
return found ;
}
bool Arguments::parse_Debug (ArgIt& curarg)
{
bool found = false ;
if (*curarg == "--printgraph") {
if (DebugCommand.is_set()) {
throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
}
DebugCommand.setValue (PRINTGRAPH) ;
found = true ;
curarg++ ;
}
else if (*curarg == "--printgmlgraph") {
if (DebugCommand.is_set()) {
throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
}
DebugCommand.setValue (PRINTGMLGRAPH) ;
found = true ;
curarg++ ;
}
else if (*curarg == "--printgmlvertex") {
if (DebugCommand.is_set()) {
throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
}
DebugCommand.setValue (PRINTGMLVERTEX) ;
curarg++ ;
int tmp = 0 ;
sscanf (curarg->c_str(), "%d", &tmp) ;
GmlGraphRecDepth.setValue (tmp) ;
curarg++ ;
sscanf (curarg->c_str(), "%d", &tmp) ;
GmlStartVertex.setValue (tmp) ;
found = true ;
curarg++ ;
}
else if (*curarg == "--printstats") {
if (DebugCommand.is_set()) {
throw SteghideError (_("you cannot use more than one debug command at a time.")) ;
}
if (Verbosity.is_set()) {
throw ArgError (_("the \"%s\" argument cannot be used here because the verbosity has already been set."), curarg->c_str()) ;
}
Verbosity.setValue (STATS) ;
found = true ;
++curarg ;
}
else if (*curarg == "--debuglevel") {
if (DebugLevel.is_set()) {
throw ArgError (_("the debug level argument can be used only once.")) ;
}
if (++curarg == TheArguments.end()) {
throw ArgError (_("the \"%s\" argument must be followed by the debug level."), (curarg - 1)->c_str()) ;
}
unsigned int tmp = 0 ;
sscanf (curarg->c_str(), "%u", &tmp) ;
DebugLevel.setValue (tmp) ;
found = true ;
++curarg ;
}
else if (*curarg == "--check") {
// TODO usual error checking (omitted due to message freeze)
Check.setValue (true) ;
found = true ;
++curarg ;
}
return found ;
}
std::string Arguments::getPassphrase (bool doublecheck)
{
int c = EOF ;
#ifndef HAVE_TERMIOS_H
Warning w (_("unknown terminal. the passphrase you type now will be visible.")) ;
w.printMessage() ;
#endif
std::cerr << _("Enter passphrase: ") ;
Terminal term ;
term.EchoOff() ;
std::string s1 = "" ;
while ((c = std::cin.get()) != '\n') {
s1 += c ;
}
term.reset() ;
std::cerr << std::endl ;
if (doublecheck) {
std::cerr << _("Re-Enter passphrase: ") ;
term.EchoOff() ;
std::string s2 = "" ;
while ((c = std::cin.get()) != '\n') {
s2 += c ;
}
term.reset() ;
std::cerr << std::endl ;
if (s1 != s2) {
throw SteghideError (_("the passphrases do not match.")) ;
}
}
return s1 ;
}
bool Arguments::stdin_isused () const
{
bool retval = false ;
if (Command.getValue() == EMBED && (EmbFn.getValue() == "" || CvrFn.getValue() == "")) {
retval = true ;
}
else if (Command.getValue() == EXTRACT && StgFn.getValue() == "") {
retval = true ;
}
else if (Command.getValue() == INFO && CvrFn.getValue() == "") {
retval = true ;
}
return retval ;
}
void Arguments::setDefaults (void)
{
myassert (Command.is_set()) ;
EmbFn.setValue ("", false) ;
CvrFn.setValue ("", false) ;
EncAlgo.setValue (Default_EncAlgo, false) ;
EncMode.setValue (Default_EncMode, false) ;
Checksum.setValue (Default_Checksum, false) ;
Compression.setValue (Default_Compression, false) ;
EmbedEmbFn.setValue (Default_EmbedEmbFn, false) ;
ExtFn.setValue ("", false) ;
Passphrase.setValue ("", false) ;
StgFn.setValue ("", false) ;
Force.setValue (Default_Force, false) ;
Verbosity.setValue (Default_Verbosity, false) ;
Radius.setValue (Default_Radius, false) ;
Goal.setValue (Default_Goal, false) ;
Check.setValue (Default_Check, false) ;
DebugCommand.setValue (Default_DebugCommand, false) ;
DebugLevel.setValue (Default_DebugLevel, false) ;
GmlGraphRecDepth.setValue (Default_GmlGraphRecDepth, false) ;
GmlStartVertex.setValue (Default_GmlStartVertex, false) ;
}
#ifdef USE_LIBMCRYPT
const EncryptionAlgorithm Arguments::Default_EncAlgo = EncryptionAlgorithm (EncryptionAlgorithm::RIJNDAEL128) ;
const EncryptionMode Arguments::Default_EncMode = EncryptionMode (EncryptionMode::CBC) ;
#else
const EncryptionAlgorithm Arguments::Default_EncAlgo = EncryptionAlgorithm (EncryptionAlgorithm::NONE) ;
const EncryptionMode Arguments::Default_EncMode = EncryptionMode (EncryptionMode::ECB) ; // is ignored
#endif

146
steghide-src/Arguments.h Normal file
View File

@ -0,0 +1,146 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_ARGUMENTS_H
#define SH_ARGUMENTS_H
#include <string>
#include <vector>
#include "Arg.h"
// to include DEBUG if defined
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/**
* \class Arguments
* \brief parsing and data representation of command-line arguments
**/
class Arguments {
public:
Arguments (void) {} ;
/**
* initialize this Arguments object with argc and argv
**/
Arguments (int argc, char *argv[]) ;
/**
* parse Argc and Argv filling the Arg* member variable for later access
**/
void parse (void) ;
/**
* is standard input used ? - according to the given arguments
**/
bool stdin_isused (void) const ;
/// the command to be executed in this session
ArgCommand Command ;
/// the name of the command to be executed in this session (as supplied by the user)
std::string CommandString ;
/// the embed file name, "" if stdin
ArgString EmbFn ;
/// the extract file name, "" if stdout
ArgString ExtFn ;
/// the cover file name, "" if stdin
ArgString CvrFn ;
/// the stego file name, "" if stdout/stdin
ArgString StgFn ;
ArgString Passphrase ;
ArgBool Checksum ;
ArgInt Compression ;
ArgBool EmbedEmbFn ;
ArgEncAlgo EncAlgo ;
ArgEncMode EncMode ;
ArgULong Radius ;
ArgFloat Goal ;
ArgBool Force ;
ArgVerbosity Verbosity ;
ArgDebugCommand DebugCommand ;
ArgBool Check ;
ArgStringList FileList ;
ArgUInt DebugLevel ;
ArgUInt GmlGraphRecDepth ;
ArgUInt GmlStartVertex ;
std::string getPassphrase (bool doublecheck = false) ;
private:
typedef std::vector<std::string>::const_iterator ArgIt ;
static const int NoCompression = 0 ;
static const EncryptionAlgorithm Default_EncAlgo ;
static const EncryptionMode Default_EncMode ;
static const bool Default_Checksum = true ;
static const int Default_Compression = 9 ; // slowest, but smallest
static const bool Default_EmbedEmbFn = true ;
static const bool Default_Force = false ;
static const VERBOSITY Default_Verbosity = NORMAL ;
static const unsigned long Default_Radius = 0 ; // there is no default radius for all file formats
static const unsigned int Max_Algorithm = 3 ;
static const float Default_Goal = 100.0 ;
static const DEBUGCOMMAND Default_DebugCommand = NONE ;
static const bool Default_Check = false ;
static const unsigned int Default_DebugLevel = 0 ;
static const unsigned int Default_GmlGraphRecDepth = 0 ;
static const unsigned int Default_GmlStartVertex = 0 ;
/**
* parse the command
*
* Note: parse_Command is the only parse_* function that requires curarg to be a command.
* (because the command is the only argument with a fixed position).
**/
void parse_Command (ArgIt& curarg) ;
/**
* test if curarg points to an emb filename argument and if yes: parse it
* \return true iff one or more arguments have been parsed
**/
bool parse_EmbFn (ArgIt& curarg) ;
bool parse_ExtFn (ArgIt& curarg) ;
bool parse_CvrFn (ArgIt& curarg) ;
bool parse_StgFn (ArgIt& curarg) ;
bool parse_Passphrase (ArgIt& curarg) ;
bool parse_Checksum (ArgIt& curarg) ;
bool parse_Compression (ArgIt& curarg) ;
bool parse_EmbedEmbFn (ArgIt& curarg) ;
bool parse_Encryption (ArgIt& curarg) ;
bool parse_Radius (ArgIt& curarg) ;
bool parse_Goal (ArgIt& curarg) ;
bool parse_Force (ArgIt& curarg) ;
bool parse_Verbosity (ArgIt& curarg) ;
bool parse_Debug (ArgIt& curarg) ;
void setDefaults (void) ;
std::vector<std::string> TheArguments ;
} ;
// gcc does not support the export keyword
#include "Arg.cc"
#endif /* ndef SH_ARGUMENTS_H */

View File

@ -0,0 +1,52 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstring>
#include "AssertionFailed.h"
void AssertionFailed::printMessage () const
{
printf ("\n") ;
SteghideError::printMessage() ;
printf (_("This means that you have found a bug. Please let me (shetzl@chello.at)\n"
"know this if you have a way to reproduce the error.\n"
"Steghide has to exit now. Sorry.\n")) ;
}
char* AssertionFailed::stripDir (const char *fn)
{
int i = 0, j = 0, start = 0, end = 0 ;
end = i = strlen (fn) - 1 ;
while ((i >= 0) && (fn[i] != '\\') && (fn[i] != '/')) {
i-- ;
}
start = i + 1 ;
char* retval = (char *) malloc (end - start + 2) ;
j = 0 ;
for (i = start ; i <= end ; i++, j++) {
retval[j] = fn [i] ;
}
retval[j] = '\0' ;
return retval ;
}

View File

@ -0,0 +1,38 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_ASSERTIONFAILED_H
#define SH_ASSERTIONFAILED_H
#include "common.h"
#include "SteghideError.h"
class AssertionFailed : public SteghideError {
public:
AssertionFailed (const char* fn, unsigned int l)
: SteghideError(_("assertion failed in %s at line number %d."), stripDir(fn), l) {} ;
void printMessage (void) const ;
private:
char* stripDir (const char* fn) ;
} ;
#endif // ndef SH_ASSERTION_FAILED

55
steghide-src/AuData.h Normal file
View File

@ -0,0 +1,55 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_AUDATA_H
#define SH_AUDATA_H
#include "BinaryIO.h"
#include "AudioData.h"
// AuMuLawAudioData
typedef AudioDataImpl<AuMuLaw,BYTE> AuMuLawAudioData ;
template<>
inline BYTE AuMuLawAudioData::readValue (BinaryIO* io) const { return (io->read8()) ; }
template<>
inline void AuMuLawAudioData::writeValue (BinaryIO* io, BYTE v) const { io->write8(v) ; }
// AuPCM8AudioData
typedef AudioDataImpl<AuPCM8,SBYTE> AuPCM8AudioData ;
template<>
inline SBYTE AuPCM8AudioData::readValue (BinaryIO* io) const { return ((SBYTE) io->read8()) ; }
template<>
inline void AuPCM8AudioData::writeValue (BinaryIO* io, SBYTE v) const { io->write8((BYTE) v) ; }
// AuPCM16AudioData
typedef AudioDataImpl<AuPCM16,SWORD16> AuPCM16AudioData ;
template<>
inline SWORD16 AuPCM16AudioData::readValue (BinaryIO* io) const { return ((SWORD16) io->read16_be()) ; }
template<>
inline void AuPCM16AudioData::writeValue (BinaryIO* io, SWORD16 v) const { io->write16_be((UWORD16) v) ; }
// AuPCM32AudioData
typedef AudioDataImpl<AuPCM32,SWORD32> AuPCM32AudioData ;
template<>
inline SWORD32 AuPCM32AudioData::readValue (BinaryIO* io) const { return ((SWORD32) io->read32_be()) ; }
template<>
inline void AuPCM32AudioData::writeValue (BinaryIO* io, SWORD32 v) const { io->write32_be((UWORD32) v) ; }
#endif // ndef SH_AUDATA_H

230
steghide-src/AuFile.cc Normal file
View File

@ -0,0 +1,230 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include "AuData.h"
#include "AuFile.h"
#include "AuSampleValues.h"
#include "CvrStgFile.h"
#include "CvrStgObject.h"
#include "DFSAPHeuristic.h"
#include "SMDConstructionHeuristic.h"
#include "common.h"
#include "error.h"
AuFile::AuFile (BinaryIO *io)
: CvrStgFile()
{
setSamplesPerVertex (SamplesPerVertex) ;
setEmbValueModulus (EmbValueModulus) ;
read (io) ;
}
AuFile::~AuFile (void)
{
delete Data ;
}
void AuFile::read (BinaryIO *io)
{
CvrStgFile::read (io) ;
try {
Header.id[0] = '.' ;
Header.id[1] = 's' ;
Header.id[2] = 'n' ;
Header.id[3] = 'd' ;
// read header
Header.offset = getBinIO()->read32_be() ;
Header.size = getBinIO()->read32_be() ;
UWORD32 encoding = getBinIO()->read32_be() ;
Header.samplerate = getBinIO()->read32_be() ;
Header.channels = getBinIO()->read32_be() ;
// read infofield
unsigned long leninfofield = Header.offset - AuHeader::HeaderSize ;
if (leninfofield > 0) {
Infofield.resize (leninfofield) ;
for (unsigned long i = 0 ; i < leninfofield ; i++) {
Infofield[i] = getBinIO()->read8() ;
}
}
// read data
switch (encoding) {
case MULAW8:
setRadius (Radius_MuLaw8) ;
Data = new AuMuLawAudioData (this) ;
break ;
case PCM8:
setRadius (Radius_PCM8) ;
Data = new AuPCM8AudioData (this) ;
break ;
case PCM16:
setRadius (Radius_PCM16) ;
Data = new AuPCM16AudioData (this) ;
break ;
default:
if (getBinIO()->is_std()) {
throw NotImplementedError (_("the au file on standard input uses the unkown encoding %d."), encoding) ;
}
else {
throw NotImplementedError (_("the au file \"%s\" uses the unknown encoding %d."), getBinIO()->getName().c_str(), encoding) ;
}
break ;
} ;
Header.encoding = (ENCODING) encoding ;
}
catch (BinaryInputError e) {
switch (e.getType()) {
case BinaryInputError::FILE_ERR:
{
throw SteghideError (_("an error occured while reading the au headers from the file \"%s\"."), getBinIO()->getName().c_str()) ;
break ;
}
case BinaryInputError::FILE_EOF:
{
throw SteghideError (_("premature end of file \"%s\" while reading au headers."), getBinIO()->getName().c_str()) ;
break ;
}
case BinaryInputError::STDIN_ERR:
{
throw SteghideError (_("an error occured while reading the au headers from standard input.")) ;
break ;
}
case BinaryInputError::STDIN_EOF:
{
throw SteghideError (_("premature end of data from standard input while reading au headers.")) ;
break ;
}
}
}
// if available, use size of audio data, else read until eof
unsigned long n = AudioData::NoLimit ;
if (Header.size != AuHeader::SizeUnknown) {
myassert (Header.size % Header.getBytesPerSample() == 0) ;
n = Header.size / Header.getBytesPerSample() ;
}
Data->read (getBinIO(), n) ;
}
void AuFile::write ()
{
CvrStgFile::write() ;
try {
// write header
getBinIO()->write8 (Header.id[0]) ;
getBinIO()->write8 (Header.id[1]) ;
getBinIO()->write8 (Header.id[2]) ;
getBinIO()->write8 (Header.id[3]) ;
getBinIO()->write32_be (Header.offset) ;
getBinIO()->write32_be (Header.size) ;
getBinIO()->write32_be ((UWORD32) Header.encoding) ;
getBinIO()->write32_be (Header.samplerate) ;
getBinIO()->write32_be (Header.channels) ;
// write infofield
for (unsigned long i = 0 ; i < Infofield.size() ; i++) {
getBinIO()->write8 (Infofield[i]) ;
}
}
catch (BinaryOutputError e) {
switch (e.getType()) {
case BinaryOutputError::FILE_ERR:
{
throw SteghideError (_("an error occured while writing the au headers to the file \"%s\"."), getBinIO()->getName().c_str()) ;
break ;
}
case BinaryOutputError::STDOUT_ERR:
{
throw SteghideError (_("an error occured while writing the au headers to standard output.")) ;
break ;
}
}
}
Data->write (getBinIO(), AudioData::NoLimit) ;
}
std::list<CvrStgFile::Property> AuFile::getProperties () const
{
std::list<CvrStgFile::Property> retval ;
// format
std::string formatstring = "au audio" ;
switch (Header.encoding) {
case MULAW8:
formatstring += _(", mu-law encoding") ;
break ;
case PCM8:
case PCM16:
formatstring += _(", PCM encoding") ;
break ;
}
retval.push_back (CvrStgFile::Property (_("format"), formatstring)) ;
return retval ;
}
unsigned short AuFile::AuHeader::getBytesPerSample () const
{
unsigned short retval = 0 ;
switch (encoding) {
case MULAW8:
retval = 1 ;
break ;
case PCM8:
retval = 1 ;
break ;
case PCM16:
retval = 2 ;
break ;
default:
myassert(0) ;
break ;
}
return retval ;
}
std::vector<MatchingAlgorithm*> AuFile::getMatchingAlgorithms (Graph* g, Matching* m) const
{
std::vector<MatchingAlgorithm*> retval ;
retval.push_back (new SMDConstructionHeuristic (g, m)) ;
retval.push_back (new DFSAPHeuristic (g, m)) ;
return retval ;
}

83
steghide-src/AuFile.h Normal file
View File

@ -0,0 +1,83 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_AUFILE_H
#define SH_AUFILE_H
#include <vector>
#include "AudioData.h"
#include "CvrStgFile.h"
class BinaryIO ;
/**
* \class AuFile
* \brief a CvrStgFile in Sun .au format
**/
class AuFile : public CvrStgFile {
public:
AuFile (BinaryIO *io) ;
~AuFile (void) ;
void read (BinaryIO *io) ;
void write (void) ;
std::list<CvrStgFile::Property> getProperties (void) const ;
std::vector<MatchingAlgorithm*> getMatchingAlgorithms (Graph* g, Matching* m) const ;
unsigned long getNumSamples (void) const
{ return Data->getNumSamples() ; } ;
void replaceSample (const SamplePos pos, const SampleValue* s)
{ return Data->replaceSample(pos, s) ; } ;
SampleValue* getSampleValue (SamplePos pos) const
{ return Data->getSampleValue(pos) ; } ;
private:
enum ENCODING { MULAW8 = 1, PCM8 = 2, PCM16 = 3 } ;
class AuHeader {
public:
char id[4] ;
UWORD32 offset ;
UWORD32 size ;
ENCODING encoding ;
UWORD32 samplerate ;
UWORD32 channels ;
static const UWORD32 SizeUnknown = 0xFFFFFFFF ;
static const unsigned short HeaderSize = 24 ;
unsigned short getBytesPerSample (void) const ;
} ;
static const UWORD32 Radius_MuLaw8 = 1 ;
static const UWORD32 Radius_PCM8 = 1 ;
static const UWORD32 Radius_PCM16 = 20 ;
static const unsigned short SamplesPerVertex = 2 ;
static const EmbValue EmbValueModulus = 2 ;
AuHeader Header ;
std::vector<BYTE> Infofield ;
AudioData* Data ;
} ;
#endif /* ndef SH_AUFILE_H */

View File

@ -0,0 +1,45 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "AuSampleValues.h"
// AuMuLawSampleValue
template<>
const BYTE AuMuLawSampleValue::MinValue = 0 ;
template<>
const BYTE AuMuLawSampleValue::MaxValue = BYTE_MAX ;
// AuPCM8SampleValue
template<>
const SBYTE AuPCM8SampleValue::MinValue = SBYTE_MIN ;
template<>
const SBYTE AuPCM8SampleValue::MaxValue = SBYTE_MAX ;
// AuPCM16SampleValue
template<>
const SWORD16 AuPCM16SampleValue::MinValue = SWORD16_MIN ;
template<>
const SWORD16 AuPCM16SampleValue::MaxValue = SWORD16_MAX ;
// AuPCM32SampleValue
template<>
const SWORD32 AuPCM32SampleValue::MinValue = SWORD32_MIN ;
template<>
const SWORD32 AuPCM32SampleValue::MaxValue = SWORD32_MAX ;

View File

@ -0,0 +1,31 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_AUSAMPLEVALUES_H
#define SH_AUSAMPLEVALUES_H
#include "AudioSampleValue.h"
typedef AudioSampleValue<AuMuLaw,BYTE> AuMuLawSampleValue ;
typedef AudioSampleValue<AuPCM8,SBYTE> AuPCM8SampleValue ;
typedef AudioSampleValue<AuPCM16,SWORD16> AuPCM16SampleValue ;
typedef AudioSampleValue<AuPCM32,SWORD32> AuPCM32SampleValue ;
#endif // ndef SH_AUSAMPLEVALUES_H

169
steghide-src/AudioData.h Normal file
View File

@ -0,0 +1,169 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_AUDIODATA_H
#define SH_AUDIODATA_H
#include <vector>
#include "AudioSampleValue.h"
class BinaryIO ;
#include "CvrStgObject.h"
/**
* \class AudioData
* \brief interface definition for AudioData objects.
*
* This class is necessary to provide one common base class for all types
* of audio data, i.e. all different instances of AudioDataImpl.
**/
class AudioData : public CvrStgObject {
public:
/// constant that can be used as parameter to read and write to indicate that there is no limit
static const UWORD32 NoLimit = 0 ;
virtual void read (BinaryIO* io, UWORD32 n = NoLimit) = 0 ;
virtual void write (BinaryIO* io, UWORD32 n = NoLimit) = 0 ;
} ;
/**
* \class AudioDataImpl
* \brief implementation of the AudioData-Interface
**/
template<AUDIOSAMPLETYPE Type, class ValueType, class SampleValueType = AudioSampleValue<Type,ValueType> >
class AudioDataImpl : public AudioData {
public:
AudioDataImpl (CvrStgFile* f) : TheCvrStgFile(f) {} ;
virtual ~AudioDataImpl (void) {} ;
void read (BinaryIO* io, UWORD32 n = AudioData::NoLimit) ;
void write (BinaryIO* io, UWORD32 n = AudioData::NoLimit) ;
unsigned long getNumSamples (void) const ;
SampleValue* getSampleValue (const SamplePos pos) const ;
void replaceSample (const SamplePos pos, const SampleValue* s) ;
private:
std::vector<ValueType> Data ;
CvrStgFile* TheCvrStgFile ;
ValueType readValue (BinaryIO* io) const ;
void writeValue (BinaryIO* io, ValueType v) const ;
} ;
#include "error.h"
template<AUDIOSAMPLETYPE Type, class ValueType, class SampleValueType>
void AudioDataImpl<Type,ValueType,SampleValueType>::read (BinaryIO* io, UWORD32 n)
{
try {
if (n == NoLimit) {
Data.clear() ;
while (!io->eof()) {
Data.push_back (readValue(io)) ;
}
}
else {
Data.resize (n) ;
for (UWORD32 i = 0 ; i < n ; i++) {
Data[i] = readValue(io) ;
}
}
}
catch (BinaryInputError e) {
switch (e.getType()) {
case BinaryInputError::FILE_ERR:
{
throw SteghideError (_("an error occured while reading the audio data from the file \"%s\"."), io->getName().c_str()) ;
break ;
}
case BinaryInputError::FILE_EOF:
{
throw SteghideError (_("premature end of file \"%s\" while reading audio data."), io->getName().c_str()) ;
break ;
}
case BinaryInputError::STDIN_ERR:
{
throw SteghideError (_("an error occured while reading the audio data from standard input.")) ;
break ;
}
case BinaryInputError::STDIN_EOF:
{
throw SteghideError (_("premature end of data from standard input while reading audio data.")) ;
break ;
}
}
}
}
template<AUDIOSAMPLETYPE Type, class ValueType, class SampleValueType>
void AudioDataImpl<Type,ValueType,SampleValueType>::write (BinaryIO* io, UWORD32 n)
{
try {
if (n == NoLimit) {
n = Data.size() ;
}
for (UWORD32 i = 0 ; i < n ; i++) {
writeValue (io, Data[i]) ;
}
}
catch (BinaryOutputError e) {
switch (e.getType()) {
case BinaryOutputError::FILE_ERR:
{
throw SteghideError (_("an error occured while writing the audio data to the file \"%s\"."), io->getName().c_str()) ;
break ;
}
case BinaryOutputError::STDOUT_ERR:
{
throw SteghideError (_("an error occured while writing the audio data to standard output.")) ;
break ;
}
}
}
}
template<AUDIOSAMPLETYPE Type, class ValueType, class SampleValueType>
unsigned long AudioDataImpl<Type,ValueType,SampleValueType>::getNumSamples (void) const
{
return Data.size() ;
}
template<AUDIOSAMPLETYPE Type, class ValueType, class SampleValueType>
SampleValue* AudioDataImpl<Type,ValueType,SampleValueType>::getSampleValue (const SamplePos pos) const
{
myassert (pos < Data.size()) ;
return ((SampleValue*) new SampleValueType (Data[pos])) ;
}
template<AUDIOSAMPLETYPE Type, class ValueType, class SampleValueType>
void AudioDataImpl<Type,ValueType,SampleValueType>::replaceSample (const SamplePos pos, const SampleValue* s)
{
const SampleValueType* sample = dynamic_cast<const SampleValueType*> (s) ;
myassert (sample) ;
myassert (pos < Data.size()) ;
Data[pos] = sample->getValue() ;
}
#endif // ndef SH_AUDIODATA_H

View File

@ -0,0 +1,136 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_AUDIOSAMPLEVALUE_H
#define SH_AUDIOSAMPLEVALUE_H
#include "CvrStgFile.h"
#include "SampleValue.h"
#include "common.h"
/**
* An enumeration containing all audio sample types. This enumeration
* is used as template parameter for AudioSampleValue and AudioData to
* identify the correct implementation for a given audio format.
**/
enum AUDIOSAMPLETYPE {
/// au 8 Bit mu-law
AuMuLaw,
/// au 8 Bit linear pcm
AuPCM8,
/// au 16 Bit linear pcm
AuPCM16,
/// au 32 Bit linear pcm
AuPCM32
} ;
/**
* \class AudioSampleValue
* \brief a class representing an audio sample
**/
template<AUDIOSAMPLETYPE Type, class ValueType>
class AudioSampleValue : public SampleValue {
public:
AudioSampleValue (ValueType v) ;
ValueType getValue (void) const { return Value ; } ;
SampleValue* getNearestTargetSampleValue (EmbValue t) const ;
UWORD32 calcDistance (const SampleValue* s) const ;
std::string getName (void) const ;
private:
ValueType Value ;
static const ValueType MinValue ;
static const ValueType MaxValue ;
UWORD32 calcKey (ValueType v) const { return (v - MinValue) ; } ;
EmbValue calcEValue (ValueType v) const { return ((EmbValue) ((v - MinValue) % Globs.TheCvrStgFile->getEmbValueModulus())) ; } ;
} ;
template<AUDIOSAMPLETYPE Type, class ValueType>
AudioSampleValue<Type,ValueType>::AudioSampleValue (ValueType v)
: SampleValue(), Value(v)
{
Key = calcKey(v) ;
EValue = calcEValue(v) ;
}
template<AUDIOSAMPLETYPE Type, class ValueType>
UWORD32 AudioSampleValue<Type,ValueType>::calcDistance (const SampleValue* s) const
{
const AudioSampleValue<Type,ValueType>* sample = (const AudioSampleValue<Type,ValueType>*) s ;
/* If s is not a correct AudioSampleValue then we get into real trouble here.
But calcDistance is called very often, a dynamic_cast costs a lot of time and
it does not make sense to pass anything but a correct AudioSampleValue as s anyway. */
if (sample->Value > Value) {
return sample->Value - Value ;
}
else {
return Value - sample->Value ;
}
}
template<AUDIOSAMPLETYPE Type, class ValueType>
SampleValue* AudioSampleValue<Type,ValueType>::getNearestTargetSampleValue (EmbValue t) const
{
ValueType val_up = Value, val_down = Value, newval = 0 ;
bool found = false ;
do {
if (val_up < MaxValue) {
val_up++ ;
}
if (val_down > MinValue) {
val_down-- ;
}
if (calcEValue(val_up) == t && calcEValue(val_down) == t) {
if (RndSrc.getBool()) {
newval = val_up ;
}
else {
newval = val_down ;
}
found = true ;
}
else if (calcEValue(val_up) == t) {
newval = val_up ;
found = true ;
}
else if (calcEValue(val_down) == t) {
newval = val_down ;
found = true ;
}
} while (!found) ;
return ((SampleValue *) new AudioSampleValue<Type,ValueType> (newval)) ;
}
template<AUDIOSAMPLETYPE Type, class ValueType>
std::string AudioSampleValue<Type,ValueType>::getName (void) const
{
char buf[128] ;
sprintf (buf, "%ld", (long) Value) ;
return std::string (buf) ;
}
#endif // ndef SH_AUDIOSAMPLEVALUE_H

View File

@ -0,0 +1,154 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "BFSAPHeuristic.h"
#include "Edge.h"
#include "EdgeIterator.h"
#include "Graph.h"
#include "Matching.h"
#include "common.h"
BFSAPHeuristic::BFSAPHeuristic (Graph* g, Matching* m)
: MatchingAlgorithm (g, m, 100.0)
{
unsigned long numvertices = g->getNumVertices() ;
VertexVisited = new bool[numvertices] ;
BackEdge = new Edge[numvertices] ;
for (VertexLabel l = 0 ; l < numvertices ; l++) {
VertexVisited[l] = false ;
}
}
BFSAPHeuristic::~BFSAPHeuristic ()
{
delete[] VertexVisited ;
delete[] BackEdge ;
}
void BFSAPHeuristic::run ()
{
const Edge** path = new const Edge*[TheGraph->getNumVertices()] ;
const std::list<Vertex*> ExposedVertices = TheMatching->getExposedVertices() ;
for (std::list<Vertex*>::const_iterator expv = ExposedVertices.begin() ;
(expv != ExposedVertices.end()) && (TheMatching->getCardinality() < CardinalityGoal) ; expv++) {
if (TheMatching->isExposed (*expv)) {
unsigned long pathlength = searchAugmentingPath (*expv, path) ;
#ifdef DEBUG
if (pathlength == 0) {
printDebug (5, "BFSAPHeuristic: could not find augmenting path for vertex %lu", (*expv)->getLabel()) ;
}
else {
if (RUNDEBUGLEVEL(5)) {
std::cerr << "BFSAPHeuristic: found augmenting path for vertex " << (*expv)->getLabel() << ": " ;
for (unsigned long i = 0 ; i < pathlength ; i++) {
std::cerr << path[i]->getVertex1()->getLabel() << "-" << path[i]->getVertex2()->getLabel() ;
if (i != pathlength - 1) {
std::cerr << ", " ;
}
}
std::cerr << std::endl ;
}
}
#endif
if (pathlength > 0) {
TheMatching->augment ((const Edge**) path, pathlength) ;
}
}
}
delete[] path ;
}
unsigned long BFSAPHeuristic::searchAugmentingPath (Vertex *v0, const Edge** path)
{
#ifdef DEBUG
printDebug (5, "BFSAPHeuristic: starting search for augmenting path from vertex %lu", v0->getLabel()) ;
#endif
unsigned long pathlen = 0 ;
bool foundap = false ;
std::list<Vertex*> srclist ;
std::list<Vertex*> destlist ;
srclist.push_back (v0) ;
VertexVisited[v0->getLabel()] = true ;
for (unsigned int depth = 0 ; !foundap && !srclist.empty() ; depth++) {
myassert (destlist.empty()) ;
// for all vertices v1 in srclist...
for (std::list<Vertex*>::const_iterator vit = srclist.begin() ; vit != srclist.end() && !foundap ; vit++) {
Vertex* v1 = *vit ;
#ifdef DEBUG
printDebug (6, "BFSAPHeuristic: starting search iteration from vertex %lu", v1->getLabel()) ;
#endif
// ...iterate through all...
EdgeIterator edgeit (v1) ;
while (!edgeit.isFinished() && !foundap) {
Edge e = **edgeit ;
// ...unmatched edges of v1
if (!TheMatching->includesEdge(e)) {
Vertex* v2 = e.getOtherVertex(v1) ;
#ifdef DEBUG
printDebug (7, "BFSAPHeuristic: examining unmatched edge %lu - %lu", v1->getLabel(), v2->getLabel()) ;
#endif
if (!VertexVisited[v2->getLabel()]) { // v2 is not yet visited -> visit it!
VertexVisited[v2->getLabel()] = true ;
BackEdge[v2->getLabel()] = e ;
if (TheMatching->isExposed(v2)) { // an augmenting path has been found!
foundap = true ;
pathlen = 2 * depth + 1 ;
// build path backwards
Vertex *v = v2 ;
for (int j = pathlen - 1 ; j >= 0 ; j--) {
path[j] = &BackEdge[v->getLabel()] ;
v = BackEdge[v->getLabel()].getOtherVertex(v) ;
}
}
else { // continue searching
Edge me = *(TheMatching->getMatchingEdge(v2)) ;
Vertex* v3 = me.getOtherVertex(v2) ;
BackEdge[v3->getLabel()] = me ;
destlist.push_back (v3) ; // use v3 as a v1 in next iteration
VertexVisited[v3->getLabel()] = true ;
}
}
}
++edgeit ;
}
}
if (!foundap) {
// prepare for next iteration
srclist.clear() ;
srclist.splice (srclist.begin(), destlist) ;
}
}
return pathlen ;
}

View File

@ -0,0 +1,64 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BFSAPHeuristic
#define SH_BFSAPHeuristic
#include "EdgeIterator.h"
#include "MatchingAlgorithm.h"
#include "Vertex.h"
class Edge ;
#include "Graph.h"
class Matching ;
/**
* \class BFSAPHeuristic
* \brief a matching algorithm implementing a heuristic breadth-first-search for augmenting paths
**/
class BFSAPHeuristic : public MatchingAlgorithm {
public:
/**
* construct an BFSAPHeuristic object
* \param g the graph on which this heuristic should run
* \param m the matching to start with
**/
BFSAPHeuristic (Graph* g, Matching* m) ;
virtual ~BFSAPHeuristic (void) ;
const char* getName (void) const
{ return "BFS Augmenting Path Heuristic" ; } ;
void run (void) ;
private:
/**
* \param v0 an exposed vertex
* \param path an array of Edge pointers where the path will be put
* \return the length of the path (the number of valid edges in path)
**/
unsigned long searchAugmentingPath (Vertex* v0, const Edge** path) ;
bool* VertexVisited ;
Edge* BackEdge ;
} ;
#endif // ndef SH_BFSAPHeuristic

323
steghide-src/BinaryIO.cc Normal file
View File

@ -0,0 +1,323 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstdio>
#include "BinaryIO.h"
#include "common.h"
#include "error.h"
void BinaryIO::init ()
{
setName ("") ;
setStream (NULL) ;
set_open (false) ;
}
BinaryIO::BinaryIO (void)
{
init() ;
}
BinaryIO::BinaryIO (const std::string& fn, MODE m)
{
init() ;
open (fn, m) ;
}
BinaryIO::~BinaryIO (void)
{
if (is_open()) {
close () ;
}
}
bool BinaryIO::Fileexists (const std::string& fn) const
{
bool retval = false ;
FILE *fd = fopen (fn.c_str(), "r") ;
if (fd != NULL) {
retval = true ;
fclose (fd) ;
}
return retval ;
}
void BinaryIO::checkForce (const std::string& fn) const
{
if (!Args.Force.getValue()) {
if (Fileexists (fn)) {
Question q (_("the file \"%s\" does already exist. overwrite ?"), fn.c_str()) ;
q.printMessage() ;
if (!q.getAnswer()) {
throw SteghideError (_("did not write to file \"%s\"."), fn.c_str()) ;
}
}
}
}
void BinaryIO::open (const std::string& fn, MODE m)
{
if (fn == "") {
switch (m) {
case READ: {
setStream (stdin) ;
break ; }
case WRITE: {
setStream (stdout) ;
break ; }
default: {
myassert (0) ;
break ; }
}
}
else {
FILE *s = NULL ;
char *cmode ;
switch (m) {
case READ: {
cmode = "rb" ;
break ; }
case WRITE: {
checkForce (fn) ;
cmode = "wb" ;
break ; }
default: {
myassert(0) ;
break ; }
}
if ((s = fopen (fn.c_str(), cmode)) == NULL) {
throw SteghideError (_("could not open the file \"%s\"."), fn.c_str()) ;
}
setStream (s) ;
}
setName (fn) ;
setMode (m) ;
set_open (true) ;
}
bool BinaryIO::eof (void) const
{
int c = fgetc (getStream()) ;
bool retval = feof (getStream()) ;
ungetc (c, getStream()) ;
return retval ;
}
void BinaryIO::close (void)
{
myassert (is_open()) ;
if (getName() != "") {
if (fclose (getStream()) == EOF) {
throw SteghideError (_("could not close the file \"%s\"."), getName().c_str()) ;
}
}
setName ("") ;
setStream (NULL) ;
set_open (false) ;
}
BYTE BinaryIO::read8 (void)
{
myassert (getMode() == READ) ;
myassert (is_open()) ;
int c = EOF ;
if ((c = fgetc (getStream())) == EOF) {
throw BinaryInputError (getName(), getStream()) ;
}
return (BYTE) c ;
}
UWORD16 BinaryIO::read16_le (void)
{
myassert (getMode() == READ) ;
myassert (is_open()) ;
int bytes[2] ;
for (int i = 0 ; i < 2 ; i++) {
if ((bytes[i] = fgetc (getStream())) == EOF) {
throw BinaryInputError (getName(), getStream()) ;
}
}
return ((bytes[1] << 8) | bytes[0]) ;
}
UWORD16 BinaryIO::read16_be (void)
{
myassert (getMode() == READ) ;
myassert (is_open()) ;
int bytes[2] ;
for (int i = 0 ; i < 2 ; i++) {
if ((bytes[i] = fgetc (getStream())) == EOF) {
throw BinaryInputError (getName(), getStream()) ;
}
}
return ((bytes[0] << 8) | bytes[1]) ;
}
UWORD32 BinaryIO::read32_le (void)
{
myassert (getMode() == READ) ;
myassert (is_open()) ;
int bytes[4] ;
for (int i = 0 ; i < 4 ; i++) {
if ((bytes[i] = fgetc (getStream())) == EOF) {
throw BinaryInputError (getName(), getStream()) ;
}
}
return ((bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]) ;
}
UWORD32 BinaryIO::read32_be (void)
{
myassert (getMode() == READ) ;
myassert (is_open()) ;
int bytes[4] ;
for (int i = 0 ; i < 4 ; i++) {
if ((bytes[i] = fgetc (getStream())) == EOF) {
throw BinaryInputError (getName(), getStream()) ;
}
}
return ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) ;
}
UWORD32 BinaryIO::read_le (unsigned short n)
{
myassert (getMode() == READ) ;
myassert (is_open()) ;
myassert (n <= 4) ;
UWORD32 retval = 0 ;
for (unsigned short i = 0 ; i < n ; i++) {
int byte = EOF ;
if ((byte = fgetc (getStream())) == EOF) {
throw BinaryInputError (getName(), getStream()) ;
}
retval |= (((BYTE) byte) << (8 * i)) ;
}
return retval ;
}
std::string BinaryIO::readstring (unsigned int len)
{
char retval[len + 1] ;
for (unsigned int i = 0 ; i < len ; i++) {
retval[i] = (char) read8() ;
}
retval[len] = '\0' ;
return std::string (retval) ;
}
void BinaryIO::write8 (BYTE val)
{
myassert (getMode() == WRITE) ;
myassert (is_open()) ;
if (fputc ((int) val, getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}
void BinaryIO::write16_le (UWORD16 val)
{
myassert (getMode() == WRITE) ;
myassert (is_open()) ;
for (int i = 0 ; i <= 1 ; i++) {
if (fputc ((val >> (8 * i)) & 0xFF, getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}
}
void BinaryIO::write16_be (UWORD16 val)
{
myassert (getMode() == WRITE) ;
myassert (is_open()) ;
for (int i = 1 ; i >= 0 ; i--) {
if (fputc ((val >> (8 * i)) & 0xFF, getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}
}
void BinaryIO::write32_le (UWORD32 val)
{
myassert (getMode() == WRITE) ;
myassert (is_open()) ;
for (int i = 0 ; i <= 3 ; i++) {
if (fputc ((val >> (8 * i)) & 0xFF, getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}
}
void BinaryIO::write32_be (UWORD32 val)
{
myassert (getMode() == WRITE) ;
myassert (is_open()) ;
for (int i = 3 ; i >= 0 ; i--) {
if (fputc ((val >> (8 * i)) & 0xFF, getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}
}
void BinaryIO::write_le (UWORD32 val, unsigned short n)
{
myassert (getMode() == WRITE) ;
myassert (is_open()) ;
myassert (n <= 4) ;
for (short i = 0 ; i < n ; i++) {
if (fputc ((val >> (8 * i)) & 0xFF, getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}
}
void BinaryIO::writestring (const std::string& s)
{
if (fputs (s.c_str(), getStream()) == EOF) {
throw BinaryOutputError (getName()) ;
}
}

203
steghide-src/BinaryIO.h Normal file
View File

@ -0,0 +1,203 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BINARYIO_H
#define SH_BINARYIO_H
#include <cstdio>
#include <string>
#include "common.h"
/**
* \class BinaryIO
* \brief provides methods for file i/o as needed by the rest of steghide
**/
class BinaryIO {
public:
enum MODE { READ, WRITE } ;
BinaryIO (void) ;
/**
* construct a BinaryIO object
* \param fn the filename ("" to indicate stdin/stdout)
* \param m the mode (BinaryIO::READ or BinaryIO::WRITE)
*
* The file described by fn is opened in the given mode.
**/
BinaryIO (const std::string& fn, MODE m) ;
~BinaryIO (void) ;
/**
* get the name (with path) of this file
**/
const std::string& getName (void) const
{ return Name ; } ;
/**
* is this file currently opened ?
**/
bool is_open (void) const
{ return FileOpen ; } ;
/**
* is this file a standard stream (stdin or stdout) ?
**/
bool is_std (void) const
{ return (getStream() != NULL && getName() == "") ; } ;
/**
* get the current position in the current file
**/
unsigned long getPos (void) const
{ return ftell(getStream()) ; } ;
/**
* is the current state of this file at the end of the file
**/
bool eof (void) const ;
/**
* open the file given by fn in the mode m
* \param fn a filename ("" to indicate stdin/stdout)
* \param m the mode (BinaryIO::READ or BinaryIO::WRITE)
**/
void open (const std::string& fn, MODE m) ;
/**
* close the currently open file - it is save to call close() even if is_std() is true
**/
void close (void) ;
/**
* read one byte from the file
**/
BYTE read8 (void) ;
/**
* read two bytes from the file using little-endian byte ordering
**/
UWORD16 read16_le (void) ;
/**
* read two bytes from the file using big-endian byte ordering
**/
UWORD16 read16_be (void) ;
/**
* read four bytes from the file using little-endian byte ordering
**/
UWORD32 read32_le (void) ;
/**
* read four bytes from the file using big-endian byte ordering
**/
UWORD32 read32_be (void) ;
/**
* read n bytes (little endian byte ordering)
* \param n the number of bytes to read (must be <= 4)
**/
UWORD32 read_le (unsigned short n) ;
/**
* read a string with length len from the file
**/
std::string readstring (unsigned int len) ;
/**
* write one byte to the file
**/
void write8 (BYTE val) ;
/**
* write two bytes to the file using little-endian byte ordering
**/
void write16_le (UWORD16 val) ;
/**
* write two bytes to the file using big-endian byte ordering
**/
void write16_be (UWORD16 val) ;
/**
* write four bytes to the file using little-endian byte ordering
**/
void write32_le (UWORD32 val) ;
/**
* write four bytes to the file using big-endian byte ordering
**/
void write32_be (UWORD32 val) ;
/**
* write n bytes of val (little endian byte ordering)
* \param n the number of bytes to write (must be <= 4)
* \param val the value
**/
void write_le (UWORD32 val, unsigned short n) ;
void writestring (const std::string& s) ;
/**
* get the underlying cstdio FILE* pointer
**/
FILE* getStream (void) const
{ return Stream ; } ;
protected:
void setStream (FILE* s)
{ Stream = s ; } ;
void setName (const std::string& fn)
{ Name = fn ; } ;
MODE getMode (void) const
{ return Mode ; } ;
void setMode (MODE m)
{ Mode = m ; } ;
private:
std::string Name ;
FILE *Stream ;
bool FileOpen ;
MODE Mode ;
void init (void) ;
void set_open (bool o)
{ FileOpen = o ; } ;
/**
* when opening a file in write mode perform various checks depending on the value of the force argument
**/
void checkForce (const std::string& fn) const ;
/**
* check if the file described by fn exists
* \return true iff a fopen call with fn as file name succeeded
**/
bool Fileexists (const std::string& fn) const ;
} ;
#endif /* ndef SH_BINARYIO_H */

471
steghide-src/BitString.cc Normal file
View File

@ -0,0 +1,471 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "AUtils.h"
#include "BitString.h"
#include "common.h"
#ifdef USE_ZLIB
namespace zlib {
#include <zlib.h>
}
#endif // def USE_ZLIB
#define BITPOS(n) (n % 8)
#define BYTEPOS(n) (n / 8)
BitString::BitString (EmbValue arity)
: Length(0)
{
setArity(arity) ;
}
BitString::BitString (const BitString& bs)
{
Length = bs.Length ;
Arity = bs.Arity ;
ArityNBits = bs.ArityNBits ;
Data.resize(bs.Data.size()) ;
for (unsigned long i = 0 ; i < bs.Data.size() ; i++) {
Data[i] = bs.Data[i] ;
}
}
BitString::BitString (unsigned long l)
{
unsigned long nbytes = 0 ;
if (l % 8 == 0) {
nbytes = l / 8 ;
}
else {
nbytes = (l / 8) + 1 ;
}
Data = std::vector<BYTE> (nbytes, 0) ; // is initialized to zeros in std::vector's constructor
Length = l ;
setArity(2) ;
}
BitString::BitString (const std::vector<BYTE> &d)
: Length(0)
{
setArity(2) ;
append (d) ;
}
BitString::BitString (const std::string &d)
: Length(0)
{
setArity(2) ;
append (d) ;
}
void BitString::setArity (EmbValue arity)
{
BYTE tmp = Arity = arity ;
ArityNBits = 0 ;
while (tmp > 1) {
myassert (tmp % 2 == 0) ; // only implemented for arity = 2^i
tmp /= 2 ;
ArityNBits++ ;
}
}
BitString& BitString::clear()
{
Data.clear() ;
Length = 0 ;
return *this ;
}
void BitString::_append (BIT v)
{
if (Length % 8 == 0) {
Data.push_back (0) ;
}
Data[BYTEPOS(Length)] |= (v << BITPOS(Length)) ;
Length++ ;
}
BitString& BitString::append (BIT v)
{
_append (v) ;
return *this ;
}
BitString& BitString::append (const BYTE v, const unsigned short n)
{
for (unsigned short i = 0 ; i < n ; i++) {
_append ((BIT) ((v & (1 << i)) >> i)) ;
}
return *this ;
}
BitString& BitString::append (const UWORD16 v, const unsigned short n)
{
for (unsigned short i = 0 ; i < n ; i++) {
_append ((BIT) ((v & (1 << i)) >> i)) ;
}
return *this ;
}
BitString& BitString::append (const UWORD32 v, const unsigned short n)
{
for (unsigned short i = 0 ; i < n ; i++) {
_append ((BIT) ((v & (1 << i)) >> i)) ;
}
return *this ;
}
BitString& BitString::append (const BitString& v)
{
for (unsigned long i = 0 ; i < v.getLength() ; i++) {
_append (v[i]) ;
}
return *this ;
}
BitString& BitString::append (const std::vector<BYTE>& v)
{
for (std::vector<BYTE>::const_iterator i = v.begin() ; i != v.end() ; i++) {
append (*i) ;
}
return *this ;
}
BitString& BitString::append (const std::string& v)
{
for (std::string::const_iterator i = v.begin() ; i != v.end() ; i++) {
append ((BYTE) *i) ;
}
return *this ;
}
BIT BitString::operator[] (unsigned long i) const
{
myassert (i < Length) ;
return ((Data[BYTEPOS(i)] >> BITPOS(i)) & 1) ;
}
BitString& BitString::setBit (unsigned long i, BIT v)
{
myassert (i < Length) ;
BYTE mask = ~(1 << BITPOS(i)) ;
Data[BYTEPOS(i)] &= mask ;
Data[BYTEPOS(i)] |= (v << BITPOS(i)) ;
return (*this) ;
}
BitString BitString::getBits (unsigned long s, unsigned long l) const
{
BitString retval ;
for (unsigned long i = s ; i < s + l ; i++) {
retval.append ((*this)[i]) ;
}
return retval ;
}
BitString BitString::cutBits (unsigned long s, unsigned long l)
{
myassert (s + l <= Length) ;
BitString retval ;
for (unsigned long i = s, j = s + l ; i < s + l || j < Length ; i++, j++) {
if (i < s + l) {
retval.append ((*this)[i]) ;
}
if (j < Length) {
setBit(i, (*this)[j]) ;
}
}
Length -= l ;
Data.resize (AUtils::div_roundup<UWORD32> (Length, 8)) ;
clearUnused() ;
return retval ;
}
UWORD32 BitString::getValue (unsigned long s, unsigned short l) const
{
myassert (l <= 32) ;
UWORD32 retval = 0 ;
for (unsigned short i = 0 ; i < l ; i++) {
retval |= (*this)[s + i] << i ;
}
return retval ;
}
const std::vector<BYTE>& BitString::getBytes() const
{
myassert (Length % 8 == 0) ;
return Data ;
}
BitString& BitString::truncate (const unsigned long s, const unsigned long e)
{
unsigned long newsize_i = e - s ;
unsigned long newsize_y = 0 ;
if (newsize_i % 8 == 0) {
newsize_y = newsize_i / 8 ;
}
else {
newsize_y = newsize_i / 8 + 1 ;
}
for (unsigned long i = 0 ; i < newsize_i ; i++) {
// replace i-th bit with (s+i)-th bit
BIT bit = (*this)[s + i] ;
Data[BYTEPOS(i)] &= (BYTE) ~(1 << BITPOS(i)) ; // delete i-th bit
Data[BYTEPOS(i)] |= (BYTE) (bit << BITPOS(i)) ;
}
Length = newsize_i ;
clearUnused() ;
return *this ;
}
BitString& BitString::pad (unsigned long mult, BIT v)
{
while (Length % mult != 0) {
_append (v) ;
}
return *this ;
}
BitString& BitString::padRandom (unsigned long mult)
{
while (Length % mult != 0) {
append (RndSrc.getBool()) ;
}
return *this ;
}
BYTE BitString::getNAry (unsigned long p) const
{
unsigned long pbinary = p * ArityNBits ;
BYTE retval = 0 ;
for (unsigned short i = 0 ; (i < ArityNBits) && (pbinary + i < Length /* Length not a multiple of ArityNBits */) ; i++) {
retval |= (*this)[pbinary + i] << i ;
}
return retval ;
}
void BitString::appendNAry (BYTE v)
{
for (unsigned short i = 0 ; i < ArityNBits ; i++) {
_append ((v & (1 << i)) >> i) ;
}
}
#ifdef USE_ZLIB
BitString& BitString::compress (int level)
{
myassert (level >= 1 && level <= 9) ;
pad (8, 0) ;
// prepare source buffer
zlib::uLong srclen = Data.size() ;
zlib::Byte *srcbuf = new zlib::Byte[srclen] ;
for (unsigned long i = 0 ; i < srclen ; i++) {
srcbuf[i] = Data[i] ;
}
// prepare dest buffer (see zlib manual for this magic length)
zlib::uLong destlen = ((zlib::uLong) ((Data.size() + 12) * 1.001)) + 1 ;
zlib::Byte* destbuf = new zlib::Byte[destlen] ;
// do compression
int ret = zlib::compress2 (destbuf, &destlen, (const zlib::Bytef*) srcbuf, srclen, level) ;
if (ret != Z_OK) {
switch (ret) {
case Z_MEM_ERROR:
throw SteghideError (_("could not allocate memory.")) ;
break ;
default:
throw SteghideError (_("error %d while calling zlib's compress2."), ret) ;
break ;
}
}
// write compressed data into Data
Data.resize (destlen) ;
for (unsigned long i = 0 ; i < destlen ; i++) {
Data[i] = destbuf[i] ;
}
Length = destlen * 8 ;
delete[] srcbuf ;
delete[] destbuf ;
return *this ;
}
BitString& BitString::uncompress (unsigned long idestlen)
{
myassert (Length % 8 == 0) ;
// prepare source buffer
zlib::uLong srclen = Length / 8 ;
zlib::Byte* srcbuf = new zlib::Byte[srclen] ;
for (unsigned long i = 0 ; i < srclen ; i++) {
srcbuf[i] = Data[i] ;
}
// prepare destination buffer
zlib::uLong ydestlen = 0 ;
if (idestlen % 8 == 0) {
ydestlen = idestlen / 8 ;
}
else {
ydestlen = (idestlen / 8) + 1 ;
}
zlib::Byte* destbuf = new zlib::Byte[ydestlen] ;
// do uncompression
zlib::uLong ydestlen_before = ydestlen ;
int ret = zlib::uncompress (destbuf, &ydestlen, (const zlib::Bytef*) srcbuf, srclen) ;
if (ret != Z_OK) {
switch (ret) {
case Z_MEM_ERROR:
throw SteghideError (_("could not allocate memory.")) ;
break ;
case Z_DATA_ERROR:
throw SteghideError (_("can not uncompress data. compressed data is corrupted.")) ;
break ;
default:
throw SteghideError (_("error %d while calling zlib's uncompress."), ret) ;
break ;
}
}
myassert (ydestlen_before == ydestlen) ; // because idestlen must be _exactly_ size in bits
// write uncompressed data into Data
Data.resize (ydestlen) ;
for (unsigned long i = 0 ; i < ydestlen ; i++) {
Data[i] = destbuf[i] ;
}
Length = idestlen ;
clearUnused() ;
delete[] srcbuf ;
delete[] destbuf ;
return *this ;
}
#endif // def USE_ZLIB
bool BitString::operator== (const BitString &v) const
{
bool retval = true ;
if (v.getLength() == getLength()) {
unsigned int n = getLength() ;
for (unsigned int i = 0 ; i < n ; i++) {
if (v[i] != (*this)[i]) {
retval = false ;
}
}
}
else {
retval = false ;
}
return retval ;
}
bool BitString::operator!= (const BitString &v) const
{
bool retval = false ;
if (v.getLength() != getLength()) {
retval = true ;
}
else {
for (unsigned int i = 0 ; i < getLength() ; i++) {
if (v[i] != (*this)[i]) {
retval = true ;
break ;
}
}
}
return retval ;
}
BitString& BitString::operator^= (const BitString &v)
{
for (unsigned long i = 0 ; i < Length ; i++) {
unsigned long bytepos = BYTEPOS (i) ;
unsigned int bitpos = BITPOS (i) ;
BIT bit = (Data[bytepos] & (1 << bitpos)) >> bitpos ;
bit ^= v[i] ;
Data[bytepos] = (Data[bytepos] & ~(1 << bitpos)) | (bit << bitpos) ;
}
return *this ;
}
void BitString::clearUnused ()
{
if (Length % 8 != 0) {
// clear unused part of last byte (_append depends on this)
unsigned short nbitsfilled = Length % 8 ;
BYTE mask = 0x00 ;
for (unsigned short i = 0 ; i < nbitsfilled ; i++) {
mask <<= 1 ;
mask |= 1 ;
}
Data[Data.size() - 1] &= mask ;
}
}
void BitString::print (unsigned short spc) const
{
char* space = new char[spc + 1] ;
for (unsigned short i = 0 ; i < spc ; i++) {
space[i] = ' ' ;
}
space[spc] = '\0' ;
std::cerr << space << "Length: " << getLength() << std::endl ;
std::cerr << space << "Data.size(): " << Data.size() << std::endl ;
std::cerr << space << "Data:" << std::endl ;
std::cerr << space ;
for (unsigned long i = 0 ; i < getLength() ; i++) {
if ((i % 64 == 0) && (i > 0)) { // new line
std::cerr << std::endl << space ;
}
if (i % 8 == 0) { // new byte
std::cerr << " " ;
}
std::cerr << ((*this)[i]) ;
}
std::cerr << std::endl ;
}
#ifdef DEBUG
void BitString::printDebug (unsigned short level, unsigned short spc) const
{
if (RUNDEBUGLEVEL(level)) {
print (spc) ;
}
}
#endif

280
steghide-src/BitString.h Normal file
View File

@ -0,0 +1,280 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BITSTRING_H
#define SH_BITSTRING_H
#include <vector>
#include <string>
#include "AUtils.h"
#include "common.h"
/**
* \class BitString
* \brief a string of bits
*
* This class provides a way to conveniently store and
* manipulate a string of bits. Various objects can be
* appended to a BitString.
*
* For data storage a vector of BYTEs is used with little
* endian bit encoding, i.e. the first bit is the least
* significant bit of the first byte and so on.
**/
class BitString {
public:
/**
* construct an empty BitString
**/
BitString (EmbValue arity = 2) ;
/**
* copy constructor
**/
BitString (const BitString& bs) ;
/**
* construct a BitString containing l bits with value zero
**/
BitString (const unsigned long l) ;
/**
* construct a BitString containing the data in d
**/
BitString (const std::vector<BYTE>& d) ;
/**
* construct a BitString containing the characters in d as 8 bit unsigned chars
**/
BitString (const std::string& d) ;
void setArity (EmbValue arity) ;
EmbValue getArity (void) const
{ return Arity ; } ;
/**
* get the number of bits in this BitString
**/
UWORD32 getLength (void) const
{ return Length ; } ;
/**
* get the number of EmbValues in this BitString (using this BitString's arity)
**/
UWORD32 getNAryLength (void) const
{ return AUtils::div_roundup<UWORD32> (Length, ArityNBits) ; } ;
/**
* delete the contents of this Bitstring
**/
BitString& clear (void) ;
/**
* append the bit v to this BitString
**/
BitString& append (const BIT v) ;
/**
* append n lower order bits of v to this BitString
* \param v the value to be appended
* \param n the number of bits to be appended
**/
BitString& append (const BYTE v, const unsigned short n = 8) ;
/**
* append n lower order bits of v to this BitString
* \param v the value to be appended
* \param n the number of bits to be appended
**/
BitString& append (const UWORD16 v, const unsigned short n = 16) ;
/**
* append n lower order bits of v to this BitString
* \param v the value to be appended
* \param n the number of bits to be appended
**/
BitString& append (const UWORD32 v, const unsigned short n = 32) ;
/**
* append the string v to this BitString
**/
BitString& append (const std::string& v) ;
/**
* append the vector v byte-wise to this BitString
**/
BitString& append (const std::vector<BYTE>& v) ;
/**
* append the BitString v to this BitString
* \param v the BitString to be appended
**/
BitString& append (const BitString& v) ;
/**
* set the p-th bit to v
* \param i the index (must be < getLength())
* \param v the value
**/
BitString& setBit (unsigned long i, BIT v) ;
/**
* get a BitString that is a part of this BitString
* \param s the index of the first bit to be copied from this BitString
* \param l the total number of bits to be used for the return value
* \return the BitString containing of the bits [s...s+(l-1)] of this BitString
**/
BitString getBits (const unsigned long s, const unsigned long l) const ;
/**
* cut some bits out of this BitString
* \param s the index of the first bit to be removed from this BitString
* \param l the total number of bits to be removed
* \return the BitString containing of the bits [s...s+(l-1)] of this BitString
*
* After calling cutBits, this BitString consists of the bits 0,...,s-1,s+l,... .
**/
BitString cutBits (const unsigned long s, const unsigned long l) ;
/**
* return a value composed from bits in this BitString
* \param s the index of the first bit to be used for the return value
* \param l the total number of bits to be used for the return value (must be <= 32)
* \return the value (*this)[s],...,(*this)[s+l-1]
**/
UWORD32 getValue (const unsigned long s, const unsigned short l) const ;
/**
* get the contents of this BitString as vector of bytes
* \return the contents of this BitString as vector of bytes
*
* getLength() % 8 must be 0 to call this function
**/
const std::vector<BYTE>& getBytes (void) const ;
/**
* truncate this BitString
* \param s start
* \param e end
* \return this BitString modified to contain only (*this)[s]...(*this)[e - 1]
**/
BitString& truncate (const unsigned long s, const unsigned long e) ;
/**
* pad this BitString with the value in v
* \param mult this BitString is padded until size is a multiple of mult (given in bits)
* \param v the value this BitString should be padded with
**/
BitString& pad (const unsigned long mult, const BIT v) ;
/**
* pad this BitString with random data
* \param mult this BitString is padded until size is a multiple of mult (given in bits)
**/
BitString& padRandom (const unsigned long mult) ;
/**
* get an n-ary digit from this BitString
* \param p the position (in the n-ary representation of this BitString)
* \return the p-th n-ary digit
**/
BYTE getNAry (unsigned long p) const ;
/**
* append an n-ary digit to this BitString
* \param v the n-ary value to be appended
**/
void appendNAry (BYTE v) ;
#ifdef USE_ZLIB
/**
* compress this BitString using zlib's compress2 function
* \param level the compression level (ranging from 1 (best speed) to 9 (best compression)
*
* As zlib operates on byte vectors and not on bit vectors, this BitString is padded
* with zeros until the next byte boundary before starting the compression.
**/
BitString& compress (int level) ;
/**
* uncompress this BitString using zlib's uncompress function
* \param idestlen the length of the uncompressed data (in bits)
* \return this BitString modified to contain exactly idestlen uncompressed bits
*
* idestlen must be the size of the uncompressed data (in bits) to make
* it possible to allocate a destination buffer and to give information
* about the length of the uncompressed data without padding.
*
* A precondition for calling this function is that this BitString actually
* contains data that has been compressed by the BitString::compress function,
* and especially that the Length % 8 is 0.
**/
BitString& uncompress (unsigned long idestlen) ;
#endif // def USE_ZLIB
/**
* get the value of the i-th bit
**/
BIT operator[] (const unsigned long i) const ;
/**
* xor v with this BitString, saving the result in this Bitstring.
* The result has the same length as this BitString.
**/
BitString& operator^= (const BitString &v) ;
/**
* compare this BitString with the BitString v
* \return true iff the lengths are equal and for every valid index the value is equal
**/
bool operator== (const BitString& v) const ;
/**
* compare this BitString with the BitString v
* \return true iff the lengths are not equal or there exists an index with different values
**/
bool operator!= (const BitString& v) const ;
void print (unsigned short spc = 0) const ;
#ifdef DEBUG
void printDebug (unsigned short level, unsigned short spc = 0) const ;
#endif
private:
/// the number of bits in Data
UWORD32 Length ;
/// the arity that will be used for getLength/getNAry/appendNAry
EmbValue Arity ;
/// the number of Bits per n-ary digit (where n is Arity)
unsigned short ArityNBits ;
/// the actual data
std::vector<BYTE> Data ;
void _append (BIT v) ;
/**
* clear unused part of last byte (_append depends on this)
**/
void clearUnused (void) ;
} ;
#endif // ndef SH_BITSTRING_H

848
steghide-src/BmpFile.cc Normal file
View File

@ -0,0 +1,848 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstdio>
#include <cstdlib>
#include "AUtils.h"
#include "BFSAPHeuristic.h"
#include "ColorPalette.h"
#include "CvrStgFile.h"
#include "DFSAPHeuristic.h"
#include "DMDConstructionHeuristic.h"
#include "BmpFile.h"
#include "BmpPaletteSampleValue.h"
#include "BmpRGBSampleValue.h"
#include "SampleValueAdjacencyList.h"
#include "SMDConstructionHeuristic.h"
#include "WKSConstructionHeuristic.h"
#include "common.h"
#include "error.h"
BmpFile::BmpFile (BinaryIO *io)
: CvrStgFile()
{
read (io) ;
}
BmpFile::~BmpFile ()
{
delete Palette ;
}
BmpFile::SUBFORMAT BmpFile::getSubformat () const
{
return subformat ;
}
void BmpFile::read (BinaryIO *io)
{
CvrStgFile::read (io) ;
Palette = NULL ;
readheaders() ;
readdata() ;
}
void BmpFile::write ()
{
CvrStgFile::write() ;
writeheaders() ;
writedata() ;
}
std::list<CvrStgFile::Property> BmpFile::getProperties () const
{
std::list<CvrStgFile::Property> retval ;
// format
std::string formatstring ;
switch (getSubformat()) {
case WIN:
formatstring = _("Windows 3.x bitmap") ;
break ;
case OS2:
formatstring = _("OS/2 1.x bitmap") ;
break ;
}
retval.push_back (CvrStgFile::Property (_("format"), formatstring)) ;
return retval ;
}
std::vector<MatchingAlgorithm*> BmpFile::getMatchingAlgorithms (Graph* g, Matching* m) const
{
std::vector<MatchingAlgorithm*> retval ;
if (getBitCount() == 24) {
retval.push_back (new SMDConstructionHeuristic (g, m)) ;
}
else {
retval.push_back (new SMDConstructionHeuristic (g, m)) ;
}
return retval ;
}
unsigned long BmpFile::getNumSamples() const
{
unsigned long retval = 0 ;
switch (getSubformat()) {
case WIN: {
retval = bmih.biWidth * bmih.biHeight ;
break ; }
case OS2: {
retval = bmch.bcWidth * bmch.bcHeight ;
break ; }
}
return retval ;
}
void BmpFile::replaceSample (const SamplePos pos, const SampleValue* s)
{
unsigned long index = 0 ;
unsigned short firstbit = 0 ;
calcIndex (pos, &index, &firstbit) ;
unsigned short bitcount = getBitCount() ;
switch (bitcount) {
case 1: case 4: case 8: {
const BmpPaletteSampleValue* sample = dynamic_cast<const BmpPaletteSampleValue*> (s) ;
myassert (sample) ;
for (unsigned short i = 0 ; i < bitcount ; i++) {
BitmapData[index] = BitmapData[index] & (~(1 << (firstbit + i))) ;
BitmapData[index] = BitmapData[index] | ((sample->getIndex() & (1 << i)) << firstbit) ;
}
break ; }
case 24: {
const BmpRGBSampleValue* sample = dynamic_cast<const BmpRGBSampleValue*> (s) ;
myassert (sample) ;
BitmapData[index] = sample->getBlue() ;
BitmapData[index + 1] = sample->getGreen() ;
BitmapData[index + 2] = sample->getRed() ;
break ; }
}
}
SampleValue *BmpFile::getSampleValue (SamplePos pos) const
{
unsigned long index = 0 ;
unsigned short firstbit = 0 ;
calcIndex (pos, &index, &firstbit) ;
unsigned short bitcount = getBitCount() ;
SampleValue *retval = NULL ;
switch (bitcount) {
case 1: case 4: case 8: {
BYTE idx_pal = 0 ;
for (unsigned short i = 0 ; i < bitcount ; i++) {
idx_pal |= ((BitmapData[index] & (1 << (firstbit + i))) >> firstbit) ;
}
retval = (SampleValue*) new BmpPaletteSampleValue (idx_pal) ;
break ; }
case 24: {
retval = (SampleValue*) new BmpRGBSampleValue (BitmapData[index + 2], BitmapData[index + 1], BitmapData[index]) ;
break ; }
}
return retval ;
}
std::vector<SampleValueAdjacencyList*> BmpFile::calcSVAdjacencyLists (const std::vector<SampleValue*>& svs) const
{
if (getBitCount() == 24) {
EmbValue m = getEmbValueModulus() ;
UWORD32 r = getRadius() ;
// create svalists
std::vector<SampleValueAdjacencyList*> lists (m) ;
for (EmbValue i = 0 ; i < m ; i++) {
lists[i] = new SampleValueAdjacencyList (svs.size()) ;
}
// redmap contains all sample values in a 3-dimensional RGB-tree
typedef std::map<BYTE, BmpRGBSampleValue*> BlueMap ;
typedef std::map<BYTE, BlueMap> GreenMap ;
typedef std::map<BYTE, GreenMap> RedMap ;
RedMap redmap ;
for (std::vector<SampleValue*>::const_iterator svit = svs.begin() ; svit != svs.end() ; svit++) {
BmpRGBSampleValue* rgbsv = (BmpRGBSampleValue*) (*svit) ;
redmap[rgbsv->getRed()][rgbsv->getGreen()][rgbsv->getBlue()] = rgbsv ;
}
// create hemisphere matrix (will contain a discrete hemisphere with radius getRadius())
unsigned short r_eucl = (unsigned short) sqrt (r) ; // the euclidean radius (not squared) - rounded to next lower natural number
short hemisphere[2 * r_eucl + 1][2 * r_eucl + 1] ;
for (short dr = -r_eucl ; dr <= r_eucl ; dr++) {
for (short dg = -r_eucl ; dg <= r_eucl ; dg++) {
short db_sq = r_eucl*r_eucl - dr*dr - dg*dg ;
if (db_sq >= 0) {
// round hemishpere points to next lower natural numbers
hemisphere[dr + r_eucl][dg + r_eucl] = (short) sqrt (db_sq) ;
}
else {
hemisphere[dr + r_eucl][dg + r_eucl] = -1 ;
}
}
}
//
// fill adjacency lists
//
// create reservoir - for every i reservoir[i] contains the sample values that are neighbourss of
// the sample value with label i and have a lower label (and have already been found)
// This is necessary to use collapsing trees together with bucket sort (without huge increase in memory usage)
std::vector<BmpRGBSampleValue*> reservoir[svs.size()] ;
// neighbours sorted by distance (for the current source sample value)
std::vector<BmpRGBSampleValue*> neighbours_byd[r + 1] ;
for (std::vector<SampleValue*>::const_iterator srcsvit = svs.begin() ; srcsvit != svs.end() ; srcsvit++) {
BmpRGBSampleValue* srcsv = (BmpRGBSampleValue*) (*srcsvit) ;
// sort reservoir into neighbours_byd
for (std::vector<BmpRGBSampleValue*>::const_iterator it = reservoir[srcsv->getLabel()].begin() ;
it != reservoir[srcsv->getLabel()].end() ; it++) {
neighbours_byd[srcsv->calcDistance(*it)].push_back (*it) ;
}
unsigned short r_abs_start = AUtils::bminus<unsigned short> (srcsv->getRed(), r_eucl) ;
unsigned short r_abs_end = AUtils::bplus<unsigned short, 255> (srcsv->getRed(), r_eucl) ;
unsigned short g_abs_start = AUtils::bminus<unsigned short> (srcsv->getGreen(), r_eucl) ;
unsigned short g_abs_end = AUtils::bplus<unsigned short, 255> (srcsv->getGreen(), r_eucl) ;
RedMap::iterator rit = redmap.lower_bound (r_abs_start) ;
while ((rit != redmap.end()) && (rit->first <= r_abs_end)) {
GreenMap& greenmap = rit->second ;
if (greenmap.empty()) {
RedMap::iterator delme = rit ;
rit++ ;
redmap.erase (delme) ;
}
else {
GreenMap::iterator git = greenmap.lower_bound (g_abs_start) ;
while ((git != greenmap.end()) && (git->first <= g_abs_end)) {
unsigned short red_index = (rit->first - srcsv->getRed()) + r_eucl ;
unsigned short green_index = (git->first - srcsv->getGreen()) + r_eucl ;
short delta_b = hemisphere[red_index][green_index] ;
if (delta_b < 0) { // this blue map has no sample values in sphere
git++ ;
}
else {
BlueMap& bluemap = git->second ;
if (bluemap.empty()) {
GreenMap::iterator delme = git ;
git++ ;
greenmap.erase (delme) ;
}
else {
unsigned short b_abs_start = AUtils::bminus<unsigned short> (srcsv->getBlue(), delta_b) ;
unsigned short b_abs_end = AUtils::bplus<unsigned short,255> (srcsv->getBlue(), delta_b) ;
BlueMap::iterator bit = bluemap.lower_bound (b_abs_start) ;
while ((bit != bluemap.end()) && (bit->first <= b_abs_end)) {
if (srcsv->getLabel() < bit->second->getLabel()) {
neighbours_byd[srcsv->calcDistance(bit->second)].push_back (bit->second) ;
reservoir[bit->second->getLabel()].push_back (srcsv) ;
bit++ ;
}
else {
BlueMap::iterator delme = bit ;
bit++ ;
bluemap.erase (delme) ;
}
}
git++ ;
}
}
} // end of git loop
rit++ ;
}
} // end of rit loop
for (unsigned short d = 0 ; d <= r ; d++) {
if (!neighbours_byd[d].empty()) {
for (std::vector<BmpRGBSampleValue*>::const_iterator it = neighbours_byd[d].begin() ;
it != neighbours_byd[d].end() ; it++) {
(*(lists[(*it)->getEmbeddedValue()]))[srcsv].push_back (*it) ;
}
neighbours_byd[d].clear() ;
}
}
} // end of svs for loop
return lists ;
}
else {
return CvrStgFile::calcSVAdjacencyLists(svs) ;
}
}
void BmpFile::calcIndex (SamplePos pos, unsigned long* index, unsigned short* firstbit) const
{
unsigned long width = getWidth(), bitcount = getBitCount() ;
unsigned long bytesperline_nonpadded = 0 ;
if (width * bitcount % 8 == 0) {
bytesperline_nonpadded = (width * bitcount) / 8 ;
}
else {
bytesperline_nonpadded = (width * bitcount) / 8 + 1 ;
}
unsigned long row = pos / width ;
pos = pos % width ;
unsigned long column = 0 ;
switch (bitcount) {
case 1: case 4: case 8:
{
unsigned short samplesperbyte = 8 / bitcount ;
column = pos / samplesperbyte ;
// to account for the order pixels are stored in one byte:
*firstbit = (samplesperbyte - (pos % samplesperbyte) - 1) * bitcount ;
myassert (*firstbit < 8) ;
}
break ;
case 24:
column = pos * 3 ;
*firstbit = 0 ;
break ;
default:
myassert(false) ;
break ;
}
*index = bytesperline_nonpadded * row + column ;
}
unsigned short BmpFile::getBitCount() const
{
unsigned short retval = 0 ;
switch (getSubformat()) {
case WIN: {
retval = bmih.biBitCount ;
break ; }
case OS2: {
retval = bmch.bcBitCount ;
break ; }
}
myassert (retval == 1 || retval == 4 || retval == 8 || retval == 24) ;
return retval ;
}
unsigned long BmpFile::getWidth() const
{
unsigned long retval = 0 ;
switch (getSubformat()) {
case WIN:
retval = bmih.biWidth ;
break ;
case OS2:
retval = bmch.bcWidth ;
break ;
}
return retval ;
}
unsigned long BmpFile::getHeight() const
{
unsigned long retval = 0 ;
switch (getSubformat()) {
case WIN: {
retval = bmih.biHeight ;
break ; }
case OS2: {
retval = bmch.bcHeight ;
break ; }
}
return retval ;
}
ColorPalette *BmpFile::getPalette() const
{
myassert (getBitCount() != 24) ;
myassert (Palette) ;
return Palette ;
}
/* reads the headers of a bmp file from disk */
void BmpFile::readheaders ()
{
try {
bmfh.bfType = IdBm ;
bmfh.bfSize = getBinIO()->read32_le() ;
bmfh.bfReserved1 = getBinIO()->read16_le() ;
bmfh.bfReserved2 = getBinIO()->read16_le() ;
bmfh.bfOffBits = getBinIO()->read32_le() ;
unsigned long tmpSize = getBinIO()->read32_le() ;
switch (tmpSize) {
case SizeBMINFOHEADER: {
// this file is in the Windows bmp format
subformat = WIN ;
bmpwin_readheaders () ;
break ; }
case SizeBMCOREHEADER: {
// this file is in the OS/2 bmp format
subformat = OS2 ;
bmpos2_readheaders () ;
break ; }
default: {
if (getBinIO()->is_std()) {
throw NotImplementedError (_("the bmp data from standard input has a format that is not supported (biSize: %lu)."), tmpSize) ;
}
else {
throw NotImplementedError (_("the bmp file \"%s\" has a format that is not supported (biSize: %lu)."), getBinIO()->getName().c_str(), tmpSize) ;
}
break ; }
}
}
catch (BinaryInputError e) {
switch (e.getType()) {
case BinaryInputError::FILE_ERR: {
throw SteghideError (_("an error occured while reading the bmp headers from the file \"%s\"."), getBinIO()->getName().c_str()) ;
break ; }
case BinaryInputError::FILE_EOF: {
throw SteghideError (_("premature end of file \"%s\" while reading bmp headers."), getBinIO()->getName().c_str()) ;
break ; }
case BinaryInputError::STDIN_ERR: {
throw SteghideError (_("an error occured while reading the bmp headers from standard input.")) ;
break ; }
case BinaryInputError::STDIN_EOF: {
throw SteghideError (_("premature end of data from standard input while reading bmp headers.")) ;
break ; }
}
}
}
void BmpFile::bmpwin_readheaders ()
{
bmih.biSize = SizeBMINFOHEADER ;
bmih.biWidth = getBinIO()->read32_le () ;
bmih.biHeight = getBinIO()->read32_le () ;
bmih.biPlanes = getBinIO()->read16_le () ;
myassert (bmih.biPlanes == 1) ;
bmih.biBitCount = getBinIO()->read16_le () ;
switch (bmih.biBitCount) {
case 1:
setSamplesPerVertex (SamplesPerVertex_SmallPalette) ;
setEmbValueModulus (EmbValueModulus_SmallPalette) ;
setRadius (Radius_Palette) ;
break ;
case 4:
setSamplesPerVertex (SamplesPerVertex_SmallPalette) ;
setEmbValueModulus (EmbValueModulus_SmallPalette) ;
setRadius (Radius_Palette) ;
break ;
case 8:
setSamplesPerVertex (SamplesPerVertex_LargePalette) ;
setEmbValueModulus (EmbValueModulus_LargePalette) ;
setRadius (Radius_Palette) ;
break ;
case 24:
setSamplesPerVertex (SamplesPerVertex_RGB) ;
setEmbValueModulus (EmbValueModulus_RGB) ;
setRadius (Radius_RGB) ;
break ;
default:
if (getBinIO()->is_std()) {
throw NotImplementedError (_("the bmp data from standard input has a format that is not supported (biBitCount: %d)."), bmih.biBitCount) ;
}
else {
throw NotImplementedError (_("the bmp file \"%s\" has a format that is not supported (biBitCount: %d)."), getBinIO()->getName().c_str(), bmih.biBitCount) ;
}
break ;
}
bmih.biCompression = getBinIO()->read32_le () ;
if (bmih.biCompression != COMPRESSION_BI_RGB) {
if (getBinIO()->is_std()) {
throw NotImplementedError (_("the bitmap data from standard input is compressed which is not supported.")) ;
}
else {
throw NotImplementedError (_("the bitmap data in \"%s\" is compressed which is not supported."), getBinIO()->getName().c_str()) ;
}
}
bmih.biSizeImage = getBinIO()->read32_le () ;
bmih.biXPelsPerMeter = getBinIO()->read32_le () ;
bmih.biYPelsPerMeter = getBinIO()->read32_le () ;
bmih.biClrUsed = getBinIO()->read32_le () ;
bmih.biClrImportant = getBinIO()->read32_le () ;
if (bmih.biBitCount != 24) {
/* a color table exists */
Palette = new ColorPalette() ;
unsigned int ncolors = 0 ;
switch (bmih.biBitCount) {
case 1: {
if (Args.Command.getValue() == EMBED) {
Warning w (_("using a black/white bitmap as cover is very insecure!")) ;
w.printMessage() ;
}
ncolors = 2 ;
break ; }
case 4: {
if (Args.Command.getValue() == EMBED) {
Warning w (_("using a 16-color bitmap as cover is very insecure!")) ;
w.printMessage() ;
}
ncolors = 16 ;
break ; }
case 8: {
ncolors = 256 ;
break ; }
default: {
myassert (0) ;
break ; }
}
if (bmih.biClrUsed != 0) {
ncolors = bmih.biClrUsed ;
}
for (unsigned int i = 0 ; i < ncolors ; i++) {
unsigned char b = getBinIO()->read8() ;
unsigned char g = getBinIO()->read8() ;
unsigned char r = getBinIO()->read8() ;
if (getBinIO()->read8() != 0) {
Warning w (_("maybe corrupted windows bmp data (Reserved in RGBQUAD is non-zero).")) ;
w.printMessage() ;
}
Palette->addEntry(r, g, b) ;
}
}
}
void BmpFile::bmpos2_readheaders ()
{
bmch.bcSize = SizeBMCOREHEADER ;
bmch.bcWidth = getBinIO()->read16_le () ;
bmch.bcHeight = getBinIO()->read16_le () ;
bmch.bcPlanes = getBinIO()->read16_le () ;
myassert (bmch.bcPlanes == 1) ;
bmch.bcBitCount = getBinIO()->read16_le () ;
switch (bmch.bcBitCount) {
case 1:
setSamplesPerVertex (SamplesPerVertex_SmallPalette) ;
setEmbValueModulus (EmbValueModulus_SmallPalette) ;
setRadius (Radius_Palette) ;
break ;
case 4:
setSamplesPerVertex (SamplesPerVertex_SmallPalette) ;
setEmbValueModulus (EmbValueModulus_SmallPalette) ;
setRadius (Radius_Palette) ;
break ;
case 8:
setSamplesPerVertex (SamplesPerVertex_LargePalette) ;
setEmbValueModulus (EmbValueModulus_LargePalette) ;
setRadius (Radius_Palette) ;
break ;
case 24:
setSamplesPerVertex (SamplesPerVertex_RGB) ;
setEmbValueModulus (EmbValueModulus_RGB) ;
setRadius (Radius_RGB) ;
break ;
default:
if (getBinIO()->is_std()) {
throw NotImplementedError (_("the bmp data from standard input has a format that is not supported (bcBitCount: %d)."), bmch.bcBitCount) ;
}
else {
throw NotImplementedError (_("the bmp file \"%s\" has a format that is not supported (bcBitCount: %d)."), getBinIO()->getName().c_str(), bmch.bcBitCount) ;
}
break ;
}
if (bmch.bcBitCount != 24) {
/* a color table exists */
unsigned int ncolors = 0 ;
Palette = new ColorPalette() ;
switch (bmch.bcBitCount) {
case 1: {
if (Args.Command.getValue() == EMBED) {
Warning w (_("using a black/white bitmap as cover is very insecure!")) ;
w.printMessage() ;
}
ncolors = 2 ;
break ; }
case 4: {
if (Args.Command.getValue() == EMBED) {
Warning w (_("using a 16-color bitmap as cover is very insecure!")) ;
w.printMessage() ;
}
ncolors = 16 ;
break ; }
case 8: {
ncolors = 256 ;
break ; }
default: {
myassert (0) ;
break ; }
}
for (unsigned int i = 0 ; i < ncolors ; i++) {
unsigned char b = getBinIO()->read8() ;
unsigned char g = getBinIO()->read8() ;
unsigned char r = getBinIO()->read8() ;
Palette->addEntry (r, g, b) ;
}
}
}
/* writes the headers of a bmp file to disk */
void BmpFile::writeheaders ()
{
try {
getBinIO()->write16_le (bmfh.bfType) ;
getBinIO()->write32_le (bmfh.bfSize) ;
getBinIO()->write16_le (bmfh.bfReserved1) ;
getBinIO()->write16_le (bmfh.bfReserved2) ;
getBinIO()->write32_le (bmfh.bfOffBits) ;
switch (getSubformat()) {
case WIN: {
bmpwin_writeheaders() ;
break ; }
case OS2: {
bmpos2_writeheaders() ;
break ; }
default: {
myassert (0) ;
break ; }
}
}
catch (BinaryOutputError e) {
switch (e.getType()) {
case BinaryOutputError::FILE_ERR: {
throw SteghideError (_("an error occured while writing the bmp headers to the file \"%s\"."), getBinIO()->getName().c_str()) ;
break ; }
case BinaryOutputError::STDOUT_ERR: {
throw SteghideError (_("an error occured while writing the bmp headers to standard output.")) ;
break ; }
}
}
}
void BmpFile::bmpwin_writeheaders ()
{
getBinIO()->write32_le (bmih.biSize) ;
getBinIO()->write32_le (bmih.biWidth) ;
getBinIO()->write32_le (bmih.biHeight) ;
getBinIO()->write16_le (bmih.biPlanes) ;
getBinIO()->write16_le (bmih.biBitCount) ;
getBinIO()->write32_le (bmih.biCompression) ;
getBinIO()->write32_le (bmih.biSizeImage) ;
getBinIO()->write32_le (bmih.biXPelsPerMeter) ;
getBinIO()->write32_le (bmih.biYPelsPerMeter) ;
getBinIO()->write32_le (bmih.biClrUsed) ;
getBinIO()->write32_le (bmih.biClrImportant) ;
if (Palette != NULL) {
for (unsigned int i = 0 ; i < Palette->getSize() ; i++) {
getBinIO()->write8 ((*Palette)[i].Blue) ;
getBinIO()->write8 ((*Palette)[i].Green) ;
getBinIO()->write8 ((*Palette)[i].Red) ;
getBinIO()->write8 (0) ;
}
}
}
void BmpFile::bmpos2_writeheaders ()
{
getBinIO()->write32_le (bmch.bcSize) ;
getBinIO()->write16_le (bmch.bcWidth) ;
getBinIO()->write16_le (bmch.bcHeight) ;
getBinIO()->write16_le (bmch.bcPlanes) ;
getBinIO()->write16_le (bmch.bcBitCount) ;
if (Palette != NULL) {
for (unsigned int i = 0 ; i < Palette->getSize() ; i++) {
getBinIO()->write8 ((*Palette)[i].Blue) ;
getBinIO()->write8 ((*Palette)[i].Green) ;
getBinIO()->write8 ((*Palette)[i].Red) ;
}
}
}
/* returns the number of bytes used to store the pixel data of one scan line */
unsigned long BmpFile::calcLinelength ()
{
unsigned long retval = 0 ;
switch (getSubformat()) {
case WIN: {
if (bmih.biBitCount * bmih.biWidth % 8 == 0) {
retval = bmih.biBitCount * bmih.biWidth / 8 ;
}
else {
retval = (bmih.biBitCount * bmih.biWidth / 8) + 1;
}
break ; }
case OS2: {
if (bmch.bcBitCount * bmch.bcWidth % 8 == 0) {
retval = bmch.bcBitCount * bmch.bcWidth / 8 ;
}
else {
retval = (bmch.bcBitCount * bmch.bcWidth / 8) + 1;
}
break ; }
default: {
myassert (0) ;
break ; }
}
return retval ;
}
/* reads a bmp file from disk into a CVRSTGFILE structure */
void BmpFile::readdata ()
{
try {
unsigned long linelength = calcLinelength () ;
unsigned long height = getHeight () ;
int paddinglength = 0 ;
if (linelength % 4 == 0) {
paddinglength = 0 ;
}
else {
paddinglength = 4 - (linelength % 4) ;
}
BitmapData.resize (height * linelength) ;
for (unsigned long line = 0 ; line < height ; line++) {
for (unsigned long posinline = 0 ; posinline < linelength ; posinline++) {
BitmapData[line * linelength + posinline] = getBinIO()->read8() ;
}
for (int i = 0 ; i < paddinglength ; i++) {
if (getBinIO()->read8() != 0) {
Warning w (_("maybe corrupted bmp data (padding byte at 0x%lx set to non-zero)."), getBinIO()->getPos() - 1) ;
w.printMessage() ;
}
}
}
atend.clear() ;
while (!getBinIO()->eof()) {
atend.push_back (getBinIO()->read8()) ;
}
}
catch (BinaryInputError e) {
switch (e.getType()) {
case BinaryInputError::FILE_ERR: {
throw SteghideError (_("an error occured while reading the bmp data from the file \"%s\"."), getBinIO()->getName().c_str()) ;
break ; }
case BinaryInputError::FILE_EOF: {
throw SteghideError (_("premature end of file \"%s\" while reading bmp data."), getBinIO()->getName().c_str()) ;
break ; }
case BinaryInputError::STDIN_ERR: {
throw SteghideError (_("an error occured while reading the bmp data from standard input.")) ;
break ; }
case BinaryInputError::STDIN_EOF: {
throw SteghideError (_("premature end of bmp data from standard input.")) ;
break ; }
}
}
}
void BmpFile::writedata ()
{
try {
unsigned long linelength = calcLinelength () ;
unsigned long height = getHeight () ;
unsigned int paddinglength = 0 ;
if (linelength % 4 == 0) {
paddinglength = 0 ;
}
else {
paddinglength = 4 - (linelength % 4) ;
}
for (unsigned long line = 0 ; line < height ; line++) {
for (unsigned long posinline = 0 ; posinline < linelength ; posinline++) {
getBinIO()->write8 (BitmapData[line * linelength + posinline]) ;
}
// write padding bytes
for (unsigned int i = 0 ; i < paddinglength ; i++) {
getBinIO()->write8 (0) ;
}
}
for (std::vector<unsigned char>::iterator i = atend.begin() ; i != atend.end() ; i++) {
getBinIO()->write8 (*i) ;
}
}
catch (BinaryOutputError e) {
switch (e.getType()) {
case BinaryOutputError::FILE_ERR: {
throw SteghideError (_("an error occured while writing the bitmap data to the file \"%s\"."), getBinIO()->getName().c_str()) ;
break ; }
case BinaryOutputError::STDOUT_ERR: {
throw SteghideError (_("an error occured while writing the bitmap data to standard output.")) ;
break ; }
}
}
}

149
steghide-src/BmpFile.h Normal file
View File

@ -0,0 +1,149 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BMPFILE_H
#define SH_BMPFILE_H
#include <vector>
#include "CvrStgFile.h"
class BinaryIO ;
class ColorPalette ;
class BmpFile : public CvrStgFile {
public:
BmpFile (void) ;
BmpFile (BinaryIO *io) ;
~BmpFile (void) ;
void read (BinaryIO *io) ;
void write (void) ;
std::list<CvrStgFile::Property> getProperties (void) const ;
std::vector<MatchingAlgorithm*> getMatchingAlgorithms (Graph* g, Matching* m) const ;
unsigned long getNumSamples (void) const ;
void replaceSample (const SamplePos pos, const SampleValue* s) ;
SampleValue* getSampleValue (SamplePos pos) const ;
std::vector<SampleValueAdjacencyList*> calcSVAdjacencyLists (const std::vector<SampleValue*>& svs) const ;
unsigned short getBitCount (void) const ;
unsigned long getWidth (void) const ;
unsigned long getHeight (void) const ;
ColorPalette *getPalette (void) const ;
protected:
typedef struct struct_BITMAPFILEHEADER {
unsigned short bfType ;
unsigned long bfSize ;
unsigned short bfReserved1 ;
unsigned short bfReserved2 ;
unsigned long bfOffBits ;
} BITMAPFILEHEADER ;
/* windows bmp file format */
typedef struct struct_BITMAPINFOHEADER {
unsigned long biSize ;
signed long biWidth ;
signed long biHeight ;
unsigned short biPlanes ;
unsigned short biBitCount ;
unsigned long biCompression ;
unsigned long biSizeImage ;
signed long biXPelsPerMeter ;
signed long biYPelsPerMeter ;
unsigned long biClrUsed ;
unsigned long biClrImportant ;
} BITMAPINFOHEADER ;
/* os/2 bmp file format */
typedef struct struct_BITMAPCOREHEADER {
unsigned long bcSize;
unsigned short bcWidth;
unsigned short bcHeight;
unsigned short bcPlanes;
unsigned short bcBitCount;
} BITMAPCOREHEADER ;
private:
static const unsigned int IdBm = 19778 ;
static const unsigned short SizeBMFILEHEADER = 14 ;
static const unsigned short SizeBMINFOHEADER = 40 ;
static const unsigned short SizeBMCOREHEADER = 12 ;
static const unsigned int COMPRESSION_BI_RGB = 0 ;
static const unsigned short SamplesPerVertex_SmallPalette = 2 ;
static const unsigned short SamplesPerVertex_LargePalette = 3 ;
static const unsigned short SamplesPerVertex_RGB = 2 ;
/// the default radius for palette images (400 = 20^2)
static const UWORD32 Radius_Palette = 400 ;
/// the default radius for RGB images (100 = 10^2)
static const UWORD32 Radius_RGB = 100 ;
static const EmbValue EmbValueModulus_SmallPalette = 2 ;
static const EmbValue EmbValueModulus_LargePalette = 4 ;
static const EmbValue EmbValueModulus_RGB = 4 ; // if changed here - also change BmpRGBSampleValue::calcEValue
enum SUBFORMAT { WIN, OS2 } ;
SUBFORMAT subformat ;
BITMAPFILEHEADER bmfh ;
BITMAPINFOHEADER bmih ;
BITMAPCOREHEADER bmch ;
ColorPalette* Palette ;
/**
* contains the bitmap in the following format
* bitmap[i] is the pixel data of the i-th row of the bitmap
* bitmap[i][j] is the j-th byte of the pixel data of the i-th row of the bitmap
* if bitcount is < 8 then bitmap[i][j] contains the pixels as read in from the file (i.e. in the "wrong" direction)
* this is taken care of in the calcRCB function
**/
std::vector<std::vector <unsigned char> > bitmap ;
/**
* contains the bitmap data in the same order as read from file (but without padding bytes)
**/
std::vector<BYTE> BitmapData ;
/// contains bytes that are appended at the end of the bitmap data (some image editors apparently do this)
std::vector<BYTE> atend ;
void readheaders () ;
void bmpwin_readheaders () ;
void bmpos2_readheaders () ;
void writeheaders () ;
void bmpwin_writeheaders () ;
void bmpos2_writeheaders () ;
void readdata () ;
void writedata () ;
/**
* translate a sample position into a <index,firstbit> pair "pointing" into the BitmapData array
* \param pos a sample position
* \param index a pointer to a variable that will contain the array index used to access the pos-th sample
* \param firstbit the firstbit in BitmapData[index] that belongs to the sample with the given position
**/
void calcIndex (SamplePos pos, unsigned long* index, unsigned short* firstbit) const ;
unsigned long calcLinelength () ;
SUBFORMAT getSubformat (void) const ;
} ;
#endif /* ndef SH_BMPFILE_H */

View File

@ -0,0 +1,63 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "BmpFile.h"
#include "BmpPaletteSampleValue.h"
#include "ColorPalette.h"
BmpPaletteSampleValue::BmpPaletteSampleValue (unsigned char i)
: BmpSampleValue(), Index(i)
{
const BmpFile* bmpfile = dynamic_cast<const BmpFile*> (Globs.TheCvrStgFile) ;
myassert (bmpfile) ;
Palette = bmpfile->getPalette() ;
Key = ((unsigned long) getIndex() << 24) | ((unsigned long) getRed() << 16) |
((unsigned long) getGreen() << 8) | ((unsigned long) getBlue()) ;
EValue = calcEValue(getIndex()) ;
}
SampleValue* BmpPaletteSampleValue::getNearestTargetSampleValue (EmbValue t) const
{
BmpPaletteSampleValue* sv_mindist = NULL ;
UWORD32 mindist = UWORD32_MAX ;
for (unsigned int i = 0 ; i < Palette->getSize() ; i++) {
if (calcEValue(i) == t) {
BmpPaletteSampleValue* destsv = new BmpPaletteSampleValue (i) ;
UWORD32 curdist = calcDistance (destsv) ;
if (curdist < mindist) {
delete sv_mindist ;
sv_mindist = destsv ;
mindist = curdist ;
}
else {
delete destsv ;
}
}
}
myassert (sv_mindist != NULL) ;
return ((SampleValue*) sv_mindist) ;
}
std::string BmpPaletteSampleValue::getName () const
{
char buf[128] ;
sprintf (buf, "i%ur%ug%ub%u", getIndex(), getRed(), getGreen(), getBlue()) ;
return std::string (buf) ;
}

View File

@ -0,0 +1,53 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BMPPALETTESAMPLEVALUE_H
#define SH_BMPPALETTESAMPLEVALUE_H
#include "BmpSampleValue.h"
#include "CvrStgFile.h"
#include "ColorPalette.h"
#include "common.h"
/**
* \class BmpPaletteSampleValue
* \brief a sample in a bmp palette (i.e. in a 1-,4- or 8-bit) file
**/
class BmpPaletteSampleValue : public BmpSampleValue {
public:
BmpPaletteSampleValue (BYTE i) ;
SampleValue* getNearestTargetSampleValue (EmbValue t) const ;
std::string getName (void) const ;
BYTE getIndex (void) const { return Index ; } ;
BYTE getRed (void) const { return (*Palette)[Index].Red ; } ;
BYTE getGreen (void) const { return (*Palette)[Index].Green ; } ;
BYTE getBlue (void) const { return (*Palette)[Index].Blue ; } ;
private:
ColorPalette* Palette ;
BYTE Index ;
EmbValue calcEValue (BYTE idx) const
{ return (idx % Globs.TheCvrStgFile->getEmbValueModulus()) ; } ;
} ;
#endif // ndef SH_BMPPALETTESAMPLEVALUE_H

View File

@ -0,0 +1,142 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "BmpRGBSampleValue.h"
BmpRGBSampleValue::BmpRGBSampleValue (BYTE r, BYTE g, BYTE b)
: BmpSampleValue(), Color(r, g, b)
{
Key = calcKey (Color) ;
EValue = calcEValue (Color) ;
}
BmpRGBSampleValue::BmpRGBSampleValue (RGBTriple t)
: BmpSampleValue(), Color(t)
{
Key = calcKey (Color) ;
EValue = calcEValue (Color) ;
}
UWORD32 BmpRGBSampleValue::calcDistance (const SampleValue *s) const
{
const BmpRGBSampleValue *sample = (const BmpRGBSampleValue*) s ;
/* If s is not a BmpRGBSampleValue then we get into real trouble here.
But calcDistance is called very often, a dynamic_cast costs a lot of time and
it does not make sense to pass anything but a BmpRGBSampleValue as s anyway. */
int dr = (int) Color.Red - (int) sample->Color.Red ;
int dg = (int) Color.Green - (int) sample->Color.Green ;
int db = (int) Color.Blue - (int) sample->Color.Blue ;
return (UWORD32) (dr*dr + dg*dg + db*db) ;
}
SampleValue *BmpRGBSampleValue::getNearestTargetSampleValue (EmbValue t) const
{
std::vector<RGBTriple> candidates ;
BYTE cube[3][2] ;
cube[RED][UP] = Color.Red ; cube[RED][DOWN] = Color.Red ;
cube[GREEN][UP] = Color.Green ; cube[GREEN][DOWN] = Color.Green ;
cube[BLUE][UP] = Color.Blue ; cube[BLUE][DOWN] = Color.Blue ;
do {
cube[RED][UP] = plus(cube[RED][UP], 1) ;
cube[RED][DOWN] = minus(cube[RED][DOWN], 1) ;
cube[GREEN][UP] = plus(cube[GREEN][UP], 1) ;
cube[GREEN][DOWN] = minus(cube[GREEN][DOWN], 1) ;
cube[BLUE][UP] = plus(cube[BLUE][UP], 1) ;
cube[BLUE][DOWN] = minus(cube[BLUE][DOWN], 1) ;
addNTSVCandidates (candidates, cube, RED, UP, GREEN, BLUE, t) ;
addNTSVCandidates (candidates, cube, RED, DOWN, GREEN, BLUE, t) ;
addNTSVCandidates (candidates, cube, GREEN, UP, RED, BLUE, t) ;
addNTSVCandidates (candidates, cube, GREEN, DOWN, RED, BLUE, t) ;
addNTSVCandidates (candidates, cube, BLUE, UP, RED, GREEN, t) ;
addNTSVCandidates (candidates, cube, BLUE, DOWN, RED, GREEN, t) ;
} while (candidates.empty()) ;
// calculate minimal distance
UWORD32 mindist = UWORD32_MAX ;
for (std::vector<RGBTriple>::const_iterator cit = candidates.begin() ; cit != candidates.end() ; cit++) {
UWORD32 curdist = Color.calcDistance(*cit) ;
if (curdist < mindist) {
mindist = curdist ;
}
}
// choose only from those with the minimal distance
std::vector<RGBTriple> finalcandidates ;
for (std::vector<RGBTriple>::const_iterator cit = candidates.begin() ; cit != candidates.end() ; cit++) {
if (Color.calcDistance(*cit) == mindist) {
finalcandidates.push_back(*cit) ;
}
}
unsigned int rnd = (unsigned int) RndSrc.getValue (finalcandidates.size()) ;
return ((SampleValue*) new BmpRGBSampleValue (finalcandidates[rnd])) ;
}
void BmpRGBSampleValue::addNTSVCandidates (std::vector<RGBTriple>& cands, const BYTE cube[3][2], COLOR fc, DIRECTION fd, COLOR i1, COLOR i2, EmbValue t) const
{
for (BYTE value1 = cube[i1][DOWN] ; value1 < cube[i1][UP] ; value1++) {
for (BYTE value2 = cube[i2][DOWN] ; value2 < cube[i2][UP] ; value2++) {
// create an RGBTriple
BYTE color[3] ;
color[fc] = cube[fc][fd] ;
color[i1] = value1 ;
color[i2] = value2 ;
RGBTriple rgb (color[RED], color[GREEN], color[BLUE]) ;
if (calcEValue (rgb) == t) {
// add rgb to candidates...
bool found = false ;
for (std::vector<RGBTriple>::const_iterator cit = cands.begin() ; cit != cands.end() ; cit++) {
if (*cit == rgb) {
found = true ;
}
}
if (!found) {
cands.push_back (rgb) ;
}
}
}
}
}
std::string BmpRGBSampleValue::getName () const
{
char buf[128] ;
sprintf (buf, "r%ug%ub%u", getRed(), getGreen(), getBlue()) ;
return std::string (buf) ;
}
BYTE BmpRGBSampleValue::minus (BYTE a, BYTE b) const
{
BYTE retval = 0 ;
if (a > b) {
retval = a - b ;
}
return retval ;
}
BYTE BmpRGBSampleValue::plus (BYTE a, BYTE b) const
{
unsigned int sum = a + b ;
return ((sum <= 255) ? sum : 255) ;
}

View File

@ -0,0 +1,80 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BMPRGBSAMPLEVALUE_H
#define SH_BMPRGBSAMPLEVALUE_H
#include "BmpSampleValue.h"
#include "RGBTriple.h"
#include "common.h"
/**
* \class BmpRGBSampleValue
* \brief a sample in a bmp rgb (i.e. 24-bit) file
**/
class BmpRGBSampleValue : public BmpSampleValue {
public:
BmpRGBSampleValue (BYTE r, BYTE g, BYTE b) ;
BmpRGBSampleValue (RGBTriple t) ;
UWORD32 calcDistance (const SampleValue *s) const ;
SampleValue* getNearestTargetSampleValue (EmbValue t) const ;
std::string getName (void) const ;
BYTE getRed (void) const { return Color.Red ; } ;
BYTE getGreen (void) const { return Color.Green ; } ;
BYTE getBlue (void) const { return Color.Blue ; } ;
private:
RGBTriple Color ;
UWORD32 calcKey (const RGBTriple& rgb) const
{ return (((UWORD32) rgb.Red << 16) | ((UWORD32) rgb.Green << 8) | ((UWORD32) rgb.Blue)) ;} ;
EmbValue calcEValue (const RGBTriple& rgb) const
// { /* for Modulus 8 */ return ((EmbValue) (((rgb.Red & 1) << 2) | ((rgb.Green & 1) << 1) | (rgb.Blue & 1))) ; } ;
{ /* for Modulus 4 */ return ((EmbValue) ((((rgb.Red & 1) ^ (rgb.Green & 1)) << 1) | ((rgb.Red & 1) ^ (rgb.Blue & 1)))) ; } ;
enum COLOR { RED, GREEN, BLUE } ;
enum DIRECTION { UP, DOWN } ;
/**
* add the BYTEs a and b
* \return min(255, a + b)
**/
BYTE plus (BYTE a, BYTE b) const ;
/**
* substract the BYTE b from the BYTE a
* \return max(0, a - b)
**/
BYTE minus (BYTE a, BYTE b) const ;
/**
* add candidates for the nearest target sample value
* \param cands the candidates vector
* \param cube the color values describing the current search cube
* \param fc the fixed color
* \param fd the fixed side of the fixed color
**/
void addNTSVCandidates (std::vector<RGBTriple>& cands, const BYTE cube[3][2], COLOR fc, DIRECTION fd, COLOR i1, COLOR i2, EmbValue t) const ;
} ;
#endif // ndef SH_BMPRGBSAMPLEVALUE_H

View File

@ -0,0 +1,35 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "BmpSampleValue.h"
#include "common.h"
UWORD32 BmpSampleValue::calcDistance (const SampleValue *s) const
{
const BmpSampleValue *sample = (const BmpSampleValue*) s ;
/* If s is not a BmpSampleValue then we get into real trouble here.
But calcDistance is called very often, a dynamic_cast costs a lot of time and
it does not make sense to pass anything but a BmpSampleValue as s anyway. */
int dr = (int) getRed() - (int) sample->getRed() ;
int dg = (int) getGreen() - (int) sample->getGreen() ;
int db = (int) getBlue() - (int) sample->getBlue() ;
return (UWORD32) (dr*dr + dg*dg + db*db) ;
}

View File

@ -0,0 +1,54 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_BMPSAMPLE_H
#define SH_BMPSAMPLE_H
#include "SampleValue.h"
#include "common.h"
/**
* \class BmpSampleValue
* \brief an (abstract) sample value in a bmp file
**/
class BmpSampleValue : public SampleValue {
public:
BmpSampleValue (void) : SampleValue() {} ;
virtual UWORD32 calcDistance (const SampleValue *s) const ;
/**
* get the red color component
**/
virtual unsigned char getRed (void) const = 0 ;
/**
* get the green color component
**/
virtual unsigned char getGreen (void) const = 0 ;
/**
* get the blue color component
**/
virtual unsigned char getBlue (void) const = 0 ;
} ;
#endif // ndef SH_BMPSAMPLE_H

View File

@ -0,0 +1,57 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_COLORPALETTE_H
#define SH_COLORPALETTE_H
#include <vector>
#include "RGBTriple.h"
#include "common.h"
/**
* \class ColorPalette
* \brief a color palette
*
* This class is essentially a vector<RGBTriple> with
* some wrappers for exisiting methods.
**/
class ColorPalette : public std::vector<RGBTriple> {
public:
/**
* get the size, i.e. the number of entries of this color palette
**/
unsigned int getSize (void) const
{ return size() ; } ;
/**
* add (a copy of) rgb to the end of this color palette
**/
void addEntry (RGBTriple rgb)
{ push_back (rgb) ; } ;
/**
* add the color r/g/b to the end of this color palette
**/
void addEntry (BYTE r, BYTE g, BYTE b)
{ push_back (RGBTriple (r, g, b)) ; } ;
} ;
#endif // ndef SH_COLORPALETTE_H

222
steghide-src/CvrStgFile.cc Normal file
View File

@ -0,0 +1,222 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "DFSAPHeuristic.h"
#include "AuFile.h"
#include "AUtils.h"
#include "BmpFile.h"
#include "CvrStgFile.h"
#include "JpegFile.h"
#include "SampleValue.h"
#include "SampleValueAdjacencyList.h"
#include "Utils.h"
#include "WavFile.h"
#include "WKSConstructionHeuristic.h"
#include "common.h"
#include "error.h"
#include "msg.h"
CvrStgFile::CvrStgFile ()
: BinIO(NULL), SamplesPerVertex(0), Radius(0), EmbValueModulus(0)
{
Globs.TheCvrStgFile = this ;
}
CvrStgFile::~CvrStgFile (void)
{
if (BinIO != NULL) {
delete BinIO ;
}
}
void CvrStgFile::setRadius (UWORD32 r)
{
if (Args.Radius.is_set()) {
Radius = Args.Radius.getValue() ;
}
else {
Radius = r ;
}
}
void CvrStgFile::read (BinaryIO *io)
{
setBinIO (io) ;
}
void CvrStgFile::write (void)
{
}
void CvrStgFile::transform (const std::string& stgfn)
{
delete BinIO ;
BinIO = NULL ;
BinIO = new BinaryIO (stgfn, BinaryIO::WRITE) ;
}
std::vector<SampleValueAdjacencyList*> CvrStgFile::calcSVAdjacencyLists (const std::vector<SampleValue*>& svs) const
{
EmbValue m = getEmbValueModulus() ;
std::vector<SampleValueAdjacencyList*> lists (m) ;
for (EmbValue i = 0 ; i < m ; i++) {
lists[i] = new SampleValueAdjacencyList (svs.size()) ;
}
for (SampleValueLabel i = 0 ; i < svs.size() ; i++) { // to be integrated into lists
SampleValueAdjacencyList* sval = lists[svs[i]->getEmbeddedValue()] ;
for (SampleValueLabel j = 0 ; j < svs.size() ; j++) { // line where integration should happen
if ((svs[i]->isNeighbour(svs[j])) && (i != j)) {
(*sval)[svs[j]].push_back (svs[i]) ;
}
}
}
for (EmbValue i = 0 ; i < m ; i++) {
lists[i]->sort() ;
}
return lists ;
}
std::vector<MatchingAlgorithm*> CvrStgFile::getMatchingAlgorithms (Graph* g, Matching* m) const
{
std::vector<MatchingAlgorithm*> retval ;
retval.push_back (new WKSConstructionHeuristic (g, m)) ;
retval.push_back (new DFSAPHeuristic (g, m)) ;
return retval ;
}
EmbValue CvrStgFile::getEmbeddedValue (const SamplePos pos) const
{
SampleValue* sv = getSampleValue(pos) ;
EmbValue retval = sv->getEmbeddedValue() ;
delete sv ;
return retval ;
}
unsigned long CvrStgFile::getCapacity () const
{
float maxnvertices = getNumSamples() / getSamplesPerVertex() ;
float maxnbits = maxnvertices * log2(getEmbValueModulus()) ;
return ((unsigned long) (maxnbits / 8)) ;
}
std::string CvrStgFile::getHRCapacity () const
{
return Utils::formatHRSize (getCapacity()) ;
}
#ifdef DEBUG
std::map<SampleKey,unsigned long>* CvrStgFile::getFrequencies ()
{
unsigned long n = getNumSamples() ;
std::map<SampleKey,unsigned long>* table = new std::map<SampleKey,unsigned long> () ;
for (unsigned long pos = 0 ; pos < n ; pos++) {
SampleValue *sv = getSampleValue (pos) ;
(*table)[sv->getKey()]++ ;
delete sv ;
}
return table ;
}
void CvrStgFile::printFrequencies (const std::map<SampleKey,unsigned long>& freqs)
{
for (std::map<SampleKey,unsigned long>::const_iterator fit = freqs.begin() ; fit != freqs.end() ; fit++) {
std::cout << fit->first << ": " << fit->second << std::endl ;
}
}
#endif // def DEBUG
CvrStgFile::FILEFORMAT CvrStgFile::guessff (BinaryIO *io)
{
char buf[4] = { '\0', '\0', '\0', '\0' } ;
FILEFORMAT retval = UNKNOWN ;
for (unsigned int i = 0 ; i < 2 ; i++) {
buf[i] = (char) io->read8() ;
}
if (strncmp ("BM", buf, 2) == 0) {
retval = BMP ;
}
else if ((unsigned char) buf[0] == 0xFF && (unsigned char) buf[1] == 0xD8) {
retval = JPEG ;
}
else {
for (unsigned int i = 2 ; i < 4 ; i++) {
buf[i] = (char) io->read8() ;
}
if (strncmp (".snd", buf, 4) == 0) {
retval = AU ;
}
else if (strncmp ("RIFF", buf, 4) == 0) {
retval = WAV ;
}
}
return retval ;
}
CvrStgFile* CvrStgFile::readFile (const std::string& fn)
{
BinaryIO *BinIO = new BinaryIO (fn, BinaryIO::READ) ;
CvrStgFile *file = NULL ;
switch (guessff (BinIO)) {
case UNKNOWN: {
throw UnSupFileFormat (BinIO) ;
break ; }
case BMP: {
file = new BmpFile (BinIO) ;
break ; }
case WAV: {
file = new WavFile (BinIO) ;
break ; }
case AU: {
file = new AuFile (BinIO) ;
break ; }
case JPEG: {
#ifdef USE_LIBJPEG
file = new JpegFile (BinIO) ;
#else
throw SteghideError (_("can not read input file. steghide has been compiled without support for jpeg files.")) ;
#endif
break ; }
default: {
myassert(0) ;
break ; }
}
return file ;
}

189
steghide-src/CvrStgFile.h Normal file
View File

@ -0,0 +1,189 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_CVRSTGFILE_H
#define SH_CVRSTGFILE_H
#include <list>
#include <string>
#include <map>
#include "BinaryIO.h"
#include "CvrStgObject.h"
class Graph ;
class Matching ;
class MatchingAlgorithm ;
class SampleValue ;
class SampleValueAdjacencyList ;
/**
* \class CvrStgFile
* \brief a cover-/stego-file
*
* file-format specific constants are handled as follows:
* CvrStgFile contains a protected set-function (e.g. setSamplesPerVertex), a public
* get-function (e.g. getSamplesPerVertex() const) and a private variable. The public get
* function does nothing else than returning the private variable, which must be set
* as soon as possible (if it is not set, it will contain a null value set in CvrStgFile::CvrStgFile).
**/
class CvrStgFile : public CvrStgObject {
public:
/**
* this function reads the file with name fn and returns
* a *File object of the correct type casted to CvrStgFile.
**/
static CvrStgFile *readFile (const std::string& fn) ;
class Property : private std::pair<std::string,std::string> {
public:
Property (std::string key, std::string value)
: std::pair<std::string,std::string> (key, value) {} ;
std::string getKey (void) const
{ return first ; } ;
std::string getValue (void) const
{ return second ; } ;
} ;
CvrStgFile (void) ;
virtual ~CvrStgFile (void) ;
virtual void read (BinaryIO *io) ;
virtual void write (void) ;
void transform (const std::string& fn) ;
virtual std::list<Property> getProperties (void) const = 0 ;
/**
* calculate a vector a SampleValueAdjacencyLists
* \param svs a vector of unique(!) sample values where svs[i]->getLabel() == i holds for all i
* \return a vector of SampleValueAdjacencyLists where retval[i] only contains sample values with getEmbValue() == i
*
* Every row in the adjacency lists must be sorted in the following order: The first sample value has
* the least distance to the source sample value, the last has the largest distance. If two sample values
* in one row have the same distance to the source sample value, the order does not matter.
*
* May be overridden in derived class to provide a faster version.
**/
virtual std::vector<SampleValueAdjacencyList*> calcSVAdjacencyLists (const std::vector<SampleValue*>& svs) const ;
/**
* get recommended list of matching algorithms
* \param m an empty matching - will be used in construction of MatchingAlgorithm objects
*
* The MatchingAlgorithm objects returned by this function should be deleted by the caller
* if they are no longer needed.
**/
virtual std::vector<MatchingAlgorithm*> getMatchingAlgorithms (Graph* g, Matching* m) const ;
/**
* get the name of this cvrstgfile
**/
const std::string& getName (void) const
{ return getBinIO()->getName() ; } ;
bool is_std (void) const
{ return getBinIO()->is_std() ; } ;
/**
* get the capacity of this cvrstgfile
* \return the capacity in bytes
**/
unsigned long getCapacity (void) const ;
/**
* get the capacity as a human-readable string
**/
std::string getHRCapacity (void) const ;
/**
* get the number of samples per vertex (this is a file-format specific constant)
**/
unsigned short getSamplesPerVertex (void) const
{ return SamplesPerVertex ; } ;
/**
* get the neighbourhood radius (this is a file-format specific constant)
**/
UWORD32 getRadius (void) const
{ return Radius ; } ;
/**
* values that are embedded in samples will be in 0...Modulus-1 (this is a file-format specific constant)
**/
EmbValue getEmbValueModulus (void) const
{ return EmbValueModulus ; } ;
/**
* get the value that is embedded in the Sample pos
* \param pos the position of the sample
* \return the value that is embedded in the sample at the given sample position
*
* This is equivalent to getSample(pos)->getEmbeddedValue() and is implemented here like this.
*
* May be overwritten by derived class to provide a faster version.
**/
virtual EmbValue getEmbeddedValue (const SamplePos pos) const ;
#ifdef DEBUG
/**
* return a map that contains the absolute sample frequencies indexed by sample key
**/
virtual std::map<SampleKey,unsigned long>* getFrequencies (void) ;
/**
* print the frequency table freqs
*
* This method is meant to be overriden in *File to provide a file-format specific way
* of printing a frequency table.
**/
virtual void printFrequencies (const std::map<SampleKey,unsigned long>& freqs) ;
#endif
protected:
void setSamplesPerVertex (unsigned short spv)
{ SamplesPerVertex = spv ; } ;
/**
* set Radius to r unless Args.Radius is set (set Radius to Args.Radius.getValue() then)
**/
void setRadius (UWORD32 r) ;
void setEmbValueModulus (EmbValue m)
{ EmbValueModulus = m ; } ;
void setBinIO (BinaryIO* io)
{ BinIO = io ; } ;
BinaryIO* getBinIO (void) const
{ return BinIO ; } ;
private:
enum FILEFORMAT { UNKNOWN, BMP, WAV, AU, JPEG } ;
/**
* guesses the file format by looking at the first few bytes
**/
static FILEFORMAT guessff (BinaryIO *io) ;
BinaryIO* BinIO ;
unsigned short SamplesPerVertex ;
UWORD32 Radius ;
EmbValue EmbValueModulus ;
} ;
#endif /* ndef SH_CVRSTGFILE_H */

View File

@ -0,0 +1,67 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_CVRSTGOBJECT_H
#define SH_CVRSTGOBJECT_H
#include "common.h"
class SampleValue ;
/**
* \class CvrStgObject
* \brief an object that can hold embedded data
*
* This abstract base class provides an interface for every class that is able
* to hold embedded data. Something that can hold embedded data is essentially
* though of as an array of samples.
*
* Definitions:
* Embedded Bit...a bit to be embedded (one bit in the original or extracted embfile)
* Sample...the smallest data unit in a file (e.g. a RGB triple, a DCT coefficient)
**/
class CvrStgObject {
public:
/**
* get the number of samples in this CvrStgObject
**/
virtual unsigned long getNumSamples (void) const = 0 ;
/**
* get the sample at position pos
* \param pos the position of a sample (must be in 0...getNumSamples()-1)
* \return the sample at the given position
*
* The sample object is created in this function and should be deleted by the caller.
* The derived class should check the condition(s) given above in its Implementation of this function.
**/
virtual SampleValue* getSampleValue (const SamplePos pos) const = 0 ;
/**
* replace a sample thus (possibly) altering the value of the bit returned by SampleValue->getBit()
* \param pos the position of the sample (must be in 0...getNumSamples()-1)
* \param s the sample value that should replace the current sample value (must be of correct type for this CvrStgObject)
*
* The derived class should check the condition(s) given above in its Implementation of this function.
**/
virtual void replaceSample (const SamplePos pos, const SampleValue* s) = 0 ;
} ;
#endif //ndef SH_CVRSTGOBJECT_H

View File

@ -0,0 +1,259 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "DFSAPHeuristic.h"
#include "Edge.h"
#include "EdgeIterator.h"
#include "Graph.h"
#include "Matching.h"
#include "common.h"
DFSAPHeuristic::DFSAPHeuristic (Graph* g, Matching* m, float goal, UWORD32 mne, EdgeIterator::ITERATIONMODE mo)
: MatchingAlgorithm (g, m, goal)
{
unsigned long numvertices = g->getNumVertices() ;
TimeCounter = 0 ;
TimeCounters = new UWORD32[numvertices] ;
VertexOnPath = new bool[numvertices] ;
EdgeIterators = new EdgeIterator[numvertices] ;
for (VertexLabel l = 0 ; l < numvertices ; l++) {
TimeCounters[l] = 0 ;
VertexOnPath[l] = false ;
EdgeIterators[l].reset (g->getVertex(l), mo) ;
}
EdgeIterator::setMaxNumEdges (mne) ;
#ifdef DEBUG
NSuccessful = 0 ;
NUnsuccessful = 0 ;
NEdgesSuccessful = 0 ;
NEdgesUnsuccessful = 0 ;
SuccessString = "" ;
#endif
}
DFSAPHeuristic::~DFSAPHeuristic ()
{
delete[] EdgeIterators ;
delete[] TimeCounters ;
delete[] VertexOnPath ;
}
void DFSAPHeuristic::reset (UWORD32 mne, EdgeIterator::ITERATIONMODE mo)
{
EdgeIterator::setMaxNumEdges (mne) ;
unsigned long numvertices = TheGraph->getNumVertices() ;
TimeCounter = 0 ;
for (VertexLabel l = 0 ; l < numvertices ; l++) {
VertexOnPath[l] = false ;
TimeCounters[l] = 0 ;
EdgeIterators[l].reset(mo) ;
}
}
void DFSAPHeuristic::run ()
{
const Edge** path = new const Edge*[TheGraph->getNumVertices()] ;
const std::list<Vertex*> ExposedVertices = TheMatching->getExposedVertices() ;
for (std::list<Vertex*>::const_iterator expv = ExposedVertices.begin() ;
(expv != ExposedVertices.end()) && (TheMatching->getCardinality() < CardinalityGoal) ; expv++) {
if (TheMatching->isExposed (*expv)) {
unsigned long pathlength = searchAugmentingPath (*expv, path) ;
#ifdef DEBUG
if (pathlength == 0) {
printDebug (5, "DFSAPHeuristic: could not find augmenting path for vertex %lu", (*expv)->getLabel()) ;
}
else {
if (RUNDEBUGLEVEL(5)) {
std::cerr << "DFSAPHeuristic: found augmenting path for vertex " << (*expv)->getLabel() << ": " ;
for (unsigned long i = 0 ; i < pathlength ; i++) {
std::cerr << path[i]->getVertex1()->getLabel() << "-" << path[i]->getVertex2()->getLabel() ;
if (i != pathlength - 1) {
std::cerr << ", " ;
}
}
std::cerr << std::endl ;
}
}
#endif
if (pathlength > 0) {
TheMatching->augment ((const Edge**) path, pathlength) ;
}
}
}
delete[] path ;
}
#ifdef DEBUG
#define pushOnPath(EDGE) \
printDebug (6, "DFSAPHeuristic: pushing edge on path: %lu - %lu", EDGE->getVertex1()->getLabel(), EDGE->getVertex2()->getLabel()) ; \
path[pathlen] = EDGE ; \
pathlen++ ; \
VertexOnPath[EDGE->getVertex1()->getLabel()] = true ; \
VertexOnPath[EDGE->getVertex2()->getLabel()] = true ; \
NEdgesPushed++ ;
#else
#define pushOnPath(EDGE) \
path[pathlen] = EDGE ; \
pathlen++ ; \
VertexOnPath[EDGE->getVertex1()->getLabel()] = true ; \
VertexOnPath[EDGE->getVertex2()->getLabel()] = true ;
#endif
unsigned long DFSAPHeuristic::searchAugmentingPath (Vertex *v0, const Edge** path)
{
#ifdef DEBUG
printDebug (5, "DFSAPHeuristic: searching augmenting path for vertex with label %lu", v0->getLabel()) ;
unsigned long long NEdgesPushed = 0 ;
#endif
TimeCounter++ ;
unsigned long pathlen = 0 ;
const Edge* e = NULL ;
while ((e = getNextEdge(v0)) != NULL) {
pushOnPath(e) ;
Vertex *w = e->getOtherVertex (v0) ;
if (TheMatching->isExposed(w)) {
#ifdef DEBUG
SuccessString += "+" ;
NSuccessful++ ;
NEdgesSuccessful += NEdgesPushed ;
#endif
return pathlen ;
}
// add matched edge
markVisited (w) ;
e = TheMatching->getMatchingEdge (w) ; // w is matched (because not exposed)
Vertex *w_next = e->getOtherVertex (w) ;
pushOnPath(e) ;
while (pathlen > 0) {
const Edge* e_next = getNextEdge (w_next) ;
if (e_next != NULL) { // found next edge
pushOnPath(e_next) ;
w = e_next->getOtherVertex (w_next) ;
if (TheMatching->isExposed(w)) {
#ifdef DEBUG
SuccessString += "+" ;
NSuccessful++ ;
NEdgesSuccessful += NEdgesPushed ;
#endif
return pathlen ;
}
// add matched edge
markVisited (w) ;
e = TheMatching->getMatchingEdge (w) ; // w is matched (because not exposed)
w_next = e->getOtherVertex (w) ;
pushOnPath(e) ;
}
else { // could not find next edge
#ifdef DEBUG
printDebug (6, "DFSAPHeuristic: could not find next edge from vertex with label %lu", w_next->getLabel()) ;
printDebug (6, "DFSAPHeuristic: popping edge %lu - %lu from path", path[pathlen - 1]->getVertex1()->getLabel(), path[pathlen - 1]->getVertex2()->getLabel()) ;
printDebug (6, "DFSAPHeuristic: popping edge %lu - %lu from path", path[pathlen - 2]->getVertex1()->getLabel(), path[pathlen - 2]->getVertex2()->getLabel()) ;
#endif
VertexOnPath[e->getVertex1()->getLabel()] = false ;
VertexOnPath[e->getVertex2()->getLabel()] = false ;
// matched edge: pop from path
myassert (path[pathlen - 1] == e) ;
pathlen-- ;
// unmatched edge: pop from path and delete (has been created only for path)
myassert (!TheMatching->includesEdge(path[pathlen - 1])) ;
pathlen-- ;
// set w,e,w_next to complete backtracking step
if (pathlen > 0) {
e = path[pathlen - 1] ;
const Edge* before_e = path[pathlen - 2] ;
if (before_e->contains (e->getVertex1())) {
w = e->getVertex1() ;
w_next = e->getVertex2() ;
}
else if (before_e->contains (e->getVertex2())) {
w = e->getVertex2() ;
w_next = e->getVertex1() ;
}
else {
myassert(false) ;
}
}
}
}
}
#ifdef DEBUG
SuccessString += "-" ;
NUnsuccessful++ ;
NEdgesUnsuccessful += NEdgesPushed ;
#endif
return pathlen ;
}
const Edge* DFSAPHeuristic::getNextEdge (Vertex *v)
{
if (isVisited(v)) {
if (EdgeIterators[v->getLabel()].isFinished()) {
return NULL ;
}
++(EdgeIterators[v->getLabel()]) ;
}
else {
EdgeIterators[v->getLabel()].reset() ;
markVisited(v) ;
}
const Edge* e = NULL ;
bool found = false ;
do {
if (EdgeIterators[v->getLabel()].isFinished()) {
// no more unexamined edges for this vertex
#ifdef DEBUG
printDebug (7, "DFSAPHeuristic::getNextEdge: no more unexamined edges for vertex %lu", v->getLabel()) ;
#endif
found = true ;
}
else {
VertexLabel pvlbl = EdgeIterators[v->getLabel()].getPartnerVertexLabel() ;
if (!(VertexOnPath[pvlbl] && isVisited(pvlbl))) { // edge is admissible
e = *EdgeIterators[v->getLabel()] ;
found = true ;
#ifdef DEBUG
printDebug (7, "DFSAPHeuristic::getNextEdge: admissible edge for vertex %lu goes to vertex %lu", v->getLabel(), pvlbl) ;
#endif
}
else {
++(EdgeIterators[v->getLabel()]) ;
}
}
} while (!found) ;
return e ;
}

View File

@ -0,0 +1,107 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_DFSAPHEURISTIC
#define SH_DFSAPHEURISTIC
#include "EdgeIterator.h"
#include "MatchingAlgorithm.h"
#include "Vertex.h"
class Edge ;
#include "Graph.h"
class Matching ;
/**
* \class DFSAPHeuristic
* \brief a matching algorithm implementing a heuristic search for augmenting paths
*
* This class implements the heuristic augmenting path search presented by
* Rolf H. Moehring and Matthias Mueller-Hannemann in their paper: "Cardinality
* Matching: Heuristic Search for Augmenting Paths".
**/
class DFSAPHeuristic : public MatchingAlgorithm {
public:
/**
* construct an DFSAPHeuristic object
* \param g the graph on which this heuristic should run
* \param m the matching to start with
* \param goal the percentage of matched vertices that should be reached
* \param mne the maximum number of edges that should be considered for every vertex
* \param mo the mode for edge iteration
**/
DFSAPHeuristic (Graph* g, Matching* m, float goal = 100.0, UWORD32 mne = UWORD32_MAX, EdgeIterator::ITERATIONMODE mo = EdgeIterator::SAMPLEOCCURENCE) ;
virtual ~DFSAPHeuristic (void) ;
const char* getName (void) const
{ return "DFS Augmenting Path Heuristic" ; } ;
/**
* reset the state of this DFSAPHeuristic, esp. the EdgeIterators
* \param mne the maximum number of edges that should be considered for every vertex for now on
**/
void reset (UWORD32 mne = UWORD32_MAX, EdgeIterator::ITERATIONMODE mo = EdgeIterator::SAMPLEOCCURENCE) ;
void run (void) ;
private:
/**
* \param v0 an exposed vertex
* \param path an array of Edge pointers where the path will be put
* \return the length of the path (the number of valid edges in path)
**/
unsigned long searchAugmentingPath (Vertex* v0, const Edge** path) ;
const Edge* getNextEdge (Vertex *v) ;
void markVisited (Vertex *v)
{ TimeCounters[v->getLabel()] = TimeCounter ; } ;
/**
* returns true iff v has already been visited in this
* iteration, i.e. in the current call of searchAugmentingPath
**/
bool isVisited (Vertex *v) const
{ return isVisited(v->getLabel()) ; } ;
bool isVisited (VertexLabel vlbl) const
{ return (TimeCounters[vlbl] == TimeCounter) ; } ;
UWORD32 TimeCounter ;
UWORD32* TimeCounters ;
bool* VertexOnPath ;
EdgeIterator* EdgeIterators ;
#ifdef DEBUG
/// the number of edges that have been examined in all successful searches
unsigned long long NEdgesSuccessful ;
/// the number of edges that have been examined in all unsuccessful searches
unsigned long long NEdgesUnsuccessful ;
/// the number of calls to searchAugmentingPath that have been sucessful
unsigned long NSuccessful ;
/// the number of calls to searchAugmentingPath that have been unsuccessful
unsigned long NUnsuccessful ;
/// string indicating if n-th search was successful
std::string SuccessString ;
#endif
} ;
#endif // ndef SH_DFSAPHEURISTIC

View File

@ -0,0 +1,70 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "DMDConstructionHeuristic.h"
#include "Edge.h"
#include "Graph.h"
#include "Matching.h"
#include "Vertex.h"
DMDConstructionHeuristic::DMDConstructionHeuristic (Graph* g, Matching* m, float goal)
: MatchingAlgorithm (g, m, goal)
{
AvailableVertices = std::vector<Vertex*> (g->getNumVertices()) ;
for (VertexLabel l = 0 ; l < g->getNumVertices() ; l++) {
AvailableVertices[l] = g->getVertex(l) ;
}
}
void DMDConstructionHeuristic::run (void)
{
VertexLabel mdi = MinDegNotFound ;
while ((mdi = findMinDegIndex (AvailableVertices)) != MinDegNotFound) {
Vertex* v1 = AvailableVertices[mdi] ;
v1->updateShortestEdge() ;
Edge* e = v1->getShortestEdge() ;
Vertex* v2 = e->getOtherVertex(v1) ;
TheMatching->addEdge(*e) ;
v1->markDeleted() ;
v2->markDeleted() ;
AvailableVertices[v1->getLabel()] = NULL ;
AvailableVertices[v2->getLabel()] = NULL ;
}
TheGraph->unmarkDeletedAllVertices() ;
}
VertexLabel DMDConstructionHeuristic::findMinDegIndex (const std::vector<Vertex*>& vertices)
{
VertexLabel mdi = MinDegNotFound ;
UWORD32 mindeg = UWORD32_MAX ;
for (VertexLabel l = 0 ; l < vertices.size() ; l++) {
if (vertices[l] != NULL) {
UWORD32 curdeg = vertices[l]->getDegree() ;
if (0 < curdeg && curdeg < mindeg) {
mdi = l ;
mindeg = curdeg ;
}
}
}
return mdi ;
}

View File

@ -0,0 +1,51 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_DMDCONSTRUCTIONHEURISTIC_H
#define SH_DMDCONSTRUCTIONHEURISTIC_H
#include "MatchingAlgorithm.h"
class Vertex ;
#include "common.h"
/**
* \class DMDConstructionHeuristic
* \brief an implementation of the "dynamic minimum degree" heuristic for contruction a matching
**/
class DMDConstructionHeuristic : public MatchingAlgorithm {
public:
DMDConstructionHeuristic (Graph* g, Matching* m, float goal = 100.0) ;
virtual ~DMDConstructionHeuristic (void) {} ;
const char* getName (void) const
{ return "Dynamic Minimum Degree Construction Heuristic" ; } ;
void run (void) ;
private:
static const VertexLabel MinDegNotFound = VERTEXLABEL_MAX ;
std::vector<Vertex*> AvailableVertices ;
VertexLabel findMinDegIndex (const std::vector<Vertex*>& vertices) ;
} ;
#endif // ndef SH_DMDCONSTRUCTIONHEURISTIC_H

187
steghide-src/Edge.cc Normal file
View File

@ -0,0 +1,187 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "Edge.h"
#include "SampleValue.h"
#include "Vertex.h"
#include "common.h"
Edge::Edge (Vertex *v1, unsigned short idx1, Vertex *v2, unsigned short idx2)
: Vertex1(v1), Index1(idx1), Vertex2(v2), Index2(idx2), Weight(UWORD32_MAX)
{
myassert (v1->getLabel() != v2->getLabel()) ;
}
Edge::Edge (const Edge& e)
{
Vertex1 = e.Vertex1 ;
Index1 = e.Index1 ;
Vertex2 = e.Vertex2 ;
Index2 = e.Index2 ;
Weight = e.Weight ;
}
UWORD32 Edge::getWeight ()
{
if (Weight == UWORD32_MAX) {
Weight = Vertex1->getSampleValue(Index1)->calcDistance(Vertex2->getSampleValue(Index2)) ;
}
return Weight ;
}
void Edge::set (Vertex* v1, unsigned short idx1, Vertex* v2, unsigned short idx2)
{
Vertex1 = v1 ;
Index1 = idx1 ;
Vertex2 = v2 ;
Index2 = idx2 ;
Weight = UWORD32_MAX ;
}
void Edge::set1 (Vertex* v1, unsigned short idx1)
{
Vertex1 = v1 ;
Index1 = idx1 ;
Weight = UWORD32_MAX ;
}
void Edge::set2 (Vertex* v2, unsigned short idx2)
{
Vertex2 = v2 ;
Index2 = idx2 ;
Weight = UWORD32_MAX ;
}
bool Edge::operator== (const Edge& e) const
{
if ((Vertex1->getLabel() == e.Vertex1->getLabel()) && (Vertex2->getLabel() == e.Vertex2->getLabel()) &&
(Index1 == e.Index1) && (Index2 == e.Index2)) {
return true ;
}
if ((Vertex1->getLabel() == e.Vertex2->getLabel()) && (Vertex2->getLabel() == e.Vertex1->getLabel()) &&
(Index1 == e.Index2) && (Index2 == e.Index1)) {
return true ;
}
return false ;
}
bool Edge::operator!= (const Edge& e) const
{
return (!operator==(e)) ;
}
void Edge::swap (void)
{
Vertex* v_tmp = Vertex1 ;
Vertex1 = Vertex2 ;
Vertex2 = v_tmp ;
unsigned short idx_tmp = Index1 ;
Index1 = Index2 ;
Index2 = idx_tmp ;
}
bool Edge::contains (const Vertex* v) const
{
return ((v->getLabel() == Vertex1->getLabel()) || (v->getLabel() == Vertex2->getLabel())) ;
}
Vertex *Edge::getOtherVertex (const Vertex *v) const
{
Vertex *retval = NULL ;
if (v->getLabel() == Vertex1->getLabel()) {
retval = Vertex2 ;
}
else if (v->getLabel() == Vertex2->getLabel()) {
retval = Vertex1 ;
}
else {
myassert (0) ;
}
return retval ;
}
SamplePos Edge::getSamplePos (Vertex *v) const
{
SamplePos retval = 0 ;
if (v->getLabel() == Vertex1->getLabel()) {
retval = Vertex1->getSamplePos (Index1) ;
}
else if (v->getLabel() == Vertex2->getLabel()) {
retval = Vertex2->getSamplePos (Index2) ;
}
else {
myassert (0) ;
}
return retval ;
}
SampleValue *Edge::getOriginalSampleValue (Vertex *v) const
{
unsigned short index = 0 ;
if (v->getLabel() == Vertex1->getLabel()) {
index = Index1 ;
}
else if (v->getLabel() == Vertex2->getLabel()) {
index = Index2 ;
}
else {
myassert (0) ;
}
return v->getSampleValue (index) ;
}
SampleValue *Edge::getReplacingSampleValue (Vertex *v) const
{
SampleValue *retval = NULL ;
if (v->getLabel() == Vertex1->getLabel()) {
retval = Vertex2->getSampleValue (Index2) ;
}
else if (v->getLabel() == Vertex2->getLabel()) {
retval = Vertex1->getSampleValue (Index1) ;
}
else {
myassert (0) ;
}
return retval ;
}
void Edge::print (unsigned short spc) const
{
char* space = new char[spc + 1] ;
for (unsigned short i = 0 ; i < spc ; i++) {
space[i] = ' ' ;
}
space[spc] = '\0' ;
std::cerr << space << "Edge:" << std::endl ;
Vertex1->print (spc + 1) ;
std::cerr << space << " Index1: " << Index1 << std::endl ;
Vertex2->print (spc + 1) ;
std::cerr << space << " Index2: " << Index2 << std::endl ;
std::cerr << space << " Weight: " ;
if (Weight == UWORD32_MAX) {
std::cerr << "not calculated" ;
}
else {
std::cerr << Weight ;
}
std::cerr << std::endl ;
}

120
steghide-src/Edge.h Normal file
View File

@ -0,0 +1,120 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_EDGE_H
#define SH_EDGE_H
#include "SampleValue.h"
#include "Vertex.h"
#include "common.h"
class Edge {
public:
/**
* default constructor - does not create a useful object
**/
Edge (void)
: Vertex1(NULL), Index1(0), Vertex2(NULL), Index2(0), Weight(UWORD32_MAX) {} ;
/**
* constructs an edge object
**/
Edge (Vertex *v1, unsigned short idx1, Vertex *v2, unsigned short idx2) ;
/**
* copy constructor
**/
Edge (const Edge& e) ;
Vertex *getVertex1 (void) const
{ return Vertex1 ; } ;
void setVertex1 (Vertex* v)
{ Vertex1 = v ; } ;
Vertex *getVertex2 (void) const
{ return Vertex2 ; } ;
unsigned short getIndex1 (void) const
{ return Index1 ; } ;
void setIndex1 (unsigned short i)
{ Index1 = i ; } ;
unsigned short getIndex2 (void) const
{ return Index2 ; } ;
UWORD32 getWeight (void) ;
void set (Vertex* v1, unsigned short idx1, Vertex* v2, unsigned short idx2) ;
void set1 (Vertex* v1, unsigned short idx1) ;
void set2 (Vertex* v2, unsigned short idx2) ;
bool operator== (const Edge& e) const ;
bool operator!= (const Edge& e) const ;
/**
* swap vertices 1 and 2 in this edge (weight is not altered)
**/
void swap (void) ;
/**
* \return true iff this edge contains the vertex v
**/
bool contains (const Vertex *v) const ;
/**
* get the vertex on this edge that is not equal to v
**/
Vertex *getOtherVertex (const Vertex *v) const ;
/**
* get the position of the sample that should be changed to embed the bit represented by the vertex v
**/
SamplePos getSamplePos (Vertex* v) const ;
/**
* get the old sample value that will be replaced to embed the bit represented by the vertex v
**/
SampleValue *getOriginalSampleValue (Vertex *v) const ;
/**
* get the sample value that should replace the previous sample value to embed the bit represented by the vertex v
**/
SampleValue *getReplacingSampleValue (Vertex *v) const ;
void print (unsigned short spc = 0) const ;
private:
Vertex *Vertex1 ;
/// contains the index of the sample (of those in Vertex1) that will be changed (if this edge is used)
unsigned short Index1 ;
Vertex *Vertex2 ;
/// contains the index of the sample (of those in Vertex2) that will be changed (if this edge is used)
unsigned short Index2 ;
UWORD32 Weight ;
} ;
#endif // ndef SH_EDGE_H

View File

@ -0,0 +1,199 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "Edge.h"
#include "EdgeIterator.h"
#include "Graph.h"
#include "SampleOccurence.h"
#include "Vertex.h"
#include "common.h"
EdgeIterator::EdgeIterator ()
: SVALIndices(NULL)
{
SVALIndices = new unsigned long[Globs.TheCvrStgFile->getSamplesPerVertex()] ;
}
EdgeIterator::EdgeIterator (Vertex *v, ITERATIONMODE m)
{
SVALIndices = new unsigned long[Globs.TheCvrStgFile->getSamplesPerVertex()] ;
reset(v, m) ;
}
EdgeIterator::EdgeIterator (const EdgeIterator& eit)
{
CurrentEdge = eit.CurrentEdge ;
Mode = eit.Mode ;
SVALIndices = new unsigned long[Globs.TheCvrStgFile->getSamplesPerVertex()] ;
for (unsigned short i = 0 ; i < Globs.TheCvrStgFile->getSamplesPerVertex() ; i++) {
SVALIndices[i] = eit.SVALIndices[i] ;
}
Finished = eit.Finished ;
SampleOccurenceIt = eit.SampleOccurenceIt ;
}
EdgeIterator::~EdgeIterator ()
{
delete[] SVALIndices ;
}
void EdgeIterator::operator++ ()
{
myassert (!Finished) ;
Vertex* srcv = CurrentEdge.getVertex1() ;
unsigned short srcidx = CurrentEdge.getIndex1() ;
switch (Mode) {
case SAMPLEOCCURENCE:
{
SampleValue* srcsv = srcv->getSampleValue(srcidx) ;
SampleValue* destsv = (*(Globs.TheGraph->SVALists[srcv->getTargetValue(srcidx)]))[srcsv][SVALIndices[srcidx]] ;
bool cont = false ;
do {
SampleOccurenceIt++ ;
cont = false ;
if (SampleOccurenceIt != Globs.TheGraph->SampleOccurences[destsv->getLabel()].end()) {
if ((srcsv->getEmbeddedValue() != SampleOccurenceIt->getVertex()->getTargetValue(SampleOccurenceIt->getIndex())) || (SampleOccurenceIt->getVertex()->getLabel() == srcv->getLabel())) {
cont = true ;
}
}
} while (cont) ;
if (SampleOccurenceIt == Globs.TheGraph->SampleOccurences[destsv->getLabel()].end()) {
// search new destination sample value
SVALIndices[srcidx]++ ;
findNextEdge() ;
}
break ;
}
case SAMPLEVALUE:
{
SVALIndices[srcidx]++ ;
findNextEdge() ;
break ;
}
}
// increment EdgeIndex while checking that it has not become too high
if (++EdgeIndex >= MaxNumEdges) {
Finished = true ;
}
if (!Finished) {
CurrentEdge.set2 (SampleOccurenceIt->getVertex(), SampleOccurenceIt->getIndex()) ;
}
}
void EdgeIterator::reset (ITERATIONMODE m)
{
Mode = m ;
Finished = false ;
for (unsigned short i = 0 ; i < Globs.TheCvrStgFile->getSamplesPerVertex() ; i++) {
SVALIndices[i] = 0 ;
}
findNextEdge() ;
EdgeIndex = 0 ;
if (!Finished) {
CurrentEdge.set2 (SampleOccurenceIt->getVertex(), SampleOccurenceIt->getIndex()) ;
}
}
void EdgeIterator::reset (Vertex* v, ITERATIONMODE m)
{
CurrentEdge.setVertex1 (v) ;
reset(m) ;
}
void EdgeIterator::findNextEdge ()
{
UWORD32 mindist = UWORD32_MAX ;
for (unsigned short i = 0 ; i < Globs.TheCvrStgFile->getSamplesPerVertex() ; i++) {
Vertex* srcv = CurrentEdge.getVertex1() ;
SampleValue* srcsv = srcv->getSampleValue(i) ;
SampleValue* destsv = NULL ;
std::list<SampleOccurence>::const_iterator soccit_candidate ;
// increment SVALIndices[i] until it points to a valid destination sample value
while (SVALIndices[i] < (*(Globs.TheGraph->SVALists[srcv->getTargetValue(i)]))[srcsv].size()) {
destsv = (*(Globs.TheGraph->SVALists[srcv->getTargetValue(i)]))[srcsv][SVALIndices[i]] ;
// look for a sample occurence of destsv - thereby setting soccit_candidate
bool found = false ;
const std::list<SampleOccurence>& socc = Globs.TheGraph->SampleOccurences[destsv->getLabel()] ;
soccit_candidate = socc.begin() ;
while (!found && soccit_candidate != socc.end()) {
if ((soccit_candidate->getVertex()->getLabel() == srcv->getLabel()) ||
(srcsv->getEmbeddedValue() != soccit_candidate->getVertex()->getTargetValue(soccit_candidate->getIndex()))) {
soccit_candidate++ ;
}
else {
found = true ;
}
}
if (found) {
break ;
}
else {
SVALIndices[i]++ ;
}
}
// test if the destination sample value leads to edge with (until now) minimal distance - thereby setting CurrentEdge.Index1 and SampleOccurenceIt
if (SVALIndices[i] < (*(Globs.TheGraph->SVALists[srcv->getTargetValue(i)]))[srcsv].size()) {
UWORD32 thisdist = srcsv->calcDistance(destsv) ;
if (thisdist < mindist) {
mindist = thisdist ;
CurrentEdge.setIndex1(i) ;
SampleOccurenceIt = soccit_candidate ;
}
}
}
if (mindist == UWORD32_MAX) {
// no edge has been found
Finished = true ;
}
}
#ifdef DEBUG
void EdgeIterator::print (unsigned short spc) const
{
char* space = new char[spc + 1] ;
for (unsigned short i = 0 ; i < spc ; i++) {
space[i] = ' ' ;
}
space[spc] = '\0' ;
std::cerr << space << "Current Edge:" << std::endl ;
CurrentEdge.print(spc + 1) ;
std::cerr << space << "SampleOccurenceIt: <" << SampleOccurenceIt->getVertex()->getLabel() << "," << SampleOccurenceIt->getIndex() << ">" << std::endl ;
std::cerr << space << "Finished: " << Finished << std::endl ;
std::cerr << space << "EdgeIndex: " << EdgeIndex << std::endl ;
for (unsigned short i = 0 ; i < Globs.TheCvrStgFile->getSamplesPerVertex() ; i++) {
std::cerr << space << "SVALIndices[" << i << "]: " << SVALIndices[i] << std::endl ;
}
}
#endif
UWORD32 EdgeIterator::MaxNumEdges = UWORD32_MAX ;

158
steghide-src/EdgeIterator.h Normal file
View File

@ -0,0 +1,158 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_EDGEITERATOR_H
#define SH_EDGEITERATOR_H
#include <list>
#include "Edge.h"
class Graph ;
#include "SampleOccurence.h"
class SampleValue ;
class Vertex ;
/**
* \class EdgeIterator
* \brief allows an iteration trough all edges of a vertex
*
* The Vertex that is the source for all edges is called "source vertex".
* The order of the iteration through the edges is from the shortest to the longest edge.
* If two edges have the same length they are ordered the same way as the corresponding
* entries in the sample value adjacency lists (for different sample values) respectivly
* the destination sample occurences in the SampleOccurences data structure (for the same
* sample value).
*
* EdgeIterator uses an SampleOccurence::const_iterator to store information
* about the current edge. Graph::(un)markDeletedSampleOccurence can invalidate
* such iterators. It is therefore not a good idea to use EdgeIterators at the same
* time as the Graph::(un)markDeletedSampleOccurence functionality.
*
* <b>NOTE:</b> EdgeIterator relies on the Globals object pointed to by the Globs pointer.
* This means that it must be set correctly before using any method of an EdgeIterator object.
**/
class EdgeIterator {
public:
enum ITERATIONMODE {
SAMPLEOCCURENCE, // incrementing increments to next sample occurence (possibly of the same sample value) thus using every edge of the source vertex
SAMPLEVALUE // incrementing increments to the next sample value thus not using all edges in general
} ;
/**
* the default contructor - does not create a valid object
**/
EdgeIterator (void) ;
/**
* \param v the source vertex
**/
EdgeIterator (Vertex *v, ITERATIONMODE m = SAMPLEOCCURENCE) ;
/**
* the copy constructor
**/
EdgeIterator (const EdgeIterator& eit) ;
~EdgeIterator (void) ;
/**
* get the current edge
* \return the edge that is described by the current status of this EdgeIterator
**/
const Edge* operator* (void) const
{ return ((Finished) ? NULL : &CurrentEdge) ; }
/**
* set this iterator to next edge
**/
void operator++ (void) ;
/**
* set this iterator to first (shortest) edge of vertex v
* \param v new vertex (don't change if it is NULL)
**/
void reset (Vertex* v, ITERATIONMODE m = SAMPLEOCCURENCE) ;
/**
* reset this iterator to first (shortest) edge
**/
void reset (ITERATIONMODE m = SAMPLEOCCURENCE) ;
/**
* \return true iff this EdgeIterator points to the end of the list of edges of SrcVertex
**/
bool isFinished (void) const
{ return Finished ; } ;
/**
* get the label of the partner vertex
* \return the label of the vertex that builds the edge returned by operator* together with SrcVertex
**/
VertexLabel getPartnerVertexLabel (void) const
{ return SampleOccurenceIt->getVertex()->getLabel() ; } ;
static UWORD32 getMaxNumEdges (void)
{ return MaxNumEdges ; } ;
static void setMaxNumEdges (UWORD32 mne)
{ MaxNumEdges = mne ; } ;
void print (unsigned short spc = 0) const ;
private:
/// the current edge (is returned by operator*)
Edge CurrentEdge ;
/// mode of iteration
ITERATIONMODE Mode ;
/// contains (for every sample value) an index to the current opposite neighbour
unsigned long* SVALIndices ;
/// the maximum number of edges the EdgeIterator should iterate through
static UWORD32 MaxNumEdges ;
/// the index/number of the edge that is currently returned by operator*
UWORD32 EdgeIndex ;
/// is true iff there are no more edges for this source vertex
bool Finished ;
/**
* contains the iterator pointing to the sample occurence that constitutes
* the edge together with SourceVertex/SourceSamleValueIndex
**/
std::list<SampleOccurence>::const_iterator SampleOccurenceIt ;
/**
* find the shortest edge, starting the search at SVOppNeighsIndices[0...k]
* set the private variables accordingly
* is only called to find a new destination sample value, i.e. if one of the
* SVOppNeighsIndices[i] is changed
**/
void findNextEdge (void) ;
/**
* \return true iff there is a sample with value sv that is part of an edge starting at SrcVertex
**/
bool isDestSampleValueOK (const SampleValue *sv) ;
} ;
#endif // ndef SH_EDGEITERATOR_H

375
steghide-src/EmbData.cc Normal file
View File

@ -0,0 +1,375 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "AUtils.h"
#include "BinaryIO.h"
#include "BitString.h"
#include "EmbData.h"
#include "error.h"
#include "MCryptPP.h"
#include "MHashPP.h"
#include "common.h"
EmbData::EmbData (MODE m, std::string pp, std::string fn)
: Mode(m), Passphrase(pp), FileName(fn)
{
if (m == EXTRACT) {
NumBitsNeeded = NumBitsRequested = NBitsMagic ;
Version = CodeVersion ;
State = READ_MAGIC ;
Reservoir = BitString() ;
}
}
bool EmbData::finished ()
{
myassert (Mode == EXTRACT) ;
return (State == END) ;
}
unsigned long EmbData::getNumBitsRequested ()
{
myassert (Mode == EXTRACT) ;
return NumBitsRequested ;
}
void EmbData::addBits (BitString addbits)
{
myassert (Mode == EXTRACT) ;
#ifdef DEBUG
printDebug (1, "\nEmbData::addBits called with") ;
printDebug (1, " addbits:") ;
addbits.printDebug (1, 2) ;
printDebug (1, " Reservoir:") ;
Reservoir.printDebug (1, 2) ;
#endif
Reservoir.append (addbits) ;
BitString bits ;
if (Reservoir.getLength() >= NumBitsNeeded) {
bits = Reservoir.cutBits (0, NumBitsNeeded) ; // take exactly the first NumBitsNeeded bits from Reservoir | addbits
}
else { // Reservoir.getLength() < NumBitsNeeded
myassert(false) ;
}
#ifdef DEBUG
printDebug (1, "bits is now:") ;
bits.printDebug (1, 2) ;
#endif
switch (State) {
case READ_MAGIC:
{
#ifdef DEBUG
printDebug (1, "in the READ_MAGIC state") ;
#endif
if (bits.getValue(0, NBitsMagic) == Magic) {
NumBitsNeeded = 1 ;
NumBitsRequested = AUtils::bminus<unsigned long> (NumBitsNeeded, Reservoir.getLength()) ;
State = READ_VERSION ;
}
else {
throw SteghideError (_("could not extract any data with that passphrase!")) ;
}
break ;
}
case READ_VERSION:
{
#ifdef DEBUG
printDebug (1, "in the READ_VERSION state") ;
#endif
if (bits[0] == true) {
Version++ ;
NumBitsNeeded = AUtils::bminus ((UWORD32) 1, Reservoir.getLength()) ;
}
else {
if (Version > CodeVersion) {
throw CorruptDataError (_("attempting to read an embedding of version %d but steghide %s only supports embeddings of version %d."), Version, VERSION, CodeVersion) ;
}
NumBitsNeeded = EncryptionAlgorithm::IRep_size + EncryptionMode::IRep_size ;
NumBitsRequested = AUtils::bminus<unsigned long> (NumBitsNeeded, Reservoir.getLength()) ;
State = READ_ENCINFO ;
}
break ;
}
case READ_ENCINFO: {
#ifdef DEBUG
printDebug (1, "in the READ_ENCINFO state") ;
#endif
unsigned int algo = (unsigned int) bits.getValue (0, EncryptionAlgorithm::IRep_size) ;
if (EncryptionAlgorithm::isValidIntegerRep (algo)) {
EncAlgo.setValue ((EncryptionAlgorithm::IRep) algo) ;
}
unsigned int mode = (unsigned int) bits.getValue (EncryptionAlgorithm::IRep_size, EncryptionMode::IRep_size) ;
if (EncryptionMode::isValidIntegerRep (mode)) {
EncMode.setValue ((EncryptionMode::IRep) mode) ;
}
NumBitsNeeded = NBitsNPlainBits ;
NumBitsRequested = AUtils::bminus<unsigned long> (NumBitsNeeded, Reservoir.getLength()) ;
State = READ_NPLAINBITS ;
#ifndef USE_LIBMCRYPT
if (EncAlgo.getIntegerRep() != EncryptionAlgorithm::NONE) {
throw SteghideError (_(
"The embedded data is encrypted but steghide has been compiled without encryption\n"
"support. To be able to read the embedded data, you have to install libmcrypt\n"
"(http://mcrypt.sourceforge.net/) and recompile steghide.")) ;
}
#endif
break ; }
case READ_NPLAINBITS: {
#ifdef DEBUG
printDebug (1, "in the READ_NPLAINBITS state") ;
#endif
NPlainBits = bits.getValue (0, NBitsNPlainBits) ;
#ifdef USE_LIBMCRYPT
NumBitsNeeded = (UWORD32) MCryptPP::getEncryptedSize (EncAlgo, EncMode, NPlainBits) ;
#else
NumBitsNeeded = NPlainBits ;
#endif
NumBitsRequested = AUtils::bminus<unsigned long> (NumBitsNeeded, Reservoir.getLength()) ;
State = READ_ENCRYPTED ;
break ; }
case READ_ENCRYPTED: {
#ifdef DEBUG
printDebug (1, "in the READ_ENCRYPTED state") ;
#endif
BitString plain ;
#ifdef USE_LIBMCRYPT
if (EncAlgo.getIntegerRep() == EncryptionAlgorithm::NONE) {
plain = bits ;
}
else {
MCryptPP crypto (EncAlgo, EncMode) ;
plain = crypto.decrypt (bits, Passphrase) ;
}
#else
plain = bits ;
#endif
plain.truncate (0, NPlainBits) ; // cut off random padding used to achieve full number of encryption blocks
unsigned long pos = 0 ;
// read Compression (and uncompress)
Compression = ((plain[pos++]) ? 9 : 0) ; // to make compression contain a value that makes sense
#ifdef DEBUG
printDebug (2, " compression: %d\n", plain[pos - 1]) ;
#endif
if (Compression > 0) {
UWORD32 NUncompressedBits = plain.getValue (pos, NBitsNUncompressedBits) ;
#ifdef DEBUG
printDebug (2, " nuncobits: %lu\n", NUncompressedBits) ;
#endif
pos += NBitsNUncompressedBits ;
plain.truncate (pos, plain.getLength()) ;
pos = 0 ;
plain.uncompress (NUncompressedBits) ;
}
// read Checksum
Checksum = plain[pos++] ;
#ifdef DEBUG
printDebug (2, " checksum: %d\n", plain[pos - 1]) ;
#endif
if (Checksum) {
CRC32 = plain.getValue (pos, NBitsCrc32) ;
#ifdef DEBUG
printDebug (2, " crc32: 0x%x\n", CRC32) ;
#endif
pos += NBitsCrc32 ;
}
// read filename
char curchar = '\0' ;
FileName = "" ;
do {
curchar = (char) plain.getValue (pos, 8) ;
if (curchar != '\0') {
FileName += curchar ;
}
pos += 8 ;
} while (curchar != '\0') ;
// extract data
if ((plain.getLength() - pos) % 8 != 0) {
throw CorruptDataError (_("the embedded data has an invalid length.")) ;
}
const unsigned long extdatalen = (plain.getLength() - pos) / 8 ;
Data.resize (extdatalen) ;
for (unsigned int i = 0 ; i < extdatalen ; i++) {
Data[i] = ((BYTE) plain.getValue (pos, 8)) ;
pos += 8 ;
}
NumBitsNeeded = 0 ;
NumBitsRequested = 0 ;
State = END ;
break ; }
case END:
default: {
myassert (0) ;
break ; }
}
}
bool EmbData::checksumOK (void) const
{
// test if checksum is ok
bool ok = true ;
if (Checksum) {
MHashPP hash (MHASH_CRC32) ;
for (std::vector<BYTE>::const_iterator i = Data.begin() ; i != Data.end() ; i++) {
hash << *i ;
}
hash << MHashPP::endhash ;
unsigned long calccrc32 = hash.getHashBits().getValue(0, NBitsCrc32) ;
if (calccrc32 == CRC32) {
ok = true ;
}
else {
ok = false ;
}
}
return ok ;
}
void EmbData::setEncAlgo (EncryptionAlgorithm a)
{
EncAlgo = a ;
}
EncryptionAlgorithm EmbData::getEncAlgo () const
{
return EncAlgo ;
}
void EmbData::setEncMode (EncryptionMode m)
{
EncMode = m ;
}
EncryptionMode EmbData::getEncMode () const
{
return EncMode ;
}
void EmbData::setCompression (int c)
{
Compression = c ;
}
int EmbData::getCompression (void) const
{
return Compression ;
}
void EmbData::setChecksum (bool c)
{
Checksum = c ;
}
bool EmbData::getChecksum (void) const
{
return Checksum ;
}
BitString EmbData::getBitString ()
{
myassert (Mode == EMBED) ;
// assembling data that can be compressed
BitString compr ;
compr.append (Checksum) ;
if (Checksum) {
MHashPP hash (MHASH_CRC32) ;
for (std::vector<BYTE>::iterator i = Data.begin() ; i != Data.end() ; i++) {
hash << *i ;
}
hash << MHashPP::endhash ;
compr.append (hash.getHashBits()) ;
}
compr.append (stripDir (FileName)) ;
compr.append ((BYTE) 0, 8) ; // end of fileame
compr.append (Data) ;
// assembling data that can be encrypted
BitString plain ;
plain.append ((Compression > 0) ? true : false) ;
if (Compression > 0) {
plain.append (compr.getLength(), NBitsNUncompressedBits) ;
compr.compress (Compression) ;
}
plain.append (compr) ;
// put it all together
BitString main ;
main.append(Magic, NBitsMagic) ;
for (unsigned short i = 0 ; i < CodeVersion ; i++) {
main.append(true) ;
}
main.append(false) ; // end of version
main.append((UWORD16) EncAlgo.getIntegerRep(), EncryptionAlgorithm::IRep_size) ;
main.append((UWORD16) EncMode.getIntegerRep(), EncryptionMode::IRep_size) ;
main.append(plain.getLength(), NBitsNPlainBits) ;
#ifdef USE_LIBMCRYPT
if (EncAlgo.getIntegerRep() != EncryptionAlgorithm::NONE) {
MCryptPP crypto (EncAlgo, EncMode) ;
plain = crypto.encrypt (plain, Passphrase) ;
}
#else
myassert (EncAlgo.getIntegerRep() == EncryptionAlgorithm::NONE) ;
#endif
main.append (plain) ;
return main ;
}
std::string EmbData::stripDir (std::string s)
{
unsigned int start = 0 ;
if ((start = s.find_last_of ("/\\")) == std::string::npos) {
start = 0 ;
}
else {
start += 1 ;
}
return s.substr (start, std::string::npos) ;
}

134
steghide-src/EmbData.h Normal file
View File

@ -0,0 +1,134 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_EMBDATA_H
#define SH_EMBDATA_H
#include <string>
#include <vector>
#include "common.h"
#include "BitString.h"
#include "EncryptionAlgorithm.h"
#include "EncryptionMode.h"
class EmbData {
public:
enum MODE { EMBED, EXTRACT } ;
enum STATE { READ_MAGIC, READ_VERSION, READ_ENCINFO, READ_NPLAINBITS, READ_ENCRYPTED, END } ;
/**
* construct a new EmbData object
* \param m the mode (EMBED or EXTRACT)
* \param pp the passphrase
* \param fn the filename (only need for mode EMBED)
**/
EmbData (MODE m, std::string pp, std::string fn = "") ;
BitString getBitString (void) ;
bool finished (void) ;
/**
* get the minimum length of the BitString that is to be passed to addBits
**/
unsigned long getNumBitsRequested (void) ;
void addBits (BitString addbits) ;
void setEncAlgo (EncryptionAlgorithm a) ;
EncryptionAlgorithm getEncAlgo (void) const ;
void setEncMode (EncryptionMode m) ;
EncryptionMode getEncMode (void) const ;
void setCompression (int c) ;
int getCompression (void) const ;
void setChecksum (bool c) ;
bool getChecksum (void) const ;
/**
* check if crc32 checksum is ok (needs filled Data and CRC32 fields)
* \return true iff checksum is ok
**/
bool checksumOK (void) const ;
void setData (const std::vector<BYTE> data)
{ Data = data ; } ;
std::vector<BYTE> getData (void) const
{ return Data ; } ;
std::string getFileName (void) const
{ return FileName ; } ;
/// the minimum size of the part of the generatred BitString that is not the data
static const unsigned int MinStegoHeaderSize = 50 ;
protected:
std::string stripDir (std::string s) ;
private:
/// number of bits used to code the number of plain bits
static const unsigned int NBitsNPlainBits = 32 ;
/// number of bits used to code the number of uncompressed bits
static const unsigned int NBitsNUncompressedBits = 32 ;
/// size of a crc32 checksum in bits
static const unsigned int NBitsCrc32 = 32 ;
/// version of this steghide embedding (stego compatibility of EmbData)
static const unsigned short CodeVersion = 0 ;
/// steghide magic to recognize embedded data (the string "shm")
static const UWORD32 Magic = 0x73688DUL ;
/// size (in bits of Magic)
static const unsigned int NBitsMagic = 24 ;
MODE Mode ;
STATE State ;
unsigned long NPlainBits ;
/// the number of bits that the caller must at least supply to addBits
unsigned long NumBitsRequested ;
/// exactly the number of bits that the next step will consume from Reservoir and addBits together
unsigned long NumBitsNeeded ;
BitString Reservoir ;
std::string Passphrase ;
/// version read from input bitstring
unsigned short Version ;
EncryptionAlgorithm EncAlgo ;
EncryptionMode EncMode ;
/// compression level: 0(none),1(best speed),...,9(best compression)
int Compression ;
/// will a checksum be embedded ?
bool Checksum ;
/// the checksum
unsigned long CRC32 ;
std::string FileName ;
/// contains the actual message to be embedded
std::vector<BYTE> Data ;
} ;
#endif // ndef SH_EMBDATA_H

284
steghide-src/Embedder.cc Normal file
View File

@ -0,0 +1,284 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cfloat>
#include <cstdlib>
#include "DFSAPHeuristic.h"
#include "BitString.h"
#include "CvrStgFile.h"
#include "DMDConstructionHeuristic.h"
#include "EmbData.h"
#include "Embedder.h"
#include "Edge.h"
#include "Graph.h"
#include "Matching.h"
#include "ProgressOutput.h"
#include "Selector.h"
#include "Vertex.h"
#include "WKSConstructionHeuristic.h"
#include "common.h"
#include "error.h"
#include "msg.h"
Globals Globs ;
Embedder::Embedder ()
{
// read embfile
VerboseMessage vrs ;
if (Args.EmbFn.getValue() == "") {
vrs.setMessage (_("reading secret data from standard input...")) ;
}
else {
vrs.setMessage (_("reading secret file \"%s\"..."), Args.EmbFn.getValue().c_str()) ;
vrs.setNewline (false) ;
}
vrs.printMessage() ;
std::vector<BYTE> emb ;
BinaryIO embio (Args.EmbFn.getValue(), BinaryIO::READ) ;
while (!embio.eof()) {
emb.push_back (embio.read8()) ;
}
embio.close() ;
VerboseMessage vdone (_(" done")) ;
if (Args.EmbFn.getValue() != "") {
vdone.printMessage() ;
}
// create bitstring to be embedded
std::string fn = "" ;
if (Args.EmbedEmbFn.getValue()) {
fn = Args.EmbFn.getValue() ;
}
EmbData embdata (EmbData::EMBED, Args.Passphrase.getValue(), fn) ;
embdata.setEncAlgo (Args.EncAlgo.getValue()) ;
embdata.setEncMode (Args.EncMode.getValue()) ;
embdata.setCompression (Args.Compression.getValue()) ;
embdata.setChecksum (Args.Checksum.getValue()) ;
embdata.setData (emb) ;
ToEmbed = embdata.getBitString() ;
// read cover-/stego-file
VerboseMessage vrc ;
if (Args.CvrFn.getValue() == "") {
vrc.setMessage (_("reading cover file from standard input...")) ;
}
else {
vrc.setMessage (_("reading cover file \"%s\"..."), Args.CvrFn.getValue().c_str()) ;
}
vrc.setNewline (false) ;
vrc.printMessage() ;
CvrStgFile::readFile (Args.CvrFn.getValue()) ;
vdone.printMessage() ;
ToEmbed.setArity (Globs.TheCvrStgFile->getEmbValueModulus()) ;
if ((ToEmbed.getNAryLength() * Globs.TheCvrStgFile->getSamplesPerVertex()) > Globs.TheCvrStgFile->getNumSamples()) {
throw SteghideError (_("the cover file is too short to embed the data.")) ;
}
// create graph
Selector sel (Globs.TheCvrStgFile->getNumSamples(), Args.Passphrase.getValue()) ;
VerboseMessage v (_("creating the graph...")) ;
v.setNewline (false) ;
v.printMessage() ;
new Graph (Globs.TheCvrStgFile, ToEmbed, sel) ;
Globs.TheGraph->printVerboseInfo() ;
if (Args.Check.getValue()) {
if (!Globs.TheGraph->check()) {
CriticalWarning w ("integrity checking of graph data structures failed!") ; // TODO: internationalize this
w.printMessage() ;
}
}
#ifdef DEBUG
if (Args.DebugCommand.getValue() == PRINTGRAPH) {
Globs.TheGraph->print() ;
exit (EXIT_SUCCESS) ;
}
else if (Args.DebugCommand.getValue() == PRINTGMLGRAPH) {
Globs.TheGraph->print_gml (std::cout) ;
exit (EXIT_SUCCESS) ;
}
else if (Args.DebugCommand.getValue() == PRINTGMLVERTEX) {
std::vector<bool> nodeprinted (Globs.TheGraph->getNumVertices()) ;
std::vector<bool> edgesprinted (Globs.TheGraph->getNumVertices()) ;
Globs.TheGraph->printPrologue_gml(std::cout) ;
Globs.TheGraph->printVertex_gml (std::cout, Globs.TheGraph->getVertex(Args.GmlStartVertex.getValue()), Args.GmlGraphRecDepth.getValue(), nodeprinted, edgesprinted) ;
Globs.TheGraph->printEpilogue_gml(std::cout) ;
exit (EXIT_SUCCESS) ;
}
#endif
}
Embedder::~Embedder ()
{
delete Globs.TheGraph ;
delete Globs.TheCvrStgFile ;
}
void Embedder::embed ()
{
ProgressOutput* prout = NULL ;
if (Args.Verbosity.getValue() == NORMAL) {
std::string embstring, cvrstring ;
if (Args.EmbFn.getValue() == "") {
embstring = _("standard input") ;
}
else {
embstring = "\"" + Args.EmbFn.getValue() + "\"" ;
}
if (Args.CvrFn.getValue() == "") {
cvrstring = _("standard input") ;
}
else {
cvrstring = "\"" + Args.CvrFn.getValue() + "\"" ;
}
char buf[200] ;
sprintf (buf, _("embedding %s in %s..."), embstring.c_str(), cvrstring.c_str()) ;
prout = new ProgressOutput (std::string(buf)) ;
}
else if (Args.Verbosity.getValue() == VERBOSE) {
prout = new ProgressOutput () ;
}
const Matching* M = calculateMatching (prout) ;
// embed matched edges
const std::list<Edge*> medges = M->getEdges() ;
for (std::list<Edge*>::const_iterator it = medges.begin() ; it != medges.end() ; it++) {
embedEdge (*it) ;
}
// embed exposed vertices
const std::list<Vertex*> *expvertices = M->getExposedVerticesLink() ;
for (std::list<Vertex*>::const_iterator it = expvertices->begin() ; it != expvertices->end() ; it++) {
embedExposedVertex (*it) ;
}
delete M ;
// write stego file
Globs.TheCvrStgFile->transform (Args.StgFn.getValue()) ;
bool displaydone = false ;
if (Globs.TheCvrStgFile->is_std()) {
Message ws (_("writing stego file to standard output... ")) ;
ws.printMessage() ;
}
else {
if (Args.StgFn.getValue() != Args.CvrFn.getValue()) {
Message ws (_("writing stego file \"%s\"... "), Globs.TheCvrStgFile->getName().c_str()) ;
ws.setNewline (false) ;
ws.printMessage() ;
displaydone = true ;
}
}
Globs.TheCvrStgFile->write() ;
if (displaydone) {
Message wsd (_("done")) ;
wsd.printMessage() ;
}
}
const Matching* Embedder::calculateMatching (ProgressOutput* prout)
{
Matching* matching = new Matching (Globs.TheGraph, prout) ;
std::vector<MatchingAlgorithm*> MatchingAlgos = Globs.TheCvrStgFile->getMatchingAlgorithms (Globs.TheGraph, matching) ;
for (std::vector<MatchingAlgorithm*>::const_iterator ait = MatchingAlgos.begin() ; ait != MatchingAlgos.end() ; ait++) {
if (Args.Verbosity.getValue() == VERBOSE) {
prout->setMessage (_("executing %s..."), (*ait)->getName()) ;
}
(*ait)->setGoal (Args.Goal.getValue()) ;
(*ait)->run() ;
delete *ait ;
if (Args.Verbosity.getValue() == VERBOSE) {
prout->done (matching->getMatchedRate(), matching->getAvgEdgeWeight()) ;
}
}
if (Args.Check.getValue()) {
if (!matching->check()) {
CriticalWarning w ("integrity checking of matching data structures failed!") ; // TODO: internationalize this
w.printMessage() ;
}
}
matching->printVerboseInfo() ; // only print info for best matching
if (Args.Verbosity.getValue() == NORMAL) {
prout->done() ;
}
if (prout) {
delete prout ;
}
return matching ;
}
void Embedder::embedEdge (Edge *e)
{
Vertex* v1 = e->getVertex1() ;
Vertex* v2 = e->getVertex2() ;
Globs.TheCvrStgFile->replaceSample (e->getSamplePos(v1), e->getReplacingSampleValue (v1)) ;
Globs.TheCvrStgFile->replaceSample (e->getSamplePos(v2), e->getReplacingSampleValue (v2)) ;
}
void Embedder::embedExposedVertex (Vertex *v)
{
SamplePos samplepos = 0 ;
SampleValue *newsample = NULL ;
float mindistance = FLT_MAX ;
for (unsigned short i = 0 ; i < Globs.TheCvrStgFile->getSamplesPerVertex() ; i++) {
SampleValue *curold = v->getSampleValue(i) ;
SampleValue *curnew = v->getSampleValue(i)->getNearestTargetSampleValue(v->getTargetValue(i)) ;
if (curold->calcDistance (curnew) < mindistance) {
samplepos = v->getSamplePos(i) ;
newsample = curnew ;
mindistance = curold->calcDistance (curnew) ;
}
else {
delete curnew ;
}
}
#ifdef DEBUG
printDebug (1, "embedding vertex with label %lu by changing sample position %lu.", v->getLabel(), samplepos) ;
#endif
EmbValue oldev = Globs.TheCvrStgFile->getEmbeddedValue (samplepos) ;
Globs.TheCvrStgFile->replaceSample (samplepos, newsample) ;
myassert (oldev != Globs.TheCvrStgFile->getEmbeddedValue (samplepos)) ;
delete newsample ;
}

61
steghide-src/Embedder.h Normal file
View File

@ -0,0 +1,61 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_EMBEDDER_H
#define SH_EMBEDDER_H
#include "BitString.h"
class Edge ;
class CvrStgFile ;
class Graph ;
class Matching ;
class ProgressOutput ;
class Vertex ;
class Embedder {
public:
Embedder (void) ;
~Embedder (void) ;
void embed (void) ;
private:
static const unsigned int Default_NConstrHeur = 1 ;
BitString ToEmbed ;
/**
* do the matching algorithms
**/
const Matching* calculateMatching (ProgressOutput* prout) ;
/**
* embed the two bits represented by the two vertices adjacent to e
**/
void embedEdge (Edge *e) ;
/**
* embed the bit represented by the Vertex v
**/
void embedExposedVertex (Vertex *v) ;
} ;
#endif // ndef SH_EMBEDDER_H

View File

@ -0,0 +1,122 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "common.h"
#include "EncryptionAlgorithm.h"
EncryptionAlgorithm::EncryptionAlgorithm ()
{
setValue (NONE) ;
}
EncryptionAlgorithm::EncryptionAlgorithm (EncryptionAlgorithm::IRep irep)
{
setValue (irep) ;
}
EncryptionAlgorithm::EncryptionAlgorithm (std::string srep)
{
setValue (translate (srep)) ;
}
void EncryptionAlgorithm::setValue (EncryptionAlgorithm::IRep irep)
{
Value = irep ;
}
std::string EncryptionAlgorithm::getStringRep () const
{
return translate(Value) ;
}
EncryptionAlgorithm::IRep EncryptionAlgorithm::getIntegerRep () const
{
return Value ;
}
bool EncryptionAlgorithm::isValidStringRep (std::string srep)
{
bool retval = false ;
for (unsigned int i = 0 ; i < NumValues ; i++) {
if (Translations[i].srep == srep) {
retval = true ;
}
}
return retval ;
}
bool EncryptionAlgorithm::isValidIntegerRep (unsigned int irep)
{
return (irep < NumValues) ;
}
std::string EncryptionAlgorithm::translate (EncryptionAlgorithm::IRep irep)
{
std::string retval ;
bool found = false ;
for (unsigned int i = 0 ; i < NumValues ; i++) {
if (Translations[i].irep == irep) {
retval = std::string (Translations[i].srep) ;
found = true ;
}
}
myassert (found) ;
return retval ;
}
EncryptionAlgorithm::IRep EncryptionAlgorithm::translate (std::string srep)
{
IRep retval = NONE ;
bool found = false ;
for (unsigned int i = 0 ; i < NumValues ; i++) {
if (Translations[i].srep == srep) {
retval = Translations[i].irep ;
found = true ;
}
}
myassert (found) ;
return retval ;
}
const EncryptionAlgorithm::Translation EncryptionAlgorithm::Translations[] = {
{ NONE, "none" },
{ TWOFISH, "twofish" },
{ RIJNDAEL128, "rijndael-128" },
{ RIJNDAEL192, "rijndael-192" },
{ RIJNDAEL256, "rijndael-256" },
{ SAFERPLUS, "saferplus" },
{ RC2, "rc2" },
{ XTEA, "xtea" },
{ SERPENT, "serpent" },
{ SAFERSK64, "safer-sk64" },
{ SAFERSK128, "safer-sk128" },
{ CAST256, "cast-256" },
{ LOKI97, "loki97" },
{ GOST, "gost" },
{ THREEWAY, "threeway" },
{ CAST128, "cast-128" },
{ BLOWFISH, "blowfish" },
{ DES, "des" },
{ TRIPLEDES, "tripledes" },
{ ENIGMA, "enigma" },
{ ARCFOUR, "arcfour" },
{ PANAMA, "panama" },
{ WAKE, "wake" }
} ;

View File

@ -0,0 +1,104 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_ENCALGO_H
#define SH_ENCALGO_H
#include <string>
class EncryptionAlgorithm {
public:
/// number of bits needed to code the algorithm
static const unsigned int IRep_size = 5 ;
/// integer representation of encryption algorithm
enum IRep {
NONE = 0,
TWOFISH = 1,
RIJNDAEL128 = 2,
RIJNDAEL192 = 3,
RIJNDAEL256 = 4,
SAFERPLUS = 5,
RC2 = 6,
XTEA = 7,
SERPENT = 8,
SAFERSK64 = 9,
SAFERSK128 = 10,
CAST256 = 11,
LOKI97 = 12,
GOST = 13,
THREEWAY = 14,
CAST128 = 15,
BLOWFISH = 16,
DES = 17,
TRIPLEDES = 18,
ENIGMA = 19,
ARCFOUR = 20,
PANAMA = 21,
WAKE = 22
} ;
EncryptionAlgorithm (void) ;
EncryptionAlgorithm (IRep irep) ;
/**
* construct a new EncryptionAlgorithm object from a std::string representation
* \param srep a valid(!) std::string representation
**/
EncryptionAlgorithm (std::string srep) ;
void setValue (IRep irep) ;
std::string getStringRep (void) const ;
IRep getIntegerRep (void) const ;
bool operator== (const EncryptionAlgorithm& algo) const
{ return (Value == algo.Value) ; } ;
/**
* check if srep is a valid std::string representation (w.r.t the Translations array)
* \param srep a std::string that maybe represents an encryption algorithm fron the Translations table
* \return true iff the Translations table contains srep
**/
static bool isValidStringRep (std::string srep) ;
static bool isValidIntegerRep (unsigned int irep) ;
/**
* translate an integer representation into the corresponding std::string representation
**/
static std::string translate (IRep irep) ;
/**
* translate a valid std::string representation into the corresponding integer representation
**/
static IRep translate (std::string srep) ;
private:
static const unsigned int NumValues = 23 ;
IRep Value ;
typedef struct struct_Translation {
IRep irep ;
char* srep ;
} Translation ;
static const Translation Translations[] ;
} ;
#endif // ndef SH_ENCALGO_H

View File

@ -0,0 +1,107 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "common.h"
#include "EncryptionMode.h"
EncryptionMode::EncryptionMode ()
{
setValue (ECB) ;
}
EncryptionMode::EncryptionMode (EncryptionMode::IRep irep)
{
setValue (irep) ;
}
EncryptionMode::EncryptionMode (std::string srep)
{
setValue (translate (srep)) ;
}
void EncryptionMode::setValue (EncryptionMode::IRep irep)
{
Value = irep ;
}
std::string EncryptionMode::getStringRep () const
{
return translate(Value) ;
}
EncryptionMode::IRep EncryptionMode::getIntegerRep () const
{
return Value ;
}
bool EncryptionMode::isValidStringRep (std::string srep)
{
bool retval = false ;
for (unsigned int i = 0 ; i < NumValues ; i++) {
if (Translations[i].srep == srep) {
retval = true ;
}
}
return retval ;
}
bool EncryptionMode::isValidIntegerRep (unsigned int irep)
{
return (irep < NumValues) ;
}
std::string EncryptionMode::translate (EncryptionMode::IRep irep)
{
std::string retval ;
bool found = false ;
for (unsigned int i = 0 ; i < NumValues ; i++) {
if (Translations[i].irep == irep) {
retval = std::string (Translations[i].srep) ;
found = true ;
}
}
myassert (found) ;
return retval ;
}
EncryptionMode::IRep EncryptionMode::translate (std::string srep)
{
IRep retval = ECB ;
bool found = false ;
for (unsigned int i = 0 ; i < NumValues ; i++) {
if (Translations[i].srep == srep) {
retval = Translations[i].irep ;
found = true ;
}
}
myassert (found) ;
return retval ;
}
const EncryptionMode::Translation EncryptionMode::Translations[] = {
{ ECB, "ecb" },
{ CBC, "cbc" },
{ OFB, "ofb" },
{ CFB, "cfb" },
{ NOFB, "nofb" },
{ NCFB, "ncfb" },
{ CTR, "ctr" },
{ STREAM, "stream" }
} ;

View File

@ -0,0 +1,79 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_ENCMODE_H
#define SH_ENCMODE_H
#include <string>
class EncryptionMode {
public:
/// number of bits needed to code the mode
static const unsigned int IRep_size = 3 ;
/// integer representation of encryption mode
enum IRep {
ECB = 0,
CBC = 1,
OFB = 2,
CFB = 3,
NOFB = 4,
NCFB = 5,
CTR = 6,
STREAM = 7
} ;
/**
* construct a new EncryptionMode object setting Value to ECB
**/
EncryptionMode (void) ;
EncryptionMode (IRep irep) ;
/**
* construct a new EncryptionMode object from a std::string representation
* \param srep a valid(!) std::string representation
**/
EncryptionMode (std::string srep) ;
void setValue (IRep irep) ;
std::string getStringRep (void) const ;
IRep getIntegerRep (void) const ;
bool operator== (const EncryptionMode& mode) const
{ return (Value == mode.Value) ; } ;
static bool isValidStringRep (std::string srep) ;
static bool isValidIntegerRep (unsigned int irep) ;
static std::string translate (IRep irep) ;
static IRep translate (std::string srep) ;
private:
static const unsigned int NumValues = 8 ;
IRep Value ;
typedef struct struct_Translation {
IRep irep ;
char* srep ;
} Translation ;
static const Translation Translations[] ;
} ;
#endif // ndef SH_ENCMODE_H

98
steghide-src/Extractor.cc Normal file
View File

@ -0,0 +1,98 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <string>
#include "BitString.h"
#include "CvrStgFile.h"
#include "EmbData.h"
#include "Extractor.h"
#include "SampleValue.h"
#include "Selector.h"
#include "common.h"
#include "error.h"
EmbData* Extractor::extract ()
{
VerboseMessage vrs ;
if (Args.StgFn.getValue() == "") {
vrs.setMessage (_("reading stego file from standard input...")) ;
}
else {
vrs.setMessage (_("reading stego file \"%s\"..."), Args.StgFn.getValue().c_str()) ;
}
vrs.setNewline (false) ;
vrs.printMessage() ;
Globs.TheCvrStgFile = CvrStgFile::readFile (StegoFileName) ;
VerboseMessage vd (_(" done")) ;
vd.printMessage() ;
EmbData* embdata = new EmbData (EmbData::EXTRACT, Passphrase) ;
Selector sel (Globs.TheCvrStgFile->getNumSamples(), Passphrase) ;
VerboseMessage ve (_("extracting data...")) ;
ve.setNewline (false) ;
ve.printMessage() ;
unsigned long sv_idx = 0 ;
while (!embdata->finished()) {
unsigned short bitsperembvalue = AUtils::log2_ceil<unsigned short> (Globs.TheCvrStgFile->getEmbValueModulus()) ;
unsigned long embvaluesrequested = AUtils::div_roundup<unsigned long> (embdata->getNumBitsRequested(), bitsperembvalue) ;
if (sv_idx + (Globs.TheCvrStgFile->getSamplesPerVertex() * embvaluesrequested) >= Globs.TheCvrStgFile->getNumSamples()) {
if (Globs.TheCvrStgFile->is_std()) {
throw CorruptDataError (_("the stego data from standard input is too short to contain the embedded data.")) ;
}
else {
throw CorruptDataError (_("the stego file \"%s\" is too short to contain the embedded data."), Globs.TheCvrStgFile->getName().c_str()) ;
}
}
BitString bits (Globs.TheCvrStgFile->getEmbValueModulus()) ;
for (unsigned long i = 0 ; i < embvaluesrequested ; i++) {
EmbValue ev = 0 ;
for (unsigned int j = 0 ; j < Globs.TheCvrStgFile->getSamplesPerVertex() ; j++, sv_idx++) {
ev = (ev + Globs.TheCvrStgFile->getEmbeddedValue (sel[sv_idx])) % Globs.TheCvrStgFile->getEmbValueModulus() ;
}
bits.appendNAry(ev) ;
}
embdata->addBits (bits) ;
}
vd.printMessage() ;
// TODO (postponed due to message freeze): rename into "verifying crc32 checksum..."
VerboseMessage vc (_("checking crc32 checksum...")) ;
vc.setNewline (false) ;
vc.printMessage() ;
if (embdata->checksumOK()) {
VerboseMessage vok (_(" ok")) ;
vok.printMessage() ;
}
else {
VerboseMessage vfailed (_(" FAILED!")) ;
vfailed.printMessage() ;
CriticalWarning w (_("crc32 checksum failed! extracted data is probably corrupted.")) ;
w.printMessage() ;
}
return embdata ;
}

38
steghide-src/Extractor.h Normal file
View File

@ -0,0 +1,38 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_EXTRACTOR_H
#define SH_EXTRACTOR_H
#include <string>
class Extractor {
public:
Extractor (std::string stgfn, std::string pp)
: StegoFileName(stgfn), Passphrase(pp) {} ;
EmbData* extract (void) ;
private:
std::string StegoFileName ;
std::string Passphrase ;
} ;
#endif // ndef SH_EXTRACTOR_H

76
steghide-src/Globals.h Normal file
View File

@ -0,0 +1,76 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_GLOBALS_H
#define SH_GLOBALS_H
#include <cstdlib>
class CvrStgFile ;
class Graph ;
/**
* \class Globals
* \brief some useful pointers that should be global
*
* This class provides some useful global variables. They are not static,
* instead there exists a global Globs object to make it easy to use
* different Globals objects during one execution (this is necessary for
* some unit-tests).
*
* The Graph constructor as well as the CvrStgFile constructor write itself
* into the Globs object. Doing this so early is necessary because the
* construction of a Graph or CvrStgFile object might already need a correctly
* set Globs object.
*
* During one "normal" (i.e. non-unit-test) execution of steghide only one
* Globals object will be used, namely the one created in main(), filled in
* the Graph and the CvrStgFile constructor and stored at the Globs pointer.
*
* The main purpose of making these variables global is to save memory in
* classes that are small but used in large numbers (e.g. *SampleValue,...).
* Using static pointers in these classed would be too chaotic to reset for
* the unit tests and non-static pointers would need too much memory.
**/
class Globals {
public:
Globals (CvrStgFile* f = NULL, Graph* g = NULL)
: TheCvrStgFile(f), TheGraph(g) {} ;
/// the cover-/stego- file that is operated on (set in CvrStgFile::CvrStgFile)
CvrStgFile* TheCvrStgFile ;
/// the graph that is built upon the cover-/stego-file (set in Graph::Graph)
Graph* TheGraph ;
void operator= (const Globals& g)
{
TheCvrStgFile = g.TheCvrStgFile ;
TheGraph = g.TheGraph ;
}
void reset (void)
{
TheCvrStgFile = NULL ;
TheGraph = NULL ;
}
} ;
#endif // ndef SH_GLOBALS_H

668
steghide-src/Graph.cc Normal file
View File

@ -0,0 +1,668 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <ctime>
#include <list>
#include <map>
#include <vector>
#include <climits>
#include "BitString.h"
#include "CvrStgFile.h"
#include "Edge.h"
#include "Graph.h"
#include "Selector.h"
#include "Vertex.h"
#include "common.h"
#include "msg.h"
#include "wrapper_hash_set.h"
Graph::Graph (CvrStgFile *cvr, const BitString& emb, Selector& sel)
{
Globs.TheGraph = this ;
File = cvr ;
EmbValueModulus = File->getEmbValueModulus() ;
SamplesPerVertex = File->getSamplesPerVertex() ;
// construct sposs and tvalues
std::vector<SamplePos*> sposs ;
std::vector<EmbValue> tvalues ;
unsigned long n = emb.getNAryLength() ;
for (unsigned long i = 0 ; i < n ; i++) {
SamplePos *poss = new SamplePos[File->getSamplesPerVertex()] ;
EmbValue modulosum = 0 ;
for (unsigned int j = 0 ; j < File->getSamplesPerVertex() ; j++) {
poss[j] = sel[(i * File->getSamplesPerVertex()) + j] ;
modulosum = (modulosum + File->getEmbeddedValue(poss[j])) % File->getEmbValueModulus() ;
}
if (modulosum != emb.getNAry(i)) {
sposs.push_back (poss) ;
tvalues.push_back (emb.getNAry(i)) ;
}
else {
delete[] poss ;
}
}
myassert (sposs.size() == tvalues.size()) ;
std::vector<SampleValue**> svalues ; // will contain pointers to unique sample value objects
constructSamples (sposs, svalues) ;
myassert (sposs.size() == svalues.size()) ;
constructVertices (sposs, svalues, tvalues) ;
constructEdges () ;
}
void Graph::constructSamples (const std::vector<SamplePos*>& sposs, std::vector<SampleValue**>& svalues)
{
const VertexLabel numvertices = sposs.size() ;
svalues.resize (numvertices) ;
// fill a hash table with the (unique) sample values and svalues with pointers to them
sgi::hash_set<SampleValue*,SampleValueHash,SampleValuesEqual> SampleValues_set ;
for (unsigned long i = 0 ; i < numvertices ; i++) {
svalues[i] = new SampleValue*[File->getSamplesPerVertex()] ;
for (unsigned short j = 0 ; j < File->getSamplesPerVertex() ; j++) {
SampleValue *sv = File->getSampleValue (sposs[i][j]) ;
sgi::hash_set<SampleValue*,SampleValueHash,SampleValuesEqual>::iterator res = SampleValues_set.find (sv) ;
if (res == SampleValues_set.end()) { // sample has not been found - add it !
SampleValues_set.insert (sv) ;
svalues[i][j] = sv ;
}
else { // sample value is already in SampleValues_set
delete sv ;
svalues[i][j] = *res ;
}
}
}
// move the hash_set SampleValues_set into the vector SampleValues, set sample labels
SampleValues = std::vector<SampleValue*> (SampleValues_set.size()) ;
unsigned long label = 0 ;
for (sgi::hash_set<SampleValue*,SampleValueHash,SampleValuesEqual>::const_iterator i = SampleValues_set.begin() ; i != SampleValues_set.end() ; i++) {
SampleValues[label] = *i ;
SampleValues[label]->setLabel (label) ;
label++ ;
}
}
void Graph::constructVertices (std::vector<SamplePos*>& sposs, std::vector<SampleValue**>& svalues, const std::vector<EmbValue>& tvalues)
{
const VertexLabel numvertices = sposs.size() ;
Vertices = std::vector<Vertex*> (numvertices) ;
for (VertexLabel i = 0 ; i < numvertices ; i++) {
Vertices[i] = new Vertex (i, sposs[i], svalues[i], tvalues[i]) ;
}
}
void Graph::constructEdges ()
{
// create SampleValue Adjacency Lists
SVALists = File->calcSVAdjacencyLists (SampleValues) ;
// allocate memory for SampleOccurences
SampleOccurences = std::vector<std::list<SampleOccurence> > (SampleValues.size()) ;
DeletedSampleOccurences = std::vector<std::list<SampleOccurence> > (SampleValues.size()) ;
NumSampleOccurences = std::vector<UWORD32*> (SampleValues.size()) ;
NumDeletedSampleOccurences = std::vector<UWORD32*> (SampleValues.size()) ;
for (SampleValueLabel lbl = 0 ; lbl < SampleValues.size() ; lbl++) {
NumSampleOccurences[lbl] = new UWORD32[EmbValueModulus] ;
NumDeletedSampleOccurences[lbl] = new UWORD32[EmbValueModulus] ;
for (unsigned short t = 0 ; t < EmbValueModulus ; t++) {
NumSampleOccurences[lbl][t] = 0 ;
NumDeletedSampleOccurences[lbl][t] = 0 ;
}
}
// fill SampleOccurences
for (std::vector<Vertex*>::iterator vit = Vertices.begin() ; vit != Vertices.end() ; vit++) {
for (unsigned short j = 0 ; j < Globs.TheCvrStgFile->getSamplesPerVertex() ; j++) {
SampleOccurence occ (*vit, j) ;
SampleValueLabel lbl = (*vit)->getSampleValue(j)->getLabel() ;
std::list<SampleOccurence>::iterator occit = SampleOccurences[lbl].insert (SampleOccurences[lbl].end(), occ) ;
NumSampleOccurences[lbl][(*vit)->getTargetValue(j)]++ ;
(*vit)->setSampleOccurenceIt (j, occit) ;
}
}
// compute NumEdges for all sample values
for (SampleValueLabel srclbl = 0 ; srclbl < SampleValues.size() ; srclbl++) {
for (EmbValue t = 0 ; t < EmbValueModulus ; t++) {
UWORD32 numedges = 0 ;
for (std::vector<SampleValue*>::const_iterator destsv = (*(SVALists[t]))[srclbl].begin() ;
destsv != (*(SVALists[t]))[srclbl].end() ; destsv++) {
numedges += NumSampleOccurences[(*destsv)->getLabel()][SampleValues[srclbl]->getEmbeddedValue()] ;
}
SampleValues[srclbl]->setNumEdges(t, numedges) ;
}
}
}
Graph::~Graph()
{
for (std::vector<Vertex*>::iterator i = Vertices.begin() ; i != Vertices.end() ; i++) {
delete *i ;
}
for (std::vector<SampleValue*>::iterator svit = SampleValues.begin() ; svit != SampleValues.end() ; svit++) {
delete *svit ;
}
for (EmbValue t = 0 ; t < EmbValueModulus ; t++) {
delete SVALists[t] ;
}
for (SampleValueLabel lbl = 0 ; lbl < SampleValues.size() ; lbl++) {
delete[] NumSampleOccurences[lbl] ;
delete[] NumDeletedSampleOccurences[lbl] ;
}
}
void Graph::unmarkDeletedAllVertices ()
{
for (std::vector<Vertex*>::iterator it = Vertices.begin() ; it != Vertices.end() ; it++) {
(*it)->unmarkDeleted() ;
}
}
std::list<SampleOccurence>::iterator Graph::markDeletedSampleOccurence (std::list<SampleOccurence>::iterator it)
{
Vertex *v = it->getVertex() ;
unsigned short i = it->getIndex() ;
SampleValueLabel lbl = v->getSampleValue(i)->getLabel() ;
SampleOccurences[lbl].erase (it) ;
NumSampleOccurences[lbl][v->getTargetValue(i)]-- ;
NumDeletedSampleOccurences[lbl][v->getTargetValue(i)]++ ;
return DeletedSampleOccurences[lbl].insert (DeletedSampleOccurences[lbl].end(), SampleOccurence (v, i)) ;
}
std::list<SampleOccurence>::iterator Graph::unmarkDeletedSampleOccurence (std::list<SampleOccurence>::iterator it)
{
Vertex *v = it->getVertex() ;
unsigned short i = it->getIndex() ;
SampleValueLabel lbl = v->getSampleValue(i)->getLabel() ;
DeletedSampleOccurences[lbl].erase (it) ;
NumDeletedSampleOccurences[lbl][v->getTargetValue(i)]-- ;
NumSampleOccurences[lbl][v->getTargetValue(i)]++ ;
return SampleOccurences[lbl].insert (SampleOccurences[lbl].end(), SampleOccurence (v, i)) ;
}
float Graph::getAvgVertexDegree () const
{
unsigned long sumdeg = 0 ;
for (std::vector<Vertex*>::const_iterator vit = Vertices.begin() ; vit != Vertices.end() ; vit++) {
sumdeg += (*vit)->getDegree() ;
}
return ((float) sumdeg / (float) Vertices.size()) ;
}
void Graph::printVerboseInfo()
{
if (Args.Verbosity.getValue() == VERBOSE || Args.Verbosity.getValue() == STATS) {
unsigned long sumdeg = 0 ;
unsigned long mindeg = ULONG_MAX ;
unsigned long maxdeg = 0 ;
for (std::vector<Vertex*>::iterator i = Vertices.begin() ; i != Vertices.end() ; i++) {
unsigned long deg = (*i)->getDegree() ;
sumdeg += deg ;
if (deg < mindeg) {
mindeg = deg ;
}
if (deg > maxdeg) {
maxdeg = deg ;
}
}
float avgdeg = ((float) sumdeg / (float) Vertices.size()) ;
myassert (sumdeg % 2 == 0) ;
if (Args.Verbosity.getValue() == STATS) {
printf ("%lu:%lu:%lu:%lu:%lu:%.1f:",
(unsigned long) SampleValues.size(), // number of distinct sample values
(unsigned long) Vertices.size(), // number of vertices
sumdeg / 2, // number of edges
mindeg, // minimum vertex degree
maxdeg, // maximum vertex degree
avgdeg // average vertex degree
) ;
}
else { // Verbosity is VERBOSE
VerboseMessage vmsg1 (_(" %lu sample values, %lu vertices, %lu edges"), SampleValues.size(), Vertices.size(), sumdeg / 2) ;
vmsg1.printMessage() ;
}
}
}
bool Graph::check (bool verbose) const
{
bool retval = true ;
retval = check_Vertices(verbose) && retval ;
retval = check_SampleValues(verbose) && retval ;
retval = check_SampleOccurences(verbose) && retval ;
retval = check_SVALists(verbose) && retval ;
return retval ;
}
bool Graph::check_Vertices (bool verbose) const
{
bool label_consistency = true ;
for (unsigned long i = 0 ; i < Vertices.size() ; i++) {
label_consistency = (Vertices[i]->getLabel() == i) && label_consistency ;
}
// check if SampleValue pointers are the same as in SampleValues data structure
bool svuniqueness = true ;
for (unsigned long i = 0 ; i < Vertices.size() ; i++) {
for (unsigned short j = 0 ; j < File->getSamplesPerVertex() ; j++) {
SampleValue* sv = Vertices[i]->getSampleValue(j) ;
svuniqueness = (sv == SampleValues[sv->getLabel()]) && svuniqueness ;
}
}
return label_consistency && svuniqueness ;
}
bool Graph::check_SampleValues (bool verbose) const
{
unsigned long n = SampleValues.size() ;
bool label_consistency = true ;
for (unsigned long i = 0 ; i < n ; i++) {
if (SampleValues[i]->getLabel() != i) {
label_consistency = false ;
if (verbose) {
std::cerr << "----- FAILED: check_SampleValues -----" << std::endl ;
std::cerr << "SamplesValue[" << i << "]->getLabel(): " << SampleValues[i]->getLabel() << std::endl ;
std::cerr << "--------------------------------------" << std::endl ;
}
}
}
bool sv_uniqueness = true ;
for (unsigned long i = 0 ; i < n ; i++) {
for (unsigned long j = 0 ; j < n ; j++) {
if (i != j) {
if (*(SampleValues[i]) == *(SampleValues[j])) {
sv_uniqueness = false ;
if (verbose) {
std::cerr << "----- FAILED: check_SampleValues -----" << std::endl ;
std::cerr << "uniqueness violated with the following two samples:" << std::endl ;
SampleValues[i]->print(1) ;
SampleValues[j]->print(1) ;
std::cerr << "--------------------------------------" << std::endl ;
}
}
}
}
}
return (label_consistency && sv_uniqueness) ;
}
bool Graph::check_SampleOccurences (bool verbose) const
{
bool retval = true ;
retval = check_SampleOccurences_size (verbose) && retval ;
retval = check_SampleOccurences_correctness (verbose) && retval ;
retval = check_SampleOccurences_completeness (verbose) && retval ;
return retval ;
}
bool Graph::check_SampleOccurences_size (bool verbose) const
{
bool size = (SampleOccurences.size() == SampleValues.size()) ;
if (!size && verbose) {
std::cerr << std::endl << "---- FAILED: check_SampleOccurences_size ----" << std::endl ;
std::cerr << "SampleOccurences.size(): " << SampleOccurences.size() << std::endl ;
std::cerr << "SampleValues.size(): " << SampleValues.size() << std::endl ;
std::cerr << "-------------------------------------" << std::endl ;
}
return size ;
}
bool Graph::check_SampleOccurences_correctness (bool verbose) const
{
bool correctness = true ;
for (unsigned long lbl = 0 ; lbl < SampleValues.size() ; lbl++) {
for (std::list<SampleOccurence>::const_iterator socit = SampleOccurences[lbl].begin() ; socit != SampleOccurences[lbl].end() ; socit++) {
Vertex *v = socit->getVertex() ;
unsigned short idx = socit->getIndex() ;
correctness = (v->getSampleValue(idx) == SampleValues[lbl]) && correctness ; // pointer equivalence
}
}
return correctness ;
}
bool Graph::check_SampleOccurences_completeness (bool verbose) const
{
bool completeness = true ;
for (unsigned long vlbl = 0 ; vlbl < Vertices.size() ; vlbl++) {
for (unsigned short j = 0 ; j < File->getSamplesPerVertex() ; j++) {
SampleOccurence soc (Vertices[vlbl], j) ;
SampleValueLabel svlbl = Vertices[vlbl]->getSampleValue(j)->getLabel() ;
completeness = (find(SampleOccurences[svlbl].begin(), SampleOccurences[svlbl].end(), soc) != SampleOccurences[svlbl].end()) && completeness ;
}
}
return completeness ;
}
bool Graph::check_SVALists (bool verbose) const
{
bool retval = true ;
retval = check_SVALists_size (verbose) && retval ;
retval = check_SVALists_soundness (verbose) && retval ;
retval = check_SVALists_sorted (verbose) && retval ;
retval = check_SVALists_uniqueness (verbose) && retval ;
retval = check_SVALists_completeness (verbose) && retval ;
return retval ;
}
bool Graph::check_SVALists_size (bool verbose) const
{
bool size = true ;
for (EmbValue i = 0 ; i < File->getEmbValueModulus() ; i++) {
size = (SVALists[i]->getNumRows() == SampleValues.size()) && size ;
if ((SVALists[i]->getNumRows() != SampleValues.size()) && verbose) {
std::cerr << std::endl << "---- FAILED: check_SVALists_size ----" << std::endl ;
std::cerr << "SVALists[" << i << "]->getNumRows(): " << SVALists[i]->getNumRows() << std::endl ;
std::cerr << "SampleValues.size(): " << SampleValues.size() << std::endl ;
std::cerr << "-------------------------------------" << std::endl ;
}
}
return size ;
}
bool Graph::check_SVALists_soundness (bool verbose) const
{
unsigned long numsvs = SampleValues.size() ;
// check if everything in SVALists[i][j] really is a neighbour of j and has the embedded value i
bool target_ok = true ;
bool neigh_ok = true ;
for (EmbValue t = 0 ; t < File->getEmbValueModulus() ; t++) {
for (SampleValueLabel srclbl = 0 ; srclbl < numsvs ; srclbl++) {
SampleValue* srcsv = SampleValues[srclbl] ;
const std::vector<SampleValue*> &row = (*(SVALists[t]))[srclbl];
for (std::vector<SampleValue*>::const_iterator destsv = row.begin() ; destsv != row.end() ; destsv++) {
if ((*destsv)->getEmbeddedValue() != t) {
target_ok = false ;
if (verbose) {
std::cerr << std::endl << "---- FAILED: check_SVALists_soundness ----" << std::endl ;
std::cerr << "in SVALists[" << (int) t << "][" << srclbl << "] is a sv with getEmbeddedValue() == " << (*destsv)->getEmbeddedValue() << std::endl ;
std::cerr << "-------------------------------------" << std::endl ;
}
}
if (!srcsv->isNeighbour(*destsv)) {
neigh_ok = false ;
if (verbose) {
std::cerr << std::endl << "---- FAILED: check_SVALists_soundness ----" << std::endl ;
std::cerr << "in SVALists[" << (int) t << "][" << srclbl << "] is a sv that is not a neighbour of " << srclbl << std::endl ;
std::cerr << "-------------------------------------" << std::endl ;
}
}
}
}
}
return target_ok && neigh_ok ;
}
bool Graph::check_SVALists_sorted (bool verbose) const
{
unsigned long numsvs = SampleValues.size() ;
// check if SVALists[t][l][1...n] have increasing distance
bool sorted = true ;
for (EmbValue t = 0 ; t < File->getEmbValueModulus() ; t++) {
for (SampleValueLabel srclbl = 0 ; srclbl < numsvs ; srclbl++) {
SampleValue* srcsv = SampleValues[srclbl] ;
const std::vector<SampleValue*> &row = (*(SVALists[t]))[srclbl] ;
if (row.size() > 1) {
for (unsigned int i = 0 ; i < (row.size() - 1) ; i++) {
UWORD32 d1 = srcsv->calcDistance (row[i]) ;
UWORD32 d2 = srcsv->calcDistance (row[i + 1]) ;
if (!(d1 <= d2)) {
sorted = false ;
if (verbose) {
std::cerr << std::endl << "---- FAILED: check_SVALists_sorted ----" << std::endl ;
std::cerr << "source sample:" << std::endl ;
srcsv->print(1) ;
std::cerr << "dest sample at position " << i << ":" << std::endl ;
row[i]->print(1) ;
std::cerr << "dest sample at position " << i + 1 << ":" << std::endl ;
row[i + 1]->print(1) ;
std::cerr << "-------------------------------------" << std::endl ;
}
}
}
}
}
}
return sorted ;
}
bool Graph::check_SVALists_uniqueness (bool verbose) const
{
// check if there is no sample value that has two entries in an SVAList
bool unique = true ;
for (EmbValue t = 0 ; t < File->getEmbValueModulus() ; t++) {
for (SampleValueLabel srclbl = 0 ; srclbl < SampleValues.size() ; srclbl++) {
for (unsigned int i = 0 ; i < (*(SVALists[t]))[srclbl].size() ; i++) {
for (unsigned int j = i + 1 ; j < (*(SVALists[t]))[srclbl].size() ; j++) {
if (*((*(SVALists[t]))[srclbl][i]) == *((*(SVALists[t]))[srclbl][j])) {
unique = false ;
if (verbose) {
std::cerr << std::endl << "---- FAILED: check_SVALists_uniqueness ----" << std::endl ;
std::cerr << "SVALists[" << (int) t << "][" << srclbl << "][" << i << "]->getLabel() == " << (*(SVALists[t]))[srclbl][i]->getLabel() << std::endl ;
std::cerr << "SVALists[" << (int) t << "][" << srclbl << "][" << j << "]->getLabel() == " << (*(SVALists[t]))[srclbl][j]->getLabel() << std::endl ;
std::cerr << "-------------------------------------" << std::endl ;
}
}
}
}
}
}
return unique ;
}
bool Graph::check_SVALists_completeness (bool verbose) const
{
bool ok = true ;
unsigned long numsvs = SampleValues.size() ;
for (unsigned long i = 0 ; i < numsvs ; i++) {
SampleValue *svsrc = SampleValues[i] ;
for (unsigned long j = 0 ; j < numsvs ; j++) {
SampleValue *svdest = SampleValues[j] ;
if (svsrc->isNeighbour(svdest) && (svsrc->getLabel() != svdest->getLabel())) {
// svsrc and svdest are neighbours => there must be an entry in SVALists
myassert (svdest->isNeighbour (svsrc)) ;
const std::vector<SampleValue*> &row = (*(SVALists[svdest->getEmbeddedValue()]))[i] ;
bool found = false ;
for (std::vector<SampleValue*>::const_iterator k = row.begin() ; k != row.end() ; k++) {
if ((*k)->getLabel() == j) {
found = true ;
}
}
if (!found) {
ok = false ;
if (verbose) {
std::cerr << std::endl << "---- FAILED: check_SVALists_completeness ----" << std::endl ;
std::cerr << "sample values "<< svsrc->getLabel() << " and " << svdest->getLabel() << " are neighbours..." << std::endl ;
std::cerr << "...but SVALists[" << (int) svdest->getEmbeddedValue() << "][" << i << "] does not contain " << j << std::endl ;
std::cerr << "-------------------------------------" << std::endl ;
}
}
}
}
}
return ok ;
}
#ifdef DEBUG
void Graph::print (void) const
{
unsigned long sumdeg = 0 ;
for (std::vector<Vertex*>::const_iterator i = Vertices.begin() ; i != Vertices.end() ; i++) {
sumdeg += (*i)->getDegree() ;
}
myassert (sumdeg % 2 == 0) ;
std::cout << Vertices.size() << " " << (sumdeg / 2) << " U" << std::endl ;
for (unsigned long i = 0 ; i < Vertices.size() ; i++) {
std::cout << Vertices[i]->getDegree() << " " << (i + 1) << " 0 0" << std::endl ;
for (unsigned short j = 0 ; j < File->getSamplesPerVertex() ; j++) {
SampleValue *srcsample = Vertices[i]->getSampleValue(j) ;
EmbValue srctarget = Vertices[i]->getTargetValue(j) ;
for (unsigned long k = 0 ; k != Vertices.size() ; k++) {
if (i != k) { // no loops
for (unsigned short l = 0 ; l < File->getSamplesPerVertex() ; l++) {
SampleValue *destsample = Vertices[k]->getSampleValue(l) ;
EmbValue desttarget = Vertices[k]->getTargetValue(l) ;
if ((srcsample->isNeighbour(destsample)) &&
(srcsample->getEmbeddedValue() == desttarget) &&
(destsample->getEmbeddedValue() == srctarget)) {
std::cout << (k + 1) << " 0" << std::endl ;
}
}
}
}
}
}
}
void Graph::print_gml (std::ostream& out) const
{
printPrologue_gml(out) ;
srand ((unsigned int) time (NULL)) ;
std::vector<bool> nodeprinted (Vertices.size()) ;
std::vector<bool> edgesprinted (Vertices.size()) ;
for (unsigned int i = 0 ; i < Vertices.size() ; i++) {
printVertex_gml (out, Vertices[i], 1, nodeprinted, edgesprinted, false) ;
}
printEpilogue_gml(out) ;
}
void Graph::printVertex_gml (std::ostream& out, Vertex* vstart, unsigned int recdepth, std::vector<bool>& nodeprinted, std::vector<bool>& edgesprinted, bool start) const
{
const float width = 1300.0 ;
const float height = 1000.0 ;
if (!nodeprinted[vstart->getLabel()]) {
out << " node [" << std::endl ;
out << " id " << vstart->getLabel() << std::endl ;
std::string vlabel = "" ;
for (unsigned short i = 0 ; i < File->getSamplesPerVertex() ; i++) {
vlabel += vstart->getSampleValue(i)->getName() ;
if (i != File->getSamplesPerVertex() - 1) {
vlabel += "/" ;
}
}
out << " label \"" << vlabel << "\"" << std::endl ;
out << " graphics [" << std::endl ;
out << " x " << (width * (rand() / (RAND_MAX + 1.0))) << std::endl ;
out << " y " << (height * (rand() / (RAND_MAX + 1.0))) << std::endl ;
out << " w 10.0" << std::endl ;
out << " h 10.0" << std::endl ;
out << " type \"rectangle\"" << std::endl ;
out << " width 1.0" << std::endl ;
if (start) {
out << " fill \"#00FF00\"" << std::endl ;
}
out << " ]" << std::endl ;
out << " ]" << std::endl ;
}
nodeprinted[vstart->getLabel()] = true ;
if (recdepth > 0) {
EdgeIterator eit (vstart) ;
while (!eit.isFinished()) {
const Edge* e = *eit ;
Vertex* vnext = e->getOtherVertex(vstart) ;
if (!edgesprinted[vstart->getLabel()] && !edgesprinted[vnext->getLabel()]) {
out << " edge [" << std::endl ;
out << " source " << e->getVertex1()->getLabel() << std::endl ;
out << " target " << e->getVertex2()->getLabel() << std::endl ;
out << " label \"" ;
out << e->getVertex1()->getSampleValue(e->getIndex1())->getName() << "/" ;
out << e->getVertex2()->getSampleValue(e->getIndex2())->getName() << "\"" << std::endl ;
out << " ]" << std::endl ;
}
++eit ;
}
edgesprinted[vstart->getLabel()] = true ;
eit.reset() ;
while (!eit.isFinished()) {
const Edge* e = *eit ;
Vertex* vnext = e->getOtherVertex(vstart) ;
printVertex_gml (out, vnext, recdepth - 1, nodeprinted, edgesprinted, false) ;
++eit ;
}
}
}
void Graph::printPrologue_gml (std::ostream& out) const
{
out << "graph [" << std::endl ;
out << " directed 0" << std::endl ;
}
void Graph::printEpilogue_gml (std::ostream& out) const
{
out << "]" << std::endl ;
}
void Graph::print_Vertices (unsigned short spc) const
{
char* space = new char[spc + 1] ;
for (unsigned short i = 0 ; i < spc ; i++) {
space[i] = ' ' ;
}
space[spc] = '\0' ;
std::cerr << space << "Vertices:" << std::endl ;
for (std::vector<Vertex*>::const_iterator vit = Vertices.begin() ; vit != Vertices.end() ; vit++) {
(*vit)->print(spc + 1) ;
}
}
#endif

209
steghide-src/Graph.h Normal file
View File

@ -0,0 +1,209 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_GRAPH_H
#define SH_GRAPH_H
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <vector>
#include "EdgeIterator.h"
#include "SampleValueAdjacencyList.h"
#include "common.h"
#include "wrapper_hash_set.h"
class BitString ;
class SampleOccurence ;
class Selector ;
class Vertex ;
class VertexContent ;
struct VertexContentsEqual ;
/**
* \class Graph
* \brief a graph constructed from a cover file and a message to be embedded
*
* This class provides a purely graph-theoretic interface to any other class.
* Some classes however need access to the internal (steganographic) representation,
* for example: Vertex, EdgeIterator,... . These are declared as friends of Graph here and
* thus have direct access to the private data structures.
**/
class Graph {
public:
/**
* construct a graph
* \param cvr the underlying cover file
* \param emb the bitstring to be embedded (with correct arity already set)
**/
Graph (CvrStgFile* cvr, const BitString& emb, Selector& sel) ;
/**
* destructor
**/
~Graph (void) ;
/**
* get the number of vertices in this graph
**/
unsigned long getNumVertices (void) const
{ return Vertices.size() ; } ;
/**
* get a vertex
* \param l the vertex label (index) of the vertex to be returned (must be < getNumVertices())
* \return the vertex with label l
**/
Vertex* getVertex (VertexLabel l) const
{ return Vertices[l] ; } ;
void unmarkDeletedAllVertices (void) ;
/**
* calculate and return the average vertex degree
**/
float getAvgVertexDegree (void) const ;
void printVerboseInfo (void) ;
/**
* check the integrity of all data structures,
* only used for debugging and testing
**/
bool check (bool verbose = false) const ;
/**
* check the integrity of the Vertices data structure,
* only used for debugging and testing
**/
bool check_Vertices (bool verbose = false) const ;
/**
* check the integrity of the SampleValues data structure,
* only used for debugging and testing
**/
bool check_SampleValues (bool verbose = false) const ;
/**
* check the integrity of the SampleOccurences data structure,
* it is assumed that DeletedSampleOccurences is empty,
* only used for debugging and testing
**/
bool check_SampleOccurences (bool verbose = false) const ;
/**
* check the integrity of the SVALists data structure,
* only used for debugging and testing
**/
bool check_SVALists (bool verbose = false) const ;
#ifdef DEBUG
/**
* prints graph in a format suitable as input to the C implementation
* of Gabow's non-weighted matching algorithm by E. Rothberg to stdout
* (available at: ftp://ftp.zib.de/pub/Packages/mathprog/matching/index.html
**/
void print (void) const ;
void print_gml (std::ostream& out) const ;
void printVertex_gml (std::ostream& out, Vertex* v, unsigned int recdepth, std::vector<bool>& nodeprinted, std::vector<bool>& edgesprinted, bool start = true) const ;
void printPrologue_gml (std::ostream& out) const ;
void printEpilogue_gml (std::ostream& out) const ;
void print_Vertices (unsigned short spc = 0) const ;
#endif
private:
//
// friend-declarations
//
friend class WKSConstructionHeuristic ;
friend class EdgeIterator ;
friend class SampleValueAdjacencyList ;
friend class Vertex ;
/// contains the vertices in this graph - Vertices[l] is the vertex with label l
std::vector<Vertex*> Vertices ;
/// contains the list of (unique) sample values - SampleValues[l] is the sample value with label l
std::vector<SampleValue*> SampleValues ;
/// contains the sample value adjacency lists (SVALists[v] contains only sample values with embedded value v)
std::vector<SampleValueAdjacencyList*> SVALists ;
/// SampleOccurences[l] contains all occurences of the sample value with label l
std::vector<std::list<SampleOccurence> > SampleOccurences ;
/**
* NumSampleOccurences[l][t] contains the number vertices that contain the sample value with label l and associated target t
**/
std::vector<UWORD32*> NumSampleOccurences ;
/// contains those sample occurences that have been marked as deleted from SampleOccurences
std::vector<std::list<SampleOccurence> > DeletedSampleOccurences ;
std::vector<UWORD32*> NumDeletedSampleOccurences ;
std::list<SampleOccurence>::iterator markDeletedSampleOccurence (std::list<SampleOccurence>::iterator it) ;
std::list<SampleOccurence>::iterator unmarkDeletedSampleOccurence (std::list<SampleOccurence>::iterator it) ;
//
// end of friend-declarations
// Note: private members of Graph that are declared beyond this point should
// not be used by friends.
//
/**
* construct sample-related data structures
*
* needs: sposs(unsorted)
* provides: svalues(unsorted,unique), SampleValues
**/
void constructSamples (const std::vector<SamplePos*> &sposs, std::vector<SampleValue**>& svalues) ;
/**
* construct vertex-related data structures
*
* needs: sposs(unsorted), svalues(unsorted,unique), tvalues
* provides: sposs(sorted), Vertices (except SampleOccurenceIts)
**/
void constructVertices (std::vector<SamplePos*>& sposs, std::vector<SampleValue**>& svalues, const std::vector<EmbValue>& tvalues) ;
/**
* construct edge-related data structures
*
* needs: SampleValues, Vertices (except SampleOccurenceIts)
* provides: SVALists, SampleOccurences, Vertices (SampleOccurenceIts)
**/
void constructEdges (void) ;
CvrStgFile *File ;
EmbValue EmbValueModulus ;
unsigned short SamplesPerVertex ;
bool check_SampleOccurences_size (bool verbose = false) const ;
bool check_SampleOccurences_correctness (bool verbose = false) const ;
bool check_SampleOccurences_completeness (bool verbose = false) const ;
bool check_SVALists_size (bool verbose = false) const ;
bool check_SVALists_soundness (bool verbose = false) const ;
bool check_SVALists_sorted (bool verbose = false) const ;
bool check_SVALists_uniqueness (bool verbose = false) const ;
bool check_SVALists_completeness (bool verbose = false) const ;
} ;
#endif // ndef SH_GRAPH_H

251
steghide-src/JpegFile.cc Normal file
View File

@ -0,0 +1,251 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "common.h"
#ifdef USE_LIBJPEG
#include <cstdio>
#include <iostream>
#include "AUtils.h"
#include "BinaryIO.h"
#include "JpegFile.h"
#include "JpegSampleValue.h"
#include "SMDConstructionHeuristic.h"
#include "error.h"
JpegFile::JpegFile (BinaryIO* io)
: CvrStgFile()
{
setSamplesPerVertex (SamplesPerVertex) ;
setRadius (Radius) ;
setEmbValueModulus (EmbValueModulus) ;
HeightInBlocks = NULL ;
WidthInBlocks = NULL ;
read (io) ;
}
JpegFile::~JpegFile ()
{
if (WidthInBlocks) {
delete[] WidthInBlocks ;
}
if (HeightInBlocks) {
delete[] HeightInBlocks ;
}
}
std::list<CvrStgFile::Property> JpegFile::getProperties () const
{
std::list<CvrStgFile::Property> retval ;
// format
retval.push_back (CvrStgFile::Property (_("format"), "jpeg")) ;
return retval ;
}
void JpegFile::read (BinaryIO* io)
{
CvrStgFile::read (io) ;
// TODO - use BinaryIO (or similar class) as input/output module for libjpeg (to avoid the NotImplementedError and using FILE* here)
FILE *infile = NULL ;
if (io->is_std()) {
throw NotImplementedError (_("can not use standard input as source for jpeg files with libjpeg.")) ;
}
else {
infile = io->getStream() ;
rewind (infile) ;
}
struct jpeg_error_mgr errmgr ;
DeCInfo.err = jpeg_std_error (&errmgr) ;
jpeg_create_decompress (&DeCInfo) ;
jpeg_stdio_src (&DeCInfo, infile) ;
jpeg_read_header (&DeCInfo, TRUE) ;
DctCoeffs = jpeg_read_coefficients (&DeCInfo) ;
// fill HeightInBlocks and WidthInBlocks
unsigned short max_v_samp_factor = 0 ;
unsigned short max_h_samp_factor = 0 ;
for (unsigned short icomp = 0 ; icomp < DeCInfo.num_components ; icomp++) {
max_v_samp_factor = AUtils::max<unsigned short> (max_v_samp_factor, DeCInfo.comp_info[icomp].v_samp_factor) ;
max_h_samp_factor = AUtils::max<unsigned short> (max_h_samp_factor, DeCInfo.comp_info[icomp].h_samp_factor) ;
}
HeightInBlocks = new unsigned int[DeCInfo.num_components] ;
WidthInBlocks = new unsigned int[DeCInfo.num_components] ;
for (unsigned short icomp = 0 ; icomp < DeCInfo.num_components ; icomp++) {
HeightInBlocks[icomp] = AUtils::div_roundup<unsigned int> (DeCInfo.image_height * DeCInfo.comp_info[icomp].v_samp_factor,
8 * max_v_samp_factor) ;
WidthInBlocks[icomp] = AUtils::div_roundup<unsigned int> (DeCInfo.image_width * DeCInfo.comp_info[icomp].h_samp_factor,
8 * max_h_samp_factor) ;
}
// resize LinDctCoeffs to size that is enough to contain all dct coeffs
unsigned long totalnumcoeffs = 0 ;
for (unsigned short icomp = 0 ; icomp < DeCInfo.num_components ; icomp++) {
totalnumcoeffs += CoeffPerBlock * (HeightInBlocks[icomp] * WidthInBlocks[icomp]) ;
}
LinDctCoeffs.resize (totalnumcoeffs) ;
// read data from jpeglib's virtual array into LinDctCoeffs and StegoIndices
UWORD32 linindex = 0 ;
for (unsigned short icomp = 0 ; icomp < DeCInfo.num_components ; icomp++) {
unsigned int currow = 0 ;
while (currow < HeightInBlocks[icomp]) {
unsigned int naccess = 1 ;
JBLOCKARRAY array = (*(DeCInfo.mem->access_virt_barray))
((j_common_ptr) &DeCInfo, DctCoeffs[icomp], currow, naccess, FALSE) ;
for (unsigned int irow = 0 ; irow < naccess ; irow++) {
for (unsigned int iblock = 0 ; iblock < WidthInBlocks[icomp] ; iblock++) {
for (unsigned int icoeff = 0 ; icoeff < CoeffPerBlock ; icoeff++) {
LinDctCoeffs[linindex] = array[irow][iblock][icoeff] ;
// don't use zero dct coefficients to embed data
if (LinDctCoeffs[linindex] != 0) {
StegoIndices.push_back (linindex) ;
}
linindex++ ;
}
}
}
currow += naccess ;
}
}
}
void JpegFile::write ()
{
CvrStgFile::write() ;
FILE* outfile = getBinIO()->getStream() ;
// prepare for writing
jpeg_create_compress (&CInfo) ;
jpeg_copy_critical_parameters (&DeCInfo, &CInfo) ;
struct jpeg_error_mgr jerr2 ;
CInfo.err = jpeg_std_error(&jerr2) ;
jpeg_stdio_dest (&CInfo, outfile) ;
// write file header
jpeg_write_coefficients (&CInfo, DctCoeffs) ;
UWORD32 linindex = 0 ;
for (unsigned short icomp = 0 ; icomp < CInfo.num_components ; icomp++) {
unsigned int currow = 0 ;
while (currow < HeightInBlocks[icomp]) {
unsigned int naccess = 1 ;
JBLOCKARRAY array = (*(CInfo.mem->access_virt_barray))
((j_common_ptr) &CInfo, DctCoeffs[icomp], currow, naccess, TRUE) ;
for (unsigned int irow = 0 ; irow < naccess ; irow++) {
for (unsigned int iblock = 0 ; iblock < WidthInBlocks[icomp] ; iblock++) {
for (unsigned int icoeff = 0 ; icoeff < CoeffPerBlock ; icoeff++) {
array[irow][iblock][icoeff] = LinDctCoeffs[linindex] ;
linindex++ ;
}
}
}
currow += naccess ;
}
}
// write and deallocate everything (writing is possible only once)
jpeg_finish_compress (&CInfo) ;
jpeg_destroy_compress(&CInfo);
jpeg_finish_decompress (&DeCInfo) ;
jpeg_destroy_decompress(&DeCInfo);
}
unsigned long JpegFile::getNumSamples (void) const
{
return StegoIndices.size() ;
}
SampleValue* JpegFile::getSampleValue (const SamplePos pos) const
{
myassert (pos < StegoIndices.size()) ;
return new JpegSampleValue (LinDctCoeffs[StegoIndices[pos]]) ;
}
void JpegFile::replaceSample (const SamplePos pos, const SampleValue* s)
{
const JpegSampleValue* sample = dynamic_cast<const JpegSampleValue*> (s) ;
myassert (sample != NULL) ;
myassert (pos <= StegoIndices.size()) ;
LinDctCoeffs[StegoIndices[pos]] = sample->getDctCoeff() ;
}
EmbValue JpegFile::getEmbeddedValue (const SamplePos pos) const
{
myassert (pos < StegoIndices.size()) ;
return JpegSampleValue::calcEValue (LinDctCoeffs[StegoIndices[pos]]) ;
}
std::vector<MatchingAlgorithm*> JpegFile::getMatchingAlgorithms (Graph* g, Matching* m) const
{
std::vector<MatchingAlgorithm*> retval ;
retval.push_back (new SMDConstructionHeuristic (g, m)) ;
return retval ;
}
#ifdef DEBUG
std::map<SampleKey,unsigned long>* JpegFile::getFrequencies ()
{
unsigned long n = LinDctCoeffs.size() ;
std::map<SampleKey,unsigned long>* table = new std::map<SampleKey,unsigned long> () ;
for (unsigned long pos = 0 ; pos < n ; pos++) {
SampleValue *sv = (SampleValue*) new JpegSampleValue (LinDctCoeffs[pos]) ;
(*table)[sv->getKey()]++ ;
delete sv ;
}
return table ;
}
void JpegFile::printFrequencies (const std::map<SampleKey,unsigned long>& freqs)
{
std::list<std::string> output ;
// insert the positive dct coeffs into output list
for (std::map<SampleKey,unsigned long>::const_iterator pit = freqs.begin() ; pit->first < 2147483648UL /* 2^31 */ ; pit++) {
char buf[30] ;
sprintf (buf, "%ld: %lu", (long) pit->first, pit->second) ;
output.push_back (std::string(buf)) ;
}
// insert the negative dct coeffs into output list
for (std::map<SampleKey,unsigned long>::const_reverse_iterator nit = freqs.rbegin() ; nit->first > 2147483648UL /* 2^31 */ ; nit++) {
char buf[30] ;
sprintf (buf, "%ld: %lu", (long) nit->first, nit->second) ;
output.push_front (std::string(buf)) ;
}
for (std::list<std::string>::const_iterator it = output.begin() ; it != output.end() ; it++) {
std::cout << *it << std::endl ;
}
}
#endif // def DEBUG
#endif // def USE_LIBJPEG

92
steghide-src/JpegFile.h Normal file
View File

@ -0,0 +1,92 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_JPEGFILE_H
#define SH_JPEGFILE_H
#include "common.h"
#ifdef USE_LIBJPEG
#include <vector>
extern "C" {
#include <stdio.h>
#include <jpeglib.h>
}
class BinaryIO ;
#include "CvrStgFile.h"
class SampleValue ;
/**
* \class JpegFile
* \brief a cover-/stego-file in the jpeg file format
*
* This class uses the JPEG library by the IJG for access to jpeg files.
**/
class JpegFile : public CvrStgFile {
public:
JpegFile (BinaryIO* io) ;
~JpegFile (void) ;
void read (BinaryIO* io) ;
void write (void) ;
std::list<CvrStgFile::Property> getProperties (void) const ;
std::vector<MatchingAlgorithm*> getMatchingAlgorithms (Graph* g, Matching* m) const ;
unsigned long getNumSamples (void) const ;
void replaceSample (const SamplePos pos, const SampleValue* s) ;
SampleValue* getSampleValue (const SamplePos pos) const ;
EmbValue getEmbeddedValue (const SamplePos pos) const ;
#ifdef DEBUG
std::map<SampleKey,unsigned long>* getFrequencies (void) ;
/**
* SampleKey is unsigned, jpeg dct coefficients are signed data. This function is a specialization
* of printFrequencies that converts the SampleKeys back to dct coefficient values before printing
* them and also prints the values starting from the lowest (negative) and ending with the highest
* (positive).
**/
void printFrequencies (const std::map<SampleKey,unsigned long>& freqs) ;
#endif
private:
/// the number of dct coefficients per block
static const unsigned int CoeffPerBlock = 64 ;
static const unsigned short SamplesPerVertex = 3 ;
static const UWORD32 Radius = 1 ;
static const EmbValue EmbValueModulus = 2 ;
struct jpeg_compress_struct CInfo ;
struct jpeg_decompress_struct DeCInfo ;
unsigned int* HeightInBlocks ;
unsigned int* WidthInBlocks ;
jvirt_barray_ptr* DctCoeffs ;
std::vector<SWORD16> LinDctCoeffs ;
std::vector<UWORD32> StegoIndices ;
} ;
#endif // def USE_LIBJPEG
#endif // ndef SH_JPEGFILE_H

View File

@ -0,0 +1,98 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstdlib>
#include <cmath>
#include "common.h"
#include "JpegSampleValue.h"
JpegSampleValue::JpegSampleValue (int c)
: SampleValue(), DctCoeff (c)
{
Key = (UWORD32) DctCoeff ;
EValue = calcEValue (DctCoeff) ;
}
SampleValue *JpegSampleValue::getNearestTargetSampleValue (EmbValue t) const
{
SWORD16 minvalue = 0, maxvalue = 0 ;
if (DctCoeff > 0) {
minvalue = 1 ;
maxvalue = SWORD16_MAX ;
}
else if (DctCoeff < 0) {
minvalue = SWORD16_MIN ;
maxvalue = -1 ;
}
else {
myassert(false) ;
}
SWORD16 dctc_up = DctCoeff, dctc_down = DctCoeff, dctc_new = 0 ;
bool found = false ;
do {
if (dctc_up < maxvalue) {
dctc_up++ ;
}
if (dctc_down > minvalue) {
dctc_down-- ;
}
if (calcEValue(dctc_up) == t && calcEValue(dctc_down) == t) {
if (RndSrc.getBool()) {
dctc_new = dctc_up ;
}
else {
dctc_new = dctc_down ;
}
found = true ;
}
else if (calcEValue(dctc_up) == t) {
dctc_new = dctc_up ;
found = true ;
}
else if (calcEValue(dctc_down) == t) {
dctc_new = dctc_down ;
found = true ;
}
} while (!found) ;
return ((SampleValue *) new JpegSampleValue (dctc_new)) ;
}
UWORD32 JpegSampleValue::calcDistance (const SampleValue *s) const
{
const JpegSampleValue *sample = (const JpegSampleValue*) s ;
/* If s is not a JpegSampleValue then we get into real trouble here.
But calcDistance is called very often, a dynamic_cast costs a lot of time and
it does not make sense to pass anything but a JpegSampleValue as s anyway. */
int d = DctCoeff - sample->DctCoeff ;
return ((d >= 0) ? ((UWORD32) d) : ((UWORD32) -d)) ;
}
std::string JpegSampleValue::getName (void) const
{
char buf[128] ;
sprintf (buf, "%d", DctCoeff) ;
return std::string (buf) ;
}

View File

@ -0,0 +1,44 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_JPEGSAMPLE_H
#define SH_JPEGSAMPLE_H
#include "SampleValue.h"
class JpegSampleValue : public SampleValue {
public:
JpegSampleValue (int c) ;
SampleValue* getNearestTargetSampleValue (EmbValue t) const ;
UWORD32 calcDistance (const SampleValue *s) const ;
std::string getName (void) const ;
SWORD16 getDctCoeff (void) const
{ return DctCoeff ; } ;
static EmbValue calcEValue (SWORD16 dctc)
{ return (((dctc >= 0) ? dctc : -dctc) % 2) ; } ;
private:
SWORD16 DctCoeff ;
} ;
#endif // ndef SH_JPEGSAMPLE_H

327
steghide-src/MCryptPP.cc Normal file
View File

@ -0,0 +1,327 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "common.h"
#ifdef USE_LIBMCRYPT
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <string>
#include <mcrypt.h>
#include "BitString.h"
#include "EncryptionAlgorithm.h"
#include "EncryptionMode.h"
#include "MCryptPP.h"
#include "MHashKeyGen.h"
#include "error.h"
MCryptPP::MCryptPP ()
{
ModuleOpen = false ;
}
MCryptPP::MCryptPP (EncryptionAlgorithm a, EncryptionMode m)
{
open (a, m) ;
}
MCryptPP::~MCryptPP ()
{
if (ModuleOpen) {
close() ;
}
}
void MCryptPP::open (EncryptionAlgorithm a, EncryptionMode m)
{
std::string tmp1 = a.getStringRep(), tmp2 = m.getStringRep() ;
char algo[tmp1.size() + 1], mode[tmp2.size() + 1] ;
strcpy (algo, tmp1.c_str()) ;
strcpy (mode, tmp2.c_str()) ;
if ((MCryptD = mcrypt_module_open (algo, MCRYPTPP_LIBDIR, mode, MCRYPTPP_LIBDIR)) == MCRYPT_FAILED) {
throw SteghideError (_("could not open libmcrypt module \"%s\",\"%s\"."), algo, mode) ;
}
ModuleOpen = true ;
}
void MCryptPP::close ()
{
mcrypt_module_close (MCryptD) ;
ModuleOpen = false ;
}
BitString MCryptPP::encrypt (BitString p, std::string pp)
{
p.padRandom (8 * mcrypt_enc_get_block_size (MCryptD)) ; // blocksize is 1 for stream algorithms
std::vector<unsigned char> ciphertext = _encrypt (p.getBytes(), pp) ;
return BitString (ciphertext) ;
}
BitString MCryptPP::decrypt (BitString c, std::string pp)
{
myassert (c.getLength() % (8 * mcrypt_enc_get_block_size (MCryptD)) == 0) ;
std::vector<unsigned char> plaintext = _decrypt (c.getBytes(), pp) ;
return BitString (plaintext) ;
}
void* MCryptPP::createKey (std::string pp)
{
unsigned int keysize = mcrypt_enc_get_key_size (MCryptD) ;
MHashKeyGen keygen (KEYGEN_MCRYPT, MHASH_MD5, keysize) ;
std::vector<unsigned char> key = keygen.createKey (pp) ;
unsigned char *retval = (unsigned char *) s_malloc (keysize) ;
for (unsigned int i = 0 ; i < keysize ; i++) {
retval[i] = key[i] ;
}
return retval ;
}
std::vector<unsigned char> MCryptPP::_encrypt (std::vector<unsigned char> p, std::string pp)
{
// genereate key and IV (if needed)
void *key = createKey (pp) ;
unsigned char *IV = NULL ;
if (mcrypt_enc_mode_has_iv (MCryptD)) {
unsigned int ivsize = mcrypt_enc_get_iv_size (MCryptD) ;
std::vector<unsigned char> rndIV = RndSrc.getBytes (ivsize) ;
IV = (unsigned char *) s_malloc (ivsize) ;
for (unsigned int i = 0 ; i < ivsize ; i++) {
IV[i] = rndIV[i] ;
}
}
// initialize libmcrypt thread
unsigned int keysize = mcrypt_enc_get_key_size (MCryptD) ;
int err = -1 ;
if ((err = mcrypt_generic_init (MCryptD, key, keysize, IV)) < 0) {
mcrypt_perror (err) ;
throw SteghideError (_("could not initialize libmcrypt encryption. see above error messages if any.")) ;
}
// copy plaintext
unsigned int plntextlen = p.size() ;
myassert (plntextlen % mcrypt_enc_get_block_size (MCryptD) == 0) ;
unsigned char *plntext = (unsigned char *) s_malloc (plntextlen) ;
for (unsigned int i = 0 ; i < plntextlen ; i++) {
plntext[i] = p[i] ;
}
// encrypt plaintext
if (mcrypt_generic (MCryptD, plntext, plntextlen) != 0) {
throw SteghideError (_("could not encrypt data.")) ;
}
// create the return value
std::vector<unsigned char> retval ;
unsigned int i = 0 ;
if (mcrypt_enc_mode_has_iv (MCryptD)) {
unsigned int ivsize = mcrypt_enc_get_iv_size (MCryptD) ;
retval = std::vector<unsigned char> (ivsize + plntextlen) ;
for ( ; i < ivsize ; i++) {
retval[i] = IV[i] ;
}
}
else {
retval = std::vector<unsigned char> (plntextlen) ;
}
for (unsigned int j = 0 ; j < plntextlen ; i++, j++) {
retval[i] = plntext[j] ;
}
// clean up
if (mcrypt_generic_deinit (MCryptD) < 0) {
throw SteghideError (_("could not finish libmcrypt encryption.")) ;
}
free (plntext) ;
free (key) ;
if (mcrypt_enc_mode_has_iv (MCryptD)) {
free (IV) ;
}
return retval ;
}
std::vector<unsigned char> MCryptPP::_decrypt (std::vector<unsigned char> c, std::string pp)
{
// generate key
void *key = createKey (pp) ;
unsigned char *IV = NULL ;
unsigned int cstart = 0 ;
if (mcrypt_enc_mode_has_iv (MCryptD)) {
unsigned int ivsize = mcrypt_enc_get_iv_size (MCryptD) ;
IV = (unsigned char *) s_malloc (ivsize) ;
for (unsigned int i = 0 ; i < ivsize ; i++) {
IV[i] = c[i] ;
}
cstart = ivsize ;
}
// initialize libmcrypt thread
unsigned int keysize = mcrypt_enc_get_key_size (MCryptD) ;
int err = -1 ;
if ((err = mcrypt_generic_init (MCryptD, key, keysize, IV)) < 0) {
mcrypt_perror (err) ;
throw SteghideError (_("could not initialize libmcrypt decryption. see above error messages if any.")) ;
}
// copy ciphertext
unsigned long ciphertextlen = c.size() - cstart ;
myassert (ciphertextlen % mcrypt_enc_get_block_size (MCryptD) == 0) ;
unsigned char *ciphertext = (unsigned char *) s_malloc (ciphertextlen) ;
for (unsigned int i = 0 ; i < ciphertextlen ; i++) {
ciphertext[i] = c[cstart + i] ;
}
// decrypt ciphertext
if (mdecrypt_generic (MCryptD, ciphertext, ciphertextlen) != 0) {
throw SteghideError (_("could not decrypt data.")) ;
}
// create return value
std::vector<unsigned char> retval (ciphertextlen) ;
for (unsigned int i = 0 ; i < ciphertextlen ; i++) {
retval[i] = ciphertext[i] ;
}
// clean up
if (mcrypt_generic_deinit (MCryptD) < 0) {
throw SteghideError (_("could not finish libmcrypt decryption.")) ;
}
free (ciphertext) ;
free (key) ;
if (mcrypt_enc_mode_has_iv (MCryptD)) {
free (IV) ;
}
return retval ;
}
EncryptionAlgorithm MCryptPP::getAlgorithm () const
{
myassert (ModuleOpen) ;
char *name = mcrypt_enc_get_algorithms_name (MCryptD) ;
return EncryptionAlgorithm (name) ;
}
EncryptionMode MCryptPP::getMode () const
{
myassert (ModuleOpen) ;
char *name = mcrypt_enc_get_modes_name (MCryptD) ;
return EncryptionMode (name) ;
}
unsigned long MCryptPP::getEncryptedSize (EncryptionAlgorithm a, EncryptionMode m, unsigned long plnsize)
{
unsigned long retval = 0 ;
if (a.getIntegerRep() == EncryptionAlgorithm::NONE) {
retval = plnsize ;
}
else {
std::string tmp1 = a.getStringRep(), tmp2 = m.getStringRep() ;
char algo[tmp1.size() + 1], mode[tmp2.size() + 1] ;
strcpy (algo, tmp1.c_str()) ;
strcpy (mode, tmp2.c_str()) ;
MCRYPT td ;
if ((td = mcrypt_module_open (algo, MCRYPTPP_LIBDIR, mode, MCRYPTPP_LIBDIR)) == MCRYPT_FAILED) {
throw SteghideError (_("could not open libmcrypt module \"%s\",\"%s\"."), algo, mode) ;
}
if (mcrypt_enc_mode_has_iv (td)) {
retval += (8 * mcrypt_enc_get_iv_size(td)) ;
}
unsigned long blocks = 0 ;
const unsigned long blocksize = 8 * mcrypt_enc_get_block_size(td) ; // is 1 for stream algorithms
if (plnsize % blocksize == 0) {
blocks = plnsize / blocksize ;
}
else {
blocks = (plnsize / blocksize) + 1;
}
retval += (blocks * blocksize) ;
mcrypt_module_close (td) ;
}
return retval ;
}
std::vector<std::string> MCryptPP::getListAlgorithms ()
{
int size = 0 ;
char **list = mcrypt_list_algorithms (MCRYPTPP_LIBDIR, &size) ;
/**
* There is a bug in libmcrypt, at least in version 2.5.5 that has the
* effect that the algorithm list contains every algorithm twice.
**/
std::vector<std::string> retval ;
for (int i = 0 ; i < size ; i++) {
if ((i == 0) || (strcmp(list[i], list[i - 1]) != 0)) { // workaround for the bug mentioned above
retval.push_back (std::string (list[i])) ;
}
}
mcrypt_free_p (list, size) ;
return retval ;
}
std::vector<std::string> MCryptPP::getListModes ()
{
int size = 0 ;
char **list = mcrypt_list_modes (MCRYPTPP_LIBDIR, &size) ;
std::vector<std::string> retval ;
for (int i = 0 ; i < size ; i++) {
retval.push_back (std::string (list[i])) ;
}
mcrypt_free_p (list, size) ;
return retval ;
}
bool MCryptPP::AlgoSupportsMode (EncryptionAlgorithm a, EncryptionMode m)
{
std::string tmp1 = a.getStringRep(), tmp2 = m.getStringRep() ;
char algo[tmp1.size() + 1], mode[tmp2.size() + 1] ;
strcpy (algo, tmp1.c_str()) ;
strcpy (mode, tmp2.c_str()) ;
return (mcrypt_module_is_block_algorithm (algo, MCRYPTPP_LIBDIR) ==
mcrypt_module_is_block_algorithm_mode (mode, MCRYPTPP_LIBDIR)) ;
}
void *MCryptPP::s_malloc (size_t size)
{
void *retval = NULL ;
if ((retval = malloc (size)) == NULL) {
throw SteghideError (_("could not allocate memory.")) ;
}
return retval ;
}
#endif // def USE_LIBMCRYPT

127
steghide-src/MCryptPP.h Normal file
View File

@ -0,0 +1,127 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "common.h"
#ifdef USE_LIBMCRYPT
#ifndef SH_MCRYPTPP_H
#define SH_MCRYPTPP_H
#include <string>
#include <mcrypt.h>
class BitString ;
class EncryptionAlgorithm ;
class EncryptionMode ;
#ifdef WIN32
#define MCRYPTPP_LIBDIR "./modules/"
#else
#define MCRYPTPP_LIBDIR NULL
#endif
class MCryptPP {
public:
MCryptPP (void) ;
MCryptPP (EncryptionAlgorithm a, EncryptionMode m) ;
~MCryptPP (void) ;
/**
* open the libmcrypt module algo/mode
* \param a the encryption algorithm
* \param m the encryption mode (must be supported by the given encryption algorithm)
**/
void open (EncryptionAlgorithm a, EncryptionMode m) ;
/**
* close the opened libmcrypt module
**/
void close (void) ;
/**
* encrypt p using pp as passphrase
* \param p the plaintext to be encrypted
* \param pp the passphrase
* \return the encrypted data (with the IV as first block (if an IV is used by this mode))
**/
BitString encrypt (BitString p, std::string pp) ;
/**
* decrypt c using pp as passphrase
* \param c the ciphertext to be decrypted (with the IV as first block (if an IV is used by this mode))
* \param pp the passphrase
* \return the plain data data (without IV)
**/
BitString decrypt (BitString c, std::string pp) ;
EncryptionAlgorithm getAlgorithm (void) const ;
EncryptionMode getMode (void) const ;
/**
* get the size of an encryption result
* \param a the algorithm to be used for encryption
* \param m the mode to be used for encryption
* \param plnsize the size of the plaintext (in bits)
* \return the size the ciphertext would have (in bits and including the IV)
**/
static unsigned long getEncryptedSize (EncryptionAlgorithm a, EncryptionMode m, unsigned long plnsize) ;
static std::vector<std::string> getListModes (void) ;
static std::vector<std::string> getListAlgorithms (void) ;
static bool AlgoSupportsMode (EncryptionAlgorithm a, EncryptionMode m) ;
protected:
void *createKey (std::string pp) ;
/**
* do the actual encryption
* \param p the plaintext to be encrypted
* \param pp the passphrase
* \return the encrypted data (with the IV as first block (if an IV is used by this mode))
*
* The size of p must be a multiple of the blocksize of the encryption algorithm.
**/
std::vector<BYTE> _encrypt (std::vector<unsigned char> p, std::string pp) ;
/**
* do the actual decryption
* \param c the ciphertext to be decrypted (with the IV as first block (if an IV is used by this mode))
* \param pp the passphrase
* \return the decrypted data
*
* The size of c must be a multiple of the blocksize of the encryption algorithm.
**/
std::vector<BYTE> _decrypt (std::vector<unsigned char> c, std::string pp) ;
private:
/// true iff CryptD contains a valid encryption descriptor
bool ModuleOpen ;
MCRYPT MCryptD ;
void *s_malloc (size_t size) ;
} ;
#endif // ndef SH_MCRYPTPP_H
#endif // def USE_LIBMCRYPT

118
steghide-src/MHashKeyGen.cc Normal file
View File

@ -0,0 +1,118 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstring>
#include <cstdlib>
#include <vector>
#include "common.h"
#include "error.h"
#include "MHashKeyGen.h"
MHashKeyGen::MHashKeyGen ()
{
AlgorithmData.count = 0 ;
AlgorithmData.salt = NULL ;
AlgorithmData.salt_size = 0 ;
}
MHashKeyGen::MHashKeyGen (keygenid kgalgo, hashid halgo, unsigned int keysize)
{
setKeyGenAlgorithm (kgalgo) ;
setKeySize (keysize) ;
setHashAlgorithm (halgo) ;
AlgorithmData.count = 0 ;
AlgorithmData.salt = NULL ;
AlgorithmData.salt_size = 0 ;
}
MHashKeyGen::~MHashKeyGen ()
{
if (AlgorithmData.salt != NULL) {
free (AlgorithmData.salt) ;
}
}
std::vector<unsigned char> MHashKeyGen::createKey (std::string password)
{
char *passwd = (char *) s_malloc (password.size() + 1) ;
strcpy (passwd, password.c_str()) ;
int passwdlen = strlen (passwd) ;
unsigned char *key = (unsigned char *) s_malloc (KeySize) ;
if (mhash_keygen_ext (Algorithm, AlgorithmData, key, KeySize, (unsigned char *) passwd, passwdlen) < 0) {
throw SteghideError (_("could not generate key using libmhash.")) ;
}
std::vector<unsigned char> retval (KeySize) ;
for (unsigned int i = 0 ; i < KeySize ; i++) {
retval[i] = key[i] ;
}
free (passwd) ;
free (key) ;
return retval ;
}
void MHashKeyGen::setKeySize (unsigned int keysize)
{
KeySize = keysize ;
}
void MHashKeyGen::setKeyGenAlgorithm (keygenid algo)
{
Algorithm = algo ;
}
void MHashKeyGen::setHashAlgorithm (hashid hashalgo)
{
AlgorithmData.hash_algorithm[0] = hashalgo ;
}
void MHashKeyGen::setHashAlgorithms (std::vector<hashid> hashalgos)
{
myassert (hashalgos.size() <= 2) ;
for (unsigned int i = 0 ; i < hashalgos.size() ; i++) {
AlgorithmData.hash_algorithm[i] = hashalgos[i] ;
}
}
void MHashKeyGen::setSalt (std::vector<unsigned char> salt)
{
AlgorithmData.salt_size = salt.size() ;
if (AlgorithmData.salt != NULL) {
free (AlgorithmData.salt) ;
}
AlgorithmData.salt = s_malloc (AlgorithmData.salt_size) ;
unsigned char *tmp = (unsigned char *) AlgorithmData.salt ;
for (int i = 0 ; i < AlgorithmData.salt_size ; i++) {
tmp[i] = salt[i] ;
}
}
void *MHashKeyGen::s_malloc (size_t size)
{
void *retval = NULL ;
if ((retval = malloc (size)) == NULL) {
throw SteghideError (_("could not allocate memory.")) ;
}
return retval ;
}

View File

@ -0,0 +1,51 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_MHASHKEYGEN_H
#define SH_MHASHKEYGEN_H
#include <vector>
#include <mhash.h>
class MHashKeyGen {
public:
MHashKeyGen (void) ;
MHashKeyGen (keygenid kgalgo, hashid halgo, unsigned int keysize) ;
~MHashKeyGen (void) ;
void setKeySize (unsigned int KeySize) ;
void setKeyGenAlgorithm (keygenid algo) ;
void setHashAlgorithm (hashid hashalgo) ;
void setHashAlgorithms (std::vector<hashid> hashalgos) ;
void setSalt (std::vector<unsigned char> salt) ;
std::vector<unsigned char> createKey (std::string password) ;
private:
bool ready ;
keygenid Algorithm ;
KEYGEN AlgorithmData ;
unsigned int KeySize ;
void *s_malloc (size_t size) ;
} ;
#endif // ndef SH_MHASHKEYGEN_H

145
steghide-src/MHashPP.cc Normal file
View File

@ -0,0 +1,145 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cstdlib>
#include <string>
#include <mhash.h>
#include "BitString.h"
#include "common.h"
#include "error.h"
#include "MHashPP.h"
MHashPP::MHashPP ()
{
hashing = false ;
HashBytesValid = false ;
}
MHashPP::MHashPP (hashid id)
{
init (id) ;
}
void MHashPP::init (hashid id)
{
if ((HashD = mhash_init (id)) == MHASH_FAILED) {
throw SteghideError (_("could not initialize libmhash %s algorithm."), getAlgorithmName(id).c_str()) ;
}
hashing = true ;
HashBytesValid = false ;
}
const std::vector<BYTE>& MHashPP::end ()
{
myassert (hashing) ;
unsigned int n = getHashSize() ;
HashBytes = std::vector<BYTE> (n) ;
BYTE hash[n] ;
mhash_deinit (HashD, hash) ;
hashing = false ;
for (unsigned int i = 0 ; i < n ; i++) {
HashBytes[i] = hash[i] ;
}
HashBytesValid = true ;
return HashBytes ;
}
unsigned int MHashPP::getHashSize (void)
{
myassert (hashing) ;
return ((unsigned int) mhash_get_block_size (mhash_get_mhash_algo (HashD))) ;
}
MHashPP& MHashPP::operator<< (std::string v)
{
myassert (hashing) ;
mhash (HashD, v.data(), v.size()) ;
return *this ;
}
MHashPP& MHashPP::operator<< (BitString v)
{
myassert (hashing) ;
myassert (v.getLength() % 8 == 0) ;
unsigned long n = v.getLength() / 8 ;
for (unsigned int i = 0 ; i < n ; i++) {
(*this) << (BYTE) v.getValue (8 * i, 8) ;
}
return *this ;
}
MHashPP& MHashPP::operator<< (BYTE v)
{
myassert (hashing) ;
mhash (HashD, &v, 1) ;
return *this ;
}
MHashPP& MHashPP::operator<< (MHashPP::Command c)
{
switch (c) {
case endhash:
HashBytes = end() ;
break ;
default:
myassert (0) ;
break ;
}
return *this ;
}
std::string MHashPP::getAlgorithmName ()
{
myassert (hashing) ;
return getAlgorithmName (mhash_get_mhash_algo (HashD)) ;
}
std::string MHashPP::getAlgorithmName (hashid id)
{
char *name = (char *) mhash_get_hash_name (id) ;
std::string retval ;
if (name == NULL) {
retval = std::string ("<algorithm not found>") ;
}
else {
retval = std::string (name) ;
}
free (name) ;
return retval ;
}
BitString MHashPP::getHashBits ()
{
myassert (HashBytesValid) ;
return BitString (HashBytes) ;
}
const std::vector<BYTE>& MHashPP::getHashBytes()
{
myassert (HashBytesValid) ;
return HashBytes ;
}

92
steghide-src/MHashPP.h Normal file
View File

@ -0,0 +1,92 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_MHASHPP_H
#define SH_MHASHPP_H
#include <mhash.h>
#include "common.h"
class BitString ;
class MHashPP {
public:
enum Command { endhash } ;
MHashPP (void) ;
MHashPP (hashid a) ;
void init (hashid a) ;
const std::vector<BYTE>& end (void) ;
/**
* feed the std::string v to the hashing algorithm
* \param v the std::string to be feeded to the hashing algorithm (without '\0' at the end)
**/
MHashPP& operator<< (std::string v) ;
/**
* feed the BitString v to the hashing algorithm
* \param v the BitString to be feeded to the hashing algorithm (v.getLength() % 8 == 0 must hold)
**/
MHashPP& operator<< (BitString v) ;
/**
* feed the byte v to the hashing algorithm
* \param v the byte to be feeded to the hashing algorithm
**/
MHashPP& operator<< (BYTE v) ;
/**
* interpret the command c
* \param c a command (member of MHashPP::Command)
**/
MHashPP& operator<< (Command c) ;
/**
* get the hash bits
* \return the hash value of the data that has been passed via <<
**/
BitString getHashBits (void) ;
const std::vector<BYTE>& getHashBytes (void) ;
/**
* get the hash size
* \return the size of the value returned by getHashBits in bytes
**/
unsigned int getHashSize (void) ;
private:
/// true iff HashD contains a legal hash descriptor and data can be passed via <<
bool hashing ;
MHASH HashD ;
/// true iff HashBytes contains a valid hash value
bool HashBytesValid ;
std::vector<BYTE> HashBytes ;
std::string getAlgorithmName (void) ;
static std::string getAlgorithmName (hashid id) ;
} ;
#endif // ndef SH_MHASHPP_H

360
steghide-src/Matching.cc Normal file
View File

@ -0,0 +1,360 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "Edge.h"
#include "Graph.h"
#include "Matching.h"
#include "ProgressOutput.h"
#include "common.h"
#include "msg.h"
Matching::Matching (Graph* g, ProgressOutput* po)
: TheGraph(g), PrOut(po)
{
unsigned long nvertices = TheGraph->getNumVertices() ;
for (unsigned long i = 0 ; i < nvertices ; i++) {
ExposedVertices.push_back (TheGraph->getVertex (i)) ;
}
VertexInformation.reserve (nvertices) ;
for (std::list<Vertex*>::iterator i = ExposedVertices.begin() ; i != ExposedVertices.end() ; i++) {
VertexInformation.push_back (VertexInfo (i)) ;
}
Cardinality = 0 ;
}
Matching::~Matching ()
{
for (std::list<Edge*>::iterator edgeit = MatchingEdges.begin() ; edgeit != MatchingEdges.end() ; edgeit++) {
delete (*edgeit) ;
}
}
bool Matching::includesEdge (const Edge& e) const
{
Vertex* v1 = e.getVertex1() ;
Vertex* v2 = e.getVertex2() ;
bool v1ok = false, v2ok = false ;
if (VertexInformation[v1->getLabel()].isMatched()) {
if (*(VertexInformation[v1->getLabel()].getMatchingEdge()) == e) {
v1ok = true ;
}
}
if (VertexInformation[v2->getLabel()].isMatched()) {
if (*(VertexInformation[v2->getLabel()].getMatchingEdge()) == e) {
v2ok = true ;
}
}
return (v1ok && v2ok) ;
}
void Matching::addEdge (const Edge& e)
{
VertexLabel vlbl1 = e.getVertex1()->getLabel() ;
VertexLabel vlbl2 = e.getVertex2()->getLabel() ;
myassert (VertexInformation[vlbl1].isExposed()) ;
myassert (VertexInformation[vlbl2].isExposed()) ;
std::list<Edge*>::iterator edgeit = MatchingEdges.insert (MatchingEdges.end(), new Edge (e)) ;
ExposedVertices.erase (VertexInformation[vlbl1].getExposedIterator()) ;
ExposedVertices.erase (VertexInformation[vlbl2].getExposedIterator()) ;
VertexInformation[vlbl1].setMatched (edgeit) ;
VertexInformation[vlbl2].setMatched (edgeit) ;
setCardinality (Cardinality + 1) ;
}
void Matching::removeEdge (const Edge& e)
{
Vertex* v1 = e.getVertex1() ;
Vertex* v2 = e.getVertex2() ;
VertexLabel vlbl1 = v1->getLabel() ;
VertexLabel vlbl2 = v2->getLabel() ;
// assert: matching contains e
myassert (VertexInformation[vlbl1].isMatched()) ;
myassert (VertexInformation[vlbl2].isMatched()) ;
// delete e from MatchingEdges
std::list<Edge*>::iterator eit1 = VertexInformation[vlbl1].getMatchedIterator() ;
std::list<Edge*>::iterator eit2 = VertexInformation[vlbl2].getMatchedIterator() ;
myassert (eit1 == eit2) ;
delete (*eit1) ;
MatchingEdges.erase (eit1) ;
// add v1,v2 to ExposedVertices
std::list<Vertex*>::iterator expvit1 = ExposedVertices.insert (ExposedVertices.end(), v1) ;
VertexInformation[vlbl1].setExposed (expvit1) ;
std::list<Vertex*>::iterator expvit2 = ExposedVertices.insert (ExposedVertices.end(), v2) ;
VertexInformation[vlbl2].setExposed (expvit2) ;
setCardinality (Cardinality - 1) ;
}
Matching& Matching::augment (const Edge** path, unsigned long len)
{
// TODO - rewrite this to use structure like: while (+--+==+ -> +==+--+); +--+ -> +==+ where == is matched edge
myassert (len % 2 == 1) ;
bool e_was_matched = false ;
Edge *e = NULL ;
Edge *e_before = NULL ;
for (unsigned int i = 0 ; i < len ; i++) {
// give e the correct orientation (using pointer equivalence of vertices(!))
e = new Edge (*(path[i])) ;
if (e_before == NULL) {
if (len > 1) {
// e is the first, but not the only edge in path
if ((e->getVertex1() == path[1]->getVertex1()) || (e->getVertex1() == path[1]->getVertex2())) {
e->swap() ;
}
}
}
else {
if (e->getVertex1() != e_before->getVertex2()) {
e->swap() ;
}
myassert (e->getVertex1() == e_before->getVertex2()) ;
}
// make changes in VertexInformation, ExposedVertices and MatchingEdges
if (e_was_matched) { // at the time this is called, v1 is matched with "v0"
Vertex *v2 = e->getVertex2() ;
VertexLabel v2lbl = v2->getLabel() ;
// remove old edge from matching
delete (*(VertexInformation[v2lbl].getMatchedIterator())) ;
MatchingEdges.erase (VertexInformation[v2lbl].getMatchedIterator()) ;
// v2 is exposed now (for one iteration)
std::list<Vertex*>::iterator expvit2 = ExposedVertices.insert (ExposedVertices.end(), v2) ;
VertexInformation[v2lbl].setExposed (expvit2) ;
}
else {
Vertex *v1 = e->getVertex1() ;
Vertex *v2 = e->getVertex2() ;
VertexLabel v1lbl = v1->getLabel() ;
VertexLabel v2lbl = v2->getLabel() ;
// v1 is no longer exposed
ExposedVertices.erase (VertexInformation[v1lbl].getExposedIterator()) ;
// add new edge to matching
std::list<Edge*>::iterator edgeit = MatchingEdges.insert (MatchingEdges.end(), e) ;
VertexInformation[v1lbl].setMatched (edgeit) ;
VertexInformation[v2lbl].setMatched (edgeit) ;
}
e_was_matched = !e_was_matched ;
e_before = e ;
}
ExposedVertices.erase (VertexInformation[e->getVertex2()->getLabel()].getExposedIterator()) ;
VertexInformation[e->getVertex2()->getLabel()].setMatched (find (MatchingEdges.begin(), MatchingEdges.end(), e)) ;
setCardinality (Cardinality + 1) ;
return *this ;
}
Matching& Matching::augment (const std::vector<Edge*>& path)
{
unsigned long len = path.size() ;
const Edge** p = new const Edge*[len] ;
for (unsigned long i = 0 ; i < len ; i++) {
p[i] = path[i] ;
}
return augment (p, len) ;
}
void Matching::printVerboseInfo (void) const
{
// only used for STATS output
if (Args.Verbosity.getValue() == STATS) {
float sumweights = 0 ;
for (std::list<Edge*>::const_iterator it = MatchingEdges.begin() ; it != MatchingEdges.end() ; it++) {
sumweights += (*it)->getWeight() ;
}
printf ("%.4f:%.1f:",
1.0 - (((float) (getCardinality() * 2)) / ((float) TheGraph->getNumVertices())), // percentage of unmatched vertices
((float) sumweights / (float) getCardinality()) // average edge weight
) ;
}
}
float Matching::getMatchedRate (void) const
{
return (((float) (2 * Cardinality)) / ((float) TheGraph->getNumVertices())) ;
}
float Matching::getAvgEdgeWeight (void) const
{
float sumweights = 0 ;
for (std::list<Edge*>::const_iterator it = MatchingEdges.begin() ; it != MatchingEdges.end() ; it++) {
sumweights += (*it)->getWeight() ;
}
return (sumweights / (float) getCardinality()) ;
}
void Matching::setCardinality (unsigned long c)
{
Cardinality = c ;
if (PrOut) {
PrOut->update (getMatchedRate()) ;
}
}
bool Matching::check () const
{
bool retval = true ;
retval = check_MatchingEdges_vs_VertexInformation() && retval ;
retval = check_ExposedVertices_vs_VertexInformation() && retval ;
retval = check_VertexInformation_Integrity() && retval ;
return retval ;
}
bool Matching::check_MatchingEdges_vs_VertexInformation () const
{
bool err = false ;
// for every e = (v1,v2) in MatchingEdges: isMatched(v1) && isMatched(v2)
for (std::list<Edge*>::const_iterator it = MatchingEdges.begin() ; it != MatchingEdges.end() ; it++) {
Vertex *v1 = (*it)->getVertex1() ;
Vertex *v2 = (*it)->getVertex2() ;
if (VertexInformation[v1->getLabel()].isExposed() || VertexInformation[v2->getLabel()].isExposed()) {
err = true ;
break ;
}
}
if (err) {
std::cerr << "FAILED: There is an edge in MatchingEdges that is adjacent to a vertex marked as exposed." << std::endl ;
}
return !err ;
}
bool Matching::check_ExposedVertices_vs_VertexInformation () const
{
bool err = false ;
// for every exposed vertex v: isExposed(v)
for (std::list<Vertex*>::const_iterator it = ExposedVertices.begin() ; it != ExposedVertices.end() ; it++) {
if (VertexInformation[(*it)->getLabel()].isMatched()) {
err = true ;
break ;
}
}
if (err) {
std::cerr << "FAILED: There is a vertex in ExposedVertices that is marked matched." << std::endl ;
}
return !err ;
}
bool Matching::check_VertexInformation_Integrity () const
{
bool err_matched = false ;
for (unsigned long vlbl = 0 ; vlbl < VertexInformation.size() ; vlbl++) {
if (VertexInformation[vlbl].isMatched()) {
Edge* e = *(VertexInformation[vlbl].getMatchedIterator()) ;
if ((e->getVertex1()->getLabel() != vlbl) && (e->getVertex2()->getLabel() != vlbl)) {
if (vlbl == 16) { std::cerr << "FAILED, printing edge:" << std::endl ; e->print() ; }
err_matched = true ;
break ;
}
}
}
if (err_matched) {
std::cerr << "FAILED: There is a shortest edge that is not adjacent to its vertex." << std::endl ;
}
return !err_matched ;
}
bool Matching::check_ValidAugPath (const std::vector<Edge*>& path) const
{
// check cohesion
bool cohesion = true ;
std::vector<Vertex*> vertices ;
Vertex* lastvertex = NULL ;
if (path[1]->contains (path[0]->getVertex1())) {
vertices.push_back (path[0]->getVertex2()) ;
vertices.push_back (path[0]->getVertex1()) ;
lastvertex = path[0]->getVertex1() ;
}
else if (path[1]->contains (path[0]->getVertex2())) {
vertices.push_back (path[0]->getVertex1()) ;
vertices.push_back (path[0]->getVertex2()) ;
lastvertex = path[0]->getVertex2() ;
}
else {
cohesion = false ;
}
std::vector<Edge*>::const_iterator it = path.begin() ;
for (it++ ; it != path.end() ; it++) {
if ((*it)->getVertex1() == lastvertex) {
vertices.push_back ((*it)->getVertex2()) ;
lastvertex = (*it)->getVertex2() ;
}
else if ((*it)->getVertex2() == lastvertex) {
vertices.push_back ((*it)->getVertex1()) ;
lastvertex = (*it)->getVertex1() ;
}
else {
cohesion = false ;
}
}
myassert (vertices.size() - 1 == path.size()) ;
// check that path has no loop
bool hasloop = false ;
unsigned long nvertices = vertices.size() ;
for (unsigned long i = 0 ; i < nvertices ; i++) {
for (unsigned long j = i + 1 ; j < nvertices ; j++) {
if (vertices[i] == vertices[j]) {
hasloop = true ;
}
}
}
// check that path is augmenting w.r.t. the matching
bool isaugmenting = true ;
bool shouldinclude = false ;
for (std::vector<Edge*>::const_iterator it = path.begin() ; it != path.end() ; it++) {
if (shouldinclude) {
isaugmenting = includesEdge(*it) && isaugmenting ;
}
else {
isaugmenting = !includesEdge(*it) && isaugmenting ;
}
shouldinclude = !shouldinclude ;
}
return cohesion && !hasloop && isaugmenting ;
}

234
steghide-src/Matching.h Normal file
View File

@ -0,0 +1,234 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_MATCHING_H
#define SH_MATCHING_H
#include <list>
#include <vector>
#include "Vertex.h"
#include "common.h"
class Edge ;
class ProgressOutput ;
/**
* \class Matching
* \brief represent a matching on a graph
*
* A Matching object will copy all Edges that are passed to it and will take care of them, i.e.
* delete them if they are no longer used. Edges do only "leave" a Matching object as const
* pointers.
**/
class Matching {
public:
/**
* create an empty matching that is ready for adding and augmenting
* \param g the underlying graph
* \param po a ProgressOutput object that will print the number of matched vertices (in percent)
**/
Matching (Graph* g, ProgressOutput* po = NULL) ;
~Matching (void) ;
/**
* returns true iff the vertex v is matched in this matching.
**/
bool isMatched (Vertex *v) const
{ return VertexInformation[v->getLabel()].isMatched() ; } ;
/**
* returns true iff the vertex with the label vlbl is matched in this matching.
**/
bool isMatched (VertexLabel vlbl) const
{ return VertexInformation[vlbl].isMatched() ; } ;
/**
* returns true iff the vertex v is exposed (not matched) in this matching.
**/
bool isExposed (Vertex *v) const
{ return VertexInformation[v->getLabel()].isExposed() ; } ;
/**
* returns true iff the vertex with the label vlbl is exposed (not matched) in this matching.
**/
bool isExposed (VertexLabel vlbl) const
{ return VertexInformation[vlbl].isExposed() ; } ;
/**
* get the edge that is in the matching and adjacent to v
* \return the matched edge or NULL if v is exposed
**/
const Edge* getMatchingEdge (Vertex *v) const
{ return VertexInformation[v->getLabel()].getMatchingEdge() ; } ;
/**
* does this matching include the edge e ?
* \return true iff the edge e is element of this matching
**/
bool includesEdge (const Edge* e) const { return includesEdge(*e) ; } ;
bool includesEdge (const Edge& e) const ;
/**
* get the cardinality (the number of matched edges)
**/
unsigned long getCardinality (void) const
{ return Cardinality ; } ;
const std::list<Vertex*>& getExposedVertices (void) const
{ return ExposedVertices ; } ;
/**
* get the rate of vertices of the underlying graph that are currently matched in this matching
* \return a value between 0 and 1
**/
float getMatchedRate (void) const ;
/**
* get the average weight of all edges that are in this matching
**/
float getAvgEdgeWeight (void) const ;
/**
* get access to the std::list of exposed vertices
* \return a pointer to the std::list of exposed vertices in this matching.
*
* The std::list that is pointed to by return value contains the exposed vertices
* even after augment has been called (it is the ExposedVertices member) an
* arbitrary number of times.
**/
const std::list<Vertex*> *getExposedVerticesLink (void) const
{ return &ExposedVertices ; } ;
/**
* add an edge to the matching
* \param e the edge to add.
*
* For e=(v1,v2): neither v1 nor v2 are allowed to be adjacent
* to an edge that is already in the matching,
**/
void addEdge (const Edge& e) ;
void addEdge (Edge* e) { addEdge(*e) ; } ;
/**
* remove an edge from the matching
* \param e the edge to remove
*
* The edge e _must_ be in this matching
**/
void removeEdge (const Edge& e) ;
/**
* get the list of all edges in this matching
**/
const std::list<Edge*>& getEdges (void) const
{ return MatchingEdges ; } ;
/**
* augment this matching along the given augmenting path
* \param path an augmenting path
* \param len the length (number of edges) of the augmenting path
*
* An augementing path is a path where edges with odd indices (the first, third,...) are not
* in the matching and edges with even indices are and the path has
* an odd length.
**/
Matching& augment (const Edge** path, unsigned long len) ;
Matching& augment (const std::vector<Edge*>& path) ;
void printVerboseInfo (void) const ;
private:
/**
* \class VertexInfo
* \brief contains information about a vertex that is possibly in a matching
**/
class VertexInfo {
public:
VertexInfo (std::list<Edge*>::iterator mit)
{ setMatched (mit) ; } ;
VertexInfo (std::list<Vertex*>::iterator eit)
{ setExposed (eit) ; } ;
bool isExposed (void) const
{ return !Matched ; } ;
bool isMatched (void) const
{ return Matched ; } ;
Edge *getMatchingEdge (void) const
{ return *MatchedIterator ; } ;
std::list<Edge*>::iterator getMatchedIterator (void) const
{ return MatchedIterator ; } ;
std::list<Vertex*>::iterator getExposedIterator (void) const
{ return ExposedIterator ; } ;
void setMatched (std::list<Edge*>::iterator mit)
{ Matched = true ; MatchedIterator = mit ; } ;
void setExposed (std::list<Vertex*>::iterator eit)
{ Matched = false ; ExposedIterator = eit ; } ;
private:
bool Matched ;
/// an iterator into the list of matched edges (only valid if this vertex is matched)
std::list<Edge*>::iterator MatchedIterator ;
/// an iterator into the list of exposed vertices (only valid if this vertex is exposed)
std::list<Vertex*>::iterator ExposedIterator ;
} ;
/// contains a VertexInfo object for every vertex
std::vector<VertexInfo> VertexInformation ;
/// the std::list of all exposed vertices
std::list<Vertex*> ExposedVertices ;
/// the std::list of all edges in the matching
std::list<Edge*> MatchingEdges ;
/// the number of edges in the matching
unsigned long Cardinality ;
/// the graph underlying this Matching
Graph* TheGraph ;
/// the ProgressOutput object that will print the number of matched vertices (as percentage)
ProgressOutput* PrOut ;
/**
* set the cardinality (thereby updating PrOut)
**/
void setCardinality (unsigned long c) ;
public:
bool check (void) const ;
bool check_MatchingEdges_vs_VertexInformation (void) const ;
bool check_ExposedVertices_vs_VertexInformation (void) const ;
bool check_VertexInformation_Integrity (void) const ;
bool check_ValidAugPath (const std::vector<Edge*>& path) const ;
} ;
#endif // ndef SH_MATCHING_H

View File

@ -0,0 +1,35 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "Graph.h"
#include "MatchingAlgorithm.h"
MatchingAlgorithm::MatchingAlgorithm (Graph* g, Matching* m, float goal)
: TheGraph(g), TheMatching(m)
{
setGoal(goal) ;
}
void MatchingAlgorithm::setGoal (float goal)
{
// if goal is 100.0 and the graph has an odd number of vertices the algorithm won't spend time
// searching an edge for the last vertex as / rounds down to the next smaller integer
CardinalityGoal = (unsigned long) (((float) TheGraph->getNumVertices()) * (goal / 100.0)) / 2 ;
}

View File

@ -0,0 +1,47 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_MATCHINGALGORITHM_H
#define SH_MATCHINGALGORITHM_H
class Graph ;
class Matching ;
class MatchingAlgorithm {
public:
MatchingAlgorithm (Graph* g, Matching* m, float goal) ;
virtual ~MatchingAlgorithm (void) {} ;
virtual void run (void) = 0 ;
Matching* getMatching (void) const
{ return TheMatching ; } ;
void setGoal (float goal) ;
virtual const char* getName (void) const = 0 ;
protected:
Graph* TheGraph ;
Matching* TheMatching ;
unsigned long CardinalityGoal ;
} ;
#endif // ndef SH_MATCHINGALGORITHM

View File

@ -0,0 +1,80 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <cmath>
#include "ProgressOutput.h"
#include "common.h"
ProgressOutput::ProgressOutput ()
: Message("__nomessage__")
{
LastUpdate = time(NULL) - 1 ; // -1 to ensure that message is written first time
}
ProgressOutput::ProgressOutput (const std::string& m)
: Message(m)
{
LastUpdate = time(NULL) - 1 ; // -1 to ensure that message is written first time
}
void ProgressOutput::setMessage (const char *msgfmt, ...)
{
va_list ap ;
va_start (ap, msgfmt) ;
setMessage (vcompose (msgfmt, ap)) ;
va_end (ap) ;
}
std::string ProgressOutput::vcompose (const char *msgfmt, va_list ap) const
{
char *str = new char[200] ;
vsnprintf (str, 200, msgfmt, ap) ;
std::string retval (str) ;
delete[] str ;
return retval ;
}
void ProgressOutput::update (float rate)
{
time_t now = time(NULL) ;
if (LastUpdate < now) {
LastUpdate = now ;
printf ("\r%s %.1f%%", Message.c_str(), 100.0 * rate) ;
fflush (stdout) ;
}
}
void ProgressOutput::done (float rate, float avgweight) const
{
printf ("\r%s %.1f%%", Message.c_str(), 100.0 * rate) ;
if (avgweight != NoAvgWeight) {
printf (" (%.1f)", avgweight) ;
}
printf (_(" done")) ;
printf (" \n") ; // be sure to overwrite old line (even in a language with one-letter done)
fflush (stdout) ;
}
void ProgressOutput::done () const
{
printf ("\r%s", Message.c_str()) ;
printf (_(" done\n")) ;
}

View File

@ -0,0 +1,77 @@
/*
* steghide 0.5.1 - a steganography program
* Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef SH_PROGRESSOUTPUT_H
#define SH_PROGRESSOUTPUT_H
#include <cstdarg>
#include <ctime>
#include <string>
/**
* \class ProgressOutput
* \brief prints the progress to stdout
**/
class ProgressOutput {
public:
/**
* create an empty ProgressOutput object
**/
ProgressOutput (void) ;
/**
* create a ProgressOutput object
* \param m the message to be displayed
**/
ProgressOutput (const std::string& m) ;
void setMessage (const std::string& m)
{ Message = m ; } ;
void setMessage (const char *msgfmt, ...) ;
/**
* update the output (taking update frequency into account) with rate as percentage
**/
void update (float rate) ;
/**
* update the output appending "done" and a newline (no rate nor average weight)
**/
void done (void) const ;
/**
* update the output appending rate, [average edge weight], "done" and a newline
* \param rate the rate of matched vertices
* \param avgweight the average edge weight (is not printed if not given)
**/
void done (float rate, float avgweight = NoAvgWeight) const ;
static const float NoAvgWeight = -1.0 ;
protected:
std::string vcompose (const char *msgfmt, va_list ap) const ;
private:
std::string Message ;
time_t LastUpdate ;
} ;
#endif // ndef SH_PROGRESSOUTPUT_H

Some files were not shown because too many files have changed in this diff Show More