steghide
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -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
|
||||
}
|
|
@ -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" );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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 */
|
|
@ -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 ;
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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()) ;
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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 ; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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) ;
|
||||
}
|
|
@ -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
|
|
@ -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) ;
|
||||
}
|
|
@ -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
|
|
@ -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) ;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
|
@ -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
|
|
@ -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) ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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" }
|
||||
} ;
|
|
@ -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
|
|
@ -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" }
|
||||
} ;
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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) ;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
|
@ -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")) ;
|
||||
}
|
|
@ -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
|