pax_global_header00006660000000000000000000000064134647006600014520gustar00rootroot0000000000000052 comment=5511183c9ce042a33933d9b4cf84147d598552f7 rifiuti2-0.7.0/000077500000000000000000000000001346470066000132615ustar00rootroot00000000000000rifiuti2-0.7.0/.gitattribute000066400000000000000000000000421346470066000157650ustar00rootroot00000000000000* text eol=lf *.bat text eol=crlf rifiuti2-0.7.0/.gitignore000066400000000000000000000011441346470066000152510ustar00rootroot00000000000000**/*.exe **/*.o **/.deps **/Makefile **/Makefile.in /.dirstamp /ABOUT-NLS /aclocal.m4 /autom4te.cache /compile /config.cache /config.guess /config.h /config.h.in /config.log /config.rpath /config.status /config.sub /configure /depcomp /install-sh /m4 /missing /mkinstalldirs /po/*.gmo /po/*.header /po/*.mo /po/*.pot /po/*.sed /po/insert-header.sin /po/Makefile.in.in /po/Makevars.template /po/POTFILES /po/remove-potcdate.sin /po/Rules-quot /po/stamp-it /po/stamp-po /src/rifiuti /src/rifiuti-vista /stamp-h1 /test/atconfig /test/atlocal /test/package.m4 /test/testsuite /test/testsuite.dir /test/testsuite.log rifiuti2-0.7.0/.travis.yml000066400000000000000000000012411346470066000153700ustar00rootroot00000000000000language: c compiler: clang branches: except: - gh-pages os: - linux dist: xenial addons: apt: update: true packages: - libglib2.0-dev - libxml2-utils - autopoint before_script: - autoreconf -f -i -v script: - ./configure && make distcheck deploy: provider: releases api_key: secure: "BHyNz+01netkQ0knn17Fgj27YUnwtuu/ensNNfMgUaPiobsLHOhXg6W6PCugjCGcBldA5NeLtTf2b1ee64iyGO8Fhh6m4PE0GwkAIjWhbYHHwlvA7G9PWXVhFadXbLezH2iAVzYU8S1pC92qlBwBeBQSnKCSK9wJduaPA35Lz+k=" file: "rifiuti2-*.tar.xz" file_glob: "true" skip_cleanup: true draft: true on: tags: true rifiuti2-0.7.0/ChangeLog000066400000000000000000000002001346470066000150230ustar00rootroot00000000000000This file is intentionally left blank. ChangeLog can be inspected via git log. Announcement for users is available in NEWS.md . rifiuti2-0.7.0/Makefile.am000066400000000000000000000013751346470066000153230ustar00rootroot00000000000000# vim: set sw=4 ts=4 noexpandtab : AUTOMAKE_OPTIONS = foreign dist-xz dist-zip SUBDIRS = src po test EXTRA_DIST = \ docs \ README.md \ NEWS.md \ $(NULL) dist-hook: -find $(top_distdir) -type f \( -name '*~' -o -name '.*~' \) -print0 | xargs -0 -r rm -f # despite what manual says, I want all build auxiliary files gone MAINTAINERCLEANFILES = \ $(top_srcdir)/configure \ $(top_srcdir)/aclocal.m4 \ $(top_srcdir)/compile \ $(top_srcdir)/config.guess \ $(top_srcdir)/config.h.in \ $(top_srcdir)/config.sub \ $(top_srcdir)/depcomp \ $(top_srcdir)/install-sh \ $(top_srcdir)/Makefile.in \ $(top_srcdir)/missing \ $(NULL) distclean-local: -rm -rf win-pkg rifiuti2-0.7.0/NEWS.md000066400000000000000000000064121346470066000143620ustar00rootroot00000000000000## 0.7.0 #### Feature Addition * Support recycle bin from jurassic Windows: 95, NT4, ME (Issue #9) * Verified to work for recycle bin on network shared folder using UNC path (such thing is rare but does exist) * Display timezone in tab-delimited output header * Guess Windows version based on recycle bin artifacts * Distributed Windows binaries: * Copes better with Windows ACL, detecting folder with insufficient permissions * Attempts to detect Windows locale setting and automatically determine translation to use #### Change * Now **mandates UTF-8 locale except on Windows** * File output is also in UTF-8 encoding under Windows * `-8` option is rendered obsolete as a result * **Distributed Windows binaries can only run on Vista or above** * Windows XP/2003 support removed due to glib changes * Won't overwrite destination file if it already exists * `$Recycle.bin` version: * Not printing file size field if it is corrupt * Exit with error status whenever errors are found in any entry, not just the last entry * `INFO2` version: * Restricts the choice of legacy path character encoding; generally, all encodings not ASCII compatible are disallowed * Building requirement changes * Remove GNUism for part of build toolchain (`make`, `awk`) * Use external GNU gettext instead of obsolete `glib-gettextize` #### Bug fix * Fix unicode display on Windows console (Issue #12) * More robust handling of invalid or undecipherable characters, displaying escaped hex or unicode sequences in such cases (Issue #5) ---- ## 0.6.1 #### Bug fix * Restore old date/time format for tab-delimited output, in order to be more spreadsheet friendly (Issue #8) * Fix timezone offset for ISO8601-format date, to account for DST * Fix data retrieval on big endian systems * No more attempt to limit usage of TZ environment variable (which doesn't work anyway) ---- ## 0.6.0 #### Feature * Windows 10 recycle bin support (Issue #1) * Add GUI dialog to notify first time Windows users (Issue #2) * 8.3 path names can also be used in XML output now #### Bug fix * Win98 INFO2 trashed file size not retrieved correctly * Substantial rework on showing translation and file names in different lanuages, especially on Windows platform #### Change * Display file deletion time in UTC time zone by default * Vista version: * No more accepts multiple file arguments * Invalid file or dir in command argument treated as fatal error * Result is sorted by deletion time, instead of random order * Show version info in order to differentiate between Vista & Windows 10 formats * INFO2 version: * No more accepts standard input as input data ---- ## 0.5.1 * New manpage * Test cases added to repository * Debian packaging stuff added to repository ---- ## 0.5.0 * Complete rewrite, using glib for I18N support and unicode handling * This means INFO2 records from any localized version of Windows can be parsed correctly * Since Vista recycle bin format changed completely, there will be no INFO2 file. A new program, `rifiuti-vista`, handles such format. * Both program can output in XML format as well as tab-delimited plain text. * Can choose to output long path name or legacy one (like "Progra~1") * Some preliminary check to guard against specially crafted recycle bin files. rifiuti2-0.7.0/README.md000066400000000000000000000110751346470066000145440ustar00rootroot00000000000000| Appveyor | Travis | |----------|--------| | [![Appveyor status](https://ci.appveyor.com/api/projects/status/github/abelcheung/rifiuti2?svg=true&branch=master)](https://ci.appveyor.com/project/abelcheung/rifiuti2) | [![Travis status](https://travis-ci.org/abelcheung/rifiuti2.svg?branch=master)](https://travis-ci.org/abelcheung/rifiuti2) | ## Introduction `Rifiuti2` is a for analyzing Windows Recycle Bin INFO2 file. Analysis of Windows Recycle Bin is usually carried out during Windows computer forensics. `Rifiuti2` can extract file deletion time, original path and size of deleted files and whether the trashed files have been permanently removed. For those interested in what it does, and what functionality it provides, please [check out official site][1] for more info. Latest features and changes can be found in [NEWS file](NEWS.md). [1]: https://abelcheung.github.io/rifiuti2 ## Special note for 0.7.0 * Windows binaries will be automatically built from [Appveyor](https://www.appveyor.com/) and published to Github. * **Systems supporting UTF-8 encoding is mandatory, except on Windows console (file output is also in UTF-8).** This shouldn't be problematic though, as UTF-8 locale is pretty much standard for Linux and macOS these years. On Windows front, there are already many featureful text editors capable of opening UTF-8 unicode text files. * As a result, `-8` option is obsolete and no more affects output in any way. ## Usage `rifiuti2` is designed to be portable, and runs on command line environment. Depending on relevant Windows recycle bin format, there are 2 binaries to choose from (most users would want first one): Program | Recycle bin from OS | Purpose ---------------|---------------------|-------- `rifiuti-vista`|Vista – Win10 | Scans `\$Recycle.bin` style folder `rifiuti` |Win95 – XP/2003| Reads `INFO` or `INFO2` file in `\RECYCLED` or `\RECYCLER` folder Run programs without any option for more detail. Here are some more frequently used options: Option | Purpose :----------|:-------- `-o `| Output to file `-x` | Output XML instead of tab-separated fields `-l ` | Display legacy (8.3) filenames and specify its codepage Please consult manpage (Unix) or README.html (bundled with Windows binaries) for complete options and detailed usage description. ### Examples * `rifiuti-vista.exe -x -z -o result.xml \case\S-1-2-3\` > Scan for index files under `\case\S-1-2-3\`, adjust all deletion time > for local time zone, and write XML output to `result.xml` * `rifiuti -l CP932 -t "\n" INFO2` > Assume INFO2 file is generated from Japanese Windows (codepage 932), > and display each field line by line, instead of separated by tab ## Supported platform It has been tested on Linux, Windows 7 and FreeBSD. Some testing on big endian platforms are done with Qemu emulator. More compatibility fix for other architectures welcome. ## Download ### Windows Windows binaries are officially provided [on Github release page][6]. Note that 0.6.1 version is the last version that can run on Windows XP and 2003; upcoming versions would require Vista or above. ### Linux * DEB packages available officially on [Debian][7] and [Ubuntu][8], hence also available on most (if not all) derivatives focusing on security and forensics, such as (this is incomplete list): * [Kali Linux][9] * [Deft X Virtual Appliance][10] * BackBox Linux * RPM packages from [Linux Forensics Tools Repository (LiFTeR)][11] can be used on Fedora, and very likely CentOS and RHEL. * [ArchStrike (formerly ArchAssault)][12], a penetration testing derivative of Arch Linux, has `rifiuti2` packaged since late 2014. ### FreeBSD Official [FreeBSD port][13] is available since 8.4. ### Others (Compile from source) For OS where `rifiuti2` is not readily available, it is always possible to compile from source. `rifiuti2` follows the usual `autotools` based procedure: ```sh ./configure && make check && make install ``` Please [refer to wiki page][14] for more detail. ## License `rifiuti2` is released under BSD license. Please refer to [license file](docs/LICENSE.md) for more detail. [6]: https://github.com/abelcheung/rifiuti2/releases [7]: https://packages.debian.org/search?keywords=rifiuti2 [8]: http://packages.ubuntu.com/search?keywords=rifiuti2 [9]: https://pkg.kali.org/pkg/rifiuti2 [10]: http://www.deftlinux.net/package-list/deft-x-va/ [11]: https://forensics.cert.org/ByPackage/rifiuti2.html [12]: https://archstrike.org/packages/rifiuti2 [13]: https://www.freebsd.org/cgi/ports.cgi?query=rifiuti2 [14]: https://github.com/abelcheung/rifiuti2/wiki/Compile-From-Sourcerifiuti2-0.7.0/appveyor.bat000066400000000000000000000022721346470066000156210ustar00rootroot00000000000000@echo off :: Copyright 2018-2019 Abel Cheung :: All rights reserved. set OLDPATH=%PATH% PATH C:\msys64\%MSYSTEM%\bin;C:\msys64\usr\bin;%OLDPATH% cd %APPVEYOR_BUILD_FOLDER% goto %1 echo Unknown build target. exit 1 :build @echo on :: Build fails (unresolved dep) w/o updated msys2 runtime :-/ pacman.exe --noconfirm --noprogressbar -Syu :: Second invocation updates everything else :: Wastes too much time updating unnecessary non-core stuff :: pacman --noconfirm --noprogressbar -Syu pacman.exe --noconfirm --noprogressbar -S --needed markdown mingw-w64-%MSYS2_ARCH%-glib2 bash -lc "autoreconf -f -i -v && ./configure --enable-static && make all" @echo off goto :eof :check @echo on file.exe src\rifiuti.exe ldd.exe src\rifiuti.exe file.exe src\rifiuti-vista.exe ldd.exe src\rifiuti-vista.exe bash -lc "make check" @echo off goto :eof :package @echo on if "%APPVEYOR_REPO_TAG%" == "true" ( echo "*** Building official release ***" bash -lc "make -f dist-win.mk dist-win" ) else ( bash -lc "make -f dist-win.mk dist-win ZIPNAME=%APPVEYOR_PROJECT_SLUG%-%APPVEYOR_REPO_COMMIT:~0,8%-win-%MSYS2_ARCH%" ) @echo off goto :eof rifiuti2-0.7.0/config.rpath000066400000000000000000000000001346470066000155540ustar00rootroot00000000000000rifiuti2-0.7.0/configure.ac000066400000000000000000000111651346470066000155530ustar00rootroot00000000000000dnl vim: set sw=2 ts=2 expandtab : dnl dnl Copyright (C) 2007-2019 Abel Cheung. dnl All rights reserved. AC_PREREQ([2.69]) AC_INIT([rifiuti2], [0.7.0], [https://github.com/abelcheung/rifiuti2/issues], [], [https://abelcheung.github.io/rifiuti2/]) AC_CONFIG_SRCDIR([src/rifiuti-vista.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_TESTDIR([test]) AM_INIT_AUTOMAKE([1.11]) AC_CANONICAL_HOST dnl Platform check. AS_CASE([$host], [*-*-msys* | *-*-mingw*], [is_mingw=y ], [*-*-cygwin* ], [is_cygwin=y ], [*-*-solaris* ], [os_solaris=y]) AC_SUBST(is_mingw) AC_SUBST(is_cygwin) AM_CONDITIONAL([OS_WINDOWS], [test "x$is_mingw" != x]) dnl I18N AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.19]) LOCALEDIR_PORTABLE="${PACKAGE}-l10n" AC_SUBST([LOCALEDIR_PORTABLE]) dnl Compiler and devel toolchain checks. AS_BOX([Compiler and toolchain]) AC_PROG_CC AC_PROG_CC_STDC if test "x$ac_cv_prog_cc_c99" = "xno"; then AC_MSG_ERROR([Could not find a C99 compatible compiler]) fi dnl Always use -Wall for gcc AC_MSG_CHECKING(whether compiler understands -Wall) old_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wall" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) CFLAGS="$old_CFLAGS"]) dnl Checks for programs. AC_PROG_LN_S dnl dnl For test suite dnl AS_BOX([Test suite programs]) AC_PATH_PROG([XMLLINT],[xmllint]) dnl CP932 is commonly available among glibc, libiconv, dnl as well as solaris with extra iconv module installed AC_CACHE_CHECK([for iconv that supports more Windows codepages], [ac_cv_path_ICONV], [AC_PATH_PROGS_FEATURE_CHECK([ICONV], [iconv], [$ac_path_ICONV -f UTF-8 -t CP932 < /dev/null > /dev/null 2>&1 \ && ac_cv_path_ICONV=$ac_path_ICONV ac_path_ICONV_found=:])]) AC_SUBST([ICONV],[$ac_cv_path_ICONV]) dnl dnl Checks for libraries. dnl AS_BOX([Libraries]) dnl g_slist_free_full() requires 2.28.0, and dnl g_win32_get_command_line() needs 2.40.0 AS_VAR_SET_IF([is_mingw], [glib_req="glib-2.0 >= 2.40.0"], [glib_req="glib-2.0 >= 2.28.0"]) PKG_CHECK_MODULES([GLIB], [$glib_req],, [AC_MSG_ERROR([*** GLib not found. Error is: $GLIB_PKG_ERRORS])]) dnl dnl See if glib is linked to Solaris implementation of iconv dnl FIXME this check goes berserk under MinGW but magically works dnl after manual gcc argument reordering dnl dnl There exists solaris derivatives that can install external dnl glib2 package that links with libiconv, and they would require dnl appropriate RPATH settings. However this is exception rather than dnl the norm, and I don't have such system readily available now. dnl GLIB_RPATH=`pkg-config --libs-only-L glib-2.0 | sed -e 's#-L#-R#g'` dnl GLIB_LIBS="$GLIB_LIBS $GLIB_RPATH" AS_VAR_SET_IF([os_solaris],[dnl save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $GLIB_CFLAGS" LDFLAGS="$LDFLAGS $GLIB_LIBS $GLIB_RPATH" AC_LANG_ASSERT([C]) AC_MSG_CHECKING([iconv implementation used by glib2]) AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [return (g_iconv_open("UTF-8","CP950") == (GIConv) -1);])], [AC_MSG_RESULT([native/libiconv])], [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [return (g_iconv_open("UTF-8","646") == (GIConv) -1);])], [AC_MSG_RESULT([solaris])], [AC_MSG_RESULT([unknown]) AC_MSG_ERROR([dnl iconv() implementation used by glib2 is not recognized, which would encumber functionality of rifiuti2. Please contact maintainer if you think this is a bug.])])]) CFLAGS="$save_CFLAGS" LDFLAGS="$save_LDFLAGS" ])dnl end AS_VAR_SET_IF os_solaris AC_ARG_ENABLE(static, [AS_HELP_STRING([--enable-static], [build static binaries [default=no]])],, [enable_static=no]) dnl Need to pull in libiconv manually for mingw static build dnl And this undocumented GLIB_STATIC_COMPILATION thing... dang AS_VAR_IF([enable_static], [yes], [dnl AS_VAR_SET_IF([is_mingw], [pcfiles="glib-2.0 iconv"], [pcfiles="glib-2.0"]) GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_STATIC_COMPILATION" GLIB_LIBS="`$PKG_CONFIG --libs --static $pcfiles` $GLIB_RPATH" ]) AM_CONDITIONAL([STATIC_BUILD], [test "x$enable_static" = "xyes"]) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) dnl Checks for header files. AC_CHECK_HEADERS([errno.h inttypes.h stdio.h time.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UINT64_T if test "x$ac_cv_c_uint64_t" = "xno" || test "x$ac_cv_c_uint64_t" = "x"; then AC_MSG_ERROR([This system does not support 64 bit integers.]) fi dnl Checks for library functions. AC_CHECK_FUNCS([setlocale strerror fseek fread memcpy]) AC_CONFIG_FILES([ Makefile po/Makefile.in src/Makefile test/Makefile test/atlocal ]) AC_OUTPUT rifiuti2-0.7.0/dist-win.mk000066400000000000000000000025461346470066000153570ustar00rootroot00000000000000# vim: set sw=4 ts=4 noexpandtab : # # Make file fragment for rifiuti2 -- maintainer only # Handle binary distribution for Windows # include Makefile ZIPNAME ?= $(distdir)-win-$(build_cpu) dist-win: win-pkg-data win-pkg-bin cd win-pkg && \ rm -f $(ZIPNAME).zip && \ 7z a -bd -o$(abs_top_builddir) $(ZIPNAME).zip . win-pkg-data: win-pkg/$(LOCALEDIR_PORTABLE) win-pkg/README.html win-pkg-bin: \ win-pkg/rifiuti.exe \ win-pkg/rifiuti-vista.exe win-pkg/README.html: $(top_srcdir)/src/rifiuti.1 set -e ;\ tmpfile1=$$(mktemp) ;\ tmpfile2=$$(mktemp) ;\ groff -Thtml -mman $< | \ sed -r 's@(####CHANGELOG####)

@\n\2\n@' > $$tmpfile1 ;\ ( sed -e '0,/^##[^#]/d; /^----/,$$d;' $(abs_top_srcdir)/NEWS.md | \ markdown | sed -r 's@<(/?)h[0-9]>@<\1strong>@g;'; ) > $$tmpfile2 ;\ ( sed -e '/^####CHANGELOG####/,$$d' $$tmpfile1; cat $$tmpfile2; \ sed -e '0,/^####CHANGELOG####/d' $$tmpfile1 ) > $@ ;\ rm -f $$tmpfile1 $$tmpfile2 win-pkg/$(LOCALEDIR_PORTABLE): $(top_srcdir)/po/$(PACKAGE).pot cd po && $(MAKE) install localedir=$(abs_top_builddir)/$@ cp $< $(abs_top_builddir)/$@/ win-pkg/rifiuti.exe: $(top_builddir)/src/rifiuti.exe $(MKDIR_P) win-pkg strip --strip-unneeded -o $@ $< win-pkg/rifiuti-vista.exe: $(top_builddir)/src/rifiuti-vista.exe $(MKDIR_P) win-pkg strip --strip-unneeded -o $@ $< .PHONY: win-pkg-data win-pkg-bin dist-win rifiuti2-0.7.0/docs/000077500000000000000000000000001346470066000142115ustar00rootroot00000000000000rifiuti2-0.7.0/docs/AUTHORS000066400000000000000000000001651346470066000152630ustar00rootroot00000000000000Current version: Copyright (C) 2007-2019 Abel Cheung Original version of rifiuti: Copyright (C) 2003 Keith J. Jones rifiuti2-0.7.0/docs/LICENSE.md000066400000000000000000000044101346470066000156140ustar00rootroot00000000000000# License `rifiuti2` is released in Revised BSD License: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS *AS IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---- This project relies heavily on [Glib library][1], which is released under [LGPL license][2]. ---- This project uses [Automake] as build system, which is covered under [GPL license][2]. ---- This project also incorporates one of the files from [pyrediff project][3], which carries following license statement: Copyright (c) 2013-2017 Luke Mewburn Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. [1]: https://wiki.gnome.org/Projects/GLib [2]: https://www.gnu.org/licenses/licenses.html [3]: https://github.com/lukem/pyrediff rifiuti2-0.7.0/docs/THANKS000066400000000000000000000023541346470066000151300ustar00rootroot00000000000000Obviously, all credits must go to Keith Jones and all the folks at Foundstone. Without their analysis on Windows Recycle Bin it is much more difficult to fully dissect it. Their elaborate white paper and original version of rifiuti are available from ODESSA project: http://odessa.sourceforge.net/ There are more people to say thanks: Hilda Chan (Providing Chinese Vista Recycle Bin sample data) Anthony Wong (Providing manpage & original Debian packaging) Finally, rifiuti2 won't have extensive testing without several OSS projects and software archives: 1. winworldpc.com library, hosting many obsolete and unpurchaseable versions of Windows, especially ancient beta versions which provide insight on how Windows has evolved. 2. VirtualBox and Qemu, without their excellent virtual machine emulation it is simply impossible to test program behavior on different platforms. 3. A few website hosting obsolete service packs and ancient IE installers, relieving some pain on network access and tools installation in virtual machines: - Folks at browser.evolt.org who mirrored many ancient IE versions - Mirror for all NT service packs in sdfox7.com/winntsp.htm - There can be other website I forgot to mention rifiuti2-0.7.0/po/000077500000000000000000000000001346470066000136775ustar00rootroot00000000000000rifiuti2-0.7.0/po/ChangeLog000066400000000000000000000000001346470066000154370ustar00rootroot00000000000000rifiuti2-0.7.0/po/LINGUAS000066400000000000000000000000061346470066000147200ustar00rootroot00000000000000zh_HK rifiuti2-0.7.0/po/Makevars000066400000000000000000000065361346470066000154050ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --add-comments="TRANSLATOR" # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = # This tells whether or not to prepend "GNU " prefix to the package # name that gets inserted into the header of the $(DOMAIN).pot file. # Possible values are "yes", "no", or empty. If it is empty, try to # detect it automatically by scanning the files in $(top_srcdir) for # "GNU packagename" string. PACKAGE_GNU = no # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = https://github.com/abelcheung/rifiuti2/issues # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = # This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' # context. Possible values are "yes" and "no". Set this to yes if the # package uses functions taking also a message context, like pgettext(), or # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. USE_MSGCTXT = no # These options get passed to msgmerge. # Useful options are in particular: # --previous to keep previous msgids of translated messages, # --quiet to reduce the verbosity. MSGMERGE_OPTIONS = # These options get passed to msginit. # If you want to disable line wrapping when writing PO files, add # --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and # MSGINIT_OPTIONS. MSGINIT_OPTIONS = # This tells whether or not to regenerate a PO file when $(DOMAIN).pot # has changed. Possible values are "yes" and "no". Set this to no if # the POT file is checked in the repository and the version control # program ignores timestamps. PO_DEPENDS_ON_POT = yes # This tells whether or not to forcibly update $(DOMAIN).pot and # regenerate PO files on "make dist". Possible values are "yes" and # "no". Set this to no if the POT file and PO files are maintained # externally. DIST_DEPENDS_ON_UPDATE_PO = yes rifiuti2-0.7.0/po/POTFILES.in000066400000000000000000000000761346470066000154570ustar00rootroot00000000000000src/rifiuti-vista.c src/rifiuti.c src/utils.c src/utils-win.c rifiuti2-0.7.0/po/zh_HK.po000066400000000000000000000410521346470066000152440ustar00rootroot00000000000000# Traditional Chinese (Hong Kong) translation of rifiuti2. # Copyright (C) 2015-2019 Abel Cheung # This file is distributed under the same license as the rifiuti2 package. # Abel Cheung , 2015-2019. # msgid "" msgstr "" "Project-Id-Version: rifiuti2 0.7.0\n" "Report-Msgid-Bugs-To: https://github.com/abelcheung/rifiuti2/issues\n" "POT-Creation-Date: 2019-05-09 06:35+0800\n" "PO-Revision-Date: 2019-05-01 20:44+0800\n" "Last-Translator: Abel Cheung \n" "Language-Team: Chinese (Hong Kong)\n" "Language: zh_HK\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/rifiuti-vista.c:78 #, c-format msgid "%s(): failed to retrieve file content for '%s': %s" msgstr "%s(): 無法讀取檔案 ‘%s’ 的內容:%s" #: src/rifiuti-vista.c:91 msgid "File is truncated, or probably not a $Recycle.bin index file." msgstr "檔案被截短了,又或者根本不是 $Recycle.bin 索引檔案。" #: src/rifiuti-vista.c:111 src/rifiuti-vista.c:129 msgid "Index file expected size and real size do not match." msgstr "索引檔實際大小和預期不符。" #: src/rifiuti-vista.c:137 msgid "Unsupported file version, or probably not a $Recycle.bin index file." msgstr "檔案版本不支援,又或者根本不是 $Recycle.bin 索引檔。" #: src/rifiuti-vista.c:215 #, c-format msgid "(Record %s) Error converting unicode path to UTF-8." msgstr "(紀錄 %s) 無法將路徑轉換為 UTF-8 編碼。" #: src/rifiuti-vista.c:241 src/rifiuti.c:325 #, c-format msgid "File '%s' fails validation." msgstr "檔案 ‘%s’ 不通過檢驗。" #. TRANSLATOR: appears in help text short summary #: src/rifiuti-vista.c:303 msgid "DIR_OR_FILE" msgstr "目錄或檔案" #: src/rifiuti-vista.c:305 msgid "" "Parse index files in C:\\$Recycle.bin style folder and dump recycle bin " "data. Can also dump a single index file." msgstr "" "解析 C:\\$Recycle.bin 形式的目錄裏面的索引檔,並顯示其中的回收筒資料。也可以" "解析單一的索引檔。" #: src/rifiuti-vista.c:328 msgid "No valid recycle bin index file found." msgstr "找不到合符格式的回收筒索引檔。" #: src/rifiuti-vista.c:355 msgid "" "Index files come from multiple versions of Windows. Please check each file " "independently." msgstr "索引檔來自多個不同的 Windows 版本。請每個檔案獨立進行檢測。" #: src/rifiuti-vista.c:404 src/rifiuti.c:456 msgid "" "Some entries could not be presented as correct unicode path. The concerned " "characters are displayed in escaped unicode sequences." msgstr "" "某些項目無法顯示為正常的 unicode 路徑。有關字元會使用 unicode 碼點顯示。" #: src/rifiuti.c:84 #, c-format msgid "Error opening file '%s' for reading: %s" msgstr "無法開啟檔案 ‘%s’ 讀取內容:%s" #. TRANSLATOR COMMENT: file size must be at least 20 bytes #: src/rifiuti.c:95 #, c-format msgid "File size less than minimum allowed (%d bytes)" msgstr "檔案大小小於下限 (%d 位元組)" #: src/rifiuti.c:126 src/rifiuti.c:163 msgid "Unsupported file version, or probably not an INFO2 file at all." msgstr "檔案版本不支援,又或者根本不是 INFO2 檔案。" #: src/rifiuti.c:134 msgid "" "This INFO2 file was produced on a legacy system without Unicode file name " "(Windows ME or earlier). Please specify codepage of concerned system with '-" "l' or '--legacy-filename' option." msgstr "" "這個 INFO2 檔來自沒有 Unicode 檔名支援的古老 Windows (ME 或更早)。請用 ‘-l’ " "或 ‘--legacy-filename’ 選項指定原本的系統的編碼。" #. TRANSLATOR COMMENT: can choose example from YOUR language & code page #: src/rifiuti.c:140 msgid "" "For example, if recycle bin is expected to come from West European versions " "of Windows, use '-l CP1252' option; or in case of Japanese Windows, use '-l " "CP932'." msgstr "" "舉個例子,如果預期回收筒來自繁體中文 Windows,請使用 ‘-l CP950’ 選項;如果是" "簡體的,則用 ‘-l CP936’。" #: src/rifiuti.c:216 #, c-format msgid "Invalid drive number (0x%X) for record %u." msgstr "第 %2$u 項紀錄中的磁碟號碼 (0x%1$X) 不合法。" #: src/rifiuti.c:252 #, c-format msgid "(Record %u) Error converting legacy path to UTF-8." msgstr "(紀錄 %u) 無法將舊式路徑轉換為 UTF-8 編碼。" #: src/rifiuti.c:272 #, c-format msgid "(Record %u) Error converting unicode path to UTF-8." msgstr "(紀錄 %u) 無法將 unicode 路徑轉換為 UTF-8 編碼。" #: src/rifiuti.c:359 #, c-format msgid "Failed to read record at position %li: %s" msgstr "無法在位置 %li 讀取紀錄:%s" #: src/rifiuti.c:365 #, c-format msgid "Premature end of file, last record (%zu bytes) discarded" msgstr "檔案被截短了,最後一筆紀錄 (%zu 位元組) 被無視" #. TRANSLATOR: appears in help text short summary #: src/rifiuti.c:385 msgid "INFO2" msgstr "INFO2" #: src/rifiuti.c:387 msgid "Parse INFO2 file and dump recycle bin data." msgstr "分析 INFO2 檔案並顯示資源回收筒的內容。" #: src/rifiuti.c:417 msgid "Recycle bin file has no valid record.\n" msgstr "回收筒中沒有任何刪檔紀錄。\n" #: src/rifiuti.c:451 #, c-format msgid "" "Some entries could not be interpreted in %s encoding. The concerned " "characters are displayed in hex value instead. Very likely the (localised) " "Windows generating the recycle bin artifact does not use specified codepage." msgstr "" "某些項目無法用 %s 編碼表示;受影響的字元會改用 16 進制數值顯示。很有可能產生" "該回收筒檔案的 (本地化) Windows 並不是使用那個編碼。" #: src/utils.c:64 msgid "Windows 95" msgstr "Windows 95" #: src/utils.c:65 msgid "Windows NT 4.0" msgstr "Windows NT 4.0" #: src/utils.c:66 msgid "Windows 98" msgstr "Windows 98" #: src/utils.c:67 msgid "Windows ME" msgstr "Windows ME" #: src/utils.c:68 msgid "Windows 2000" msgstr "Windows 2000" #: src/utils.c:69 msgid "Windows XP or 2003" msgstr "Windows XP 或 2003" #: src/utils.c:70 msgid "Windows 2000, XP or 2003" msgstr "Windows 2000、XP 或 2003" #: src/utils.c:71 msgid "Windows Vista - 8.1" msgstr "Windows Vista 至 8.1" #: src/utils.c:72 msgid "Windows 10 or above" msgstr "Windows 10 或以上" #: src/utils.c:90 msgid "String to use as delimiter (TAB by default)" msgstr "作為區隔欄位用的字串 (預設為 TAB)" #: src/utils.c:90 msgid "STRING" msgstr "字串" #: src/utils.c:95 msgid "Don't show column header and metadata" msgstr "不顯示欄位標題和中繼資料" #: src/utils.c:100 msgid "(This option is deprecated)" msgstr "(此選項已經被廢置)" #: src/utils.c:109 msgid "Write output to FILE" msgstr "輸出至 <檔案>" #: src/utils.c:109 msgid "FILE" msgstr "檔案" #: src/utils.c:114 msgid "Output in XML format instead of tab-delimited values" msgstr "輸出改為 XML 模式,而非 Tab 字元分隔的文字模式" #: src/utils.c:119 msgid "Present deletion time in time zone of local system (default is UTC)" msgstr "以本系統的時區顯示檔案刪除時間 (預設為 UTC)" #: src/utils.c:125 msgid "Print version information and exit" msgstr "顯示版本資料並離開" #: src/utils.c:130 msgid "INFO2 file name" msgstr "INFO2 檔案名稱" #: src/utils.c:140 msgid "Show legacy (8.3) path if available and specify its CODEPAGE" msgstr "盡可能顯示舊式 (8.3) 檔案路徑,並指定該用哪個 <編碼頁> 處理" #: src/utils.c:141 msgid "CODEPAGE" msgstr "編碼頁" #: src/utils.c:163 msgid "Plain text format options can not be used in XML mode." msgstr "文字模式的選項不可以配合 XML 模式使用。" #: src/utils.c:251 msgid "Multiple delimiter options disallowed." msgstr "不允許使用多個區隔字串選項。" #: src/utils.c:272 msgid "Multiple output destinations disallowed." msgstr "不允許指定多個輸出檔。" #: src/utils.c:280 msgid "Empty output filename disallowed." msgstr "輸出檔名稱不允許空白" #: src/utils.c:286 msgid "Output destinations already exists." msgstr "輸出檔已經存在。" #: src/utils.c:300 #, c-format msgid "NOTE: Option '%s' is deprecated and ignored." msgstr "‘%s’ 選項已經被廢置,不會生效。" #: src/utils.c:320 msgid "Multiple encoding options disallowed." msgstr "不允許多次使用編碼選項。" #: src/utils.c:328 msgid "Empty encoding option disallowed." msgstr "編碼名稱不允許空白" #: src/utils.c:339 src/utils.c:374 #, c-format msgid "" "'%s' can't possibly be a code page or compatible encoding used by localized " "Windows." msgstr "‘%s’ 不可能是任何語言的 Windows 會採用的編碼頁或者其相容編碼" #: src/utils.c:356 #, c-format msgid "" "'%s' encoding is not supported by glib library on this system. If iconv " "program is present on system, use 'iconv -l' for a list of possible " "alternatives; otherwise check out following site for a list of probable " "encodings to use:\n" "\n" "\t%s" msgstr "" "本系統的 glib 程式庫不支援 ‘%s’ 編碼。如果系統有 iconv 程式,可執行 ‘iconv -" "l’ 列出可作為代替用的編碼;否則請瀏覽以下網站尋找可使用的編碼:\n" "\n" "\t%s" #: src/utils.c:399 msgid "Must specify exactly one file or folder argument." msgstr "必須指定剛好一個檔案或目錄作為參數。" #: src/utils.c:617 msgid "Converted path failed UTF-8 validation" msgstr "轉換後的路徑不通過 UTF-8 檢驗" #: src/utils.c:657 src/utils.c:666 msgid "Coordinated Universal Time (UTC)" msgstr "協調世界時 (UTC)" #: src/utils.c:669 src/utils-win.c:209 src/utils-win.c:219 msgid "(Failed to retrieve timezone name)" msgstr "(無法獲取時區名稱)" #. TRANSLATOR COMMENT: argument is bug report webpage #: src/utils.c:806 #, c-format msgid "Report bugs to %s" msgstr "如程式有問題,請在 %s 報告" #: src/utils.c:831 msgid "Plain text output options:" msgstr "文字模式輸出選項:" #: src/utils.c:832 msgid "Show plain text output options" msgstr "顯示和文字模式輸出有關的選項" #: src/utils.c:889 #, c-format msgid "Error parsing options: %s" msgstr "無法解析選項:%s" #: src/utils.c:971 #, c-format msgid "Error opening temp file for writing: %s" msgstr "無法開啟暫存檔來寫入資料:%s" #: src/utils.c:999 #, c-format msgid "Error opening directory '%s': %s" msgstr "無法開啟 ‘%s’ 目錄:%s" #: src/utils.c:1064 #, c-format msgid "'%s' does not exist." msgstr "‘%s’ 不存在。" #: src/utils.c:1079 #, c-format msgid "No files with name pattern '%s' are found in directory." msgstr "目錄中沒有名稱像 ‘%s’ 的檔案。" #: src/utils.c:1090 #, c-format msgid "'%s' is not a normal file or directory." msgstr "‘%s’ 不是一般檔案或目錄。" #: src/utils.c:1091 #, c-format msgid "'%s' is not a normal file." msgstr "‘%s’ 不是一般檔案。" #: src/utils.c:1112 msgid "Supplied format or arguments not in UTF-8 encoding" msgstr "所提供的格式或參數並非使用 UTF-8 編碼" #: src/utils.c:1130 #, c-format msgid "Error converting output from UTF-8 to UTF-16: %s" msgstr "無法將輸出內容從 UTF-8 轉換為 UTF-16:%s" #: src/utils.c:1182 #, c-format msgid "Recycle bin path: '%s'" msgstr "資源回收筒路徑:‘%s’" #. TRANSLATOR COMMENT: Empty folder, no file avaiable for analysis #: src/utils.c:1189 msgid "??? (empty folder)" msgstr "??? (空白目錄)" #: src/utils.c:1193 #, c-format msgid "Version: %s" msgstr "版本:%s" #: src/utils.c:1200 #, c-format msgid "Total entries ever existed: %d" msgstr "曾經回收的項目總數:%d" #: src/utils.c:1205 msgid "OS detection failed" msgstr "操作系統無法估計" #: src/utils.c:1207 #, c-format msgid "OS Guess: %s" msgstr "估計操作系統為:%s" #: src/utils.c:1230 #, c-format msgid "Time zone: %s [%s]" msgstr "時區:%s [%s]" #. TRANSLATOR COMMENT: appears in column header #: src/utils.c:1243 msgid "Index" msgstr "索引" #: src/utils.c:1243 msgid "Deleted Time" msgstr "回收時間" #: src/utils.c:1243 msgid "Size" msgstr "大小" #: src/utils.c:1243 msgid "Path" msgstr "路徑" #. TRANSLATOR COMMENT: appears in column header, means file is restored or purged #: src/utils.c:1254 msgid "Gone?" msgstr "已刪?" #: src/utils.c:1327 msgid "(File name not representable in UTF-8 encoding)" msgstr "(檔案名稱無法用 UTF-8 編碼顯示)" #: src/utils.c:1338 src/utils.c:1368 #, c-format msgid "Error formatting file deletion time for record index %s." msgstr "無法將紀錄 %s 的檔案刪除時間顯示出來。" #: src/utils.c:1350 msgid "Yes" msgstr "是" #: src/utils.c:1350 msgid "No" msgstr "否" #. TRANSLATOR COMMENT: argument is system error message #: src/utils.c:1448 #, c-format msgid "Error moving output data to desinated file: %s" msgstr "無法將輸出檔案移動到指定位置:%s" #. TRANSLATOR COMMENT: argument is temp file location #: src/utils.c:1453 #, c-format msgid "Output content is left in '%s'." msgstr "輸出內容留在 ‘%s’。" #. TRANSLATOR COMMENT: %s is software name #: src/utils.c:1464 #, c-format msgid "%s is distributed under the BSD 3-Clause License.\n" msgstr "%s 根據 3-clause BSD 使用條款發行。\n" #. TRANSLATOR COMMENT: 1st argument is software name, 2nd is official URL #: src/utils.c:1467 #, c-format msgid "" "Information about %s can be found on\n" "\n" "\t%s\n" msgstr "" "以下網站有更多有關 %s 的資料:\n" "\n" "\t%s\n" #: src/utils-win.c:53 msgid "This is a command line application" msgstr "這個是命令提示字元模式下的應用程式" #: src/utils-win.c:244 #, c-format msgid "Failed to get current user name: %s" msgstr "無法獲取目前使用者的名稱:%s" #: src/utils-win.c:257 src/utils-win.c:274 #, c-format msgid "LookupAccountName() failed: %s" msgstr "LookupAccountName() 失敗:%s" #: src/utils-win.c:311 #, c-format msgid "AuthzInitializeResourceManager() failed: %s" msgstr "AuthzInitializeResourceManager() 失敗:%s" #: src/utils-win.c:322 #, c-format msgid "Failed to retrieve Discretionary ACL info for '%s': %s" msgstr "無法獲取檔案 ‘%s’ 的 Discretionary ACL 內容:%s" #: src/utils-win.c:331 #, c-format msgid "AuthzInitializeContextFromSid() failed: %s" msgstr "AuthzInitializeContextFromSid() 失敗:%s" #: src/utils-win.c:341 #, c-format msgid "AuthzAccessCheck() failed: %s" msgstr "AuthzAccessCheck() 失敗:%s" #: src/utils-win.c:356 msgid "Error listing directory: Insufficient permission." msgstr "無法列出目錄:權限不足。" #~ msgid "Error getting metadata of file '%s': %s" #~ msgstr "無法獲取 ‘%s’ 檔案的相關資料:%s" #~ msgid "%s(): fread() failed when reading version info from '%s'" #~ msgstr "%s(): 從 ‘%s’ 讀取版本資料時,fread() 發生錯誤" #~ msgid "%s(): fread() failed when reading recordsize from '%s'" #~ msgstr "%s(): 從 ‘%s’ 讀取 recordsize 時,fread() 發生錯誤" #~ msgid "??? (version inconsistent)" #~ msgstr "??? (版本不一致)" #~ msgid "Index%sDeleted Time%sGone?%sSize%sPath" #~ msgstr "索引碼%s回收時間%s已刪?%s大小%s路徑" #~ msgid "Index%sDeleted Time%sSize%sPath" #~ msgstr "索引檔%s回收時間%s大小%s路徑" #~ msgid "" #~ "Must specify exactly one directory containing $Recycle.bin index files, " #~ "or one such index file as argument." #~ msgstr "" #~ "選項中必須指定剛好一個載有 $Recycle.bin 索引檔案的目錄,或者剛好一個這種檔" #~ "案,不多不少。" #~ msgid "Run program without any option for more info." #~ msgstr "請在執行程式時不加任何選項顯示詳情。" #~ msgid "" #~ "Error converting file name from %s encoding to UTF-8 for index %s: %s" #~ msgstr "無法將紀錄 %2$s 的檔案名稱從 %1$s 編碼轉換為 UTF-8 編碼:%3$s" #~ msgid "" #~ "File is not supported, or it is probably not a $Recycle.bin index file.\n" #~ msgstr "檔案格式不支援,又或者根本不是 $Recycle.bin 索引檔案。\n" #~ msgid "Plain text format options can not be used in XML mode.\n" #~ msgstr "文字模式的選項不可以配合 XML 模式使用。\n" #~ msgid "Invalid record size for this version of INFO2" #~ msgstr "回收筒每項紀錄的長度和這個版本的 INFO2 應有的不符" #~ msgid "Error converting path name to display for record %s: %s" #~ msgstr "無法將紀錄 %s 的檔案名稱轉換為可顯示的內容:%s" #~ msgid "" #~ "Output in XML format instead of tab-delimited values (plain text options " #~ "disallowed in this case)" #~ msgstr "" #~ "輸出改為 XML 模式,而非 Tab 字元分隔的文字模式 (這情況下不允許使用文字模式" #~ "的選項)" #~ msgid "Error formatting file deletion time for file '%s'." #~ msgstr "無法整理索引檔 ‘%s’ 中的檔案刪除時間成為可顯示的形式。" rifiuti2-0.7.0/src/000077500000000000000000000000001346470066000140505ustar00rootroot00000000000000rifiuti2-0.7.0/src/.indent.pro000066400000000000000000000010521346470066000161270ustar00rootroot00000000000000/* * GNU .indent.pro file for Rifiuti2 * Sources still need some manual edit to achieve desired * result, where tabs of any size would still look good. * - Some continuation lines have tabs partially replaced by spaces. * - Code after switch/case are indented by 2 spaces instead of a tab. */ -gnu -bfda -bli0 -bls -cbi2 -cli2 -cs -di16 -hnl -i4 -l80 -psl -ts4 -ut /* Declarations */ -T FILE -T rbin_type -T rbin_struct -T uint32_t -T uint64_t -T int64_t -T off_t /* Glib types */ -T GStatBuf -T GSList -T gboolean -T GLogLevelFlags -T gpointer rifiuti2-0.7.0/src/Makefile.am000066400000000000000000000020351346470066000161040ustar00rootroot00000000000000# vim: set sw=4 ts=4 noexpandtab : AM_CPPFLAGS = \ -I$(srcdir) \ $(GLIB_CFLAGS) \ -DLOCALEDIR=\"$(localedir)\" \ -DLOCALEDIR_PORTABLE=\"$(LOCALEDIR_PORTABLE)\" \ -DG_LOG_DOMAIN=\"$(PACKAGE)\" if STATIC_BUILD AM_LDFLAGS = -static endif bin_PROGRAMS = rifiuti rifiuti-vista man_MANS = rifiuti.1 EXTRA_DIST = rifiuti.1 COMMON_SOURCES = \ utils.c \ utils.h \ $(NULL) rifiuti_SOURCES = \ rifiuti.c \ rifiuti.h \ $(COMMON_SOURCES) rifiuti_LDADD = $(GLIB_LIBS) rifiuti_vista_SOURCES = \ rifiuti-vista.c \ rifiuti-vista.h \ $(COMMON_SOURCES) rifiuti_vista_LDADD = $(GLIB_LIBS) if OS_WINDOWS WIN_SOURCES = \ utils-win.c \ utils-win.h \ $(NULL) rifiuti_SOURCES += $(WIN_SOURCES) rifiuti_vista_SOURCES += $(WIN_SOURCES) rifiuti_LDADD += -lauthz rifiuti_vista_LDADD += -lauthz endif install-data-hook: cd $(DESTDIR)$(mandir)/man1 && $(LN_S) rifiuti.1 rifiuti-vista.1 uninstall-hook: -rm -f $(DESTDIR)$(mandir)/man1/rifiuti-vista.1 MAINTAINERCLEANFILES = $(srcdir)/Makefile.in rifiuti2-0.7.0/src/rifiuti-vista.c000066400000000000000000000275531346470066000170270ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include #include #include "utils.h" #ifdef G_OS_WIN32 # include "utils-win.h" #endif #include #include #include "rifiuti-vista.h" static r2status exit_status = EXIT_SUCCESS; static metarecord meta; /*! * Check if index file has sufficient amount of data for reading. * If successful, its file content will be stored in buf. * Return 0 if successful, non-zero on error */ static r2status validate_index_file (const char *filename, void **filebuf, gsize *bufsize, uint64_t *ver, uint32_t *pathlen) { gsize expected; int status; GError *err = NULL; char *buf; g_debug ("Start file validation for '%s'...", filename); g_return_val_if_fail ( (filename != NULL) && (*filename != '\0'), R2_ERR_INTERNAL ); g_return_val_if_fail ( (filebuf != NULL), R2_ERR_INTERNAL ); g_return_val_if_fail ( (bufsize != NULL), R2_ERR_INTERNAL ); g_return_val_if_fail ( (ver != NULL), R2_ERR_INTERNAL ); g_return_val_if_fail ( (pathlen != NULL), R2_ERR_INTERNAL ); if ( !g_file_get_contents (filename, &buf, bufsize, &err) ) { g_critical (_("%s(): failed to retrieve file content for '%s': %s"), __func__, filename, err->message); g_clear_error (&err); status = R2_ERR_OPEN_FILE; goto validation_error; } g_debug ("Retrieval of '%s' is done, size = %" G_GSIZE_FORMAT, filename, *bufsize); if (*bufsize <= VERSION1_FILENAME_OFFSET) { g_debug ("File size expected to be more than %" G_GSIZE_FORMAT, (gsize) VERSION1_FILENAME_OFFSET); g_printerr (_("File is truncated, or probably not a $Recycle.bin index file.")); g_printerr ("\n"); status = R2_ERR_BROKEN_FILE; goto validation_error; } copy_field (ver, VERSION, FILESIZE); *ver = GUINT64_FROM_LE (*ver); g_debug ("version = %" G_GUINT64_FORMAT, *ver); switch (*ver) { case VERSION_VISTA: expected = VERSION1_FILE_SIZE; /* see populate_record_data() for reason */ if ( (*bufsize != expected) && (*bufsize != expected - 1) ) { g_debug ("File size expected to be %" G_GSIZE_FORMAT " or %" G_GSIZE_FORMAT, expected, expected - 1); g_printerr (_("Index file expected size and real size do not match.")); g_printerr ("\n"); status = R2_ERR_BROKEN_FILE; goto validation_error; } *pathlen = WIN_PATH_MAX; break; case VERSION_WIN10: copy_field (pathlen, VERSION1_FILENAME, VERSION2_FILENAME); *pathlen = GUINT32_FROM_LE (*pathlen); /* Header length + file name length in UTF-16 encoding */ expected = VERSION2_FILENAME_OFFSET + (*pathlen) * 2; if (*bufsize != expected) { g_debug ("File size expected to be %" G_GSIZE_FORMAT, expected); g_printerr (_("Index file expected size and real size do not match.")); g_printerr ("\n"); status = R2_ERR_BROKEN_FILE; goto validation_error; } break; default: g_printerr (_("Unsupported file version, or probably not a $Recycle.bin index file.")); g_printerr ("\n"); status = R2_ERR_BROKEN_FILE; goto validation_error; } *filebuf = buf; return EXIT_SUCCESS; validation_error: *filebuf = NULL; return status; } static rbin_struct * populate_record_data (void *buf, uint64_t version, uint32_t pathlen, gboolean erraneous) { uint64_t win_filetime; rbin_struct *record; size_t read; record = g_malloc0 (sizeof (rbin_struct)); record->version = version; /* * In rare cases, the size of index file is 543 bytes versus (normal) 544 bytes. * In such occasion file size only occupies 56 bit, not 64 bit as it ought to be. * Actually this 56-bit file size is very likely wrong after all. Probably some * bug inside Windows. This is observed during deletion of dd.exe from Forensic * Acquisition Utilities (by George M. Garner Jr) in certain localized Vista. */ memcpy (&record->filesize, buf + FILESIZE_OFFSET, FILETIME_OFFSET - FILESIZE_OFFSET - (int) erraneous); if (erraneous) { g_debug ("filesize field broken, 56 bit only, val=0x%" G_GINT64_MODIFIER "X", record->filesize); /* not printing the value because it was wrong and misleading */ record->filesize = G_MAXUINT64; } else { record->filesize = GUINT64_FROM_LE (record->filesize); g_debug ("deleted file size = %" G_GUINT64_FORMAT, record->filesize); } /* File deletion time */ memcpy (&win_filetime, buf + FILETIME_OFFSET - (int) erraneous, VERSION1_FILENAME_OFFSET - FILETIME_OFFSET); win_filetime = GUINT64_FROM_LE (win_filetime); record->deltime = win_filetime_to_epoch (win_filetime); /* One extra char for safety, though path should have already been null terminated */ g_debug ("pathlen = %d", pathlen); switch (version) { case VERSION_VISTA: record->uni_path = conv_path_to_utf8_with_tmpl ( (const char *) (buf - erraneous + VERSION1_FILENAME_OFFSET), NULL, "<\\u%04X>", &read, &exit_status); break; case VERSION_WIN10: record->uni_path = conv_path_to_utf8_with_tmpl ( (const char *) (buf + VERSION2_FILENAME_OFFSET), NULL, "<\\u%04X>", &read, &exit_status); break; default: g_assert_not_reached (); } if (record->uni_path == NULL) { g_warning (_("(Record %s) Error converting unicode path to UTF-8."), record->index_s); record->uni_path = ""; } return record; } static void parse_record_cb (char *index_file, GSList **recordlist) { rbin_struct *record; char *basename; uint64_t version = 0; uint32_t pathlen = 0; gsize bufsize; void *buf = NULL; r2status validate_st; basename = g_path_get_basename (index_file); validate_st = validate_index_file ( index_file, &buf, &bufsize, &version, &pathlen); if ( validate_st != EXIT_SUCCESS ) { g_printerr (_("File '%s' fails validation."), basename); g_printerr ("\n"); exit_status = validate_st; goto parse_record_error; } g_debug ("Start populating record for '%s'...", basename); switch (version) { case VERSION_VISTA: /* see populate_record_data() for meaning of last parameter */ record = populate_record_data (buf, version, pathlen, (bufsize == VERSION1_FILE_SIZE - 1)); break; case VERSION_WIN10: record = populate_record_data (buf, version, pathlen, FALSE); break; default: g_assert_not_reached(); } g_debug ("Parsing done for '%s'", basename); record->index_s = basename; record->meta = &meta; *recordlist = g_slist_prepend (*recordlist, record); g_free (buf); return; parse_record_error: g_free (buf); g_free (basename); } static int sort_record_by_time (rbin_struct *a, rbin_struct *b) { /* sort primary key: deletion time; secondary key: index file name */ return ((a->deltime < b->deltime) ? -1 : (a->deltime > b->deltime) ? 1 : strcmp (a->index_s, b->index_s)); } int main (int argc, char **argv) { GSList *filelist = NULL; GSList *recordlist = NULL; GOptionContext *context; extern char **fileargs; rifiuti_init (argv[0]); /* TRANSLATOR: appears in help text short summary */ context = g_option_context_new (N_("DIR_OR_FILE")); g_option_context_set_summary (context, N_( "Parse index files in C:\\$Recycle.bin style folder " "and dump recycle bin data. Can also dump a single index file.")); rifiuti_setup_opt_ctx (&context, RECYCLE_BIN_TYPE_DIR); exit_status = rifiuti_parse_opt_ctx (&context, &argc, &argv); if (exit_status != EXIT_SUCCESS) goto cleanup; exit_status = check_file_args (fileargs[0], &filelist, RECYCLE_BIN_TYPE_DIR); if (exit_status != EXIT_SUCCESS) goto cleanup; g_slist_foreach (filelist, (GFunc) parse_record_cb, &recordlist); /* Fill in recycle bin metadata */ meta.type = RECYCLE_BIN_TYPE_DIR; meta.filename = fileargs[0]; meta.keep_deleted_entry = FALSE; meta.is_empty = (filelist == NULL); meta.has_unicode_path = TRUE; /* NULL filelist at this point means a valid empty $Recycle.bin */ if ( !meta.is_empty && (recordlist == NULL) ) { g_printerr (_("No valid recycle bin index file found.")); g_printerr ("\n"); exit_status = R2_ERR_BROKEN_FILE; goto cleanup; } recordlist = g_slist_sort (recordlist, (GCompareFunc) sort_record_by_time); /* detect global recycle bin version from versions of all files */ { GSList *l = recordlist; if (!l) meta.version = VERSION_NOT_FOUND; else { meta.version = (int64_t) ((rbin_struct *) recordlist->data)->version; while (NULL != (l = l->next)) { if ((int64_t) ((rbin_struct *) l->data)->version != meta.version) { meta.version = VERSION_INCONSISTENT; break; } } if (meta.version == VERSION_INCONSISTENT) { g_printerr (_("Index files come from multiple versions of Windows." " Please check each file independently.")); g_printerr ("\n"); exit_status = R2_ERR_BROKEN_FILE; goto cleanup; } } } /* * No attempt is made to distinguish difference for Vista - 8.1. * The corrupt filesize artifact on Vista can't be reproduced, * therefore must be very rare. */ switch (meta.version) { case VERSION_VISTA: meta.os_guess = OS_GUESS_VISTA; break; case VERSION_WIN10: meta.os_guess = OS_GUESS_10; break; default: meta.os_guess = OS_GUESS_UNKNOWN; } /* Print everything */ { r2status s = prepare_output_handle (); if (s != EXIT_SUCCESS) { exit_status = s; goto cleanup; } } print_header (meta); g_slist_foreach (recordlist, (GFunc) print_record_cb, NULL); print_footer (); close_output_handle (); /* file descriptor should have been closed at this point */ { r2status s = move_temp_file (); if ( s != EXIT_SUCCESS ) exit_status = s; } cleanup: /* Last minute error messages for accumulated non-fatal errors */ switch (exit_status) { case R2_ERR_USER_ENCODING: g_printerr (_("Some entries could not be presented as correct " "unicode path. The concerned characters are displayed " "in escaped unicode sequences.")); g_printerr ("\n"); break; default: break; } g_debug ("Cleaning up..."); g_slist_free_full (recordlist, (GDestroyNotify) free_record_cb); g_slist_free_full (filelist , (GDestroyNotify) g_free ); free_vars (); return exit_status; } rifiuti2-0.7.0/src/rifiuti-vista.h000066400000000000000000000036641346470066000170310ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _RIFIUTI_VISTA_H #define _RIFIUTI_VISTA_H #include "utils.h" #define VERSION_OFFSET 0x0 #define FILESIZE_OFFSET 0x8 #define FILETIME_OFFSET 0x10 #define VERSION1_FILENAME_OFFSET 0x18 #define VERSION2_FILENAME_OFFSET 0x1C #define VERSION1_FILE_SIZE ((VERSION1_FILENAME_OFFSET) + (WIN_PATH_MAX) * 2) #endif rifiuti2-0.7.0/src/rifiuti.1000066400000000000000000000350671346470066000156200ustar00rootroot00000000000000.\"- .\" Man page for rifiuti2 .\" .\" Copyright (c) 2008 Anthony Wong .\" Copyrgith (c) 2015 Abel Cheung .\" .\" This documentation is available under BSD 3-clause license. .\" . ie \n[www-html] \{\ .\" see groff_www(7) .BCL black #bbffee blue blue #302226 .HEAD "" .TH "RIFIUTI2 0.7.0" "1" .SH INSTALLATION ON WINDOWS \fBRifiuti2\fP is designed to run as portable Windows \fIcommand line\fP application, and no installation is required. Extract zip file onto any folder of your choice and programs are ready for use. Read sections below on how to use them. .SS Translation By default output messages of rifiuti2 are in English. The program shall be able to pick up translation automatically if user has correct Region / Language setting. This setting is under "Formats" tab of "Region and Language" (name may vary for different versions of Windows). Optionally one may use \fCLANGUAGE\fP environment variable to force using certain translation. Supported language codes are the same as existing subdirectory names under .nh \fCrifiuti2\-l10n\fP .hy folder. For example, assuming folder .nh \fCrifiuti2\-l10n\\fr\\\fP .hy exists, running following in Windows console would enable French translation: .RS \fCset LANGUAGE=fr\fP .RE The file \fCrifiuti.pot\fP in archive contains translation template for rifiuti2. Rifiuti2 makes use of \f[CB]gettext\fP for handling translation. There are lots of tutorial on internet on how to work with gettext translations; any completed translation can be submitted to main author for inclusion in next release. .SH LATEST CHANGE ####CHANGELOG#### .PP .URL https://github.com/abelcheung/rifiuti2/blob/master/NEWS.md "Changes for previous versions" are available on Github. . \} . el \{\ .TH RIFIUTI2 "1" "May 2015" "0.7.0" "MS Windows recycle bin analysis tool" .SH NAME rifiuti2 \- MS Windows recycle bin analysis tool . \} .SH SYNOPSIS .B rifiuti or .B rifiuti-vista .RB [ \-hv ] .B rifiuti .RB [ \-x " |" .RB [ \-n ] .RB [ \-t .IR delim "]]" .RB [ \-z ] .RB [ \-l .IR codepage ] .RB [ \-o .IR outfile ] .I filename .B rifiuti-vista .RB [ \-x " |" .RB [ \-n ] .RB [ \-t .IR delim "]]" .RB [ \-z ] .RB [ \-o .IR outfile ] .I file_or_directory .SH DESCRIPTION Rifiuti2 analyse recycle bin files from Windows. Analysis of Windows recycle bin is usually carried out during Windows computer forensics. Rifiuti2 can extract file deletion time, original path and size of deleted files and whether the deleted files have been moved out from the recycle bin since they are trashed. .PP Rifiuti2 supports a wide range of Windows versions, from Windows 95 to Windows 10. The command used for analysis depends on the version of Windows producing the recycle bin (\fBnot the version of users' system!\fP), which uses vastly different format before and after Vista: .PP .TP \fCrifiuti-vista\fP For Vista or later, which is located in .nh \fC\\$Recycle.bin\\\fP\fI\fP\fC\\\fP. .hy Each deleted file has its own accompanied index file remembering the original path, file size and deletion time. If original file is permanentsly deleted, so is the index file. .TP \fCrifiuti\fP For Windows 95 to XP/2003, which uses a single index file named \fCINFO2\fP (98 or above) or \fCINFO\fP (95 and NT4) under either .nh \fC\\RECYCLED\\\fP .hy (FAT 16/32) or .nh \fC\\RECYCLER\\\fP\fI\fP\fC\\\fP .hy (NTFS). This file keeps track record for deletion status and info for \fIall\fP deleted items, including those permanently removed or restored. .PP By default, both programs dump tab-delimited fields on screen, which can be viewed on screen or imported into spreadsheet program. \fB\-x\fP option instructs program to dump XML formatted content instead. .PP \fBSince 0.7.0 version\fP, rifiuti2 output is in UTF-8 encoding only, including the case of writing file under Windows. .PP Index field has different meaning for pre-Vista and post-Vista versions. INFO2 has an index number for each of deletion item indicating the chronological order of items. For Vista version, it means the index file name instead, which matches pattern \(lq$I\fBxxxxxx\fP.\fI\fP\(rq, where \fBx\fP is random alphanumeric character, and \fI\fP matches the extension of original deleted item. .PP Deleted time is represented in UTC time by default. Under tab-delimited mode, date/time is presented in format recognized by spreadsheet programs, while in XML mode ISO 8601 date/time format is used. For example, 3PM at 2014 X'mas represented in these modes would be respectively: .RS \fC2014-12-25 15:00:00\fP .br \fC2014-12-25T15:00:00Z\fP .RE .PP File size and file path are self-explanatory, but there are some special issues to take care about. Refer to \fBCAVEATS\fP section below for more detail. .SH OPTIONS .TP \fB\-o\fP, \fB\-\-output\fP=\fI\,FILE\/\fP Write output to FILE. .TP \fB\-x\fP, \fB\-\-xml\fP Output in XML format instead of tab\-delimited values. With XML mode, all plain text options are disallowed, and result is always in UTF-8 encoding. See below for plain text options. .TP \fB\-l\fP, \fB\-\-legacy\-filename\fP=\fI\,CODEPAGE\/\fP Show legacy filename if available (like \(lq\fCD:\\Progra~1\\\fP\(rq), and specify the CODEPAGE used in the Windows system producing this INFO2 file. Any encodings supported by \fBiconv\fP(1) can be used, though for maximum accuracy of file name results, it is better to stick with Microsoft codepages (such as CP850 or CP1252 for west European version, CP932 for Japanese, etc). .RS \fBNote\fP: This option is mandatory if INFO2 file is created by Windows 95, 98 or ME, since recycle bins under these OS don't contain Unicode file name. This option does not exist in \fCrifiuti-vista\fP. .RE .TP \fB\-z\fP, \fB\-\-localtime\fP Present deletion time in numeric time zone of local system running the program. By default, UTC time is displayed, which is the time value recorded in index files. Using the X'mas example above, the time for Berlin (without daylight saving time) would be \fC2014-12-25T16:00:00+0100\fP in ISO 8601 format. .RS \fBNote\fP: It is possible to use any timezone of users' choice by setting \fC$TZ\fP environment variable, though not recommended. See \fBENVIRONMENT VARIABLE\fP section below. .RE .SS PLAIN TEXT OUTPUT OPTIONS .TP \fB\-t\fP, \fB\-\-delimiter\fP=\fI\,STRING\/\fP String to use as delimiter (TAB by default). Other than normal characters, several escape sequences are also recognised: .br \fC\\r\fP (carriage return) .br \fC\\n\fP (line feed) .br \fC\\t\fP (tab) .br \fC\\e\fP (escape) .TP \fB\-n\fP, \fB\-\-no\-heading\fP Don't show recycle bin path name, metadata and field headers .TP \fB\-8\fP, \fB\-\-always\-utf8\fP (Option deprecated since 0.7.0 version) .PP .SS MISCELLANEOUS OPTIONS .TP \fB\-v\fP, \fB\-\-version\fP Print version information and exit. .TP \fB\-h\fP, \fB\-\-help\fP Show help options and exit. .TP \fB\-\-help\-all\fP Show all help options and exit. .TP \fB\-\-help\-text\fP Show plain text output options and exit. .PP .SH EXAMPLES .TP \fCrifiuti-vista \-x \-z \-o result.xml \\case\\S\-1\-2\-3\\\fP .RS Scan for index files under \\case\\S\-1\-2\-3\\, adjust all deletion time for local time zone, and write XML output to result.xml .RE .TP \fCrifiuti-vista \-n \\case\\S\-1\-2\-3\\\fP Show tab-delimited result on screen without header and metadata .TP \fCrifiuti-vista -t '\\r\\n' \\case\\S\-1\-2\-3\\$IF96NJ3.rtf\fP Only analyse a single index file and print each field in its own line .TP \fCrifiuti \-t ',' -o result.csv INFO2\fP Change tab-delimited result to comma-delimited and write to result.csv .TP \fCrifiuti \-l CP1255 \-n INFO2\fP .RS Assuming INFO2 from Hebrew version of Windows, display 8.3 file names without header and metadata .RE .SH ENVIRONMENT VARIABLES The following environment variables affect execution of program: .TP \fBLANG\fP / \fBLC_MESSAGES\fP / \fBLC_ALL\fP / \fBLANGUAGE\fP .RS Listed in order of increasing importance, these variables determine the translation to use. They belong to the group of locale environment variables. In general, these variables are already properly set up on Unix-like systems, while unused on Windows. Please consult relevant document of user's operating system for more detail. .RE .TP \fBLANG\fP / \fBLC_CTYPE\fP / \fBLC_ALL\fP .RS If recycle bin path contains non-ASCII character, these variables affect how they are displayed, in a manner similar to translation related variables described above. However it is not recommended to modify them, as since 0.7.0 version rifiuti2 no more expects any environment using non UTF-8 encoding. .RE .TP \fBRIFIUTI_DEBUG\fP .RS Setting it to any non-empty value would cause programs to print more debugging output to stderr. .RE .TP \fBTZ\fP .RS If non-empty, indicate user-specified time zone when \fB\-z\fP option is used. Normally the time zone information is obtained from system and there is no need to set this variable. However, it can be used as a facility to temporarily override timezone for some programs, which can be used for situations like constructing timeline event. .PP This value is OS dependent. For example, for timezone in Los Angeles, the value for Windows is \(lqPST8PDT\(rq, while corresponding value on Linux would be \(lqAmerica/Los_Angeles\(rq. Please consult manual for your operating system for more info. .PP Please see \fBCAVEATS\fP section below for problems when using this variable. .RE .SH EXIT STATUS Both programs return 0 on success, and greater than 0 if error occurs. .PP In particular, \fCrifiuti-vista\fP would exit with the latest non-zero status when error is encountered in \fIany\fP of the index files. .TP 1 Wrong command line argument .TP 2 Error when opening file or directory .TP 3 Recycle bin data fails basic validation .TP 4 Error when writing output to file .TP 5 User supplied wrong encoding for legacy path .SH HISTORY .PP \fIRifiuti2\fP is a rewrite of \fIrifiuti\fP, a tool of identical purpose written by Foundstone which was later purchased by McAfee. Quoting from the original FoundStone page: .RS Many computer crime investigations require the reconstruction of a subject's Recycle Bin. Since this analysis technique is executed regularly, we researched the structure of the data found in the Recycle Bin repository files (INFO2 files). Rifiuti, the Italian word meaning "trash", was developed to examine the contents of the INFO2 file in the Recycle Bin. ... Rifiuti is built to work on multiple platforms and will execute on Windows (through Cygwin), Mac OS X, Linux, and *BSD platforms. .RE .PP However, since the original rifiuti (last updated 2004) can't analyze recycle bin from any localized version of Windows (restricted to English), this rewrite effort is born to overcome the limitation. Later rifiuti2 was improved to add support for Vista format recycle bin, XML output and other extra features not available from original version. .SH CAVEATS In very special circumstance (which author can't reproduce now), index file of certain deleted item can be corrupt, causing incorrect deleted file size to be stored. There is no way to report correct size. This problem was only observed in Vista though, not any other versions of Window. .PP Non-ASCII deleted item path name may not be always displayed appropriately on console. Although great care is taken to display path name as much as possible (resorting to escaped hex .nh \fC<\\XX>\fP .hy or escaped unicode .nh \fC<\\uXXXX>\fP .hy in case of invalid or invisible characters), the font used in console might not be able to display all characters needed. Dumping result into file and open with UTF-8 capable text editor is an option. .PP It is always better to use UTC time whenever possible, because calculation of local time might not be correct, especially for non-US users. Documentation of . ie \n[www-html] \{\ .URL https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset "\fC_tzset()\fP function on Windows" . \} . el \{\ \fC_tzset()\fP function on Windows . \} has this statement: .RS The C run-time library assumes the United States' rules for implementing the calculation of daylight saving time (DST). .RE Since the difference between standard time and DST is hardcoded to be one hour (which is incorrect for a few selected regions), the file deletion time might not be correct for these regions when DST is in effect. .PP File size can mean the real size of deleted file, or the cluster size it occupies on filesystem, depending on recycle bin format. As a rule of thumb, if all sizes of entries are multiples of 512, it can be assumed the concerned sizes refer to cluster size. .SH REPORTING BUGS Report bugs to .\" The whole link and text would disappear when using .\" ascii driver, So have to use if/else . ie \n[www-html] \{\ .\" Using .IP doesn't work, URL is emitted before it .RS .URL https://github.com/abelcheung/rifiuti2/issues .RE . \} . el \{\ .IP https://github.com/abelcheung/rifiuti2/issues . \} .PP Information about rifiuti2 can be found on . ie \n[www-html] \{\ .RS .URL https://abelcheung.github.io/rifiuti2/ .RE . \} . el \{\ .IP https://abelcheung.github.io/rifiuti2/ . \} .SH SEE ALSO . ie \n[www-html] \{\ .PP .URL http://odessa.sourceforge.net/ "Open Digital Evidence Search and Seizure Architecture project" , which contains the original rifiuti tool .PP .URL https://www.blackbagtech.com/blog/2017/01/19/examining-the-windows-10-recycle-bin/ "Windows 10 Recycle Bin Index Structure" , by BlackBag Technologies .PP .URL https://pdfs.semanticscholar.org/db62/a02a2f90c569200bf37ead369221e04393d8.pdf "$Recycle.Bin Forensics for Windows 7 and Windows Vista" , by Timothy R. Leschke .PP .URL http://www.cyber-ssct.com/resources/INFO2.pdf "INFO2 recycle bin file example" , by Steve Hailey . \} . el \{\ .TP Open Digital Evidence Search and Seizure Architecture project, which contains the original rifiuti tool http://odessa.sourceforge.net/ .TP Windows 10 Recycle Bin Index Structure, by BlackBag Technologies https://www.blackbagtech.com/blog/2017/01/19/examining-the-windows-10-recycle-bin/ .TP $Recycle.Bin Forensics for Windows 7 and Windows Vista, by Timothy R. Leschke https://pdfs.semanticscholar.org/db62/a02a2f90c569200bf37ead369221e04393d8.pdf .TP INFO2 recycle bin file example, by Steve Hailey http://www.cyber-ssct.com/resources/INFO2.pdf . \} .PP .SH COPYRIGHT Part of the work of rifiuti2 is derived from Rifiuti. Both pieces of software are licensed under the simplified BSD license. .SH AUTHOR The main author of rifiuti2 is Abel Cheung .nh \fC\fP .hy .PP The original author of rifiuti is Keith J. Jones .nh \fC\fP .hy .PP Anthony Wong .nh \fC\fP .hy helped in Debian packaging and was author of the original manpage. rifiuti2-0.7.0/src/rifiuti.c000066400000000000000000000334001346470066000156670ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2003, by Keith J. Jones. * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include #include #include "utils.h" #ifdef G_OS_WIN32 # include "utils-win.h" #endif #include #include #include "rifiuti.h" static r2status exit_status = EXIT_SUCCESS; static metarecord meta; extern char *legacy_encoding; /* 0-25 => A-Z, 26 => '\', 27 or above is erraneous */ unsigned char driveletters[28] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\\', '?' }; /*! * Check if index file has sufficient amount of data for reading * 0 = success, all other return status = error * If success, infile will be set to file pointer and other args * will be filled, otherwise file pointer = NULL */ static r2status validate_index_file (const char *filename, FILE **infile) { void *buf; FILE *fp = NULL; uint32_t ver; int e, ret; g_debug ("Start file validation..."); g_return_val_if_fail ( infile != NULL, R2_ERR_INTERNAL ); *infile = NULL; if ( !(fp = g_fopen (filename, "rb")) ) { e = errno; g_printerr (_("Error opening file '%s' for reading: %s"), filename, g_strerror (e)); g_printerr ("\n"); return R2_ERR_OPEN_FILE; } buf = g_malloc (RECORD_START_OFFSET); if ( 1 > fread (buf, RECORD_START_OFFSET, 1, fp) ) { /* TRANSLATOR COMMENT: file size must be at least 20 bytes */ g_critical (_("File size less than minimum allowed (%d bytes)"), RECORD_START_OFFSET); ret = R2_ERR_BROKEN_FILE; goto validation_broken; } copy_field (&ver, VERSION, KEPT_ENTRY); ver = GUINT32_FROM_LE (ver); /* total_entry only meaningful for 95 and NT4, on other versions * it's junk memory data, don't bother copying */ if ( ( ver == VERSION_NT4 ) || ( ver == VERSION_WIN95 ) ) { copy_field (&meta.total_entry, TOTAL_ENTRY, RECORD_SIZE); meta.total_entry = GUINT32_FROM_LE (meta.total_entry); } copy_field (&meta.recordsize, RECORD_SIZE, FILESIZE_SUM); meta.recordsize = GUINT32_FROM_LE (meta.recordsize); g_free (buf); /* Turns out version is not reliable indicator. Use size instead */ switch (meta.recordsize) { case LEGACY_RECORD_SIZE: meta.has_unicode_path = FALSE; if ( ( ver != VERSION_ME_03 ) && /* ME still use 280 byte record */ ( ver != VERSION_WIN98 ) && ( ver != VERSION_WIN95 ) ) { g_printerr (_("Unsupported file version, or probably not an INFO2 file at all.")); g_printerr ("\n"); ret = R2_ERR_BROKEN_FILE; goto validation_broken; } if (!legacy_encoding) { g_printerr (_("This INFO2 file was produced on a legacy system " "without Unicode file name (Windows ME or earlier). " "Please specify codepage of concerned system with " "'-l' or '--legacy-filename' option.")); g_printerr ("\n\n"); /* TRANSLATOR COMMENT: can choose example from YOUR language & code page */ g_printerr (_("For example, if recycle bin is expected to come from West " "European versions of Windows, use '-l CP1252' option; " "or in case of Japanese Windows, use '-l CP932'.")); g_printerr ("\n"); ret = R2_ERR_ARG; goto validation_broken; } switch (ver) { case VERSION_WIN95: meta.os_guess = OS_GUESS_95; break; case VERSION_WIN98: meta.os_guess = OS_GUESS_98; break; case VERSION_ME_03: meta.os_guess = OS_GUESS_ME; break; } break; case UNICODE_RECORD_SIZE: meta.has_unicode_path = TRUE; if ( ( ver != VERSION_ME_03 ) && ( ver != VERSION_NT4 ) ) { g_printerr (_("Unsupported file version, or probably not an INFO2 file at all.")); g_printerr ("\n"); ret = R2_ERR_BROKEN_FILE; goto validation_broken; } /* guess is not complete yet for latter case, see populate_record_data */ meta.os_guess = (ver == VERSION_NT4) ? OS_GUESS_NT4 : OS_GUESS_2K_03; break; default: ret = R2_ERR_BROKEN_FILE; goto validation_broken; } rewind (fp); *infile = fp; meta.version = (int64_t) ver; return EXIT_SUCCESS; validation_broken: fclose (fp); return ret; } static rbin_struct * populate_record_data (void *buf) { rbin_struct *record; uint64_t win_filetime; uint32_t drivenum; size_t read; char *legacy_fname; record = g_malloc0 (sizeof (rbin_struct)); /* Guarantees null-termination by allocating extra byte; same goes with * unicode filename */ legacy_fname = g_malloc0 (RECORD_INDEX_OFFSET - LEGACY_FILENAME_OFFSET + 1); copy_field (legacy_fname, LEGACY_FILENAME, RECORD_INDEX); /* Index number associated with the record */ copy_field (&record->index_n, RECORD_INDEX, DRIVE_LETTER); record->index_n = GUINT32_FROM_LE (record->index_n); g_debug ("index=%u", record->index_n); /* Number representing drive letter */ copy_field (&drivenum, DRIVE_LETTER, FILETIME); drivenum = GUINT32_FROM_LE (drivenum); g_debug ("drive=%u", drivenum); if (drivenum >= sizeof (driveletters) - 1) g_warning (_("Invalid drive number (0x%X) for record %u."), drivenum, record->index_n); record->drive = driveletters[MIN (drivenum, sizeof (driveletters) - 1)]; record->emptied = FALSE; /* first byte will be removed from filename if file is not in recycle bin */ if (!*legacy_fname) { record->emptied = TRUE; *legacy_fname = record->drive; } /* File deletion time */ copy_field (&win_filetime, FILETIME, FILESIZE); win_filetime = GUINT64_FROM_LE (win_filetime); record->deltime = win_filetime_to_epoch (win_filetime); /* File size or occupied cluster size */ /* BEWARE! This is 32bit data casted to 64bit struct member */ copy_field (&record->filesize, FILESIZE, UNICODE_FILENAME); record->filesize = GUINT64_FROM_LE (record->filesize); g_debug ("filesize=%" G_GUINT64_FORMAT, record->filesize); /* * 1. Only bother populating legacy path if users need it, * because otherwise we don't know which encoding to use * 2. Enclose with angle brackets because they are not allowed * in Windows file name, therefore stands out better that * the escaped hex sequences are not part of real file name */ if (legacy_encoding) { record->legacy_path = conv_path_to_utf8_with_tmpl ( legacy_fname, legacy_encoding, "<\\%02X>", &read, &exit_status); if (record->legacy_path == NULL) { g_warning (_("(Record %u) Error converting legacy path to UTF-8."), record->index_n); record->legacy_path = ""; } } g_free (legacy_fname); if (! meta.has_unicode_path) return record; /******************************************* * Part below deals with unicode path only * *******************************************/ record->uni_path = conv_path_to_utf8_with_tmpl ( (char *) (buf + UNICODE_FILENAME_OFFSET), NULL, "<\\u%04X>", &read, &exit_status); if (record->uni_path == NULL) { g_warning (_("(Record %u) Error converting unicode path to UTF-8."), record->index_n); record->uni_path = ""; } /* * We check for junk memory filling the padding area after * unicode path, using it as the indicator of OS generating this * INFO2 file. (server 2000 / 2003) * * The padding area after legacy path is no good; experiment * shows that legacy path *always* contain non-zero bytes after * null terminator if path contains double-byte character, * regardless of OS. * * Those non-zero bytes resemble partial end of full path. * Looks like an ANSI codepage full path is filled in * legacy path field, then overwritten in place by a 8.3 * version of path whenever applicable (which was always shorter). */ if (! meta.fill_junk) { void *ptr; for (ptr = buf + UNICODE_FILENAME_OFFSET + read; ptr < buf + UNICODE_RECORD_SIZE; ptr++) { if ( *(char *) ptr != '\0' ) { g_debug ("Junk detected at offset 0x%tx of unicode path", ptr - buf - UNICODE_FILENAME_OFFSET); meta.fill_junk = TRUE; break; } } } return record; } static void parse_record_cb (char *index_file, GSList **recordlist) { rbin_struct *record; FILE *infile; size_t size; void *buf = NULL; exit_status = validate_index_file (index_file, &infile); if ( exit_status != EXIT_SUCCESS ) { g_printerr (_("File '%s' fails validation."), index_file); g_printerr ("\n"); return; } g_debug ("Start populating record for '%s'...", index_file); /* * Add padding bytes as null-termination of unicode file name. * Normally Windows should have done the null termination within * WIN_PATH_MAX limit, but on 98/ME/2000 programmers were sloppy * and use junk memory as padding, so just play safe. */ buf = g_malloc0 (meta.recordsize + sizeof(gunichar2)); fseek (infile, RECORD_START_OFFSET, SEEK_SET); meta.is_empty = TRUE; while (meta.recordsize == (size = fread (buf, 1, meta.recordsize, infile))) { record = populate_record_data (buf); record->meta = &meta; /* INFO2 already sort entries by time */ *recordlist = g_slist_append (*recordlist, record); meta.is_empty = FALSE; } g_free (buf); /* do this only when all entries are scanned */ if ( ! meta.is_empty && ( meta.os_guess == OS_GUESS_2K_03 ) ) meta.os_guess = meta.fill_junk ? OS_GUESS_2K : OS_GUESS_XP_03; if ( ferror (infile) ) { g_critical (_("Failed to read record at position %li: %s"), ftell (infile), strerror (errno)); exit_status = R2_ERR_OPEN_FILE; } if ( feof (infile) && size && ( size < meta.recordsize ) ) { g_warning (_("Premature end of file, last record (%zu bytes) discarded"), size); exit_status = R2_ERR_BROKEN_FILE; } fclose (infile); } int main (int argc, char **argv) { GSList *filelist = NULL; GSList *recordlist = NULL; GOptionContext *context; extern char **fileargs; rifiuti_init (argv[0]); /* TRANSLATOR: appears in help text short summary */ context = g_option_context_new (N_("INFO2")); g_option_context_set_summary (context, N_( "Parse INFO2 file and dump recycle bin data.")); rifiuti_setup_opt_ctx (&context, RECYCLE_BIN_TYPE_FILE); exit_status = rifiuti_parse_opt_ctx (&context, &argc, &argv); if (exit_status != EXIT_SUCCESS) goto cleanup; exit_status = check_file_args (fileargs[0], &filelist, RECYCLE_BIN_TYPE_FILE); if (exit_status != EXIT_SUCCESS) goto cleanup; /* To be overwritten in parse_record_cb() when appropriate */ meta.os_guess = OS_GUESS_UNKNOWN; /* * TODO May be silly for single file, but would be useful in future * when reading multiple files from live system */ g_slist_foreach (filelist, (GFunc) parse_record_cb, &recordlist); meta.type = RECYCLE_BIN_TYPE_FILE; meta.filename = fileargs[0]; /* * Keeping deleted entry is only available since 98 * Note: always set this variable after parse_record_cb() because * meta.version is not set beforehand */ meta.keep_deleted_entry = ( meta.version >= VERSION_WIN98 ); if ( !meta.is_empty && (recordlist == NULL) ) { g_printerr ("%s", _("Recycle bin file has no valid record.\n")); exit_status = R2_ERR_BROKEN_FILE; goto cleanup; } /* Print everything */ { r2status s = prepare_output_handle (); if (s != EXIT_SUCCESS) { exit_status = s; goto cleanup; } } print_header (meta); g_slist_foreach (recordlist, (GFunc) print_record_cb, NULL); print_footer (); close_output_handle (); /* file descriptor should have been closed at this point */ { r2status s = move_temp_file (); if ( s != EXIT_SUCCESS ) exit_status = s; } cleanup: /* Last minute error messages for accumulated non-fatal errors */ switch (exit_status) { case R2_ERR_USER_ENCODING: if (legacy_encoding) { g_printerr (_("Some entries could not be interpreted in %s encoding." " The concerned characters are displayed in hex value instead." " Very likely the (localised) Windows generating the recycle bin " "artifact does not use specified codepage."), legacy_encoding); } else { g_printerr (_("Some entries could not be presented as correct " "unicode path. The concerned characters are displayed " "in escaped unicode sequences.")); } g_printerr ("\n"); break; default: break; } g_debug ("Cleaning up..."); g_slist_free_full (recordlist, (GDestroyNotify) free_record_cb); g_slist_free_full (filelist , (GDestroyNotify) g_free ); free_vars (); return exit_status; } rifiuti2-0.7.0/src/rifiuti.h000066400000000000000000000046531346470066000157040ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2003, by Keith J. Jones. * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _RIFIUTI_H #define _RIFIUTI_H #include "utils.h" /* These offsets are relative to file start */ #define VERSION_OFFSET 0 #define KEPT_ENTRY_OFFSET 4 #define TOTAL_ENTRY_OFFSET 8 #define RECORD_SIZE_OFFSET 12 #define FILESIZE_SUM_OFFSET 16 #define RECORD_START_OFFSET 20 /* Following offsets are relative to start of each record */ #define LEGACY_FILENAME_OFFSET 0x0 #define RECORD_INDEX_OFFSET WIN_PATH_MAX #define DRIVE_LETTER_OFFSET ((WIN_PATH_MAX) + 4) #define FILETIME_OFFSET ((WIN_PATH_MAX) + 8) #define FILESIZE_OFFSET ((WIN_PATH_MAX) + 16) #define UNICODE_FILENAME_OFFSET ((WIN_PATH_MAX) + 20) #define LEGACY_RECORD_SIZE ((WIN_PATH_MAX) + 20) /* 280 bytes */ #define UNICODE_RECORD_SIZE ((WIN_PATH_MAX) * 3 + 20) /* 800 bytes */ #endif rifiuti2-0.7.0/src/utils-win.c000066400000000000000000000277371346470066000161670ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2015-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include "utils-win.h" #include #include #include #include #include #include HANDLE wincon_fh = NULL; /* GUI message box */ void gui_message (const char *message) { gunichar2 *title, *body; GError *error = NULL; title = g_utf8_to_utf16 (_("This is a command line application"), -1, NULL, NULL, &error); if (error) { g_clear_error (&error); title = g_utf8_to_utf16 ("This is a command line application", -1, NULL, NULL, NULL); } body = g_utf8_to_utf16 (message, -1, NULL, NULL, &error); if (error) { g_clear_error (&error); body = g_utf8_to_utf16 ("(Original message failed to be displayed in UTF-16)", -1, NULL, NULL, NULL); } /* Takes advantage of the fact that LPCWSTR (wchar_t) is actually 16bit on Windows */ MessageBoxW (NULL, (LPCWSTR) body, (LPCWSTR) title, MB_OK | MB_ICONINFORMATION | MB_TOPMOST); g_free (title); g_free (body); } /*! * A copy of latter part of g_win32_getlocale() */ #ifndef SUBLANG_SERBIAN_LATIN_BA #define SUBLANG_SERBIAN_LATIN_BA 0x06 #endif static const char * get_win32_locale_script (int primary, int sub) { switch (primary) { case LANG_AZERI: switch (sub) { case SUBLANG_AZERI_LATIN: return "@Latn"; case SUBLANG_AZERI_CYRILLIC: return "@Cyrl"; } break; case LANG_SERBIAN: /* LANG_CROATIAN == LANG_SERBIAN */ switch (sub) { case SUBLANG_SERBIAN_LATIN: case SUBLANG_SERBIAN_LATIN_BA: /* Serbian (Latin) - Bosnia and Herzegovina */ return "@Latn"; } break; case LANG_UZBEK: switch (sub) { case SUBLANG_UZBEK_LATIN: return "@Latn"; case SUBLANG_UZBEK_CYRILLIC: return "@Cyrl"; } break; } return NULL; } /*! * We can't use [`g_win32_getlocale()`][1] directly. * * There are 3 possible source for language UI settings: * - [`GetThreadLocale()`][2] (used by g_win32_getlocale) * - User default language * - System default language * * For GUI applications, thread locale is good enough; this is the * default for gettext and glib on Windows. But rifiuti2 is a CLI * program, where the caller is a console. In such case thread locale * is solely determined by console code page, not always equal to user * preferred language. * * For example, multiple West European Windows use console codepage 850, * which GetLocaleInfo() returns en_US, not any West European languages. * * Here we attempt to pick up user default first, followed by thread * locale; and do the dirty work in a manner almost identical to * g_win32_getlocale(). * * [1]: https://developer.gnome.org/glib/stable/glib-Windows-Compatibility-Functions.html#g-win32-getlocale * [2]: https://docs.microsoft.com/en-us/windows/desktop/api/winnls/nf-winnls-getthreadlocale */ char * get_win32_locale (void) { LCID lcid; LANGID langid; char *ev; char iso639[10]; char iso3166[10]; const char *script; /* Allow user overriding locale env */ if (((ev = getenv ("LC_ALL")) != NULL && ev[0] != '\0') || ((ev = getenv ("LC_MESSAGES")) != NULL && ev[0] != '\0') || ((ev = getenv ("LANG")) != NULL && ev[0] != '\0')) return g_strdup (ev); lcid = LOCALE_USER_DEFAULT; if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME , iso639 , sizeof (iso639)) || !GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166))) { lcid = GetThreadLocale(); if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME , iso639 , sizeof (iso639)) || !GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166))) return g_strdup ("C"); } /* Strip off the sorting rules, keep only the language part. */ langid = LANGIDFROMLCID (lcid); /* Get script based on language and territory */ script = get_win32_locale_script (PRIMARYLANGID (langid), SUBLANGID (langid)); return g_strconcat (iso639, "_", iso3166, script, NULL); } /*! * `strftime()` on Windows can show garbage timezone name, because its * encoding does not match console codepage. For example, strftime %Z result * is in CP936 encoding for zh-HK, while console codepage is CP950. * * OTOH, `wcsftime() %Z` would not return anything if console codepage is * set to any non-default codepage for current system. * * `GetTimeZoneInformation()` returns sensible result regardless of * console codepage setting. */ char * get_win_timezone_name (void) { TIME_ZONE_INFORMATION tzinfo; wchar_t *name; DWORD id; char *ret; GError *err = NULL; id = GetTimeZoneInformation (&tzinfo); switch (id) { case TIME_ZONE_ID_UNKNOWN: case TIME_ZONE_ID_STANDARD: name = tzinfo.StandardName; break; case TIME_ZONE_ID_DAYLIGHT: name = tzinfo.DaylightName; break; default: ret = g_win32_error_message (GetLastError ()); g_critical ("%s", ret); g_free (ret); return g_strdup (_("(Failed to retrieve timezone name)")); break; } ret = g_utf16_to_utf8 ( (const gunichar2 *) name, -1, NULL, NULL, &err); if (err == NULL) return ret; g_warning ("%s", err->message); g_error_free (err); return g_strdup (_("(Failed to retrieve timezone name)")); } /*! * Retrieve current user name and convert it to SID * * Following functions originates from [example of `GetEffectiveRightsFromAcl()`][1], * which is not about the function itself but a _replacement_ of it (shrug). * * [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa446637(v=vs.85).aspx */ static PSID get_user_sid (void) { gboolean status; char username[UNLEN + 1], *errmsg; DWORD err = 0, bufsize = UNLEN + 1, sidsize = 0, domainsize = 0; PSID sid; LPTSTR domainname; SID_NAME_USE sidtype; if ( !GetUserName (username, &bufsize) ) { errmsg = g_win32_error_message (GetLastError()); g_critical (_("Failed to get current user name: %s"), errmsg); goto getsid_fail; } status = LookupAccountName (NULL, username, NULL, &sidsize, NULL, &domainsize, &sidtype); if ( !status ) err = GetLastError(); g_debug ("1st LookupAccountName(): status = %d", (int) status); if ( err != ERROR_INSUFFICIENT_BUFFER ) { errmsg = g_win32_error_message (err); g_critical (_("LookupAccountName() failed: %s"), errmsg); goto getsid_fail; } sid = (PSID) g_malloc (sidsize); domainname = (LPTSTR) g_malloc (domainsize); status = LookupAccountName (NULL, username, sid, &sidsize, domainname, &domainsize, &sidtype); err = status ? 0 : GetLastError(); g_debug ("2nd LookupAccountName(): status = %d", (int) status); g_free (domainname); /* unused */ if ( status != 0 ) return sid; /* success */ errmsg = g_win32_error_message (err); g_critical (_("LookupAccountName() failed: %s"), errmsg); g_free (sid); getsid_fail: g_free (errmsg); return NULL; } /*! * Fetch ACL access mask using Authz API */ gboolean can_list_win32_folder (const char *path) { char *errmsg = NULL; gunichar2 *wpath; gboolean ret = FALSE; PSID sid; DWORD dw, dw2; PSECURITY_DESCRIPTOR sec_desc; ACCESS_MASK mask; AUTHZ_RESOURCE_MANAGER_HANDLE authz_manager; AUTHZ_CLIENT_CONTEXT_HANDLE authz_ctxt = NULL; AUTHZ_ACCESS_REQUEST authz_req = { MAXIMUM_ALLOWED, NULL, NULL, 0, NULL }; AUTHZ_ACCESS_REPLY authz_reply; if ( NULL == ( sid = get_user_sid() ) ) return FALSE; wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL); if (wpath == NULL) return FALSE; if ( !AuthzInitializeResourceManager (AUTHZ_RM_FLAG_NO_AUDIT, NULL, NULL, NULL, NULL, &authz_manager) ) { errmsg = g_win32_error_message (GetLastError()); g_printerr (_("AuthzInitializeResourceManager() failed: %s"), errmsg); g_printerr ("\n"); goto traverse_fail; } dw = GetNamedSecurityInfoW ((wchar_t *)wpath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &sec_desc); if ( dw != ERROR_SUCCESS ) { errmsg = g_win32_error_message (dw); g_printerr (_("Failed to retrieve Discretionary ACL info for '%s': %s"), path, errmsg); g_printerr ("\n"); goto traverse_getacl_fail; } if ( !AuthzInitializeContextFromSid (0, sid, authz_manager, NULL, (LUID) {0} /* unused */, NULL, &authz_ctxt) ) { errmsg = g_win32_error_message (GetLastError()); g_printerr (_("AuthzInitializeContextFromSid() failed: %s"), errmsg); g_printerr ("\n"); goto traverse_getacl_fail; } authz_reply = (AUTHZ_ACCESS_REPLY) { 1, &mask, &dw2, &dw }; /* last 2 param unused */ if ( !AuthzAccessCheck (0, authz_ctxt, &authz_req, NULL, sec_desc, NULL, 0, &authz_reply, NULL ) ) { errmsg = g_win32_error_message (GetLastError()); g_printerr (_("AuthzAccessCheck() failed: %s"), errmsg); g_printerr ("\n"); } else { /* * We only need permission to list directory; even directory traversal is * not needed, because we are going to access the files directly later. * Unlike Unix, no read permission on parent folder is needed to list * files within. */ if ( (mask & FILE_LIST_DIRECTORY) == FILE_LIST_DIRECTORY && (mask & FILE_READ_EA) == FILE_READ_EA ) ret = TRUE; else { g_printerr (_("Error listing directory: Insufficient permission.")); g_printerr ("\n"); } /* use glib type to avoid including more header */ g_debug ("Access Mask hex for '%s': 0x%X", path, (guint32) mask); } AuthzFreeContext (authz_ctxt); traverse_getacl_fail: LocalFree (sec_desc); AuthzFreeResourceManager (authz_manager); traverse_fail: g_free (sid); g_free (errmsg); g_free (wpath); return ret; } /*! * Initialize console handle under Windows * * Used only when output is Windows native console. For all other cases * unix-style file stream is used. */ gboolean init_wincon_handle (void) { HANDLE h = GetStdHandle (STD_OUTPUT_HANDLE); /* * FILE_TYPE_CHAR only happens when output is a native Windows cmd * console. For Cygwin and Msys shell environments (and output redirection), * GetFileType() would return FILE_TYPE_PIPE. In those cases printf * family outputs UTF-8 data properly. Only Windows console needs to be * dealt with using wide char API. */ if (GetFileType (h) == FILE_TYPE_CHAR) { wincon_fh = h; return TRUE; } return FALSE; } void close_wincon_handle (void) { if (wincon_fh != NULL) CloseHandle (wincon_fh); return; } gboolean puts_wincon (const wchar_t *wstr) { g_return_val_if_fail (wstr != NULL, FALSE); g_return_val_if_fail (wincon_fh != NULL, FALSE); if (WriteConsoleW (wincon_fh, wstr, wcslen (wstr), NULL, NULL)) return TRUE; else return FALSE; } rifiuti2-0.7.0/src/utils-win.h000066400000000000000000000040031346470066000161510ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _RIFIUTI_UTILS_WIN_H #define _RIFIUTI_UTILS_WIN_H #include void gui_message (const char *message ); char * get_win32_locale (void); char * get_win_timezone_name (void); gboolean can_list_win32_folder (const char *dir ); gboolean init_wincon_handle (void); void close_wincon_handle (void); gboolean puts_wincon (const wchar_t *wstr ); #endif rifiuti2-0.7.0/src/utils.c000066400000000000000000001102031346470066000153510ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include #include #include #if HAVE_SETLOCALE #include #endif #include "utils.h" #include #include #ifdef G_OS_WIN32 # include # include "utils-win.h" #endif /* These aren't intended for public */ #define DECL_OPT_CALLBACK(func) \ gboolean func (const gchar *opt_name, \ const gchar *value, \ gpointer data, \ GError **err) static DECL_OPT_CALLBACK(_check_legacy_encoding); static DECL_OPT_CALLBACK(_set_output_path); static DECL_OPT_CALLBACK(_option_deprecated); static DECL_OPT_CALLBACK(_set_opt_delim); static DECL_OPT_CALLBACK(_set_opt_noheading); static DECL_OPT_CALLBACK(_set_output_xml); /* WARNING: MUST match order of _os_guess enum */ static char *os_strings[] = { N_("Windows 95"), N_("Windows NT 4.0"), N_("Windows 98"), N_("Windows ME"), N_("Windows 2000"), N_("Windows XP or 2003"), N_("Windows 2000, XP or 2003"), N_("Windows Vista - 8.1"), N_("Windows 10 or above") }; static int output_mode = OUTPUT_NONE; static gboolean no_heading = FALSE; static gboolean use_localtime = FALSE; char *delim = NULL; char *legacy_encoding = NULL; /*!< INFO2 only, or upon request */ char *output_loc = NULL; char *tmppath = NULL; /*!< used iff output_loc is defined */ char **fileargs = NULL; FILE *out_fh = NULL; /*!< unused for Windows console */ /*! These options are only effective for tab delimited mode output */ static const GOptionEntry text_options[] = { { "delimiter", 't', 0, G_OPTION_ARG_CALLBACK, _set_opt_delim, N_("String to use as delimiter (TAB by default)"), N_("STRING") }, { "no-heading", 'n', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, _set_opt_noheading, N_("Don't show column header and metadata"), NULL }, { "always-utf8", '8', G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, _option_deprecated, N_("(This option is deprecated)"), NULL }, {NULL} }; static const GOptionEntry main_options[] = { { "output", 'o', 0, G_OPTION_ARG_CALLBACK, _set_output_path, N_("Write output to FILE"), N_("FILE") }, { "xml", 'x', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, _set_output_xml, N_("Output in XML format instead of tab-delimited values"), NULL }, { "localtime", 'z', 0, G_OPTION_ARG_NONE, &use_localtime, N_("Present deletion time in time zone of local system (default is UTC)"), NULL }, { "version", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (GOptionArgFunc) print_version_and_exit, N_("Print version information and exit"), NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &fileargs, N_("INFO2 file name"), NULL }, {NULL} }; /*! Appended to main option group if program is INFO2 reader */ const GOptionEntry rbinfile_options[] = { { "legacy-filename", 'l', 0, G_OPTION_ARG_CALLBACK, _check_legacy_encoding, N_("Show legacy (8.3) path if available and specify its CODEPAGE"), N_("CODEPAGE") }, {NULL} }; /* * Option handling related routines */ static gboolean _set_output_mode (int mode, GError **err) { if (output_mode == mode) return TRUE; if (output_mode == OUTPUT_NONE) { output_mode = mode; return TRUE; } g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Plain text format options can not be used in XML mode.")); return FALSE; } static gboolean _set_output_xml (const gchar *opt_name, const gchar *value, gpointer data, GError **err) { return _set_output_mode (OUTPUT_XML, err); } static gboolean _set_opt_noheading (const gchar *opt_name, const gchar *value, gpointer data, GError **err) { no_heading = TRUE; return _set_output_mode (OUTPUT_CSV, err); } /*! * single/double quotes and backslashes have already been * quoted / unquoted when parsing arguments. We need to * interpret \\r, \\n etc separately */ static char * _filter_escapes (const char *str) { GString *result, *debug_str; char *i = (char *) str; g_return_val_if_fail ( (str != NULL) && (*str != '\0'), NULL); result = g_string_new (NULL); do { if ( *i != '\\' ) { result = g_string_append_c (result, *i); continue; } switch ( *(++i) ) { case 'r': result = g_string_append_c (result, '\r'); break; case 'n': result = g_string_append_c (result, '\n'); break; case 't': result = g_string_append_c (result, '\t'); break; case 'e': result = g_string_append_c (result, '\x1B'); break; default: result = g_string_append_c (result, '\\'); i--; } } while ( *(++i) ); debug_str = g_string_new ("filtered delimiter = "); i = result->str; do { if ( *i >= 0x20 && *i <= 0x7E ) /* problem during linking with g_ascii_isprint */ debug_str = g_string_append_c (debug_str, *i); else g_string_append_printf (debug_str, "\\x%02X", *(unsigned char *) i); } while ( *(++i) ); g_debug ("%s", debug_str->str); g_string_free (debug_str, TRUE); return g_string_free (result, FALSE); } static gboolean _set_opt_delim (const gchar *opt_name, const gchar *value, gpointer data, GError **err) { static gboolean seen = FALSE; if (seen) { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Multiple delimiter options disallowed.")); return FALSE; } seen = TRUE; delim = (*value) ? _filter_escapes (value) : g_strdup (""); return _set_output_mode (OUTPUT_CSV, err); } static gboolean _set_output_path (const gchar *opt_name, const gchar *value, gpointer data, GError **err) { static gboolean seen = FALSE; if (seen) { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Multiple output destinations disallowed.")); return FALSE; } seen = TRUE; if ( *value == '\0' ) { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Empty output filename disallowed.")); return FALSE; } if (g_file_test (value, G_FILE_TEST_EXISTS)) { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Output destinations already exists.")); return FALSE; } output_loc = g_strdup (value); return TRUE; } static gboolean _option_deprecated (const gchar *opt_name, const gchar *unused, gpointer data, GError **err) { g_printerr (_("NOTE: Option '%s' is deprecated and ignored."), opt_name); g_printerr ("\n"); return TRUE; } static gboolean _check_legacy_encoding (const gchar *opt_name, const gchar *enc, gpointer data, GError **err) { char *s; gint e; gboolean ret = FALSE; static gboolean seen = FALSE; GError *conv_err = NULL; if (seen) { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Multiple encoding options disallowed.")); return FALSE; } seen = TRUE; if ( *enc == '\0' ) { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Empty encoding option disallowed.")); return FALSE; } s = g_convert ("C:\\", -1, "UTF-8", enc, NULL, NULL, &conv_err); if (conv_err == NULL) { if (strcmp ("C:\\", s) != 0) /* e.g. EBCDIC based code pages */ { g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("'%s' can't possibly be a code page or compatible " "encoding used by localized Windows."), enc); } else { legacy_encoding = g_strdup (enc); ret = TRUE; } goto done_check_encoding; } e = conv_err->code; g_clear_error (&conv_err); switch (e) { case G_CONVERT_ERROR_NO_CONVERSION: g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("'%s' encoding is not supported by glib library " "on this system. If iconv program is present on " "system, use 'iconv -l' for a list of possible " "alternatives; otherwise check out following site for " "a list of probable encodings to use:\n\n\t%s"), enc, #ifdef G_OS_WIN32 "https://github.com/win-iconv/win-iconv/blob/master/win_iconv.c" #else "https://www.gnu.org/software/libiconv/" #endif ); break; /* Encodings not ASCII compatible can't possibly be ANSI/OEM code pages */ case G_CONVERT_ERROR_ILLEGAL_SEQUENCE: case G_CONVERT_ERROR_PARTIAL_INPUT: g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("'%s' can't possibly be a code page or compatible " "encoding used by localized Windows."), enc); break; default: g_assert_not_reached (); } done_check_encoding: g_free (s); return ret; } static gboolean _count_fileargs (GOptionContext *context, GOptionGroup *group, gpointer data, GError **err) { if (fileargs && g_strv_length (fileargs) == 1) return TRUE; /* FIXME unable to pull user data, so only print generic mesg */ g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Must specify exactly one file or folder argument.")); /* _("Must specify exactly one INFO2 file as argument.")); (_("Must specify exactly one directory containing " "$Recycle.bin index files, or one such index file " "as argument.")); */ return FALSE; } /* * Charset conversion routines */ size_t ucs2_strnlen (const gunichar2 *str, size_t max_sz) { #ifdef G_OS_WIN32 return wcsnlen_s ((const wchar_t *) str, max_sz); #else size_t i; if (str == NULL) return 0; for (i=0; (istr, output->allocated_len, "%Y-%m-%d %H:%M:%S", tm); if ( !len ) { g_string_free (output, TRUE); return NULL; } output->len = len; return output; } /* Return full name of current timezone */ static char * get_timezone_name (struct tm *tm) { #ifdef G_OS_WIN32 /* Impossible to use strftime() family on Windows, * see get_win_timezone_name() for reason */ if (tm == NULL) return g_strdup (_("Coordinated Universal Time (UTC)")); return get_win_timezone_name (); #else /* ! G_OS_WIN32 */ char buf[128]; if (tm == NULL) return g_strdup (_("Coordinated Universal Time (UTC)")); if ( 0 == strftime (buf, sizeof (buf) - 1, "%Z", tm) ) return g_strdup (_("(Failed to retrieve timezone name)")); return g_strdup (buf); #endif } /*! Return ISO8601 numeric timezone, like "+0400" */ static const char * get_timezone_numeric (struct tm *tm) { static char buf[10]; if (tm == NULL) return "+0000"; /* ISO8601 forbids -0000 */ /* * Turns out strftime is not so cross-platform, Windows one supports far * less format strings than that defined in Single Unix Specification. * However, GDateTime is not available until 2.26, so bite the bullet. */ #ifdef G_OS_WIN32 struct _timeb timeb; _ftime (&timeb); /* * 1. timezone value is in opposite sign of what people expect * 2. it doesn't account for DST. * 3. tm.tm_isdst is merely a flag and not indication on difference of * hours between DST and standard time. But there is no way to * override timezone in C library other than $TZ, and it always use * US rule, so again, just give up and use the value */ int offset = MAX(tm->tm_isdst, 0) * 60 - timeb.timezone; g_snprintf (buf, sizeof(buf), "%+.2i%.2i", offset / 60, abs(offset) % 60); #else /* !def G_OS_WIN32 */ size_t len = strftime (buf, sizeof(buf), "%z", tm); if ( !len ) return "+????"; #endif return (const char *) (&buf); } /*! Return ISO 8601 formatted time with timezone */ static GString * get_iso8601_datetime_str (struct tm *tm) { GString *output; if ( ( output = get_datetime_str (tm) ) == NULL ) return NULL; output->str[10] = 'T'; if ( !use_localtime ) return g_string_append_c (output, 'Z'); return g_string_append (output, get_timezone_numeric(tm)); } time_t win_filetime_to_epoch (uint64_t win_filetime) { uint64_t epoch; g_debug ("%s(): FileTime = %" G_GUINT64_FORMAT, __func__, win_filetime); /* Let's assume we don't need millisecond resolution time for now */ epoch = (win_filetime - 116444736000000000LL) / 10000000; /* Let's assume this program won't survive till 22th century */ return (time_t) (epoch & 0xFFFFFFFF); } void rifiuti_init (const char *progpath) { if (NULL != g_getenv ("RIFIUTI_DEBUG")) g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, my_debug_handler, NULL); setlocale (LC_ALL, ""); #ifdef G_OS_WIN32 { /* * Setting GETTEXT_MUI is not enough. Though it successfully * pick up user default locale under Windows, glib internally * only considers g_win32_getlocale() for decision making, * which in turn only considers thread locale. * So we need to override g_win32_getlocale() result. And * overriding that with LC_* would render GETTEXT_MUI useless. */ /* _putenv_s ("GETTEXT_MUI", "1"); */ char *loc = get_win32_locale(); if (0 == _putenv_s ("LC_MESSAGES", loc)) { g_debug ("(Windows) Use LC_MESSAGES = %s", loc); } else { g_warning ("Failed setting LC_MESSAGES variable, " "move on as if no translation is used."); } g_free (loc); } #endif { /* searching current dir is more useful on Windows */ char *d = g_path_get_dirname (progpath); char *p = g_build_filename (d, LOCALEDIR_PORTABLE, NULL); if (g_file_test (p, G_FILE_TEST_IS_DIR)) { g_debug ("Portable LOCALEDIR = %s", p); bindtextdomain (PACKAGE, p); } else bindtextdomain (PACKAGE, LOCALEDIR); g_free (p); g_free (d); } bind_textdomain_codeset (PACKAGE, "UTF-8"); textdomain (PACKAGE); } void rifiuti_setup_opt_ctx (GOptionContext **context, rbin_type type) { char *bug_report_str; GOptionGroup *group; g_option_context_set_translation_domain (*context, PACKAGE); bug_report_str = g_strdup_printf ( /* TRANSLATOR COMMENT: argument is bug report webpage */ _("Report bugs to %s"), PACKAGE_BUGREPORT); g_option_context_set_description (*context, bug_report_str); g_free (bug_report_str); /* main group */ group = g_option_group_new (NULL, NULL, NULL, NULL, NULL); g_option_group_add_entries (group, main_options); switch (type) { case RECYCLE_BIN_TYPE_FILE: g_option_group_add_entries (group, rbinfile_options); break; default: break; /* There will be option for recycle bin dir later */ } g_option_group_set_parse_hooks (group, NULL, _count_fileargs); g_option_group_set_translation_domain (group, PACKAGE); g_option_context_set_main_group (*context, group); /* text group */ /* FIXME For unknown reason, short description of option * groups are not translated at all if using N_() */ group = g_option_group_new ("text", _("Plain text output options:"), N_("Show plain text output options"), NULL, NULL); g_option_group_add_entries (group, text_options); g_option_group_set_translation_domain (group, PACKAGE); g_option_context_add_group (*context, group); g_option_context_set_help_enabled (*context, TRUE); } r2status rifiuti_parse_opt_ctx (GOptionContext **context, int *argc, char ***argv) { GError *err = NULL; char *help_msg; gboolean ret, do_print_help = FALSE; /* Must be done before parsing, since argc might be modified later */ if (*argc <= 1) do_print_help = TRUE; #if GLIB_CHECK_VERSION (2, 40, 0) { char **args; # ifdef G_OS_WIN32 args = g_win32_get_command_line (); # else args = g_strdupv (*argv); # endif ret = g_option_context_parse_strv (*context, &args, &err); g_strfreev (args); } #else /* glib < 2.40 */ ret = g_option_context_parse (*context, argc, argv, &err); #endif help_msg = g_option_context_get_help (*context, FALSE, NULL); g_option_context_free (*context); if (do_print_help) { #ifdef G_OS_WIN32 g_set_print_handler (gui_message); #endif g_print ("%s", help_msg); g_free (help_msg); exit (EXIT_SUCCESS); } g_free (help_msg); if ( !ret ) { g_printerr (_("Error parsing options: %s"), err->message); g_printerr ("\n"); g_error_free (err); return R2_ERR_ARG; } /* Some fallback values after successful option parsing... */ if (delim == NULL) delim = g_strdup ("\t"); if (output_mode == OUTPUT_NONE) output_mode = OUTPUT_CSV; return EXIT_SUCCESS; } /*! * Wrapper of g_utf16_to_utf8 for big endian system. * Always assume string is nul-terminated. (Unused now?) */ char * utf16le_to_utf8 (const gunichar2 *str, glong len, glong *items_read, glong *items_written, GError **error) { #if ((G_BYTE_ORDER) == (G_LITTLE_ENDIAN)) return g_utf16_to_utf8 (str, -1, items_read, items_written, error); #else gunichar2 *buf; char *ret; /* should be guaranteed to succeed */ buf = (gunichar2 *) g_convert ((const char *) str, len * 2, "UTF-16BE", "UTF-16LE", NULL, NULL, NULL); ret = g_utf16_to_utf8 (buf, -1, items_read, items_written, error); g_free (buf); return ret; #endif } void my_debug_handler (const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer data) { g_printerr ("DEBUG: %s\n", message); } static r2status _get_tempfile (void) { int fd, e = 0; FILE *h; char *t; /* segfaults if string is pre-allocated in stack */ t = g_strdup ("rifiuti-XXXXXX"); if ( -1 == ( fd = g_mkstemp (t) ) ) { e = errno; goto tempfile_fail; } h = fdopen (fd, "wb"); if (h == NULL) { e = errno; close (fd); goto tempfile_fail; } out_fh = h; tmppath = t; return EXIT_SUCCESS; tempfile_fail: g_printerr (_("Error opening temp file for writing: %s"), g_strerror (e)); g_printerr ("\n"); return R2_ERR_OPEN_FILE; } /*! Scan folder and add all "$Ixxxxxx.xxx" to filelist for parsing */ static gboolean _populate_index_file_list (GSList **list, const char *path) { GDir *dir; const char *direntry; char *fname; GPatternSpec *pattern1, *pattern2; GError *error = NULL; /* * g_dir_open returns cryptic error message or even succeeds on Windows, * when in fact the directory content is inaccessible. */ #ifdef G_OS_WIN32 if ( !can_list_win32_folder (path) ) return FALSE; #endif if (NULL == (dir = g_dir_open (path, 0, &error))) { g_printerr (_("Error opening directory '%s': %s"), path, error->message); g_printerr ("\n"); g_clear_error (&error); return FALSE; } pattern1 = g_pattern_spec_new ("$I??????.*"); pattern2 = g_pattern_spec_new ("$I??????"); while ((direntry = g_dir_read_name (dir)) != NULL) { if (!g_pattern_match_string (pattern1, direntry) && !g_pattern_match_string (pattern2, direntry)) continue; fname = g_build_filename (path, direntry, NULL); *list = g_slist_prepend (*list, fname); } g_dir_close (dir); g_pattern_spec_free (pattern1); g_pattern_spec_free (pattern2); return TRUE; } /*! Search for desktop.ini in folder for hint of recycle bin */ static gboolean found_desktop_ini (const char *path) { char *filename, *content, *found; filename = g_build_filename (path, "desktop.ini", NULL); if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) goto desktop_ini_error; /* assume desktop.ini is ASCII and not something spurious */ if (!g_file_get_contents (filename, &content, NULL, NULL)) goto desktop_ini_error; /* Don't bother parsing, we don't use the content at all */ found = strstr (content, RECYCLE_BIN_CLSID); g_free (content); g_free (filename); return (found != NULL); desktop_ini_error: g_free (filename); return FALSE; } /*! Add potentially valid file(s) to list */ int check_file_args (const char *path, GSList **list, rbin_type type) { g_debug ("Start basic file checking..."); g_return_val_if_fail ( (path != NULL) && (list != NULL), R2_ERR_INTERNAL ); if ( !g_file_test (path, G_FILE_TEST_EXISTS) ) { g_printerr (_("'%s' does not exist."), path); g_printerr ("\n"); return R2_ERR_OPEN_FILE; } else if ( (type == RECYCLE_BIN_TYPE_DIR) && g_file_test (path, G_FILE_TEST_IS_DIR) ) { if ( ! _populate_index_file_list (list, path) ) return R2_ERR_OPEN_FILE; /* * last ditch effort: search for desktop.ini. Just print empty content * representing empty recycle bin if found. */ if ( !*list && !found_desktop_ini (path) ) { g_printerr (_("No files with name pattern '%s' " "are found in directory."), "$Ixxxxxx.*"); g_printerr ("\n"); return R2_ERR_OPEN_FILE; } } else if ( g_file_test (path, G_FILE_TEST_IS_REGULAR) ) *list = g_slist_prepend ( *list, g_strdup (path) ); else { g_printerr ( (type == RECYCLE_BIN_TYPE_DIR) ? _("'%s' is not a normal file or directory.") : _("'%s' is not a normal file."), path); g_printerr ("\n"); return R2_ERR_OPEN_FILE; } return EXIT_SUCCESS; } static gboolean _local_printf (const char *format, ...) { va_list args; char *str; g_return_val_if_fail (format != NULL, FALSE); va_start (args, format); str = g_strdup_vprintf (format, args); va_end (args); if ( !g_utf8_validate (str, -1, NULL)) { g_critical (_("Supplied format or arguments not in UTF-8 encoding")); g_free (str); return FALSE; } #ifdef G_OS_WIN32 /* * Use Windows API only if: * 1. On Windows console * 2. Output is not piped nor redirected * See init_wincon_handle(). */ if (out_fh == NULL) { GError *err = NULL; wchar_t *wstr = g_utf8_to_utf16 (str, -1, NULL, NULL, &err); if (err != NULL) { g_critical (_("Error converting output from UTF-8 to UTF-16: %s"), err->message); g_clear_error (&err); wstr = g_utf8_to_utf16 ("(Original message failed to be displayed in UTF-16)", -1, NULL, NULL, NULL); } puts_wincon (wstr); g_free (wstr); } else #endif fputs (str, out_fh); g_free (str); return TRUE; } r2status prepare_output_handle (void) { r2status s = EXIT_SUCCESS; if (output_loc) s = _get_tempfile (); else { #ifdef G_OS_WIN32 if (!init_wincon_handle()) #endif out_fh = stdout; } return s; } void print_header (metarecord meta) { char *rbin_path; if (no_heading) return; g_return_if_fail (meta.filename != NULL); g_debug ("Entering %s()", __func__); rbin_path = g_filename_display_name (meta.filename); switch (output_mode) { case OUTPUT_CSV: _local_printf (_("Recycle bin path: '%s'"), rbin_path); _local_printf ("\n"); { char *ver; if (meta.version == VERSION_NOT_FOUND) { /* TRANSLATOR COMMENT: Empty folder, no file avaiable for analysis */ ver = g_strdup (_("??? (empty folder)")); } else ver = g_strdup_printf ("%" G_GUINT64_FORMAT, meta.version); _local_printf (_("Version: %s"), ver); _local_printf ("\n"); g_free (ver); } if (( meta.type == RECYCLE_BIN_TYPE_FILE ) && ( ! meta.keep_deleted_entry )) { _local_printf (_("Total entries ever existed: %d"), meta.total_entry); _local_printf ("\n"); } if (meta.os_guess == OS_GUESS_UNKNOWN) _local_printf (_("OS detection failed")); else _local_printf (_("OS Guess: %s"), gettext (os_strings[meta.os_guess]) ); _local_printf ("\n"); { char *tz_name; const char *tz_numeric; if (use_localtime) { struct tm _tm; time_t t = time (NULL); localtime_r (&t, &_tm); tz_name = get_timezone_name (&_tm); tz_numeric = get_timezone_numeric (&_tm); } else { tz_name = get_timezone_name (NULL); tz_numeric = get_timezone_numeric (NULL); } _local_printf (_("Time zone: %s [%s]"), tz_name, tz_numeric); _local_printf ("\n"); g_free (tz_name); } _local_printf ("\n"); { GArray *a; char **c, *headerline; char *colhead[] = { /* TRANSLATOR COMMENT: appears in column header */ N_("Index"), N_("Deleted Time"), N_("Size"), N_("Path"), NULL }; a = g_array_sized_new (TRUE, TRUE, sizeof (gpointer), 5); c = colhead; while (*c != NULL) { const char *t = gettext (*c++); g_array_append_val (a, t); } if (meta.keep_deleted_entry) { /* TRANSLATOR COMMENT: appears in column header, means file is restored or purged */ char *t = _("Gone?"); g_array_insert_val (a, 2, t); } headerline = g_strjoinv (delim, (char **) a->data); _local_printf ("%s", headerline); _local_printf ("\n"); g_free (headerline); g_array_free (a, TRUE); } break; case OUTPUT_XML: /* No proper way to report wrong version info yet */ _local_printf ( "\n" "\n" " \n", ( meta.type == RECYCLE_BIN_TYPE_FILE ) ? "file" : "dir", MAX (meta.version, 0), rbin_path); break; default: g_assert_not_reached(); } g_free (rbin_path); g_debug ("Leaving %s()", __func__); } void print_record_cb (rbin_struct *record) { char *out_fname, *index, *size = NULL; char *outstr = NULL, *deltime = NULL; GString *t; struct tm del_tm; g_return_if_fail (record != NULL); index = (record->meta->type == RECYCLE_BIN_TYPE_FILE) ? g_strdup_printf ("%u", record->index_n) : g_strdup (record->index_s); /* * Used to check TZ environment variable here, but no more. * Problems with that approach is now documented elsewhere. */ /* * g_warning() further down below is an inline func that makes use of * localtime(), and if localtime/gmtime is used here (it used to be), * the value would be overwritten upon the g_warning call, into current * machine time. Nasty. * * But why is the behavior occuring on MinGW-w64, but not even on MSYS2 * itself or any other OS; and why only manifesting now but not earlier? * -- 2019-03-19 */ if (use_localtime) localtime_r (&(record->deltime), &del_tm); else gmtime_r (&(record->deltime), &del_tm); if ( record->legacy_path != NULL ) out_fname = g_strdup (record->legacy_path); else { out_fname = record->uni_path ? g_strdup (record->uni_path) : g_strdup (_("(File name not representable in UTF-8 encoding)")); } switch (output_mode) { case OUTPUT_CSV: if ((t = get_datetime_str (&del_tm)) != NULL) deltime = g_string_free (t, FALSE); else { g_warning (_("Error formatting file deletion time for record index %s."), index); deltime = g_strdup ("???"); } if ( record->filesize == G_MAXUINT64 ) /* faulty */ size = g_strdup ("???"); else size = g_strdup_printf ("%" G_GUINT64_FORMAT, record->filesize); if (record->meta->keep_deleted_entry) { const char *purged = record->emptied ? _("Yes") : _("No"); outstr = g_strjoin (delim, index, deltime, purged, size, out_fname, NULL); } else outstr = g_strjoin (delim, index, deltime, size, out_fname, NULL); _local_printf ("%s\n", outstr); break; case OUTPUT_XML: { GString *s = g_string_new (NULL); if ((t = get_iso8601_datetime_str (&del_tm)) != NULL) deltime = g_string_free (t, FALSE); else { g_warning (_("Error formatting file deletion time for record index %s."), index); deltime = g_strdup ("???"); } g_string_printf (s, " meta->keep_deleted_entry) g_string_append_printf (s, " emptied=\"%c\"", record->emptied ? 'Y' : 'N'); if ( record->filesize == G_MAXUINT64 ) /* faulty */ size = g_strdup_printf (" size=\"-1\""); else size = g_strdup_printf (" size=\"%" G_GUINT64_FORMAT "\"", record->filesize); s = g_string_append (s, (const gchar*) size); g_string_append_printf (s, ">\n" " \n" " \n", out_fname); outstr = g_string_free (s, FALSE); _local_printf ("%s", outstr); } break; default: g_assert_not_reached(); } g_free (outstr); g_free (out_fname); g_free (deltime); g_free (size); g_free (index); } void print_footer (void) { switch (output_mode) { case OUTPUT_CSV: /* do nothing */ break; case OUTPUT_XML: _local_printf ("%s", "\n"); break; default: g_assert_not_reached(); } } void close_output_handle (void) { if (out_fh != NULL) fclose (out_fh); #ifdef G_OS_WIN32 close_wincon_handle(); #endif } r2status move_temp_file (void) { int e; if ( !tmppath || !output_loc ) return EXIT_SUCCESS; if ( 0 == g_rename (tmppath, output_loc) ) return EXIT_SUCCESS; e = errno; /* TRANSLATOR COMMENT: argument is system error message */ g_printerr (_("Error moving output data to desinated file: %s"), g_strerror(e)); g_printerr ("\n"); /* TRANSLATOR COMMENT: argument is temp file location */ g_printerr (_("Output content is left in '%s'."), tmppath); g_printerr ("\n"); return R2_ERR_WRITE_FILE; } void print_version_and_exit (void) { fprintf (stdout, "%s %s\n", PACKAGE, VERSION); /* TRANSLATOR COMMENT: %s is software name */ fprintf (stdout, _("%s is distributed under the " "BSD 3-Clause License.\n"), PACKAGE); /* TRANSLATOR COMMENT: 1st argument is software name, 2nd is official URL */ fprintf (stdout, _("Information about %s can be found on\n\n\t%s\n"), PACKAGE, PACKAGE_URL); exit (EXIT_SUCCESS); } void free_record_cb (rbin_struct *record) { if ( record->meta->type == RECYCLE_BIN_TYPE_DIR ) g_free (record->index_s); g_free (record->uni_path); g_free (record->legacy_path); g_free (record); } void free_vars (void) { g_strfreev (fileargs); g_free (output_loc); g_free (legacy_encoding); g_free (delim); g_free (tmppath); }rifiuti2-0.7.0/src/utils.h000066400000000000000000000167641346470066000153770ustar00rootroot00000000000000/* vim: set sw=4 ts=4 noexpandtab : */ /* * Copyright (C) 2007-2019 Abel Cheung. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _RIFIUTI_UTILS_H #define _RIFIUTI_UTILS_H /* * Rifiuti itself only need _POSIX_C_SOURCE == 1 for usage of * localtime_r(); however glib2's usage of siginfo_t pushes * the requirement further. It's undefined in some Unices. */ #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309L #endif #include #include #include #include /* Error and exit status */ typedef enum { R2_OK = 0, /* as synonym of EXIT_SUCCESS */ R2_ERR_ARG, R2_ERR_OPEN_FILE, R2_ERR_BROKEN_FILE, /* file format validation failure */ R2_ERR_WRITE_FILE, R2_ERR_USER_ENCODING, R2_ERR_INTERNAL = 64 } r2status; typedef enum { RECYCLE_BIN_TYPE_FILE, RECYCLE_BIN_TYPE_DIR, } rbin_type; /* The first 4 or 8 bytes of recycle bin index files */ enum { /* negative number means error when retrieving version info */ VERSION_INCONSISTENT = -2, VERSION_NOT_FOUND, /* $Recycle.bin */ VERSION_VISTA = 1, VERSION_WIN10, /* INFO / INFO2 */ VERSION_WIN95 = 0, VERSION_NT4 = 2, VERSION_WIN98 = 4, VERSION_ME_03, }; /* * The following enum is different from the versions above. * This is more detailed breakdown, and for detection of exact * Windows version from various recycle bin artifacts. * WARNING: MUST match os_strings string array */ typedef enum { OS_GUESS_UNKNOWN = -1, OS_GUESS_95, OS_GUESS_NT4, OS_GUESS_98, OS_GUESS_ME, OS_GUESS_2K, OS_GUESS_XP_03, OS_GUESS_2K_03, /* Empty recycle bin, full detection impossible */ OS_GUESS_VISTA, /* includes everything up to 8.1 */ OS_GUESS_10 } _os_guess; enum { OUTPUT_NONE, OUTPUT_CSV, OUTPUT_XML }; /*! \struct _rbin_meta * \brief Metadata for recycle bin */ typedef struct _rbin_meta { rbin_type type; const char *filename; _os_guess os_guess; int64_t version; uint32_t recordsize; /*!< INFO2 only */ uint32_t total_entry; /*!< 95/NT4 only */ gboolean keep_deleted_entry; /*!< 98-03 only, add extra output column */ gboolean is_empty; gboolean has_unicode_path; gboolean fill_junk; /*!< TRUE for 98/ME/2000 only, some fields padded with junk data instaed of zeroed */ } metarecord; /*! \struct _rbin_struct * \brief Struct for single recycle bin item */ typedef struct _rbin_struct { /*! For $Recycle.bin, version of each index file is kept here, * while meta.version keeps the global status of whole dir */ uint64_t version; /* $Recycle.bin only */ /*! Each record links to metadata for more convenient access */ const metarecord *meta; /*! \brief Number is for INFO2, file name for $Recycle.bin */ union { uint32_t index_n; /* INFO2 only */ char *index_s; /* $Recycle.bin only */ }; /*! Item delection time */ time_t deltime; /*! Can mean cluster size or actual file/folder size */ uint64_t filesize; /* despite var names, all filenames are converted to UTF-8 upon parsing */ char *uni_path; char *legacy_path; /* INFO2 only */ gboolean emptied; /* INFO2 only */ unsigned char drive; /* INFO2 only */ } rbin_struct; /* convenience macro */ #define copy_field(field, off1, off2) memcpy((field), \ buf + off1 ## _OFFSET, off2 ## _OFFSET - off1 ## _OFFSET) /*! Every Windows use this GUID in recycle bin desktop.ini */ #define RECYCLE_BIN_CLSID "645FF040-5081-101B-9F08-00AA002F954E" /* * Most versions of recycle bin use full PATH_MAX (260 char) to store file paths, * in either ANSI or Unicode variations, except Windows 10 which uses variable size. * However we don't want to use PATH_MAX directly since on Linux/Unix it's * another thing. */ #define WIN_PATH_MAX 260 /* shared functions */ void rifiuti_init (const char *progpath); void rifiuti_setup_opt_ctx (GOptionContext **context, rbin_type type); r2status rifiuti_parse_opt_ctx (GOptionContext **context, int *argc, char ***argv); time_t win_filetime_to_epoch (uint64_t win_filetime); char * utf16le_to_utf8 (const gunichar2 *str, glong len, glong *items_read, glong *items_written, GError **error) G_GNUC_UNUSED; int check_file_args (const char *path, GSList **list, rbin_type type); r2status prepare_output_handle (void); void close_output_handle (void); void print_header (metarecord meta); void print_record_cb (rbin_struct *record); void print_footer (void); r2status move_temp_file (void); void print_version_and_exit (void) G_GNUC_NORETURN; void free_record_cb (rbin_struct *record); void my_debug_handler (const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer data); char * conv_path_to_utf8_with_tmpl (const char *str, const char *from_enc, const char *tmpl, size_t *read, r2status *st); void free_vars (void); #endif rifiuti2-0.7.0/test/000077500000000000000000000000001346470066000142405ustar00rootroot00000000000000rifiuti2-0.7.0/test/Makefile.am000066400000000000000000000067751346470066000163130ustar00rootroot00000000000000# vim: set sw=4 ts=4 noexpandtab : # # Copyright (C) 2015 Abel Cheung. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the project nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # The `:;' works around a Bash 3.2 bug when the output is not writable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac :;{ \ echo '# Signature of the current package.' && \ echo 'm4_define([AT_PACKAGE_NAME], [$(PACKAGE_NAME)])' && \ echo 'm4_define([AT_PACKAGE_TARNAME], [$(PACKAGE_TARNAME)])' && \ echo 'm4_define([AT_PACKAGE_VERSION], [$(PACKAGE_VERSION)])' && \ echo 'm4_define([AT_PACKAGE_STRING], [$(PACKAGE_STRING)])' && \ echo 'm4_define([AT_PACKAGE_BUGREPORT], [$(PACKAGE_BUGREPORT)])'; \ echo 'm4_define([AT_PACKAGE_URL], [$(PACKAGE_URL)])'; \ } > $@ noinst_PROGRAMS = test_glib_iconv test_glib_iconv_LDADD = $(GLIB_LIBS) test_glib_iconv_CFLAGS = $(GLIB_CFLAGS) TESTSUITE = $(srcdir)/testsuite INC_AT_FILES = \ ax_at_check_pattern.m4 \ test_cli_option.at \ test_common.at \ test_encoding.at \ test_faulty_dir.at \ test_parse_dir.at \ test_parse_info2.at \ test_read_write.at \ test_xml.at AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te AUTOTEST = $(AUTOM4TE) --language=autotest # Autotest won't use AC_ macros, therefore pass the result # of AC_CHECK_PROGS as external variables TEST_FLAGS_EXTRA = 'AWK=$(AWK)' check-local: atconfig atlocal $(TESTSUITE) $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) $(TEST_FLAGS_EXTRA) installcheck-local: atconfig atlocal $(TESTSUITE) $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ $(TESTSUITEFLAGS) $(TEST_FLAGS_EXTRA) clean-local: test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' --clean -rm -f *.tmp $(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4 $(INC_AT_FILES) $(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at mv $@.tmp $@ EXTRA_DIST = \ rifiuti.dtd \ samples \ $(srcdir)/package.m4 \ testsuite.at \ $(TESTSUITE) \ atlocal.in \ $(INC_AT_FILES) \ $(NULL) DISTCLEANFILES = atconfig atlocal CLEANFILES = testsuite.log MAINTAINERCLEANFILES = \ $(TESTSUITE) \ $(srcdir)/package.m4 \ $(srcdir)/Makefile.in \ $(NULL) rifiuti2-0.7.0/test/atlocal.in000066400000000000000000000027201346470066000162100ustar00rootroot00000000000000# -*- shell-script -*- # vim: set filetype=sh sw=4 ts=4 noexpandtab : # @configure_input@ # Configurable variable values for Autoconf test suite. # prog checks iconv="@ICONV@" has_iconv="test 'x@ICONV@' != 'x'" xmllint="@XMLLINT@" has_xmllint="test 'x@XMLLINT@' != 'x'" awk="@AWK@" # detect & set env is_mingw="test x@is_mingw@ != x" is_cygwin="test x@is_cygwin@ != x" # abbrev progf="$abs_top_builddir/src/rifiuti" progd="$abs_top_builddir/src/rifiuti-vista" sample="$abs_srcdir/samples" # # For some systems, glib may or may not be using system iconv # (e.g. Solaris and FreeBSD), therefore simply finding out # supported encoding from iconv program is not enough. # # In general, there is no cross platform way of specifying # encoding names. To rub salt into wounds, even glib itself # appears to append different encoding aliases on different # OSes... (such as using win_iconv on Windows) # # Have to give up specifying charset names according to OS, and # resort to checking runtime behavior instead. # for i in IBM-037 IBM037 CP037; do if ./test_glib_iconv "$i"; then ebcdic_latin1_name="$i" break fi done for i in CP936 MS936 Windows-936 GBK csGBK; do if ./test_glib_iconv "$i"; then gbk_name="$i" break fi done for i in CP932 Windows-932 IBM-943 SJIS JIS_X0208 SHIFT_JIS SHIFT-JIS; do if ./test_glib_iconv "$i"; then sjis_name="$i" break fi done for i in CP950 Windows-950 Big5 BIG5; do if ./test_glib_iconv "$i"; then big5_name="$i" break fi donerifiuti2-0.7.0/test/ax_at_check_pattern.m4000066400000000000000000000102071346470066000204700ustar00rootroot00000000000000# SYNOPSIS # # AX_AT_CHECK_PATTERN(COMMANDS, [STATUS], [STDOUT-RE], [STDERR-RE], [RUN-IF-FAIL], [RUN-IF-PASS]) # AX_AT_DIFF_PATTERN(PATTERN-FILE, TEST-FILE, [STATUS=0], [DIFFERENCES]) # AX_AT_DATA_CHECK_PATTERN_AWK(FILENAME) # # DESCRIPTION # # AX_AT_CHECK_PATTERN() executes a test similar to AT_CHECK(), except # that stdout and stderr are awk regular expressions (REs). # # NOTE: as autoconf uses [] for quoting, the use of [brackets] in the RE # arguments STDOUT-RE and STDERR-RE can be awkward and require careful # extra quoting, or quadrigraphs '@<:@' (for '[') and '@:>@' (for ']'). # # awk is invoked via $AWK, which defaults to "awk" if unset or empty. # # Implemented using AT_CHECK() with a custom value for $at_diff that # invokes diff with an awk post-processor. # # # AX_AT_DIFF_PATTERN() checks that the PATTERN-FILE applies to TEST-FILE. # If there are differences, STATUS will be 1 and they should be DIFFERENCES. # # # AX_AT_DATA_CHECK_PATTERN_AWK() creates FILENAME with the contents of # the awk script used. # # # The latest version of this macro and a supporting test suite are at: # https://github.com/lukem/pyrediff # # # LICENSE # # Copyright (c) 2013-2017 Luke Mewburn # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without any warranty. #serial 13 m4_define([_AX_AT_CHECK_PATTERN_AWK], [[BEGIN { exitval=0 } function set_mode(m) { mode=m lc=0 rc=0 } function mismatch() { print mode for (i = 0; i < lc; i++) { print ll@<:@i@:>@ } print "---" for (i = 0; i < rc; i++) { print rl@<:@i@:>@ } set_mode("") exitval=1 } function change_mode(m) { if (lc > rc) { mismatch() } set_mode(m) } @S|@1 ~ /^@<:@0-9@:>@+(,@<:@0-9@:>@+)?@<:@ad@:>@@<:@0-9@:>@+(,@<:@0-9@:>@+)?@S|@/ { change_mode("") print exitval=1 next } @S|@1 ~ /^@<:@0-9@:>@+(,@<:@0-9@:>@+)?@<:@c@:>@@<:@0-9@:>@+(,@<:@0-9@:>@+)?@S|@/ { change_mode(@S|@1) next } mode == "" { print @S|@0 next } @S|@1 == "<" { ll@<:@lc@:>@ = @S|@0 lc = lc + 1 next } @S|@1 == "---" { next } @S|@1 == ">" { rl@<:@rc@:>@ = @S|@0 rc = rc + 1 if (rc > lc) { mismatch() next } pat = "^" substr(ll@<:@rc-1@:>@, 3) "@S|@" str = substr(@S|@0, 3) if (str !~ pat) { mismatch() } next } { print "UNEXPECTED LINE: " @S|@0 exit 10 } END { change_mode("") exit exitval } ]]) m4_defun([_AX_AT_CHECK_PATTERN_PREPARE], [dnl dnl Can't use AC_PROG_AWK() in autotest. AS_VAR_IF([AWK], [], [AWK=awk]) AS_REQUIRE_SHELL_FN([ax_at_diff_pattern], [AS_FUNCTION_DESCRIBE([ax_at_diff_pattern], [PATTERN OUTPUT], [Diff PATTERN OUTPUT and elide change lines where the RE pattern matches])], [diff "$[]1" "$[]2" | $AWK '_AX_AT_CHECK_PATTERN_AWK']) ])dnl _AX_AT_CHECK_PATTERN_PREPARE m4_defun([AX_AT_CHECK_PATTERN], [dnl AS_REQUIRE([_AX_AT_CHECK_PATTERN_PREPARE]) _ax_at_check_pattern_prepare_original_at_diff="$at_diff" at_diff='ax_at_diff_pattern' AT_CHECK(m4_expand([$1]), [$2], m4_expand([$3]), m4_expand([$4]), [at_diff="$_ax_at_check_pattern_prepare_original_at_diff";$5], [at_diff="$_ax_at_check_pattern_prepare_original_at_diff";$6]) ])dnl AX_AT_CHECK_PATTERN m4_defun([AX_AT_DIFF_PATTERN], [dnl AS_REQUIRE([_AX_AT_CHECK_PATTERN_PREPARE]) AT_CHECK([ax_at_diff_pattern $1 $2], [$3], [$4]) ])dnl AX_AT_DIFF_PATTERN m4_defun([AX_AT_DATA_CHECK_PATTERN_AWK], [dnl m4_if([$1], [], [m4_fatal([$0: argument 1: empty filename])])dnl AT_DATA([$1], [dnl # check_pattern.awk # Generated by AX_AT_DATA_CHECK_PATTERN_AWK() # from https://github.com/lukem/pyrediff # # awk script to process the output of "diff PATTERN OUTPUT" removing lines # where the difference is a PATTERN line that exactly matches an OUTPUT line. # # # Copyright (c) 2013-2017 Luke Mewburn # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without any warranty. # ] _AX_AT_CHECK_PATTERN_AWK) ])dnl AX_AT_DATA_CHECK_PATTERN_AWK rifiuti2-0.7.0/test/rifiuti.dtd000066400000000000000000000004771346470066000164200ustar00rootroot00000000000000 rifiuti2-0.7.0/test/samples/000077500000000000000000000000001346470066000157045ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/INFO-95-ja-1000066400000000000000000000060341346470066000173460ustar00rootroot00000000000000 ,D:\WINDOWS\޽į\The Microsoft Network ̾ı.lnk ְD:\WINDOWS\޽į\VKޯϯ Ұ.bmpOƯD:\WINDOWS\޽į\VK÷ĕ.txtsϺD:\My Documents\DirectX-V8.0a\bda.cabϋ D:\My Documents\DirectX-V8.0a\bdant.cabϋ D:\My Documents\DirectX-V8.0a\cfgmgr32.dll?ϋD:\My Documents\DirectX-V8.0a\dxsetup.exe 9ϋD:\My Documents\DirectX-V8.0a\setupapi.dll 9ϋD:\WINDOWS\޽į\Connect to the Internet.LNK  %ыD:\WINDOWS\޽į\Outlook Express.lnk'ыD:\WINDOWS\޽į\VK÷ĕ.txtIrifiuti2-0.7.0/test/samples/INFO-95-ja-1.txt000066400000000000000000000021461346470066000201640ustar00rootroot00000000000000Recycle bin path: 'INFO-95-ja-1' Version: 0 Total entries ever existed: 16 OS Guess: Windows 95 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path 1 2015-05-11 05:59:49 32768 D:\WINDOWS\デスクトップ\The Microsoft Network のセットアップ.lnk 2 2015-05-11 06:00:25 950272 D:\WINDOWS\デスクトップ\新規ビットマップ イメージ.bmp 3 2015-05-11 07:19:25 32768 D:\WINDOWS\デスクトップ\新規テキスト文書.txt 4 2015-05-11 09:48:21 589824 D:\My Documents\DirectX-V8.0a\bda.cab 5 2015-05-11 09:48:21 589824 D:\My Documents\DirectX-V8.0a\bdant.cab 6 2015-05-11 09:48:21 65536 D:\My Documents\DirectX-V8.0a\cfgmgr32.dll 11 2015-05-11 09:48:23 163840 D:\My Documents\DirectX-V8.0a\dxsetup.exe 12 2015-05-11 09:48:23 360448 D:\My Documents\DirectX-V8.0a\setupapi.dll 13 2015-05-11 09:59:19 32768 D:\WINDOWS\デスクトップ\Connect to the Internet.LNK 14 2015-05-11 09:59:22 32768 D:\WINDOWS\デスクトップ\Outlook Express.lnk 15 2015-05-18 00:45:09 32768 D:\WINDOWS\デスクトップ\新規テキスト文書.txt rifiuti2-0.7.0/test/samples/INFO-NT-en-1000066400000000000000000000113241346470066000174400ustar00rootroot00000000000000 ,C:\WINNT\Profiles\Administrator\Desktop\IE 5.5 SP2 Full tSC:\WINNT\Profiles\Administrator\Desktop\IE 5.5 SP2 FullC:\WINNT\Profiles\Administrator\Desktop\Firefox Setup 2[1].0.0.20.exe J\C:\WINNT\Profiles\Administrator\Desktop\Firefox Setup 2[1].0.0.20.exeC:\WINNT\Profiles\Administrator\Desktop\coreftplite[1].ansi.exe'C:\WINNT\Profiles\Administrator\Desktop\coreftplite[1].ansi.exeC:\WINNT\Profiles\Administrator\Desktop\ie55sp2_nt.zip28C:\WINNT\Profiles\Administrator\Desktop\ie55sp2_nt.zipC:\TEMP\ie6@O=C:\TEMP\ie6C:\TEMP\ie6-standaloneռ΃C:\TEMP\ie6-standalonerifiuti2-0.7.0/test/samples/INFO-NT-en-1.txt000066400000000000000000000012121346470066000202510ustar00rootroot00000000000000Recycle bin path: 'INFO-NT-en-1' Version: 2 Total entries ever existed: 18 OS Guess: Windows NT 4.0 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path 12 2015-05-23 01:50:28 89355264 C:\WINNT\Profiles\Administrator\Desktop\IE 5.5 SP2 Full 13 2015-05-23 01:50:31 6048256 C:\WINNT\Profiles\Administrator\Desktop\Firefox Setup 2[1].0.0.20.exe 14 2015-05-23 01:50:31 2615296 C:\WINNT\Profiles\Administrator\Desktop\coreftplite[1].ansi.exe 15 2015-05-23 01:50:31 3682816 C:\WINNT\Profiles\Administrator\Desktop\ie55sp2_nt.zip 16 2015-05-23 01:50:49 20809216 C:\TEMP\ie6 17 2015-05-23 01:50:49 8637952 C:\TEMP\ie6-standalone rifiuti2-0.7.0/test/samples/INFO2-03-tw-uncpath000066400000000000000000000062241346470066000207600ustar00rootroot00000000000000 \\Vm-2003-r2-tw\Temp\\DOWNLO~1\HxDSetup.zip4e 0\\Vm-2003-r2-tw\Temp\eN\Downloads\HxDSetup.zip\Vm-2003-r2-tw\Temp\\DOWNLO~1\README~1.HTMe@\\Vm-2003-r2-tw\Temp\eN\Downloads\README.html\Vm-2003-r2-tw\Temp\\DOWNLO~1\____PC~1.BINS.binqJf`\\Vm-2003-r2-tw\Temp\eN\Downloads\____PC__FONTS.bin\\Vm-2003-r2-tw\Temp\\DOWNLO~1\ws_ftple.exePd) f \\Vm-2003-r2-tw\Temp\eN\Downloads\ws_ftple.exerifiuti2-0.7.0/test/samples/INFO2-03-tw-uncpath.txt000066400000000000000000000007711346470066000215770ustar00rootroot00000000000000Recycle bin path: 'INFO2-03-tw-uncpath' Version: 5 OS Guess: Windows XP or 2003 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 1 2019-05-05 17:08:49 No 3153920 \\Vm-2003-r2-tw\Temp\文件\Downloads\HxDSetup.zip 2 2019-05-05 17:12:32 Yes 16384 \\Vm-2003-r2-tw\Temp\文件\Downloads\README.html 3 2019-05-05 17:14:38 Yes 24576 \\Vm-2003-r2-tw\Temp\文件\Downloads\____PC__FONTS.bin 4 2019-05-05 17:14:46 No 708608 \\Vm-2003-r2-tw\Temp\文件\Downloads\ws_ftple.exe rifiuti2-0.7.0/test/samples/INFO2-2k-cht-1000066400000000000000000000076641346470066000177050ustar00rootroot00000000000000 C:\DOCUME~1\Nobody\ୱ\ABCs~1.TXT\ABCsWr.txtf|ld~wH1w|wH  @wpgC:\Documents and Settings\Nobody\Lhb\ABCeXeW[eN.txtd~wX1wx·wx ʶwwwx@ IoyJoyE wf@@d~wxwPYw ww$ ww Ccxpx jH jH  f @~w @Tww8 f{w|FyC:\DOCUME~1\Nobody\ୱ\MOZILL~1.LNK\Mozilla Firefox.lnkh |IlId~wH1w|IwH  @w@2tC:\Documents and Settings\Nobody\Lhb\Mozilla Firefox.lnkxI·wxM ʶwwwxI@M IIoyJoyEI w I@I@Id~wxwPIYwM ww ww CcxpxI vvM h  III@~w @IIITwwҋ 0S f{w|FyC:\Documents and Settings\Nobody\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901.bmpjC:\Documents and Settings\Nobody\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901.bmpC:\temp\ODULLU~1.DOCr ?????.doc0R ,wH  RRd~wH1wRwH  @wC:\temp\dll mT-NeW[ *4CJD.doc`R,wJaBsÑ rifiuti2-0.7.0/test/samples/INFO2-ME-en-1.txt000066400000000000000000000010471346470066000203210ustar00rootroot00000000000000Recycle bin path: 'INFO2-ME-en-1' Version: 5 OS Guess: Windows ME Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 1 2015-05-10 12:43:36 No 4096 C:\WINDOWS\Desktop\Windows Media Player.lnk 2 2015-05-10 12:45:41 No 0 C:\My Documents\Temp Folder é à ä ç 3 2015-05-18 22:15:32 Yes 495616 C:\My Documents\Copy of My Music 3 2015-05-18 23:38:34 Yes 4096 C:\My Documents\bin-me.zip 4 2015-05-18 23:38:53 Yes 4096 C:\My Documents\bin-me.zip 5 2015-05-18 23:39:31 No 8192 C:\WINDOWS\Desktop\New WordPad Document.doc rifiuti2-0.7.0/test/samples/INFO2-empty000066400000000000000000000000241346470066000175740ustar00rootroot00000000000000 rifiuti2-0.7.0/test/samples/INFO2-empty.txt000066400000000000000000000002461346470066000204200ustar00rootroot00000000000000Recycle bin path: 'INFO2-empty' Version: 5 OS Guess: Windows 2000, XP or 2003 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path rifiuti2-0.7.0/test/samples/INFO2-me-en-uncpath000066400000000000000000000015341346470066000211060ustar00rootroot00000000000000\\Vm-me\temp\Documents\langastas.xpi#D#DފpD?xܸ`DFo'APG@$x1?-8p8Dxu?xxdxvĐFxB'l\\Vm-me\temp\Documents\3DPacmanSetupTrial.exeD#DފpD?~ܸ̗Fo'APGW$~1?-8p8D~u?~~d~vF~BhH\Vm-me\temp\Documents\fgabida.lst#D#DފpD?ܸ0OIo'APGU$1?-8p8Du?dvaFB7#rifiuti2-0.7.0/test/samples/INFO2-me-en-uncpath.txt000066400000000000000000000005661346470066000217300ustar00rootroot00000000000000Recycle bin path: 'INFO2-me-en-uncpath' Version: 5 OS Guess: Windows ME Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 1 2019-05-02 16:31:45 No 420864 \\Vm-me\temp\Documents\langastas.xpi 2 2019-05-02 16:38:56 No 4773888 \\Vm-me\temp\Documents\3DPacmanSetupTrial.exe 3 2019-05-02 16:43:15 Yes 4608 \\Vm-me\temp\Documents\fgabida.lst rifiuti2-0.7.0/test/samples/INFO2-sample1000066400000000000000000000310241346470066000200040ustar00rootroot00000000000000 D )C:\DOCUME~1\ALLUSE~1\Desktop\е~1.LNKp\еʵ.lnk,J Z9C:\Documents and Settings\All Users\Desktop\ gSLhb͋xQ.lnkC:\Documents and Settings\Administrator\Desktop\wongsir_url.txt-@L=C:\Documents and Settings\Administrator\Desktop\wongsir_url.txtC:\Documents and Settings\Administrator\Desktop\dd-wrt.v24_mini_wrt54g.bin.@Č?p,C:\Documents and Settings\Administrator\Desktop\dd-wrt.v24_mini_wrt54g.binC:\Documents and Settings\Administrator\Desktop\theme\.svn/ fE C:\Documents and Settings\Administrator\Desktop\theme\.svnC:\Documents and Settings\Administrator\Desktop\Config Client0EXC:\Documents and Settings\Administrator\Desktop\Config ClientC:\Documents and Settings\Administrator\Desktop\Config Client.7z1E0C:\Documents and Settings\Administrator\Desktop\Config Client.7zC:\Documents and Settings\All Users\Desktop\Wireshark.lnk2r+JC:\Documents and Settings\All Users\Desktop\Wireshark.lnkC:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline.rar9FJ)C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline.rar:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline@[J)C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConlineC:\DOCUME~1\ADMINI~1\Desktop\360~1.LNKesktop\360.lnkAJC:\Documents and Settings\Administrator\Desktop\360Oi{.lnkC:\Documents and Settings\Administrator\Desktop\gdbB`HJ)C:\Documents and Settings\Administrator\Desktop\gdbC:\Documents and Settings\Administrator\Desktop\gdb.zipC`HJ)C:\Documents and Settings\Administrator\Desktop\gdb.zipC:\Documents and Settings\Administrator\Desktop\recovered filesD 7:JC:\Documents and Settings\Administrator\Desktop\recovered filesC:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConlineEwJ)C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConlineC:\Documents and Settings\Administrator\Desktop\Uneraser_Setup(2).exeFpwJNC:\Documents and Settings\Administrator\Desktop\Uneraser_Setup(2).exeC:\Documents and Settings\Administrator\Desktop\Uneraser_Setup.exeGpwJNC:\Documents and Settings\Administrator\Desktop\Uneraser_Setup.exerifiuti2-0.7.0/test/samples/INFO2-sample1-alt.txt000066400000000000000000000032621346470066000214030ustar00rootroot00000000000000Recycle bin path: 'INFO2-sample1' Version: 5 OS Guess: Windows XP or 2003 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 44 2008-10-28 15:53:42 No 4096 C:\DOCUME~1\ALLUSE~1\Desktop\有道桌~1.LNK 45 2008-11-03 15:01:59 No 4096 C:\Documents and Settings\Administrator\Desktop\wongsir_url.txt 46 2008-11-06 09:20:58 No 2912256 C:\Documents and Settings\Administrator\Desktop\dd-wrt.v24_mini_wrt54g.bin 47 2008-11-13 12:08:39 No 765952 C:\Documents and Settings\Administrator\Desktop\theme\.svn 48 2008-11-13 12:11:33 No 5812224 C:\Documents and Settings\Administrator\Desktop\Config Client 49 2008-11-13 12:11:36 No 1847296 C:\Documents and Settings\Administrator\Desktop\Config Client.7z 50 2008-11-19 04:42:04 No 4096 C:\Documents and Settings\All Users\Desktop\Wireshark.lnk 57 2008-11-19 05:07:15 No 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline.rar 64 2008-11-19 05:07:35 Yes 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline 65 2008-11-19 05:17:12 No 4096 C:\DOCUME~1\ADMINI~1\Desktop\360保~1.LNK 66 2008-11-19 05:21:37 No 2732032 C:\Documents and Settings\Administrator\Desktop\gdb 67 2008-11-19 05:21:37 No 2723840 C:\Documents and Settings\Administrator\Desktop\gdb.zip 68 2008-11-19 11:34:23 No 0 C:\Documents and Settings\Administrator\Desktop\recovered files 69 2008-11-19 18:51:45 No 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline 70 2008-11-19 18:51:45 No 5169152 C:\Documents and Settings\Administrator\Desktop\Uneraser_Setup(2).exe 71 2008-11-19 18:51:45 No 5169152 C:\Documents and Settings\Administrator\Desktop\Uneraser_Setup.exe rifiuti2-0.7.0/test/samples/INFO2-sample1.txt000066400000000000000000000033371346470066000206300ustar00rootroot00000000000000Recycle bin path: 'INFO2-sample1' Version: 5 OS Guess: Windows XP or 2003 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 44 2008-10-28 15:53:42 No 4096 C:\Documents and Settings\All Users\Desktop\有道桌面词典.lnk 45 2008-11-03 15:01:59 No 4096 C:\Documents and Settings\Administrator\Desktop\wongsir_url.txt 46 2008-11-06 09:20:58 No 2912256 C:\Documents and Settings\Administrator\Desktop\dd-wrt.v24_mini_wrt54g.bin 47 2008-11-13 12:08:39 No 765952 C:\Documents and Settings\Administrator\Desktop\theme\.svn 48 2008-11-13 12:11:33 No 5812224 C:\Documents and Settings\Administrator\Desktop\Config Client 49 2008-11-13 12:11:36 No 1847296 C:\Documents and Settings\Administrator\Desktop\Config Client.7z 50 2008-11-19 04:42:04 No 4096 C:\Documents and Settings\All Users\Desktop\Wireshark.lnk 57 2008-11-19 05:07:15 No 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline.rar 64 2008-11-19 05:07:35 Yes 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline 65 2008-11-19 05:17:12 No 4096 C:\Documents and Settings\Administrator\Desktop\360保险箱.lnk 66 2008-11-19 05:21:37 No 2732032 C:\Documents and Settings\Administrator\Desktop\gdb 67 2008-11-19 05:21:37 No 2723840 C:\Documents and Settings\Administrator\Desktop\gdb.zip 68 2008-11-19 11:34:23 No 0 C:\Documents and Settings\Administrator\Desktop\recovered files 69 2008-11-19 18:51:45 No 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline 70 2008-11-19 18:51:45 No 5169152 C:\Documents and Settings\Administrator\Desktop\Uneraser_Setup(2).exe 71 2008-11-19 18:51:45 No 5169152 C:\Documents and Settings\Administrator\Desktop\Uneraser_Setup.exe rifiuti2-0.7.0/test/samples/INFO2-sample1.xml000066400000000000000000000067741346470066000206210ustar00rootroot00000000000000 test_case/INFO2 5 44 N 4096 C:\Documents and Settings\All Users\Desktop\有道桌面词典.lnk 45 N 4096 C:\Documents and Settings\Administrator\Desktop\wongsir_url.txt 46 N 2912256 C:\Documents and Settings\Administrator\Desktop\dd-wrt.v24_mini_wrt54g.bin 47 N 765952 C:\Documents and Settings\Administrator\Desktop\theme\.svn 48 N 5812224 C:\Documents and Settings\Administrator\Desktop\Config Client 49 N 1847296 C:\Documents and Settings\Administrator\Desktop\Config Client.7z 50 N 4096 C:\Documents and Settings\All Users\Desktop\Wireshark.lnk 57 N 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline.rar 64 Y 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline 65 N 4096 C:\Documents and Settings\Administrator\Desktop\360保险箱.lnk 66 N 2732032 C:\Documents and Settings\Administrator\Desktop\gdb 67 N 2723840 C:\Documents and Settings\Administrator\Desktop\gdb.zip 68 N 0 C:\Documents and Settings\Administrator\Desktop\recovered files 69 N 2727936 C:\Documents and Settings\Administrator\Desktop\GetDataBackforFAT-v3.63_PConline 70 N 5169152 C:\Documents and Settings\Administrator\Desktop\Uneraser_Setup(2).exe 71 N 5169152 C:\Documents and Settings\Administrator\Desktop\Uneraser_Setup.exe rifiuti2-0.7.0/test/samples/INFO2-sample2000066400000000000000000000036741346470066000200170ustar00rootroot00000000000000 YYC:\WINDOWS\All Users\Desktop\Connect to the Internet.LNKternet.LNKYCC0C&CY0CYbCwY0LCCCYdY0Y\JYCHC4YtCzC:\WINDOWS\Desktop\Online Servicese Services1WS\Desktop\Online Services\AYCC0C&CY0CYbCwY0LCCCYdY0Y\JYCHC4Y Csz:\WINDOWS\Desktop\IE9-WindowsVista-x64-enu.exe64-enu.exe,Y4CC0C&CY04CYbCwY0LCC8CYdY0Y\JY8CH8C4Y8C?NMzC:\My Documents\Rsum.txt.txtm.txt.txtD\DC3.TXTz<v=hWEC0C&C0WEbCw㐁0LCCWE|0\J<WEHWE?D`A{C:\WINDOWS\Desktop\winzip100.exezip100.exeDC4.EXE| @Y̺CC0C&C0̺CYbCw㐁0LCCкCYdY0Y\JYкCHкC4YC {_:\WINDOWS\Desktop\111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111CF{C:\WINDOWS\Desktop\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345C`F1{rifiuti2-0.7.0/test/samples/INFO2-sample2-wrong-enc.txt000066400000000000000000000020671346470066000225250ustar00rootroot00000000000000Recycle bin path: 'INFO2-sample2' Version: 4 OS Guess: Windows 98 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 0 2015-04-20 00:07:36 No 32768 C:\WINDOWS\All Users\Desktop\Connect to the Internet.LNK 1 2015-04-20 00:07:42 No 32768 C:\WINDOWS\Desktop\Online Services 2 2015-04-20 00:09:43 Yes 524288 C:\WINDOWS\Desktop\IE9-WindowsVista-x64-enu.exe 3 2015-04-20 01:04:33 No 32768 C:\My Documents\R駸um<\E9>.txt.txt 4 2015-04-20 01:05:01 No 6258688 C:\WINDOWS\Desktop\winzip100.exe 5 2015-04-20 01:05:41 Yes 32768 C:\WINDOWS\Desktop\111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 6 2015-04-20 01:06:12 No 32768 C:\WINDOWS\Desktop\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 rifiuti2-0.7.0/test/samples/INFO2-sample2.txt000066400000000000000000000020641346470066000206250ustar00rootroot00000000000000Recycle bin path: 'INFO2-sample2' Version: 4 OS Guess: Windows 98 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path 0 2015-04-20 00:07:36 No 32768 C:\WINDOWS\All Users\Desktop\Connect to the Internet.LNK 1 2015-04-20 00:07:42 No 32768 C:\WINDOWS\Desktop\Online Services 2 2015-04-20 00:09:43 Yes 524288 C:\WINDOWS\Desktop\IE9-WindowsVista-x64-enu.exe 3 2015-04-20 01:04:33 No 32768 C:\My Documents\Résumé.txt.txt 4 2015-04-20 01:05:01 No 6258688 C:\WINDOWS\Desktop\winzip100.exe 5 2015-04-20 01:05:41 Yes 32768 C:\WINDOWS\Desktop\111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 6 2015-04-20 01:06:12 No 32768 C:\WINDOWS\Desktop\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 rifiuti2-0.7.0/test/samples/INFO2-sample2.xml000066400000000000000000000030431346470066000206040ustar00rootroot00000000000000 INFO2-sample2 C:\WINDOWS\All Users\Desktop\Connect to the Internet.LNK C:\WINDOWS\Desktop\Online Services C:\WINDOWS\Desktop\IE9-WindowsVista-x64-enu.exe C:\My Documents\Résumé.txt.txt C:\WINDOWS\Desktop\winzip100.exe C:\WINDOWS\Desktop\111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 C:\WINDOWS\Desktop\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 rifiuti2-0.7.0/test/samples/dir-2019-uncpath.txt000066400000000000000000000006231346470066000212550ustar00rootroot00000000000000Recycle bin path: 'dir-2019-uncpath' Version: 2 OS Guess: Windows 10 or above Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path $IW0RYW0.rtf 2019-05-07 20:56:04 7 \\WIN-163RLA0PH3N\somewhere\hahaha.rtf $I4OZLXW.bmp 2019-05-07 21:01:01 1714662 \\WIN-163RLA0PH3N\somewhere\পরীক্ষা.bmp $IYDW1CC.rtf 2019-05-07 21:08:55 7 \\WIN-163RLA0PH3N\somewhere\hahaha.rtf rifiuti2-0.7.0/test/samples/dir-2019-uncpath/000077500000000000000000000000001346470066000205135ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-2019-uncpath/$I4OZLXW.bmp000066400000000000000000000001541346470066000223770ustar00rootroot00000000000000) (\\WIN-163RLA0PH3N\somewhere\ .bmprifiuti2-0.7.0/test/samples/dir-2019-uncpath/$IW0RYW0.rtf000066400000000000000000000001521346470066000223530ustar00rootroot00000000000000LI'\\WIN-163RLA0PH3N\somewhere\hahaha.rtfrifiuti2-0.7.0/test/samples/dir-2019-uncpath/$IYDW1CC.rtf000066400000000000000000000001521346470066000223350ustar00rootroot00000000000000P,z'\\WIN-163RLA0PH3N\somewhere\hahaha.rtfrifiuti2-0.7.0/test/samples/dir-bad-uni.txt000066400000000000000000000007001346470066000205350ustar00rootroot00000000000000Recycle bin path: 'dir-bad-uni' Version: 1 OS Guess: Windows Vista - 8.1 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path $I77T7B0.ahk 2019-04-14 11:44:43 324 D:\𐂂𐌰𐎅𐠔𨋢.ahk $I77T7B1.ahk 2019-04-14 11:44:43 324 D:\𐂂𐌰𐎅𐠔<\uD860>.<\uDEE2>.ahk $I77T7B2.ahk 2019-04-14 11:44:43 324 D:\<\uDC82><\uD800>𐌰𐎅𐠔𨋢.ahk $I77T7B3.ahk 2019-04-14 11:44:43 324 D:\𐂂𐌰<\u05FF>𐎅𐠔𨋢.ahk rifiuti2-0.7.0/test/samples/dir-bad-uni/000077500000000000000000000000001346470066000177775ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-bad-uni/$I77T7B0.ahk000066400000000000000000000010401346470066000214660ustar00rootroot00000000000000D0QsD:\؂0؅`.ahkrifiuti2-0.7.0/test/samples/dir-bad-uni/$I77T7B1.ahk000066400000000000000000000010401346470066000214670ustar00rootroot00000000000000D0QsD:\؂0؅`..ahkrifiuti2-0.7.0/test/samples/dir-bad-uni/$I77T7B2.ahk000066400000000000000000000010401346470066000214700ustar00rootroot00000000000000D0QsD:\0؅`.ahkrifiuti2-0.7.0/test/samples/dir-bad-uni/$I77T7B3.ahk000066400000000000000000000010401346470066000214710ustar00rootroot00000000000000D0QsD:\؂0؅`.ahkrifiuti2-0.7.0/test/samples/dir-bad-uni/desktop.ini000066400000000000000000000002011346470066000221420ustar00rootroot00000000000000[.ShellClassInfo] CLSID={645FF040-5081-101B-9F08-00AA002F954E} LocalizedResourceName=@%SystemRoot%\system32\shell32.dll,-8964 rifiuti2-0.7.0/test/samples/dir-empty.txt000066400000000000000000000002401346470066000203530ustar00rootroot00000000000000Recycle bin path: 'dir-empty' Version: ??? (empty folder) OS detection failed Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path rifiuti2-0.7.0/test/samples/dir-empty/000077500000000000000000000000001346470066000176165ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-empty/desktop.ini000066400000000000000000000002011346470066000217610ustar00rootroot00000000000000[.ShellClassInfo] CLSID={645FF040-5081-101B-9F08-00AA002F954E} LocalizedResourceName=@%SystemRoot%\system32\shell32.dll,-8964 rifiuti2-0.7.0/test/samples/dir-mixed/000077500000000000000000000000001346470066000175665ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-mixed/$IDNLPD4.exe000066400000000000000000000001221346470066000213660ustar00rootroot00000000000000P `N zC:\Temp\FAU\FAU.x86\dd.exerifiuti2-0.7.0/test/samples/dir-mixed/$IEQWWMF.exe000066400000000000000000000010401346470066000214470ustar00rootroot00000000000000` `{*C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\fmdata.exerifiuti2-0.7.0/test/samples/dir-sample1.txt000066400000000000000000000037121346470066000205660ustar00rootroot00000000000000Recycle bin path: 'dir-sample1' Version: 1 OS Guess: Windows Vista - 8.1 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path $IUVFB0M.rtf 2007-09-21 06:32:46 155 C:\Users\student\Desktop\New Rich Text Document.rtf $I0JGHX7 2007-09-21 06:47:49 0 C:\Users\student\Desktop\New Folder 1 $I1IS2OK.txt 2007-09-21 06:48:13 0 C:\Users\student\Desktop\New Text Document blah.txt $IYAR1YY.exe 2007-09-21 07:54:23 ??? C:\dd.exe $I95CUKU 2007-09-21 08:02:59 4096 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\sparsefile $IHMU3NR.zip 2007-09-21 08:17:19 5025829 C:\Users\student\Downloads\fau-1.3.0.2355(rc3).zip $I7FV8IY.exe 2007-09-21 08:23:18 153478296 C:\Users\student\Downloads\VMware-server-installer-1.0.4-56528.exe $IMG2SSB 2007-09-21 08:28:57 0 C:\Users\student\Desktop\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 $IZK01YL.txt 2007-09-21 08:31:35 11 C:\Users\student\Desktop\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012\1234567.txt $I1TDH1G.exe 2007-09-21 08:38:30 704512 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\nc.exe $IEQWWMF.exe 2007-09-21 08:38:30 679936 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\fmdata.exe $IFRN1CZ.exe 2007-09-21 08:38:30 110592 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\wipe.exe $IW527XU.exe 2007-09-21 08:38:30 331776 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\volume_dump.exe $IC6GEAW.exe 2007-09-21 08:50:16 ??? C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\dd.exe $IZUFRX4.vmdk 2007-09-21 09:22:25 10737418240 C:\Virtual Machines\Windows XP Professional\Windows XP Professional-flat.vmdk rifiuti2-0.7.0/test/samples/dir-sample1.xml000066400000000000000000000065571346470066000205610ustar00rootroot00000000000000 $IZK01YL.txt 11 C:\Users\student\Desktop\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012\1234567.txt $IW527XU.exe 331776 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\volume_dump.exe $IHMU3NR.zip 5025829 C:\Users\student\Downloads\fau-1.3.0.2355(rc3).zip $I7FV8IY.exe 153478296 C:\Users\student\Downloads\VMware-server-installer-1.0.4-56528.exe $I95CUKU 4096 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\sparsefile $IC6GEAW.exe 20480 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\dd.exe $I0JGHX7 0 C:\Users\student\Desktop\New Folder 1 $IYAR1YY.exe 20480 C:\dd.exe $IFRN1CZ.exe 110592 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\wipe.exe $IEQWWMF.exe 679936 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\fmdata.exe $IUVFB0M.rtf 155 C:\Users\student\Desktop\New Rich Text Document.rtf $I1TDH1G.exe 704512 C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\nc.exe $I1IS2OK.txt 0 C:\Users\student\Desktop\New Text Document blah.txt $IMG2SSB 0 C:\Users\student\Desktop\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 $IZUFRX4.vmdk 10737418240 C:\Virtual Machines\Windows XP Professional\Windows XP Professional-flat.vmdk rifiuti2-0.7.0/test/samples/dir-sample1/000077500000000000000000000000001346470066000200225ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-sample1/$I0JGHX7000066400000000000000000000010401346470066000210240ustar00rootroot00000000000000SC:\Users\student\Desktop\New Folder 1rifiuti2-0.7.0/test/samples/dir-sample1/$I1IS2OK.txt000066400000000000000000000010401346470066000216430ustar00rootroot00000000000000`daC:\Users\student\Desktop\New Text Document blah.txtrifiuti2-0.7.0/test/samples/dir-sample1/$I1TDH1G.exe000066400000000000000000000010401346470066000215650ustar00rootroot00000000000000 `{*C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\nc.exerifiuti2-0.7.0/test/samples/dir-sample1/$I7FV8IY.exe000066400000000000000000000010401346470066000216310ustar00rootroot00000000000000% N>(C:\Users\student\Downloads\VMware-server-installer-1.0.4-56528.exerifiuti2-0.7.0/test/samples/dir-sample1/$I95CUKU000066400000000000000000000010401346470066000210420ustar00rootroot00000000000000%C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\sparsefilerifiuti2-0.7.0/test/samples/dir-sample1/$IC6GEAW.exe000066400000000000000000000010371346470066000216170ustar00rootroot00000000000000P/Tn,C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\dd.exerifiuti2-0.7.0/test/samples/dir-sample1/$IEQWWMF.exe000066400000000000000000000010401346470066000217030ustar00rootroot00000000000000` `{*C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\fmdata.exerifiuti2-0.7.0/test/samples/dir-sample1/$IFRN1CZ.exe000066400000000000000000000010401346470066000216400ustar00rootroot00000000000000`{*C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\wipe.exerifiuti2-0.7.0/test/samples/dir-sample1/$IHMU3NR.zip000066400000000000000000000010401346470066000216720ustar00rootroot00000000000000%L'C:\Users\student\Downloads\fau-1.3.0.2355(rc3).ziprifiuti2-0.7.0/test/samples/dir-sample1/$IMG2SSB000066400000000000000000000010401346470066000210520ustar00rootroot00000000000000Ps)C:\Users\student\Desktop\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012rifiuti2-0.7.0/test/samples/dir-sample1/$IUVFB0M.rtf000066400000000000000000000010401346470066000216460ustar00rootroot00000000000000,29C:\Users\student\Desktop\New Rich Text Document.rtfrifiuti2-0.7.0/test/samples/dir-sample1/$IW527XU.exe000066400000000000000000000010401346470066000216160ustar00rootroot00000000000000PZ}*C:\Users\student\Downloads\fau-1.3.0.2355(rc3)\fau\FAU.x86\volume_dump.exerifiuti2-0.7.0/test/samples/dir-sample1/$IYAR1YY.exe000066400000000000000000000010371346470066000217010ustar00rootroot00000000000000Pp$C:\dd.exerifiuti2-0.7.0/test/samples/dir-sample1/$IZK01YL.txt000066400000000000000000000010401346470066000216650ustar00rootroot00000000000000 bt)C:\Users\student\Desktop\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012\1234567.txtrifiuti2-0.7.0/test/samples/dir-sample1/$IZUFRX4.vmdk000066400000000000000000000010401346470066000220570ustar00rootroot00000000000000`p0C:\Virtual Machines\Windows XP Professional\Windows XP Professional-flat.vmdkrifiuti2-0.7.0/test/samples/dir-sample1/$RUVFB0M.rtf000066400000000000000000000002301346470066000216570ustar00rootroot00000000000000{\rtf1\ansi\deff0{\fonttbl{\f0\fswiss\fcharset0 Arial;}} {\*\generator Msftedit 5.41.21.2506;}\viewkind4\uc1\pard\lang1033\f0\fs20 lalala hahaha\par } rifiuti2-0.7.0/test/samples/dir-win10-01.txt000066400000000000000000000014741346470066000204030ustar00rootroot00000000000000Recycle bin path: 'dir-win10-01' Version: 2 OS Guess: Windows 10 or above Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path $IKEGS1G 2015-04-04 17:19:52 0 C:\Users\tester\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 $IQ7LAXT.png 2015-04-04 17:20:01 6455 C:\Users\tester\Pictures\web-canvas.png $I7R52EG.txt 2015-04-04 17:24:09 14 C:\Temp\foobat.txt.txt $IBBFODN 2015-04-07 23:19:35 7 C:\Temp\𨳊𨶙閪邨鰂 $IHO61YT 2015-04-07 23:32:07 12884901888 C:\Temp\largesparsefile $IROMPZ0.exe 2015-04-19 10:49:59 1761792 C:\Temp\FAU\FAU.x64\dd.exe $IDNLPD4.exe 2015-04-19 10:50:51 872448 C:\Temp\FAU\FAU.x86\dd.exe rifiuti2-0.7.0/test/samples/dir-win10-01.xml000066400000000000000000000023671346470066000203660ustar00rootroot00000000000000 test/samples/dir-win10-01 C:\Temp\foobat.txt.txt C:\Temp\𨳊𨶙閪邨鰂 C:\Temp\FAU\FAU.x86\dd.exe C:\Temp\largesparsefile C:\Users\tester\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 C:\Users\tester\Pictures\web-canvas.png C:\Temp\FAU\FAU.x64\dd.exe rifiuti2-0.7.0/test/samples/dir-win10-01/000077500000000000000000000000001346470066000176345ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-win10-01/$I7R52EG.txt000066400000000000000000000001121346470066000214170ustar00rootroot000000000000008)nC:\Temp\foobat.txt.txtrifiuti2-0.7.0/test/samples/dir-win10-01/$IBBFODN000066400000000000000000000000741346470066000206670ustar00rootroot00000000000000OqC:\Temp\ccؙݪrifiuti2-0.7.0/test/samples/dir-win10-01/$IDNLPD4.exe000066400000000000000000000001221346470066000214340ustar00rootroot00000000000000P `N zC:\Temp\FAU\FAU.x86\dd.exerifiuti2-0.7.0/test/samples/dir-win10-01/$IHO61YT000066400000000000000000000001141346470066000206620ustar00rootroot00000000000000NqC:\Temp\largesparsefilerifiuti2-0.7.0/test/samples/dir-win10-01/$IKEGS1G000066400000000000000000000010121346470066000206470ustar00rootroot00000000000000Z;nC:\Users\tester\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890rifiuti2-0.7.0/test/samples/dir-win10-01/$IQ7LAXT.png000066400000000000000000000001541346470066000214770ustar00rootroot000000000000007nn(C:\Users\tester\Pictures\web-canvas.pngrifiuti2-0.7.0/test/samples/dir-win10-01/$IROMPZ0.exe000066400000000000000000000001221346470066000214760ustar00rootroot00000000000000@ݔzC:\Temp\FAU\FAU.x64\dd.exerifiuti2-0.7.0/test/samples/dir-win10-01/$R7R52EG.txt000066400000000000000000000000161346470066000214330ustar00rootroot00000000000000Blah blah blahrifiuti2-0.7.0/test/samples/dir-win10-01/$RKEGS1G000066400000000000000000000000001346470066000206540ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/dir-win10-01/$RQ7LAXT.png000066400000000000000000000144671346470066000215240ustar00rootroot00000000000000PNG  IHDRl~QgAMA asRGBPLTE rxwDFH Z[[-/189<ABDG{{UVY[]a7:=㬰kmp58;<>Bmorefjwm69="$&37:(+-9}h9AAwꌎpãrbi%-"ø~uEIIϼTlN5WW,j9{)}޿[(,WA8DulblgaJe̷CB&MÂ`mpgWI쉌¤Z,M|ZOϓ[N(/CB'2_tHkߧb6a|<\BY73I{}p֣|5PYc;{^j콻X[VM8Ī鞞-?Ve13lrCv=u.N.ރF|n~d;_+ sZ$@QABEqjQ/p=SO,{~$F«TJHZFk\(mD-TT#*!X0I dH(1~-窔T.gD-HEBxDOT ,~ڰ-(8Gggδ9axUH*}O^pa}kBT$GGӯ0f P*E"t?T_p9s=]> /\$x uP"a3lwg$},(&uܝ3{ $l<61{->a ܽz?g-+H%`ľ{2a;tw׮ぁ N ُ} >[b?]rE&l0&@?25Cp)$ ɔX$<#/#G_7ߘx18@(gdz '~]}xwO/T( )lg[Aў={1~͚5 W&>! Ӎ AٱpOuw4JuG/,1%l^m=V@[ }i֬wf&B-! j ~!pGêǷÉ<d>Z2Z\#;amIrEl*i*lK <:24npӳe:e2п}ǎ_@m8PW%%[<vV$t۶,˘'}!/@k/_b6?hB!'x:Lg߸?4G_ӟxvAQQ[ׯ_/0\I$Fq$g?4h^~Pq(}ڹs=u}jR 9HU&J$=^'?Dş_cۆ1DZώيB')a3`!G(303^wnl\V 1ށw~ܹoӳIu\'L-NS*0,㶊%<n*m =ysmr4!&1;ҺO0ܮ?bG"=& BY6`b/NV)~ c~++aw{fg鼜 T~x&FiggݷV~"[cif[߮rvo*$Z6lTڑOnn۝ =Bw:uXvZ1lDG~YETi45][>1 qꅭ==Y8nBB"MLVKLcz `M|uDؕM5o]y9^L8mlyzZgϡ{*B:L*`7WG̸؃-j |||bDTT%,ys7jzϗĆ{3믕h

