pax_global_header00006660000000000000000000000064122121454630014512gustar00rootroot0000000000000052 comment=fe6338bd8ec0d9ff2148a134fabab5a0423a0b90 unshield-1.0/000077500000000000000000000000001221214546300131655ustar00rootroot00000000000000unshield-1.0/.gitignore000066400000000000000000000005141221214546300151550ustar00rootroot00000000000000aclocal.m4 autom4te.cache/ config.guess config.log config.status config.sub configure configure.ac depcomp .deps/ install-sh *.la .libs lib/stamp-h1 libtool lib/unshield_config.h lib/unshield_config.h.in libunshield.pc *.lo ltmain.sh Makefile Makefile.in missing *.o src/unshield src/unshield-deobfuscate *.core .*.swp .gdb_history unshield-1.0/.travis.yml000066400000000000000000000000571221214546300153000ustar00rootroot00000000000000language: c compiler: gcc script: ./rebuild.sh unshield-1.0/ChangeLog000066400000000000000000000013311221214546300147350ustar00rootroot000000000000002009-07-16 Mark Ellis * 0.6 release 2009-06-18 Mark Ellis * src/unshield.c - fix use of -L (lowercase) option with -d 2008-05-06 Jonny Lamb * .cvsignore: * cvsclean: * lib/.cvsignore: * lib/md5/.cvsignore: * src/.cvsignore: Removed useless CVS ignore and clean files. * bootstrap: * unshield.spec.in: Removed spec file. 2008-05-06 Jonny Lamb * VERSION: Upped version number to 0.5.1. 2008-02-15 Mark Ellis * added man page for unshield 2008-01-09 Mark Ellis * started changelog * added LICENSE to EXTRA_DIST * added cabfile.h to libunshield_la_SOURCES unshield-1.0/LICENSE000066400000000000000000000021031221214546300141660ustar00rootroot00000000000000Copyright (c) 2003 David Eriksson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. unshield-1.0/Makefile.am000066400000000000000000000005731221214546300152260ustar00rootroot00000000000000## Makefile.am -- Process this file with automake to produce Makefile.in @SET_MAKE@ ## don't complain about missing AUTHORS, NEWS, ChangeLog, etc AUTOMAKE_OPTIONS = foreign 1.4 pcfiles = libunshield.pc all_local: $(pcfiles) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(pcfiles) EXTRA_DIST = libunshield.pc.in LICENSE CLEANFILES = $(pcfiles) SUBDIRS = lib src man unshield-1.0/README000066400000000000000000000047151221214546300140540ustar00rootroot00000000000000vim: tw=65 wrap CONTENTS ======== Dictionary About Unshield License DICTIONARY ========== InstallShield (IS): see www.installshield.com InstallShield Cabinet File (ISCF): A .cab file used by IS. Microsoft Cabinet File (MSCF): A .cab file used by Microsoft. ABOUT UNSHIELD ============== To install a Pocket PC application remotely, an installable Microsoft Cabinet File is copied to the /Windows/AppMgr/Install directory on the PDA and then the wceload.exe is executed to perform the actual install. That is a very simple procedure. Unfortunately, many applications for Pocket PC are distributed as InstallShield installers for Microsoft Windows, and not as individual Microsoft Cabinet Files. That is very impractical for users of other operating systems, such as Linux or FreeBSD. An installer created by the InstallShield software stores the files it will install inside of InstallShield Cabinet Files. It would thus be desirable to be able to extract the Microsoft Cabinet Files from the InstallShield Cabinet Files in order to be able to install the applications without access to Microsoft Windows. The format of InstallShield Cabinet Files is not officially documented but there are two tools available for Microsoft Windows that extracts files from InstallShield installers, and they are distributed with source code included. These tools are named "i5comp" and "i6comp" and can be downloaded from the Internet. One major drawback with these tools are that for the actual decompression of the files stored in the InstallShield Cabinet Files they require the use of code written by InstallShield that is not available as source code. Luckily, by examining this code with the 'strings' tool, I discovered that they were using the open source zlib library (www.gzip.org/zlib) for decompression. I could have modified i5comp and i6comp to run on other operating systems than Microsoft Windows, but I preferred to use them as a reference for this implementation. The goals of this implementation are: - Use a well known open source license (MIT) - Work on both little-endian and big-endian systems - Separate the implementation in a tool and a library - Support InstallShield versions 5 and later - Be able to list contents of InstallShield Cabinet Files - Be able to extract files from InstallShield Cabinet Files LICENSE ======= Unshield uses the MIT license. The short version is "do as you like, but don't blame me if anything goes wrong". See the file LICENSE for details. unshield-1.0/TODO000066400000000000000000000001101221214546300136450ustar00rootroot00000000000000$Id$ TODO for Unshield ================= - Support "encrypted" files unshield-1.0/VERSION000066400000000000000000000000041221214546300142270ustar00rootroot000000000000001.0 unshield-1.0/bootstrap000077500000000000000000000013051221214546300151270ustar00rootroot00000000000000#!/bin/sh set -e VERSION=`cat VERSION` if [ -z "$VERSION" ]; then echo "Empty version" exit 1 fi # create configure.ac with correct version number ACFILE="configure.ac" ACFILE_IN="$ACFILE.in" if [ -f $ACFILE ]; then rm $ACFILE fi echo -n "Creating $ACFILE..." cat $ACFILE_IN | sed "s/\\(AC_INIT(.*,\\).*)/\\1 $VERSION)/" > $ACFILE if [ -s $ACFILE ]; then echo "done." else exit 1 fi rm -f config.cache if [ -d "m4" ]; then INCLUDES="-I m4" fi set -x aclocal $INCLUDES autoheader # Check For OSX # rhcp011235@gmail.com KERNEL_NAME=`uname -s` if [ "$KERNEL_NAME" = "Darwin" ]; then glibtoolize --copy --automake else libtoolize --copy --automake fi automake --copy --foreign --add-missing autoconf unshield-1.0/config.rpath000077500000000000000000000334341221214546300155040ustar00rootroot00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2002 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # 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. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a shlibext= host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix3* | aix4* | aix5*) wl='-Wl,' ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6*) wl='-Wl,' ;; linux*) echo '__INTEL_COMPILER' > conftest.$ac_ext if $CC -E conftest.$ac_ext >/dev/null | grep __INTEL_COMPILER >/dev/null then : else # Intel icc wl='-Qoption,ld,' fi ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) if test "x$host_vendor" = xsni; then wl='-LD' else wl='-Wl,' fi ;; esac fi hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then case "$host_os" in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken ld_shlibs=no ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac fi if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=yes ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9* | hpux10* | hpux11*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. ;; irix5* | irix6*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) if test "x$host_vendor" = xsno; then hardcode_direct=yes # is this really true??? else hardcode_direct=no # Motorola manual says yes, but my tests say they lie fi ;; sysv4.3*) ;; sysv5*) hardcode_libdir_flag_spec= ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4.2uw2*) hardcode_direct=yes hardcode_minus_L=no ;; sysv5uw7* | unixware7*) ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics libname_spec='lib$name' sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" case "$host_os" in aix3*) shlibext=so ;; aix4* | aix5*) shlibext=so ;; amigaos*) shlibext=ixlibrary ;; beos*) shlibext=so ;; bsdi4*) shlibext=so sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" ;; cygwin* | mingw* | pw32*) case $GCC,$host_os in yes,cygwin*) shlibext=dll.a ;; yes,mingw*) shlibext=dll sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` ;; yes,pw32*) shlibext=dll ;; *) shlibext=dll ;; esac ;; darwin* | rhapsody*) shlibext=dylib ;; freebsd1*) ;; freebsd*) shlibext=so ;; gnu*) shlibext=so ;; hpux9* | hpux10* | hpux11*) shlibext=sl ;; irix5* | irix6*) shlibext=so case "$host_os" in irix5*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 ") libsuff= shlibsuff= ;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) ;; linux-gnu*) shlibext=so ;; netbsd*) shlibext=so ;; newsos6) shlibext=so ;; openbsd*) shlibext=so ;; os2*) libname_spec='$name' shlibext=dll ;; osf3* | osf4* | osf5*) shlibext=so sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) shlibext=so ;; solaris*) shlibext=so ;; sunos4*) shlibext=so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) shlibext=so case "$host_vendor" in motorola) sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) shlibext=so ;; dgux*) shlibext=so ;; sysv4*MP*) if test -d /usr/nec; then shlibext=so fi ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_sys_lib_search_path_spec=`echo "X$sys_lib_search_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_sys_lib_dlsearch_path_spec=`echo "X$sys_lib_dlsearch_path_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <], [size_t value = 0; printf("%zi", value);], [SIZE_FORMAT="zi"], [AC_TRY_COMPILE([#include ], [size_t value = 0; printf("%i", value);], [SIZE_FORMAT="i"], [AC_TRY_COMPILE([#include ], [size_t value = 0; printf("%li", value);], [SIZE_FORMAT="li"], [AC_MSG_RESULT([Failed!]) AC_MSG_ERROR([You must be using a really weird platform!])]) ]) ]) AC_MSG_RESULT([${SIZE_FORMAT}]) AC_DEFINE_UNQUOTED(SIZE_FORMAT, ["${SIZE_FORMAT}"], [printf format that works with size_t values]) CFLAGS="$SAVED_CFLAGS" # http://www.gnu.org/manual/autoconf-2.53/html_node/AC_LIBOBJ-vs.-LIBOBJS.html # This is necessary so that .o files in LIBOBJS are also built via # the ANSI2KNR-filtering rules. LIB@&t@OBJS=`echo "$LIB@&t@OBJS" | sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'` LTLIBOBJS=`echo "$LIB@&t@OBJS" | sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'` AC_SUBST(LTLIBOBJS) CHECK_ZLIB() CHECK_SSL() if test x$HAVE_SSL = xyes; then USE_OUR_OWN_MD5=0 else USE_OUR_OWN_MD5=1 fi AC_DEFINE_UNQUOTED([USE_OUR_OWN_MD5], [$USE_OUR_OWN_MD5], [Defined if we should use our own MD5 routines.]) AM_CONDITIONAL(USE_OUR_OWN_MD5, [test x$HAVE_SSL != xyes]) AC_FUNC_FNMATCH AC_OUTPUT([libunshield.pc Makefile man/Makefile lib/convert_utf/Makefile lib/md5/Makefile lib/Makefile src/Makefile]) unshield-1.0/lib/000077500000000000000000000000001221214546300137335ustar00rootroot00000000000000unshield-1.0/lib/Makefile.am000066400000000000000000000011141221214546300157640ustar00rootroot00000000000000if USE_OUR_OWN_MD5 MD5_SUBDIR = md5 MD5_LIBS = md5/libmd5.la else MD5_SUBDIR = MD5_LIBS = endif ## useful flags AM_CPPFLAGS = -I.. ## create this library lib_LTLIBRARIES = libunshield.la ## use these sources libunshield_la_SOURCES = \ bswap.c \ component.c \ directory.c \ file.c \ file_group.c \ helper.c \ internal.h \ libunshield.h libunshield.c \ log.h log.c \ cabfile.h libunshield_la_LDFLAGS = -no-undefined -version-info 0:0:0 libunshield_la_LIBADD = convert_utf/libconvert_utf.la $(MD5_LIBS) include_HEADERS = libunshield.h SUBDIRS = convert_utf $(MD5_SUBDIR) . unshield-1.0/lib/bswap.c000066400000000000000000000006041221214546300152130ustar00rootroot00000000000000/* $Id$ */ #include "internal.h" #if IMPLEMENT_BSWAP_XX /* * Written by Manuel Bouyer . * Public domain. */ uint16_t bswap_16(uint16_t x) { return ((x << 8) & 0xff00) | ((x >> 8) & 0x00ff); } uint32_t bswap_32(uint32_t x) { return ((x << 24) & 0xff000000 ) | ((x << 8) & 0x00ff0000 ) | ((x >> 8) & 0x0000ff00 ) | ((x >> 24) & 0x000000ff ); } #endif unshield-1.0/lib/cabfile.h000066400000000000000000000042401221214546300154710ustar00rootroot00000000000000/* $Id$ */ #ifndef __cabfile_h__ #define __cabfile_h__ #include "internal.h" #define OFFSET_COUNT 0x47 #define CAB_SIGNATURE 0x28635349 #define MSCF_SIGNATURE 0x4643534d #define COMMON_HEADER_SIZE 20 #define VOLUME_HEADER_SIZE_V5 40 #define VOLUME_HEADER_SIZE_V6 64 #define MAX_FILE_GROUP_COUNT 71 #define MAX_COMPONENT_COUNT 71 typedef struct { uint32_t signature; /* 00 */ uint32_t version; uint32_t volume_info; uint32_t cab_descriptor_offset; uint32_t cab_descriptor_size; /* 10 */ } CommonHeader; typedef struct { uint32_t data_offset; uint32_t data_offset_high; uint32_t first_file_index; uint32_t last_file_index; uint32_t first_file_offset; uint32_t first_file_offset_high; uint32_t first_file_size_expanded; uint32_t first_file_size_expanded_high; uint32_t first_file_size_compressed; uint32_t first_file_size_compressed_high; uint32_t last_file_offset; uint32_t last_file_offset_high; uint32_t last_file_size_expanded; uint32_t last_file_size_expanded_high; uint32_t last_file_size_compressed; uint32_t last_file_size_compressed_high; } VolumeHeader; typedef struct { uint32_t file_table_offset; /* c */ uint32_t file_table_size; /* 14 */ uint32_t file_table_size2; /* 18 */ uint32_t directory_count; /* 1c */ uint32_t file_count; /* 28 */ uint32_t file_table_offset2; /* 2c */ uint32_t file_group_offsets[MAX_FILE_GROUP_COUNT]; /* 0x3e */ uint32_t component_offsets [MAX_COMPONENT_COUNT]; /* 0x15a */ } CabDescriptor; #define FILE_SPLIT 1 #define FILE_OBFUSCATED 2 #define FILE_COMPRESSED 4 #define FILE_INVALID 8 #define LINK_NONE 0 #define LINK_PREV 1 #define LINK_NEXT 2 #define LINK_BOTH 3 typedef struct { uint32_t name_offset; uint32_t directory_index; uint16_t flags; uint32_t expanded_size; uint32_t compressed_size; uint32_t data_offset; uint8_t md5[16]; uint16_t volume; uint32_t link_previous; uint32_t link_next; uint8_t link_flags; } FileDescriptor; typedef struct { uint32_t name_offset; uint32_t descriptor_offset; uint32_t next_offset; } OffsetList; #endif unshield-1.0/lib/component.c000066400000000000000000000031321221214546300161000ustar00rootroot00000000000000/* $Id$ */ #include "internal.h" #include "log.h" #include #include int unshield_component_count(Unshield* unshield) { Header* header = unshield->header_list; return header->component_count; } const char* unshield_component_name(Unshield* unshield, int index) { Header* header = unshield->header_list; if (index >= 0 && index < header->component_count) return header->components[index]->name; else return NULL; } UnshieldComponent* unshield_component_new(Header* header, uint32_t offset) { UnshieldComponent* self = NEW1(UnshieldComponent); uint8_t* p = unshield_header_get_buffer(header, offset); uint32_t file_group_table_offset; unsigned i; self->name = unshield_header_get_string(header, READ_UINT32(p)); p += 4; switch (header->major_version) { case 0: case 5: p += 0x6c; break; case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: default: p += 0x6b; break; } self->file_group_count = READ_UINT16(p); p += 2; if (self->file_group_count > MAX_FILE_GROUP_COUNT) abort(); self->file_group_names = NEW(const char*, self->file_group_count); file_group_table_offset = READ_UINT32(p); p += 4; p = unshield_header_get_buffer(header, file_group_table_offset); for (i = 0; i < self->file_group_count; i++) { self->file_group_names[i] = unshield_header_get_string(header, READ_UINT32(p)); p += 4; } return self; } void unshield_component_destroy(UnshieldComponent* self) { if (self) { FREE(self->file_group_names); free(self); } } unshield-1.0/lib/convert_utf/000077500000000000000000000000001221214546300162715ustar00rootroot00000000000000unshield-1.0/lib/convert_utf/ConvertUTF.c000066400000000000000000000451731221214546300204460ustar00rootroot00000000000000/* * Copyright 2001-2004 Unicode, Inc. * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. */ /* --------------------------------------------------------------------- Conversions between UTF32, UTF-16, and UTF-8. Source code file. Author: Mark E. Davis, 1994. Rev History: Rick McGowan, fixes & updates May 2001. Sept 2001: fixed const & error conditions per mods suggested by S. Parent & A. Lillich. June 2002: Tim Dodd added detection and handling of incomplete source sequences, enhanced error detection, added casts to eliminate compiler warnings. July 2003: slight mods to back out aggressive FFFE detection. Jan 2004: updated switches in from-UTF8 conversions. Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. See the header file "ConvertUTF.h" for complete documentation. ------------------------------------------------------------------------ */ #include "ConvertUTF.h" #ifdef CVTUTF_DEBUG #include #endif static const int halfShift = 10; /* used for shifting by 10 bits */ static const UTF32 halfBase = 0x0010000UL; static const UTF32 halfMask = 0x3FFUL; #define UNI_SUR_HIGH_START (UTF32)0xD800 #define UNI_SUR_HIGH_END (UTF32)0xDBFF #define UNI_SUR_LOW_START (UTF32)0xDC00 #define UNI_SUR_LOW_END (UTF32)0xDFFF #define false 0 #define true 1 /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF32toUTF16 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { UTF32 ch; if (target >= targetEnd) { result = targetExhausted; break; } ch = *source++; if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = (UTF16)ch; /* normal case */ } } else if (ch > UNI_MAX_LEGAL_UTF32) { if (flags == strictConversion) { result = sourceIllegal; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ if (target + 1 >= targetEnd) { --source; /* Back up source pointer! */ result = targetExhausted; break; } ch -= halfBase; *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); } } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF16toUTF32 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF32* target = *targetStart; UTF32 ch, ch2; while (source < sourceEnd) { const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ result = sourceExhausted; break; } } else if (flags == strictConversion) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } if (target >= targetEnd) { source = oldSource; /* Back up source pointer! */ result = targetExhausted; break; } *target++ = ch; } *sourceStart = source; *targetStart = target; #ifdef CVTUTF_DEBUG if (result == sourceIllegal) { fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); fflush(stderr); } #endif return result; } /* --------------------------------------------------------------------- */ /* * Index into the table below with the first byte of a UTF-8 sequence to * get the number of trailing bytes that are supposed to follow it. * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is * left as-is for anyone who may want to do such conversion, which was * allowed in earlier algorithms. */ static const char trailingBytesForUTF8[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; /* * Magic values subtracted from a buffer value during UTF8 conversion. * This table contains as many values as there might be trailing bytes * in a UTF-8 sequence. */ static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; /* * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed * into the first byte, depending on how many bytes follow. There are * as many entries in this table as there are UTF-8 sequence types. * (I.e., one byte sequence, two byte... etc.). Remember that sequencs * for *legal* UTF-8 will be 4 or fewer bytes total. */ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; /* --------------------------------------------------------------------- */ /* The interface converts a whole buffer to avoid function-call overhead. * Constants have been gathered. Loops & conditionals have been removed as * much as possible for efficiency, in favor of drop-through switches. * (See "Note A" at the bottom of the file for equivalent code.) * If your compiler supports it, the "isLegalUTF8" call can be turned * into an inline function. */ /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { UTF32 ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ result = sourceExhausted; break; } } else if (flags == strictConversion) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } /* Figure out how many bytes the result will require */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; } target += bytesToWrite; if (target > targetEnd) { source = oldSource; /* Back up source pointer! */ target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ /* * Utility routine to tell whether a sequence of bytes is legal UTF-8. * This must be called with the length pre-determined by the first byte. * If not calling this from ConvertUTF8to*, then the length can be set by: * length = trailingBytesForUTF8[*source]+1; * and the sequence is illegal right away if there aren't that many bytes * available. * If presented with a length > 4, this returns false. The Unicode * definition of UTF-8 goes up to 4-byte sequences. */ static Boolean isLegalUTF8(const UTF8 *source, int length) { UTF8 a; const UTF8 *srcptr = source+length; switch (length) { default: return false; /* Everything else falls through when "true"... */ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 2: if ((a = (*--srcptr)) > 0xBF) return false; switch (*source) { /* no fall-through in this inner switch */ case 0xE0: if (a < 0xA0) return false; break; case 0xED: if (a > 0x9F) return false; break; case 0xF0: if (a < 0x90) return false; break; case 0xF4: if (a > 0x8F) return false; break; default: if (a < 0x80) return false; } case 1: if (*source >= 0x80 && *source < 0xC2) return false; } if (*source > 0xF4) return false; return true; } /* --------------------------------------------------------------------- */ /* * Exported function to return whether a UTF-8 sequence is legal or not. * This is not used here; it's just exported. */ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { int length = trailingBytesForUTF8[*source]+1; if (source+length > sourceEnd) { return false; } return isLegalUTF8(source, length); } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { UTF32 ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { result = sourceExhausted; break; } /* Do this check whether lenient or strict */ if (! isLegalUTF8(source, extraBytesToRead+1)) { result = sourceIllegal; break; } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ result = targetExhausted; break; } if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = (UTF16)ch; /* normal case */ } } else if (ch > UNI_MAX_UTF16) { if (flags == strictConversion) { result = sourceIllegal; source -= (extraBytesToRead+1); /* return to the start */ break; /* Bail out; shouldn't continue */ } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ if (target + 1 >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ result = targetExhausted; break; } ch -= halfBase; *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); } } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; ch = *source++; if (flags == strictConversion ) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } /* * Figure out how many bytes the result will require. Turn any * illegally large UTF32 things (> Plane 17) into replacement chars. */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; result = sourceIllegal; } target += bytesToWrite; if (target > targetEnd) { --source; /* Back up source pointer! */ target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF8toUTF32 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF32* target = *targetStart; while (source < sourceEnd) { UTF32 ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { result = sourceExhausted; break; } /* Do this check whether lenient or strict */ if (! isLegalUTF8(source, extraBytesToRead+1)) { result = sourceIllegal; break; } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; case 4: ch += *source++; ch <<= 6; case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up the source pointer! */ result = targetExhausted; break; } if (ch <= UNI_MAX_LEGAL_UTF32) { /* * UTF-16 surrogate values are illegal in UTF-32, and anything * over Plane 17 (> 0x10FFFF) is illegal. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = ch; } } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ result = sourceIllegal; *target++ = UNI_REPLACEMENT_CHAR; } } *sourceStart = source; *targetStart = target; return result; } /* --------------------------------------------------------------------- Note A. The fall-through switches in UTF-8 reading code save a temp variable, some decrements & conditionals. The switches are equivalent to the following loop: { int tmpBytesToRead = extraBytesToRead+1; do { ch += *source++; --tmpBytesToRead; if (tmpBytesToRead) ch <<= 6; } while (tmpBytesToRead > 0); } In UTF-8 writing code, the switches on "bytesToWrite" are similarly unrolled loops. --------------------------------------------------------------------- */ unshield-1.0/lib/convert_utf/ConvertUTF.h000066400000000000000000000134651221214546300204520ustar00rootroot00000000000000/* * Copyright 2001-2004 Unicode, Inc. * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. */ /* --------------------------------------------------------------------- Conversions between UTF32, UTF-16, and UTF-8. Header file. Several funtions are included here, forming a complete set of conversions between the three formats. UTF-7 is not included here, but is handled in a separate source file. Each of these routines takes pointers to input buffers and output buffers. The input buffers are const. Each routine converts the text between *sourceStart and sourceEnd, putting the result into the buffer between *targetStart and targetEnd. Note: the end pointers are *after* the last item: e.g. *(sourceEnd - 1) is the last item. The return result indicates whether the conversion was successful, and if not, whether the problem was in the source or target buffers. (Only the first encountered problem is indicated.) After the conversion, *sourceStart and *targetStart are both updated to point to the end of last text successfully converted in the respective buffers. Input parameters: sourceStart - pointer to a pointer to the source buffer. The contents of this are modified on return so that it points at the next thing to be converted. targetStart - similarly, pointer to pointer to the target buffer. sourceEnd, targetEnd - respectively pointers to the ends of the two buffers, for overflow checking only. These conversion functions take a ConversionFlags argument. When this flag is set to strict, both irregular sequences and isolated surrogates will cause an error. When the flag is set to lenient, both irregular sequences and isolated surrogates are converted. Whether the flag is strict or lenient, all illegal sequences will cause an error return. This includes sequences such as: , , or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code must check for illegal sequences. When the flag is set to lenient, characters over 0x10FFFF are converted to the replacement character; otherwise (when the flag is set to strict) they constitute an error. Output parameters: The value "sourceIllegal" is returned from some routines if the input sequence is malformed. When "sourceIllegal" is returned, the source value will point to the illegal value that caused the problem. E.g., in UTF-8 when a sequence is malformed, it points to the start of the malformed sequence. Author: Mark E. Davis, 1994. Rev History: Rick McGowan, fixes & updates May 2001. Fixes & updates, Sept 2001. ------------------------------------------------------------------------ */ /* --------------------------------------------------------------------- The following 4 definitions are compiler-specific. The C standard does not guarantee that wchar_t has at least 16 bits, so wchar_t is no less portable than unsigned short! All should be unsigned values to avoid sign extension during bit mask & shift operations. ------------------------------------------------------------------------ */ typedef unsigned long UTF32; /* at least 32 bits */ typedef unsigned short UTF16; /* at least 16 bits */ typedef unsigned char UTF8; /* typically 8 bits */ typedef unsigned char Boolean; /* 0 or 1 */ /* Some fundamental constants */ #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD #define UNI_MAX_BMP (UTF32)0x0000FFFF #define UNI_MAX_UTF16 (UTF32)0x0010FFFF #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF typedef enum { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ targetExhausted, /* insuff. room in target for conversion */ sourceIllegal /* source sequence is illegal/malformed */ } ConversionResult; typedef enum { strictConversion = 0, lenientConversion } ConversionFlags; /* This is for C++ and does no harm in C */ #ifdef __cplusplus extern "C" { #endif ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF8toUTF32 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF16toUTF32 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); ConversionResult ConvertUTF32toUTF16 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); #ifdef __cplusplus } #endif /* --------------------------------------------------------------------- */ unshield-1.0/lib/convert_utf/Makefile.am000066400000000000000000000002431221214546300203240ustar00rootroot00000000000000AM_CPPFLAGS = -I.. ## create this library noinst_LTLIBRARIES = libconvert_utf.la ## use these sources libconvert_utf_la_SOURCES = \ ConvertUTF.h ConvertUTF.c unshield-1.0/lib/convert_utf/README.google000066400000000000000000000004611221214546300204250ustar00rootroot00000000000000This is a utf8/16/32 conversion functions downloaded from unicode.org website from url: ftp://www.unicode.org/Public/PROGRAMS/CVTUTF/ Only ConvertUTF.h and ConvertUTF.c files were downloaded. The rest of files related to UTF7 and testing harness were not downloaded. No modifications have been done. unshield-1.0/lib/convert_utf/README.unshield000066400000000000000000000001571221214546300207660ustar00rootroot00000000000000These files were downloaded from http://gears.googlecode.com/svn/trunk/third_party/convert_utf/ on 2013-02-15. unshield-1.0/lib/convert_utf/readme.txt000066400000000000000000000027241221214546300202740ustar00rootroot00000000000000 The accompanying C source code file "ConvertUTF.c" and the associated header file "ConvertUTF.h" provide for conversion between various transformation formats of Unicode characters. The following conversions are supported: UTF-32 to UTF-16 UTF-32 to UTF-8 UTF-16 to UTF-32 UTF-16 to UTF-8 UTF-8 to UTF-16 UTF-8 to UTF-32 In addition, there is a test harness which runs various tests. The files "CVTUTF7.C" and "CVTUTF7.H" are for archival and historical purposes only. They have not been updated to Unicode 3.0 or later and should be considered obsolescent. "CVTUTF7.C" contains two functions that can convert between UCS2 (i.e., the BMP characters only) and UTF-7. Surrogates are not supported, the code has not been tested, and should be considered unsuitable for general purpose use. Please submit any bug reports about these programs here: http://www.unicode.org/unicode/reporting.html Version 1.0: initial version. Version 1.1: corrected some minor problems; added stricter checks. Version 1.2: corrected switch statements associated with "extraBytesToRead" in 4 & 5 byte cases, in functions for conversion from UTF8. Note: formally, the 4 & 5 byte cases are illegal in the latest UTF8, but the table and this code has always catered for those, cases since at one time they were legal. Version 1.3: Updated UTF-8 legality check; updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions Updated UTF-8 legality tests in harness.c Last update: October 19, 2004 unshield-1.0/lib/directory.c000066400000000000000000000014361221214546300161070ustar00rootroot00000000000000/* $Id$ */ #include "internal.h" #include "log.h" int unshield_directory_count(Unshield* unshield) { if (unshield) { /* XXX: multi-volume support... */ Header* header = unshield->header_list; return header->cab.directory_count; } else return -1; } const char* unshield_directory_name(Unshield* unshield, int index) { if (unshield && index >= 0) { /* XXX: multi-volume support... */ Header* header = unshield->header_list; if (index < (int)header->cab.directory_count) return unshield_get_utf8_string(header, header->data + header->common.cab_descriptor_offset + header->cab.file_table_offset + header->file_table[index]); } unshield_warning("Failed to get directory name %i", index); return NULL; } unshield-1.0/lib/file.c000066400000000000000000000744671221214546300150400ustar00rootroot00000000000000/* $Id$ */ #include "internal.h" #if USE_OUR_OWN_MD5 #include "md5/global.h" #include "md5/md5.h" #else #include #define MD5Init MD5_Init #define MD5Update MD5_Update #define MD5Final MD5_Final #endif #include "cabfile.h" #include "log.h" #include #include #include #include /* for MIN(a,b) */ #include #define VERBOSE 3 #define ror8(x,n) (((x) >> ((int)(n))) | ((x) << (8 - (int)(n)))) #define rol8(x,n) (((x) << ((int)(n))) | ((x) >> (8 - (int)(n)))) static FileDescriptor* unshield_read_file_descriptor(Unshield* unshield, int index) { /* XXX: multi-volume support... */ Header* header = unshield->header_list; uint8_t* p = NULL; uint8_t* saved_p = NULL; FileDescriptor* fd = NEW1(FileDescriptor); switch (header->major_version) { case 0: case 5: saved_p = p = header->data + header->common.cab_descriptor_offset + header->cab.file_table_offset + header->file_table[header->cab.directory_count + index]; #if VERBOSE unshield_trace("File descriptor offset %i: %08x", index, p - header->data); #endif fd->volume = header->index; fd->name_offset = READ_UINT32(p); p += 4; fd->directory_index = READ_UINT32(p); p += 4; fd->flags = READ_UINT16(p); p += 2; fd->expanded_size = READ_UINT32(p); p += 4; fd->compressed_size = READ_UINT32(p); p += 4; p += 0x14; fd->data_offset = READ_UINT32(p); p += 4; #if VERBOSE >= 2 unshield_trace("Name offset: %08x", fd->name_offset); unshield_trace("Directory index: %08x", fd->directory_index); unshield_trace("Flags: %04x", fd->flags); unshield_trace("Expanded size: %08x", fd->expanded_size); unshield_trace("Compressed size: %08x", fd->compressed_size); unshield_trace("Data offset: %08x", fd->data_offset); #endif if (header->major_version == 5) { memcpy(fd->md5, p, 0x10); p += 0x10; assert((p - saved_p) == 0x3a); } break; case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: default: saved_p = p = header->data + header->common.cab_descriptor_offset + header->cab.file_table_offset + header->cab.file_table_offset2 + index * 0x57; #if VERBOSE unshield_trace("File descriptor offset: %08x", p - header->data); #endif fd->flags = READ_UINT16(p); p += 2; fd->expanded_size = READ_UINT32(p); p += 4; p += 4; fd->compressed_size = READ_UINT32(p); p += 4; p += 4; fd->data_offset = READ_UINT32(p); p += 4; p += 4; memcpy(fd->md5, p, 0x10); p += 0x10; p += 0x10; fd->name_offset = READ_UINT32(p); p += 4; fd->directory_index = READ_UINT16(p); p += 2; assert((p - saved_p) == 0x40); p += 0xc; fd->link_previous = READ_UINT32(p); p += 4; fd->link_next = READ_UINT32(p); p += 4; fd->link_flags = *p; p ++; #if VERBOSE if (fd->link_flags != LINK_NONE) { unshield_trace("Link: previous=%i, next=%i, flags=%i", fd->link_previous, fd->link_next, fd->link_flags); } #endif fd->volume = READ_UINT16(p); p += 2; assert((p - saved_p) == 0x57); break; } if (!(fd->flags & FILE_COMPRESSED) && fd->compressed_size != fd->expanded_size) { unshield_warning("File is not compressed but compressed size is %08x and expanded size is %08x", fd->compressed_size, fd->expanded_size); } return fd; } static FileDescriptor* unshield_get_file_descriptor(Unshield* unshield, int index) { /* XXX: multi-volume support... */ Header* header = unshield->header_list; if (index < 0 || index >= (int)header->cab.file_count) { unshield_error("Invalid index"); return NULL; } if (!header->file_descriptors) header->file_descriptors = calloc(header->cab.file_count, sizeof(FileDescriptor*)); if (!header->file_descriptors[index]) header->file_descriptors[index] = unshield_read_file_descriptor(unshield, index); return header->file_descriptors[index]; } int unshield_file_count (Unshield* unshield)/*{{{*/ { if (unshield) { /* XXX: multi-volume support... */ Header* header = unshield->header_list; return header->cab.file_count; } else return -1; }/*}}}*/ const char* unshield_file_name (Unshield* unshield, int index)/*{{{*/ { FileDescriptor* fd = unshield_get_file_descriptor(unshield, index); if (fd) { /* XXX: multi-volume support... */ Header* header = unshield->header_list; return unshield_get_utf8_string(header, header->data + header->common.cab_descriptor_offset + header->cab.file_table_offset + fd->name_offset); } unshield_warning("Failed to get file descriptor %i", index); return NULL; }/*}}}*/ bool unshield_file_is_valid(Unshield* unshield, int index) { bool is_valid = false; FileDescriptor* fd; if (index < 0 || index >= unshield_file_count(unshield)) goto exit; if (!(fd = unshield_get_file_descriptor(unshield, index))) goto exit; if (fd->flags & FILE_INVALID) goto exit; if (!fd->name_offset) goto exit; if (!fd->data_offset) goto exit; is_valid = true; exit: return is_valid; } static int unshield_uncompress (Byte *dest, uLong* destLen, Byte *source, uLong *sourceLen)/*{{{*/ { z_stream stream; int err; stream.next_in = source; stream.avail_in = (uInt)*sourceLen; stream.next_out = dest; stream.avail_out = (uInt)*destLen; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; /* make second parameter negative to disable checksum verification */ err = inflateInit2(&stream, -MAX_WBITS); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); return err; } *destLen = stream.total_out; *sourceLen = stream.total_in; err = inflateEnd(&stream); return err; }/*}}}*/ static int unshield_uncompress_old(Byte *dest, uLong *destLen, Byte *source, uLong *sourceLen)/*{{{*/ { z_stream stream; int err; stream.next_in = source; stream.avail_in = (uInt)*sourceLen; stream.next_out = dest; stream.avail_out = (uInt)*destLen; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; *destLen = 0; *sourceLen = 0; /* make second parameter negative to disable checksum verification */ err = inflateInit2(&stream, -MAX_WBITS); if (err != Z_OK) return err; err = inflate(&stream, Z_BLOCK); if (err != Z_OK) { inflateEnd(&stream); return err; } *destLen = stream.total_out; *sourceLen = stream.total_in; err = inflateEnd(&stream); return err; }/*}}}*/ typedef struct { Unshield* unshield; unsigned index; FileDescriptor* file_descriptor; int volume; FILE* volume_file; VolumeHeader volume_header; unsigned volume_bytes_left; unsigned obfuscation_offset; } UnshieldReader; static bool unshield_reader_open_volume(UnshieldReader* reader, int volume)/*{{{*/ { bool success = false; unsigned data_offset = 0; unsigned volume_bytes_left_compressed; unsigned volume_bytes_left_expanded; CommonHeader common_header; #if VERBOSE >= 2 unshield_trace("Open volume %i", volume); #endif FCLOSE(reader->volume_file); reader->volume_file = unshield_fopen_for_reading(reader->unshield, volume, CABINET_SUFFIX); if (!reader->volume_file) { unshield_error("Failed to open input cabinet file %i", volume); goto exit; } { uint8_t tmp[COMMON_HEADER_SIZE]; uint8_t* p = tmp; if (COMMON_HEADER_SIZE != fread(&tmp, 1, COMMON_HEADER_SIZE, reader->volume_file)) goto exit; if (!unshield_read_common_header(&p, &common_header)) goto exit; } memset(&reader->volume_header, 0, sizeof(VolumeHeader)); switch (reader->unshield->header_list->major_version) { case 0: case 5: { uint8_t five_header[VOLUME_HEADER_SIZE_V5]; uint8_t* p = five_header; if (VOLUME_HEADER_SIZE_V5 != fread(&five_header, 1, VOLUME_HEADER_SIZE_V5, reader->volume_file)) goto exit; reader->volume_header.data_offset = READ_UINT32(p); p += 4; #if VERBOSE if (READ_UINT32(p)) unshield_trace("Unknown = %08x", READ_UINT32(p)); #endif /* unknown */ p += 4; reader->volume_header.first_file_index = READ_UINT32(p); p += 4; reader->volume_header.last_file_index = READ_UINT32(p); p += 4; reader->volume_header.first_file_offset = READ_UINT32(p); p += 4; reader->volume_header.first_file_size_expanded = READ_UINT32(p); p += 4; reader->volume_header.first_file_size_compressed = READ_UINT32(p); p += 4; reader->volume_header.last_file_offset = READ_UINT32(p); p += 4; reader->volume_header.last_file_size_expanded = READ_UINT32(p); p += 4; reader->volume_header.last_file_size_compressed = READ_UINT32(p); p += 4; if (reader->volume_header.last_file_offset == 0) reader->volume_header.last_file_offset = INT32_MAX; } break; case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: default: { uint8_t six_header[VOLUME_HEADER_SIZE_V6]; uint8_t* p = six_header; if (VOLUME_HEADER_SIZE_V6 != fread(&six_header, 1, VOLUME_HEADER_SIZE_V6, reader->volume_file)) goto exit; reader->volume_header.data_offset = READ_UINT32(p); p += 4; reader->volume_header.data_offset_high = READ_UINT32(p); p += 4; reader->volume_header.first_file_index = READ_UINT32(p); p += 4; reader->volume_header.last_file_index = READ_UINT32(p); p += 4; reader->volume_header.first_file_offset = READ_UINT32(p); p += 4; reader->volume_header.first_file_offset_high = READ_UINT32(p); p += 4; reader->volume_header.first_file_size_expanded = READ_UINT32(p); p += 4; reader->volume_header.first_file_size_expanded_high = READ_UINT32(p); p += 4; reader->volume_header.first_file_size_compressed = READ_UINT32(p); p += 4; reader->volume_header.first_file_size_compressed_high = READ_UINT32(p); p += 4; reader->volume_header.last_file_offset = READ_UINT32(p); p += 4; reader->volume_header.last_file_offset_high = READ_UINT32(p); p += 4; reader->volume_header.last_file_size_expanded = READ_UINT32(p); p += 4; reader->volume_header.last_file_size_expanded_high = READ_UINT32(p); p += 4; reader->volume_header.last_file_size_compressed = READ_UINT32(p); p += 4; reader->volume_header.last_file_size_compressed_high = READ_UINT32(p); p += 4; } break; } #if VERBOSE >= 2 unshield_trace("First file index = %i, last file index = %i", reader->volume_header.first_file_index, reader->volume_header.last_file_index); unshield_trace("First file offset = %08x, last file offset = %08x", reader->volume_header.first_file_offset, reader->volume_header.last_file_offset); #endif /* enable support for split archives for IS5 */ if (reader->unshield->header_list->major_version == 5) { if (reader->index < (reader->unshield->header_list->cab.file_count - 1) && reader->index == reader->volume_header.last_file_index && reader->volume_header.last_file_size_compressed != reader->file_descriptor->compressed_size) { unshield_trace("IS5 split file last in volume"); reader->file_descriptor->flags |= FILE_SPLIT; } else if (reader->index > 0 && reader->index == reader->volume_header.first_file_index && reader->volume_header.first_file_size_compressed != reader->file_descriptor->compressed_size) { unshield_trace("IS5 split file first in volume"); reader->file_descriptor->flags |= FILE_SPLIT; } } if (reader->file_descriptor->flags & FILE_SPLIT) { #if VERBOSE unshield_trace(/*"Total bytes left = 0x08%x, "*/"previous data offset = 0x08%x", /*total_bytes_left, */data_offset); #endif if (reader->index == reader->volume_header.last_file_index && reader->volume_header.last_file_offset != 0x7FFFFFFF) { /* can be first file too... */ #if VERBOSE unshield_trace("Index %i is last file in cabinet file %i", reader->index, volume); #endif data_offset = reader->volume_header.last_file_offset; volume_bytes_left_expanded = reader->volume_header.last_file_size_expanded; volume_bytes_left_compressed = reader->volume_header.last_file_size_compressed; } else if (reader->index == reader->volume_header.first_file_index) { #if VERBOSE unshield_trace("Index %i is first file in cabinet file %i", reader->index, volume); #endif data_offset = reader->volume_header.first_file_offset; volume_bytes_left_expanded = reader->volume_header.first_file_size_expanded; volume_bytes_left_compressed = reader->volume_header.first_file_size_compressed; } else { success = true; goto exit; } #if VERBOSE unshield_trace("Will read 0x%08x bytes from offset 0x%08x", volume_bytes_left_compressed, data_offset); #endif } else { data_offset = reader->file_descriptor->data_offset; volume_bytes_left_expanded = reader->file_descriptor->expanded_size; volume_bytes_left_compressed = reader->file_descriptor->compressed_size; } if (reader->file_descriptor->flags & FILE_COMPRESSED) reader->volume_bytes_left = volume_bytes_left_compressed; else reader->volume_bytes_left = volume_bytes_left_expanded; fseek(reader->volume_file, data_offset, SEEK_SET); reader->volume = volume; success = true; exit: return success; }/*}}}*/ void unshield_deobfuscate(unsigned char* buffer, size_t size, unsigned* seed) { unsigned tmp_seed = *seed; for (; size > 0; size--, buffer++, tmp_seed++) { *buffer = ror8(*buffer ^ 0xd5, 2) - (tmp_seed % 0x47); } *seed = tmp_seed; } static void unshield_reader_deobfuscate(UnshieldReader* reader, uint8_t* buffer, size_t size) { unshield_deobfuscate(buffer, size, &reader->obfuscation_offset); } static bool unshield_reader_read(UnshieldReader* reader, void* buffer, size_t size)/*{{{*/ { bool success = false; uint8_t* p = buffer; size_t bytes_left = size; #if VERBOSE >= 3 unshield_trace("unshield_reader_read start: bytes_left = 0x%x, volume_bytes_left = 0x%x", bytes_left, reader->volume_bytes_left); #endif for (;;) { /* Read as much as possible from this volume */ size_t bytes_to_read = MIN(bytes_left, reader->volume_bytes_left); #if VERBOSE >= 3 unshield_trace("Trying to read 0x%x bytes from offset %08x in volume %i", bytes_to_read, ftell(reader->volume_file), reader->volume); #endif if (bytes_to_read != fread(p, 1, bytes_to_read, reader->volume_file)) { unshield_error("Failed to read 0x%08x bytes of file %i (%s) from volume %i. Current offset = 0x%08x", bytes_to_read, reader->index, unshield_file_name(reader->unshield, reader->index), reader->volume, ftell(reader->volume_file)); goto exit; } bytes_left -= bytes_to_read; reader->volume_bytes_left -= bytes_to_read; #if VERBOSE >= 3 unshield_trace("bytes_left = %i, volume_bytes_left = %i", bytes_left, reader->volume_bytes_left); #endif if (!bytes_left) break; p += bytes_to_read; /* Open next volume */ if (!unshield_reader_open_volume(reader, reader->volume + 1)) { unshield_error("Failed to open volume %i to read %i more bytes", reader->volume + 1, bytes_to_read); goto exit; } } if (reader->file_descriptor->flags & FILE_OBFUSCATED) unshield_reader_deobfuscate(reader, buffer, size); success = true; exit: return success; }/*}}}*/ static UnshieldReader* unshield_reader_create(/*{{{*/ Unshield* unshield, int index, FileDescriptor* file_descriptor) { bool success = false; UnshieldReader* reader = NEW1(UnshieldReader); if (!reader) return NULL; reader->unshield = unshield; reader->index = index; reader->file_descriptor = file_descriptor; for (;;) { if (!unshield_reader_open_volume(reader, file_descriptor->volume)) { unshield_error("Failed to open volume %i", file_descriptor->volume); goto exit; } /* Start with the correct volume for IS5 cabinets */ if (reader->unshield->header_list->major_version == 5 && index > (int)reader->volume_header.last_file_index) { unshield_trace("Trying next volume..."); file_descriptor->volume++; continue; } break; }; success = true; exit: if (success) return reader; FREE(reader); return NULL; }/*}}}*/ static void unshield_reader_destroy(UnshieldReader* reader)/*{{{*/ { if (reader) { FCLOSE(reader->volume_file); free(reader); } }/*}}}*/ #define BUFFER_SIZE (64*1024) /* * If filename is NULL, just throw away the result */ bool unshield_file_save (Unshield* unshield, int index, const char* filename)/*{{{*/ { bool success = false; FILE* output = NULL; unsigned char* input_buffer = (unsigned char*)malloc(BUFFER_SIZE+1); unsigned char* output_buffer = (unsigned char*)malloc(BUFFER_SIZE); int bytes_left; uLong total_written = 0; UnshieldReader* reader = NULL; FileDescriptor* file_descriptor; MD5_CTX md5; MD5Init(&md5); if (!unshield) goto exit; if (!(file_descriptor = unshield_get_file_descriptor(unshield, index))) { unshield_error("Failed to get file descriptor for file %i", index); goto exit; } if ((file_descriptor->flags & FILE_INVALID) || 0 == file_descriptor->data_offset) { /* invalid file */ goto exit; } if (file_descriptor->link_flags & LINK_PREV) { success = unshield_file_save(unshield, file_descriptor->link_previous, filename); goto exit; } reader = unshield_reader_create(unshield, index, file_descriptor); if (!reader) { unshield_error("Failed to create data reader for file %i", index); goto exit; } if (unshield_fsize(reader->volume_file) == (long)file_descriptor->data_offset) { unshield_error("File %i is not inside the cabinet.", index); goto exit; } if (filename) { output = fopen(filename, "w"); if (!output) { unshield_error("Failed to open output file '%s'", filename); goto exit; } } if (file_descriptor->flags & FILE_COMPRESSED) bytes_left = file_descriptor->compressed_size; else bytes_left = file_descriptor->expanded_size; /*unshield_trace("Bytes to read: %i", bytes_left);*/ while (bytes_left > 0) { uLong bytes_to_write = BUFFER_SIZE; int result; if (file_descriptor->flags & FILE_COMPRESSED) { uLong read_bytes; uint16_t bytes_to_read = 0; if (!unshield_reader_read(reader, &bytes_to_read, sizeof(bytes_to_read))) { #if VERBOSE unshield_error("Failed to read %i bytes of file %i (%s) from input cabinet file %i", sizeof(bytes_to_read), index, unshield_file_name(unshield, index), file_descriptor->volume); #endif goto exit; } bytes_to_read = letoh16(bytes_to_read); if (!unshield_reader_read(reader, input_buffer, bytes_to_read)) { #if VERBOSE unshield_error("Failed to read %i bytes of file %i (%s) from input cabinet file %i", bytes_to_read, index, unshield_file_name(unshield, index), file_descriptor->volume); #endif goto exit; } /* add a null byte to make inflate happy */ input_buffer[bytes_to_read] = 0; read_bytes = bytes_to_read+1; result = unshield_uncompress(output_buffer, &bytes_to_write, input_buffer, &read_bytes); if (Z_OK != result) { unshield_error("Decompression failed with code %i. bytes_to_read=%i, volume_bytes_left=%i, volume=%i, read_bytes=%i", result, bytes_to_read, reader->volume_bytes_left, file_descriptor->volume, read_bytes); goto exit; } #if VERBOSE >= 3 unshield_trace("read_bytes = %i", read_bytes); #endif bytes_left -= 2; bytes_left -= bytes_to_read; } else { bytes_to_write = MIN(bytes_left, BUFFER_SIZE); if (!unshield_reader_read(reader, output_buffer, bytes_to_write)) { #if VERBOSE unshield_error("Failed to read %i bytes from input cabinet file %i", bytes_to_write, file_descriptor->volume); #endif goto exit; } bytes_left -= bytes_to_write; } MD5Update(&md5, output_buffer, bytes_to_write); if (output) { if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output)) { unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename); goto exit; } } total_written += bytes_to_write; } if (file_descriptor->expanded_size != total_written) { unshield_error("Expanded size expected to be %i, but was %i", file_descriptor->expanded_size, total_written); goto exit; } if (unshield->header_list->major_version >= 6) { unsigned char md5result[16]; MD5Final(md5result, &md5); if (0 != memcmp(md5result, file_descriptor->md5, 16)) { unshield_error("MD5 checksum failure for file %i (%s)", index, unshield_file_name(unshield, index)); goto exit; } } success = true; exit: unshield_reader_destroy(reader); FCLOSE(output); FREE(input_buffer); FREE(output_buffer); return success; }/*}}}*/ int unshield_file_directory(Unshield* unshield, int index)/*{{{*/ { FileDescriptor* fd = unshield_get_file_descriptor(unshield, index); if (fd) { return fd->directory_index; } else return -1; }/*}}}*/ size_t unshield_file_size(Unshield* unshield, int index)/*{{{*/ { FileDescriptor* fd = unshield_get_file_descriptor(unshield, index); if (fd) { return fd->expanded_size; } else return 0; }/*}}}*/ bool unshield_file_save_raw(Unshield* unshield, int index, const char* filename) { /* XXX: Thou Shalt Not Cut & Paste... */ bool success = false; FILE* output = NULL; unsigned char* input_buffer = (unsigned char*)malloc(BUFFER_SIZE); unsigned char* output_buffer = (unsigned char*)malloc(BUFFER_SIZE); int bytes_left; UnshieldReader* reader = NULL; FileDescriptor* file_descriptor; if (!unshield) goto exit; if (!(file_descriptor = unshield_get_file_descriptor(unshield, index))) { unshield_error("Failed to get file descriptor for file %i", index); goto exit; } if ((file_descriptor->flags & FILE_INVALID) || 0 == file_descriptor->data_offset) { /* invalid file */ goto exit; } if (file_descriptor->link_flags & LINK_PREV) { success = unshield_file_save_raw(unshield, file_descriptor->link_previous, filename); goto exit; } reader = unshield_reader_create(unshield, index, file_descriptor); if (!reader) { unshield_error("Failed to create data reader for file %i", index); goto exit; } if (unshield_fsize(reader->volume_file) == (long)file_descriptor->data_offset) { unshield_error("File %i is not inside the cabinet.", index); goto exit; } if (filename) { output = fopen(filename, "w"); if (!output) { unshield_error("Failed to open output file '%s'", filename); goto exit; } } if (file_descriptor->flags & FILE_COMPRESSED) bytes_left = file_descriptor->compressed_size; else bytes_left = file_descriptor->expanded_size; /*unshield_trace("Bytes to read: %i", bytes_left);*/ while (bytes_left > 0) { uLong bytes_to_write = MIN(bytes_left, BUFFER_SIZE); if (!unshield_reader_read(reader, output_buffer, bytes_to_write)) { #if VERBOSE unshield_error("Failed to read %i bytes from input cabinet file %i", bytes_to_write, file_descriptor->volume); #endif goto exit; } bytes_left -= bytes_to_write; if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output)) { unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename); goto exit; } } success = true; exit: unshield_reader_destroy(reader); FCLOSE(output); FREE(input_buffer); FREE(output_buffer); return success; } static uint8_t* find_bytes( const uint8_t* buffer, size_t bufferSize, const uint8_t* pattern, size_t patternSize) { const void *p = buffer; size_t buffer_left = bufferSize; while ((p = memchr(p, pattern[0], buffer_left)) != NULL) { if (patternSize > buffer_left) break; if (memcmp(p, pattern, patternSize) == 0) return (uint8_t*)p; ++p; --buffer_left; } return NULL; } bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)/*{{{*/ { /* XXX: Thou Shalt Not Cut & Paste... */ bool success = false; FILE* output = NULL; size_t input_buffer_size = BUFFER_SIZE; unsigned char* input_buffer = (unsigned char*)malloc(BUFFER_SIZE); unsigned char* output_buffer = (unsigned char*)malloc(BUFFER_SIZE); int bytes_left; uLong total_written = 0; UnshieldReader* reader = NULL; FileDescriptor* file_descriptor; if (!unshield) goto exit; if (!(file_descriptor = unshield_get_file_descriptor(unshield, index))) { unshield_error("Failed to get file descriptor for file %i", index); goto exit; } if ((file_descriptor->flags & FILE_INVALID) || 0 == file_descriptor->data_offset) { /* invalid file */ goto exit; } if (file_descriptor->link_flags & LINK_PREV) { success = unshield_file_save(unshield, file_descriptor->link_previous, filename); goto exit; } reader = unshield_reader_create(unshield, index, file_descriptor); if (!reader) { unshield_error("Failed to create data reader for file %i", index); goto exit; } if (unshield_fsize(reader->volume_file) == (long)file_descriptor->data_offset) { unshield_error("File %i is not inside the cabinet.", index); goto exit; } if (filename) { output = fopen(filename, "w"); if (!output) { unshield_error("Failed to open output file '%s'", filename); goto exit; } } if (file_descriptor->flags & FILE_COMPRESSED) bytes_left = file_descriptor->compressed_size; else bytes_left = file_descriptor->expanded_size; /*unshield_trace("Bytes to read: %i", bytes_left);*/ while (bytes_left > 0) { uLong bytes_to_write = 0; int result; if (file_descriptor->flags & FILE_COMPRESSED) { static const uint8_t END_OF_CHUNK[4] = { 0x00, 0x00, 0xff, 0xff }; uLong read_bytes; size_t input_size = reader->volume_bytes_left; uint8_t* chunk_buffer; while (input_size > input_buffer_size) { input_buffer_size *= 2; #if VERBOSE >= 3 unshield_trace("increased input_buffer_size to 0x%x", input_buffer_size); #endif input_buffer = realloc(input_buffer, input_buffer_size); assert(input_buffer); } if (!unshield_reader_read(reader, input_buffer, input_size)) { #if VERBOSE unshield_error("Failed to read 0x%x bytes of file %i (%s) from input cabinet file %i", input_size, index, unshield_file_name(unshield, index), file_descriptor->volume); #endif goto exit; } bytes_left -= input_size; for (chunk_buffer = input_buffer; input_size; ) { size_t chunk_size; uint8_t* match = find_bytes(chunk_buffer, input_size, END_OF_CHUNK, sizeof(END_OF_CHUNK)); if (!match) { unshield_error("Could not find end of chunk for file %i (%s) from input cabinet file %i", index, unshield_file_name(unshield, index), file_descriptor->volume); goto exit; } chunk_size = match - chunk_buffer; #if VERBOSE >= 3 unshield_trace("chunk_size = 0x%x", chunk_size); #endif /* add a null byte to make inflate happy */ chunk_buffer[chunk_size] = 0; bytes_to_write = BUFFER_SIZE; read_bytes = chunk_size; result = unshield_uncompress_old(output_buffer, &bytes_to_write, chunk_buffer, &read_bytes); if (Z_OK != result) { unshield_error("Decompression failed with code %i. input_size=%i, volume_bytes_left=%i, volume=%i, read_bytes=%i", result, input_size, reader->volume_bytes_left, file_descriptor->volume, read_bytes); goto exit; } #if VERBOSE >= 3 unshield_trace("read_bytes = 0x%x", read_bytes); #endif chunk_buffer += chunk_size; chunk_buffer += sizeof(END_OF_CHUNK); input_size -= chunk_size; input_size -= sizeof(END_OF_CHUNK); if (output) if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output)) { unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename); goto exit; } total_written += bytes_to_write; } } else { bytes_to_write = MIN(bytes_left, BUFFER_SIZE); if (!unshield_reader_read(reader, output_buffer, bytes_to_write)) { #if VERBOSE unshield_error("Failed to read %i bytes from input cabinet file %i", bytes_to_write, file_descriptor->volume); #endif goto exit; } bytes_left -= bytes_to_write; if (output) if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output)) { unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename); goto exit; } total_written += bytes_to_write; } } if (file_descriptor->expanded_size != total_written) { unshield_error("Expanded size expected to be %i, but was %i", file_descriptor->expanded_size, total_written); goto exit; } success = true; exit: unshield_reader_destroy(reader); FCLOSE(output); FREE(input_buffer); FREE(output_buffer); return success; }/*}}}*/ unshield-1.0/lib/file_group.c000066400000000000000000000034401221214546300162330ustar00rootroot00000000000000/* $Id$ */ #include "internal.h" #include "log.h" #include #include #define VERBOSE 1 UnshieldFileGroup* unshield_file_group_new(Header* header, uint32_t offset)/*{{{*/ { UnshieldFileGroup* self = NEW1(UnshieldFileGroup); uint8_t* p = unshield_header_get_buffer(header, offset); #if VERBOSE unshield_trace("File group descriptor offset: %08x", offset); #endif self->name = unshield_header_get_string(header, READ_UINT32(p)); p += 4; if (header->major_version == 5) p += 0x48; else p += 0x12; self->first_file = READ_UINT32(p); p += 4; self->last_file = READ_UINT32(p); p += 4; #if VERBOSE unshield_trace("File group %08x first file = %i, last file = %i", offset, self->first_file, self->last_file); #endif return self; }/*}}}*/ void unshield_file_group_destroy(UnshieldFileGroup* self)/*{{{*/ { FREE(self); }/*}}}*/ int unshield_file_group_count(Unshield* unshield)/*{{{*/ { Header* header = unshield->header_list; return header->file_group_count; }/*}}}*/ UnshieldFileGroup* unshield_file_group_get(Unshield* unshield, int index) { Header* header = unshield->header_list; if (index >= 0 && index < header->file_group_count) return header->file_groups[index]; else return NULL; } UnshieldFileGroup* unshield_file_group_find(Unshield* unshield, const char* name) { Header* header = unshield->header_list; int i; for (i = 0; i < header->file_group_count; i++) { if (STREQ(header->file_groups[i]->name, name)) return header->file_groups[i]; } return NULL; } const char* unshield_file_group_name(Unshield* unshield, int index)/*{{{*/ { Header* header = unshield->header_list; if (index >= 0 && index < header->file_group_count) return header->file_groups[index]->name; else return NULL; }/*}}}*/ unshield-1.0/lib/helper.c000066400000000000000000000111701221214546300153560ustar00rootroot00000000000000#define _BSD_SOURCE 1 #include "internal.h" #include "log.h" #include "convert_utf/ConvertUTF.h" #include #include #include #include #include #define VERBOSE 0 FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suffix) { if (unshield && unshield->filename_pattern) { FILE* result = NULL; char filename[256]; char dirname[256]; char * p = strrchr(unshield->filename_pattern, '/'); const char *q; struct dirent *dent = NULL; DIR *sourcedir; snprintf(filename, sizeof(filename), unshield->filename_pattern, index, suffix); q=strrchr(filename,'/'); if (q) q++; else q=filename; if (p) { strncpy( dirname, unshield->filename_pattern,sizeof(dirname)); if ((unsigned int)(p-unshield->filename_pattern) > sizeof(dirname)) { unshield_trace("WARN: size\n"); dirname[sizeof(dirname)-1]=0; } else dirname[(p-unshield->filename_pattern)] = 0; } else strcpy(dirname,"."); sourcedir = opendir(dirname); /* Search for the File case independent */ if (sourcedir) { for (dent=readdir(sourcedir);dent;dent=readdir(sourcedir)) { if (!(strcasecmp(q, dent->d_name))) { /*unshield_trace("Found match %s\n",dent->d_name);*/ break; } } if (dent == NULL) { unshield_trace("File %s not found even case insensitive\n",filename); goto exit; } else snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name); } else unshield_trace("Could not open directory %s error %s\n", dirname, strerror(errno)); #if VERBOSE unshield_trace("Opening file '%s'", filename); #endif result = fopen(filename, "r"); exit: if (sourcedir) closedir(sourcedir); return result; } return NULL; } long unshield_fsize(FILE* file) { long result; long previous = ftell(file); fseek(file, 0L, SEEK_END); result = ftell(file); fseek(file, previous, SEEK_SET); return result; } bool unshield_read_common_header(uint8_t** buffer, CommonHeader* common) { uint8_t* p = *buffer; common->signature = READ_UINT32(p); p += 4; if (CAB_SIGNATURE != common->signature) { unshield_error("Invalid file signature"); if (MSCF_SIGNATURE == common->signature) unshield_warning("Found Microsoft Cabinet header. Use cabextract (http://www.kyz.uklinux.net/cabextract.php) to unpack this file."); return false; } common->version = READ_UINT32(p); p += 4; common->volume_info = READ_UINT32(p); p += 4; common->cab_descriptor_offset = READ_UINT32(p); p += 4; common->cab_descriptor_size = READ_UINT32(p); p += 4; #if VERBOSE unshield_trace("Common header: %08x %08x %08x %08x", common->version, common->volume_info, common->cab_descriptor_offset, common->cab_descriptor_size); #endif *buffer = p; return true; } /** Get pointer at cab descriptor + offset */ uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset) { if (offset) return header->data + header->common.cab_descriptor_offset + offset; else return NULL; } static int unshield_strlen_utf16(const uint16_t* utf16) { const uint16_t* current = utf16; while (*current++) ; return current - utf16; } static StringBuffer* unshield_add_string_buffer(Header* header) { StringBuffer* result = NEW1(StringBuffer); result->next = header->string_buffer; return header->string_buffer = result; } static const char* unshield_utf16_to_utf8(Header* header, const uint16_t* utf16) { StringBuffer* string_buffer = unshield_add_string_buffer(header); int length = unshield_strlen_utf16(utf16); int buffer_size = 2 * length + 1; char* target = string_buffer->string = NEW(char, buffer_size); ConversionResult result = ConvertUTF16toUTF8( (const UTF16**)&utf16, utf16 + length + 1, (UTF8**)&target, (UTF8*)(target + buffer_size), lenientConversion); if (result != conversionOK) { /* fail fast */ abort(); } return string_buffer->string; } const char* unshield_get_utf8_string(Header* header, const void* buffer) { if (header->major_version == 18 && buffer != NULL) { return unshield_utf16_to_utf8(header, (const uint16_t*)buffer); } else { return (const char*)buffer; } } /** Get string at cab descriptor offset + string offset */ const char* unshield_header_get_string(Header* header, uint32_t offset) { return unshield_get_utf8_string(header, unshield_header_get_buffer(header, offset)); } unshield-1.0/lib/internal.h000066400000000000000000000060211221214546300157170ustar00rootroot00000000000000/* $Id$ */ #ifndef __internal_h__ #define __internal_h__ #include "libunshield.h" #include "unshield_config.h" #if HAVE_STDINT_H #include #elif HAVE_INTTYPES_H #include #endif #include #include /* for FILE */ #include "cabfile.h" typedef struct _StringBuffer StringBuffer; struct _StringBuffer { StringBuffer* next; char* string; }; typedef struct _Header Header; struct _Header { Header* next; int index; uint8_t* data; size_t size; int major_version; /* shortcuts */ CommonHeader common; CabDescriptor cab; uint32_t* file_table; FileDescriptor** file_descriptors; int component_count; UnshieldComponent** components; int file_group_count; UnshieldFileGroup** file_groups; StringBuffer* string_buffer; }; struct _Unshield { Header* header_list; char* filename_pattern; }; /* Internal component functions */ UnshieldComponent* unshield_component_new(Header* header, uint32_t offset); void unshield_component_destroy(UnshieldComponent* self); /* Internal file group functions */ UnshieldFileGroup* unshield_file_group_new(Header* header, uint32_t offset); void unshield_file_group_destroy(UnshieldFileGroup* self); /* Helpers */ FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suffix); long unshield_fsize(FILE* file); bool unshield_read_common_header(uint8_t** buffer, CommonHeader* common); const char* unshield_get_utf8_string(Header* header, const void* buffer); const char* unshield_header_get_string(Header* header, uint32_t offset); uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset); /* Constants */ #define HEADER_SUFFIX "hdr" #define CABINET_SUFFIX "cab" /* Macros for safer development */ #define FREE(ptr) { if (ptr) { free(ptr); ptr = NULL; } } #define STRDUP(str) ((str) ? strdup(str) : NULL) #define NEW(type, count) ((type*)calloc(count, sizeof(type))) #define NEW1(type) ((type*)calloc(1, sizeof(type))) #define FCLOSE(file) if (file) { fclose(file); file = NULL; } #define FSIZE(file) (file ? unshield_fsize(file) : 0) #define STREQ(s1,s2) (0 == strcmp(s1,s2)) #if WORDS_BIGENDIAN #if HAVE_BYTESWAP_H #include #elif HAVE_SYS_BYTESWAP_H #include #else /* use our own functions */ #define IMPLEMENT_BSWAP_XX 1 #define bswap_16 unshield_bswap_16 #define bswap_32 unshield_bswap_32 uint16_t bswap_16(uint16_t x); uint32_t bswap_32(uint32_t x); #endif #define letoh16(x) bswap_16(x) #define letoh32(x) bswap_32(x) #else #define letoh32(x) (x) #define letoh16(x) (x) #endif static inline uint16_t get_unaligned_le16(const uint8_t *p) { return p[0] | p[1] << 8; } static inline uint32_t get_unaligned_le32(const uint8_t *p) { return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; } #define READ_UINT16(p) get_unaligned_le16(p) #define READ_UINT32(p) get_unaligned_le32(p) #define READ_INT16(p) ((int16_t)READ_UINT16(p)) #define READ_INT32(p) ((int32_t)READ_UINT32(p)) #endif unshield-1.0/lib/libunshield.c000066400000000000000000000240551221214546300164070ustar00rootroot00000000000000/* $Id$ */ #define _BSD_SOURCE 1 #include "internal.h" #include "log.h" #include #include #include #include /** Create filename pattern used by unshield_fopen_for_reading() */ static bool unshield_create_filename_pattern(Unshield* unshield, const char* filename)/*{{{*/ { /* TODO Correct his function so that it handles filenames with more than one dot ('.')! */ if (unshield && filename) { char pattern[256]; char* prefix = strdup(filename); char* p = strrchr(prefix, '/'); if (!p) p = prefix; for (; *p != '\0'; p++) { if ('.' == *p || isdigit(*p)) { *p = '\0'; break; } } snprintf(pattern, sizeof(pattern), "%s%%i.%%s", prefix); free(prefix); FREE(unshield->filename_pattern); unshield->filename_pattern = strdup(pattern); return true; } else return false; }/*}}}*/ static bool unshield_get_common_header(Header* header) { uint8_t* p = header->data; return unshield_read_common_header(&p, &header->common); } static bool unshield_get_cab_descriptor(Header* header) { if (header->common.cab_descriptor_size) { uint8_t* p = header->data + header->common.cab_descriptor_offset; int i; p += 0xc; header->cab.file_table_offset = READ_UINT32(p); p += 4; p += 4; header->cab.file_table_size = READ_UINT32(p); p += 4; header->cab.file_table_size2 = READ_UINT32(p); p += 4; header->cab.directory_count = READ_UINT32(p); p += 4; p += 8; header->cab.file_count = READ_UINT32(p); p += 4; header->cab.file_table_offset2 = READ_UINT32(p); p += 4; assert((p - (header->data + header->common.cab_descriptor_offset)) == 0x30); if (header->cab.file_table_size != header->cab.file_table_size2) unshield_warning("File table sizes do not match"); unshield_trace("Cabinet descriptor: %08x %08x %08x %08x", header->cab.file_table_offset, header->cab.file_table_size, header->cab.file_table_size2, header->cab.file_table_offset2 ); unshield_trace("Directory count: %i", header->cab.directory_count); unshield_trace("File count: %i", header->cab.file_count); p += 0xe; for (i = 0; i < MAX_FILE_GROUP_COUNT; i++) { header->cab.file_group_offsets[i] = READ_UINT32(p); p += 4; } for (i = 0; i < MAX_COMPONENT_COUNT; i++) { header->cab.component_offsets[i] = READ_UINT32(p); p += 4; } return true; } else { unshield_error("No CAB descriptor available!"); return false; } } static bool unshield_get_file_table(Header* header) { uint8_t* p = header->data + header->common.cab_descriptor_offset + header->cab.file_table_offset; int count = header->cab.directory_count + header->cab.file_count; int i; header->file_table = calloc(count, sizeof(uint32_t)); for (i = 0; i < count; i++) { header->file_table[i] = READ_UINT32(p); p += 4; } return true; } static bool unshield_header_get_components(Header* header)/*{{{*/ { int count = 0; int i; int available = 16; header->components = malloc(available * sizeof(UnshieldComponent*)); for (i = 0; i < MAX_COMPONENT_COUNT; i++) { if (header->cab.component_offsets[i]) { OffsetList list; list.next_offset = header->cab.component_offsets[i]; while (list.next_offset) { uint8_t* p = unshield_header_get_buffer(header, list.next_offset); list.name_offset = READ_UINT32(p); p += 4; list.descriptor_offset = READ_UINT32(p); p += 4; list.next_offset = READ_UINT32(p); p += 4; if (count == available) { available <<= 1; header->components = realloc(header->components, available * sizeof(UnshieldComponent*)); } header->components[count++] = unshield_component_new(header, list.descriptor_offset); } } } header->component_count = count; return true; } /*}}}*/ static bool unshield_header_get_file_groups(Header* header)/*{{{*/ { int count = 0; int i; int available = 16; header->file_groups = malloc(available * sizeof(UnshieldFileGroup*)); for (i = 0; i < MAX_FILE_GROUP_COUNT; i++) { if (header->cab.file_group_offsets[i]) { OffsetList list; list.next_offset = header->cab.file_group_offsets[i]; while (list.next_offset) { uint8_t* p = unshield_header_get_buffer(header, list.next_offset); list.name_offset = READ_UINT32(p); p += 4; list.descriptor_offset = READ_UINT32(p); p += 4; list.next_offset = READ_UINT32(p); p += 4; if (count == available) { available <<= 1; header->file_groups = realloc(header->file_groups, available * sizeof(UnshieldFileGroup*)); } header->file_groups[count++] = unshield_file_group_new(header, list.descriptor_offset); } } } header->file_group_count = count; return true; } /*}}}*/ /** Read all header files */ static bool unshield_read_headers(Unshield* unshield, int version)/*{{{*/ { int i; bool iterate = true; Header* previous = NULL; if (unshield->header_list) { unshield_warning("Already have a header list"); return true; } for (i = 1; iterate; i++) { FILE* file = unshield_fopen_for_reading(unshield, i, HEADER_SUFFIX); if (file) { unshield_trace("Reading header from .hdr file %i.", i); iterate = false; } else { unshield_trace("Could not open .hdr file %i. Reading header from .cab file %i instead.", i, i); file = unshield_fopen_for_reading(unshield, i, CABINET_SUFFIX); } if (file) { size_t bytes_read; Header* header = NEW1(Header); header->index = i; header->size = FSIZE(file); if (header->size < 4) { unshield_error("Header file %i too small", i); goto error; } header->data = malloc(header->size); if (!header->data) { unshield_error("Failed to allocate memory for header file %i", i); goto error; } bytes_read = fread(header->data, 1, header->size, file); FCLOSE(file); if (bytes_read != header->size) { unshield_error("Failed to read from header file %i. Expected = %i, read = %i", i, header->size, bytes_read); goto error; } if (!unshield_get_common_header(header)) { unshield_error("Failed to read common header from header file %i", i); goto error; } if (version != -1) { header->major_version = version; } else if (header->common.version >> 24 == 1) { header->major_version = (header->common.version >> 12) & 0xf; } else if (header->common.version >> 24 == 2 || header->common.version >> 24 == 4) { header->major_version = (header->common.version & 0xffff); if (header->major_version != 0) header->major_version = header->major_version / 100; } #if 0 if (header->major_version < 5) header->major_version = 5; #endif unshield_trace("Version 0x%08x handled as major version %i", header->common.version, header->major_version); if (!unshield_get_cab_descriptor(header)) { unshield_error("Failed to read CAB descriptor from header file %i", i); goto error; } if (!unshield_get_file_table(header)) { unshield_error("Failed to read file table from header file %i", i); goto error; } if (!unshield_header_get_components(header)) { unshield_error("Failed to read components from header file %i", i); goto error; } if (!unshield_header_get_file_groups(header)) { unshield_error("Failed to read file groups from header file %i", i); goto error; } if (previous) previous->next = header; else previous = unshield->header_list = header; continue; error: if (header) FREE(header->data); FREE(header); iterate = false; } else iterate = false; } return (unshield->header_list != NULL); }/*}}}*/ Unshield* unshield_open(const char* filename)/*{{{*/ { return unshield_open_force_version(filename, -1); }/*}}}*/ Unshield* unshield_open_force_version(const char* filename, int version)/*{{{*/ { Unshield* unshield = NEW1(Unshield); if (!unshield) { unshield_error("Failed to allocate memory for Unshield structure"); goto error; } if (!unshield_create_filename_pattern(unshield, filename)) { unshield_error("Failed to create filename pattern"); goto error; } if (!unshield_read_headers(unshield, version)) { unshield_error("Failed to read header files"); goto error; } return unshield; error: unshield_close(unshield); return NULL; }/*}}}*/ static void unshield_free_string_buffers(Header* header) { StringBuffer* current = header->string_buffer; header->string_buffer = NULL; while (current != NULL) { StringBuffer* next = current->next; FREE(current->string); FREE(current); current = next; } } void unshield_close(Unshield* unshield)/*{{{*/ { if (unshield) { Header* header; for(header = unshield->header_list; header; ) { Header* next = header->next; int i; unshield_free_string_buffers(header); if (header->components) { for (i = 0; i < header->component_count; i++) unshield_component_destroy(header->components[i]); free(header->components); } if (header->file_groups) { for (i = 0; i < header->file_group_count; i++) unshield_file_group_destroy(header->file_groups[i]); free(header->file_groups); } if (header->file_descriptors) { for (i = 0; i < (int)header->cab.file_count; i++) FREE(header->file_descriptors[i]); free(header->file_descriptors); } FREE(header->file_table); FREE(header->data); FREE(header); header = next; } FREE(unshield->filename_pattern); free(unshield); } }/*}}}*/ unshield-1.0/lib/libunshield.h000066400000000000000000000046061221214546300164140ustar00rootroot00000000000000/* $Id$ */ #ifndef __unshield_h__ #define __unshield_h__ #include #include #define UNSHIELD_LOG_LEVEL_LOWEST 0 #define UNSHIELD_LOG_LEVEL_ERROR 1 #define UNSHIELD_LOG_LEVEL_WARNING 2 #define UNSHIELD_LOG_LEVEL_TRACE 3 #define UNSHIELD_LOG_LEVEL_HIGHEST 4 #ifdef __cplusplus extern "C" { #endif typedef struct _Unshield Unshield; /* Logging */ void unshield_set_log_level(int level); /* Open/close functions */ Unshield* unshield_open(const char* filename); Unshield* unshield_open_force_version(const char* filename, int version); void unshield_close(Unshield* unshield); /* Component functions */ typedef struct { const char* name; unsigned file_group_count; const char** file_group_names; } UnshieldComponent; int unshield_component_count (Unshield* unshield); const char* unshield_component_name (Unshield* unshield, int index); /* File group functions */ typedef struct { const char* name; unsigned first_file; unsigned last_file; } UnshieldFileGroup; int unshield_file_group_count (Unshield* unshield); UnshieldFileGroup* unshield_file_group_get (Unshield* unshield, int index); UnshieldFileGroup* unshield_file_group_find (Unshield* unshield, const char* name); const char* unshield_file_group_name (Unshield* unshield, int index); /* Directory functions */ int unshield_directory_count (Unshield* unshield); const char* unshield_directory_name (Unshield* unshield, int index); /* File functions */ int unshield_file_count (Unshield* unshield); const char* unshield_file_name (Unshield* unshield, int index); bool unshield_file_is_valid (Unshield* unshield, int index); bool unshield_file_save (Unshield* unshield, int index, const char* filename); int unshield_file_directory (Unshield* unshield, int index); size_t unshield_file_size (Unshield* unshield, int index); /** For investigation of compressed data */ bool unshield_file_save_raw(Unshield* unshield, int index, const char* filename); /** Maybe it's just gzip without size? */ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename); /** Deobfuscate a buffer. Seed is 0 at file start */ void unshield_deobfuscate(unsigned char* buffer, size_t size, unsigned* seed); #ifdef __cplusplus } #endif #endif unshield-1.0/lib/log.c000066400000000000000000000007701221214546300146640ustar00rootroot00000000000000/* $Id */ #include "log.h" #include #include /* evil static data */ static int current_log_level = UNSHIELD_LOG_LEVEL_HIGHEST; void unshield_set_log_level(int level) { current_log_level = level; } void _unshield_log(int level, const char* file, int line, const char* format, ...) { va_list ap; if (level > current_log_level) return; fprintf(stderr, "[%s:%i] ", file, line); va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "\n"); } unshield-1.0/lib/log.h000066400000000000000000000017351221214546300146730ustar00rootroot00000000000000/* $Id$ */ #ifndef __log_h__ #define __log_h__ #include "internal.h" #define UNSHIELD_LOG_LEVEL_LOWEST 0 #define UNSHIELD_LOG_LEVEL_ERROR 1 #define UNSHIELD_LOG_LEVEL_WARNING 2 #define UNSHIELD_LOG_LEVEL_TRACE 3 #define UNSHIELD_LOG_LEVEL_HIGHEST 4 #ifdef __cplusplus extern "C" { #endif void _unshield_log(int level, const char* file, int line, const char* format, ...); #define unshield_trace(format, args...) \ _unshield_log(UNSHIELD_LOG_LEVEL_TRACE,__PRETTY_FUNCTION__, __LINE__, format, ##args) #define unshield_warning(format, args...) \ _unshield_log(UNSHIELD_LOG_LEVEL_WARNING,__PRETTY_FUNCTION__, __LINE__, format, ##args) #define unshield_warning_unless(cond, format, args...) \ if (!(cond)) \ _unshield_log(UNSHIELD_LOG_LEVEL_WARNING,__PRETTY_FUNCTION__, __LINE__, format, ##args) #define unshield_error(format, args...) \ _unshield_log(UNSHIELD_LOG_LEVEL_ERROR,__PRETTY_FUNCTION__, __LINE__, format, ##args) #ifdef __cplusplus } #endif #endif unshield-1.0/lib/md5/000077500000000000000000000000001221214546300144205ustar00rootroot00000000000000unshield-1.0/lib/md5/Makefile.am000066400000000000000000000002161221214546300164530ustar00rootroot00000000000000AM_CPPFLAGS = -I.. ## create this library noinst_LTLIBRARIES = libmd5.la ## use these sources libmd5_la_SOURCES = \ md5.h md5c.c global.h unshield-1.0/lib/md5/global.h000066400000000000000000000014101221214546300160250ustar00rootroot00000000000000/* GLOBAL.H - RSAREF types and constants */ /* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ typedef unsigned int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif unshield-1.0/lib/md5/md5.h000066400000000000000000000025061221214546300152610ustar00rootroot00000000000000/* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); unshield-1.0/lib/md5/md5c.c000066400000000000000000000243071221214546300154220ustar00rootroot00000000000000/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "global.h" #include "md5.h" /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffffU) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void MD5Update (context, input, inputLen) MD5_CTX *context; /* context */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) context->count[1]++; context->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ void MD5Final (digest, context) unsigned char digest[16]; /* message digest */ MD5_CTX *context; /* context */ { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen); /* Append length (before padding) */ MD5Update (context, bits, 8); /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset ((POINTER)context, 0, sizeof (*context)); } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform (state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ MD5_memset ((POINTER)x, 0, sizeof (x)); } /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode (output, input, len) unsigned char *output; UINT4 *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ static void Decode (output, input, len) UINT4 *output; unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD5_memcpy (output, input, len) POINTER output; POINTER input; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset (output, value, len) POINTER output; int value; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } unshield-1.0/libunshield.pc.in000066400000000000000000000003651221214546300164240ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libunshield Description: Library to extract CAB files from InstallShield installers Version: @VERSION@ Libs: -L${libdir} -lunshield Cflags: -I${includedir} unshield-1.0/m4/000077500000000000000000000000001221214546300135055ustar00rootroot00000000000000unshield-1.0/m4/check_ssl.m4000066400000000000000000000040371221214546300157110ustar00rootroot00000000000000dnl @synopsis CHECK_SSL dnl dnl This macro will check various standard spots for OpenSSL including dnl a user-supplied directory. The user uses '--with-ssl' or dnl '--with-ssl=/path/to/ssl' as arguments to configure. dnl dnl If OpenSSL is found the include directory gets added to CFLAGS and dnl CXXFLAGS as well as '-DHAVE_SSL', '-lssl' & '-lcrypto' get added to dnl LIBS, and the libraries location gets added to LDFLAGS. Finally dnl 'HAVE_SSL' gets set to 'yes' for use in your Makefile.in I use it dnl like so (valid for gmake): dnl dnl HAVE_SSL = @HAVE_SSL@ dnl ifeq ($(HAVE_SSL),yes) dnl SRCS+= @srcdir@/my_file_that_needs_ssl.c dnl endif dnl dnl For bsd 'bmake' use: dnl dnl .if ${HAVE_SSL} == "yes" dnl SRCS+= @srcdir@/my_file_that_needs_ssl.c dnl .endif dnl dnl @category InstalledPackages dnl @author Mark Ethan Trostler dnl @version 2003-01-28 dnl @license AllPermissive AC_DEFUN([CHECK_SSL], [AC_MSG_CHECKING(if ssl is wanted) AC_ARG_WITH(ssl, [ --with-ssl enable ssl [will check /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr ] ], [ AC_MSG_RESULT(yes) for dir in $withval /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr; do ssldir="$dir" if test -f "$dir/include/openssl/ssl.h"; then found_ssl="yes"; CFLAGS="$CFLAGS -I$ssldir/include/openssl -DHAVE_SSL"; CXXFLAGS="$CXXFLAGS -I$ssldir/include/openssl -DHAVE_SSL"; break; fi if test -f "$dir/include/ssl.h"; then found_ssl="yes"; CFLAGS="$CFLAGS -I$ssldir/include/ -DHAVE_SSL"; CXXFLAGS="$CXXFLAGS -I$ssldir/include/ -DHAVE_SSL"; break fi done if test x_$found_ssl != x_yes; then AC_MSG_ERROR(Cannot find ssl libraries) else printf "OpenSSL found in $ssldir\n"; LIBS="$LIBS -lssl -lcrypto"; LDFLAGS="$LDFLAGS -L$ssldir/lib"; HAVE_SSL=yes fi AC_SUBST(HAVE_SSL) ], [ AC_MSG_RESULT(no) ]) ])dnl unshield-1.0/m4/check_zlib.m4000066400000000000000000000051371221214546300160520ustar00rootroot00000000000000dnl @synopsis CHECK_ZLIB() dnl dnl This macro searches for an installed zlib library. If nothing dnl was specified when calling configure, it searches first in /usr/local dnl and then in /usr. If the --with-zlib=DIR is specified, it will try dnl to find it in DIR/include/zlib.h and DIR/lib/libz.a. If --without-zlib dnl is specified, the library is not searched at all. dnl dnl If either the header file (zlib.h) or the library (libz) is not dnl found, the configuration exits on error, asking for a valid dnl zlib installation directory or --without-zlib. dnl dnl The macro defines the symbol HAVE_LIBZ if the library is found. You should dnl use autoheader to include a definition for this symbol in a config.h dnl file. Sample usage in a C/C++ source is as follows: dnl dnl #ifdef HAVE_LIBZ dnl #include dnl #endif /* HAVE_LIBZ */ dnl dnl @version $Id$ dnl @author Loic Dachary dnl AC_DEFUN([CHECK_ZLIB], # # Handle user hints # [AC_MSG_CHECKING(if zlib is wanted) AC_ARG_WITH(zlib, [ --with-zlib=DIR root directory path of zlib installation [defaults to /usr/local or /usr if not found in /usr/local] --without-zlib to disable zlib usage completely], [if test "$withval" != no ; then AC_MSG_RESULT(yes) ZLIB_HOME="$withval" else AC_MSG_RESULT(no) fi], [ AC_MSG_RESULT(yes) ZLIB_HOME=/usr/local if test ! -f "${ZLIB_HOME}/include/zlib.h" then ZLIB_HOME=/usr fi ]) # # Locate zlib, if wanted # if test -n "${ZLIB_HOME}" then ZLIB_OLD_LDFLAGS=$LDFLAGS ZLIB_OLD_CPPFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" AC_LANG_SAVE AC_LANG_C AC_CHECK_LIB(z, inflateEnd, [zlib_cv_libz=yes], [zlib_cv_libz=no]) AC_CHECK_HEADER(zlib.h, [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no]) AC_LANG_RESTORE if test "$zlib_cv_libz" = "yes" -a "$zlib_cv_zlib_h" = "yes" then # # If both library and header were found, use them # AC_CHECK_LIB(z, inflateEnd) AC_MSG_CHECKING(zlib in ${ZLIB_HOME}) AC_MSG_RESULT(ok) else # # If either header or library was not found, revert and bomb # AC_MSG_CHECKING(zlib in ${ZLIB_HOME}) LDFLAGS="$ZLIB_OLD_LDFLAGS" CPPFLAGS="$ZLIB_OLD_CPPFLAGS" AC_MSG_RESULT(failed) AC_MSG_ERROR(either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib) fi fi ]) unshield-1.0/m4/lib-ld.m4000066400000000000000000000062601221214546300151160ustar00rootroot00000000000000# lib-ld.m4 serial 1 (gettext-0.11) dnl Copyright (C) 1996-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then acl_cv_prog_gnu_ld=yes else acl_cv_prog_gnu_ld=no fi]) with_gnu_ld=$acl_cv_prog_gnu_ld ]) dnl From libtool-1.4. Sets the variable LD. AC_DEFUN([AC_LIB_PROG_LD], [AC_ARG_WITH(gnu-ld, [ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then test "$with_gnu_ld" != no && break else test "$with_gnu_ld" != yes && break fi fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) unshield-1.0/m4/lib-link.m4000066400000000000000000000556331221214546300154640ustar00rootroot00000000000000# lib-link.m4 serial 3 (gettext-0.11.3) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes undefine([Name]) undefine([NAME]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. If found, it dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" LIBS="$LIBS $LIB[]NAME" AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) undefine([Name]) undefine([NAME]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, dnl hardcode_direct, hardcode_minus_L, dnl sys_lib_search_path_spec, sys_lib_dlsearch_path_spec. AC_DEFUN([AC_LIB_RPATH], [ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" sys_lib_search_path_spec="$acl_cv_sys_lib_search_path_spec" sys_lib_dlsearch_path_spec="$acl_cv_sys_lib_dlsearch_path_spec" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE(rpath, [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_ARG_WITH([lib$1-prefix], [ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib --without-lib$1-prefix don't search for lib$1 in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) unshield-1.0/m4/lib-prefix.m4000066400000000000000000000117551221214546300160210ustar00rootroot00000000000000# lib-prefix.m4 serial 1 (gettext-0.11) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) unshield-1.0/man/000077500000000000000000000000001221214546300137405ustar00rootroot00000000000000unshield-1.0/man/Makefile.am000066400000000000000000000000601221214546300157700ustar00rootroot00000000000000man_MANS = unshield.1 EXTRA_DIST = $(man_MANS) unshield-1.0/man/unshield.1000066400000000000000000000026171221214546300156430ustar00rootroot00000000000000.TH UNSHIELD "1" "July 2004" "The SynCE project" "http://www.synce.org" .SH NAME unshield \- extract CAB files from an InstallShield installer archive .SH SYNOPSIS unshield [\-c COMPONENT] [\-d DIRECTORY] [\-D LEVEL] [\-g GROUP] [\-h] [\-j] [\-L] [\-n] [\-o] [\-O] [\-r] [\-v] [\-V] c|g|l|t|x CABFILE .SH DESCRIPTION Unshield extracts CAB files from InstallShield installers, used to install software on Microsoft Windows based machines. .SH OPTIONS .TP \fB\-c\fR COMPONENT Only list/extract this component .TP \fB\-d\fR DIRECTORY Extract files to DIRECTORY .TP \fB\-D\fR LEVEL Set debug log level 0 \- No logging (default) 1 \- Errors only 2 \- Errors and warnings 3 \- Errors, warnings and debug messages .TP \fB\-g\fR GROUP Only list/extract this file group .TP \fB\-h\fR Show help message .TP \fB\-j\fR Junk paths (do not make directories) .TP \fB\-L\fR Make file and directory names lowercase .TP \fB\-n\fR Never overwrite files .TP \fB\-o\fR Always overwrite files .TP \fB\-O\fR Use old compression .TP \fB\-r\fR Save raw data (do not decompress) .TP \fB\-v\fR Be verbose .TP \fB\-V\fR Print version information .SS "Commands:" .TP c List components .TP g List file groups .TP l List files .TP t Test files .TP x Extract files .SS "Other:" .TP CABFILE The InstallShield installer file to act upon .SH "AUTHOR" This manual page was adapted by Mark Ellis , from the skeleton generated by help2man unshield-1.0/rebuild.sh000077500000000000000000000002071221214546300151510ustar00rootroot00000000000000#!/bin/sh set -x export CFLAGS="-Wall -Werror -ggdb3" ./bootstrap && ./configure --prefix=/var/tmp/unshield --with-ssl && make install unshield-1.0/src/000077500000000000000000000000001221214546300137545ustar00rootroot00000000000000unshield-1.0/src/Makefile.am000066400000000000000000000003141221214546300160060ustar00rootroot00000000000000AM_CPPFLAGS = -I../lib LDADD = ../lib/libunshield.la bin_PROGRAMS = unshield noinst_PROGRAMS = unshield-deobfuscate unshield_SOURCES = unshield.c unshield_deobfuscate_SOURCES = unshield-deobfuscate.c unshield-1.0/src/unshield-deobfuscate.c000066400000000000000000000017701221214546300202220ustar00rootroot00000000000000#include #include #include "../lib/libunshield.h" int main(int argc, char** argv) { unsigned seed = 0; FILE* input = NULL; FILE* output = NULL; size_t size; unsigned char buffer[16384]; if (argc != 3) { fprintf(stderr, "Syntax:\n" " %s INPUT-FILE OUTPUT-FILE\n", argv[0]); exit(1); } input = fopen(argv[1], "r"); if (!input) { fprintf(stderr, "Failed to open %s for reading\n", argv[1]); exit(2); } output = fopen(argv[2], "w"); if (!output) { fprintf(stderr, "Failed to open %s for writing\n", argv[2]); exit(3); } while ((size = fread(buffer, 1, sizeof(buffer), input)) != 0) { unshield_deobfuscate(buffer, size, &seed); if (fwrite(buffer, 1, size, output) != size) { fprintf(stderr, "Failed to write %lu bytes to %s\n", (unsigned long)size, argv[2]); exit(4); } } fclose(input); fclose(output); return 0; } unshield-1.0/src/unshield.c000066400000000000000000000324211221214546300157350ustar00rootroot00000000000000/* $Id$ */ #ifdef __linux__ #define _BSD_SOURCE 1 #define _POSIX_C_SOURCE 2 #endif #include #include #include #include #include #include #include #include #include "../lib/libunshield.h" #ifdef HAVE_CONFIG_H #include "../lib/unshield_config.h" #endif #if HAVE_FNMATCH #include #endif #ifndef VERSION #define VERSION "Unknown" #endif #define FREE(ptr) { if (ptr) { free(ptr); ptr = NULL; } } typedef enum { OVERWRITE_ASK, OVERWRITE_NEVER, OVERWRITE_ALWAYS, } OVERWRITE; typedef enum { ACTION_EXTRACT, ACTION_LIST_COMPONENTS, ACTION_LIST_FILE_GROUPS, ACTION_LIST_FILES, ACTION_TEST } ACTION; typedef enum { FORMAT_NEW, FORMAT_OLD, FORMAT_RAW } FORMAT; #define DEFAULT_OUTPUT_DIRECTORY "." static const char* output_directory = DEFAULT_OUTPUT_DIRECTORY; static const char* file_group_name = NULL; static const char* component_name = NULL; static bool junk_paths = false; static bool make_lowercase = false; static bool verbose = false; static ACTION action = ACTION_EXTRACT; static OVERWRITE overwrite = OVERWRITE_ASK; static int log_level = UNSHIELD_LOG_LEVEL_LOWEST; static int exit_status = 0; static FORMAT format = FORMAT_NEW; static int is_version = -1; static const char* cab_file_name = NULL; static char* const* path_names = NULL; static int path_name_count = 0; static bool make_sure_directory_exists(const char* directory)/*{{{*/ { struct stat dir_stat; const char* p = directory; bool success = false; char* current = NULL; while (p && *p) { if ('/' == *p) p++; else if (0 == strncmp(p, "./", 2)) p+=2; else if (0 == strncmp(p, "../", 3)) p+=3; else { const char* slash = strchr(p, '/'); current = strdup(directory); if (slash) current[slash-directory] = '\0'; if (stat(current, &dir_stat) < 0) { if (mkdir(current, 0700) < 0) { fprintf(stderr, "Failed to create directory %s\n", directory); goto exit; } } p = slash; FREE(current); } } success = true; exit: FREE(current); return success; }/*}}}*/ static void show_usage(const char* name) { fprintf(stderr, "Syntax:\n" "\n" "\t%s [-c COMPONENT] [-d DIRECTORY] [-D LEVEL] [-g GROUP] [-i VERSION] [-GhlOrV] c|g|l|t|x CABFILE [FILENAME...]\n" "\n" "Options:\n" "\t-c COMPONENT Only list/extract this component\n" "\t-d DIRECTORY Extract files to DIRECTORY\n" "\t-D LEVEL Set debug log level\n" "\t 0 - No logging (default)\n" "\t 1 - Errors only\n" "\t 2 - Errors and warnings\n" "\t 3 - Errors, warnings and debug messages\n" "\t-g GROUP Only list/extract this file group\n" "\t-h Show this help message\n" "\t-i VERSION Force InstallShield version number (don't autodetect)\n" "\t-j Junk paths (do not make directories)\n" "\t-L Make file and directory names lowercase\n" "\t-O Use old compression\n" "\t-r Save raw data (do not decompress)\n" "\t-V Print copyright and version information\n" "\n" "Commands:\n" "\tc List components\n" "\tg List file groups\n" "\tl List files\n" "\tt Test files\n" "\tx Extract files\n" "\n" "Other:\n" "\tCABFILE The file to list or extract contents of\n" "\tFILENAME... Optionally specify names of specific files to extract" #if HAVE_FNMATCH " (wildcards are supported)" #endif "\n" , name); #if 0 "\t-n Never overwrite files\n" "\t-o Overwrite files WITHOUT prompting\n" "\t-v Verbose output\n" #endif } static bool handle_parameters( int argc, char* const argv[]) { int c; while ((c = getopt(argc, argv, "c:d:D:g:hi:jLnoOrV")) != -1) { switch (c) { case 'c': component_name = optarg; break; case 'd': output_directory = optarg; break; case 'D': log_level = atoi(optarg); break; case 'g': file_group_name = optarg; break; case 'i': is_version = atoi(optarg); break; case 'j': junk_paths = true; break; case 'L': make_lowercase = true; break; case 'n': overwrite = OVERWRITE_NEVER; break; case 'o': overwrite = OVERWRITE_ALWAYS; break; case 'O': format = FORMAT_OLD; break; case 'r': format = FORMAT_RAW; break; case 'v': verbose = true; break; case 'V': printf("Unshield version " VERSION ". Copyright (C) 2003-2013 David Eriksson.\n"); exit(0); break; case 'h': default: show_usage(argv[0]); return false; } } unshield_set_log_level(log_level); if (optind == argc || !argv[optind]) { fprintf(stderr, "No action provided on command line.\n\n"); show_usage(argv[0]); return false; } char action_char = argv[optind++][0]; switch (action_char) { case 'c': action = ACTION_LIST_COMPONENTS; break; case 'g': action = ACTION_LIST_FILE_GROUPS; break; case 'l': action = ACTION_LIST_FILES; break; case 't': action = ACTION_TEST; break; case 'x': action = ACTION_EXTRACT; break; default: fprintf(stderr, "Unknown action '%c' on command line.\n\n", action_char); show_usage(argv[0]); return false; } cab_file_name = argv[optind++]; if (cab_file_name == NULL) { fprintf(stderr, "No InstallShield Cabinet File name provided on command line.\n\n"); show_usage(argv[0]); return false; } path_name_count = argc - optind; path_names = &argv[optind]; return true; } static bool extract_file(Unshield* unshield, const char* prefix, int index) { bool success; char dirname[256]; char filename[256]; char* p; int directory = unshield_file_directory(unshield, index); strcpy(dirname, output_directory); strcat(dirname, "/"); if (prefix && prefix[0]) { strcat(dirname, prefix); strcat(dirname, "/"); } if (!junk_paths && directory >= 0) { const char* tmp = unshield_directory_name(unshield, directory); if (tmp && tmp[0]) { strcat(dirname, tmp); strcat(dirname, "/"); } } for (p = dirname + strlen(output_directory); *p != '\0'; p++) { switch (*p) { case '\\': *p = '/'; break; case ' ': case '<': case '>': case '[': case ']': *p = '_'; break; default: if (!isprint(*p)) *p = '_'; else if (make_lowercase) *p = tolower(*p); break;; } } #if 0 if (dirname[strlen(dirname)-1] != '/') strcat(dirname, "/"); #endif make_sure_directory_exists(dirname); snprintf(filename, sizeof(filename), "%s%s", dirname, unshield_file_name(unshield, index)); for (p = filename + strlen(dirname); *p != '\0'; p++) { if (!isprint(*p)) *p = '_'; else if (make_lowercase) *p = tolower(*p); } printf(" extracting: %s\n", filename); switch (format) { case FORMAT_NEW: success = unshield_file_save(unshield, index, filename); break; case FORMAT_OLD: success = unshield_file_save_old(unshield, index, filename); break; case FORMAT_RAW: success = unshield_file_save_raw(unshield, index, filename); break; } if (!success) { fprintf(stderr, "Failed to extract file '%s'.%s\n", unshield_file_name(unshield, index), (log_level < 3) ? "Run unshield again with -D 3 for more information." : ""); unlink(filename); exit_status = 1; } return success; } static bool should_process_file(Unshield* unshield, int index) { int i; if (path_name_count == 0) return true; for (i = 0; i < path_name_count; i++) { #if HAVE_FNMATCH if (fnmatch(path_names[i], unshield_file_name(unshield, index), 0) == 0) return true; #else if (strcmp(path_names[i], unshield_file_name(unshield, index)) == 0) return true; #endif } return false; } static int extract_helper(Unshield* unshield, const char* prefix, int first, int last)/*{{{*/ { int i; int count = 0; for (i = first; i <= last; i++) { if (unshield_file_is_valid(unshield, i) && should_process_file(unshield, i) && extract_file(unshield, prefix, i)) count++; } return count; }/*}}}*/ static bool test_file(Unshield* unshield, int index) { bool success; printf(" testing: %s\n", unshield_file_name(unshield, index)); success = unshield_file_save(unshield, index, NULL); if (!success) { fprintf(stderr, "Failed to extract file '%s'.%s\n", unshield_file_name(unshield, index), (log_level < 3) ? "Run unshield again with -D 3 for more information." : ""); exit_status = 1; } return success; } static int test_helper(Unshield* unshield, const char* prefix, int first, int last)/*{{{*/ { int i; int count = 0; for (i = first; i <= last; i++) { if (unshield_file_is_valid(unshield, i) && test_file(unshield, i)) count++; } return count; }/*}}}*/ static bool list_components(Unshield* unshield) { int i; int count = unshield_component_count(unshield); if (count < 0) return false; for (i = 0; i < count; i++) { printf("%s\n", unshield_component_name(unshield, i)); } printf("-------\n%i components\n", count); return true; } static bool list_file_groups(Unshield* unshield) { int i; int count = unshield_file_group_count(unshield); if (count < 0) return false; for (i = 0; i < count; i++) { printf("%s\n", unshield_file_group_name(unshield, i)); } printf("-------\n%i file groups\n", count); return true; } static int list_files_helper(Unshield* unshield, const char* prefix, int first, int last)/*{{{*/ { int i; int valid_count = 0; for (i = first; i <= last; i++) { char dirname[256]; if (unshield_file_is_valid(unshield, i) && should_process_file(unshield, i)) { valid_count++; if (prefix && prefix[0]) { strcpy(dirname, prefix); strcat(dirname, "\\"); } else dirname[0] = '\0'; strcat(dirname, unshield_directory_name(unshield, unshield_file_directory(unshield, i))); #if 0 for (p = dirname + strlen(output_directory); *p != '\0'; p++) if ('\\' == *p) *p = '/'; #endif if (dirname[strlen(dirname)-1] != '\\') strcat(dirname, "\\"); printf(" %8" SIZE_FORMAT " %s%s\n", unshield_file_size(unshield, i), dirname, unshield_file_name(unshield, i)); } } return valid_count; }/*}}}*/ typedef int (*ActionHelper)(Unshield* unshield, const char* prefix, int first, int last); static bool do_action(Unshield* unshield, ActionHelper helper) { int count = 0; if (component_name) { abort(); } else if (file_group_name) { UnshieldFileGroup* file_group = unshield_file_group_find(unshield, file_group_name); printf("File group: %s\n", file_group_name); if (file_group) count = helper(unshield, file_group_name, file_group->first_file, file_group->last_file); } else { int i; for (i = 0; i < unshield_file_group_count(unshield); i++) { UnshieldFileGroup* file_group = unshield_file_group_get(unshield, i); if (file_group) count += helper(unshield, file_group->name, file_group->first_file, file_group->last_file); } } printf(" -------- -------\n %i files\n", count); return true; } int main(int argc, char* const argv[]) { bool success = false; Unshield* unshield = NULL; setlocale(LC_ALL, ""); if (!handle_parameters(argc, argv)) goto exit; unshield = unshield_open_force_version(cab_file_name, is_version); if (!unshield) { fprintf(stderr, "Failed to open %s as an InstallShield Cabinet File\n", cab_file_name); goto exit; } printf("Cabinet: %s\n", cab_file_name); switch (action) { case ACTION_EXTRACT: success = do_action(unshield, extract_helper); break; case ACTION_LIST_COMPONENTS: success = list_components(unshield); break; case ACTION_LIST_FILE_GROUPS: success = list_file_groups(unshield); break; case ACTION_LIST_FILES: success = do_action(unshield, list_files_helper); break; case ACTION_TEST: if (strcmp(output_directory, DEFAULT_OUTPUT_DIRECTORY) != 0) fprintf(stderr, "Output directory (-d) option has no effect with test (t) command.\n"); if (make_lowercase) fprintf(stderr, "Make lowercase (-L) option has no effect with test (t) command.\n"); success = do_action(unshield, test_helper); break; } exit: unshield_close(unshield); if (!success) exit_status = 1; return exit_status; } unshield-1.0/travis.md000066400000000000000000000001641221214546300150200ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/twogood/unshield.png?branch=master)](https://travis-ci.org/twogood/unshield) unshield-1.0/valgrind.sh000077500000000000000000000001511221214546300153270ustar00rootroot00000000000000#!/bin/sh libtool --mode=execute valgrind --num-callers=10 --leak-check=yes `dirname $0`/src/unshield $@