>KDh4⪬G?_SU$ɿ҃w\{ӦlB@/C JۉDPDD͒kЎ5Wh4%ĝ q\</^ ./U0}Z}äb(t˙L`#<#~δ}J|@UJPvFxn6{`l8:`cIA6ܸ熍6IЭX)=v%=tqٔYDI-#t0().FolL^w߾}i4P GDz)qw(2O@;ڕ;pCXp0=lPll0^_{Id^dɵҬPh:7Ŏސ Rym #…K{o .YU 2fiS}Ig@% ؇2|eQ[˖5-&B!)z:]ḏbUJ٥rO :&1`&vDv8|Vq]P޴Tx _xȑ+S+Z_;{)4*!!+3 3S2[%^6}2861|!ƕ[qUz*7A} @9ꎋ?={6^Y~6!~玫"M؛Ur2B§%2>Zqn{퇗£XKrݩ{pa0gZ;KB%3 p6fC1L􌽧M |d-(zJ^RV5. XʰK/--3]ZVLw>p|\of& 8`lxDrA#Ტy-g6nnvjiy{DN زӳBC҄Qe%=DG 7FRRL,{ueA/G+*߼y!1'޻ 'ZtM&LPG)K`C%m`#۳'Om(Xa0 )5e*P-AFv:"Jr#(sOERc7Jj)RVˏ.]ҖG-t|oGGkDz3їqtC,ݤ?Ѥp'U".s|q,S%%7.z;Յ G<ǒ~+, q&z5'NCMj2RP,"cC. <7() -Ym\A$KaR|AIBo@ 𚛈M.Rll0Uf|CWr@KBooG<Oۖ' ?LQQ[S)a5f Ą$ƉVgffxxk[r?U___I1k%lo~G/hL!Lt߂+iZC(} $HTLvΔN|حanij ~DIX3lbR%pG?n3'ΞMEFGnҍߊWtBC3^)E{>-T#?YrwҲ.\TI5R~OԩDqHȌ/?3Qw:W'M1}k. _WsR̷ y2(w|z{YGmkxY=|6l-rys$땴T_MZCr^;zO#8oW/-T 52/ὄn! 6͵}1"H__ԺG'SN{TJj?ecŰ7DR5kkE}XCrnvrVSRflˢ=7 kfoقmr2z[5/OHL(C)cwƔI řzj @_sgF|aR3g ܣB(q,#oL9ߝg??v2 Nh8b1,Ͼ1e;9>qBR Çgq1nDh5C j5%͉cR1,8c2O)oN0&OS?~$!EaԫZ&N N2ᯍ}.L%St1ɘ3dž9ZZ ?PI:U7?Jgho3;?O?(K?+I>IENDB`rifiuti2-0.7.0/test/samples/dir-win10-01/desktop.ini000066400000000000000000000002011346470066000217770ustar00rootroot00000000000000[.ShellClassInfo] CLSID={645FF040-5081-101B-9F08-00AA002F954E} LocalizedResourceName=@%SystemRoot%\system32\shell32.dll,-8964 rifiuti2-0.7.0/test/samples/japanese-path-dir.txt000066400000000000000000000002541346470066000217420ustar00rootroot00000000000000Recycle bin path: './ごみ箱/dir-empty' Version: ??? (empty folder) OS detection failed Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Size Path rifiuti2-0.7.0/test/samples/japanese-path-file.txt000066400000000000000000000002621346470066000221020ustar00rootroot00000000000000Recycle bin path: './ごみ箱/INFO2-empty' Version: 5 OS Guess: Windows 2000, XP or 2003 Time zone: Coordinated Universal Time (UTC) [+0000] Index Deleted Time Gone? Size Path rifiuti2-0.7.0/test/samples/ごみ箱/000077500000000000000000000000001346470066000211245ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/ごみ箱/INFO2-empty000066400000000000000000000000241346470066000230140ustar00rootroot00000000000000 rifiuti2-0.7.0/test/samples/ごみ箱/dir-empty/000077500000000000000000000000001346470066000230365ustar00rootroot00000000000000rifiuti2-0.7.0/test/samples/ごみ箱/dir-empty/desktop.ini000066400000000000000000000002011346470066000252010ustar00rootroot00000000000000[.ShellClassInfo] CLSID={645FF040-5081-101B-9F08-00AA002F954E} LocalizedResourceName=@%SystemRoot%\system32\shell32.dll,-8964 rifiuti2-0.7.0/test/test_cli_option.at000066400000000000000000000043101346470066000177620ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_SETUP([Short Options]) AT_KEYWORDS([option]) _r2_chk_status_only([-?]) _r2_chk_status_only([-v]) _r2_chk_opt_status_only([-t :]) _r2_chk_opt_status_only([-n]) AT_CLEANUP AT_SETUP([Long Options]) AT_KEYWORDS([option]) _r2_chk_status_only([--help-all]) _r2_chk_opt_status_only([--delimiter=:]) _r2_chk_opt_status_only([--no-heading]) AT_CLEANUP AT_SETUP([Invalid options]) AT_KEYWORDS([option]) _r2_chk_opt_status_only([--invalid-option], [1]) AX_AT_CHECK_PATTERN([dnl $progf -l foobar $sample/INFO2-sample2], [1],, [dnl Error parsing options: 'foobar' encoding is not supported by glib library .* https://.* ]) AT_CLEANUP AT_SETUP([Duplicative options]) AT_KEYWORDS([option]) AT_CHECK([dnl $progf -l ASCII -l CP1252 $sample/INFO2-sample2], [1],, [dnl Error parsing options: Multiple encoding options disallowed. ]) _r2_chk_opt_err([-t : -t ,], [1], [dnl Error parsing options: Multiple delimiter options disallowed. ]) _r2_chk_opt_err([-o file1 -o file2], [1], [dnl Error parsing options: Multiple output destinations disallowed. ]) AT_CLEANUP AT_SETUP([Options with empty arg]) AT_KEYWORDS([option]) _r2_chk_opt_err([-o ""], [1], [dnl Error parsing options: Empty output filename disallowed. ]) AT_CHECK([dnl $progf -l "" $sample/INFO2-sample2], [1],, [dnl Error parsing options: Empty encoding option disallowed. ]) AT_CLEANUP dnl TODO check stderr too AT_SETUP([Wrong combinations]) AT_KEYWORDS([option]) _r2_chk_opt_status_only([-x -t :], [1]) _r2_chk_opt_status_only([-x -n], [1]) AT_CLEANUP dnl TODO check stderr too AT_SETUP([Err on no file args]) AT_KEYWORDS([file option]) _r2_chk_status_only([-x], [1]) AT_CLEANUP dnl TODO check stderr too AT_SETUP([Err on multiple file args]) AT_KEYWORDS([file option]) _r2_chk_status_only([foo bar baz], [1]) AT_CLEANUP AT_SETUP([Escaped char in delimiter]) AT_KEYWORDS([option]) AT_CHECK([ $awk '{ gsub("\t","\n\t"); print; }' < $sample/INFO2-sample1.txt > expout cd $sample $progf -t "\n\t" INFO2-sample1 ],, [expout], []) AT_CHECK([ $awk '{ gsub("\t","\n\t"); print; }' < $sample/dir-sample1.txt > expout cd $sample $progd -t "\n\t" dir-sample1 ],, [expout], []) AT_CLEANUP rifiuti2-0.7.0/test/test_common.at000066400000000000000000000013031346470066000171120ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 m4_defun([_r2_chk_status_only], [dnl AT_CHECK([$progf $1], [$2], [ignore], [ignore]) AT_CHECK([$progd $1], [$2], [ignore], [ignore]) ]) m4_defun([_r2_chk_opt_status_only], [dnl AT_CHECK([$progf $1 $sample/INFO2-empty], [$2], [ignore], [ignore]) AT_CHECK([$progd $1 $sample/dir-empty] , [$2], [ignore], [ignore]) ]) m4_defun([_r2_chk_opt_err], [dnl AT_CHECK([$progf $1 $sample/INFO2-empty], [$2], [], [$3]) AT_CHECK([$progd $1 $sample/dir-empty] , [$2], [], [$3]) ]) m4_defun([_r2_basic_compare], [ AT_CHECK([ rm -f expout $as_ln_s $sample/$2 expout cd $sample $1 ], 0, [expout]) ]) rifiuti2-0.7.0/test/test_encoding.at000066400000000000000000000036711346470066000174220ustar00rootroot00000000000000dnl -*- coding: utf-8; mode: m4; -*- dnl vim: set fileencoding=utf-8 filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 dnl dnl ごみ箱 is 'recycle bin' in Japanese dnl AT_SETUP([Unicode characters in file argument]) AT_KEYWORDS([encoding]) AT_CHECK([ $as_ln_s $sample/japanese-path-file.txt expout cd $sample $progf ./ごみ箱/INFO2-empty ],, [expout]) AT_CHECK([ rm -f expout $as_ln_s $sample/japanese-path-dir.txt expout cd $sample $progd ./ごみ箱/dir-empty ],, [expout]) AT_CLEANUP AT_SETUP([Legacy path encoding - correct]) AT_SKIP_IF([test -z "${gbk_name}"]) AT_KEYWORDS([info2 encoding]) _r2_basic_compare([$progf -l "${gbk_name}" INFO2-sample1], [INFO2-sample1-alt.txt]) AT_CLEANUP AT_SETUP([Legacy path encoding - illegal (1)]) AT_KEYWORDS([info2 encoding]) AX_AT_CHECK_PATTERN([ cd $sample $progf -l xxx INFO2-sample1 ], 1,, [dnl .* encoding is not supported by glib library on this system\..* https://.* ]) AT_CLEANUP dnl dnl Demands ASCII-compatible encoding, EBCDIC not one of those dnl AT_SETUP([Legacy path encoding - illegal (2)]) AT_KEYWORDS([info2 encoding]) AT_SKIP_IF([test -z "${ebcdic_latin1_name}"]) AX_AT_CHECK_PATTERN([ cd $sample $progf -l "${ebcdic_latin1_name}" INFO2-sample1 ], 1,, [dnl .* can't possibly be a code page or compatible encoding .* ]) AT_CLEANUP dnl dnl Original file in Windows ANSI (CP1252), but users attempts dnl to treat it as Shift-JIS, and got hex escapes as result dnl AT_SETUP([Legacy path encoding - wrong]) AT_KEYWORDS([encoding]) AT_SKIP_IF([test -z "${sjis_name}"]) AT_CHECK([ $as_ln_s $sample/INFO2-sample2-wrong-enc.txt expout cd $sample $progf -l "${sjis_name}" INFO2-sample2 ], 5, [expout], [ignore]) AT_CLEANUP dnl dnl Test for: single surrogate, swapped surrogate pair, unassigned codepoint dnl AT_SETUP([Bad unicode path]) AT_KEYWORDS([encoding]) AT_CHECK([ $as_ln_s $sample/dir-bad-uni.txt expout cd $sample $progd dir-bad-uni ], 5, [expout], [ignore]) AT_CLEANUP rifiuti2-0.7.0/test/test_faulty_dir.at000066400000000000000000000030711346470066000177700ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_SETUP([Index files of different versions]) AT_KEYWORDS([recycledir crafted]) AX_AT_CHECK_PATTERN([ cd $sample $progd dir-mixed ], [3],, [dnl Index files come from multiple versions of Windows\..* ]) AT_CLEANUP AT_SETUP([Directory w/o Windows access permission]) AT_KEYWORDS([recycledir crafted windows]) AT_CHECK([which icacls.exe > /dev/null || exit 77])dnl need 2003 SP2 or later AT_SKIP_IF([! $is_mingw]) dnl dnl MSYS2_ARG_CONV_EXCL would prevent command line options automagically dnl treated as unix paths (and translated into windows paths or drive letters) dnl AT_CHECK([ cp -pR $sample/dir-win10-01 dir1 icacls.exe dir1 /inheritance:r > /dev/null icacls.exe dir1 /grant:r "Users:(OI)(CI)(S,REA)" > /dev/null $progd dir1 ], [2],, [Error listing directory: Insufficient permission. ], [MSYS2_ARG_CONV_EXCL="/reset" icacls.exe dir1 /reset > /dev/null], [MSYS2_ARG_CONV_EXCL="/reset" icacls.exe dir1 /reset > /dev/null]) AT_CLEANUP dnl MinGW mounts root with noacl option by default. Though user can change dnl mount options, it is safer to skip this test altogether AT_SETUP([Directory w/o Unix access permission]) AT_KEYWORDS([recycledir crafted unix]) AT_SKIP_IF([$is_mingw]) dnl in front of root, permission is futile AT_SKIP_IF([test "`id -u`" = "0"]) AX_AT_CHECK_PATTERN([ cp -pR $sample/dir-win10-01 dir1 chmod u= dir1 $progd dir1 ], [2],, [Error opening directory 'dir1': Error opening directory .+dir1.+: Permission denied ], [chmod u=rwx dir1]) AT_CLEANUP rifiuti2-0.7.0/test/test_glib_iconv.c000066400000000000000000000007251346470066000175620ustar00rootroot00000000000000#include int main (int argc, char **argv) { GIConv cd; if (argc < 2 || *(argv[1]) == '\0') { return 2; } /* * In rifiuti2 we only need → UTF-8 conversion, * so we only test for this case. There are some odd OSes * where even identity conversion can be unsupported (say * CP936 → CP936), such as on Solaris. */ cd = g_iconv_open ("UTF-8", argv[1]); if (cd != (GIConv) -1) g_iconv_close (cd); return (cd == (GIConv) -1); } rifiuti2-0.7.0/test/test_parse_dir.at000066400000000000000000000015271346470066000176020ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_SETUP([Empty $Recycle.bin]) AT_KEYWORDS([recycledir]) _r2_basic_compare([$progd dir-empty], [dir-empty.txt]) AT_CLEANUP AT_SETUP([$Recycle.bin Sample 1 - Vista]) AT_KEYWORDS([recycledir]) _r2_basic_compare([$progd dir-sample1], [dir-sample1.txt]) AT_CLEANUP AT_SETUP([$Recycle.bin Sample 2 - Win 10]) AT_KEYWORDS([recycledir]) _r2_basic_compare([$progd dir-win10-01], [dir-win10-01.txt]) AT_CLEANUP AT_SETUP([$Recycle.bin single index file]) AT_KEYWORDS([recycledir]) AT_CHECK([ grep 'IHO61YT' $sample/dir-win10-01.txt > expout $progd -n $sample/dir-win10-01/\$IHO61YT ],, [expout], []) AT_CLEANUP AT_SETUP([$Recycle.bin UNC path]) AT_KEYWORDS([recycledir unc]) _r2_basic_compare([$progd dir-2019-uncpath], [dir-2019-uncpath.txt]) AT_CLEANUP rifiuti2-0.7.0/test/test_parse_info2.at000066400000000000000000000030031346470066000200300ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_SETUP([Empty INFO2]) AT_KEYWORDS([info2]) _r2_basic_compare([$progf INFO2-empty], [INFO2-empty.txt]) AT_CLEANUP AT_SETUP([INFO2 Sample 1 - 95]) AT_KEYWORDS([info2]) AT_SKIP_IF([test -z "${sjis_name}"]) _r2_basic_compare([$progf -l "${sjis_name}" INFO-95-ja-1], [INFO-95-ja-1.txt]) AT_CLEANUP AT_SETUP([INFO2 Sample 2 - NT4]) AT_KEYWORDS([info2]) _r2_basic_compare([$progf INFO-NT-en-1], [INFO-NT-en-1.txt]) AT_CLEANUP AT_SETUP([INFO2 Sample 3 - 98]) AT_KEYWORDS([info2]) _r2_basic_compare([$progf -l CP1252 INFO2-sample2], [INFO2-sample2.txt]) AT_CLEANUP AT_SETUP([INFO2 Sample 4 - ME]) AT_KEYWORDS([info2]) _r2_basic_compare([$progf -l CP1252 INFO2-ME-en-1], [INFO2-ME-en-1.txt]) AT_CLEANUP AT_SETUP([INFO2 Sample 5 - 2000]) AT_KEYWORDS([info2]) _r2_basic_compare([$progf INFO2-2k-cht-1], [INFO2-2k-cht-1.txt]) AT_CLEANUP AT_SETUP([INFO2 Sample 6 - XP/03]) AT_KEYWORDS([info2]) _r2_basic_compare([$progf INFO2-sample1], [INFO2-sample1.txt]) AT_CLEANUP AT_SETUP([INFO2 - UNC legacy path 1]) AT_KEYWORDS([info2 unc]) _r2_basic_compare([$progf -l ASCII INFO2-me-en-uncpath], [INFO2-me-en-uncpath.txt]) AT_CLEANUP AT_SETUP([INFO2 - UNC legacy path 2]) AT_KEYWORDS([info2 unc]) _r2_basic_compare([$progf -l ${big5_name} INFO2-2k-tw-uncpath], [INFO2-2k-tw-uncpath.txt]) AT_CLEANUP AT_SETUP([INFO2 - UNC unicode path]) AT_KEYWORDS([info2 unc]) _r2_basic_compare([$progf INFO2-03-tw-uncpath], [INFO2-03-tw-uncpath.txt]) AT_CLEANUPrifiuti2-0.7.0/test/test_read_write.at000066400000000000000000000020021346470066000177440ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_SETUP([Err on non-existent input]) AT_KEYWORDS([file]) _r2_chk_status_only([foobar], [2]) AT_CLEANUP AT_SETUP([Err on non-regular file]) AT_KEYWORDS([file unix]) _r2_chk_status_only([/dev/zero], [2]) AT_CLEANUP dnl g_file_test() was not so usable on Windows: NUL, CON etc are considered dnl as regular files. Therefore they can't be determined ahead as unusable, dnl they have to be actually parsed. Only MinGW can access the special files; dnl cygwin hides them from user. AT_SETUP([Err on non-regular file (Windows)]) AT_KEYWORDS([file windows]) AT_SKIP_IF([! $is_mingw]) _r2_chk_status_only([nul], [3]) AT_CLEANUP AT_SETUP([UTF-8 console/file output are equal]) AT_KEYWORDS([file]) AT_CHECK([ $progf -o expout $sample/INFO2-sample1 $progf $sample/INFO2-sample1 ],, [expout]) AT_CHECK([ rm -f expout $progd -o expout $sample/dir-sample1 $progd $sample/dir-sample1 ],, [expout]) AT_CLEANUP rifiuti2-0.7.0/test/test_xml.at000066400000000000000000000015451346470066000164320ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_SETUP([INFO2: XML validation]) AT_KEYWORDS([info2 xml]) AT_SKIP_IF([! $has_xmllint]) AT_CHECK([ $progf -x $sample/INFO2-sample1 | \ $xmllint --noout - ]) AT_CLEANUP AT_SETUP([INFO2: DTD validation]) AT_KEYWORDS([info2 xml]) AT_SKIP_IF([! $has_xmllint]) AT_CHECK([ $progf -x $sample/INFO2-sample1 | \ $xmllint --noout --dtdvalid $srcdir/rifiuti.dtd - ]) AT_CLEANUP AT_SETUP([$Recycle.bin: XML validation]) AT_KEYWORDS([recycledir xml]) AT_SKIP_IF([! $has_xmllint]) AT_CHECK([ $progd -x $sample/dir-sample1 | \ $xmllint --noout - ]) AT_CLEANUP AT_SETUP([$Recycle.bin: DTD validation]) AT_KEYWORDS([recycledir xml]) AT_SKIP_IF([! $has_xmllint]) AT_CHECK([ $progd -x $sample/dir-sample1 | \ $xmllint --noout --dtdvalid $srcdir/rifiuti.dtd - ]) AT_CLEANUP rifiuti2-0.7.0/test/testsuite.at000066400000000000000000000021141346470066000166150ustar00rootroot00000000000000dnl -*- mode: m4; -*- dnl vim: set filetype=m4 ts=4 sw=4 noexpandtab : dnl dnl Test suite for rifiuti2 AT_INIT AT_COPYRIGHT([ Copyright (c) 2015-2019, Abel Cheung All rights reserved. Makes use of macros from pyrediff project, which carries following notice: Copyright (c) 2013-2017 Luke Mewburn luke@mewburn.net Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. ]) m4_include([ax_at_check_pattern.m4]) m4_include([test_common.at]) AT_BANNER([Command Line Options]) m4_include([test_cli_option.at]) AT_BANNER([Basic Read/Write Check]) m4_include([test_read_write.at]) AT_BANNER([Parsing INFO2]) m4_include([test_parse_info2.at]) AT_BANNER([Parsing $Recycle.bin folder]) m4_include([test_parse_dir.at]) AT_BANNER([Parse faulty or crafted folder]) m4_include([test_faulty_dir.at]) AT_BANNER([Character Encoding Tests]) m4_include([test_encoding.at]) AT_BANNER([XML Validation]) m4_include([test_xml.at])