libdc0-0.3.24~svn3121/0000755000175000017500000000000011556467000013225 5ustar sikonsikonlibdc0-0.3.24~svn3121/AUTHORS0000644000175000017500000000031711074130777014301 0ustar sikonsikonMathias Küster Mario Boikov Stephen Leaf François Gannaz Edward Sheldrake libdc0-0.3.24~svn3121/Makefile.dist0000644000175000017500000000027511033457111015623 0ustar sikonsikonall: $(info Run "autoreconf --verbose --force --install" to generate configure) $(info This requires automake, autoconf and libtool.) $(info This is not required for released tarballs.) libdc0-0.3.24~svn3121/configure.in0000644000175000017500000001561411256231515015542 0ustar sikonsikonAC_INIT([dclib], [0.3.24svn], [http://sourceforge.net/tracker/?group_id=181579&atid=897767]) dnl there is also a version in hex in dcos.h.in AC_CONFIG_SRCDIR([COPYING.OpenSSL]) AC_CONFIG_AUX_DIR([admin]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST AM_INIT_AUTOMAKE dnl yes dclib is C++ so do all tests as C++ AC_LANG([C++]) is_mingw32="false" case $host in *mingw32) is_mingw32="true" esac AM_CONDITIONAL([WIN32], [test x$is_mingw32 = "xtrue"]) LARGEFILESUPPORT="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE" AC_ARG_ENABLE([lfs], [AS_HELP_STRING([--disable-lfs],[disable largefile (files larger than 2GiB) support (default enabled)])], [ if test "x$enableval" = "xno" then LARGEFILESUPPORT="" fi ] ) dnl these have changed but I do not want to start doing dnl 1000 tests of "does -Wsome-unusual-option-only-in-gcc-4.3 work?" WARNINGFLAGS="-Wall -W -pedantic -Wno-long-long -Wundef -Wconversion" AC_ARG_ENABLE([warnings], [AS_HELP_STRING([--disable-warnings],[disable compiler warnings (default enabled)])], [ if test "x$enableval" = "xno" then WARNINGFLAGS="" fi ] ) DEBUGFLAGS="" DEBUGCOMPILE="" AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug],[enable debugging support (default disabled)])], [ if test "x$enableval" = "xyes" then DEBUGFLAGS="-DDEBUG" DEBUGCOMPILE="-g" fi ] ) dnl really -D_GNU_SOURCE should be used for strcasestr and canonicalize_file_name dnl but it compiles without it PACKAGE_FLAGS="$DEBUGFLAGS $WARNINGFLAGS $LARGEFILESUPPORT -D_REENTRANT" case $host in *-*-linux-gnu) PACKAGE_FLAGS="$PACKAGE_FLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE" esac AC_SUBST(PACKAGE_FLAGS) AC_SUBST(DEBUGCOMPILE) AC_PROG_CXX AC_PROG_CXXCPP AC_ENABLE_SHARED([yes]) AC_ENABLE_STATIC([no]) AC_PROG_LIBTOOL AC_CHECK_HEADER( [bzlib.h], [], [AC_MSG_ERROR([bzlib headers not found. install bzlib devel package])] ) AC_CHECK_LIB( [bz2], [BZ2_bzBuffToBuffCompress], [], [ if test x$is_mingw32 = "xtrue" then AC_MSG_WARN([bz2 library test failed, continuing anyway]) LIBS="${LIBS} -lbz2" else AC_MSG_ERROR([bz2 library test failed, install bzip2 devel package]) fi ] ) AC_CHECK_HEADER( [zlib.h], [], [AC_MSG_ERROR([zlib headers not found. install zlib devel package])] ) AC_CHECK_LIB( [z], [inflate], [], [AC_MSG_ERROR([zlib not found. install zlib package])] ) dnl the plugin manager uses dlopen / dlsym on unix dnl the check valknut used was from KDE 3 and also checked for dnl "shl_unload" in "dld" but there is no #ifdef'ed code for that if test x$is_mingw32 = "xfalse" then AC_CHECK_HEADER([dlfcn.h]) AC_CHECK_LIB([dl],[dlopen]) fi dnl There was a KDE test here to work out what the third argument of accept() and dnl getsockname() is. The manpage says: dnl #include dnl int getsockname(int s, struct sockaddr *name, socklen_t *namelen); dnl So socklen_t is defined in and there's no need to dnl attempt to work out what it is. The accept() manpage also says dnl #include may be required so that was added to dclib/core/csocket.cpp dnl XML PKG_CHECK_MODULES( [XML], [libxml-2.0 >= 2.0.0], [], [AM_PATH_XML2( [2.0.0], [AC_SUBST([XML_CFLAGS], [${XML_CPPFLAGS}])], [AC_MSG_ERROR([libxml2 development package is required])] )] ) dnl check some includes - mainly for CDir or CSocket dnl definitions not used were removed dnl definitions only used by gnulib fsusage.c are not included here dnl that's what gl_FSUSAGE is for AC_CHECK_HEADERS([unistd.h sys/filio.h sys/sockio.h sys/termios.h langinfo.h malloc.h]) dnl fsusage.c - get free disk space if test x$is_mingw32 = "xfalse" then gl_PREREQ_FSUSAGE_EXTRA gl_FSUSAGE dnl that gnulib test tries to run test programs dnl therefore does not work when cross-compiling dnl re-check for what gnulib picks on GNU/Linux if test x$gl_cv_fs_space = "xno" then AC_MSG_WARN([All the gnulib file system space usage tests failed...]) AC_MSG_CHECKING([for statfs(const char *path, struct statfs *buf) and statfs.f_bsize]) AC_LINK_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct statfs fsd; fsd.f_bsize = 0; return statfs(".", &fsd); } ]])], [AC_MSG_RESULT([yes]) AC_DEFINE(STAT_STATFS2_BSIZE, 1, [ Define if statfs takes 2 args and struct statfs has a field named f_bsize. (4.3BSD, SunOS 4, HP-UX, AIX PS/2)])], [AC_MSG_RESULT([no])] ) fi fi dnl gl_MD5 uses this but now also CCaseFolder needs it dnl TigerHash.cpp has defines for big endian and 64 bit CPU AC_C_BIGENDIAN AC_CHECK_SIZEOF([long]) dnl cmd5.c - compute MD5 checksum gl_MD5 dnl see if canonicalize_file_name is provided by system libs (glibc) dnl if not realpath gets used with a big buffer dnl canonicalize_file_name and strcasestr unfortunately require -D_GNU_SOURCE dnl definitions not used were removed AC_CHECK_FUNCS([canonicalize_file_name realpath strtoll strtoull strtoq strtouq strcasestr lrint nanosleep usleep nl_langinfo _strtoi64 _strtoui64 if_nameindex malloc_trim]) AC_ARG_ENABLE([socks], [AS_HELP_STRING([--enable-socks],[use the socks proxying library (default disabled)])], [ if test x$enableval = "xyes" then AC_DEFINE([HAVE_SOCKS],[1],[use the socks library]) AC_CHECK_LIB([socks], [Rconnect], [], [AC_MSG_ERROR([Socks support requested but socks library not found])]) fi ]) AM_ICONV if test x$is_mingw32 = "xfalse" then ACX_PTHREAD([], [AC_MSG_ERROR([POSIX threads support required but not found])]) fi PKG_PROG_PKG_CONFIG([0.9.0]) DCLIB_CHECK_SSL DCLIB_CHECK_STL HIDESYMS="-fvisibility=hidden" AC_MSG_CHECKING([if $CXX supports $HIDESYMS]) ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $HIDESYMS" AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[ int main() { return 0; } ]] )], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) HIDESYMS="" ]) CXXFLAGS="$ac_save_CXXFLAGS" AC_SUBST(HIDESYMS) dnl build date and svn revision information, no longer put into PACKAGE_VERSION AC_MSG_CHECKING([for build date and svn revision]) DCLIB_BUILD_INFO="Build date: `date +%Y%m%d`" if echo "$PACKAGE_VERSION" | grep svn >/dev/null 2>&1 then DCLIB_BUILD_INFO="$DCLIB_BUILD_INFO svn: `svnversion ${srcdir}`" else DCLIB_BUILD_INFO="$DCLIB_BUILD_INFO release" fi AC_MSG_RESULT([$DCLIB_BUILD_INFO]) AC_DEFINE_UNQUOTED([DCLIB_BUILD_INFO], ["${DCLIB_BUILD_INFO}"], [build date and svn rev]) AC_CONFIG_FILES([ Makefile ]) AC_CONFIG_FILES([ dclib.spec ]) AC_CONFIG_FILES([ dclib.lsm ]) AC_CONFIG_FILES([ dclib.pc ]) AC_CONFIG_FILES([ dclib-uninstalled.pc ]) AC_CONFIG_FILES([ dclib/dcos.h ]) AC_CONFIG_FILES([ dclib/dclib-ssl-use.h ]) AC_CONFIG_FILES([ dclib/dclib-stl-use.h ]) AC_CONFIG_FILES([ dclib/Makefile ]) AC_CONFIG_FILES([ dclib/gnulib/Makefile ]) AC_CONFIG_FILES([ dclib/core/Makefile ]) AC_CONFIG_FILES([ dclib/hash/Makefile ]) AC_CONFIG_FILES([ tests/Makefile ]) AC_CONFIG_FILES([ extras/Makefile ]) AC_OUTPUT libdc0-0.3.24~svn3121/extras/0000755000175000017500000000000011556467000014533 5ustar sikonsikonlibdc0-0.3.24~svn3121/extras/dclib-tiger.cpp0000644000175000017500000000337411455415612017433 0ustar sikonsikon/* dclib-tiger.cpp - Tiger Hash tool Copyright (C) 2009 Edward Sheldrake This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* * DC++ headers are no longer installed with dclib. * And the symbols are supposed to be hidden from the library. */ #include "../dclib/hash/compat.h" #include "../dclib/hash/TigerHash.h" #include "../dclib/core/cbytearray.h" #include "../dclib/core/cfile.h" #include #include int main( int argc, char * argv[] ) { dcpp::TigerHash hasher; CByteArray buffer(16*1024); CFile file; long read = -1; uint8_t res[24]; for ( int i = 1; i < argc; ++i ) { if ( file.Open(argv[i], IO_RAW | IO_READONLY) ) { hasher.reset(); while ( (read = file.Read((char*)buffer.Data(), buffer.Size())) > 0 ) { hasher.update(buffer.Data(), read); } file.Close(); memcpy(res, hasher.finalize(), 24); /* TODO: add option to make it like "gpg2 --print-md tiger192" */ printf("%s: ", argv[i]); /* This is like the NESSIE test vectors on the algorithm home page */ for ( int j = 0; j < 24; ++j ) { printf("%02X",res[j]); } printf("\n"); } } return 0; } libdc0-0.3.24~svn3121/extras/Makefile.am0000644000175000017500000000070111175405324016563 0ustar sikonsikonLDADD = ../dclib/libdc.la AM_CXXFLAGS = @CXXFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir) $(PACKAGE_FLAGS) $(SSL_CPPFLAGS) noinst_PROGRAMS = \ dclib-dump-database \ dclib-fix-timestamps \ dclib-tiger \ dclib-tth dclib_dump_database_SOURCES = dclib-dump-database.cpp dclib_fix_timestamps_SOURCES = dclib-fix-timestamps.cpp dclib_tiger_SOURCES = dclib-tiger.cpp ../dclib/hash/TigerHash.cpp dclib_tth_SOURCES = dclib-tth.cpp libdc0-0.3.24~svn3121/extras/dclib-dump-database.cpp0000644000175000017500000001141311104144315021007 0ustar sikonsikon// g++ -g -Wall `pkg-config --cflags dclib` `pkg-config --libs dclib` -o dclib-dump-database dclib-dump-database.cpp /*************************************************************************** dclib-dump-database.cpp - Dump the contents of dclib's database ------------------- begin : Sun Aug 24 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* * Print out the contents of dclib's files and hash database. */ #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include // only for struct fbo/hbo #include #include #include #include #include int main( int argc, char *argv[] ) { if ( argc != 2 ) { printf("Usage: %s [directory containing your .dc directory]\n",argv[0]); return 100; } CString prefix = argv[1]; prefix += "/.dc/"; /* because ctime adds an \n */ CString s; CByteArray filebase, filepaths, filenames; CByteArray hashbase; struct filebaseobject fbo; if ( filebase.LoadFromFile(prefix + "database.bin") == false ) { printf("Failed to load database.bin from %s\n",prefix.Data()); return 200; } filepaths.LoadFromFile(prefix + "pathbase.bin"); filenames.LoadFromFile(prefix + "filebase.bin"); hashbase.LoadFromFile(prefix + "hashbase.bin"); printf("***** Files database *****\n\n"); for ( unsigned long i = 0; i < filebase.Size(); i += sizeof(struct filebaseobject) ) { memcpy( &fbo, filebase.Data()+i, sizeof(struct filebaseobject) ); printf("%lu ",i); printf("filetype=%u ",fbo.m_eFileType); printf("size=%llu ",fbo.m_nSize); printf("pathindex=%lu ",fbo.m_nPathIndex); printf("fileindex=%lu ",fbo.m_nFileIndex); printf("hashindex=%lu ",fbo.m_nHashIndex); printf("modtime=%lu ",fbo.m_tModTime); printf("pathname="); if ( fbo.m_nPathIndex < filepaths.Size() ) { printf( "'%s'", (char*) filepaths.Data()+fbo.m_nPathIndex ); } else { printf("(invalid index)"); } printf(" filename="); if ( fbo.m_nFileIndex < filenames.Size() ) { printf( "'%s'", (char*) filenames.Data()+fbo.m_nFileIndex ); } else { printf("(invalid index)"); } if ( (fbo.m_nHashIndex != (unsigned long)-1) && (fbo.m_nHashIndex + sizeof(struct hashbaseobject) > hashbase.Size()) ) { printf(" *** invalid hashindex ***"); } s = ctime(&fbo.m_tModTime); s = s.Left( s.Length()-1 ); printf(" modified='%s'\n",s.Data()); } CByteArray hashpaths, hashnames, hashindex; CByteArray hash; CString tth; struct hashbaseobject hbo; hashpaths.LoadFromFile(prefix + "hashpathbase.bin"); hashnames.LoadFromFile(prefix + "hashfilebase.bin"); hashindex.LoadFromFile(prefix + "hashindex.bin"); printf("\n\n***** Hash database *****\n\n"); for ( unsigned long i = 0; i < hashbase.Size(); i += sizeof(struct hashbaseobject) ) { memcpy( &hbo, hashbase.Data()+i, sizeof(struct hashbaseobject) ); printf("%lu ",i); printf("size=%llu ",hbo.m_nSize); printf("pathindex=%lu ",hbo.m_nPathIndex); printf("fileindex=%lu ",hbo.m_nFileIndex); printf("hashindex=%lu ",hbo.m_nHashIndex); printf("leavesindex=%lu ",hbo.m_nHashLeavesIndex); printf("modtime=%lu ",hbo.m_tModTime); printf("pathname="); if ( hbo.m_nPathIndex < hashpaths.Size() ) { printf( "'%s'", (char*) hashpaths.Data()+hbo.m_nPathIndex ); } else { printf("(invalid index)"); } printf(" filename="); if ( hbo.m_nFileIndex < hashnames.Size() ) { printf( "'%s'", (char*) hashnames.Data()+hbo.m_nFileIndex ); } else { printf("(invalid index)"); } s = ctime(&hbo.m_tModTime); s = s.Left( s.Length()-1 ); printf(" modified='%s' ", s.Data() ); printf("tth="); if ( hbo.m_nHashIndex + 24 <= hashindex.Size() ) { hash.SetSize(0); hash.Append( hashindex.Data()+hbo.m_nHashIndex, 24 ); CBase32::Encode( &tth, &hash ); printf( "'%s'", tth.Data() ); } else { printf("(invalid index)"); } printf("\n"); } return 0; } libdc0-0.3.24~svn3121/extras/dclib-tth.cpp0000644000175000017500000000217111175405324017110 0ustar sikonsikon/* dclib-tth.cpp - Tiger Tree Hash tool Copyright (C) 2009 Edward Sheldrake This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include int main( int argc, char * argv[] ) { for ( int i = 1; i < argc; ++i ) { CFileHasher hasher( argv[i] ); hasher.ComputeHash(); if ( hasher.GetStatus() == efhsFinished ) { printf("%s %s\n", hasher.GetHashRoot().Data(), argv[i]); } else { fprintf(stderr, "error on file %s\n",argv[i]); } } return 0; } libdc0-0.3.24~svn3121/extras/dclib-fix-timestamps.cpp0000644000175000017500000002054311204332211021251 0ustar sikonsikon// g++ -g -Wall `pkg-config --cflags dclib` `pkg-config --libs dclib` -o dclib-fix-timestamps dclib-fix-timestamps.cpp /*************************************************************************** dclib-fix-timestamps.cpp - Fix timestamps hit by FAT32 / DST issues ------------------- begin : Sun Aug 24 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* * This program fixes all timestamps in the hash database that are * out by some integral number of hours. This happens in Linux for * files stored on FAT32 partitions (don't know about NTFS) * when the clocks change for daylight savings time. It may happen * after the next boot, not next mount or when the clock changes. * * Consider not using this program, and instead use the tz=UTC * mount option, or a better filesystem. * * Warning: There is no way to determine if the file was actually * modified exactly N hours ago and it's size was unchanged, and * it actually does need to be re-hashed. So your hash database * should otherwise be fully up to date. * * All entries for which: * * The file cannot be found or stat'ed * The file size has changed * The modification timestamps do not differ by N hours * * are copied unchanged into the new files. * * Your original hashbase.bin is not changed, instead * hashbase.bin.fixed is saved. */ #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include // only for struct fbo/hbo #include #include #include #include #include #include #include #include int main( int argc, char *argv[] ) { if ( argc != 2 ) { printf("Usage: %s [directory containing your .dc directory]\n",argv[0]); printf("So run: %s %s\n",argv[0],CDir::HomeDirPath().Data()); printf("And because the output will be very long run:\n"); printf("%s %s > logfile.txt\n",argv[0],CDir::HomeDirPath().Data()); return 100; } CDir dir; CString configpath = argv[1]; if ( dir.IsDir( configpath, false ) == false ) { printf("%s is not a directory\n",configpath.Data()); return 200; } CConfig::SetInstance(new CConfig(configpath)); CConfig::Instance()->LoadDCLib(); CString filename; CString prefix = configpath + "/.dc/"; struct stat buf; CByteArray filebase, filepaths, filenames, newfilebase; struct filebaseobject fbo; filebase.LoadFromFile(prefix + "database.bin"); filepaths.LoadFromFile(prefix + "pathbase.bin"); filenames.LoadFromFile(prefix + "filebase.bin"); newfilebase.SetSize(0); /* * Actually this is not necessary because database.bin is always re-created * from scratch. */ printf("***** Needlessly doing files database anyway *****\n"); for ( unsigned long i = 0; i < filebase.Size(); i += sizeof(struct filebaseobject) ) { memcpy( &fbo, filebase.Data()+i, sizeof(struct filebaseobject) ); if ( (fbo.m_nPathIndex == (unsigned long)-1) || (fbo.m_nFileIndex == (unsigned long)-1) ) { printf("Copy fbo with (unsigned long)-1) file/path index at %lu\n",i); newfilebase.Append( (const char*)&fbo, sizeof(struct filebaseobject) ); continue; } if ( (fbo.m_nPathIndex > filepaths.Size()) || (fbo.m_nFileIndex > filenames.Size()) ) { printf("Copy fbo with invalid file/path index at %lu\n",i); newfilebase.Append( (const char*)&fbo, sizeof(struct filebaseobject) ); continue; } filename = (char*) filepaths.Data()+fbo.m_nPathIndex; filename += '/'; filename += (char*) filenames.Data()+fbo.m_nFileIndex; filename = dir.SimplePath( filename ); printf("%lu %s ",i,filename.Data()); filename = CConfig::Instance()->AliasToPath(filename); if ( dir.IsFile( filename, false ) ) { if ( dir.getFileSize( filename, false ) == fbo.m_nSize ) { if ( stat( filename.Data(), &buf ) == 0 ) { if ( fbo.m_tModTime != buf.st_mtime ) { time_t difference; if ( fbo.m_tModTime > buf.st_mtime ) { difference = fbo.m_tModTime - buf.st_mtime; } else { difference = buf.st_mtime - fbo.m_tModTime; } if ( (difference % 3600) == 0 ) { printf("mtime was %lu now %lu\n",fbo.m_tModTime,buf.st_mtime); fbo.m_tModTime = buf.st_mtime; } else { printf("%lu %lu not off by n hours\n",fbo.m_tModTime,buf.st_mtime); } } else { printf("ok\n"); } } else { printf("stat failed\n"); } } else { printf("sizes differ\n"); } } else { printf("not found / not file\n"); } newfilebase.Append( (const char*)&fbo, sizeof(struct filebaseobject) ); } newfilebase.SaveToFile(prefix + "database.bin.fixed"); CByteArray hashbase, hashpaths, hashnames, newhashbase; struct hashbaseobject hbo; hashbase.LoadFromFile(prefix + "hashbase.bin"); hashpaths.LoadFromFile(prefix + "hashpathbase.bin"); hashnames.LoadFromFile(prefix + "hashfilebase.bin"); newhashbase.SetSize(0); printf("***** Doing hash database *****\n"); long fixed = 0; for ( unsigned long i = 0; i < hashbase.Size(); i += sizeof(struct hashbaseobject) ) { memcpy( &hbo, hashbase.Data()+i, sizeof(struct hashbaseobject) ); if ( (hbo.m_nPathIndex == (unsigned long)-1) || (hbo.m_nFileIndex == (unsigned long)-1) ) { printf("Copy hbo with (unsigned long)-1) file/path index at %lu\n",i); newhashbase.Append( (const char*)&hbo, sizeof(struct hashbaseobject) ); continue; } if ( (hbo.m_nPathIndex > hashpaths.Size()) || (hbo.m_nFileIndex > hashnames.Size()) ) { printf("Copy hbo with invalid file/path index at %lu\n",i); newhashbase.Append( (const char*)&hbo, sizeof(struct hashbaseobject) ); continue; } filename = (char*) hashpaths.Data()+hbo.m_nPathIndex; filename += '/'; filename += (char*) hashnames.Data()+hbo.m_nFileIndex; filename = dir.SimplePath( filename ); printf("%lu %s ",i,filename.Data()); filename = CConfig::Instance()->AliasToPath(filename); if ( dir.IsFile( filename, false ) ) { if ( dir.getFileSize( filename, false ) == hbo.m_nSize ) { if ( stat( filename.Data(), &buf ) == 0 ) { if ( hbo.m_tModTime != buf.st_mtime ) { time_t difference; if ( hbo.m_tModTime > buf.st_mtime ) { difference = hbo.m_tModTime - buf.st_mtime; } else { difference = buf.st_mtime - hbo.m_tModTime; } if ( (difference % 3600) == 0 ) { printf("mtime was %lu now %lu\n",hbo.m_tModTime,buf.st_mtime); hbo.m_tModTime = buf.st_mtime; ++fixed; } else { printf("%lu %lu not off by n hours\n",hbo.m_tModTime,buf.st_mtime); } } else { printf("ok\n"); } } else { printf("stat failed\n"); } } else { printf("sizes differ\n"); } } else { printf("not found\n"); } newhashbase.Append( (const char*)&hbo, sizeof(struct hashbaseobject) ); } newhashbase.SaveToFile(prefix + "hashbase.bin.fixed"); printf("Adjusted %ld timestamps in hash database\n",fixed); printf("New files hashbase.bin.fixed and database.bin.fixed have been\n"); printf("created in %s\n",prefix.Data()); printf("Confirm that they are the same size as database.bin and hashbase.bin .\n"); printf("Rename the original database.bin and hashbase.bin .\n"); printf("Then remove .fixed from the names of the new files.\n"); printf("\n"); printf("Consider using the tz=UTC mount option rather than this program.\n"); delete CConfig::Instance(); return 0; } libdc0-0.3.24~svn3121/admin/0000755000175000017500000000000011556466777014341 5ustar sikonsikonlibdc0-0.3.24~svn3121/admin/Makefile.common0000644000175000017500000000027511033457111017240 0ustar sikonsikonall: $(info Run "autoreconf --verbose --force --install" to generate configure) $(info This requires automake, autoconf and libtool.) $(info This is not required for released tarballs.) libdc0-0.3.24~svn3121/admin/config.rpath0000755000175000017500000004364711033365002016630 0ustar sikonsikon#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2007 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; rdos*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) wl='-Wl,' ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. # Unlike libtool.m4, here we don't care about _all_ names of the library, but # only about the one the linker finds when passed -lNAME. This is the last # element of library_names_spec in libtool.m4, or possibly two of them if the # linker has special search rules. library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) library_names_spec='$libname.a' ;; aix4* | aix5*) library_names_spec='$libname$shrext' ;; amigaos*) library_names_spec='$libname.a' ;; beos*) library_names_spec='$libname$shrext' ;; bsdi[45]*) library_names_spec='$libname$shrext' ;; cygwin* | mingw* | pw32*) shrext=.dll library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib library_names_spec='$libname$shrext' ;; dgux*) library_names_spec='$libname$shrext' ;; freebsd1*) ;; freebsd* | dragonfly*) case "$host_os" in freebsd[123]*) library_names_spec='$libname$shrext$versuffix' ;; *) library_names_spec='$libname$shrext' ;; esac ;; gnu*) library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac library_names_spec='$libname$shrext' ;; interix[3-9]*) library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux* | k*bsd*-gnu) library_names_spec='$libname$shrext' ;; knetbsd*-gnu) library_names_spec='$libname$shrext' ;; netbsd*) library_names_spec='$libname$shrext' ;; newsos6) library_names_spec='$libname$shrext' ;; nto-qnx*) library_names_spec='$libname$shrext' ;; openbsd*) library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) library_names_spec='$libname$shrext' ;; rdos*) ;; solaris*) library_names_spec='$libname$shrext' ;; sunos4*) library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) library_names_spec='$libname$shrext' ;; sysv4*MP*) library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) library_names_spec='$libname$shrext' ;; uts4*) library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' < 0.3.8-1 - replace antique shipped .spec.in file one based on Fedora Extras .spec * Mon Jan 3 2007 Luke Macken 0.3.8-1 - 0.3.8 from new upstream - Remove patches: dclib-0.3.7-permissions.patch dclib-0.3.7-keylock.patch dclib-0.3.7-hashfix.patch * Sun Sep 3 2006 Luke Macken 0.3.7-8 - Rebuild for FC6 * Sun Apr 20 2006 Luke Macken 0.3.7-7 - dclib-0.3.7-permissions.patch make valknut use the umask instead of hardcoded permissions - dclib-0.3.7-keylock.patch fixes $Lock-parsing problem - dclib-0.3.7-hashfix.patch fixes production of wrong hashes * Mon Feb 13 2006 Luke Macken 0.3.7-6 - Rebuild for FE5 * Tue Dec 27 2005 Luke Macken 0.3.7-5 - Rebuild * Thu Nov 10 2005 Luke Macken 0.3.7-4 - Rebuild for new openssl * Mon Oct 03 2005 Luke Macken 0.3.7-3 - Add libxml2-devel to Requires * Sun Oct 02 2005 Luke Macken 0.3.7-2 - Add documentation and license to package - Set defattr and fix Requires in the devel package * Thu Sep 29 2005 Luke Macken 0.3.7-1 - Packaged for Fedora Extras libdc0-0.3.24~svn3121/dclib.lsm.in0000644000175000017500000000072611074130777015434 0ustar sikonsikonBegin3 Title: @PACKAGE@ Version: @PACKAGE_VERSION@ Entered-date: Description: Direct Connect file sharing library Keywords: Author: Mathias Küster Maintained-by: Mathias Küster Primary-site: http://dcgui.berlios.de Home-page: http://dcgui.berlios.de Original-site: http://dcgui.berlios.de Platforms: Linux and other Unices Copying-policy: GNU Public License End libdc0-0.3.24~svn3121/dclib-uninstalled.pc.in0000644000175000017500000000060211041037473017545 0ustar sikonsikonprefix=@abs_top_builddir@ exec_prefix=@abs_top_builddir@ libdir=@abs_top_builddir@/dclib includedir=@abs_top_srcdir@ Name: @PACKAGE@ uninstalled Description: Direct Connect file sharing library, not installed Version: @PACKAGE_VERSION@ URL: http://wxdcgui.sourceforge.net Libs: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ ${libdir}/libdc.la Cflags: -I${includedir} @PTHREAD_CFLAGS@ @SSL_CPPFLAGS@ libdc0-0.3.24~svn3121/COPYING.OpenSSL0000644000175000017500000001420710523771204015543 0ustar sikonsikon LICENSE ISSUES ============== The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the OpenSSL License and the original SSLeay license apply to the toolkit. See below for the actual license texts. Actually both licenses are BSD-style Open Source licenses. In case of any license issues related to OpenSSL please contact openssl-core@openssl.org. OpenSSL License --------------- /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. 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. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED 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 OpenSSL PROJECT OR * ITS 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 product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ Original SSLeay License ----------------------- /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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 licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ libdc0-0.3.24~svn3121/README0000644000175000017500000000344711076633653014123 0ustar sikonsikondclib is a library of classes supporting valknut, a client for the Direct Connect network protocol. In addition to the protocol support there is storage of various user data, such as a database of shareable items and lists of items to download. dclib requires zlib, bzip2, libxml2 and optionally OpenSSL. To compile it you need the development packages for these libraries installed. Website: http://wxdcgui.sourceforge.net/ Project page: http://sourceforge.net/projects/wxdcgui Compiling and installing is the same as for any other software that uses GNU automake and autoconf for the build system, INSTALL is the generic instructions that apply to all programs using a configure script. ./configure make make check make install The useful configure options are: --prefix=/path/to/install/dclib Change where dclib will be installed, the default is /usr/local which will require "make install" to be run as root. --enable-debug Adds "-g" to the compiler flags so that debuggers can produce useful backtraces. This is not enabled by default, but if no other compiler flags are set (CXXFLAGS is not set), "-O2 -g" are used. "-g" needs to be in the compiler flags for the crash dialog in valknut to contain useful information. --enable-static --disable-shared Create a static library instead of a shared library, although appropriate for dclib, it is less tested so not recommended. --disable-ssl Do not use the OpenSSL libraries, encrypted connections will not be available. --disable-unordered-stl Do not attempt to use std::tr1::unordered_set, use std::set instead. Most useful if attempting to use unordered_set is causing compilation to fail. If you obtained dclib using subversion then you need to run "autoreconf --install" to create the configure script and related files, requiring automake, autoconf and libtool. libdc0-0.3.24~svn3121/NEWS0000644000175000017500000000067111075075771013736 0ustar sikonsikonhttp://wxdcgui.sourceforge.net/news-0.3.11.html http://wxdcgui.sourceforge.net/news-0.3.14.html http://wxdcgui.sourceforge.net/news-0.3.19.html http://wxdcgui.sourceforge.net/news-0.3.20.html http://wxdcgui.sourceforge.net/news-0.3.21.html http://wxdcgui.sourceforge.net/news-0.3.22.html Release notes were not made for every release, there is also: http://wxdcgui.sourceforge.net/releases.html http://wxdcgui.sourceforge.net/history.html libdc0-0.3.24~svn3121/COPYING0000644000175000017500000003705411074130777014274 0ustar sikonsikon TERMS AND CONDITIONS FOR LINKING AGAINST OpenSSL ------------------------------------------------ In addition, as a special exception, Mathias Küster and Edward Sheldrake give permission to link the code of this program with the OpenSSL library (or with modified versions of OpenSSL that use the same license as OpenSSL), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than OpenSSL. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. END OF TERMS AND CONDITIONS ------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS libdc0-0.3.24~svn3121/tests/0000755000175000017500000000000011556467000014367 5ustar sikonsikonlibdc0-0.3.24~svn3121/tests/ciconv-test.cpp0000644000175000017500000000516211062233242017324 0ustar sikonsikon/*************************************************************************** ciconv-test.cpp - basic test for CIconv class ------------------- begin : Thu Sep 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * CIconv is a new class introduced in 0.3.11 to handle character set * encoding. Previous versions did not handle encoding in dclib * (there was some for chat and filelists in valknut), and converted * ISO-8859-1 to UTF-8 for making XML. */ #include #include #include #define TESTS 4; int main( int, char*[] ) { int ret = 0; /* same string from case folding test */ const unsigned char raw[26] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x20, 0xC1, 0xC9, 0xCC, 0xD3, 0xD9, 0x20, 0xE1, 0xE9, 0xEC, 0xF3, 0xF9, 0x20, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00 }; CString somecp1252 = (const char*) raw; CString someutf8 = "ABCDEF ÁÉÌÓÙ áéìóù UVWXYZ"; CIconv cp1252toutf8( "CP1252", "UTF-8" ); CIconv utf8tocp1252( "UTF-8", "CP1252" ); CString output = cp1252toutf8.encode( somecp1252 ); if ( output != someutf8 ) { printf("ciconv-test: failed CP1252 to UTF-8 1\n"); printf("output='%s'\n",output.Data()); ret = 1; } output = cp1252toutf8.encode( (const char*) raw ); if ( output != someutf8 ) { printf("ciconv-test: failed CP1252 to UTF-8 2\n"); ret = 2; } output = utf8tocp1252.encode( someutf8 ); if ( output != somecp1252 ) { printf("ciconv-test: failed UTF-8 to CP1252 1\n"); ret = 3; } output = utf8tocp1252.encode( someutf8.Data() ); if ( output != somecp1252 ) { printf("ciconv-test: failed UTF-8 to CP1252 2\n"); ret = 4; } output = utf8tocp1252.encode( somecp1252 ); if ( output != "ABCDEF _____ _____ UVWXYZ" ) { printf("ciconv-test: failed invalid conversion test\n"); ret = 5; } return ret; } libdc0-0.3.24~svn3121/tests/priv-ips.cpp0000644000175000017500000000365411141131203016633 0ustar sikonsikon/*************************************************************************** priv-ips.cpp - test CNetAddr::IsPrivateI4() ------------------- begin : Thu Dec 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * If it was broken for big-endian arch then so was DC++. */ #include #include int main( int /* argc */, char*[] /* argv[] */ ) { const bool expected[4] = { false,true,true,false }; const char * ips[4][4] = { {"9.255.255.255", "10.0.0.0", "10.255.255.255", "11.0.0.0" }, {"126.255.255.255", "127.0.0.0", "127.255.255.255", "128.0.0.0" }, {"172.15.255.255", "172.16.0.0", "172.31.255.255", "172.32.0.0" }, {"192.167.255.255", "192.168.0.0", "192.168.255.255", "192.169.0.0" } }; int failed = 0; for ( int i = 0; i < 4; ++i ) { for ( int j = 0; j < 4; ++j ) { /* printf("i=%d j=%d %s\n",i,j,ips[i][j]); */ if ( CNetAddr::IsPrivateI4(ips[i][j]) != expected[j] ) { printf( "failed for %s expected %d got %d\n", ips[i][j], expected[j], CNetAddr::IsPrivateI4(ips[i][j]) ); ++failed; } } } return failed; } libdc0-0.3.24~svn3121/tests/tth-test.cpp0000644000175000017500000000744311455415233016656 0ustar sikonsikon/*************************************************************************** tth-test.cpp - Test a TTH calculated is correct ------------------- begin : Thu Sep 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include #include int main( int /* argc */, char* [] /* argv */ ) { /* create test data */ /* 2 of the published test vectors */ CByteArray tv1(1024); for ( unsigned long i = 0; i < tv1.Size(); ++i ) { tv1.Data()[i] = 'A'; } CByteArray tv2(1025); for ( unsigned long i = 0; i < tv2.Size(); ++i ) { tv2.Data()[i] = 'A'; } CByteArray * res = CFileHasher::HashByteArray( &tv1, tv1.Size() ); CString v; CBase32::Encode( &v, res ); delete res; if ( v != "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA" ) { printf("tth-test: wrong tth %s calculated for test vector 1\n",v.Data()); return 10; } res = CFileHasher::HashByteArray( &tv2, tv2.Size() ); CBase32::Encode( &v, res ); delete res; if ( v != "PZMRYHGY6LTBEH63ZWAHDORHSYTLO4LEFUIKHWY" ) { printf("tth-test: wrong tth %s calculated for test vector 2\n",v.Data()); return 20; } CByteArray buffer(50*1024*1024); unsigned char c = 'a'; for ( unsigned long i = 0; i < buffer.Size(); ++i ) { if ( i%26 == 0 ) { c = 'a'; } buffer.Data()[i] = c; ++c; } res = CFileHasher::HashByteArray( &buffer, buffer.Size() ); CBase32::Encode( &v, res ); delete res; res = 0; if ( v != "B4OKDH3FH3JZJJBNN4OLNTCHW7TK7G2O6IG2JHQ" ) { printf("tth-test: wrong tth %s calculated for test file data\n",v.Data()); return 30; } if ( buffer.SaveToFile("testdata.bin") == false ) { printf("tth-test: cannot create testdata.bin file\n"); return 1; } CFileHasher hasher("testdata.bin"); hasher.ComputeHash(); int ret = 100; if ( hasher.GetStatus() != efhsFinished ) { printf("tth-test: error during hashing\n"); ret = 2; } if ( hasher.GetHashRoot() == "B4OKDH3FH3JZJJBNN4OLNTCHW7TK7G2O6IG2JHQ" ) { CByteArray * leaves = hasher.GetLeafData(); if ( leaves && leaves->Size() > 0 ) { if ( CFileHasher::ValidateHashLeaves( hasher.GetHashRoot(), leaves, buffer.Size() ) ) { /* change leaf data */ unsigned char c = leaves->Data()[0]; if ( c == 0 ) { c = 1; } else { c--; } leaves->Data()[0] = c; if ( CFileHasher::ValidateHashLeaves( hasher.GetHashRoot(), leaves, buffer.Size() ) == false ) { ret = 0; } else { printf("tth-test: modified leaves passed validation!\n"); ret = 6; } } else { printf("tth-test: leaves failed validation!\n"); ret = 5; } } else { printf("tth-test: no leaves generated!\n"); ret = 4; } if ( leaves ) { delete leaves; leaves = 0; } } else { printf("tth-test: incorrect tth %s calculated!\n",hasher.GetHashRoot().Data()); ret = 3; } CFile::UnLink("testdata.bin"); return ret; } libdc0-0.3.24~svn3121/tests/cstring-self.cpp0000644000175000017500000000467311062233242017474 0ustar sikonsikon/*************************************************************************** cstring-self.cpp - test assigning / appending CString to itself ------------------- begin : Thu Sep 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * This ability was accidentally broken when all that temporary copying * was removed from CString, until the necessary pointer checks were * added: memcpy does not work if the memory areas overlap, and * memmove is not going to help because usually the memory area will * be expanded with realloc before memcpy, possibly moving it to * somewhere else in memory. */ #include #include #define TESTS 6 int main( int, char*[] ) { /* These all assume CString == works */ bool results[TESTS]; /* Append tests */ CString abcdefg = "abcdefg"; abcdefg += abcdefg; abcdefg += abcdefg; results[0] = (abcdefg == "abcdefgabcdefgabcdefgabcdefg"); abcdefg = "abcdefg"; abcdefg += abcdefg.Data(); results[1] = (abcdefg == "abcdefgabcdefg"); abcdefg = "abcdefg"; abcdefg += abcdefg.Data()+3; results[2] = (abcdefg == "abcdefgdefg"); /* Assign tests */ abcdefg = "abcdefg"; abcdefg = abcdefg; abcdefg = abcdefg; results[3] = (abcdefg == "abcdefg"); abcdefg = "abcdefg"; abcdefg = abcdefg.Data(); abcdefg = abcdefg.Data(); results[4] = (abcdefg == "abcdefg"); abcdefg = "abcdefg"; abcdefg = abcdefg.Data()+1; abcdefg = abcdefg.Data()+1; abcdefg = abcdefg.Data()+1; results[5] = (abcdefg == "defg"); int ret = 0; for ( int i = 0; i < TESTS; ++i ) { if ( results[i] == false ) { printf("cstring-self: test %d failed\n",i); ret = 100; } } return ret; } libdc0-0.3.24~svn3121/tests/threads-mutex.cpp0000644000175000017500000000706611104136315017665 0ustar sikonsikon/*************************************************************************** threads-mutex.cpp - Test CMutex (and CThread) ------------------- begin : Mon Sep 15 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* * This is probably the most useless test ever. * It either has to take a longer time and/or very high load average * or you could have the threads spend most of their time sleeping * instead of waiting for the mutex. * * You need to increase the amount/length of threads until the * test fails when the counter does not lock the mutex. */ #include #include #include class Counter { public: Counter() : m_count( 0 ), m_high( 0 ), m_low( 0 ) {}; ~Counter() {}; long GetCount() { long c; m_Mutex.Lock(); c = m_count; m_Mutex.UnLock(); return c; } long GetHigh() { long h; m_Mutex.Lock(); h = m_high; m_Mutex.UnLock(); return h; } long GetLow() { long l; m_Mutex.Lock(); l = m_low; m_Mutex.UnLock(); return l; } void Increment() { m_Mutex.Lock(); ++m_count; if ( m_count > m_high ) { m_high = m_count; } m_Mutex.UnLock(); } void Decrement() { m_Mutex.Lock(); --m_count; if ( m_count < m_low ) { m_low = m_count; } m_Mutex.UnLock(); } private: CMutex m_Mutex; long m_count; long m_high; long m_low; }; class AddSub : public CThread { public: AddSub( int m, int n, Counter * target ) : CThread(), m_mode( m ), m_times( 0 ), m_max( n ), m_counter( target ) {}; ~AddSub() {}; virtual void Thread() { if ( m_mode == 0 ) { m_counter->Increment(); } else if ( m_mode == 1 ) { m_counter->Decrement(); } ++m_times; if ( m_times == m_max ) { Stop(); } } private: int m_mode; int m_times; int m_max; Counter * m_counter; }; /* avoid THREADS * OPS == overflow */ #define THREADS 9 #define OPS (10000000 ## L) int main( int /* argc */, char*[] /* argv */ ) { Counter TestCounter; AddSub * threads[THREADS]; for ( int i = 0; i < THREADS; ++i ) { threads[i] = new AddSub( i%2, OPS, &TestCounter ); } for ( int i = 0; i < THREADS; ++i ) { threads[i]->Start(); } int checked = 0; while ( true ) { for ( checked = 0; checked < THREADS; ++checked ) { if ( threads[checked]->Stopped() == false ) { checked = -10; break; } } if ( checked == THREADS ) { break; } CThread::NanoSleep(100); } #if 1 printf("high=%ld low=%ld\n",TestCounter.GetHigh(),TestCounter.GetLow()); printf("count=%ld expected=%ld\n",TestCounter.GetCount(), OPS * (THREADS%2)); #endif for ( int i = 0; i < THREADS; ++i ) { delete threads[i]; threads[i] = 0; } if ( TestCounter.GetCount() == OPS * (THREADS%2) ) { return 0; } else { return 100; } } libdc0-0.3.24~svn3121/tests/cstring-upper-lower.cpp0000644000175000017500000000640011102360525021012 0ustar sikonsikon/*************************************************************************** cstring-upper-lower.cpp - test CString ToUpper() / ToLower() ------------------- begin : Thu Oct 30 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * Check ToUpper() and ToLower() work since I'm removing yet * another copy. This really needs to be run under valgrind * to check for invalid memory access, leaks etc. */ #include #include int main( int, char*[] ) { const CString before = "========== a variable before =========="; const CString testdata = "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789"; const CString after = "========== a variable before =========="; CString s1 = testdata.ToLower(); CString s2 = testdata.ToUpper(); if ( s1.Length() != testdata.Length() ) { printf("cstring-upper-lower: ToLower() changed length: %ld -> %ld\n",testdata.Length(),s1.Length()); return 100; } if ( s1 != "0123456789 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz 0123456789" ) { printf("cstring-upper-lower: unexpected result from ToLower(): '%s'\n",s1.Data()); return 100; } if ( s2.Length() != testdata.Length() ) { printf("cstring-upper-lower: ToUpper() changed length: %ld -> %ld\n",testdata.Length(),s2.Length()); } if ( s2 != "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789" ) { printf("cstring-upper-lower: unexpected result from ToUpper(): '%s'\n",s2.Data()); return 100; } if ( s1.Data()[s1.Length()] != 0 ) { printf("cstring-upper-lower: ToLower() result not NULL terminated\n"); return 100; } if ( s2.Data()[s2.Length()] != 0 ) { printf("cstring-upper-lower: ToUpper() result not NULL terminated\n"); return 100; } s1 += before; s1 += after; if ( (s1.Length() != before.Length() + testdata.Length() + after.Length()) || (s1 != "0123456789 abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz 0123456789========== a variable before ==================== a variable before ==========") ) { printf("cstring-upper-lower: result of ToLower() is broken\n"); return 100; } s2 += before; s2 += after; if ( (s2.Length() != before.Length() + testdata.Length() + after.Length()) || (s2 != "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789========== a variable before ==================== a variable before ==========") ) { printf("cstring-upper-lower: result of ToUpper() is broken\n"); return 100; } return 0; } libdc0-0.3.24~svn3121/tests/case-fold.cpp0000644000175000017500000000361011077432447016735 0ustar sikonsikon/*************************************************************************** case-fold.cpp - Test the case folder works (in UTF-8 locale) ------------------- begin : Thu Sep 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include int main( int, char*[] ) { /* without CConfig CCaseFolder uses UTF-8 */ CCaseFolder folder; /* a few vowels from what gucharmap calls the Latin-1 Supplement */ CString input1 = "aBCDEF ÁÉÌÓÙ áéìóù UVWXYz"; CString input2 = "Abcdef áéìóù áéìóù uvwxyZ"; CString output1; CString output2; if ( folder.Fold( input1, output1 ) ) { if ( folder.Fold( input2, output2 ) ) { if ( output1 == output2 ) { return 0; } else { printf("case-fold: input1='%s' output1='%s'\n", input1.Data(), output1.Data()); printf("case-fold: input2='%s' output2='%s'\n", input2.Data(), output2.Data()); return 3; } } else { printf("case-fold: folding 2 failed, iconv problem?\n"); return 2; } } else { printf("case-fold: folding 1 failed, iconv problem?\n"); return 1; } } libdc0-0.3.24~svn3121/tests/Makefile.am0000644000175000017500000000147311451427141016424 0ustar sikonsikonbase32_SOURCES = base32.cpp bz2_test_SOURCES = bz2-test.cpp case_fold_SOURCES = case-fold.cpp ciconv_test_SOURCES = ciconv-test.cpp cstring_compare_SOURCES = cstring-compare.cpp cstring_find_SOURCES = cstring-find.cpp cstring_number_SOURCES = cstring-number.cpp cstring_self_SOURCES = cstring-self.cpp cstring_upper_lower_SOURCES = cstring-upper-lower.cpp priv_ips_SOURCES = priv-ips.cpp threads_mutex_SOURCES = threads-mutex.cpp tth_test_SOURCES = tth-test.cpp LDADD = ../dclib/libdc.la AM_CXXFLAGS = @CXXFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir) $(PACKAGE_FLAGS) $(SSL_CPPFLAGS) check_PROGRAMS = \ base32 \ bz2-test \ case-fold \ ciconv-test \ cstring-compare \ cstring-find \ cstring-number \ cstring-self \ cstring-upper-lower \ priv-ips \ threads-mutex \ tth-test TESTS = $(check_PROGRAMS) libdc0-0.3.24~svn3121/tests/cstring-find.cpp0000644000175000017500000000770511212457460017471 0ustar sikonsikon/*************************************************************************** cstring-find.cpp - Some tests for the CString Find functions ------------------- begin : Thu Sep 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #define TESTS 43 int main( int, char*[] ) { long expected[TESTS]; const CString empty; const CString fruits("apple orange banana grapefruit melon orange again"); const CString orange("orange"); const CString spanner("spanner"); long r[TESTS]; expected[0] = -1; expected[1] = 0; expected[2] = 8; expected[3] = -1; expected[4] = -1; r[0] = empty.Find( 'a' ); r[1] = fruits.Find( 'a' ); r[2] = fruits.Find( 'a', r[1]+1 ); r[3] = fruits.Find( 'a', fruits.Length() + 2000 ); r[4] = fruits.Find( 'q' ); /* yes an empty string matches / starts with an empty string */ expected[5] = 0; expected[6] = -1; expected[7] = 6; expected[8] = 37; expected[9] = -1; expected[10] = -1; r[5] = empty.Find( empty.Data() ); r[6] = empty.Find( "apple" ); r[7] = fruits.Find( "orange" ); r[8] = fruits.Find( "orange", r[7]+1 ); r[9] = fruits.Find( "spanner" ); r[10] = fruits.Find( "orange", r[8]+1 ); expected[11] = 0; expected[12] = -1; expected[13] = 6; expected[14] = 37; expected[15] = -1; expected[16] = -1; r[11] = empty.Find( empty ); r[12] = empty.Find( orange ); r[13] = fruits.Find( orange ); r[14] = fruits.Find( orange, r[13]+1 ); r[15] = fruits.Find( spanner ); r[16] = fruits.Find( orange, r[14]+1 ); expected[17] = 0; expected[18] = -1; expected[19] = 6; expected[20] = 37; expected[21] = -1; expected[22] = -1; r[17] = empty.FindCase( 0 ); r[18] = empty.FindCase( "apple" ); r[19] = fruits.FindCase( "orange" ); r[20] = fruits.FindCase( "orange", r[19]+1 ); r[21] = fruits.FindCase( "spanner" ); r[22] = fruits.FindCase( "orange", r[20]+1 ); expected[23] = 0; expected[24] = -1; expected[25] = 6; expected[26] = 37; expected[27] = -1; expected[28] = -1; r[23] = empty.FindCase( empty ); r[24] = empty.FindCase( orange ); r[25] = fruits.FindCase( orange ); r[26] = fruits.FindCase( orange, r[25]+1 ); r[27] = fruits.FindCase( spanner ); r[28] = fruits.FindCase( orange, r[26]+1 ); expected[29] = -1; expected[30] = -1; r[29] = empty.FindRev( 'a' ); r[30] = empty.FindRev( 'a', 50 ); expected[31] = -1; expected[32] = 37; expected[33] = 34; expected[34] = -1; r[31] = fruits.FindRev( 'q' ); r[32] = fruits.FindRev( 'o' ); r[33] = fruits.FindRev( 'o', r[32]-1 ); r[34] = fruits.FindRev( 'b', 5 ); expected[35] = 0; expected[36] = -1; r[35] = empty.FindRev( empty ); r[36] = empty.FindRev( spanner ); expected[37] = 37; expected[38] = -1; r[37] = fruits.FindRev( orange ); r[38] = fruits.FindRev( spanner ); expected[39] = 0; expected[40] = 48; r[39] = fruits.FindRev( 'a', 2 ); r[40] = fruits.FindRev( 'n' ); expected[41] = 0; expected[42] = 44; r[41] = fruits.FindRev( "apple" ); r[42] = fruits.FindRev( "again" ); int ret = 0; for ( int i = 0; i < TESTS; ++i ) { if ( expected[i] != r[i] ) { printf("CString Find test %d failed expected %ld got %ld\n",i,expected[i],r[i]); ret = 100; } } return ret; } libdc0-0.3.24~svn3121/tests/base32.cpp0000644000175000017500000000450411461356250016154 0ustar sikonsikon/*************************************************************************** base32.cpp - Test Base32 encode / decode ------------------- begin : Fri Oct 01 2010 copyright : (C) 2010 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include int main( int, char*[] ) { /* * RFC 4648 http://tools.ietf.org/html/rfc4648 * * FIXME: dclib doesn't do the padding with "=" */ const char* input[7] = { "f", "fo", "foo", "foob", "fooba", "foobar", "abcdefghijklmnopqrstuvwx" }; const char* output[7] = { "MY", /* MY====== */ "MZXQ", /* MZXQ==== */ "MZXW6", /* MZXW6=== */ "MZXW6YQ", /* MZXW6YQ= */ "MZXW6YTB", /* MZXW6YTB */ "MZXW6YTBOI", /* MZXW6YTBOI====== */ "MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6A" }; for ( size_t i = 0; i < sizeof(input)/sizeof(char*); ++i ) { CByteArray in; CString out; in.SetSize(0); in.Append(input[i], strlen(input[i])); CBase32::Encode(&out, &in); if ( out != output[i] ) { printf("CBase32 Encode in=%s expected=%s got=%s\n",input[i],output[i],out.Data()); return 10; } } for ( size_t i = 0; i < sizeof(input)/sizeof(char*); ++i ) { CByteArray out; CString in = output[i]; CString outs; CBase32::Decode(&out, &in); outs.Set((const char*) out.Data(), out.Size()); if ( outs != input[i] ) { printf("CBase32 Decode in=%s expected=%s got=%s\n",output[i],input[i],outs.Data()); return 20; } } return 0; } libdc0-0.3.24~svn3121/tests/cstring-number.cpp0000644000175000017500000001002411461356250020026 0ustar sikonsikon/*************************************************************************** cstring-number.cpp - test CString::number() functions ------------------- begin : Tue Nov 11 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * Well since printf("%llu") didn't work on WIN32 here is a test * for the CString::number() functions. * CString::number(long long) needed fixing. */ #include #include #include int main( int /* argc */, char*[] /* argv[] and remove the other [] */ ) { const int i1 = INT_MIN, i2 = 0, i3 = INT_MAX; const unsigned int ui1 = 0, ui2 = UINT_MAX; const long l1 = LONG_MIN, l2 = 0, l3 = LONG_MAX; const unsigned long ul1 = 0, ul2 = ULONG_MAX; const long long ll1 = LLONG_MIN, ll2 = 0, ll3 = LLONG_MAX; const unsigned long long ull1 = 0, ull2 = ULLONG_MAX; CString longmin, longmax, ulongmax; if ( sizeof(long) == 4 ) { longmin = "-2147483648"; longmax = "2147483647"; ulongmax = "4294967295"; } else if ( sizeof(long) == 8 ) { longmin = "-9223372036854775808"; longmax = "9223372036854775807"; ulongmax = "18446744073709551615"; } else { printf("sizeof(long)=%lu not handled\n",sizeof(long)); return 0; } int ret = 0; CString s = CString::number(i1); if ( s != "-2147483648" ) { printf("INT_MIN got '%s' expected '-2147483648'\n",s.Data()); ret = 100; } s = CString::number(i2); if ( s != "0" ) { printf("int 0 got '%s' expected '0'\n",s.Data()); ret = 100; } s = CString::number(i3); if ( s != "2147483647" ) { printf("INT_MAX got '%s' expected '2147483647'\n",s.Data()); ret = 100; } s = CString::number(ui1); if ( s != "0" ) { printf("unsigned int 0 got '%s' expected '0'\n",s.Data()); ret = 100; } s = CString::number(ui2); if ( s != "4294967295" ) { printf("UNIT_MAX got '%s' expected '4294967295'\n",s.Data()); ret = 100; } s = CString::number(l1); if ( s != longmin ) { printf("LONG_MIN got '%s' expected '%s'\n",s.Data(),longmin.Data()); ret = 100; } s = CString::number(l2); if ( s != "0" ) { printf("long 0 got '%s' expected '0'\n",s.Data()); ret = 100; } s = CString::number(l3); if ( s != longmax ) { printf("LONG_MAX got '%s' expected '%s'\n",s.Data(),longmax.Data()); ret = 100; } s = CString::number(ul1); if ( s != "0" ) { printf("unsigned long 0 got '%s' expected '0'\n",s.Data()); ret = 100; } s = CString::number(ul2); if ( s != ulongmax ) { printf("ULONG_MAX got '%s' expected '%s'\n",s.Data(),ulongmax.Data()); ret = 100; } s = CString::number(ll1); if ( s != "-9223372036854775808" ) { printf("LLONG_MIN got '%s' expected '-9223372036854775808'\n",s.Data()); ret = 100; } s = CString::number(ll2); if ( s != "0" ) { printf("long long 0 got '%s' expected '0'\n",s.Data()); ret = 100; } s = CString::number(ll3); if ( s != "9223372036854775807" ) { printf("LLONG_MAX got '%s' expected '9223372036854775807'\n",s.Data()); ret = 100; } s = CString::number(ull1); if ( s != "0" ) { printf("unsigned long long 0 got '%s' expected '0'\n",s.Data()); ret = 100; } s = CString::number(ull2); if ( s != "18446744073709551615" ) { printf("ULLONG_MAX got '%s' expected '18446744073709551615'\n",s.Data()); ret = 100; } return ret; } libdc0-0.3.24~svn3121/tests/bz2-test.cpp0000644000175000017500000000374111224416047016547 0ustar sikonsikon/*************************************************************************** bz2-test.cpp - Test the bzip2 class ------------------- begin : Mon Jul 06 2009 copyright : (C) 2009 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include int main( int /* argc */, char* [] /* argv[] */ ) { CByteArray orig(2*1024*1024); CByteArray compressed; CByteArray decompressed; memset(orig.Data(), 'D', orig.Size()); if ( CBZ::Compress(&orig, &compressed) == false ) { fprintf(stderr,"bz2-test: CBZ::Compress failed\n"); return 10; } /* 2MiB of a single repeated char should compress to very little */ if ( compressed.Size() > orig.Size() ) { fprintf(stderr,"bz2-test: failed, size increased\n"); return 20; } if ( CBZ::Decompress(&compressed,&decompressed) == false ) { fprintf(stderr,"bz2-test: CBZ::Decompress failed\n"); return 30; } if ( decompressed.Size() != orig.Size() ) { fprintf(stderr,"bz2-test: size mismatch\n"); return 40; } if ( memcmp(orig.Data(), decompressed.Data(), orig.Size()) != 0 ) { fprintf(stderr,"bz2-test: data mismatch\n"); return 50; } return 0; } libdc0-0.3.24~svn3121/tests/cstring-compare.cpp0000644000175000017500000000635111141131203020154 0ustar sikonsikon/*************************************************************************** cstring-compare.cpp - test CString::Compare() function ------------------- begin : Thu Dec 18 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* * Because I re-arranged the code, compiled with optimization it probably * turns out the same anyway. */ #include #include int main( int /* argc */, char *[] /*argv[] */ ) { CString empty1; CString cs1 = "emily"; CString cs2 = "martie"; CString cs3 = "natalie"; CString cs4 = "natalie"; CString empty2; const char * s1 = "emily"; const char * s2 = "martie"; const char * s3 = "natalie"; const char * nullstr = 0; int failed = 0; int res = cs1.Compare(cs2); if ( res >= 0 ) { printf("failed 1: %d\n",res); ++failed; } res = cs3.Compare(cs2); if ( res <= 0 ) { printf("failed 2: %d\n",res); ++failed; } res = cs3.Compare(cs4); if ( res != 0 ) { printf("failed 3: %d\n",res); ++failed; } res = cs1.Compare(s2); if ( res >= 0 ) { printf("failed 4: %d\n",res); ++failed; } res = cs3.Compare(s2); if ( res <= 0 ) { printf("failed 5: %d\n",res); ++failed; } res = cs2.Compare(s2); if ( res != 0 ) { printf("failed 6: %d\n",res); ++failed; } res = empty1.Compare(empty2); if ( res != 0 ) { printf("failed 7: %d\n",res); ++failed; } res = empty1.Compare(cs1); if ( res <= 0 ) { printf("failed 8: %d\n",res); ++failed; } res = empty1.Compare(nullstr); if ( res != 0 ) { printf("failed 9: %d\n",res); ++failed; } res = cs1.Compare(empty1); if ( res >= 0 ) { printf("failed 10: %d\n",res); ++failed; } res = cs1.Compare(nullstr); if ( res >= 0 ) { printf("failed 11: %d\n",res); ++failed; } /* CString::Compare() is not used directly, it's confusing. */ /* The comparison operators are more useful. */ if ( !((cs1 < cs2) && (cs1 < s2) && (s1 < cs2)) ) { printf("failed 12\n"); ++failed; } if ( !((cs1 <= cs2) && (cs1 <= s2) && (s1 <= cs2)) ) { printf("failed 13\n"); ++failed; } if ( !((cs3 <= cs4) && (cs2 <= s2) && (s1 <= cs1)) ) { printf("failed 14\n"); ++failed; } if ( !((cs4 > cs2) && (cs4 > s2) && (s3 > cs1)) ) { printf("failed 15\n"); ++failed; } if ( !((cs4 >= cs2) && (cs4 >= s2) && (s3 >= cs1)) ) { printf("failed 16\n"); ++failed; } if ( !((cs3 >= cs4) && (cs2 >= s2) && (s1 >= cs1)) ) { printf("failed 17\n"); ++failed; } return failed; } libdc0-0.3.24~svn3121/dclib/0000755000175000017500000000000011556467003014305 5ustar sikonsikonlibdc0-0.3.24~svn3121/dclib/ccasefolder-generated-code.cpp0000644000175000017500000021330111040047151022111 0ustar sikonsikon/* Automatically generated file do not edit. */ /* It's useless on it's own and is included */ /* at the correct place in ccasefolder.cpp */ case 0x00041: folded[outpos] = 0x00061; ++outpos; break; case 0x00042: folded[outpos] = 0x00062; ++outpos; break; case 0x00043: folded[outpos] = 0x00063; ++outpos; break; case 0x00044: folded[outpos] = 0x00064; ++outpos; break; case 0x00045: folded[outpos] = 0x00065; ++outpos; break; case 0x00046: folded[outpos] = 0x00066; ++outpos; break; case 0x00047: folded[outpos] = 0x00067; ++outpos; break; case 0x00048: folded[outpos] = 0x00068; ++outpos; break; case 0x00049: folded[outpos] = 0x00069; ++outpos; break; case 0x0004A: folded[outpos] = 0x0006A; ++outpos; break; case 0x0004B: folded[outpos] = 0x0006B; ++outpos; break; case 0x0004C: folded[outpos] = 0x0006C; ++outpos; break; case 0x0004D: folded[outpos] = 0x0006D; ++outpos; break; case 0x0004E: folded[outpos] = 0x0006E; ++outpos; break; case 0x0004F: folded[outpos] = 0x0006F; ++outpos; break; case 0x00050: folded[outpos] = 0x00070; ++outpos; break; case 0x00051: folded[outpos] = 0x00071; ++outpos; break; case 0x00052: folded[outpos] = 0x00072; ++outpos; break; case 0x00053: folded[outpos] = 0x00073; ++outpos; break; case 0x00054: folded[outpos] = 0x00074; ++outpos; break; case 0x00055: folded[outpos] = 0x00075; ++outpos; break; case 0x00056: folded[outpos] = 0x00076; ++outpos; break; case 0x00057: folded[outpos] = 0x00077; ++outpos; break; case 0x00058: folded[outpos] = 0x00078; ++outpos; break; case 0x00059: folded[outpos] = 0x00079; ++outpos; break; case 0x0005A: folded[outpos] = 0x0007A; ++outpos; break; case 0x000B5: folded[outpos] = 0x003BC; ++outpos; break; case 0x000C0: folded[outpos] = 0x000E0; ++outpos; break; case 0x000C1: folded[outpos] = 0x000E1; ++outpos; break; case 0x000C2: folded[outpos] = 0x000E2; ++outpos; break; case 0x000C3: folded[outpos] = 0x000E3; ++outpos; break; case 0x000C4: folded[outpos] = 0x000E4; ++outpos; break; case 0x000C5: folded[outpos] = 0x000E5; ++outpos; break; case 0x000C6: folded[outpos] = 0x000E6; ++outpos; break; case 0x000C7: folded[outpos] = 0x000E7; ++outpos; break; case 0x000C8: folded[outpos] = 0x000E8; ++outpos; break; case 0x000C9: folded[outpos] = 0x000E9; ++outpos; break; case 0x000CA: folded[outpos] = 0x000EA; ++outpos; break; case 0x000CB: folded[outpos] = 0x000EB; ++outpos; break; case 0x000CC: folded[outpos] = 0x000EC; ++outpos; break; case 0x000CD: folded[outpos] = 0x000ED; ++outpos; break; case 0x000CE: folded[outpos] = 0x000EE; ++outpos; break; case 0x000CF: folded[outpos] = 0x000EF; ++outpos; break; case 0x000D0: folded[outpos] = 0x000F0; ++outpos; break; case 0x000D1: folded[outpos] = 0x000F1; ++outpos; break; case 0x000D2: folded[outpos] = 0x000F2; ++outpos; break; case 0x000D3: folded[outpos] = 0x000F3; ++outpos; break; case 0x000D4: folded[outpos] = 0x000F4; ++outpos; break; case 0x000D5: folded[outpos] = 0x000F5; ++outpos; break; case 0x000D6: folded[outpos] = 0x000F6; ++outpos; break; case 0x000D8: folded[outpos] = 0x000F8; ++outpos; break; case 0x000D9: folded[outpos] = 0x000F9; ++outpos; break; case 0x000DA: folded[outpos] = 0x000FA; ++outpos; break; case 0x000DB: folded[outpos] = 0x000FB; ++outpos; break; case 0x000DC: folded[outpos] = 0x000FC; ++outpos; break; case 0x000DD: folded[outpos] = 0x000FD; ++outpos; break; case 0x000DE: folded[outpos] = 0x000FE; ++outpos; break; case 0x000DF: folded[outpos] = 0x00073; ++outpos; folded[outpos] = 0x00073; ++outpos; break; case 0x00100: folded[outpos] = 0x00101; ++outpos; break; case 0x00102: folded[outpos] = 0x00103; ++outpos; break; case 0x00104: folded[outpos] = 0x00105; ++outpos; break; case 0x00106: folded[outpos] = 0x00107; ++outpos; break; case 0x00108: folded[outpos] = 0x00109; ++outpos; break; case 0x0010A: folded[outpos] = 0x0010B; ++outpos; break; case 0x0010C: folded[outpos] = 0x0010D; ++outpos; break; case 0x0010E: folded[outpos] = 0x0010F; ++outpos; break; case 0x00110: folded[outpos] = 0x00111; ++outpos; break; case 0x00112: folded[outpos] = 0x00113; ++outpos; break; case 0x00114: folded[outpos] = 0x00115; ++outpos; break; case 0x00116: folded[outpos] = 0x00117; ++outpos; break; case 0x00118: folded[outpos] = 0x00119; ++outpos; break; case 0x0011A: folded[outpos] = 0x0011B; ++outpos; break; case 0x0011C: folded[outpos] = 0x0011D; ++outpos; break; case 0x0011E: folded[outpos] = 0x0011F; ++outpos; break; case 0x00120: folded[outpos] = 0x00121; ++outpos; break; case 0x00122: folded[outpos] = 0x00123; ++outpos; break; case 0x00124: folded[outpos] = 0x00125; ++outpos; break; case 0x00126: folded[outpos] = 0x00127; ++outpos; break; case 0x00128: folded[outpos] = 0x00129; ++outpos; break; case 0x0012A: folded[outpos] = 0x0012B; ++outpos; break; case 0x0012C: folded[outpos] = 0x0012D; ++outpos; break; case 0x0012E: folded[outpos] = 0x0012F; ++outpos; break; case 0x00130: folded[outpos] = 0x00069; ++outpos; folded[outpos] = 0x00307; ++outpos; break; case 0x00132: folded[outpos] = 0x00133; ++outpos; break; case 0x00134: folded[outpos] = 0x00135; ++outpos; break; case 0x00136: folded[outpos] = 0x00137; ++outpos; break; case 0x00139: folded[outpos] = 0x0013A; ++outpos; break; case 0x0013B: folded[outpos] = 0x0013C; ++outpos; break; case 0x0013D: folded[outpos] = 0x0013E; ++outpos; break; case 0x0013F: folded[outpos] = 0x00140; ++outpos; break; case 0x00141: folded[outpos] = 0x00142; ++outpos; break; case 0x00143: folded[outpos] = 0x00144; ++outpos; break; case 0x00145: folded[outpos] = 0x00146; ++outpos; break; case 0x00147: folded[outpos] = 0x00148; ++outpos; break; case 0x00149: folded[outpos] = 0x002BC; ++outpos; folded[outpos] = 0x0006E; ++outpos; break; case 0x0014A: folded[outpos] = 0x0014B; ++outpos; break; case 0x0014C: folded[outpos] = 0x0014D; ++outpos; break; case 0x0014E: folded[outpos] = 0x0014F; ++outpos; break; case 0x00150: folded[outpos] = 0x00151; ++outpos; break; case 0x00152: folded[outpos] = 0x00153; ++outpos; break; case 0x00154: folded[outpos] = 0x00155; ++outpos; break; case 0x00156: folded[outpos] = 0x00157; ++outpos; break; case 0x00158: folded[outpos] = 0x00159; ++outpos; break; case 0x0015A: folded[outpos] = 0x0015B; ++outpos; break; case 0x0015C: folded[outpos] = 0x0015D; ++outpos; break; case 0x0015E: folded[outpos] = 0x0015F; ++outpos; break; case 0x00160: folded[outpos] = 0x00161; ++outpos; break; case 0x00162: folded[outpos] = 0x00163; ++outpos; break; case 0x00164: folded[outpos] = 0x00165; ++outpos; break; case 0x00166: folded[outpos] = 0x00167; ++outpos; break; case 0x00168: folded[outpos] = 0x00169; ++outpos; break; case 0x0016A: folded[outpos] = 0x0016B; ++outpos; break; case 0x0016C: folded[outpos] = 0x0016D; ++outpos; break; case 0x0016E: folded[outpos] = 0x0016F; ++outpos; break; case 0x00170: folded[outpos] = 0x00171; ++outpos; break; case 0x00172: folded[outpos] = 0x00173; ++outpos; break; case 0x00174: folded[outpos] = 0x00175; ++outpos; break; case 0x00176: folded[outpos] = 0x00177; ++outpos; break; case 0x00178: folded[outpos] = 0x000FF; ++outpos; break; case 0x00179: folded[outpos] = 0x0017A; ++outpos; break; case 0x0017B: folded[outpos] = 0x0017C; ++outpos; break; case 0x0017D: folded[outpos] = 0x0017E; ++outpos; break; case 0x0017F: folded[outpos] = 0x00073; ++outpos; break; case 0x00181: folded[outpos] = 0x00253; ++outpos; break; case 0x00182: folded[outpos] = 0x00183; ++outpos; break; case 0x00184: folded[outpos] = 0x00185; ++outpos; break; case 0x00186: folded[outpos] = 0x00254; ++outpos; break; case 0x00187: folded[outpos] = 0x00188; ++outpos; break; case 0x00189: folded[outpos] = 0x00256; ++outpos; break; case 0x0018A: folded[outpos] = 0x00257; ++outpos; break; case 0x0018B: folded[outpos] = 0x0018C; ++outpos; break; case 0x0018E: folded[outpos] = 0x001DD; ++outpos; break; case 0x0018F: folded[outpos] = 0x00259; ++outpos; break; case 0x00190: folded[outpos] = 0x0025B; ++outpos; break; case 0x00191: folded[outpos] = 0x00192; ++outpos; break; case 0x00193: folded[outpos] = 0x00260; ++outpos; break; case 0x00194: folded[outpos] = 0x00263; ++outpos; break; case 0x00196: folded[outpos] = 0x00269; ++outpos; break; case 0x00197: folded[outpos] = 0x00268; ++outpos; break; case 0x00198: folded[outpos] = 0x00199; ++outpos; break; case 0x0019C: folded[outpos] = 0x0026F; ++outpos; break; case 0x0019D: folded[outpos] = 0x00272; ++outpos; break; case 0x0019F: folded[outpos] = 0x00275; ++outpos; break; case 0x001A0: folded[outpos] = 0x001A1; ++outpos; break; case 0x001A2: folded[outpos] = 0x001A3; ++outpos; break; case 0x001A4: folded[outpos] = 0x001A5; ++outpos; break; case 0x001A6: folded[outpos] = 0x00280; ++outpos; break; case 0x001A7: folded[outpos] = 0x001A8; ++outpos; break; case 0x001A9: folded[outpos] = 0x00283; ++outpos; break; case 0x001AC: folded[outpos] = 0x001AD; ++outpos; break; case 0x001AE: folded[outpos] = 0x00288; ++outpos; break; case 0x001AF: folded[outpos] = 0x001B0; ++outpos; break; case 0x001B1: folded[outpos] = 0x0028A; ++outpos; break; case 0x001B2: folded[outpos] = 0x0028B; ++outpos; break; case 0x001B3: folded[outpos] = 0x001B4; ++outpos; break; case 0x001B5: folded[outpos] = 0x001B6; ++outpos; break; case 0x001B7: folded[outpos] = 0x00292; ++outpos; break; case 0x001B8: folded[outpos] = 0x001B9; ++outpos; break; case 0x001BC: folded[outpos] = 0x001BD; ++outpos; break; case 0x001C4: folded[outpos] = 0x001C6; ++outpos; break; case 0x001C5: folded[outpos] = 0x001C6; ++outpos; break; case 0x001C7: folded[outpos] = 0x001C9; ++outpos; break; case 0x001C8: folded[outpos] = 0x001C9; ++outpos; break; case 0x001CA: folded[outpos] = 0x001CC; ++outpos; break; case 0x001CB: folded[outpos] = 0x001CC; ++outpos; break; case 0x001CD: folded[outpos] = 0x001CE; ++outpos; break; case 0x001CF: folded[outpos] = 0x001D0; ++outpos; break; case 0x001D1: folded[outpos] = 0x001D2; ++outpos; break; case 0x001D3: folded[outpos] = 0x001D4; ++outpos; break; case 0x001D5: folded[outpos] = 0x001D6; ++outpos; break; case 0x001D7: folded[outpos] = 0x001D8; ++outpos; break; case 0x001D9: folded[outpos] = 0x001DA; ++outpos; break; case 0x001DB: folded[outpos] = 0x001DC; ++outpos; break; case 0x001DE: folded[outpos] = 0x001DF; ++outpos; break; case 0x001E0: folded[outpos] = 0x001E1; ++outpos; break; case 0x001E2: folded[outpos] = 0x001E3; ++outpos; break; case 0x001E4: folded[outpos] = 0x001E5; ++outpos; break; case 0x001E6: folded[outpos] = 0x001E7; ++outpos; break; case 0x001E8: folded[outpos] = 0x001E9; ++outpos; break; case 0x001EA: folded[outpos] = 0x001EB; ++outpos; break; case 0x001EC: folded[outpos] = 0x001ED; ++outpos; break; case 0x001EE: folded[outpos] = 0x001EF; ++outpos; break; case 0x001F0: folded[outpos] = 0x0006A; ++outpos; folded[outpos] = 0x0030C; ++outpos; break; case 0x001F1: folded[outpos] = 0x001F3; ++outpos; break; case 0x001F2: folded[outpos] = 0x001F3; ++outpos; break; case 0x001F4: folded[outpos] = 0x001F5; ++outpos; break; case 0x001F6: folded[outpos] = 0x00195; ++outpos; break; case 0x001F7: folded[outpos] = 0x001BF; ++outpos; break; case 0x001F8: folded[outpos] = 0x001F9; ++outpos; break; case 0x001FA: folded[outpos] = 0x001FB; ++outpos; break; case 0x001FC: folded[outpos] = 0x001FD; ++outpos; break; case 0x001FE: folded[outpos] = 0x001FF; ++outpos; break; case 0x00200: folded[outpos] = 0x00201; ++outpos; break; case 0x00202: folded[outpos] = 0x00203; ++outpos; break; case 0x00204: folded[outpos] = 0x00205; ++outpos; break; case 0x00206: folded[outpos] = 0x00207; ++outpos; break; case 0x00208: folded[outpos] = 0x00209; ++outpos; break; case 0x0020A: folded[outpos] = 0x0020B; ++outpos; break; case 0x0020C: folded[outpos] = 0x0020D; ++outpos; break; case 0x0020E: folded[outpos] = 0x0020F; ++outpos; break; case 0x00210: folded[outpos] = 0x00211; ++outpos; break; case 0x00212: folded[outpos] = 0x00213; ++outpos; break; case 0x00214: folded[outpos] = 0x00215; ++outpos; break; case 0x00216: folded[outpos] = 0x00217; ++outpos; break; case 0x00218: folded[outpos] = 0x00219; ++outpos; break; case 0x0021A: folded[outpos] = 0x0021B; ++outpos; break; case 0x0021C: folded[outpos] = 0x0021D; ++outpos; break; case 0x0021E: folded[outpos] = 0x0021F; ++outpos; break; case 0x00220: folded[outpos] = 0x0019E; ++outpos; break; case 0x00222: folded[outpos] = 0x00223; ++outpos; break; case 0x00224: folded[outpos] = 0x00225; ++outpos; break; case 0x00226: folded[outpos] = 0x00227; ++outpos; break; case 0x00228: folded[outpos] = 0x00229; ++outpos; break; case 0x0022A: folded[outpos] = 0x0022B; ++outpos; break; case 0x0022C: folded[outpos] = 0x0022D; ++outpos; break; case 0x0022E: folded[outpos] = 0x0022F; ++outpos; break; case 0x00230: folded[outpos] = 0x00231; ++outpos; break; case 0x00232: folded[outpos] = 0x00233; ++outpos; break; case 0x0023A: folded[outpos] = 0x02C65; ++outpos; break; case 0x0023B: folded[outpos] = 0x0023C; ++outpos; break; case 0x0023D: folded[outpos] = 0x0019A; ++outpos; break; case 0x0023E: folded[outpos] = 0x02C66; ++outpos; break; case 0x00241: folded[outpos] = 0x00242; ++outpos; break; case 0x00243: folded[outpos] = 0x00180; ++outpos; break; case 0x00244: folded[outpos] = 0x00289; ++outpos; break; case 0x00245: folded[outpos] = 0x0028C; ++outpos; break; case 0x00246: folded[outpos] = 0x00247; ++outpos; break; case 0x00248: folded[outpos] = 0x00249; ++outpos; break; case 0x0024A: folded[outpos] = 0x0024B; ++outpos; break; case 0x0024C: folded[outpos] = 0x0024D; ++outpos; break; case 0x0024E: folded[outpos] = 0x0024F; ++outpos; break; case 0x00345: folded[outpos] = 0x003B9; ++outpos; break; case 0x00370: folded[outpos] = 0x00371; ++outpos; break; case 0x00372: folded[outpos] = 0x00373; ++outpos; break; case 0x00376: folded[outpos] = 0x00377; ++outpos; break; case 0x00386: folded[outpos] = 0x003AC; ++outpos; break; case 0x00388: folded[outpos] = 0x003AD; ++outpos; break; case 0x00389: folded[outpos] = 0x003AE; ++outpos; break; case 0x0038A: folded[outpos] = 0x003AF; ++outpos; break; case 0x0038C: folded[outpos] = 0x003CC; ++outpos; break; case 0x0038E: folded[outpos] = 0x003CD; ++outpos; break; case 0x0038F: folded[outpos] = 0x003CE; ++outpos; break; case 0x00390: folded[outpos] = 0x003B9; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00301; ++outpos; break; case 0x00391: folded[outpos] = 0x003B1; ++outpos; break; case 0x00392: folded[outpos] = 0x003B2; ++outpos; break; case 0x00393: folded[outpos] = 0x003B3; ++outpos; break; case 0x00394: folded[outpos] = 0x003B4; ++outpos; break; case 0x00395: folded[outpos] = 0x003B5; ++outpos; break; case 0x00396: folded[outpos] = 0x003B6; ++outpos; break; case 0x00397: folded[outpos] = 0x003B7; ++outpos; break; case 0x00398: folded[outpos] = 0x003B8; ++outpos; break; case 0x00399: folded[outpos] = 0x003B9; ++outpos; break; case 0x0039A: folded[outpos] = 0x003BA; ++outpos; break; case 0x0039B: folded[outpos] = 0x003BB; ++outpos; break; case 0x0039C: folded[outpos] = 0x003BC; ++outpos; break; case 0x0039D: folded[outpos] = 0x003BD; ++outpos; break; case 0x0039E: folded[outpos] = 0x003BE; ++outpos; break; case 0x0039F: folded[outpos] = 0x003BF; ++outpos; break; case 0x003A0: folded[outpos] = 0x003C0; ++outpos; break; case 0x003A1: folded[outpos] = 0x003C1; ++outpos; break; case 0x003A3: folded[outpos] = 0x003C3; ++outpos; break; case 0x003A4: folded[outpos] = 0x003C4; ++outpos; break; case 0x003A5: folded[outpos] = 0x003C5; ++outpos; break; case 0x003A6: folded[outpos] = 0x003C6; ++outpos; break; case 0x003A7: folded[outpos] = 0x003C7; ++outpos; break; case 0x003A8: folded[outpos] = 0x003C8; ++outpos; break; case 0x003A9: folded[outpos] = 0x003C9; ++outpos; break; case 0x003AA: folded[outpos] = 0x003CA; ++outpos; break; case 0x003AB: folded[outpos] = 0x003CB; ++outpos; break; case 0x003B0: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00301; ++outpos; break; case 0x003C2: folded[outpos] = 0x003C3; ++outpos; break; case 0x003CF: folded[outpos] = 0x003D7; ++outpos; break; case 0x003D0: folded[outpos] = 0x003B2; ++outpos; break; case 0x003D1: folded[outpos] = 0x003B8; ++outpos; break; case 0x003D5: folded[outpos] = 0x003C6; ++outpos; break; case 0x003D6: folded[outpos] = 0x003C0; ++outpos; break; case 0x003D8: folded[outpos] = 0x003D9; ++outpos; break; case 0x003DA: folded[outpos] = 0x003DB; ++outpos; break; case 0x003DC: folded[outpos] = 0x003DD; ++outpos; break; case 0x003DE: folded[outpos] = 0x003DF; ++outpos; break; case 0x003E0: folded[outpos] = 0x003E1; ++outpos; break; case 0x003E2: folded[outpos] = 0x003E3; ++outpos; break; case 0x003E4: folded[outpos] = 0x003E5; ++outpos; break; case 0x003E6: folded[outpos] = 0x003E7; ++outpos; break; case 0x003E8: folded[outpos] = 0x003E9; ++outpos; break; case 0x003EA: folded[outpos] = 0x003EB; ++outpos; break; case 0x003EC: folded[outpos] = 0x003ED; ++outpos; break; case 0x003EE: folded[outpos] = 0x003EF; ++outpos; break; case 0x003F0: folded[outpos] = 0x003BA; ++outpos; break; case 0x003F1: folded[outpos] = 0x003C1; ++outpos; break; case 0x003F4: folded[outpos] = 0x003B8; ++outpos; break; case 0x003F5: folded[outpos] = 0x003B5; ++outpos; break; case 0x003F7: folded[outpos] = 0x003F8; ++outpos; break; case 0x003F9: folded[outpos] = 0x003F2; ++outpos; break; case 0x003FA: folded[outpos] = 0x003FB; ++outpos; break; case 0x003FD: folded[outpos] = 0x0037B; ++outpos; break; case 0x003FE: folded[outpos] = 0x0037C; ++outpos; break; case 0x003FF: folded[outpos] = 0x0037D; ++outpos; break; case 0x00400: folded[outpos] = 0x00450; ++outpos; break; case 0x00401: folded[outpos] = 0x00451; ++outpos; break; case 0x00402: folded[outpos] = 0x00452; ++outpos; break; case 0x00403: folded[outpos] = 0x00453; ++outpos; break; case 0x00404: folded[outpos] = 0x00454; ++outpos; break; case 0x00405: folded[outpos] = 0x00455; ++outpos; break; case 0x00406: folded[outpos] = 0x00456; ++outpos; break; case 0x00407: folded[outpos] = 0x00457; ++outpos; break; case 0x00408: folded[outpos] = 0x00458; ++outpos; break; case 0x00409: folded[outpos] = 0x00459; ++outpos; break; case 0x0040A: folded[outpos] = 0x0045A; ++outpos; break; case 0x0040B: folded[outpos] = 0x0045B; ++outpos; break; case 0x0040C: folded[outpos] = 0x0045C; ++outpos; break; case 0x0040D: folded[outpos] = 0x0045D; ++outpos; break; case 0x0040E: folded[outpos] = 0x0045E; ++outpos; break; case 0x0040F: folded[outpos] = 0x0045F; ++outpos; break; case 0x00410: folded[outpos] = 0x00430; ++outpos; break; case 0x00411: folded[outpos] = 0x00431; ++outpos; break; case 0x00412: folded[outpos] = 0x00432; ++outpos; break; case 0x00413: folded[outpos] = 0x00433; ++outpos; break; case 0x00414: folded[outpos] = 0x00434; ++outpos; break; case 0x00415: folded[outpos] = 0x00435; ++outpos; break; case 0x00416: folded[outpos] = 0x00436; ++outpos; break; case 0x00417: folded[outpos] = 0x00437; ++outpos; break; case 0x00418: folded[outpos] = 0x00438; ++outpos; break; case 0x00419: folded[outpos] = 0x00439; ++outpos; break; case 0x0041A: folded[outpos] = 0x0043A; ++outpos; break; case 0x0041B: folded[outpos] = 0x0043B; ++outpos; break; case 0x0041C: folded[outpos] = 0x0043C; ++outpos; break; case 0x0041D: folded[outpos] = 0x0043D; ++outpos; break; case 0x0041E: folded[outpos] = 0x0043E; ++outpos; break; case 0x0041F: folded[outpos] = 0x0043F; ++outpos; break; case 0x00420: folded[outpos] = 0x00440; ++outpos; break; case 0x00421: folded[outpos] = 0x00441; ++outpos; break; case 0x00422: folded[outpos] = 0x00442; ++outpos; break; case 0x00423: folded[outpos] = 0x00443; ++outpos; break; case 0x00424: folded[outpos] = 0x00444; ++outpos; break; case 0x00425: folded[outpos] = 0x00445; ++outpos; break; case 0x00426: folded[outpos] = 0x00446; ++outpos; break; case 0x00427: folded[outpos] = 0x00447; ++outpos; break; case 0x00428: folded[outpos] = 0x00448; ++outpos; break; case 0x00429: folded[outpos] = 0x00449; ++outpos; break; case 0x0042A: folded[outpos] = 0x0044A; ++outpos; break; case 0x0042B: folded[outpos] = 0x0044B; ++outpos; break; case 0x0042C: folded[outpos] = 0x0044C; ++outpos; break; case 0x0042D: folded[outpos] = 0x0044D; ++outpos; break; case 0x0042E: folded[outpos] = 0x0044E; ++outpos; break; case 0x0042F: folded[outpos] = 0x0044F; ++outpos; break; case 0x00460: folded[outpos] = 0x00461; ++outpos; break; case 0x00462: folded[outpos] = 0x00463; ++outpos; break; case 0x00464: folded[outpos] = 0x00465; ++outpos; break; case 0x00466: folded[outpos] = 0x00467; ++outpos; break; case 0x00468: folded[outpos] = 0x00469; ++outpos; break; case 0x0046A: folded[outpos] = 0x0046B; ++outpos; break; case 0x0046C: folded[outpos] = 0x0046D; ++outpos; break; case 0x0046E: folded[outpos] = 0x0046F; ++outpos; break; case 0x00470: folded[outpos] = 0x00471; ++outpos; break; case 0x00472: folded[outpos] = 0x00473; ++outpos; break; case 0x00474: folded[outpos] = 0x00475; ++outpos; break; case 0x00476: folded[outpos] = 0x00477; ++outpos; break; case 0x00478: folded[outpos] = 0x00479; ++outpos; break; case 0x0047A: folded[outpos] = 0x0047B; ++outpos; break; case 0x0047C: folded[outpos] = 0x0047D; ++outpos; break; case 0x0047E: folded[outpos] = 0x0047F; ++outpos; break; case 0x00480: folded[outpos] = 0x00481; ++outpos; break; case 0x0048A: folded[outpos] = 0x0048B; ++outpos; break; case 0x0048C: folded[outpos] = 0x0048D; ++outpos; break; case 0x0048E: folded[outpos] = 0x0048F; ++outpos; break; case 0x00490: folded[outpos] = 0x00491; ++outpos; break; case 0x00492: folded[outpos] = 0x00493; ++outpos; break; case 0x00494: folded[outpos] = 0x00495; ++outpos; break; case 0x00496: folded[outpos] = 0x00497; ++outpos; break; case 0x00498: folded[outpos] = 0x00499; ++outpos; break; case 0x0049A: folded[outpos] = 0x0049B; ++outpos; break; case 0x0049C: folded[outpos] = 0x0049D; ++outpos; break; case 0x0049E: folded[outpos] = 0x0049F; ++outpos; break; case 0x004A0: folded[outpos] = 0x004A1; ++outpos; break; case 0x004A2: folded[outpos] = 0x004A3; ++outpos; break; case 0x004A4: folded[outpos] = 0x004A5; ++outpos; break; case 0x004A6: folded[outpos] = 0x004A7; ++outpos; break; case 0x004A8: folded[outpos] = 0x004A9; ++outpos; break; case 0x004AA: folded[outpos] = 0x004AB; ++outpos; break; case 0x004AC: folded[outpos] = 0x004AD; ++outpos; break; case 0x004AE: folded[outpos] = 0x004AF; ++outpos; break; case 0x004B0: folded[outpos] = 0x004B1; ++outpos; break; case 0x004B2: folded[outpos] = 0x004B3; ++outpos; break; case 0x004B4: folded[outpos] = 0x004B5; ++outpos; break; case 0x004B6: folded[outpos] = 0x004B7; ++outpos; break; case 0x004B8: folded[outpos] = 0x004B9; ++outpos; break; case 0x004BA: folded[outpos] = 0x004BB; ++outpos; break; case 0x004BC: folded[outpos] = 0x004BD; ++outpos; break; case 0x004BE: folded[outpos] = 0x004BF; ++outpos; break; case 0x004C0: folded[outpos] = 0x004CF; ++outpos; break; case 0x004C1: folded[outpos] = 0x004C2; ++outpos; break; case 0x004C3: folded[outpos] = 0x004C4; ++outpos; break; case 0x004C5: folded[outpos] = 0x004C6; ++outpos; break; case 0x004C7: folded[outpos] = 0x004C8; ++outpos; break; case 0x004C9: folded[outpos] = 0x004CA; ++outpos; break; case 0x004CB: folded[outpos] = 0x004CC; ++outpos; break; case 0x004CD: folded[outpos] = 0x004CE; ++outpos; break; case 0x004D0: folded[outpos] = 0x004D1; ++outpos; break; case 0x004D2: folded[outpos] = 0x004D3; ++outpos; break; case 0x004D4: folded[outpos] = 0x004D5; ++outpos; break; case 0x004D6: folded[outpos] = 0x004D7; ++outpos; break; case 0x004D8: folded[outpos] = 0x004D9; ++outpos; break; case 0x004DA: folded[outpos] = 0x004DB; ++outpos; break; case 0x004DC: folded[outpos] = 0x004DD; ++outpos; break; case 0x004DE: folded[outpos] = 0x004DF; ++outpos; break; case 0x004E0: folded[outpos] = 0x004E1; ++outpos; break; case 0x004E2: folded[outpos] = 0x004E3; ++outpos; break; case 0x004E4: folded[outpos] = 0x004E5; ++outpos; break; case 0x004E6: folded[outpos] = 0x004E7; ++outpos; break; case 0x004E8: folded[outpos] = 0x004E9; ++outpos; break; case 0x004EA: folded[outpos] = 0x004EB; ++outpos; break; case 0x004EC: folded[outpos] = 0x004ED; ++outpos; break; case 0x004EE: folded[outpos] = 0x004EF; ++outpos; break; case 0x004F0: folded[outpos] = 0x004F1; ++outpos; break; case 0x004F2: folded[outpos] = 0x004F3; ++outpos; break; case 0x004F4: folded[outpos] = 0x004F5; ++outpos; break; case 0x004F6: folded[outpos] = 0x004F7; ++outpos; break; case 0x004F8: folded[outpos] = 0x004F9; ++outpos; break; case 0x004FA: folded[outpos] = 0x004FB; ++outpos; break; case 0x004FC: folded[outpos] = 0x004FD; ++outpos; break; case 0x004FE: folded[outpos] = 0x004FF; ++outpos; break; case 0x00500: folded[outpos] = 0x00501; ++outpos; break; case 0x00502: folded[outpos] = 0x00503; ++outpos; break; case 0x00504: folded[outpos] = 0x00505; ++outpos; break; case 0x00506: folded[outpos] = 0x00507; ++outpos; break; case 0x00508: folded[outpos] = 0x00509; ++outpos; break; case 0x0050A: folded[outpos] = 0x0050B; ++outpos; break; case 0x0050C: folded[outpos] = 0x0050D; ++outpos; break; case 0x0050E: folded[outpos] = 0x0050F; ++outpos; break; case 0x00510: folded[outpos] = 0x00511; ++outpos; break; case 0x00512: folded[outpos] = 0x00513; ++outpos; break; case 0x00514: folded[outpos] = 0x00515; ++outpos; break; case 0x00516: folded[outpos] = 0x00517; ++outpos; break; case 0x00518: folded[outpos] = 0x00519; ++outpos; break; case 0x0051A: folded[outpos] = 0x0051B; ++outpos; break; case 0x0051C: folded[outpos] = 0x0051D; ++outpos; break; case 0x0051E: folded[outpos] = 0x0051F; ++outpos; break; case 0x00520: folded[outpos] = 0x00521; ++outpos; break; case 0x00522: folded[outpos] = 0x00523; ++outpos; break; case 0x00531: folded[outpos] = 0x00561; ++outpos; break; case 0x00532: folded[outpos] = 0x00562; ++outpos; break; case 0x00533: folded[outpos] = 0x00563; ++outpos; break; case 0x00534: folded[outpos] = 0x00564; ++outpos; break; case 0x00535: folded[outpos] = 0x00565; ++outpos; break; case 0x00536: folded[outpos] = 0x00566; ++outpos; break; case 0x00537: folded[outpos] = 0x00567; ++outpos; break; case 0x00538: folded[outpos] = 0x00568; ++outpos; break; case 0x00539: folded[outpos] = 0x00569; ++outpos; break; case 0x0053A: folded[outpos] = 0x0056A; ++outpos; break; case 0x0053B: folded[outpos] = 0x0056B; ++outpos; break; case 0x0053C: folded[outpos] = 0x0056C; ++outpos; break; case 0x0053D: folded[outpos] = 0x0056D; ++outpos; break; case 0x0053E: folded[outpos] = 0x0056E; ++outpos; break; case 0x0053F: folded[outpos] = 0x0056F; ++outpos; break; case 0x00540: folded[outpos] = 0x00570; ++outpos; break; case 0x00541: folded[outpos] = 0x00571; ++outpos; break; case 0x00542: folded[outpos] = 0x00572; ++outpos; break; case 0x00543: folded[outpos] = 0x00573; ++outpos; break; case 0x00544: folded[outpos] = 0x00574; ++outpos; break; case 0x00545: folded[outpos] = 0x00575; ++outpos; break; case 0x00546: folded[outpos] = 0x00576; ++outpos; break; case 0x00547: folded[outpos] = 0x00577; ++outpos; break; case 0x00548: folded[outpos] = 0x00578; ++outpos; break; case 0x00549: folded[outpos] = 0x00579; ++outpos; break; case 0x0054A: folded[outpos] = 0x0057A; ++outpos; break; case 0x0054B: folded[outpos] = 0x0057B; ++outpos; break; case 0x0054C: folded[outpos] = 0x0057C; ++outpos; break; case 0x0054D: folded[outpos] = 0x0057D; ++outpos; break; case 0x0054E: folded[outpos] = 0x0057E; ++outpos; break; case 0x0054F: folded[outpos] = 0x0057F; ++outpos; break; case 0x00550: folded[outpos] = 0x00580; ++outpos; break; case 0x00551: folded[outpos] = 0x00581; ++outpos; break; case 0x00552: folded[outpos] = 0x00582; ++outpos; break; case 0x00553: folded[outpos] = 0x00583; ++outpos; break; case 0x00554: folded[outpos] = 0x00584; ++outpos; break; case 0x00555: folded[outpos] = 0x00585; ++outpos; break; case 0x00556: folded[outpos] = 0x00586; ++outpos; break; case 0x00587: folded[outpos] = 0x00565; ++outpos; folded[outpos] = 0x00582; ++outpos; break; case 0x010A0: folded[outpos] = 0x02D00; ++outpos; break; case 0x010A1: folded[outpos] = 0x02D01; ++outpos; break; case 0x010A2: folded[outpos] = 0x02D02; ++outpos; break; case 0x010A3: folded[outpos] = 0x02D03; ++outpos; break; case 0x010A4: folded[outpos] = 0x02D04; ++outpos; break; case 0x010A5: folded[outpos] = 0x02D05; ++outpos; break; case 0x010A6: folded[outpos] = 0x02D06; ++outpos; break; case 0x010A7: folded[outpos] = 0x02D07; ++outpos; break; case 0x010A8: folded[outpos] = 0x02D08; ++outpos; break; case 0x010A9: folded[outpos] = 0x02D09; ++outpos; break; case 0x010AA: folded[outpos] = 0x02D0A; ++outpos; break; case 0x010AB: folded[outpos] = 0x02D0B; ++outpos; break; case 0x010AC: folded[outpos] = 0x02D0C; ++outpos; break; case 0x010AD: folded[outpos] = 0x02D0D; ++outpos; break; case 0x010AE: folded[outpos] = 0x02D0E; ++outpos; break; case 0x010AF: folded[outpos] = 0x02D0F; ++outpos; break; case 0x010B0: folded[outpos] = 0x02D10; ++outpos; break; case 0x010B1: folded[outpos] = 0x02D11; ++outpos; break; case 0x010B2: folded[outpos] = 0x02D12; ++outpos; break; case 0x010B3: folded[outpos] = 0x02D13; ++outpos; break; case 0x010B4: folded[outpos] = 0x02D14; ++outpos; break; case 0x010B5: folded[outpos] = 0x02D15; ++outpos; break; case 0x010B6: folded[outpos] = 0x02D16; ++outpos; break; case 0x010B7: folded[outpos] = 0x02D17; ++outpos; break; case 0x010B8: folded[outpos] = 0x02D18; ++outpos; break; case 0x010B9: folded[outpos] = 0x02D19; ++outpos; break; case 0x010BA: folded[outpos] = 0x02D1A; ++outpos; break; case 0x010BB: folded[outpos] = 0x02D1B; ++outpos; break; case 0x010BC: folded[outpos] = 0x02D1C; ++outpos; break; case 0x010BD: folded[outpos] = 0x02D1D; ++outpos; break; case 0x010BE: folded[outpos] = 0x02D1E; ++outpos; break; case 0x010BF: folded[outpos] = 0x02D1F; ++outpos; break; case 0x010C0: folded[outpos] = 0x02D20; ++outpos; break; case 0x010C1: folded[outpos] = 0x02D21; ++outpos; break; case 0x010C2: folded[outpos] = 0x02D22; ++outpos; break; case 0x010C3: folded[outpos] = 0x02D23; ++outpos; break; case 0x010C4: folded[outpos] = 0x02D24; ++outpos; break; case 0x010C5: folded[outpos] = 0x02D25; ++outpos; break; case 0x01E00: folded[outpos] = 0x01E01; ++outpos; break; case 0x01E02: folded[outpos] = 0x01E03; ++outpos; break; case 0x01E04: folded[outpos] = 0x01E05; ++outpos; break; case 0x01E06: folded[outpos] = 0x01E07; ++outpos; break; case 0x01E08: folded[outpos] = 0x01E09; ++outpos; break; case 0x01E0A: folded[outpos] = 0x01E0B; ++outpos; break; case 0x01E0C: folded[outpos] = 0x01E0D; ++outpos; break; case 0x01E0E: folded[outpos] = 0x01E0F; ++outpos; break; case 0x01E10: folded[outpos] = 0x01E11; ++outpos; break; case 0x01E12: folded[outpos] = 0x01E13; ++outpos; break; case 0x01E14: folded[outpos] = 0x01E15; ++outpos; break; case 0x01E16: folded[outpos] = 0x01E17; ++outpos; break; case 0x01E18: folded[outpos] = 0x01E19; ++outpos; break; case 0x01E1A: folded[outpos] = 0x01E1B; ++outpos; break; case 0x01E1C: folded[outpos] = 0x01E1D; ++outpos; break; case 0x01E1E: folded[outpos] = 0x01E1F; ++outpos; break; case 0x01E20: folded[outpos] = 0x01E21; ++outpos; break; case 0x01E22: folded[outpos] = 0x01E23; ++outpos; break; case 0x01E24: folded[outpos] = 0x01E25; ++outpos; break; case 0x01E26: folded[outpos] = 0x01E27; ++outpos; break; case 0x01E28: folded[outpos] = 0x01E29; ++outpos; break; case 0x01E2A: folded[outpos] = 0x01E2B; ++outpos; break; case 0x01E2C: folded[outpos] = 0x01E2D; ++outpos; break; case 0x01E2E: folded[outpos] = 0x01E2F; ++outpos; break; case 0x01E30: folded[outpos] = 0x01E31; ++outpos; break; case 0x01E32: folded[outpos] = 0x01E33; ++outpos; break; case 0x01E34: folded[outpos] = 0x01E35; ++outpos; break; case 0x01E36: folded[outpos] = 0x01E37; ++outpos; break; case 0x01E38: folded[outpos] = 0x01E39; ++outpos; break; case 0x01E3A: folded[outpos] = 0x01E3B; ++outpos; break; case 0x01E3C: folded[outpos] = 0x01E3D; ++outpos; break; case 0x01E3E: folded[outpos] = 0x01E3F; ++outpos; break; case 0x01E40: folded[outpos] = 0x01E41; ++outpos; break; case 0x01E42: folded[outpos] = 0x01E43; ++outpos; break; case 0x01E44: folded[outpos] = 0x01E45; ++outpos; break; case 0x01E46: folded[outpos] = 0x01E47; ++outpos; break; case 0x01E48: folded[outpos] = 0x01E49; ++outpos; break; case 0x01E4A: folded[outpos] = 0x01E4B; ++outpos; break; case 0x01E4C: folded[outpos] = 0x01E4D; ++outpos; break; case 0x01E4E: folded[outpos] = 0x01E4F; ++outpos; break; case 0x01E50: folded[outpos] = 0x01E51; ++outpos; break; case 0x01E52: folded[outpos] = 0x01E53; ++outpos; break; case 0x01E54: folded[outpos] = 0x01E55; ++outpos; break; case 0x01E56: folded[outpos] = 0x01E57; ++outpos; break; case 0x01E58: folded[outpos] = 0x01E59; ++outpos; break; case 0x01E5A: folded[outpos] = 0x01E5B; ++outpos; break; case 0x01E5C: folded[outpos] = 0x01E5D; ++outpos; break; case 0x01E5E: folded[outpos] = 0x01E5F; ++outpos; break; case 0x01E60: folded[outpos] = 0x01E61; ++outpos; break; case 0x01E62: folded[outpos] = 0x01E63; ++outpos; break; case 0x01E64: folded[outpos] = 0x01E65; ++outpos; break; case 0x01E66: folded[outpos] = 0x01E67; ++outpos; break; case 0x01E68: folded[outpos] = 0x01E69; ++outpos; break; case 0x01E6A: folded[outpos] = 0x01E6B; ++outpos; break; case 0x01E6C: folded[outpos] = 0x01E6D; ++outpos; break; case 0x01E6E: folded[outpos] = 0x01E6F; ++outpos; break; case 0x01E70: folded[outpos] = 0x01E71; ++outpos; break; case 0x01E72: folded[outpos] = 0x01E73; ++outpos; break; case 0x01E74: folded[outpos] = 0x01E75; ++outpos; break; case 0x01E76: folded[outpos] = 0x01E77; ++outpos; break; case 0x01E78: folded[outpos] = 0x01E79; ++outpos; break; case 0x01E7A: folded[outpos] = 0x01E7B; ++outpos; break; case 0x01E7C: folded[outpos] = 0x01E7D; ++outpos; break; case 0x01E7E: folded[outpos] = 0x01E7F; ++outpos; break; case 0x01E80: folded[outpos] = 0x01E81; ++outpos; break; case 0x01E82: folded[outpos] = 0x01E83; ++outpos; break; case 0x01E84: folded[outpos] = 0x01E85; ++outpos; break; case 0x01E86: folded[outpos] = 0x01E87; ++outpos; break; case 0x01E88: folded[outpos] = 0x01E89; ++outpos; break; case 0x01E8A: folded[outpos] = 0x01E8B; ++outpos; break; case 0x01E8C: folded[outpos] = 0x01E8D; ++outpos; break; case 0x01E8E: folded[outpos] = 0x01E8F; ++outpos; break; case 0x01E90: folded[outpos] = 0x01E91; ++outpos; break; case 0x01E92: folded[outpos] = 0x01E93; ++outpos; break; case 0x01E94: folded[outpos] = 0x01E95; ++outpos; break; case 0x01E96: folded[outpos] = 0x00068; ++outpos; folded[outpos] = 0x00331; ++outpos; break; case 0x01E97: folded[outpos] = 0x00074; ++outpos; folded[outpos] = 0x00308; ++outpos; break; case 0x01E98: folded[outpos] = 0x00077; ++outpos; folded[outpos] = 0x0030A; ++outpos; break; case 0x01E99: folded[outpos] = 0x00079; ++outpos; folded[outpos] = 0x0030A; ++outpos; break; case 0x01E9A: folded[outpos] = 0x00061; ++outpos; folded[outpos] = 0x002BE; ++outpos; break; case 0x01E9B: folded[outpos] = 0x01E61; ++outpos; break; case 0x01E9E: folded[outpos] = 0x00073; ++outpos; folded[outpos] = 0x00073; ++outpos; break; case 0x01EA0: folded[outpos] = 0x01EA1; ++outpos; break; case 0x01EA2: folded[outpos] = 0x01EA3; ++outpos; break; case 0x01EA4: folded[outpos] = 0x01EA5; ++outpos; break; case 0x01EA6: folded[outpos] = 0x01EA7; ++outpos; break; case 0x01EA8: folded[outpos] = 0x01EA9; ++outpos; break; case 0x01EAA: folded[outpos] = 0x01EAB; ++outpos; break; case 0x01EAC: folded[outpos] = 0x01EAD; ++outpos; break; case 0x01EAE: folded[outpos] = 0x01EAF; ++outpos; break; case 0x01EB0: folded[outpos] = 0x01EB1; ++outpos; break; case 0x01EB2: folded[outpos] = 0x01EB3; ++outpos; break; case 0x01EB4: folded[outpos] = 0x01EB5; ++outpos; break; case 0x01EB6: folded[outpos] = 0x01EB7; ++outpos; break; case 0x01EB8: folded[outpos] = 0x01EB9; ++outpos; break; case 0x01EBA: folded[outpos] = 0x01EBB; ++outpos; break; case 0x01EBC: folded[outpos] = 0x01EBD; ++outpos; break; case 0x01EBE: folded[outpos] = 0x01EBF; ++outpos; break; case 0x01EC0: folded[outpos] = 0x01EC1; ++outpos; break; case 0x01EC2: folded[outpos] = 0x01EC3; ++outpos; break; case 0x01EC4: folded[outpos] = 0x01EC5; ++outpos; break; case 0x01EC6: folded[outpos] = 0x01EC7; ++outpos; break; case 0x01EC8: folded[outpos] = 0x01EC9; ++outpos; break; case 0x01ECA: folded[outpos] = 0x01ECB; ++outpos; break; case 0x01ECC: folded[outpos] = 0x01ECD; ++outpos; break; case 0x01ECE: folded[outpos] = 0x01ECF; ++outpos; break; case 0x01ED0: folded[outpos] = 0x01ED1; ++outpos; break; case 0x01ED2: folded[outpos] = 0x01ED3; ++outpos; break; case 0x01ED4: folded[outpos] = 0x01ED5; ++outpos; break; case 0x01ED6: folded[outpos] = 0x01ED7; ++outpos; break; case 0x01ED8: folded[outpos] = 0x01ED9; ++outpos; break; case 0x01EDA: folded[outpos] = 0x01EDB; ++outpos; break; case 0x01EDC: folded[outpos] = 0x01EDD; ++outpos; break; case 0x01EDE: folded[outpos] = 0x01EDF; ++outpos; break; case 0x01EE0: folded[outpos] = 0x01EE1; ++outpos; break; case 0x01EE2: folded[outpos] = 0x01EE3; ++outpos; break; case 0x01EE4: folded[outpos] = 0x01EE5; ++outpos; break; case 0x01EE6: folded[outpos] = 0x01EE7; ++outpos; break; case 0x01EE8: folded[outpos] = 0x01EE9; ++outpos; break; case 0x01EEA: folded[outpos] = 0x01EEB; ++outpos; break; case 0x01EEC: folded[outpos] = 0x01EED; ++outpos; break; case 0x01EEE: folded[outpos] = 0x01EEF; ++outpos; break; case 0x01EF0: folded[outpos] = 0x01EF1; ++outpos; break; case 0x01EF2: folded[outpos] = 0x01EF3; ++outpos; break; case 0x01EF4: folded[outpos] = 0x01EF5; ++outpos; break; case 0x01EF6: folded[outpos] = 0x01EF7; ++outpos; break; case 0x01EF8: folded[outpos] = 0x01EF9; ++outpos; break; case 0x01EFA: folded[outpos] = 0x01EFB; ++outpos; break; case 0x01EFC: folded[outpos] = 0x01EFD; ++outpos; break; case 0x01EFE: folded[outpos] = 0x01EFF; ++outpos; break; case 0x01F08: folded[outpos] = 0x01F00; ++outpos; break; case 0x01F09: folded[outpos] = 0x01F01; ++outpos; break; case 0x01F0A: folded[outpos] = 0x01F02; ++outpos; break; case 0x01F0B: folded[outpos] = 0x01F03; ++outpos; break; case 0x01F0C: folded[outpos] = 0x01F04; ++outpos; break; case 0x01F0D: folded[outpos] = 0x01F05; ++outpos; break; case 0x01F0E: folded[outpos] = 0x01F06; ++outpos; break; case 0x01F0F: folded[outpos] = 0x01F07; ++outpos; break; case 0x01F18: folded[outpos] = 0x01F10; ++outpos; break; case 0x01F19: folded[outpos] = 0x01F11; ++outpos; break; case 0x01F1A: folded[outpos] = 0x01F12; ++outpos; break; case 0x01F1B: folded[outpos] = 0x01F13; ++outpos; break; case 0x01F1C: folded[outpos] = 0x01F14; ++outpos; break; case 0x01F1D: folded[outpos] = 0x01F15; ++outpos; break; case 0x01F28: folded[outpos] = 0x01F20; ++outpos; break; case 0x01F29: folded[outpos] = 0x01F21; ++outpos; break; case 0x01F2A: folded[outpos] = 0x01F22; ++outpos; break; case 0x01F2B: folded[outpos] = 0x01F23; ++outpos; break; case 0x01F2C: folded[outpos] = 0x01F24; ++outpos; break; case 0x01F2D: folded[outpos] = 0x01F25; ++outpos; break; case 0x01F2E: folded[outpos] = 0x01F26; ++outpos; break; case 0x01F2F: folded[outpos] = 0x01F27; ++outpos; break; case 0x01F38: folded[outpos] = 0x01F30; ++outpos; break; case 0x01F39: folded[outpos] = 0x01F31; ++outpos; break; case 0x01F3A: folded[outpos] = 0x01F32; ++outpos; break; case 0x01F3B: folded[outpos] = 0x01F33; ++outpos; break; case 0x01F3C: folded[outpos] = 0x01F34; ++outpos; break; case 0x01F3D: folded[outpos] = 0x01F35; ++outpos; break; case 0x01F3E: folded[outpos] = 0x01F36; ++outpos; break; case 0x01F3F: folded[outpos] = 0x01F37; ++outpos; break; case 0x01F48: folded[outpos] = 0x01F40; ++outpos; break; case 0x01F49: folded[outpos] = 0x01F41; ++outpos; break; case 0x01F4A: folded[outpos] = 0x01F42; ++outpos; break; case 0x01F4B: folded[outpos] = 0x01F43; ++outpos; break; case 0x01F4C: folded[outpos] = 0x01F44; ++outpos; break; case 0x01F4D: folded[outpos] = 0x01F45; ++outpos; break; case 0x01F50: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00313; ++outpos; break; case 0x01F52: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00313; ++outpos; folded[outpos] = 0x00300; ++outpos; break; case 0x01F54: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00313; ++outpos; folded[outpos] = 0x00301; ++outpos; break; case 0x01F56: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00313; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01F59: folded[outpos] = 0x01F51; ++outpos; break; case 0x01F5B: folded[outpos] = 0x01F53; ++outpos; break; case 0x01F5D: folded[outpos] = 0x01F55; ++outpos; break; case 0x01F5F: folded[outpos] = 0x01F57; ++outpos; break; case 0x01F68: folded[outpos] = 0x01F60; ++outpos; break; case 0x01F69: folded[outpos] = 0x01F61; ++outpos; break; case 0x01F6A: folded[outpos] = 0x01F62; ++outpos; break; case 0x01F6B: folded[outpos] = 0x01F63; ++outpos; break; case 0x01F6C: folded[outpos] = 0x01F64; ++outpos; break; case 0x01F6D: folded[outpos] = 0x01F65; ++outpos; break; case 0x01F6E: folded[outpos] = 0x01F66; ++outpos; break; case 0x01F6F: folded[outpos] = 0x01F67; ++outpos; break; case 0x01F80: folded[outpos] = 0x01F00; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F81: folded[outpos] = 0x01F01; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F82: folded[outpos] = 0x01F02; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F83: folded[outpos] = 0x01F03; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F84: folded[outpos] = 0x01F04; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F85: folded[outpos] = 0x01F05; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F86: folded[outpos] = 0x01F06; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F87: folded[outpos] = 0x01F07; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F88: folded[outpos] = 0x01F00; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F89: folded[outpos] = 0x01F01; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F8A: folded[outpos] = 0x01F02; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F8B: folded[outpos] = 0x01F03; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F8C: folded[outpos] = 0x01F04; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F8D: folded[outpos] = 0x01F05; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F8E: folded[outpos] = 0x01F06; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F8F: folded[outpos] = 0x01F07; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F90: folded[outpos] = 0x01F20; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F91: folded[outpos] = 0x01F21; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F92: folded[outpos] = 0x01F22; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F93: folded[outpos] = 0x01F23; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F94: folded[outpos] = 0x01F24; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F95: folded[outpos] = 0x01F25; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F96: folded[outpos] = 0x01F26; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F97: folded[outpos] = 0x01F27; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F98: folded[outpos] = 0x01F20; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F99: folded[outpos] = 0x01F21; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F9A: folded[outpos] = 0x01F22; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F9B: folded[outpos] = 0x01F23; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F9C: folded[outpos] = 0x01F24; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F9D: folded[outpos] = 0x01F25; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F9E: folded[outpos] = 0x01F26; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01F9F: folded[outpos] = 0x01F27; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA0: folded[outpos] = 0x01F60; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA1: folded[outpos] = 0x01F61; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA2: folded[outpos] = 0x01F62; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA3: folded[outpos] = 0x01F63; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA4: folded[outpos] = 0x01F64; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA5: folded[outpos] = 0x01F65; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA6: folded[outpos] = 0x01F66; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA7: folded[outpos] = 0x01F67; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA8: folded[outpos] = 0x01F60; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FA9: folded[outpos] = 0x01F61; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FAA: folded[outpos] = 0x01F62; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FAB: folded[outpos] = 0x01F63; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FAC: folded[outpos] = 0x01F64; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FAD: folded[outpos] = 0x01F65; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FAE: folded[outpos] = 0x01F66; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FAF: folded[outpos] = 0x01F67; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FB2: folded[outpos] = 0x01F70; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FB3: folded[outpos] = 0x003B1; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FB4: folded[outpos] = 0x003AC; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FB6: folded[outpos] = 0x003B1; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FB7: folded[outpos] = 0x003B1; ++outpos; folded[outpos] = 0x00342; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FB8: folded[outpos] = 0x01FB0; ++outpos; break; case 0x01FB9: folded[outpos] = 0x01FB1; ++outpos; break; case 0x01FBA: folded[outpos] = 0x01F70; ++outpos; break; case 0x01FBB: folded[outpos] = 0x01F71; ++outpos; break; case 0x01FBC: folded[outpos] = 0x003B1; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FBE: folded[outpos] = 0x003B9; ++outpos; break; case 0x01FC2: folded[outpos] = 0x01F74; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FC3: folded[outpos] = 0x003B7; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FC4: folded[outpos] = 0x003AE; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FC6: folded[outpos] = 0x003B7; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FC7: folded[outpos] = 0x003B7; ++outpos; folded[outpos] = 0x00342; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FC8: folded[outpos] = 0x01F72; ++outpos; break; case 0x01FC9: folded[outpos] = 0x01F73; ++outpos; break; case 0x01FCA: folded[outpos] = 0x01F74; ++outpos; break; case 0x01FCB: folded[outpos] = 0x01F75; ++outpos; break; case 0x01FCC: folded[outpos] = 0x003B7; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FD2: folded[outpos] = 0x003B9; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00300; ++outpos; break; case 0x01FD3: folded[outpos] = 0x003B9; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00301; ++outpos; break; case 0x01FD6: folded[outpos] = 0x003B9; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FD7: folded[outpos] = 0x003B9; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FD8: folded[outpos] = 0x01FD0; ++outpos; break; case 0x01FD9: folded[outpos] = 0x01FD1; ++outpos; break; case 0x01FDA: folded[outpos] = 0x01F76; ++outpos; break; case 0x01FDB: folded[outpos] = 0x01F77; ++outpos; break; case 0x01FE2: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00300; ++outpos; break; case 0x01FE3: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00301; ++outpos; break; case 0x01FE4: folded[outpos] = 0x003C1; ++outpos; folded[outpos] = 0x00313; ++outpos; break; case 0x01FE6: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FE7: folded[outpos] = 0x003C5; ++outpos; folded[outpos] = 0x00308; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FE8: folded[outpos] = 0x01FE0; ++outpos; break; case 0x01FE9: folded[outpos] = 0x01FE1; ++outpos; break; case 0x01FEA: folded[outpos] = 0x01F7A; ++outpos; break; case 0x01FEB: folded[outpos] = 0x01F7B; ++outpos; break; case 0x01FEC: folded[outpos] = 0x01FE5; ++outpos; break; case 0x01FF2: folded[outpos] = 0x01F7C; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FF3: folded[outpos] = 0x003C9; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FF4: folded[outpos] = 0x003CE; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FF6: folded[outpos] = 0x003C9; ++outpos; folded[outpos] = 0x00342; ++outpos; break; case 0x01FF7: folded[outpos] = 0x003C9; ++outpos; folded[outpos] = 0x00342; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x01FF8: folded[outpos] = 0x01F78; ++outpos; break; case 0x01FF9: folded[outpos] = 0x01F79; ++outpos; break; case 0x01FFA: folded[outpos] = 0x01F7C; ++outpos; break; case 0x01FFB: folded[outpos] = 0x01F7D; ++outpos; break; case 0x01FFC: folded[outpos] = 0x003C9; ++outpos; folded[outpos] = 0x003B9; ++outpos; break; case 0x02126: folded[outpos] = 0x003C9; ++outpos; break; case 0x0212A: folded[outpos] = 0x0006B; ++outpos; break; case 0x0212B: folded[outpos] = 0x000E5; ++outpos; break; case 0x02132: folded[outpos] = 0x0214E; ++outpos; break; case 0x02160: folded[outpos] = 0x02170; ++outpos; break; case 0x02161: folded[outpos] = 0x02171; ++outpos; break; case 0x02162: folded[outpos] = 0x02172; ++outpos; break; case 0x02163: folded[outpos] = 0x02173; ++outpos; break; case 0x02164: folded[outpos] = 0x02174; ++outpos; break; case 0x02165: folded[outpos] = 0x02175; ++outpos; break; case 0x02166: folded[outpos] = 0x02176; ++outpos; break; case 0x02167: folded[outpos] = 0x02177; ++outpos; break; case 0x02168: folded[outpos] = 0x02178; ++outpos; break; case 0x02169: folded[outpos] = 0x02179; ++outpos; break; case 0x0216A: folded[outpos] = 0x0217A; ++outpos; break; case 0x0216B: folded[outpos] = 0x0217B; ++outpos; break; case 0x0216C: folded[outpos] = 0x0217C; ++outpos; break; case 0x0216D: folded[outpos] = 0x0217D; ++outpos; break; case 0x0216E: folded[outpos] = 0x0217E; ++outpos; break; case 0x0216F: folded[outpos] = 0x0217F; ++outpos; break; case 0x02183: folded[outpos] = 0x02184; ++outpos; break; case 0x024B6: folded[outpos] = 0x024D0; ++outpos; break; case 0x024B7: folded[outpos] = 0x024D1; ++outpos; break; case 0x024B8: folded[outpos] = 0x024D2; ++outpos; break; case 0x024B9: folded[outpos] = 0x024D3; ++outpos; break; case 0x024BA: folded[outpos] = 0x024D4; ++outpos; break; case 0x024BB: folded[outpos] = 0x024D5; ++outpos; break; case 0x024BC: folded[outpos] = 0x024D6; ++outpos; break; case 0x024BD: folded[outpos] = 0x024D7; ++outpos; break; case 0x024BE: folded[outpos] = 0x024D8; ++outpos; break; case 0x024BF: folded[outpos] = 0x024D9; ++outpos; break; case 0x024C0: folded[outpos] = 0x024DA; ++outpos; break; case 0x024C1: folded[outpos] = 0x024DB; ++outpos; break; case 0x024C2: folded[outpos] = 0x024DC; ++outpos; break; case 0x024C3: folded[outpos] = 0x024DD; ++outpos; break; case 0x024C4: folded[outpos] = 0x024DE; ++outpos; break; case 0x024C5: folded[outpos] = 0x024DF; ++outpos; break; case 0x024C6: folded[outpos] = 0x024E0; ++outpos; break; case 0x024C7: folded[outpos] = 0x024E1; ++outpos; break; case 0x024C8: folded[outpos] = 0x024E2; ++outpos; break; case 0x024C9: folded[outpos] = 0x024E3; ++outpos; break; case 0x024CA: folded[outpos] = 0x024E4; ++outpos; break; case 0x024CB: folded[outpos] = 0x024E5; ++outpos; break; case 0x024CC: folded[outpos] = 0x024E6; ++outpos; break; case 0x024CD: folded[outpos] = 0x024E7; ++outpos; break; case 0x024CE: folded[outpos] = 0x024E8; ++outpos; break; case 0x024CF: folded[outpos] = 0x024E9; ++outpos; break; case 0x02C00: folded[outpos] = 0x02C30; ++outpos; break; case 0x02C01: folded[outpos] = 0x02C31; ++outpos; break; case 0x02C02: folded[outpos] = 0x02C32; ++outpos; break; case 0x02C03: folded[outpos] = 0x02C33; ++outpos; break; case 0x02C04: folded[outpos] = 0x02C34; ++outpos; break; case 0x02C05: folded[outpos] = 0x02C35; ++outpos; break; case 0x02C06: folded[outpos] = 0x02C36; ++outpos; break; case 0x02C07: folded[outpos] = 0x02C37; ++outpos; break; case 0x02C08: folded[outpos] = 0x02C38; ++outpos; break; case 0x02C09: folded[outpos] = 0x02C39; ++outpos; break; case 0x02C0A: folded[outpos] = 0x02C3A; ++outpos; break; case 0x02C0B: folded[outpos] = 0x02C3B; ++outpos; break; case 0x02C0C: folded[outpos] = 0x02C3C; ++outpos; break; case 0x02C0D: folded[outpos] = 0x02C3D; ++outpos; break; case 0x02C0E: folded[outpos] = 0x02C3E; ++outpos; break; case 0x02C0F: folded[outpos] = 0x02C3F; ++outpos; break; case 0x02C10: folded[outpos] = 0x02C40; ++outpos; break; case 0x02C11: folded[outpos] = 0x02C41; ++outpos; break; case 0x02C12: folded[outpos] = 0x02C42; ++outpos; break; case 0x02C13: folded[outpos] = 0x02C43; ++outpos; break; case 0x02C14: folded[outpos] = 0x02C44; ++outpos; break; case 0x02C15: folded[outpos] = 0x02C45; ++outpos; break; case 0x02C16: folded[outpos] = 0x02C46; ++outpos; break; case 0x02C17: folded[outpos] = 0x02C47; ++outpos; break; case 0x02C18: folded[outpos] = 0x02C48; ++outpos; break; case 0x02C19: folded[outpos] = 0x02C49; ++outpos; break; case 0x02C1A: folded[outpos] = 0x02C4A; ++outpos; break; case 0x02C1B: folded[outpos] = 0x02C4B; ++outpos; break; case 0x02C1C: folded[outpos] = 0x02C4C; ++outpos; break; case 0x02C1D: folded[outpos] = 0x02C4D; ++outpos; break; case 0x02C1E: folded[outpos] = 0x02C4E; ++outpos; break; case 0x02C1F: folded[outpos] = 0x02C4F; ++outpos; break; case 0x02C20: folded[outpos] = 0x02C50; ++outpos; break; case 0x02C21: folded[outpos] = 0x02C51; ++outpos; break; case 0x02C22: folded[outpos] = 0x02C52; ++outpos; break; case 0x02C23: folded[outpos] = 0x02C53; ++outpos; break; case 0x02C24: folded[outpos] = 0x02C54; ++outpos; break; case 0x02C25: folded[outpos] = 0x02C55; ++outpos; break; case 0x02C26: folded[outpos] = 0x02C56; ++outpos; break; case 0x02C27: folded[outpos] = 0x02C57; ++outpos; break; case 0x02C28: folded[outpos] = 0x02C58; ++outpos; break; case 0x02C29: folded[outpos] = 0x02C59; ++outpos; break; case 0x02C2A: folded[outpos] = 0x02C5A; ++outpos; break; case 0x02C2B: folded[outpos] = 0x02C5B; ++outpos; break; case 0x02C2C: folded[outpos] = 0x02C5C; ++outpos; break; case 0x02C2D: folded[outpos] = 0x02C5D; ++outpos; break; case 0x02C2E: folded[outpos] = 0x02C5E; ++outpos; break; case 0x02C60: folded[outpos] = 0x02C61; ++outpos; break; case 0x02C62: folded[outpos] = 0x0026B; ++outpos; break; case 0x02C63: folded[outpos] = 0x01D7D; ++outpos; break; case 0x02C64: folded[outpos] = 0x0027D; ++outpos; break; case 0x02C67: folded[outpos] = 0x02C68; ++outpos; break; case 0x02C69: folded[outpos] = 0x02C6A; ++outpos; break; case 0x02C6B: folded[outpos] = 0x02C6C; ++outpos; break; case 0x02C6D: folded[outpos] = 0x00251; ++outpos; break; case 0x02C6E: folded[outpos] = 0x00271; ++outpos; break; case 0x02C6F: folded[outpos] = 0x00250; ++outpos; break; case 0x02C72: folded[outpos] = 0x02C73; ++outpos; break; case 0x02C75: folded[outpos] = 0x02C76; ++outpos; break; case 0x02C80: folded[outpos] = 0x02C81; ++outpos; break; case 0x02C82: folded[outpos] = 0x02C83; ++outpos; break; case 0x02C84: folded[outpos] = 0x02C85; ++outpos; break; case 0x02C86: folded[outpos] = 0x02C87; ++outpos; break; case 0x02C88: folded[outpos] = 0x02C89; ++outpos; break; case 0x02C8A: folded[outpos] = 0x02C8B; ++outpos; break; case 0x02C8C: folded[outpos] = 0x02C8D; ++outpos; break; case 0x02C8E: folded[outpos] = 0x02C8F; ++outpos; break; case 0x02C90: folded[outpos] = 0x02C91; ++outpos; break; case 0x02C92: folded[outpos] = 0x02C93; ++outpos; break; case 0x02C94: folded[outpos] = 0x02C95; ++outpos; break; case 0x02C96: folded[outpos] = 0x02C97; ++outpos; break; case 0x02C98: folded[outpos] = 0x02C99; ++outpos; break; case 0x02C9A: folded[outpos] = 0x02C9B; ++outpos; break; case 0x02C9C: folded[outpos] = 0x02C9D; ++outpos; break; case 0x02C9E: folded[outpos] = 0x02C9F; ++outpos; break; case 0x02CA0: folded[outpos] = 0x02CA1; ++outpos; break; case 0x02CA2: folded[outpos] = 0x02CA3; ++outpos; break; case 0x02CA4: folded[outpos] = 0x02CA5; ++outpos; break; case 0x02CA6: folded[outpos] = 0x02CA7; ++outpos; break; case 0x02CA8: folded[outpos] = 0x02CA9; ++outpos; break; case 0x02CAA: folded[outpos] = 0x02CAB; ++outpos; break; case 0x02CAC: folded[outpos] = 0x02CAD; ++outpos; break; case 0x02CAE: folded[outpos] = 0x02CAF; ++outpos; break; case 0x02CB0: folded[outpos] = 0x02CB1; ++outpos; break; case 0x02CB2: folded[outpos] = 0x02CB3; ++outpos; break; case 0x02CB4: folded[outpos] = 0x02CB5; ++outpos; break; case 0x02CB6: folded[outpos] = 0x02CB7; ++outpos; break; case 0x02CB8: folded[outpos] = 0x02CB9; ++outpos; break; case 0x02CBA: folded[outpos] = 0x02CBB; ++outpos; break; case 0x02CBC: folded[outpos] = 0x02CBD; ++outpos; break; case 0x02CBE: folded[outpos] = 0x02CBF; ++outpos; break; case 0x02CC0: folded[outpos] = 0x02CC1; ++outpos; break; case 0x02CC2: folded[outpos] = 0x02CC3; ++outpos; break; case 0x02CC4: folded[outpos] = 0x02CC5; ++outpos; break; case 0x02CC6: folded[outpos] = 0x02CC7; ++outpos; break; case 0x02CC8: folded[outpos] = 0x02CC9; ++outpos; break; case 0x02CCA: folded[outpos] = 0x02CCB; ++outpos; break; case 0x02CCC: folded[outpos] = 0x02CCD; ++outpos; break; case 0x02CCE: folded[outpos] = 0x02CCF; ++outpos; break; case 0x02CD0: folded[outpos] = 0x02CD1; ++outpos; break; case 0x02CD2: folded[outpos] = 0x02CD3; ++outpos; break; case 0x02CD4: folded[outpos] = 0x02CD5; ++outpos; break; case 0x02CD6: folded[outpos] = 0x02CD7; ++outpos; break; case 0x02CD8: folded[outpos] = 0x02CD9; ++outpos; break; case 0x02CDA: folded[outpos] = 0x02CDB; ++outpos; break; case 0x02CDC: folded[outpos] = 0x02CDD; ++outpos; break; case 0x02CDE: folded[outpos] = 0x02CDF; ++outpos; break; case 0x02CE0: folded[outpos] = 0x02CE1; ++outpos; break; case 0x02CE2: folded[outpos] = 0x02CE3; ++outpos; break; case 0x0A640: folded[outpos] = 0x0A641; ++outpos; break; case 0x0A642: folded[outpos] = 0x0A643; ++outpos; break; case 0x0A644: folded[outpos] = 0x0A645; ++outpos; break; case 0x0A646: folded[outpos] = 0x0A647; ++outpos; break; case 0x0A648: folded[outpos] = 0x0A649; ++outpos; break; case 0x0A64A: folded[outpos] = 0x0A64B; ++outpos; break; case 0x0A64C: folded[outpos] = 0x0A64D; ++outpos; break; case 0x0A64E: folded[outpos] = 0x0A64F; ++outpos; break; case 0x0A650: folded[outpos] = 0x0A651; ++outpos; break; case 0x0A652: folded[outpos] = 0x0A653; ++outpos; break; case 0x0A654: folded[outpos] = 0x0A655; ++outpos; break; case 0x0A656: folded[outpos] = 0x0A657; ++outpos; break; case 0x0A658: folded[outpos] = 0x0A659; ++outpos; break; case 0x0A65A: folded[outpos] = 0x0A65B; ++outpos; break; case 0x0A65C: folded[outpos] = 0x0A65D; ++outpos; break; case 0x0A65E: folded[outpos] = 0x0A65F; ++outpos; break; case 0x0A662: folded[outpos] = 0x0A663; ++outpos; break; case 0x0A664: folded[outpos] = 0x0A665; ++outpos; break; case 0x0A666: folded[outpos] = 0x0A667; ++outpos; break; case 0x0A668: folded[outpos] = 0x0A669; ++outpos; break; case 0x0A66A: folded[outpos] = 0x0A66B; ++outpos; break; case 0x0A66C: folded[outpos] = 0x0A66D; ++outpos; break; case 0x0A680: folded[outpos] = 0x0A681; ++outpos; break; case 0x0A682: folded[outpos] = 0x0A683; ++outpos; break; case 0x0A684: folded[outpos] = 0x0A685; ++outpos; break; case 0x0A686: folded[outpos] = 0x0A687; ++outpos; break; case 0x0A688: folded[outpos] = 0x0A689; ++outpos; break; case 0x0A68A: folded[outpos] = 0x0A68B; ++outpos; break; case 0x0A68C: folded[outpos] = 0x0A68D; ++outpos; break; case 0x0A68E: folded[outpos] = 0x0A68F; ++outpos; break; case 0x0A690: folded[outpos] = 0x0A691; ++outpos; break; case 0x0A692: folded[outpos] = 0x0A693; ++outpos; break; case 0x0A694: folded[outpos] = 0x0A695; ++outpos; break; case 0x0A696: folded[outpos] = 0x0A697; ++outpos; break; case 0x0A722: folded[outpos] = 0x0A723; ++outpos; break; case 0x0A724: folded[outpos] = 0x0A725; ++outpos; break; case 0x0A726: folded[outpos] = 0x0A727; ++outpos; break; case 0x0A728: folded[outpos] = 0x0A729; ++outpos; break; case 0x0A72A: folded[outpos] = 0x0A72B; ++outpos; break; case 0x0A72C: folded[outpos] = 0x0A72D; ++outpos; break; case 0x0A72E: folded[outpos] = 0x0A72F; ++outpos; break; case 0x0A732: folded[outpos] = 0x0A733; ++outpos; break; case 0x0A734: folded[outpos] = 0x0A735; ++outpos; break; case 0x0A736: folded[outpos] = 0x0A737; ++outpos; break; case 0x0A738: folded[outpos] = 0x0A739; ++outpos; break; case 0x0A73A: folded[outpos] = 0x0A73B; ++outpos; break; case 0x0A73C: folded[outpos] = 0x0A73D; ++outpos; break; case 0x0A73E: folded[outpos] = 0x0A73F; ++outpos; break; case 0x0A740: folded[outpos] = 0x0A741; ++outpos; break; case 0x0A742: folded[outpos] = 0x0A743; ++outpos; break; case 0x0A744: folded[outpos] = 0x0A745; ++outpos; break; case 0x0A746: folded[outpos] = 0x0A747; ++outpos; break; case 0x0A748: folded[outpos] = 0x0A749; ++outpos; break; case 0x0A74A: folded[outpos] = 0x0A74B; ++outpos; break; case 0x0A74C: folded[outpos] = 0x0A74D; ++outpos; break; case 0x0A74E: folded[outpos] = 0x0A74F; ++outpos; break; case 0x0A750: folded[outpos] = 0x0A751; ++outpos; break; case 0x0A752: folded[outpos] = 0x0A753; ++outpos; break; case 0x0A754: folded[outpos] = 0x0A755; ++outpos; break; case 0x0A756: folded[outpos] = 0x0A757; ++outpos; break; case 0x0A758: folded[outpos] = 0x0A759; ++outpos; break; case 0x0A75A: folded[outpos] = 0x0A75B; ++outpos; break; case 0x0A75C: folded[outpos] = 0x0A75D; ++outpos; break; case 0x0A75E: folded[outpos] = 0x0A75F; ++outpos; break; case 0x0A760: folded[outpos] = 0x0A761; ++outpos; break; case 0x0A762: folded[outpos] = 0x0A763; ++outpos; break; case 0x0A764: folded[outpos] = 0x0A765; ++outpos; break; case 0x0A766: folded[outpos] = 0x0A767; ++outpos; break; case 0x0A768: folded[outpos] = 0x0A769; ++outpos; break; case 0x0A76A: folded[outpos] = 0x0A76B; ++outpos; break; case 0x0A76C: folded[outpos] = 0x0A76D; ++outpos; break; case 0x0A76E: folded[outpos] = 0x0A76F; ++outpos; break; case 0x0A779: folded[outpos] = 0x0A77A; ++outpos; break; case 0x0A77B: folded[outpos] = 0x0A77C; ++outpos; break; case 0x0A77D: folded[outpos] = 0x01D79; ++outpos; break; case 0x0A77E: folded[outpos] = 0x0A77F; ++outpos; break; case 0x0A780: folded[outpos] = 0x0A781; ++outpos; break; case 0x0A782: folded[outpos] = 0x0A783; ++outpos; break; case 0x0A784: folded[outpos] = 0x0A785; ++outpos; break; case 0x0A786: folded[outpos] = 0x0A787; ++outpos; break; case 0x0A78B: folded[outpos] = 0x0A78C; ++outpos; break; case 0x0FB00: folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x00066; ++outpos; break; case 0x0FB01: folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x00069; ++outpos; break; case 0x0FB02: folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x0006C; ++outpos; break; case 0x0FB03: folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x00069; ++outpos; break; case 0x0FB04: folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x00066; ++outpos; folded[outpos] = 0x0006C; ++outpos; break; case 0x0FB05: folded[outpos] = 0x00073; ++outpos; folded[outpos] = 0x00074; ++outpos; break; case 0x0FB06: folded[outpos] = 0x00073; ++outpos; folded[outpos] = 0x00074; ++outpos; break; case 0x0FB13: folded[outpos] = 0x00574; ++outpos; folded[outpos] = 0x00576; ++outpos; break; case 0x0FB14: folded[outpos] = 0x00574; ++outpos; folded[outpos] = 0x00565; ++outpos; break; case 0x0FB15: folded[outpos] = 0x00574; ++outpos; folded[outpos] = 0x0056B; ++outpos; break; case 0x0FB16: folded[outpos] = 0x0057E; ++outpos; folded[outpos] = 0x00576; ++outpos; break; case 0x0FB17: folded[outpos] = 0x00574; ++outpos; folded[outpos] = 0x0056D; ++outpos; break; case 0x0FF21: folded[outpos] = 0x0FF41; ++outpos; break; case 0x0FF22: folded[outpos] = 0x0FF42; ++outpos; break; case 0x0FF23: folded[outpos] = 0x0FF43; ++outpos; break; case 0x0FF24: folded[outpos] = 0x0FF44; ++outpos; break; case 0x0FF25: folded[outpos] = 0x0FF45; ++outpos; break; case 0x0FF26: folded[outpos] = 0x0FF46; ++outpos; break; case 0x0FF27: folded[outpos] = 0x0FF47; ++outpos; break; case 0x0FF28: folded[outpos] = 0x0FF48; ++outpos; break; case 0x0FF29: folded[outpos] = 0x0FF49; ++outpos; break; case 0x0FF2A: folded[outpos] = 0x0FF4A; ++outpos; break; case 0x0FF2B: folded[outpos] = 0x0FF4B; ++outpos; break; case 0x0FF2C: folded[outpos] = 0x0FF4C; ++outpos; break; case 0x0FF2D: folded[outpos] = 0x0FF4D; ++outpos; break; case 0x0FF2E: folded[outpos] = 0x0FF4E; ++outpos; break; case 0x0FF2F: folded[outpos] = 0x0FF4F; ++outpos; break; case 0x0FF30: folded[outpos] = 0x0FF50; ++outpos; break; case 0x0FF31: folded[outpos] = 0x0FF51; ++outpos; break; case 0x0FF32: folded[outpos] = 0x0FF52; ++outpos; break; case 0x0FF33: folded[outpos] = 0x0FF53; ++outpos; break; case 0x0FF34: folded[outpos] = 0x0FF54; ++outpos; break; case 0x0FF35: folded[outpos] = 0x0FF55; ++outpos; break; case 0x0FF36: folded[outpos] = 0x0FF56; ++outpos; break; case 0x0FF37: folded[outpos] = 0x0FF57; ++outpos; break; case 0x0FF38: folded[outpos] = 0x0FF58; ++outpos; break; case 0x0FF39: folded[outpos] = 0x0FF59; ++outpos; break; case 0x0FF3A: folded[outpos] = 0x0FF5A; ++outpos; break; case 0x10400: folded[outpos] = 0x10428; ++outpos; break; case 0x10401: folded[outpos] = 0x10429; ++outpos; break; case 0x10402: folded[outpos] = 0x1042A; ++outpos; break; case 0x10403: folded[outpos] = 0x1042B; ++outpos; break; case 0x10404: folded[outpos] = 0x1042C; ++outpos; break; case 0x10405: folded[outpos] = 0x1042D; ++outpos; break; case 0x10406: folded[outpos] = 0x1042E; ++outpos; break; case 0x10407: folded[outpos] = 0x1042F; ++outpos; break; case 0x10408: folded[outpos] = 0x10430; ++outpos; break; case 0x10409: folded[outpos] = 0x10431; ++outpos; break; case 0x1040A: folded[outpos] = 0x10432; ++outpos; break; case 0x1040B: folded[outpos] = 0x10433; ++outpos; break; case 0x1040C: folded[outpos] = 0x10434; ++outpos; break; case 0x1040D: folded[outpos] = 0x10435; ++outpos; break; case 0x1040E: folded[outpos] = 0x10436; ++outpos; break; case 0x1040F: folded[outpos] = 0x10437; ++outpos; break; case 0x10410: folded[outpos] = 0x10438; ++outpos; break; case 0x10411: folded[outpos] = 0x10439; ++outpos; break; case 0x10412: folded[outpos] = 0x1043A; ++outpos; break; case 0x10413: folded[outpos] = 0x1043B; ++outpos; break; case 0x10414: folded[outpos] = 0x1043C; ++outpos; break; case 0x10415: folded[outpos] = 0x1043D; ++outpos; break; case 0x10416: folded[outpos] = 0x1043E; ++outpos; break; case 0x10417: folded[outpos] = 0x1043F; ++outpos; break; case 0x10418: folded[outpos] = 0x10440; ++outpos; break; case 0x10419: folded[outpos] = 0x10441; ++outpos; break; case 0x1041A: folded[outpos] = 0x10442; ++outpos; break; case 0x1041B: folded[outpos] = 0x10443; ++outpos; break; case 0x1041C: folded[outpos] = 0x10444; ++outpos; break; case 0x1041D: folded[outpos] = 0x10445; ++outpos; break; case 0x1041E: folded[outpos] = 0x10446; ++outpos; break; case 0x1041F: folded[outpos] = 0x10447; ++outpos; break; case 0x10420: folded[outpos] = 0x10448; ++outpos; break; case 0x10421: folded[outpos] = 0x10449; ++outpos; break; case 0x10422: folded[outpos] = 0x1044A; ++outpos; break; case 0x10423: folded[outpos] = 0x1044B; ++outpos; break; case 0x10424: folded[outpos] = 0x1044C; ++outpos; break; case 0x10425: folded[outpos] = 0x1044D; ++outpos; break; case 0x10426: folded[outpos] = 0x1044E; ++outpos; break; case 0x10427: folded[outpos] = 0x1044F; ++outpos; break; libdc0-0.3.24~svn3121/dclib/cquerymanager.h0000644000175000017500000000706511125260136017317 0ustar sikonsikon/*************************************************************************** cquerymanager.h - description ------------------- begin : Sat Jun 8 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CQUERYMANAGER_H #define CQUERYMANAGER_H /** *@author Mathias Küster * * This processes a queue of searches and sends the results, * the results come from CFileManager. */ #include #include #include #include #include #include #include class CQueryObject { public: /** */ CQueryObject() { pMessageSearch = 0; }; /** */ ~CQueryObject() { delete pMessageSearch; pMessageSearch = 0; }; /** */ CString sHubName; /** */ CString sHubHost; /** */ CString sNick; /** */ CMessageSearchFile * pMessageSearch; /** */ time_t tTimeout; }; class CQuerySendObject { public: /** */ CQuerySendObject() { m_pSocket = 0; m_pList = new std::list(); m_nPort = 0; } /** */ ~CQuerySendObject() { delete m_pSocket; m_pSocket = 0; delete m_pList; m_pList = 0; } /** */ CSocket * m_pSocket; /** */ std::list * m_pList; /** */ CString m_sSource; /** */ int m_nPort; }; class CMutex; class CCaseFolder; enum eSearchStat { essCOUNTACTIVE=0, essCOUNTPASSIVE, essCOUNTREJECT, essCOUNTERROR, essRESULTCOUNT, essRESULTCOUNTERROR }; class CQueryManager : public CSingleton { public: /** */ CQueryManager(); /** */ virtual ~CQueryManager(); /* */ bool SearchQuery( CString hubname, CString hubhost, CString nick, CMessageSearchFile * msg ); /** */ ulonglong GetStat( enum eSearchStat e ); private: /** callbackfunction - called by CManager */ int Callback(); /** */ void HandleQuery( CQueryObject * queryobject ); /** */ bool CheckSize( CQueryObject * queryobject, struct filebaseobject * fbo ); /** */ bool CheckType( CQueryObject * queryobject, struct filebaseobject * fbo ); /** */ bool AddResult( CQuerySendObject * querysendobject, CQueryObject * queryobject, struct filebaseobject * fbo, CString filename, CString hash = CString() ); /** */ void SendResults(); /** */ _CCallback0 * m_pCallback; /** * Mutex for query queue. * Send list was never locked/unlocked. */ CMutex * m_pQueueMutex; /** the search queue */ CList * m_pQueryQueue; /** */ CList * m_pQuerySendList; /** */ ulonglong m_nSearchCountActive; /** */ ulonglong m_nSearchCountPassive; /** */ ulonglong m_nSearchCountReject; /** */ ulonglong m_nSearchCountError; /** */ ulonglong m_nResultCount; /** */ ulonglong m_nResultCountError; /** Avoid constant iconv_open / iconv_close */ CCaseFolder * m_pCaseFolder; }; #endif libdc0-0.3.24~svn3121/dclib/cclient.h0000644000175000017500000002447611125260136016102 0ustar sikonsikon/*************************************************************************** cclient.h - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCLIENT_H #define CCLIENT_H /** *@author Mathias Küster * * A hub connection. */ #include #include #include #include #include #include #include /** */ enum eReconnectState { ersNONE, ersFORCEMOVE, ersDISABLED, ersENABLED }; /* added for zpipe data buffer */ class CZLib; class CMessageHandler; class CClient : public CDCProto { public: /** */ CClient( CString remoteEncoding = CString() ); /** */ virtual ~CClient(); /** */ bool SetUserTransferInfo( CString nick, CDCMessage * msg ); /** */ inline void SetHubName( CString hubname ); /** */ inline CString GetHubName() const; /** */ inline void SetHubTopic( CString hubtopic ); /** */ inline CString GetHubTopic() const; /** */ inline void SetNick( CString nick ); /** */ inline CString GetNick() const; /** */ inline void SetEMail( CString email ); /** */ inline CString GetEMail() const; /** */ inline void SetConnectionType( CString ctype ); /** */ inline CString GetConnectionType() const; /** */ inline void SetComment( CString comment ); /** */ inline CString GetComment() const; /** */ inline void SetShareSize( ulonglong sharesize ); /** */ inline ulonglong GetShareSize() const; /** */ inline void SetMode( eClientMode mode ); /** */ inline eClientMode GetMode() const; /** */ inline void SetAwayMode( eUserAwayMode mode ); /** */ inline eUserAwayMode GetAwayMode() const; /** True if a password was used to log in to the hub */ inline bool GetUsedPassword() const; /** */ inline void SetUsedPassword( bool b ); /** */ inline void SetMyInfoTLSFlag( bool b ); /** Returns true if supports UserIP2 */ inline bool GetSupportsUserIP2() const; /** Returns true if supports NoGetINFO */ inline bool GetSupportsNoGetInfo() const; /** */ bool IsTLSInMyInfo() const { return m_MyInfo.m_bTLSFlag; }; /** */ inline bool IsHandshake() const; /** * Returns our external IP address, either the last one given to us * by the hub or gets the one from CConfig depending on settings. * The port added is a TCP port (standard or TLS). */ CString GetExternalIP( bool addport = true, bool cryptoport = false ) const; /** */ inline void SetHandleUserList( bool b ); /** */ inline void SetHandleSearch( bool b ); /** */ inline void SetHandleMyinfo( bool b ); /** */ inline void SetSendMyinfo( bool b ); /** */ inline void SetHandleForceMove( bool b ); /** */ inline void SetHandleTransfer( bool b ); /** */ inline void SetSSLMode( bool b ); /** */ inline CUserList * UserList() { return &m_UserList; }; /** */ inline void SetCallBackFunction( _CCallback2 * callback ); /** */ int HandleMessage( const CString & message ); /** send private message */ virtual int SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick = CString() ); /** */ virtual int RequestNickList(); /** */ virtual void DataAvailable( const char * buffer, int len ); /** */ virtual void DataTimeout(); /** */ virtual void Notify(); /** */ virtual void ConnectionState( eConnectionState state ); /** callback function */ virtual int DC_CallBack( CDCMessage * ) { return -1; }; /** */ int Disconnect( bool force = false ); /** Overridden to use our external IP for active and our nick for passive searches */ int SendSearch( CMessageSearchFile * msg ); protected: /** */ void UpdateReconnect( eReconnectState state, int count = -1 ); private: /** Send SSL log messages to GUI */ void SendSSLInfo(); /** user list */ CUserList m_UserList; /** */ CClientSSL m_pMessageSSL; /** user myinfo */ CMessageMyInfo m_MyInfo; /** hubname */ CString m_sHubName; /** hubtopic */ CString m_sHubTopic; /** Our External IP address */ CString m_sExternalIP; /** */ bool m_bHandshake; /** */ bool m_bSSLMode; /** */ bool m_bHandleUserList; /** */ bool m_bHandleSearch; /** */ bool m_bHandleMyinfo; /** */ bool m_bHandleForceMove; /** */ bool m_bHandleTransfer; /** */ bool m_bUpdateMyinfo; /** */ bool m_bSendMyinfo; /** */ bool m_bUsedPassword; /** */ time_t m_timeMyinfoTimeout; /** */ CString m_sBuffer; /** callback function */ _CCallback2 * m_pCallback; /** */ CMutex m_ClientMutex; /** */ time_t m_timeReconnectTimeout; /** */ eReconnectState m_eReconnectState; /** */ int m_nReconnectCount; /** */ int m_nNickListHandler; /** * Apparently the whole client - hub supports negotiation is useless * and we must assume all features we asked for have been enabled. * * This is always set to true on hubs with a lock that starts with * EXTENDEDPROTOCOL and assumes NoGetINFO and NoHello support are enabled. * * Because there is no way to be sure features we did no ask for have * been enabled anyway, there is no point keeping track of what we asked for * and better handle everything anyway. */ bool m_bExtProtocol; /** * This is set to true if we were assigned a valid IP * address by the hub. */ bool m_bGotIP; /** Stream decompress zpipe data as we received it */ CZLib * m_pZLib; /** True if expecting to receive zpipe data */ bool m_bZMode; /** Keep a CMessageHandler around, it saves opening and closing iconv */ CMessageHandler * m_pMessageHandler; }; /** inline functions */ /** */ inline void CClient::SetNick( CString nick ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_sNick != nick ) { m_bUpdateMyinfo = true; m_MyInfo.m_sNick=nick; } m_ClientMutex.UnLock(); } /** */ inline CString CClient::GetNick() const { return m_MyInfo.m_sNick; } /** */ inline void CClient::SetEMail( CString email ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_sEMail != email ) { m_bUpdateMyinfo = true; m_MyInfo.m_sEMail=email; } m_ClientMutex.UnLock(); } /** */ inline CString CClient::GetEMail() const { return m_MyInfo.m_sEMail; } /** */ inline void CClient::SetConnectionType( CString ctype ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_sUserSpeed != ctype ) { m_bUpdateMyinfo = true; m_MyInfo.m_sUserSpeed=ctype; } m_ClientMutex.UnLock(); } /** */ inline CString CClient::GetConnectionType() const { return m_MyInfo.m_sUserSpeed; } /** */ inline void CClient::SetComment( CString comment ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_sComment != comment ) { m_bUpdateMyinfo = true; m_MyInfo.m_sComment=comment; } m_ClientMutex.UnLock(); } /** */ inline CString CClient::GetComment() const { return m_MyInfo.m_sComment; } /** */ inline void CClient::SetShareSize( ulonglong sharesize ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_nShared != sharesize ) { m_bUpdateMyinfo = true; m_MyInfo.m_nShared = sharesize; } m_ClientMutex.UnLock(); } /** */ inline ulonglong CClient::GetShareSize() const { return m_MyInfo.m_nShared; } /** */ inline void CClient::SetMode( eClientMode mode ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_eClientMode != mode ) { m_bUpdateMyinfo = true; m_MyInfo.m_eClientMode=mode; } m_ClientMutex.UnLock(); } /** */ inline eClientMode CClient::GetMode() const { return m_MyInfo.m_eClientMode; } /** */ inline void CClient::SetAwayMode( eUserAwayMode mode ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_eAwayMode != mode ) { m_bUpdateMyinfo = true; m_MyInfo.m_eAwayMode = mode; } m_ClientMutex.UnLock(); } /** */ inline eUserAwayMode CClient::GetAwayMode() const { return m_MyInfo.m_eAwayMode; } /** */ inline void CClient::SetMyInfoTLSFlag( bool b ) { m_ClientMutex.Lock(); if ( m_MyInfo.m_bTLSFlag != b ) { m_bUpdateMyinfo = true; m_MyInfo.m_bTLSFlag = b; } m_ClientMutex.UnLock(); } /** */ inline void CClient::SetHubName( CString hubname ) { m_ClientMutex.Lock(); m_sHubName = hubname; m_ClientMutex.UnLock(); } /** */ inline CString CClient::GetHubName() const { return m_sHubName; } /** */ inline void CClient::SetHubTopic( CString hubtopic ) { m_ClientMutex.Lock(); m_sHubTopic = hubtopic; m_ClientMutex.UnLock(); } /** */ inline CString CClient::GetHubTopic() const { return m_sHubTopic; } inline bool CClient::GetUsedPassword() const { return m_bUsedPassword; } inline void CClient::SetUsedPassword( bool b ) { m_ClientMutex.Lock(); m_bUsedPassword = b; m_ClientMutex.UnLock(); } /** */ inline bool CClient::IsHandshake() const { return m_bHandshake; } /** */ inline void CClient::SetCallBackFunction( _CCallback2 * callback ) { m_ClientMutex.Lock(); delete m_pCallback; m_pCallback = callback; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetHandleUserList( bool b ) { m_ClientMutex.Lock(); m_bHandleUserList = b; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetHandleSearch( bool b ) { m_ClientMutex.Lock(); m_bHandleSearch = b; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetHandleMyinfo( bool b ) { m_ClientMutex.Lock(); m_bHandleMyinfo = b; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetSendMyinfo( bool b ) { m_ClientMutex.Lock(); m_bSendMyinfo = b; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetHandleForceMove( bool b ) { m_ClientMutex.Lock(); m_bHandleForceMove = b; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetHandleTransfer( bool b ) { m_ClientMutex.Lock(); m_bHandleTransfer = b; m_ClientMutex.UnLock(); } /** */ inline void CClient::SetSSLMode( bool b ) { m_ClientMutex.Lock(); m_bSSLMode = b; m_ClientMutex.UnLock(); } /** */ inline bool CClient::GetSupportsUserIP2() const { return m_bGotIP; } /** */ inline bool CClient::GetSupportsNoGetInfo() const { return m_bExtProtocol; } #endif libdc0-0.3.24~svn3121/dclib/dclib-ssl-use.h.in0000644000175000017500000000130111031524417017513 0ustar sikonsikon#ifndef DCLIB_SSL_USE_H #define DCLIB_SSL_USE_H /* * This used to be needed because the dclib compatibility depended * on if it was compiled with SSL or not. That is no longer the case. * However, it appears to be impossible to forward declare OpenSSL * items because they are declared using typedef, so this header * is still needed since dclib does not install it's config.h. */ #define DCLIB_HAS_SSL @HAVE_SSL@ /* * Similarly, if I do things properly, it won't matter which SSL * library dclib was compiled to use. Currently only OpenSSL is supported. * However adding support for GnuTLS or NSS will require changing the * CSSL API. */ #define DCLIB_USES_OPENSSL @USING_OPENSSL@ #endif libdc0-0.3.24~svn3121/dclib/dclib-stl-use.h.in0000644000175000017500000000157011555040725017532 0ustar sikonsikon#ifndef DCLIB_STL_USE_H #define DCLIB_STL_USE_H /* This is required because dclib does not install a copy of it's config.h */ #define DCLIB_USES_UNORDERED_MAP @HAVE_UNORDERED_MAP_H@ #define DCLIB_USES_UNORDERED_SET @HAVE_UNORDERED_SET_H@ #define DCLIB_USES_TR1_UNORDERED_MAP @HAVE_TR1_UNORDERED_MAP_H@ #define DCLIB_USES_TR1_UNORDERED_SET @HAVE_TR1_UNORDERED_SET_H@ /* * The compile may well break due to the CString hash functions, but * using unordered_set with a ulonglong as the key should be fine. */ #define DCLIB_ALLOWS_CSTRING_KEY @ALLOW_CSTRING_KEY@ /* * It is _Fnv_hash with gcc 4.5 * _Fnv_hash<> with gcc 4.3 * Fnv_hash<> with gcc 4.1 * configure tests which one compiles. * Irrelevant if DCLIB_ALLOWS_CSTRING_KEY is 0. */ #define DCLIB_FNV_HASH_IS_PREFIXED @FNV_HASH_PREFIXED@ #define DCLIB_FNV_HASH_IS_TEMPLATE @FNV_HASH_IS_TEMPLATE@ #endif libdc0-0.3.24~svn3121/dclib/csharelist.cpp0000644000175000017500000002633011245175233017152 0ustar sikonsikon/*************************************************************************** csharelist.cpp - description ------------------- begin : Mon May 12 2003 copyright : (C) 2003-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "csharelist.h" #ifndef WIN32 #include #endif #include #include #include "core/che3.h" #include "core/cbz.h" #include "core/cdir.h" #include "core/cxml.h" #include "core/cbytearray.h" #include "cconfig.h" #include "csearchindex.h" // for encoding of non-xml lists which no-one should still be using... #include "core/ciconv.h" // for DC_USER_INDEXLIST #include "dcobject.h" #include "csharetreefolder.h" /** */ CShareList::CShareList() { m_nShareSize = 0; m_pHE3ShareBuffer = 0; m_pBZShareBuffer = 0; m_pXMLBZShareBuffer = 0; m_pRootItem = 0; } /** */ CShareList::~CShareList() { m_MutexShareList.Lock(); delete m_pHE3ShareBuffer; m_pHE3ShareBuffer = 0; delete m_pBZShareBuffer; m_pBZShareBuffer = 0; delete m_pXMLBZShareBuffer; m_pXMLBZShareBuffer = 0; delete m_pRootItem; m_pRootItem = 0; m_MutexShareList.UnLock(); } /** */ bool CShareList::Load() { bool res = false; CString s; CByteArray ba; m_MutexShareList.Lock(); s = CConfig::Instance()->GetConfigPath() + DC_USER_INDEXLIST; if ( CDir().getFileSize(s,false) > 0 ) { if ( ba.LoadFromFile(s) ) { m_sIndexShareBuffer.Set((const char*)ba.Data(),ba.Size()); res = true; } } m_MutexShareList.UnLock(); return res; } /** */ void CShareList::Save() { FILE * out; CString s; m_MutexShareList.Lock(); s = CConfig::Instance()->GetConfigPath() + DC_USER_INDEXLIST; if ( (out = fopen(s.Data(),"wb")) != 0 ) { // fwrite returns the number of elements written, not number of characters if ( fwrite( m_sIndexShareBuffer.Data(), m_sIndexShareBuffer.Length(), 1, out ) != 1 ) { if ( m_sIndexShareBuffer.NotEmpty() ) { printf("CShareList::Save: error writing %s\n",s.Data()); } } fclose(out); } else { printf("[ERROR] open %s\n",s.Data()); } m_MutexShareList.UnLock(); } /** */ void CShareList::SetIndexBuffer( const CString & s ) { m_MutexShareList.Lock(); m_sIndexShareBuffer = s; m_MutexShareList.UnLock(); // save share list Save(); } /** */ void CShareList::CreateList( CSearchIndex * si ) { CString s,s1; long i,j,d; ulonglong sharesize; unsigned long index,oindex; CString res,resnew; struct filebaseobject fbo; int den,deo,dde; CXml xml; m_MutexShareList.Lock(); delete m_pRootItem; m_pRootItem = new CShareTreeFolder( CString('/'), 0 ); CShareTreeFolder * current = m_pRootItem; delete m_pHE3ShareBuffer; m_pHE3ShareBuffer = 0; delete m_pBZShareBuffer; m_pBZShareBuffer = 0; delete m_pXMLBZShareBuffer; m_pXMLBZShareBuffer = 0; resnew = "\n"; resnew += "\n"; sharesize = 0; i = j = 0; CString fi="\xD\xA"; den = 0; deo = -1; dde = 0; oindex = 0; while((i=m_sIndexShareBuffer.Find(fi,j))>0) { s1 = m_sIndexShareBuffer.Mid(j,i-j); d = s1.FindRev('|'); if ( (d != -1) && (s1.Length() > (d+1)) ) { // file index = s1.Mid(d+1,s1.Length()-d-1).asULONG(); if ( index != oindex ) { res.Empty(); resnew.Empty(); sharesize = 0; break; } oindex++; if ( si->GetFileBaseObject(index,&fbo) ) { sharesize += fbo.m_nSize; CString sizestring = CString::number(fbo.m_nSize); res += s1.Left(d); res += '|'; res += sizestring; res += fi; s1 = s1.Left(d).Replace("\x9",""); resnew += "GetHash(fbo.m_nHashIndex); resnew += "\"/>\n"; /* Add file to tree */ current->AddFile( index ); } } else { // path res += s1; res += fi; // 0.3.14 folders added to search index oindex++; // dir end node for(den=0;den= den ) { dde--; deo--; resnew += "\n"; /* Change to parent item */ current = (CShareTreeFolder*) current->GetParent(); } dde++; resnew += "\n"; deo = den; /* Add folder to tree and change to it */ current = current->AddFolder( s1 ); } j = i+2; } if ( resnew.NotEmpty() ) { while(dde) { resnew += "\n"; dde--; } resnew += "\n"; } //printf("%s\n",resnew.Data()); // dclib now uses the operating system encoding if remote encoding is set properly // get local system encoding CIconv iconv( CConfig::Instance()->GetLocalEncoding(), CConfig::Instance()->GetRemoteEncoding() ); res = iconv.encode( res ); CreateBuffer( esbtHE3, res ); CreateBuffer( esbtBZ, res ); CreateBuffer( esbtXMLBZ, resnew ); m_nShareSize = sharesize; m_MutexShareList.UnLock(); /* no longer needed and it is quite large so free it */ m_sIndexShareBuffer.Empty(); } /** */ void CShareList::CreateBuffer( enum eShareBufferType e, const CString & sharebuffer ) { if ( e == esbtHE3 ) { delete m_pHE3ShareBuffer; m_pHE3ShareBuffer = 0; if ( sharebuffer.NotEmpty() ) { // he3 compression CHE3 * he3 = new CHE3(); m_pHE3ShareBuffer = he3->encode_he3_data(&sharebuffer); delete he3; if ( m_pHE3ShareBuffer == 0 ) { printf("[ERROR] he3 compression failed\n"); } } } else if ( e == esbtBZ ) { delete m_pBZShareBuffer; m_pBZShareBuffer = 0; if ( sharebuffer.NotEmpty() ) { // bz compression m_pBZShareBuffer = new CByteArray(); if ( !CBZ::Compress(&sharebuffer,m_pBZShareBuffer) ) { delete m_pBZShareBuffer; m_pBZShareBuffer = 0; printf("[ERROR] bz2 compression failed\n"); } } } else if ( e == esbtXMLBZ ) { delete m_pXMLBZShareBuffer; m_pXMLBZShareBuffer = 0; if ( sharebuffer.NotEmpty() ) { // bz compression m_pXMLBZShareBuffer = new CByteArray(); if ( !CBZ::Compress(&sharebuffer,m_pXMLBZShareBuffer) ) { delete m_pXMLBZShareBuffer; m_pXMLBZShareBuffer = 0; printf("[ERROR] xmlbz2 compression failed\n"); } } } } /** */ int CShareList::GetShareBuffer( eShareBufferType type, CByteArray * sharebuffer, bool decompress ) { int err = 0; m_MutexShareList.Lock(); if( !sharebuffer ) { err = -1; } else { sharebuffer->SetSize(0); switch(type) { case esbtHE3: if ( !m_pHE3ShareBuffer ) err = -1; else if ( decompress ) { CHE3 * he3 = new CHE3(); CString * s = he3->decode_he3_data(m_pHE3ShareBuffer); delete he3; if ( s ) { sharebuffer->Append(s->Data(),s->Length()); delete s; } else err = -1; } else sharebuffer->Append(m_pHE3ShareBuffer->Data(),m_pHE3ShareBuffer->Size()); break; case esbtBZ: if ( !m_pBZShareBuffer ) err = -1; else if ( decompress ) { if ( !CBZ::Decompress( m_pBZShareBuffer, sharebuffer ) ) err = -1; } else sharebuffer->Append(m_pBZShareBuffer->Data(),m_pBZShareBuffer->Size()); break; case esbtXMLBZ: if ( !m_pXMLBZShareBuffer ) err = -1; else if ( decompress ) { if ( !CBZ::Decompress( m_pXMLBZShareBuffer, sharebuffer ) ) err = -1; } else sharebuffer->Append(m_pXMLBZShareBuffer->Data(),m_pXMLBZShareBuffer->Size()); break; case esbtXML: if ( !m_pXMLBZShareBuffer ) err = -1; else { if ( !CBZ::Decompress( m_pXMLBZShareBuffer, sharebuffer ) ) err = -1; } break; default: err = -1; break; } } m_MutexShareList.UnLock(); return err; } /** */ unsigned long CShareList::GetShareBufferSize( eShareBufferType type ) { unsigned long i = 0; m_MutexShareList.Lock(); switch(type) { case esbtHE3: if ( m_pHE3ShareBuffer ) i = m_pHE3ShareBuffer->Size(); break; case esbtBZ: if ( m_pBZShareBuffer ) i = m_pBZShareBuffer->Size(); break; case esbtXMLBZ: if ( m_pXMLBZShareBuffer ) i = m_pXMLBZShareBuffer->Size(); break; case esbtXML: if ( m_pXMLBZShareBuffer ) { CByteArray * ba = new CByteArray(); if ( GetShareBuffer( esbtXML, ba ) > 0 ) { i = ba->Size(); } delete ba; } break; default: break; } m_MutexShareList.UnLock(); return i; } /** */ ulonglong CShareList::GetShareSize() const { return m_nShareSize; } /** */ void CShareList::GetPartialListing( const CString & dir, CString & result, int depth, CSearchIndex * si ) { if ( (dir == "/") && (depth == -1) ) { CByteArray * ba = new CByteArray(); if ( GetShareBuffer( esbtXML, ba ) > 0 ) { result = (const char*) ba->Data(); } delete ba; } else { m_MutexShareList.Lock(); /* All we need to do is find the correct folder item and call GetXML() */ if ( m_pRootItem ) { CShareTreeFolder * current = m_pRootItem; int start = 0; int end = 0; CString key; for ( ; ; ) { start = dir.Find('/',start) + 1; end = dir.Find('/',start); if ( end == -1 ) { break; } else { std::list * list = current->GetChildren(); if ( list ) { key = dir.Mid( start, end - start ); for ( std::list::const_iterator it = list->begin(); it != list->end(); ++it ) { if ( (*it)->GetName() == key ) { current = (*it); delete list; list = 0; break; } } if ( list ) // folder not found! { delete list; current = 0; break; } } else { current = 0; break; } } } if ( current ) { /* XML header and opening FileListing tag */ result = "\n"; result += "\n"; result += current->GetXML( depth, si ); /* Close FileListing tag */ result += "\n"; } } m_MutexShareList.UnLock(); } //printf("GetPartialListing='%s'\n",result.Data()); } libdc0-0.3.24~svn3121/dclib/ccasefolder.cpp0000644000175000017500000001160011141131203017235 0ustar sikonsikon/*************************************************************************** ccasefolder.cpp - Get a case folded version of a string ------------------- begin : Thu Jul 17 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "ccasefolder.h" #ifdef HAVE_CONFIG_H #include #endif #ifndef ICONV_CONST #define ICONV_CONST #endif /* * Using iconv directly to convert to/from local and unicode. * CIconv outputs a CString and that isn't really appropriate. * There is mbstowcs() but it doesn't seem to work. */ #include /* For local encoding */ #include "cconfig.h" /* calloc */ #include /* printf */ #include /* errno */ #include /* int32_t */ #ifdef HAVE_STDINT_H #include #else #define int32_t int #endif #ifdef WORDS_BIGENDIAN #define UCS4_HOST "UCS-4BE" #else #define UCS4_HOST "UCS-4LE" #endif /** */ CCaseFolder::CCaseFolder() { CString localenc; if ( CConfig::Instance() ) { localenc = CConfig::Instance()->GetLocalEncoding(); } else { localenc = "UTF-8"; } to_ucs4 = iconv_open( UCS4_HOST, localenc.Data() ); from_ucs4 = iconv_open( localenc.Data(), UCS4_HOST ); } /** */ CCaseFolder::~CCaseFolder() { if ( to_ucs4 != (iconv_t)-1 ) { iconv_close( to_ucs4 ); } if ( from_ucs4 != (iconv_t)-1 ) { iconv_close( from_ucs4 ); } } /** */ bool CCaseFolder::Fold( const CString & input, CString & output ) { if ( (to_ucs4 == (iconv_t) -1) || (from_ucs4 == (iconv_t) -1) ) { return false; } /* wchar_t was only 2 bytes on Windows, int32_t is always 4 bytes */ const int int32_t_size = sizeof(int32_t); int errors = 0; char * inbuf = input.Data(); size_t inleft = input.Length(); size_t outleft = inleft * int32_t_size + 10; int32_t * unfolded = (int32_t*) calloc( 1, outleft ); if ( !unfolded ) { return false; } char * outbuf = (char*) unfolded; char * outstart = outbuf; size_t res = (size_t) -1; while ( res == (size_t) -1 ) { res = iconv( to_ucs4, (ICONV_CONST char **)&inbuf, &inleft, &outbuf, &outleft ); if ( res == (size_t) -1 ) { if ( errno == EILSEQ ) { outstart[outbuf - outstart] = '_'; inbuf++; inleft--; outbuf++; outleft--; errors++; } else { printf("CCaseFolder::Fold: iconv() to unicode failed %d\n",errno); free(unfolded); return false; } } } /* output length in bytes */ size_t len = (input.Length() * int32_t_size + 10) - outleft; /* output length in wchars */ if ( len%int32_t_size != 0 ) { printf("CCaseFolder::Fold: unexpected output size\n"); free( unfolded ); return false; } size_t wlen = len / int32_t_size; /* greatest change is 1 character to 3 */ size_t foldedlen = len * 3 + 10; int32_t * folded = (int32_t *) calloc( 1, foldedlen ); if ( !folded ) { free(unfolded); return false; } size_t outpos = 0; for ( size_t i = 0; i < wlen; ++i ) { switch ( unfolded[i] ) { #include "ccasefolder-generated-code.cpp" default: folded[outpos] = unfolded[i]; ++outpos; break; } } /* finished with unfolded unicode */ free( unfolded ); inbuf = (char*) folded; inleft = outpos * int32_t_size; outleft = (outpos * int32_t_size) + 10; char * resultdata = (char*) calloc( 1, outleft ); outbuf = resultdata; res = (size_t) -1; while ( res == (size_t) -1 ) { res = iconv( from_ucs4, (ICONV_CONST char**)&inbuf, &inleft, &outbuf, &outleft ); if ( res == (size_t) -1 ) { if ( errno == EILSEQ ) { resultdata[outbuf - resultdata] = '_'; inbuf++; inleft--; outbuf++; outleft--; errors++; } else { printf("CCaseFolder::Fold: iconv() from unicode failed %d\n",errno); free( folded ); free( resultdata ); return false; } } } /* finished with folded unicode */ free( folded ); /* * copy result data to output variable - CString computes whatever the length is, * the data is null terminated */ output = resultdata; /* free memory */ free( resultdata ); if ( errors > 0 ) { printf("CCaseFolder::Fold: total %d EILSEQs encountered\n",errors); } return true; } libdc0-0.3.24~svn3121/dclib/chttp.cpp0000644000175000017500000002536711130730641016135 0ustar sikonsikon/*************************************************************************** chttp.cpp - description ------------------- begin : Mon Jul 29 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "chttp.h" #include #include #include "core/clist.h" #include "core/cmanager.h" #include "dcobject.h" // for encoding of proxy user/pass #include "core/cbase64.h" /** */ CHttp::CHttp() { m_pHttpCallback = 0; m_pCallback = 0; m_eUrlMethod = eumGET; m_pMessageList = new CList(); } /** */ CHttp::~CHttp() { if ( m_pCallback ) { CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; } Disconnect(); delete m_pHttpCallback; m_pHttpCallback = 0; delete m_pMessageList; } /** */ int CHttp::Callback() { Thread(); return 0; } /** */ int CHttp::GetUrl( CString url, CString postdata ) { int i,i1; CString s(url); CString sRealHost; CString sRealPort; //Disconnect(); m_nErrorCode = 0; m_bData = false; m_sHeader.Empty(); m_sLocation.Empty(); m_baData.SetSize(0); if ( s.IsEmpty() ) { return -1; } if ( postdata.IsEmpty() ) { m_eUrlMethod = eumGET; m_sPostData.Empty(); } else { m_eUrlMethod = eumPOST; m_sPostData = postdata; } CString header = s.Mid(0,7); header = header.ToUpper(); if ( header == "HTTP://" ) { s = s.Mid(7,s.Length()-7); } if ( (i = s.Find(':')) >= 0 ) { m_sHost = s.Mid(0,i); } if ( (i1 = s.Find('/')) < 0 ) { printf("CHTTP: no '/' found\n"); return -1; } if ( i >= 0 ) { m_sPort = s.Mid(i+1,i1-i-1); } else { m_sHost = s.Mid(0,i1); m_sPort = "80"; } char *proxy = getenv("http_proxy"); if( proxy ) { unsigned int port; if ( ParseProxy(proxy,m_sProxyUser,m_sProxyPass,m_sProxy,port) ) { m_sProxyPort = CString::number(port); printf("CHTTP: PROXY: '%s':'%s'", m_sProxy.Data(),m_sProxyPort.Data()); if ( (m_sProxyUser.NotEmpty()) || (m_sProxyPass.NotEmpty()) ) { printf(" '%s':'%s' UNTESTED\n", m_sProxyUser.Data(),m_sProxyPass.Data()); } else { printf("\n"); } } else { printf("CHTTP: PROXY parse error\n"); } m_sUrl = url; sRealHost = m_sProxy; sRealPort = m_sProxyPort; } else { /* unset proxy variables */ m_sProxy.Empty(); m_sProxyPort.Empty(); m_sProxyUser.Empty(); m_sProxyPass.Empty(); m_sUrl = s.Mid(i1,s.Length()-i1); sRealHost = m_sHost; sRealPort = m_sPort; } printf("CHTTP: HOST : '%s:%s'\n",m_sHost.Data(),m_sPort.Data()); printf("CHTTP: URL : '%s'\n",m_sUrl.Data()); if ( Connect( sRealHost, sRealPort.asINT() ) == ecsERROR ) { return -1; } if ( !m_pCallback ) { m_pCallback = new CCallback0( this, &CHttp::Callback ); CManager::Instance()->Add( m_pCallback ); } return 0; } /** */ bool CHttp::GetData( CByteArray * ba ) { bool err = false; if ( (m_nErrorCode == 200) && m_bData && (m_eMode == estNONE) ) { if ( (m_nContentLength == -1) || (m_nContentLength == m_baData.Size()) ) { if ( ba ) { ba->SetSize(0); ba->Append( m_baData.Data(), m_baData.Size() ); } err = true; } } return err; } /** */ int CHttp::CallBack_SendObject( CDCMessage * DCMessage ) { int err; if ( m_pHttpCallback ) { err = m_pHttpCallback->notify(DCMessage); } else { err = DC_CallBack( DCMessage ); } if ( err == -1 ) { printf("CHttp: CallBack failed (state)...\n"); delete DCMessage; } return err; } /** */ void CHttp::ConnectionState( eConnectionState state ) { CMessageConnectionState *Object; Object = new CMessageConnectionState(); Object->m_eState = state; Object->m_sMessage = GetSocketError(); if ( state == estCONNECTED ) { m_eMode = estTRANSFERHANDSHAKE; } else if ( state == estDISCONNECTED ) { m_eMode = estNONE; } // callback over notify because connection class is locked m_pMessageList->Add(Object); } /** */ void CHttp::DataAvailable( const char * buffer, int len ) { int i,i1,i2; if ( m_eMode == estTRANSFERDOWNLOAD ) { if ( m_bData == false ) { for(i=0;i 4) && (m_sHeader.Data()[m_sHeader.Length()-4] == 0x0d) && (m_sHeader.Data()[m_sHeader.Length()-3] == 0x0a) && (m_sHeader.Data()[m_sHeader.Length()-2] == 0x0d) && (m_sHeader.Data()[m_sHeader.Length()-1] == 0x0a) ) { //m_sHeader += CString().Set(buffer,i); //i+=4; // parse header ... if ( (i1 = m_sHeader.Find("HTTP/1.0 ")) == -1 ) { if ( (i1 = m_sHeader.Find("HTTP/1.1 ")) == -1 ) { printf("wrong proto '%s'\n",m_sHeader.Data()); Disconnect(); return; } } if ( (i2 = m_sHeader.Find(' ',i1+9)) == -1 ) { printf("wrong proto '%s'\n",m_sHeader.Data()); Disconnect(); } else { m_nErrorCode = m_sHeader.Mid(i1+9,i2-i1-9).asINT(); if ( m_nErrorCode == 200 ) { printf("no error\n"); m_bData = true; } else if ( m_nErrorCode == 302 ) { printf("redirect 302\n"); } else { printf("http error %d\n",m_nErrorCode); Disconnect(); } } m_nContentLength = -1; if ( m_nErrorCode == 200 ) { if ( (i1 = m_sHeader.Find("Content-Length: ")) != -1 ) { if ( (i2 = m_sHeader.Find(0x0d,i1)) != -1 ) { m_nContentLength = m_sHeader.Mid(i1+16,i2-i1-16).asLONG(); } } } else if ( m_nErrorCode == 302 ) { if ( (i1 = m_sHeader.Find("Location: ")) != -1 ) { if ( (i2 = m_sHeader.Find(0x0d,i1)) != -1 ) { m_sLocation = m_sHeader.Mid(i1+10,i2-i1-10); } if ( m_sLocation.IsEmpty() ) { printf("http wrong location\n"); m_nErrorCode = 0; } } } i++; break; } } if ( m_bData && (m_nErrorCode != 0) ) { AppendData( buffer+i,len-i ); } } else { AppendData( buffer, len ); } //printf("DATA: %ld\n",baData.Size()); } } /** */ void CHttp::AppendData( const char * buffer, int len ) { CMessageTransfer * msg = new CMessageTransfer(); if ( m_nContentLength != -1 ) { msg->m_nLength = m_nContentLength; } msg->m_nTransfered = m_baData.Size(); m_pMessageList->Add(msg); m_baData.Append((const unsigned char*)buffer,len); } /** */ void CHttp::DataSend() { CString header; if ( m_eMode == estTRANSFERHANDSHAKE ) { // send request if ( m_eUrlMethod == eumGET ) { header = "GET "; } else { header = "POST "; } header += m_sUrl; header += " HTTP/1.0"; header += "\xd\xa"; header += "User-Agent: DCGUI v"; header += DCLIB_VERSION_STRING; header += "\xd\xa"; header += "Referer: http://"; header += m_sHost; header += ':'; header += m_sPort; header += '/'; header += "\xd\xa"; if ( (m_sProxy.NotEmpty()) && (m_sProxyUser.NotEmpty()) ) { header += "Proxy-Authorization: Basic "; header += CBase64::Encode( m_sProxyUser + ":" + m_sProxyPass ); header += "\xd\xa"; } header += "Host: "; header += m_sHost; header += "\xd\xa"; if ( m_eUrlMethod == eumPOST ) { header += "Content-Type: text/plain"; header += "\xd\xa"; header += "Content-Length: "; header += CString::number(m_sPostData.Length()); header += "\xd\xa"; } header += "\xd\xa"; if ( m_eUrlMethod == eumPOST ) { header += m_sPostData; } if ( Write( (const unsigned char*)header.Data(), header.Length() ) != 0 ) { m_eMode = estNONE; } else { m_eMode = estTRANSFERDOWNLOAD; } } } /** */ void CHttp::DataTimeout() { Disconnect(true); printf("data timeout\n"); } /** */ void CHttp::Notify() { CDCMessage * dcmessage = 0; while ( (dcmessage=m_pMessageList->Next(0)) != 0 ) { m_pMessageList->Remove(dcmessage); CallBack_SendObject(dcmessage); } } /** */ CString CHttp::Encode( CString s ) { CString s1; s1 = s.Replace("&","&"); s1 = s1.Replace(">",">"); s1 = s1.Replace("<","<"); s1 = s1.Replace("\x7f","□"); s1 = s1.Replace("=","="); s1 = s1.Replace(" "," "); return s1; } /** */ CString CHttp::Decode( CString s ) { CString s1; s1 = s.Replace(">",">"); s1 = s1.Replace("<","<"); s1 = s1.Replace("□","\x7f"); s1 = s1.Replace("=","="); s1 = s1.Replace(" "," "); s1 = s1.Replace("&","&"); return s1; } /** http_proxy=http://username:password@host:port/ */ bool CHttp::ParseProxy( char * data, CString & user, CString & pass, CString & host, unsigned int & port ) { if ( data == 0 ) { return false; } int i; CString temp; CString tempuser; CString temppass; CString temphost; unsigned int tempport = 8080; CString datastring(data); datastring = datastring.ToLower(); // check scheme i = datastring.Find("://"); if ( i != -1 ) { temp = datastring.Mid(0,i); if ( temp != "http" ) { printf("CHttp::ParseProxy unsupported scheme '%s'\n", temp.Data()); return false; } datastring = datastring.Mid(i+3); } // check for optional user:password i = datastring.Find('@'); if ( i != -1 ) { tempuser = datastring.Mid(0,i); datastring = datastring.Mid(i+1); int i2 = tempuser.Find(':'); if ( i2 != -1 ) { temppass = tempuser.Mid(i2+1); tempuser = tempuser.Mid(0,i2); } } // remove any path // what is this for, does a path in a proxy address make any sense? i = datastring.Find('/'); if ( i < 0 ) { //printf("CHTTP: no '/' at the end of your proxy found.\n"); //printf("CHTTP: Check your http_proxy environment variable !\n"); //printf("CHTTP: Trying without ...\n"); } else { datastring = datastring.Mid(0,i); } // check for optional port i = datastring.Find(':'); if ( i != -1 ) { temphost = datastring.Mid(0,i); tempport = datastring.Mid(i+1).asUINT(); } else { temphost = datastring; } // sanity check if ( (temphost.IsEmpty()) || (tempport > 65535) || (tempport <= 0) ) { printf("CHttp::ParseProxy validation failed\n"); return false; } else { user = tempuser; pass = temppass; host = temphost; port = tempport; return true; } } libdc0-0.3.24~svn3121/dclib/cdownloadqueue.h0000644000175000017500000001422511123245702017467 0ustar sikonsikon/*************************************************************************** cdownloadqueue.h - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CDOWNLOADQUEUE_H #define CDOWNLOADQUEUE_H /** *@author Mathias Küster * * There is both a queue of file sources (nicks and hubs for files) and * a queue of the files and their segments. * * This class does not do much, and quite often CDownloadManager will * iterate over the CStringLists in this class, they are public. */ #include #include #include #include #include #include #include #include class DCTransferQueueObject; class DCTransferFileObject; class DCFileChunkObject; class CMutex; class CDownloadQueue { public: /** */ CDownloadQueue(); /** */ virtual ~CDownloadQueue(); /** */ CStringList * GetUserHubList( CString nick ); /** */ DCTransferQueueObject * GetUserTransferObject( CString nick, CString hubname, CString hubhost ); /** */ DCTransferFileObject * GetUserFileObject( CString nick, CString hubname, CString hubhost, CString remotename ); /** */ bool DelUserFileObject( CString nick, CString hubname, CString hubhost, CString remotefile ); /** */ bool RemoveChunk( CString localfile ); /** */ bool RenameNick( CString srcnick, CString dstnick, CString srchubname, CString dsthubname ); /** */ DCFileChunkObject * GetFileChunkObject( CString file ); /** mutex for queue */ CMutex * pQueueMutex; /** file queue -> [CStringList] nick -> [CStringList] hubname -> [CTransferObject] (nick,hubname,hubhost,[CStringList(CFileObject)] -> [CStringList] remotefile (for double transfers check this name and filelength) -> [CFileObject] (all the file stuff) */ CStringList > * pQueue; /** mutex for chunks list */ CMutex * pChunksMutex; /** file chunk list -> [CStringList] sLocalFile -> DCFileChunkObject */ CStringList * pChunkList; }; class DCTransferFileObject { public: /** */ DCTransferFileObject(); /** Does a deep copy of a non-null list */ DCTransferFileObject( const DCTransferFileObject & other ); /** */ ~DCTransferFileObject(); /** */ DCTransferFileObject & operator = ( DCTransferFileObject * TransferFileObject ) { copy(TransferFileObject); return *this; }; /** */ CString m_stHash; /** */ CString m_sHash; /** file or buffer or client version */ eltMedium m_eMedium; /** remote file with path */ CString m_sRemoteFile; /** local file with path */ CString m_sLocalFile; /** local path without root path */ CString m_sLocalPath; /** local filename */ CString m_sLocalFileName; /** */ eTransferFileState m_eState; /** file size */ ulonglong m_nSize; /** */ bool m_bMulti; /** */ int m_nPriority; /** * For setting the filelist browser to a file/folder * when downloaded from search. */ CString m_sJumpTo; /** * For downloading folders from search. */ std::list * m_pDirList; private: /** */ void copy( DCTransferFileObject * TransferFileObject ); }; class DCChunkObject; class DCChunkObject { public: /** */ DCChunkObject() { m_nStart = 0; m_nEnd = 0; m_eChunkState = ecsFREE; }; /** */ DCChunkObject( DCChunkObject * ChunkObject ) { m_nStart = ChunkObject->m_nStart; m_nEnd = ChunkObject->m_nEnd; m_eChunkState = ChunkObject->m_eChunkState; }; /** */ ~DCChunkObject() {}; /** */ ulonglong m_nStart; /** */ ulonglong m_nEnd; /** */ eChunkState m_eChunkState; }; class DCFileChunkObject; class DCFileChunkObject { public: /** */ DCFileChunkObject(); /** The normal C++ copy constructor */ DCFileChunkObject( const DCFileChunkObject & other ); /** What dclib is using */ DCFileChunkObject( const DCFileChunkObject * other ); /** */ ~DCFileChunkObject(); /** */ CString m_sLocalFile; /** */ int m_nReferenceCount; /** */ bool m_bMulti; /** */ CString m_stHash; /** */ CString m_sHash; /** file size */ ulonglong m_nSize; /** file size done */ ulonglong m_nSizeDone; /** list of unfinished chunks */ CList m_Chunks; }; class DCTransferQueueObject { public: /** */ DCTransferQueueObject() { tTimeout = 0; iConnections = 0; bReconnect = false; }; /** */ ~DCTransferQueueObject() {}; /** */ CString sNick; /** */ CString sHubName; /** */ CString sHubHost; /** */ time_t tTimeout; /** */ eTransferWaitState eState; /** */ CString sUserFileList; /** */ CStringList pTransferFileList; /** */ CList pHubList; /** */ int iConnections; /** */ bool bReconnect; }; class DCTransferWait { public: /** */ DCTransferWait() { tTimeout = 0; m_nCount = 0; }; /** */ ~DCTransferWait() {}; /** * Returns true if the nick and userhost of this object match * the parameters. * * If one of this object's nick and userhost is empty, then * true is returned if the non-empty one matches the parameter * and the empty one is set to the other parameter. */ bool Match( const CString & nick, const CString & userhost ); /** */ CString sNick; /** */ CString sHubName; /** */ CString sHubHost; /** */ CString sUserHost; /** */ ulonglong m_nCount; /** */ time_t tTimeout; }; #endif libdc0-0.3.24~svn3121/dclib/csearchindex.h0000644000175000017500000002062311101144617017106 0ustar sikonsikon/*************************************************************************** csearchindex.h - description ------------------- begin : Mon May 14 2003 copyright : (C) 2003-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSEARCHINDEX_H #define CSEARCHINDEX_H /** *@author Mathias Küster * * This handles the data about files in the share, and data on all * files ever hashed (which can be cleaned up with /rebuild). * * Before 0.3.19, there was some kind of "keyword index", which was * an extremely unhelpful design first because components of file names * only 1 or 2 characters long were not stored. This meant that 1 or 2 * character components of searches were completely ignored, most * likely somebody wanted a specific episode of something but dclib * returned any 10 episodes. This was partially fixed by filtering * the results using the otherwise ignored components. * * However, the original search indexes also did not include components of * the path with the name, and worse, did not do substring matching. * As in, searching for "chick" will not find files with "chicks" in the name. * * So, the original system would either not return any results, or return a * load of results that didn't match. * * The new system is just a long list of the case folded path+name for each * file in the share. Searching it was moved to CFileManager, mainly because * a CKeywordIndex class briefly existed, which was mostly the old system * but with readable code. * * The share / hash database is implemented using CByteArray and memcmp(), * so is highly prone to error. * * The size of struct filebaseobject and hashbaseobject depends on the CPU * wordsize and possibly also the compiler. The data is probably also * CPU endian dependant. * * Unfortunately the length of the hash leaf data is stored as a ulonglong * at the start of the data pointed to by m_nHashLeavesIndex, it should * have been added to struct hashbaseobject instead. * * The hashes are not stored in any particular order, this would require * a higher level class. */ #include /* eFileTypes */ #include /* CString paramaters everywhere */ #include #include /* time_t */ #include #pragma pack(1) typedef struct filebaseobject { /** */ unsigned int m_eFileType; /** */ ulonglong m_nSize; /** */ unsigned long m_nPathIndex; /** */ unsigned long m_nFileIndex; /** */ unsigned long m_nHashIndex; /** */ time_t m_tModTime; } filebaseobject; typedef struct hashbaseobject { /** */ ulonglong m_nSize; /** */ unsigned long m_nPathIndex; /** */ unsigned long m_nFileIndex; /** */ unsigned long m_nHashIndex; /** */ unsigned long m_nHashLeavesIndex; /** */ time_t m_tModTime; } hashbaseobject; #pragma pack() class CByteArray; class CFileInfo; class CFile; class CSearchIndex { public: /** */ CSearchIndex(); /** */ virtual ~CSearchIndex(); /** */ bool LoadIndex(); /** */ void SaveIndex(); /** */ void PrepareUpdate(); /** */ void FinishUpdate(); /** */ void ResetHashIndex(); /** */ std::set * SearchHash( unsigned char * hash ); /** */ bool GetFileBaseObject( unsigned long index, struct filebaseobject * fbo ); /** */ bool GetFileBaseObjectDuringUpdate( unsigned long index, struct filebaseobject * fbo ); /** */ bool GetFileBaseObject( unsigned long index, struct filebaseobject * fbo, CString & filename ); /** */ bool GetFileBaseObjectDuringUpdate( unsigned long index, struct filebaseobject * fbo, CString & filename ); /** */ bool GetCaseFoldedName( unsigned long index, struct filebaseobject * fbo, CString & name ); /** */ CString GetFileName( unsigned long i ); /** */ CString GetFileNameDuringUpdate( unsigned long i ); /** */ unsigned long AddIndex( CFileInfo *fileinfo, CString path, eFileTypes filetype ); /** Must be added in m_pBaseArray order */ void AddSearchIndex( const CString & name ); /** */ void UpdateIndex( unsigned long index, struct filebaseobject * fbo ); /** */ unsigned long IndexCount(); /** */ unsigned long IndexCountDuringUpdate(); /** */ bool FindHash( unsigned char * hash, unsigned long * hi ); /** */ bool FindHashDuringUpdate( unsigned char * hash, unsigned long * hi ); /** */ CString GetHash( unsigned long hbi ); /** */ bool HashBaseIndexFromHashIndex( unsigned long hi, unsigned long * hbi ); /** */ bool HashBaseIndexFromHashIndexDuringUpdate( unsigned long hi, unsigned long * hbi ); /** */ bool BaseIndexFromHashBaseIndex( unsigned long hbi, unsigned long * bi ); /** */ void AddHashIndex( unsigned long filebaseindex, unsigned char * hash, unsigned char * leaves, unsigned long lsize ); /** */ bool FindHashBaseIndex( struct filebaseobject * fbo, unsigned long * hbi ); /** */ bool FindHashBaseIndexDuringUpdate( struct filebaseobject * fbo, unsigned long * hbi ); /** */ bool Compare( struct filebaseobject * fbo, struct hashbaseobject * hbo ); /** */ bool CompareDuringUpdate( struct filebaseobject * fbo, struct hashbaseobject * hbo ); /** Get the TTH leaves for the given TTH */ CByteArray * GetHashLeaves( CString tth ); /** Appends newly created hash leaf data to hashleaves.bin */ bool SaveNewHashLeaves(); /** * Rebuild the byte arrays, removing data for files not currently shared. * * Returns the number of errors detected (an m_n?????Index was out of range). * Invalid indexes are set to (unsigned long)-1. If errors is non-zero * a filelist refresh is needed. */ long RebuildLists(); /** * Validates all hash leaf data. * If the leaf data does not match the root, the hashbaseobject is * removed from the database. This causes the file to be re-hashed * in the filelist refresh which follows. The data itself is not * removed because that would make various indexes invalid. * * Returns the number of invalid entries removed. If that is > 0 * then the full filelist refresh routine must be started to * re-hash the files. */ long ValidateHashLeaves(); /** Print out some stats */ void PrintDatabaseStats(); /** Returns what LoadIndex() in constructor returned. */ bool LoadedOK() const { return m_bLoadedOK; } ; private: /** * Reads the hash leaves from the file, returning true on success. * The file must be not null and open, dest must not be null. */ bool ReadLeaves( CFile * file, unsigned long hli, CByteArray * dest ); /** */ bool m_bLoadedOK; /** read only */ CByteArray * m_pFileBaseArray; /** read only */ CByteArray * m_pPathBaseArray; /** read only */ CByteArray * m_pBaseArray; /** read only */ CByteArray * m_pHashBaseArray; /** read only */ CByteArray * m_pHashFileBaseArray; /** read only */ CByteArray * m_pHashPathBaseArray; /** read only */ CByteArray * m_pHashIndex; /** * Newly created hash leaf data to append to hashleaves.bin * There is no need to load the whole file into memory. */ CByteArray * m_pNewHashLeaves; /** The size of hashleaves.bin */ ulonglong hashleavessize; /** writeable */ CByteArray * m_pUpdatingFileBaseArray; /** writeable */ CByteArray * m_pUpdatingPathBaseArray; /** writeable */ CByteArray * m_pUpdatingBaseArray; /** writeable */ CByteArray * m_pUpdatingHashBaseArray; /** writeable */ CByteArray * m_pUpdatingHashFileBaseArray; /** writeable */ CByteArray * m_pUpdatingHashPathBaseArray; /** writeable */ CByteArray * m_pUpdatingHashIndex; /** New store of case folded path+name indexes */ CByteArray * m_pCaseFoldedBase; /** New store of case folded path+name strings */ CByteArray * m_pCaseFoldedData; /** */ CByteArray * m_pUpdatingCaseFoldedBase; /** */ CByteArray * m_pUpdatingCaseFoldedData; }; #endif libdc0-0.3.24~svn3121/dclib/ctransfer.cpp0000644000175000017500000011605611233301711016772 0ustar sikonsikon/*************************************************************************** ctransfer.cpp - description ------------------- begin : Fri Feb 22 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "ctransfer.h" #include #include #include #include #ifndef WIN32 #include #include #include #include #else #include #endif #include "dclib.h" #include "dcobject.h" #include "cmessagehandler.h" #include "cencrypt.h" #include "core/cdir.h" #include "core/cbytearray.h" #include "cconfig.h" #include "core/platform.h" #include "cfilemanager.h" #include "dclib-ssl-use.h" #include "core/clogfile.h" /* in 0.3.7 it was just m_bChunk */ #define CHUNKS_SUPPORTED ( m_MessageSupports.m_bADCGet || m_MessageSupports.m_bXMLBZList || m_MessageSupports.m_bChunk || (m_MessageSupports.m_bZBlock && CConfig::Instance()->GetCompressedTransfers()) ) CTransfer::CTransfer( bool listener ) { pCallback = 0; pByteArray = new CByteArray(); m_bListener = listener; eMedium = eltNONE; eSrcDirection = edNONE; eDstDirection = edNONE; eMode = estNONE; m_nStartPosition = 0; m_nEndPosition = 0; m_nSrcLevel = 0; m_nDstLevel = 0; starttime.tv_sec = 0; starttime.tv_usec= 0; m_nFileSize = 0; m_nTransfered = 0; m_nTransferRate = 0; m_nChunkSize = 0; m_nTransferID = 0; m_bIdle = true; m_eTransferState = etsNONE; m_eTransferType = ettNONE; // init transferrate memset(&m_AverageTransferRate,0,sizeof(m_AverageTransferRate)); m_AverageTransferRate.index=0; gettimeofday(&m_AverageTransferRate.tv[0],NULL); m_nReadFileBufferSize = CConfig::Instance()->GetReadFileBufferSize(); m_nZlibStatus = 0; m_bDisableXML = false; } CTransfer::~CTransfer() { SetCallBackFunction(0); TransferMutex.Lock(); delete pByteArray; pByteArray = 0; m_File.Close(); TransferMutex.UnLock(); /* happens whenever not finished transfer is disconnected */ /* if ( m_nZlibStatus == 1 ) // -1 error status will have already been reported elsewhere { DPRINTF("CTransfer::~CTransfer: zlib not finished\n"); } */ } /** */ int CTransfer::CallBack_SendObject( CDCMessage * DCMessage ) { int err; if ( pCallback != 0 ) { err = pCallback->notify( this, DCMessage ); } else { err = DC_CallBack( DCMessage ); } if ( err == -1 ) { DPRINTF("CTransfer: CallBack failed (state)...\n"); delete DCMessage; } return err; } /** */ int CTransfer::CallBack_SendError( CString msg ) { CMessageError * Object = new CMessageError(); Object->m_sError = msg; return CallBack_SendObject(Object); } /** */ void CTransfer::SetBuffer( CByteArray *ba ) { TransferMutex.Lock(); pByteArray->Append(ba->Data(),ba->Size()); TransferMutex.UnLock(); } /** */ void CTransfer::ClearAndAppendBuffer( const unsigned char * data, const unsigned long size ) { TransferMutex.Lock(); pByteArray->SetSize(0); pByteArray->Append( data, size ); TransferMutex.UnLock(); } /** */ long CTransfer::GetBuffer( CByteArray *ba ) { TransferMutex.Lock(); ba->Append(pByteArray->Data(),pByteArray->Size()); long i = pByteArray->Size(); TransferMutex.UnLock(); return i; } /** */ bool CTransfer::SaveBufferToFile( const CString & filename ) { TransferMutex.Lock(); bool res = pByteArray->SaveToFile( filename ); TransferMutex.UnLock(); return res; } /** */ void CTransfer::InitTime() { TransferMutex.Lock(); gettimeofday(&starttime,NULL); TransferMutex.UnLock(); } /** */ ulonglong CTransfer::GetTransferrate() { TransferMutex.Lock(); ulonglong r; if ( (starttime.tv_sec == 0) || m_bIdle ) { r = 0; } else { r = GetTraffic(); } TransferMutex.UnLock(); return r; } /** */ ulonglong CTransfer::GetBytesForTransferrate( ulonglong rate ) { TransferMutex.Lock(); if ( starttime.tv_sec == 0 ) { TransferMutex.UnLock(); return 0; } ulonglong r = GetTraffic(); if ( r < rate ) { r = rate; } else if ( r > rate ) { r = 0; } TransferMutex.UnLock(); return r; } /** */ void CTransfer::AddTraffic( long n ) { int i; ulonglong t1,t2; struct timeval tp; m_nTransfered += n; gettimeofday(&tp,NULL); t1 = ((tp.tv_sec*1000)+(tp.tv_usec/1000)); i = m_AverageTransferRate.index; t2 = ((m_AverageTransferRate.tv[i].tv_sec*1000)+(m_AverageTransferRate.tv[i].tv_usec/1000)); if ( (t1-t2) > 1000 ) { i++; if ( i >= 10 ) { i = 0; } m_AverageTransferRate.index = i; m_AverageTransferRate.tv[i] = tp; m_AverageTransferRate.transfered[i] = 0; } m_AverageTransferRate.transfered[i] += n; } /** */ ulonglong CTransfer::GetTraffic() { int i; struct timeval tp; ulonglong t1,t2; ulonglong n = 0; gettimeofday(&tp,NULL); t1 = ((tp.tv_sec*1000)+(tp.tv_usec/1000)); i = m_AverageTransferRate.index; if ( i == 9 ) i = 0; else { i++; } t2 = ((m_AverageTransferRate.tv[i].tv_sec*1000)+(m_AverageTransferRate.tv[i].tv_usec/1000)); if ( (t2 == 0) && (i > 0) ) { i = 0; } t2 = ((m_AverageTransferRate.tv[i].tv_sec*1000)+(m_AverageTransferRate.tv[i].tv_usec/1000)); if ( t2 != 0 ) { t1 = t1-t2; if ( t1 > 0 ) { for(i=0,t2=0;i<10;i++) { n += m_AverageTransferRate.transfered[i]; } n = (n*1000)/t1; } } else { DPRINTF("time is null\n"); } return n; } /** */ void CTransfer::ConnectionState( eConnectionState state ) { CMessageConnectionState * Object = new CMessageConnectionState(); Object->m_eState = state; Object->m_sMessage = GetSocketError(); if ( state == estCONNECTED ) { eMode = estTRANSFERHANDSHAKE; if ( sNick.NotEmpty() ) { SendMyNick( sNick, sHubHost ); } } else if ( state == estSSLCONNECTED ) { if ( (GetSocketMode() == esmSSLCLIENT) || (GetSocketMode() == esmSSLSERVER) ) { DPRINTF("change to old ssl mode success\n"); CallBack_SendObject(new CMessageKey()); } else if ( (GetSocketMode() == esmFULLSSLCLIENT) || (GetSocketMode() == esmFULLSSLSERVER) ) { DPRINTF("new ssl mode connected\n"); eMode = estTRANSFERHANDSHAKE; if ( sNick.NotEmpty() ) { SendMyNick( sNick, sHubHost ); } } else { DPRINTF("CTransfer::ConnectionState: unknown SSL socket mode %d\n", GetSocketMode()); } } else if ( state == estDISCONNECTED ) { eMode = estNONE; } CallBack_SendObject(Object); } /** */ int CTransfer::StartDownload( CString dstfile, ulonglong startposition, ulonglong endposition, ulonglong size, ulonglong chunksize, CString srcfile, CString adcTTH ) { if ( (srcfile.IsEmpty()) && (eMedium == eltFILE) ) { DPRINTF("ctransfer: wrong mode (empty file) %d\n",eMedium); return -1; } if ( m_bIdle == false ) { DPRINTF("ctransfer: other transfer is running\n"); return -1; } if ( eMode == estTRANSFERUPLOAD ) { DPRINTF("ctransfer: wrong transfer mode\n"); return -1; } /* this never happens anymore, fixed in 0.3.18 */ if (adcTTH.Left(4).ToUpper() == "TTH:") { DPRINTF("CTransfer::StartDownload: Removed TTH: prefix from TTH\n"); adcTTH = adcTTH.Mid(4, adcTTH.Length() - 4); } TransferMutex.Lock(); eMode = estTRANSFERDOWNLOAD; m_nStartPosition = startposition; m_nEndPosition = endposition; m_nFileSize = size; sDstFilename = dstfile; sSrcFilename = srcfile; m_nTransfered = 0; m_nChunkSize = chunksize; m_sTTH = adcTTH; TransferMutex.UnLock(); /** set starttime */ InitTime(); if ( eMedium == eltCLIENTVERSION ) { m_bIdle = true; } else { if ( GetDstFilename() == DC_USER_FILELIST ) { m_nDataType = 0; if ( m_MessageSupports.m_bXMLBZList ) { SetSrcFilename(DC_USER_FILELIST_XMLBZ); if ( m_MessageSupports.m_bADCGet ) { SendADCGet( eAdcFile, CString(), 0, -1, false, sSrcFilename ); } else { SendUGetBlock( sSrcFilename, startposition ); } } else { if ( m_MessageSupports.m_bBZList ) { SetSrcFilename(DC_USER_FILELIST_BZ); } else { SetSrcFilename(DC_USER_FILELIST_HE3); } SendGet( sSrcFilename, startposition+1 ); } } else { // if we don't have a TTH, we cannot do ADCGet // we'll try to fallback to other get commands, even though these may not work with DC++ >= 0.696 if ( m_MessageSupports.m_bADCGet && m_MessageSupports.m_bTTHF && adcTTH.NotEmpty() ) { if ( m_MessageSupports.m_bZLIG && CConfig::Instance()->GetCompressedTransfers() ) { m_nDataType = 1; SendADCGet( eAdcFile, adcTTH, startposition, chunksize, true ); } else { m_nDataType = 0; SendADCGet ( eAdcFile, adcTTH, startposition, chunksize, false ); } } else if ( m_MessageSupports.m_bXMLBZList ) { if ( m_MessageSupports.m_bZBlock && CConfig::Instance()->GetCompressedTransfers() ) { m_nDataType = 1; SendUGetZBlock( sDstFilename, startposition, chunksize ); } else { m_nDataType = 0; SendUGetBlock( sDstFilename, startposition, chunksize ); } } else if ( m_MessageSupports.m_bZBlock && CConfig::Instance()->GetCompressedTransfers() ) { m_nDataType = 1; SendGetZBlock( sDstFilename, startposition, chunksize ); } else if ( m_MessageSupports.m_bChunk ) { m_nDataType = 0; SendGet( sDstFilename, startposition+1, chunksize ); } else { m_nDataType = 0; SendGet( sDstFilename, startposition+1 ); } } } return 0; } /** */ int CTransfer::StartUpload( CString dstfile, ulonglong length, ulonglong pos, ulonglong chunksize, CString srcfile, bool uget, bool adcget, CString adcTTH, bool compress ) { if ( srcfile.IsEmpty() && (eMedium == eltFILE) ) { DPRINTF("CTransfer::StartUpload: source file empty\n"); return -1; } if ( m_bIdle == false ) { DPRINTF("ctransfer: other transfer is running\n"); return -1; } if ( eMode == estTRANSFERDOWNLOAD ) { DPRINTF("ctransfer: wrong transfer mode\n"); return -1; } TransferMutex.Lock(); eMode = estTRANSFERUPLOAD; m_nStartPosition = pos; m_nEndPosition = length; m_nFileSize = length; sDstFilename = dstfile; sSrcFilename = srcfile; m_sTTH = adcTTH; TransferMutex.UnLock(); m_nTransfered = 0; // if chunksize 0 we use the len if ( chunksize == 0 ) m_nChunkSize = length-pos; else m_nChunkSize = chunksize; m_nPendingSendBytes = 0; /** set starttime */ InitTime(); if ( compress ) { m_nDataType = 2; } else { m_nDataType = 0; } if ( adcget ) { if ( GetMedium() == eltTTHL ) { SendADCSnd( eAdcTTHL, adcTTH, pos, m_nChunkSize, compress ); } else if ( GetMedium() == eltLIST ) { SendADCSnd( eAdcList, CString(), pos, m_nChunkSize, compress, dstfile ); } else if ( GetMedium() == eltBUFFER ) { SendADCSnd( eAdcFile, CString(), pos, m_nChunkSize, compress, dstfile ); } else if ( adcTTH.IsEmpty() ) // ADCGet without TTH { SendADCSnd( eAdcFile, CString(), pos, m_nChunkSize, compress, "/" + dstfile ); } else { SendADCSnd( eAdcFile, adcTTH, pos, m_nChunkSize, compress ); } if ( (eMode != estTRANSFERUPLOAD) || (m_bIdle == false) ) { DPRINTF("Warning: not in uploadmode/idle ADCSND [%d/%d]\n",eMode,m_bIdle); } else { DoInitUpload(); } } else if ( uget || compress ) { SendSending(m_nChunkSize); // don't know why this does not work, instead code out has been copied out of HandleMessage() //HandleMessage("$Send|", length); if ( (eMode != estTRANSFERUPLOAD) || (m_bIdle == false) ) { DPRINTF("Warning: not in uploadmode/idle SEND [%d/%d]\n",eMode,m_bIdle); } else { DoInitUpload(); } } else { /* according to DC++ 0.306 it is file size and not chunk size */ SendFileLength(length); } return 0; } /** */ bool CTransfer::DoInitDownload() { CDir dir; bool b = false; if ( eMedium == eltFILE ) { int mode = 0; m_File.Close(); dir.SetPath(CString()); if ( dir.IsFile(sSrcFilename) == false ) { // create file mode |= IO_CREAT; } mode |= IO_RAW | IO_WRITEONLY; if ( m_File.Open( sSrcFilename, mode, MO_IRUSR|MO_IWUSR|MO_IRGRP|MO_IWGRP|MO_IROTH|MO_IWOTH ) == false ) { CallBack_SendError(strerror(errno)); perror("File open"); } else { if ( CConfig::Instance()->GetCreateFile() ) { if ( ((mode & IO_CREAT) == IO_CREAT) && (m_nFileSize > 0) ) { if ( m_File.Seek(m_nFileSize-1,SEEK_SET) ) { if ( m_File.Write("\0",1) == 1 ) { b = true; } } } } else { b = true; } if ( b ) { // seek to the startposition b = m_File.Seek(m_nStartPosition,SEEK_SET); } else { CallBack_SendError(strerror(errno)); perror("File seek"); m_File.Close(); } } } else { pByteArray->SetSize(0); b = true; } return b; } /** */ int CTransfer::HandleMessage( char * c, int ) { int p=0; eDCMessage type; CDCMessage * Object = 0; CMessageHandler MessageHandler; CString s = c; while( (m_bIdle || (eMode == estTRANSFERUPLOAD)) && ((type=MessageHandler.Parse(&s,p,&Object)) != DC_MESSAGE_PARSE_ERROR) ) { // DPRINTF("transfer: handle message: %d\n",type); if ( !Object ) { continue; } switch (type) { case DC_MESSAGE_SENDING: { CMessageSending * msg = (CMessageSending*)Object; if ( eMode != estTRANSFERDOWNLOAD || (m_bIdle == false) ) { DPRINTF("Warning: not in downloadmode/idle SENDING\n"); delete Object; Object = 0; } else { m_nTransfered = 0; // update endposition if ( m_nEndPosition == 0 ) { m_nEndPosition = msg->m_nLength; } // fix chunksize if ( m_nChunkSize != msg->m_nLength ) { m_nChunkSize = msg->m_nLength; } // fixme why was this commented out? if (m_nFileSize == 0) { m_nFileSize = msg->m_nLength; } // start transfer if ( DoInitDownload() ) { m_bIdle = false; } } break; } case DC_MESSAGE_ADCSND: { CMessageADCSnd * msg = (CMessageADCSnd*)Object; if ( eMode != estTRANSFERDOWNLOAD || (m_bIdle == false) ) { DPRINTF("Warning: not in downloadmode/idle ADCSND\n"); delete Object; Object = 0; } else { m_nTransfered = 0; if ( m_nEndPosition == 0 ) { m_nEndPosition = msg->m_nSize; } if ( m_nChunkSize != msg->m_nSize ) { if ( m_nChunkSize == 0 ) { m_nChunkSize = msg->m_nSize; } else { DPRINTF( "Error: wrong length: Requested=%llu Got=%lld\n", m_nChunkSize, msg->m_nSize ); CallBack_SendError("Remote client sent wrong data - incorrect length!"); Disconnect(); delete Object; Object = 0; break; } } if ( m_nStartPosition != msg->m_nPos ) { DPRINTF( "Error: wrong start position: Requested=%llu Got=%llu\n", m_nStartPosition, msg->m_nPos ); CallBack_SendError("Remote client sent wrong data - incorrect start position!"); Disconnect(); delete Object; Object = 0; break; } if (m_nFileSize == 0) { m_nFileSize = msg->m_nSize; } // not sure if this is really necessary if ( msg->m_bZlib ) { m_nDataType = 1; } else { m_nDataType = 0; } if ( DoInitDownload() ) { m_bIdle = false; } } break; } case DC_MESSAGE_FILELENGTH: case DC_MESSAGE_LISTLEN: { CMessageFileLength * msg = (CMessageFileLength*)Object; if ( eMode != estTRANSFERDOWNLOAD || (m_bIdle == false) ) { DPRINTF("Warning: not in downloadmode/idle FILELENGTH/LISTLEN\n"); delete Object; Object = 0; } else { m_nTransfered = 0; // update endposition if ( (m_nEndPosition == m_nFileSize) || (m_nEndPosition == 0) ) { m_nEndPosition = msg->m_nFileLength; } // fix chunksize if ( (m_nChunkSize == m_nFileSize) || (m_nChunkSize == 0) ) { m_nChunkSize = msg->m_nFileLength; } m_nFileSize = msg->m_nFileLength; // start transfer if ( DoInitDownload() ) { m_bIdle = false; SendSend(); } } break; } case DC_MESSAGE_SEND: { if ( (eMode != estTRANSFERUPLOAD) || (m_bIdle == false) ) { DPRINTF("Warning: not in uploadmode/idle SEND [%d/%d]\n",eMode,m_bIdle); delete Object; Object = 0; } else { DoInitUpload(); } break; } case DC_MESSAGE_ERROR: { break; } case DC_MESSAGE_DIRECTION: { CMessageDirection * msg = (CMessageDirection*)Object; if ( eDstDirection != edNONE ) { // remote will change the direction ... hoho ;-) if ( eDstDirection != msg->m_eDirection ) { Disconnect(true); DPRINTF("Warning: remote will change his direction (hack) ...\n"); delete Object; Object = 0; } } else { eDstDirection = msg->m_eDirection; m_nDstLevel = msg->m_nLevel; } break; } case DC_MESSAGE_MYNICK: { CMessageMyNick * msg = (CMessageMyNick*)Object; if ( eMode == estTRANSFERHANDSHAKE ) { sDstNick = msg->m_sNick; #if DCLIB_HAS_SSL == 1 SendSSLInfo(); #endif m_nSrcLevel = rand()%0x7FFF; } else { DPRINTF("Warning: Nick msg from '%s' only allowed in handshake",msg->m_sNick.Data()); delete Object; Object = 0; } break; } case DC_MESSAGE_LOCK: { CString s; CMessageLock * msg = (CMessageLock*)Object; // now we need to check some broken clients and later limit support // 0.68 had minor version 68, not 680! DPRINTF("LOCK %d %d %d\n",msg->m_eClientVersion,msg->m_nVersionMajor,msg->m_nVersionMinor); m_bDisableXML = ((msg->m_eClientVersion == eucvDCPP) && (msg->m_nVersionMajor == 0) && (msg->m_nVersionMinor >= 307) && (msg->m_nVersionMinor <= 403)); if ( eSrcDirection != edNONE ) { // send supports command if ( msg->m_bExtProtocol ) { // slots for small files always enabled std::vector supported; supported.push_back("MiniSlots"); if ( (CFileManager::Instance()->GetShareBufferSize(esbtXMLBZ) > 0) && ((CConfig::Instance()->GetDisableHashList() == false) || (CConfig::Instance()->GetDisableXMLListWithoutTTH() == false)) ) { supported.push_back("XmlBZList"); } // ADCGet needed for compatibility with DC++ >= 0.696 // TTHF needed for ADCGet (ADCGet by filename did exist, but no longer used by current DC++) // TTHL support also needed for compatibility with DC++ // These stay enabled if just the hash list is disabled, because that only applies to the // hashing of new files, files already hashed remain available. if ( (CConfig::Instance()->GetDisableHashList() == false) || (CConfig::Instance()->GetDisableADCGetWithoutTTH() == false) ) { supported.push_back("ADCGet"); supported.push_back("TTHF"); supported.push_back("TTHL"); } if ( CConfig::Instance()->GetCompressedTransfers() ) { supported.push_back("ZLIG"); } if ( CConfig::Instance()->GetEnableObsoleteExt() ) { // chunk, obsolete dclib extension for segmented downloading supported.push_back("CHUNK"); // bzip2 compressed text filelist if ( CFileManager::Instance()->GetShareBufferSize(esbtBZ) > 0 ) { supported.push_back("BZList"); } #if DCLIB_HAS_SSL == 1 /* Do not add old SSL supports if we are already using new full SSL mode */ CDir dir; if ( CConfig::Instance()->GetOldSSLSupport() && (GetSocketMode() == esmSOCKET) && dir.IsFile(CConfig::Instance()->GetTransferCert(),false) && dir.IsFile(CConfig::Instance()->GetTransferKey(),false) ) { supported.push_back("SSL"); } #endif if ( CConfig::Instance()->GetCompressedTransfers() ) { supported.push_back("GetZBlock"); } } /* It's never empty because MiniSlots is always present */ SendSupports( supported, CConfig::Instance()->GetShuffleSupports() ); } SendDirection( eSrcDirection, m_nSrcLevel ); s.Empty(); CEncrypt::Encrypt(msg->m_sData,s); SendKey(s); } else { Disconnect(true); } break; } case DC_MESSAGE_SUPPORTS: { CMessageSupports * msg = (CMessageSupports*)Object; if ( m_bDisableXML ) { // disable xml list for dc++ 0.401 DPRINTF("CTransfer::HandleMessage: Disabled XML filelist support for DC++ 0.307 to 0.403\n"); msg->m_bXMLBZList = false; } m_MessageSupports = *msg; break; } case DC_MESSAGE_KEY: { #if DCLIB_HAS_SSL == 1 // start ssl socket if ( m_MessageSupports.m_bSSL && CConfig::Instance()->GetTransferCert().NotEmpty() && CConfig::Instance()->GetTransferKey().NotEmpty() && CConfig::Instance()->GetOldSSLSupport() && (GetSocketMode() == esmSOCKET) ) { bool b; if ( m_bListener ) b = ChangeSocketMode(esmSSLSERVER, CConfig::Instance()->GetTransferCert(), CConfig::Instance()->GetTransferKey() ); else b = ChangeSocketMode(esmSSLCLIENT, CConfig::Instance()->GetTransferCert(), CConfig::Instance()->GetTransferKey() ); DPRINTF("change to ssl mode %d\n",b); delete Object; Object = 0; } #endif break; } case DC_MESSAGE_MAXEDOUT: { break; } case DC_MESSAGE_CANCEL: { if ( (eMode == estTRANSFERUPLOAD) && (m_bIdle == false) ) { if ( eMedium == eltFILE ) { m_File.Close(); } // free buffer pByteArray->SetSize(0); // stop transfer m_bIdle = true; } else { DPRINTF("Warning: Cancel msg not in uploadmode/idle SEND [%d/%d]\n",eMode,m_bIdle); delete Object; Object = 0; } break; } default: { //DPRINTF("ctransfer: unknown message %d\n",type); } } if (Object) { CallBack_SendObject(Object); } } return p; } /** */ bool CTransfer::GetEncrypted() { bool res = false; #if DCLIB_HAS_SSL == 1 if ( GetSocketMode() == esmSOCKET ) { res = false; } else { res = true; } #endif return res; } /** */ void CTransfer::DataSend() { int l = 0; ulonglong len=0; ulonglong sendbyte; ulonglong freebuf; int lo; if ( (eMode == estTRANSFERUPLOAD) && (m_bIdle == false) ) { for(lo=0;(lo<5) && (!m_bIdle);lo++) { sendbyte = 0; // check send rate if ( m_nTransferRate != 0 ) { sendbyte = GetBytesForTransferrate(m_nTransferRate); if ( sendbyte == 0 ) { break; } } freebuf = m_nReadFileBufferSize; //GetFreeSendBufferSize(); // should we test for zblock also? if ( !CHUNKS_SUPPORTED || (m_nChunkSize == 0) ) { len = m_nFileSize - m_nStartPosition - m_nTransfered; } else { len = m_nChunkSize - m_nTransfered; } if ( eMedium == eltFILE ) { //DPRINTF("%llu %llu %llu %llu\n",len,lStartPosition,lChunkSize,lCurrentPosition); // load data from filehandle and send ... if ( m_nFileBufferPos == m_nFileBufferSize ) { if ( len > m_nReadFileBufferSize ) { len = m_nReadFileBufferSize; } if ( m_nDataType == 2 ) { pByteArray->SetSize(0); m_nFileBufferSize = 0; CByteArray readbuffer; long fileBytesRead = 0; while ( pByteArray->Size() < ((len+1) / 2) ) { bool more = true; int inlen = 0; int outlen = 0; CByteArray temp; if ( m_nTransfered + fileBytesRead >= m_nChunkSize ) { /* * there should not be any more data in zlib * because the output buffers should always be * large enough */ more = false; break; } else { // limit to reading only up to end of this chunk if ( (m_nTransfered + fileBytesRead + len) > m_nChunkSize ) { len = m_nChunkSize - (m_nTransfered + fileBytesRead); //printf("Limiting len to %llu\n", len); } readbuffer.SetSize(len); long read = m_File.Read( (char *)readbuffer.Data(), (long)len ); if ( read == -1 ) { CallBack_SendError(strerror(errno)); perror("CTransfer::DataSend() read error ! "); Disconnect(true); return; } else if ( read == 0 ) { perror("CTransfer::DataSend() no data read ! "); Disconnect(true); return; } else { fileBytesRead += read; if ( m_nTransfered + fileBytesRead >= m_nChunkSize ) { more = false; } temp.SetSize( m_nReadFileBufferSize * 2 ); inlen = read; outlen = temp.Size(); /* * Bad things will happen if the compressed data is over twice the size of * the uncompressed data, fortunately that is very unlikely. */ m_nZlibStatus = m_Deflater.DeflateBlock( (char *)readbuffer.Data(), &inlen, (char *)temp.Data(), &outlen, more ); if ( ((m_nZlibStatus == 1) && more ) || ((m_nZlibStatus == 0) && (more == false)) ) { if ( outlen > 0 ) { pByteArray->Append( temp.Data(), outlen ); m_nFileBufferSize += outlen; } } else { CString reason; if ( m_nZlibStatus == -1 ) { reason = "zlib error"; } else if ( (m_nZlibStatus == 0) && more ) { reason = "had more data, but zlib finished"; } else if ( (m_nZlibStatus == 1) && (more == false) ) { /* * if the compressed data was over twice the size of the uncompressed... */ reason = "no more data, but zlib not finished"; } CallBack_SendError("Zlib compression failed: " + reason); printf("CTransfer::DataSend() deflate failed: %s\n", reason.Data()); Disconnect(true); return; } } } } m_nFileBufferPos = 0; len = m_nFileBufferSize; // must either change sizes or adjust m_nTransfered //SetLength( GetLength() + m_nFileBufferSize - fileBytesRead ); //SetEndPosition( GetEndPosition() + m_nFileBufferSize - fileBytesRead ); //m_nChunkSize = m_nChunkSize + m_nFileBufferSize - fileBytesRead; m_nTransfered = m_nTransfered + fileBytesRead - m_nFileBufferSize; //printf( "Compressed: %ld to %ld\n", fileBytesRead, m_nFileBufferSize ); } else // m_nDataType == 2 { m_nFileBufferSize = m_File.Read( (char *)pByteArray->Data(), (long)len ); if ( m_nFileBufferSize == -1 ) { CallBack_SendError(strerror(errno)); perror("CTransfer::DataSend() read error ! "); Disconnect(true); return; } else if ( m_nFileBufferSize == 0 ) { perror("CTransfer::DataSend() no data read ! "); Disconnect(true); return; } else if ( len > (ulonglong)m_nFileBufferSize ) { perror("CTransfer::DataSend() wrong length calculation ! "); len = m_nFileBufferSize; } m_nFileBufferPos = 0; } // m_nDataType == 2 } // limit to sendbuffer if ( len > (ulonglong)(m_nFileBufferSize-m_nFileBufferPos) ) { len = m_nFileBufferSize-m_nFileBufferPos; } } else if ( (eMedium == eltBUFFER) || (eMedium == eltTTHL) || (eMedium == eltLIST) ) { m_nFileBufferPos = m_nTransfered; } // limit to transferrate if ( sendbyte != 0 ) { if ( len > sendbyte ) { len = sendbyte; } } // limit to free socket sendbuffer if ( len > freebuf ) { len = freebuf; } // fix to pending send bytes if ( m_nPendingSendBytes != 0 ) { len = m_nPendingSendBytes; } // DPRINTF("LEN: %d\n",len); /* For compressed buffer transfers, the entire buffer was compress in DoInitUpload*/ // write data to socket l = Write( pByteArray->Data()+m_nFileBufferPos, (long)len, true ); if ( l > 0 ) { AddTraffic(l); if ( m_nPendingSendBytes != 0 ) { m_nPendingSendBytes -= l; } else { m_nPendingSendBytes = len-l; } if ( eMedium == eltFILE ) { m_nFileBufferPos += l; } // add traffic control CSocket::m_Traffic.AddTraffic(ettDATATX,len); } else if ( l == -1 ) { perror("CTransfer::DataSend() write error ! "); Disconnect(true); return; } else if ( l == 0 ) { if ( m_nPendingSendBytes == 0 ) { m_nPendingSendBytes = len; } break; } if ( (((m_nStartPosition+m_nTransfered) == m_nFileSize) && (m_nZlibStatus == 0)) || ( CHUNKS_SUPPORTED && ((m_nChunkSize == m_nTransfered) && (m_nZlibStatus == 0)) ) ) { DPRINTF("end found\n"); if ( eMedium == eltFILE ) { m_File.Close(); } // free buffer pByteArray->SetSize(0); // stop transfer m_bIdle = true; // write finished upload message into log file if ( CConfig::Instance()->GetLogFile() && CConfig::Instance()->GetLogFinishedUploads() ) { CString logmessage = "Upload: "; logmessage += sDstNick; logmessage += '@'; logmessage += sHubHost; logmessage += ' '; if ( eMedium == eltTTHL ) { logmessage += "TTHL/"; logmessage += m_sTTH; } else { logmessage += sDstFilename; } logmessage += ' '; logmessage += CString::number(m_nStartPosition); logmessage += " -> "; logmessage += CString::number(m_nStartPosition+m_nTransfered); CLogFile::Write(CConfig::Instance()->GetLogFileName(),eltINFO,logmessage); } // stop loop lo = 5; /* CDownloadManager ignores all CMessageTransfer where m_nTransfered != m_nChunkSize. */ /* Also, CDownloadManager ignores all the object members and only looks at the CTransfer. */ CMessageTransfer * cmt = new CMessageTransfer(); cmt->m_eDirection = edUPLOAD; cmt->m_nTransfered = m_nStartPosition+m_nTransfered; cmt->m_nLength = m_nFileSize; CallBack_SendObject(cmt); } } // for } } /** */ void CTransfer::DataTimeout() { if ( (eMode == estTRANSFERDOWNLOAD) && (m_bIdle == false) ) { DPRINTF("CTransfer: download timeout ...\n"); // send string ... SendString("|"); } else if ( eMode == estTRANSFERHANDSHAKE ) { DPRINTF("CTransfer: handshake timeout ...\n"); // handshake timeout Disconnect(true); } else if ( m_bIdle ) { // send string ... SendString("|"); } } /** */ void CTransfer::Notify() { } /** */ void CTransfer::DataAvailable( const char * buffer, int len ) { int i = 0, r, p = 0; while ( i < len ) { if ( (eMode == estTRANSFERDOWNLOAD) && (m_bIdle == false) ) { while ( (i < len) && (!m_bIdle) ) { if ( eMedium == eltFILE ) { r = HandleFileTransfer(buffer+i,len-i); } else if ( (eMedium == eltBUFFER) || (eMedium == eltTTHL) || (eMedium == eltLIST) ) { r = HandleBufferTransfer(buffer+i,len-i); } else { r = -1; } if ( r >= 0 ) { i += r; } else { break; } // add traffic control CSocket::m_Traffic.AddTraffic(ettDATARX,r); // set transfer to idle on finished chunk if remote // support chunks or if fileend reached if ( ((m_nChunkSize == m_nTransfered) && (m_nZlibStatus == 0)) && ( CHUNKS_SUPPORTED || ((m_nStartPosition+m_nChunkSize) == m_nFileSize) ) ) { m_bIdle = true; // send transfer message does NOT go here, moving it here // breaks multi download from original nmdc client microdc 0.11.0 // which is handled by a single $Send| getting multiple chunks } // however, we can put the test m_nChunkSize == m_nTransfered, to // avoid sending transfer messages which will just be ignored if ( m_nChunkSize == m_nTransfered ) { // send transfer message to handle new chunk-end CMessageTransfer * Object = new CMessageTransfer(); Object->m_eDirection = edDOWNLOAD; Object->m_nTransfered = m_nTransfered; Object->m_nLength = m_nFileSize; CallBack_SendObject(Object); // check end - only finish if zlib has finished (m_nZlibStatus is always 0 when not using compressed transfers) // yes we just checked m_nChunkSize == m_nTransfered // but after CallBack_SendObject() m_nTransfered may have been set back to zero if ( (m_nChunkSize == m_nTransfered) && (m_nZlibStatus == 0) ) { // if endposition not filesize and remote don't support chunks we must disconnect if ( ((m_nStartPosition+m_nChunkSize) != m_nFileSize) && !CHUNKS_SUPPORTED ) { Disconnect(); } m_bIdle = true; m_File.Close(); } } } } else { /* * if there is some problem, resulting in trying to * parse file data as NMDC command strings, then the problem * is elsewhere, and determining when the end of the * segment has been reached needs to be fixed */ r = HandleControlTransfer(buffer+i,len-i); // add traffic control CSocket::m_Traffic.AddTraffic(ettCONTROLRX,r); i += r; } if ( i == p ) { DPRINTF("WARNING: unknown data ! [%d %d]\n",i,len); break; } else { p = i; } } } /** */ int CTransfer::HandleFileTransfer( const char * buffer, int len ) { int i,i1; ulonglong l; CString serr; bool berr=false; CByteArray zbuffer; int outlen; int inlen; // decompress buffer ... if ( m_nDataType == 1 ) { zbuffer.SetSize(1024*100); outlen = 1024*100; inlen = len; m_nZlibStatus = m_ZLib.InflateZBlock( buffer, &inlen, (char*)zbuffer.Data(), &outlen ); if ( m_nZlibStatus == -1 ) { DPRINTF("HandleFileTransfer: inflate failed!\n"); // close file m_File.Close(); CallBack_SendError("Zlib decompression failed"); // disconnect on error Disconnect(); return -1; } len = outlen; buffer = (const char*)zbuffer.Data(); } // check endposition if ( (len+m_nTransfered) > m_nChunkSize ) { l = m_nChunkSize-m_nTransfered; } else { l = len; } i1 = 0; // write data if ( (m_File.IsOpen()) && (l > 0) ) { while( i1 != l ) { i = m_File.Write( buffer, l ); if ( i != -1 ) { i1 += i; } else { i1 -= m_File.GetBufferPos(); DPRINTF("CTransfer::HandleFileTransfer: write failed with %d pending bytes\n",m_File.GetBufferPos()); berr = true; serr = strerror(errno); break; } } } else { // TODO: error message } AddTraffic(i1); // handle error if ( berr ) { i1 = -1; // close file m_File.Close(); CallBack_SendError(serr); // disconnect on error Disconnect(); } else { if ( m_nDataType == 1 ) { i1 = inlen; } } return i1; } /** */ int CTransfer::HandleBufferTransfer( const char * buffer, int len ) { int i; CByteArray zbuffer; int outlen; int inlen; // decompress buffer ... if ( m_nDataType == 1 ) { zbuffer.SetSize(1024*100); outlen = 1024*100; inlen = len; m_nZlibStatus = m_ZLib.InflateZBlock( buffer, &inlen, (char*)zbuffer.Data(), &outlen ); if ( m_nZlibStatus == -1 ) { DPRINTF("HandleBufferTransfer: inflate failed!\n"); CallBack_SendError("Zlib decompression failed"); // disconnect on error Disconnect(); return -1; } len = outlen; buffer = (const char*)zbuffer.Data(); } // check endposition if ( (len+m_nTransfered) > m_nChunkSize ) { i = m_nChunkSize-m_nTransfered; } else { i = len; } pByteArray->Append((const unsigned char*)buffer,i); AddTraffic(i); if ( m_nDataType == 1 ) { i = inlen; } return i; } /** */ int CTransfer::HandleControlTransfer( const char * buffer, int len ) { CString s; int i,p = 0; // search first '|' for(i=0;i 0 ) { p = HandleMessage( s.Data(), i ); // some clients send data after filelength (e.g. nmdc 2.02) if ( (p < s.Length()) && (!m_bIdle) && (eMode == estTRANSFERDOWNLOAD) ) { DPRINTF("WARNING: transfer->client send unwanted data ! [%d %d %d]\n",i,p,len); } } if ( (i == s.Length()) || ((!m_bIdle) && (eMode == estTRANSFERDOWNLOAD)) ) { sBuffer.Empty(); } else { sBuffer = s.Mid( i, s.Length()-i ); p = len; } return p; } /** Code copied out of HandleMessage() so it can be called directly from another place */ void CTransfer::DoInitUpload() { m_nTransfered = 0; // init filehandle if ( eMedium == eltFILE ) { m_nFileBufferPos = m_nReadFileBufferSize; m_nFileBufferSize = m_nReadFileBufferSize; m_nPendingSendBytes = 0; pByteArray->SetSize(m_nReadFileBufferSize); m_File.Close(); if ( m_File.Open( sSrcFilename, IO_RAW | IO_READONLY ) == false ) { CallBack_SendError( CString("(File open) ") + strerror(errno) ); perror("File open"); } else { // seek to the startposition if ( m_File.Seek(m_nStartPosition,SEEK_SET) == false ) { CallBack_SendError( CString("(File seek) ") + strerror(errno) ); perror("File seek"); m_File.Close(); } } // check for error if ( !m_File.IsOpen() ) { Disconnect(true); } else { // start transfer m_bIdle = false; } } else { // compress buffer if necessary if ( m_nDataType == 2 ) { m_nFileBufferPos = 0; CByteArray * compressed = new CByteArray(); unsigned long outlen = CDeflater::OneShotDeflate( (const char*)pByteArray->Data(), pByteArray->Size(), compressed ); if ( outlen > 0 ) { //printf("Compressed buffer from %ld to %ld\n", pByteArray->Size(), outlen ); pByteArray->SetSize(0); pByteArray->Append( compressed->Data(), outlen ); // hack SetEndPosition(outlen); SetLength(outlen); m_nChunkSize = outlen; } else { printf("CTransfer::DoInitUpload: Compress buffer failed!\n"); } delete compressed; } // start transfer m_bIdle = false; } if ( dclibVerbose() > 0 ) { if ( eMedium == eltTTHL ) { printf("start upload ... TTHL/%s %lld/%lld\n",m_sTTH.Data(),m_nStartPosition,m_nEndPosition); } else { printf("start upload ...'%s' %lld/%lld\n",sSrcFilename.Data(),m_nStartPosition,m_nChunkSize); } } } /** */ void CTransfer::SendSSLInfo() { if ( GetSocketMode() != esmSOCKET ) { CMessageLog * log1 = new CMessageLog(); log1->sMessage = GetSSLVersion(); log1->sMessage += " connection using "; log1->sMessage += GetSSLCipher(); CallBack_SendObject(log1); #if 0 /* nobody cares and they're all auto generated self signed certs */ CMessageLog * log2 = new CMessageLog(); log2->sMessage = VerifyPeerCertificate(); CallBack_SendObject(log2); #endif } } /** */ bool CTransfer::SupportsChunks() const { return CHUNKS_SUPPORTED; } libdc0-0.3.24~svn3121/dclib/unicode/0000755000175000017500000000000011556467000015730 5ustar sikonsikonlibdc0-0.3.24~svn3121/dclib/unicode/CaseFolding-5.1.0.txt0000644000175000017500000017536111040047151021310 0ustar sikonsikon# CaseFolding-5.1.0.txt # Date: 2008-03-03, 21:57:14 GMT [MD] # # Unicode Character Database # Copyright (c) 1991-2008 Unicode, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # For documentation, see UCD.html # # Case Folding Properties # # This file is a supplement to the UnicodeData file. # It provides a case folding mapping generated from the Unicode Character Database. # If all characters are mapped according to the full mapping below, then # case differences (according to UnicodeData.txt and SpecialCasing.txt) # are eliminated. # # The data supports both implementations that require simple case foldings # (where string lengths don't change), and implementations that allow full case folding # (where string lengths may grow). Note that where they can be supported, the # full case foldings are superior: for example, they allow "MASSE" and "Maße" to match. # # All code points not listed in this file map to themselves. # # NOTE: case folding does not preserve normalization formats! # # For information on case folding, including how to have case folding # preserve normalization formats, see Section 3.13 Default Case Algorithms in # The Unicode Standard, Version 5.0. # # ================================================================================ # Format # ================================================================================ # The entries in this file are in the following machine-readable format: # # ; ; ; # # # The status field is: # C: common case folding, common mappings shared by both simple and full mappings. # F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces. # S: simple case folding, mappings to single characters where different from F. # T: special case for uppercase I and dotted uppercase I # - For non-Turkic languages, this mapping is normally not used. # - For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters. # Note that the Turkic mappings do not maintain canonical equivalence without additional processing. # See the discussions of case mapping in the Unicode Standard for more information. # # Usage: # A. To do a simple case folding, use the mappings with status C + S. # B. To do a full case folding, use the mappings with status C + F. # # The mappings with status T can be used or omitted depending on the desired case-folding # behavior. (The default option is to exclude them.) # # ================================================================= # @missing 0000..10FFFF; 0041; C; 0061; # LATIN CAPITAL LETTER A 0042; C; 0062; # LATIN CAPITAL LETTER B 0043; C; 0063; # LATIN CAPITAL LETTER C 0044; C; 0064; # LATIN CAPITAL LETTER D 0045; C; 0065; # LATIN CAPITAL LETTER E 0046; C; 0066; # LATIN CAPITAL LETTER F 0047; C; 0067; # LATIN CAPITAL LETTER G 0048; C; 0068; # LATIN CAPITAL LETTER H 0049; C; 0069; # LATIN CAPITAL LETTER I 0049; T; 0131; # LATIN CAPITAL LETTER I 004A; C; 006A; # LATIN CAPITAL LETTER J 004B; C; 006B; # LATIN CAPITAL LETTER K 004C; C; 006C; # LATIN CAPITAL LETTER L 004D; C; 006D; # LATIN CAPITAL LETTER M 004E; C; 006E; # LATIN CAPITAL LETTER N 004F; C; 006F; # LATIN CAPITAL LETTER O 0050; C; 0070; # LATIN CAPITAL LETTER P 0051; C; 0071; # LATIN CAPITAL LETTER Q 0052; C; 0072; # LATIN CAPITAL LETTER R 0053; C; 0073; # LATIN CAPITAL LETTER S 0054; C; 0074; # LATIN CAPITAL LETTER T 0055; C; 0075; # LATIN CAPITAL LETTER U 0056; C; 0076; # LATIN CAPITAL LETTER V 0057; C; 0077; # LATIN CAPITAL LETTER W 0058; C; 0078; # LATIN CAPITAL LETTER X 0059; C; 0079; # LATIN CAPITAL LETTER Y 005A; C; 007A; # LATIN CAPITAL LETTER Z 00B5; C; 03BC; # MICRO SIGN 00C0; C; 00E0; # LATIN CAPITAL LETTER A WITH GRAVE 00C1; C; 00E1; # LATIN CAPITAL LETTER A WITH ACUTE 00C2; C; 00E2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX 00C3; C; 00E3; # LATIN CAPITAL LETTER A WITH TILDE 00C4; C; 00E4; # LATIN CAPITAL LETTER A WITH DIAERESIS 00C5; C; 00E5; # LATIN CAPITAL LETTER A WITH RING ABOVE 00C6; C; 00E6; # LATIN CAPITAL LETTER AE 00C7; C; 00E7; # LATIN CAPITAL LETTER C WITH CEDILLA 00C8; C; 00E8; # LATIN CAPITAL LETTER E WITH GRAVE 00C9; C; 00E9; # LATIN CAPITAL LETTER E WITH ACUTE 00CA; C; 00EA; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX 00CB; C; 00EB; # LATIN CAPITAL LETTER E WITH DIAERESIS 00CC; C; 00EC; # LATIN CAPITAL LETTER I WITH GRAVE 00CD; C; 00ED; # LATIN CAPITAL LETTER I WITH ACUTE 00CE; C; 00EE; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX 00CF; C; 00EF; # LATIN CAPITAL LETTER I WITH DIAERESIS 00D0; C; 00F0; # LATIN CAPITAL LETTER ETH 00D1; C; 00F1; # LATIN CAPITAL LETTER N WITH TILDE 00D2; C; 00F2; # LATIN CAPITAL LETTER O WITH GRAVE 00D3; C; 00F3; # LATIN CAPITAL LETTER O WITH ACUTE 00D4; C; 00F4; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX 00D5; C; 00F5; # LATIN CAPITAL LETTER O WITH TILDE 00D6; C; 00F6; # LATIN CAPITAL LETTER O WITH DIAERESIS 00D8; C; 00F8; # LATIN CAPITAL LETTER O WITH STROKE 00D9; C; 00F9; # LATIN CAPITAL LETTER U WITH GRAVE 00DA; C; 00FA; # LATIN CAPITAL LETTER U WITH ACUTE 00DB; C; 00FB; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX 00DC; C; 00FC; # LATIN CAPITAL LETTER U WITH DIAERESIS 00DD; C; 00FD; # LATIN CAPITAL LETTER Y WITH ACUTE 00DE; C; 00FE; # LATIN CAPITAL LETTER THORN 00DF; F; 0073 0073; # LATIN SMALL LETTER SHARP S 0100; C; 0101; # LATIN CAPITAL LETTER A WITH MACRON 0102; C; 0103; # LATIN CAPITAL LETTER A WITH BREVE 0104; C; 0105; # LATIN CAPITAL LETTER A WITH OGONEK 0106; C; 0107; # LATIN CAPITAL LETTER C WITH ACUTE 0108; C; 0109; # LATIN CAPITAL LETTER C WITH CIRCUMFLEX 010A; C; 010B; # LATIN CAPITAL LETTER C WITH DOT ABOVE 010C; C; 010D; # LATIN CAPITAL LETTER C WITH CARON 010E; C; 010F; # LATIN CAPITAL LETTER D WITH CARON 0110; C; 0111; # LATIN CAPITAL LETTER D WITH STROKE 0112; C; 0113; # LATIN CAPITAL LETTER E WITH MACRON 0114; C; 0115; # LATIN CAPITAL LETTER E WITH BREVE 0116; C; 0117; # LATIN CAPITAL LETTER E WITH DOT ABOVE 0118; C; 0119; # LATIN CAPITAL LETTER E WITH OGONEK 011A; C; 011B; # LATIN CAPITAL LETTER E WITH CARON 011C; C; 011D; # LATIN CAPITAL LETTER G WITH CIRCUMFLEX 011E; C; 011F; # LATIN CAPITAL LETTER G WITH BREVE 0120; C; 0121; # LATIN CAPITAL LETTER G WITH DOT ABOVE 0122; C; 0123; # LATIN CAPITAL LETTER G WITH CEDILLA 0124; C; 0125; # LATIN CAPITAL LETTER H WITH CIRCUMFLEX 0126; C; 0127; # LATIN CAPITAL LETTER H WITH STROKE 0128; C; 0129; # LATIN CAPITAL LETTER I WITH TILDE 012A; C; 012B; # LATIN CAPITAL LETTER I WITH MACRON 012C; C; 012D; # LATIN CAPITAL LETTER I WITH BREVE 012E; C; 012F; # LATIN CAPITAL LETTER I WITH OGONEK 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE 0132; C; 0133; # LATIN CAPITAL LIGATURE IJ 0134; C; 0135; # LATIN CAPITAL LETTER J WITH CIRCUMFLEX 0136; C; 0137; # LATIN CAPITAL LETTER K WITH CEDILLA 0139; C; 013A; # LATIN CAPITAL LETTER L WITH ACUTE 013B; C; 013C; # LATIN CAPITAL LETTER L WITH CEDILLA 013D; C; 013E; # LATIN CAPITAL LETTER L WITH CARON 013F; C; 0140; # LATIN CAPITAL LETTER L WITH MIDDLE DOT 0141; C; 0142; # LATIN CAPITAL LETTER L WITH STROKE 0143; C; 0144; # LATIN CAPITAL LETTER N WITH ACUTE 0145; C; 0146; # LATIN CAPITAL LETTER N WITH CEDILLA 0147; C; 0148; # LATIN CAPITAL LETTER N WITH CARON 0149; F; 02BC 006E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE 014A; C; 014B; # LATIN CAPITAL LETTER ENG 014C; C; 014D; # LATIN CAPITAL LETTER O WITH MACRON 014E; C; 014F; # LATIN CAPITAL LETTER O WITH BREVE 0150; C; 0151; # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE 0152; C; 0153; # LATIN CAPITAL LIGATURE OE 0154; C; 0155; # LATIN CAPITAL LETTER R WITH ACUTE 0156; C; 0157; # LATIN CAPITAL LETTER R WITH CEDILLA 0158; C; 0159; # LATIN CAPITAL LETTER R WITH CARON 015A; C; 015B; # LATIN CAPITAL LETTER S WITH ACUTE 015C; C; 015D; # LATIN CAPITAL LETTER S WITH CIRCUMFLEX 015E; C; 015F; # LATIN CAPITAL LETTER S WITH CEDILLA 0160; C; 0161; # LATIN CAPITAL LETTER S WITH CARON 0162; C; 0163; # LATIN CAPITAL LETTER T WITH CEDILLA 0164; C; 0165; # LATIN CAPITAL LETTER T WITH CARON 0166; C; 0167; # LATIN CAPITAL LETTER T WITH STROKE 0168; C; 0169; # LATIN CAPITAL LETTER U WITH TILDE 016A; C; 016B; # LATIN CAPITAL LETTER U WITH MACRON 016C; C; 016D; # LATIN CAPITAL LETTER U WITH BREVE 016E; C; 016F; # LATIN CAPITAL LETTER U WITH RING ABOVE 0170; C; 0171; # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE 0172; C; 0173; # LATIN CAPITAL LETTER U WITH OGONEK 0174; C; 0175; # LATIN CAPITAL LETTER W WITH CIRCUMFLEX 0176; C; 0177; # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX 0178; C; 00FF; # LATIN CAPITAL LETTER Y WITH DIAERESIS 0179; C; 017A; # LATIN CAPITAL LETTER Z WITH ACUTE 017B; C; 017C; # LATIN CAPITAL LETTER Z WITH DOT ABOVE 017D; C; 017E; # LATIN CAPITAL LETTER Z WITH CARON 017F; C; 0073; # LATIN SMALL LETTER LONG S 0181; C; 0253; # LATIN CAPITAL LETTER B WITH HOOK 0182; C; 0183; # LATIN CAPITAL LETTER B WITH TOPBAR 0184; C; 0185; # LATIN CAPITAL LETTER TONE SIX 0186; C; 0254; # LATIN CAPITAL LETTER OPEN O 0187; C; 0188; # LATIN CAPITAL LETTER C WITH HOOK 0189; C; 0256; # LATIN CAPITAL LETTER AFRICAN D 018A; C; 0257; # LATIN CAPITAL LETTER D WITH HOOK 018B; C; 018C; # LATIN CAPITAL LETTER D WITH TOPBAR 018E; C; 01DD; # LATIN CAPITAL LETTER REVERSED E 018F; C; 0259; # LATIN CAPITAL LETTER SCHWA 0190; C; 025B; # LATIN CAPITAL LETTER OPEN E 0191; C; 0192; # LATIN CAPITAL LETTER F WITH HOOK 0193; C; 0260; # LATIN CAPITAL LETTER G WITH HOOK 0194; C; 0263; # LATIN CAPITAL LETTER GAMMA 0196; C; 0269; # LATIN CAPITAL LETTER IOTA 0197; C; 0268; # LATIN CAPITAL LETTER I WITH STROKE 0198; C; 0199; # LATIN CAPITAL LETTER K WITH HOOK 019C; C; 026F; # LATIN CAPITAL LETTER TURNED M 019D; C; 0272; # LATIN CAPITAL LETTER N WITH LEFT HOOK 019F; C; 0275; # LATIN CAPITAL LETTER O WITH MIDDLE TILDE 01A0; C; 01A1; # LATIN CAPITAL LETTER O WITH HORN 01A2; C; 01A3; # LATIN CAPITAL LETTER OI 01A4; C; 01A5; # LATIN CAPITAL LETTER P WITH HOOK 01A6; C; 0280; # LATIN LETTER YR 01A7; C; 01A8; # LATIN CAPITAL LETTER TONE TWO 01A9; C; 0283; # LATIN CAPITAL LETTER ESH 01AC; C; 01AD; # LATIN CAPITAL LETTER T WITH HOOK 01AE; C; 0288; # LATIN CAPITAL LETTER T WITH RETROFLEX HOOK 01AF; C; 01B0; # LATIN CAPITAL LETTER U WITH HORN 01B1; C; 028A; # LATIN CAPITAL LETTER UPSILON 01B2; C; 028B; # LATIN CAPITAL LETTER V WITH HOOK 01B3; C; 01B4; # LATIN CAPITAL LETTER Y WITH HOOK 01B5; C; 01B6; # LATIN CAPITAL LETTER Z WITH STROKE 01B7; C; 0292; # LATIN CAPITAL LETTER EZH 01B8; C; 01B9; # LATIN CAPITAL LETTER EZH REVERSED 01BC; C; 01BD; # LATIN CAPITAL LETTER TONE FIVE 01C4; C; 01C6; # LATIN CAPITAL LETTER DZ WITH CARON 01C5; C; 01C6; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON 01C7; C; 01C9; # LATIN CAPITAL LETTER LJ 01C8; C; 01C9; # LATIN CAPITAL LETTER L WITH SMALL LETTER J 01CA; C; 01CC; # LATIN CAPITAL LETTER NJ 01CB; C; 01CC; # LATIN CAPITAL LETTER N WITH SMALL LETTER J 01CD; C; 01CE; # LATIN CAPITAL LETTER A WITH CARON 01CF; C; 01D0; # LATIN CAPITAL LETTER I WITH CARON 01D1; C; 01D2; # LATIN CAPITAL LETTER O WITH CARON 01D3; C; 01D4; # LATIN CAPITAL LETTER U WITH CARON 01D5; C; 01D6; # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON 01D7; C; 01D8; # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE 01D9; C; 01DA; # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON 01DB; C; 01DC; # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE 01DE; C; 01DF; # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON 01E0; C; 01E1; # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON 01E2; C; 01E3; # LATIN CAPITAL LETTER AE WITH MACRON 01E4; C; 01E5; # LATIN CAPITAL LETTER G WITH STROKE 01E6; C; 01E7; # LATIN CAPITAL LETTER G WITH CARON 01E8; C; 01E9; # LATIN CAPITAL LETTER K WITH CARON 01EA; C; 01EB; # LATIN CAPITAL LETTER O WITH OGONEK 01EC; C; 01ED; # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON 01EE; C; 01EF; # LATIN CAPITAL LETTER EZH WITH CARON 01F0; F; 006A 030C; # LATIN SMALL LETTER J WITH CARON 01F1; C; 01F3; # LATIN CAPITAL LETTER DZ 01F2; C; 01F3; # LATIN CAPITAL LETTER D WITH SMALL LETTER Z 01F4; C; 01F5; # LATIN CAPITAL LETTER G WITH ACUTE 01F6; C; 0195; # LATIN CAPITAL LETTER HWAIR 01F7; C; 01BF; # LATIN CAPITAL LETTER WYNN 01F8; C; 01F9; # LATIN CAPITAL LETTER N WITH GRAVE 01FA; C; 01FB; # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE 01FC; C; 01FD; # LATIN CAPITAL LETTER AE WITH ACUTE 01FE; C; 01FF; # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE 0200; C; 0201; # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE 0202; C; 0203; # LATIN CAPITAL LETTER A WITH INVERTED BREVE 0204; C; 0205; # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE 0206; C; 0207; # LATIN CAPITAL LETTER E WITH INVERTED BREVE 0208; C; 0209; # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE 020A; C; 020B; # LATIN CAPITAL LETTER I WITH INVERTED BREVE 020C; C; 020D; # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE 020E; C; 020F; # LATIN CAPITAL LETTER O WITH INVERTED BREVE 0210; C; 0211; # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE 0212; C; 0213; # LATIN CAPITAL LETTER R WITH INVERTED BREVE 0214; C; 0215; # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE 0216; C; 0217; # LATIN CAPITAL LETTER U WITH INVERTED BREVE 0218; C; 0219; # LATIN CAPITAL LETTER S WITH COMMA BELOW 021A; C; 021B; # LATIN CAPITAL LETTER T WITH COMMA BELOW 021C; C; 021D; # LATIN CAPITAL LETTER YOGH 021E; C; 021F; # LATIN CAPITAL LETTER H WITH CARON 0220; C; 019E; # LATIN CAPITAL LETTER N WITH LONG RIGHT LEG 0222; C; 0223; # LATIN CAPITAL LETTER OU 0224; C; 0225; # LATIN CAPITAL LETTER Z WITH HOOK 0226; C; 0227; # LATIN CAPITAL LETTER A WITH DOT ABOVE 0228; C; 0229; # LATIN CAPITAL LETTER E WITH CEDILLA 022A; C; 022B; # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON 022C; C; 022D; # LATIN CAPITAL LETTER O WITH TILDE AND MACRON 022E; C; 022F; # LATIN CAPITAL LETTER O WITH DOT ABOVE 0230; C; 0231; # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON 0232; C; 0233; # LATIN CAPITAL LETTER Y WITH MACRON 023A; C; 2C65; # LATIN CAPITAL LETTER A WITH STROKE 023B; C; 023C; # LATIN CAPITAL LETTER C WITH STROKE 023D; C; 019A; # LATIN CAPITAL LETTER L WITH BAR 023E; C; 2C66; # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE 0241; C; 0242; # LATIN CAPITAL LETTER GLOTTAL STOP 0243; C; 0180; # LATIN CAPITAL LETTER B WITH STROKE 0244; C; 0289; # LATIN CAPITAL LETTER U BAR 0245; C; 028C; # LATIN CAPITAL LETTER TURNED V 0246; C; 0247; # LATIN CAPITAL LETTER E WITH STROKE 0248; C; 0249; # LATIN CAPITAL LETTER J WITH STROKE 024A; C; 024B; # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL 024C; C; 024D; # LATIN CAPITAL LETTER R WITH STROKE 024E; C; 024F; # LATIN CAPITAL LETTER Y WITH STROKE 0345; C; 03B9; # COMBINING GREEK YPOGEGRAMMENI 0370; C; 0371; # GREEK CAPITAL LETTER HETA 0372; C; 0373; # GREEK CAPITAL LETTER ARCHAIC SAMPI 0376; C; 0377; # GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA 0386; C; 03AC; # GREEK CAPITAL LETTER ALPHA WITH TONOS 0388; C; 03AD; # GREEK CAPITAL LETTER EPSILON WITH TONOS 0389; C; 03AE; # GREEK CAPITAL LETTER ETA WITH TONOS 038A; C; 03AF; # GREEK CAPITAL LETTER IOTA WITH TONOS 038C; C; 03CC; # GREEK CAPITAL LETTER OMICRON WITH TONOS 038E; C; 03CD; # GREEK CAPITAL LETTER UPSILON WITH TONOS 038F; C; 03CE; # GREEK CAPITAL LETTER OMEGA WITH TONOS 0390; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS 0391; C; 03B1; # GREEK CAPITAL LETTER ALPHA 0392; C; 03B2; # GREEK CAPITAL LETTER BETA 0393; C; 03B3; # GREEK CAPITAL LETTER GAMMA 0394; C; 03B4; # GREEK CAPITAL LETTER DELTA 0395; C; 03B5; # GREEK CAPITAL LETTER EPSILON 0396; C; 03B6; # GREEK CAPITAL LETTER ZETA 0397; C; 03B7; # GREEK CAPITAL LETTER ETA 0398; C; 03B8; # GREEK CAPITAL LETTER THETA 0399; C; 03B9; # GREEK CAPITAL LETTER IOTA 039A; C; 03BA; # GREEK CAPITAL LETTER KAPPA 039B; C; 03BB; # GREEK CAPITAL LETTER LAMDA 039C; C; 03BC; # GREEK CAPITAL LETTER MU 039D; C; 03BD; # GREEK CAPITAL LETTER NU 039E; C; 03BE; # GREEK CAPITAL LETTER XI 039F; C; 03BF; # GREEK CAPITAL LETTER OMICRON 03A0; C; 03C0; # GREEK CAPITAL LETTER PI 03A1; C; 03C1; # GREEK CAPITAL LETTER RHO 03A3; C; 03C3; # GREEK CAPITAL LETTER SIGMA 03A4; C; 03C4; # GREEK CAPITAL LETTER TAU 03A5; C; 03C5; # GREEK CAPITAL LETTER UPSILON 03A6; C; 03C6; # GREEK CAPITAL LETTER PHI 03A7; C; 03C7; # GREEK CAPITAL LETTER CHI 03A8; C; 03C8; # GREEK CAPITAL LETTER PSI 03A9; C; 03C9; # GREEK CAPITAL LETTER OMEGA 03AA; C; 03CA; # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA 03AB; C; 03CB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA 03B0; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS 03C2; C; 03C3; # GREEK SMALL LETTER FINAL SIGMA 03CF; C; 03D7; # GREEK CAPITAL KAI SYMBOL 03D0; C; 03B2; # GREEK BETA SYMBOL 03D1; C; 03B8; # GREEK THETA SYMBOL 03D5; C; 03C6; # GREEK PHI SYMBOL 03D6; C; 03C0; # GREEK PI SYMBOL 03D8; C; 03D9; # GREEK LETTER ARCHAIC KOPPA 03DA; C; 03DB; # GREEK LETTER STIGMA 03DC; C; 03DD; # GREEK LETTER DIGAMMA 03DE; C; 03DF; # GREEK LETTER KOPPA 03E0; C; 03E1; # GREEK LETTER SAMPI 03E2; C; 03E3; # COPTIC CAPITAL LETTER SHEI 03E4; C; 03E5; # COPTIC CAPITAL LETTER FEI 03E6; C; 03E7; # COPTIC CAPITAL LETTER KHEI 03E8; C; 03E9; # COPTIC CAPITAL LETTER HORI 03EA; C; 03EB; # COPTIC CAPITAL LETTER GANGIA 03EC; C; 03ED; # COPTIC CAPITAL LETTER SHIMA 03EE; C; 03EF; # COPTIC CAPITAL LETTER DEI 03F0; C; 03BA; # GREEK KAPPA SYMBOL 03F1; C; 03C1; # GREEK RHO SYMBOL 03F4; C; 03B8; # GREEK CAPITAL THETA SYMBOL 03F5; C; 03B5; # GREEK LUNATE EPSILON SYMBOL 03F7; C; 03F8; # GREEK CAPITAL LETTER SHO 03F9; C; 03F2; # GREEK CAPITAL LUNATE SIGMA SYMBOL 03FA; C; 03FB; # GREEK CAPITAL LETTER SAN 03FD; C; 037B; # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL 03FE; C; 037C; # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL 03FF; C; 037D; # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL 0400; C; 0450; # CYRILLIC CAPITAL LETTER IE WITH GRAVE 0401; C; 0451; # CYRILLIC CAPITAL LETTER IO 0402; C; 0452; # CYRILLIC CAPITAL LETTER DJE 0403; C; 0453; # CYRILLIC CAPITAL LETTER GJE 0404; C; 0454; # CYRILLIC CAPITAL LETTER UKRAINIAN IE 0405; C; 0455; # CYRILLIC CAPITAL LETTER DZE 0406; C; 0456; # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I 0407; C; 0457; # CYRILLIC CAPITAL LETTER YI 0408; C; 0458; # CYRILLIC CAPITAL LETTER JE 0409; C; 0459; # CYRILLIC CAPITAL LETTER LJE 040A; C; 045A; # CYRILLIC CAPITAL LETTER NJE 040B; C; 045B; # CYRILLIC CAPITAL LETTER TSHE 040C; C; 045C; # CYRILLIC CAPITAL LETTER KJE 040D; C; 045D; # CYRILLIC CAPITAL LETTER I WITH GRAVE 040E; C; 045E; # CYRILLIC CAPITAL LETTER SHORT U 040F; C; 045F; # CYRILLIC CAPITAL LETTER DZHE 0410; C; 0430; # CYRILLIC CAPITAL LETTER A 0411; C; 0431; # CYRILLIC CAPITAL LETTER BE 0412; C; 0432; # CYRILLIC CAPITAL LETTER VE 0413; C; 0433; # CYRILLIC CAPITAL LETTER GHE 0414; C; 0434; # CYRILLIC CAPITAL LETTER DE 0415; C; 0435; # CYRILLIC CAPITAL LETTER IE 0416; C; 0436; # CYRILLIC CAPITAL LETTER ZHE 0417; C; 0437; # CYRILLIC CAPITAL LETTER ZE 0418; C; 0438; # CYRILLIC CAPITAL LETTER I 0419; C; 0439; # CYRILLIC CAPITAL LETTER SHORT I 041A; C; 043A; # CYRILLIC CAPITAL LETTER KA 041B; C; 043B; # CYRILLIC CAPITAL LETTER EL 041C; C; 043C; # CYRILLIC CAPITAL LETTER EM 041D; C; 043D; # CYRILLIC CAPITAL LETTER EN 041E; C; 043E; # CYRILLIC CAPITAL LETTER O 041F; C; 043F; # CYRILLIC CAPITAL LETTER PE 0420; C; 0440; # CYRILLIC CAPITAL LETTER ER 0421; C; 0441; # CYRILLIC CAPITAL LETTER ES 0422; C; 0442; # CYRILLIC CAPITAL LETTER TE 0423; C; 0443; # CYRILLIC CAPITAL LETTER U 0424; C; 0444; # CYRILLIC CAPITAL LETTER EF 0425; C; 0445; # CYRILLIC CAPITAL LETTER HA 0426; C; 0446; # CYRILLIC CAPITAL LETTER TSE 0427; C; 0447; # CYRILLIC CAPITAL LETTER CHE 0428; C; 0448; # CYRILLIC CAPITAL LETTER SHA 0429; C; 0449; # CYRILLIC CAPITAL LETTER SHCHA 042A; C; 044A; # CYRILLIC CAPITAL LETTER HARD SIGN 042B; C; 044B; # CYRILLIC CAPITAL LETTER YERU 042C; C; 044C; # CYRILLIC CAPITAL LETTER SOFT SIGN 042D; C; 044D; # CYRILLIC CAPITAL LETTER E 042E; C; 044E; # CYRILLIC CAPITAL LETTER YU 042F; C; 044F; # CYRILLIC CAPITAL LETTER YA 0460; C; 0461; # CYRILLIC CAPITAL LETTER OMEGA 0462; C; 0463; # CYRILLIC CAPITAL LETTER YAT 0464; C; 0465; # CYRILLIC CAPITAL LETTER IOTIFIED E 0466; C; 0467; # CYRILLIC CAPITAL LETTER LITTLE YUS 0468; C; 0469; # CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS 046A; C; 046B; # CYRILLIC CAPITAL LETTER BIG YUS 046C; C; 046D; # CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS 046E; C; 046F; # CYRILLIC CAPITAL LETTER KSI 0470; C; 0471; # CYRILLIC CAPITAL LETTER PSI 0472; C; 0473; # CYRILLIC CAPITAL LETTER FITA 0474; C; 0475; # CYRILLIC CAPITAL LETTER IZHITSA 0476; C; 0477; # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT 0478; C; 0479; # CYRILLIC CAPITAL LETTER UK 047A; C; 047B; # CYRILLIC CAPITAL LETTER ROUND OMEGA 047C; C; 047D; # CYRILLIC CAPITAL LETTER OMEGA WITH TITLO 047E; C; 047F; # CYRILLIC CAPITAL LETTER OT 0480; C; 0481; # CYRILLIC CAPITAL LETTER KOPPA 048A; C; 048B; # CYRILLIC CAPITAL LETTER SHORT I WITH TAIL 048C; C; 048D; # CYRILLIC CAPITAL LETTER SEMISOFT SIGN 048E; C; 048F; # CYRILLIC CAPITAL LETTER ER WITH TICK 0490; C; 0491; # CYRILLIC CAPITAL LETTER GHE WITH UPTURN 0492; C; 0493; # CYRILLIC CAPITAL LETTER GHE WITH STROKE 0494; C; 0495; # CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK 0496; C; 0497; # CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER 0498; C; 0499; # CYRILLIC CAPITAL LETTER ZE WITH DESCENDER 049A; C; 049B; # CYRILLIC CAPITAL LETTER KA WITH DESCENDER 049C; C; 049D; # CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE 049E; C; 049F; # CYRILLIC CAPITAL LETTER KA WITH STROKE 04A0; C; 04A1; # CYRILLIC CAPITAL LETTER BASHKIR KA 04A2; C; 04A3; # CYRILLIC CAPITAL LETTER EN WITH DESCENDER 04A4; C; 04A5; # CYRILLIC CAPITAL LIGATURE EN GHE 04A6; C; 04A7; # CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK 04A8; C; 04A9; # CYRILLIC CAPITAL LETTER ABKHASIAN HA 04AA; C; 04AB; # CYRILLIC CAPITAL LETTER ES WITH DESCENDER 04AC; C; 04AD; # CYRILLIC CAPITAL LETTER TE WITH DESCENDER 04AE; C; 04AF; # CYRILLIC CAPITAL LETTER STRAIGHT U 04B0; C; 04B1; # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE 04B2; C; 04B3; # CYRILLIC CAPITAL LETTER HA WITH DESCENDER 04B4; C; 04B5; # CYRILLIC CAPITAL LIGATURE TE TSE 04B6; C; 04B7; # CYRILLIC CAPITAL LETTER CHE WITH DESCENDER 04B8; C; 04B9; # CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE 04BA; C; 04BB; # CYRILLIC CAPITAL LETTER SHHA 04BC; C; 04BD; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE 04BE; C; 04BF; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER 04C0; C; 04CF; # CYRILLIC LETTER PALOCHKA 04C1; C; 04C2; # CYRILLIC CAPITAL LETTER ZHE WITH BREVE 04C3; C; 04C4; # CYRILLIC CAPITAL LETTER KA WITH HOOK 04C5; C; 04C6; # CYRILLIC CAPITAL LETTER EL WITH TAIL 04C7; C; 04C8; # CYRILLIC CAPITAL LETTER EN WITH HOOK 04C9; C; 04CA; # CYRILLIC CAPITAL LETTER EN WITH TAIL 04CB; C; 04CC; # CYRILLIC CAPITAL LETTER KHAKASSIAN CHE 04CD; C; 04CE; # CYRILLIC CAPITAL LETTER EM WITH TAIL 04D0; C; 04D1; # CYRILLIC CAPITAL LETTER A WITH BREVE 04D2; C; 04D3; # CYRILLIC CAPITAL LETTER A WITH DIAERESIS 04D4; C; 04D5; # CYRILLIC CAPITAL LIGATURE A IE 04D6; C; 04D7; # CYRILLIC CAPITAL LETTER IE WITH BREVE 04D8; C; 04D9; # CYRILLIC CAPITAL LETTER SCHWA 04DA; C; 04DB; # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS 04DC; C; 04DD; # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS 04DE; C; 04DF; # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS 04E0; C; 04E1; # CYRILLIC CAPITAL LETTER ABKHASIAN DZE 04E2; C; 04E3; # CYRILLIC CAPITAL LETTER I WITH MACRON 04E4; C; 04E5; # CYRILLIC CAPITAL LETTER I WITH DIAERESIS 04E6; C; 04E7; # CYRILLIC CAPITAL LETTER O WITH DIAERESIS 04E8; C; 04E9; # CYRILLIC CAPITAL LETTER BARRED O 04EA; C; 04EB; # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS 04EC; C; 04ED; # CYRILLIC CAPITAL LETTER E WITH DIAERESIS 04EE; C; 04EF; # CYRILLIC CAPITAL LETTER U WITH MACRON 04F0; C; 04F1; # CYRILLIC CAPITAL LETTER U WITH DIAERESIS 04F2; C; 04F3; # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE 04F4; C; 04F5; # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS 04F6; C; 04F7; # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER 04F8; C; 04F9; # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS 04FA; C; 04FB; # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK 04FC; C; 04FD; # CYRILLIC CAPITAL LETTER HA WITH HOOK 04FE; C; 04FF; # CYRILLIC CAPITAL LETTER HA WITH STROKE 0500; C; 0501; # CYRILLIC CAPITAL LETTER KOMI DE 0502; C; 0503; # CYRILLIC CAPITAL LETTER KOMI DJE 0504; C; 0505; # CYRILLIC CAPITAL LETTER KOMI ZJE 0506; C; 0507; # CYRILLIC CAPITAL LETTER KOMI DZJE 0508; C; 0509; # CYRILLIC CAPITAL LETTER KOMI LJE 050A; C; 050B; # CYRILLIC CAPITAL LETTER KOMI NJE 050C; C; 050D; # CYRILLIC CAPITAL LETTER KOMI SJE 050E; C; 050F; # CYRILLIC CAPITAL LETTER KOMI TJE 0510; C; 0511; # CYRILLIC CAPITAL LETTER REVERSED ZE 0512; C; 0513; # CYRILLIC CAPITAL LETTER EL WITH HOOK 0514; C; 0515; # CYRILLIC CAPITAL LETTER LHA 0516; C; 0517; # CYRILLIC CAPITAL LETTER RHA 0518; C; 0519; # CYRILLIC CAPITAL LETTER YAE 051A; C; 051B; # CYRILLIC CAPITAL LETTER QA 051C; C; 051D; # CYRILLIC CAPITAL LETTER WE 051E; C; 051F; # CYRILLIC CAPITAL LETTER ALEUT KA 0520; C; 0521; # CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK 0522; C; 0523; # CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK 0531; C; 0561; # ARMENIAN CAPITAL LETTER AYB 0532; C; 0562; # ARMENIAN CAPITAL LETTER BEN 0533; C; 0563; # ARMENIAN CAPITAL LETTER GIM 0534; C; 0564; # ARMENIAN CAPITAL LETTER DA 0535; C; 0565; # ARMENIAN CAPITAL LETTER ECH 0536; C; 0566; # ARMENIAN CAPITAL LETTER ZA 0537; C; 0567; # ARMENIAN CAPITAL LETTER EH 0538; C; 0568; # ARMENIAN CAPITAL LETTER ET 0539; C; 0569; # ARMENIAN CAPITAL LETTER TO 053A; C; 056A; # ARMENIAN CAPITAL LETTER ZHE 053B; C; 056B; # ARMENIAN CAPITAL LETTER INI 053C; C; 056C; # ARMENIAN CAPITAL LETTER LIWN 053D; C; 056D; # ARMENIAN CAPITAL LETTER XEH 053E; C; 056E; # ARMENIAN CAPITAL LETTER CA 053F; C; 056F; # ARMENIAN CAPITAL LETTER KEN 0540; C; 0570; # ARMENIAN CAPITAL LETTER HO 0541; C; 0571; # ARMENIAN CAPITAL LETTER JA 0542; C; 0572; # ARMENIAN CAPITAL LETTER GHAD 0543; C; 0573; # ARMENIAN CAPITAL LETTER CHEH 0544; C; 0574; # ARMENIAN CAPITAL LETTER MEN 0545; C; 0575; # ARMENIAN CAPITAL LETTER YI 0546; C; 0576; # ARMENIAN CAPITAL LETTER NOW 0547; C; 0577; # ARMENIAN CAPITAL LETTER SHA 0548; C; 0578; # ARMENIAN CAPITAL LETTER VO 0549; C; 0579; # ARMENIAN CAPITAL LETTER CHA 054A; C; 057A; # ARMENIAN CAPITAL LETTER PEH 054B; C; 057B; # ARMENIAN CAPITAL LETTER JHEH 054C; C; 057C; # ARMENIAN CAPITAL LETTER RA 054D; C; 057D; # ARMENIAN CAPITAL LETTER SEH 054E; C; 057E; # ARMENIAN CAPITAL LETTER VEW 054F; C; 057F; # ARMENIAN CAPITAL LETTER TIWN 0550; C; 0580; # ARMENIAN CAPITAL LETTER REH 0551; C; 0581; # ARMENIAN CAPITAL LETTER CO 0552; C; 0582; # ARMENIAN CAPITAL LETTER YIWN 0553; C; 0583; # ARMENIAN CAPITAL LETTER PIWR 0554; C; 0584; # ARMENIAN CAPITAL LETTER KEH 0555; C; 0585; # ARMENIAN CAPITAL LETTER OH 0556; C; 0586; # ARMENIAN CAPITAL LETTER FEH 0587; F; 0565 0582; # ARMENIAN SMALL LIGATURE ECH YIWN 10A0; C; 2D00; # GEORGIAN CAPITAL LETTER AN 10A1; C; 2D01; # GEORGIAN CAPITAL LETTER BAN 10A2; C; 2D02; # GEORGIAN CAPITAL LETTER GAN 10A3; C; 2D03; # GEORGIAN CAPITAL LETTER DON 10A4; C; 2D04; # GEORGIAN CAPITAL LETTER EN 10A5; C; 2D05; # GEORGIAN CAPITAL LETTER VIN 10A6; C; 2D06; # GEORGIAN CAPITAL LETTER ZEN 10A7; C; 2D07; # GEORGIAN CAPITAL LETTER TAN 10A8; C; 2D08; # GEORGIAN CAPITAL LETTER IN 10A9; C; 2D09; # GEORGIAN CAPITAL LETTER KAN 10AA; C; 2D0A; # GEORGIAN CAPITAL LETTER LAS 10AB; C; 2D0B; # GEORGIAN CAPITAL LETTER MAN 10AC; C; 2D0C; # GEORGIAN CAPITAL LETTER NAR 10AD; C; 2D0D; # GEORGIAN CAPITAL LETTER ON 10AE; C; 2D0E; # GEORGIAN CAPITAL LETTER PAR 10AF; C; 2D0F; # GEORGIAN CAPITAL LETTER ZHAR 10B0; C; 2D10; # GEORGIAN CAPITAL LETTER RAE 10B1; C; 2D11; # GEORGIAN CAPITAL LETTER SAN 10B2; C; 2D12; # GEORGIAN CAPITAL LETTER TAR 10B3; C; 2D13; # GEORGIAN CAPITAL LETTER UN 10B4; C; 2D14; # GEORGIAN CAPITAL LETTER PHAR 10B5; C; 2D15; # GEORGIAN CAPITAL LETTER KHAR 10B6; C; 2D16; # GEORGIAN CAPITAL LETTER GHAN 10B7; C; 2D17; # GEORGIAN CAPITAL LETTER QAR 10B8; C; 2D18; # GEORGIAN CAPITAL LETTER SHIN 10B9; C; 2D19; # GEORGIAN CAPITAL LETTER CHIN 10BA; C; 2D1A; # GEORGIAN CAPITAL LETTER CAN 10BB; C; 2D1B; # GEORGIAN CAPITAL LETTER JIL 10BC; C; 2D1C; # GEORGIAN CAPITAL LETTER CIL 10BD; C; 2D1D; # GEORGIAN CAPITAL LETTER CHAR 10BE; C; 2D1E; # GEORGIAN CAPITAL LETTER XAN 10BF; C; 2D1F; # GEORGIAN CAPITAL LETTER JHAN 10C0; C; 2D20; # GEORGIAN CAPITAL LETTER HAE 10C1; C; 2D21; # GEORGIAN CAPITAL LETTER HE 10C2; C; 2D22; # GEORGIAN CAPITAL LETTER HIE 10C3; C; 2D23; # GEORGIAN CAPITAL LETTER WE 10C4; C; 2D24; # GEORGIAN CAPITAL LETTER HAR 10C5; C; 2D25; # GEORGIAN CAPITAL LETTER HOE 1E00; C; 1E01; # LATIN CAPITAL LETTER A WITH RING BELOW 1E02; C; 1E03; # LATIN CAPITAL LETTER B WITH DOT ABOVE 1E04; C; 1E05; # LATIN CAPITAL LETTER B WITH DOT BELOW 1E06; C; 1E07; # LATIN CAPITAL LETTER B WITH LINE BELOW 1E08; C; 1E09; # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE 1E0A; C; 1E0B; # LATIN CAPITAL LETTER D WITH DOT ABOVE 1E0C; C; 1E0D; # LATIN CAPITAL LETTER D WITH DOT BELOW 1E0E; C; 1E0F; # LATIN CAPITAL LETTER D WITH LINE BELOW 1E10; C; 1E11; # LATIN CAPITAL LETTER D WITH CEDILLA 1E12; C; 1E13; # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW 1E14; C; 1E15; # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE 1E16; C; 1E17; # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE 1E18; C; 1E19; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW 1E1A; C; 1E1B; # LATIN CAPITAL LETTER E WITH TILDE BELOW 1E1C; C; 1E1D; # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE 1E1E; C; 1E1F; # LATIN CAPITAL LETTER F WITH DOT ABOVE 1E20; C; 1E21; # LATIN CAPITAL LETTER G WITH MACRON 1E22; C; 1E23; # LATIN CAPITAL LETTER H WITH DOT ABOVE 1E24; C; 1E25; # LATIN CAPITAL LETTER H WITH DOT BELOW 1E26; C; 1E27; # LATIN CAPITAL LETTER H WITH DIAERESIS 1E28; C; 1E29; # LATIN CAPITAL LETTER H WITH CEDILLA 1E2A; C; 1E2B; # LATIN CAPITAL LETTER H WITH BREVE BELOW 1E2C; C; 1E2D; # LATIN CAPITAL LETTER I WITH TILDE BELOW 1E2E; C; 1E2F; # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE 1E30; C; 1E31; # LATIN CAPITAL LETTER K WITH ACUTE 1E32; C; 1E33; # LATIN CAPITAL LETTER K WITH DOT BELOW 1E34; C; 1E35; # LATIN CAPITAL LETTER K WITH LINE BELOW 1E36; C; 1E37; # LATIN CAPITAL LETTER L WITH DOT BELOW 1E38; C; 1E39; # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON 1E3A; C; 1E3B; # LATIN CAPITAL LETTER L WITH LINE BELOW 1E3C; C; 1E3D; # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW 1E3E; C; 1E3F; # LATIN CAPITAL LETTER M WITH ACUTE 1E40; C; 1E41; # LATIN CAPITAL LETTER M WITH DOT ABOVE 1E42; C; 1E43; # LATIN CAPITAL LETTER M WITH DOT BELOW 1E44; C; 1E45; # LATIN CAPITAL LETTER N WITH DOT ABOVE 1E46; C; 1E47; # LATIN CAPITAL LETTER N WITH DOT BELOW 1E48; C; 1E49; # LATIN CAPITAL LETTER N WITH LINE BELOW 1E4A; C; 1E4B; # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW 1E4C; C; 1E4D; # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE 1E4E; C; 1E4F; # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS 1E50; C; 1E51; # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE 1E52; C; 1E53; # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE 1E54; C; 1E55; # LATIN CAPITAL LETTER P WITH ACUTE 1E56; C; 1E57; # LATIN CAPITAL LETTER P WITH DOT ABOVE 1E58; C; 1E59; # LATIN CAPITAL LETTER R WITH DOT ABOVE 1E5A; C; 1E5B; # LATIN CAPITAL LETTER R WITH DOT BELOW 1E5C; C; 1E5D; # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON 1E5E; C; 1E5F; # LATIN CAPITAL LETTER R WITH LINE BELOW 1E60; C; 1E61; # LATIN CAPITAL LETTER S WITH DOT ABOVE 1E62; C; 1E63; # LATIN CAPITAL LETTER S WITH DOT BELOW 1E64; C; 1E65; # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE 1E66; C; 1E67; # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE 1E68; C; 1E69; # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE 1E6A; C; 1E6B; # LATIN CAPITAL LETTER T WITH DOT ABOVE 1E6C; C; 1E6D; # LATIN CAPITAL LETTER T WITH DOT BELOW 1E6E; C; 1E6F; # LATIN CAPITAL LETTER T WITH LINE BELOW 1E70; C; 1E71; # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW 1E72; C; 1E73; # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW 1E74; C; 1E75; # LATIN CAPITAL LETTER U WITH TILDE BELOW 1E76; C; 1E77; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW 1E78; C; 1E79; # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE 1E7A; C; 1E7B; # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS 1E7C; C; 1E7D; # LATIN CAPITAL LETTER V WITH TILDE 1E7E; C; 1E7F; # LATIN CAPITAL LETTER V WITH DOT BELOW 1E80; C; 1E81; # LATIN CAPITAL LETTER W WITH GRAVE 1E82; C; 1E83; # LATIN CAPITAL LETTER W WITH ACUTE 1E84; C; 1E85; # LATIN CAPITAL LETTER W WITH DIAERESIS 1E86; C; 1E87; # LATIN CAPITAL LETTER W WITH DOT ABOVE 1E88; C; 1E89; # LATIN CAPITAL LETTER W WITH DOT BELOW 1E8A; C; 1E8B; # LATIN CAPITAL LETTER X WITH DOT ABOVE 1E8C; C; 1E8D; # LATIN CAPITAL LETTER X WITH DIAERESIS 1E8E; C; 1E8F; # LATIN CAPITAL LETTER Y WITH DOT ABOVE 1E90; C; 1E91; # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX 1E92; C; 1E93; # LATIN CAPITAL LETTER Z WITH DOT BELOW 1E94; C; 1E95; # LATIN CAPITAL LETTER Z WITH LINE BELOW 1E96; F; 0068 0331; # LATIN SMALL LETTER H WITH LINE BELOW 1E97; F; 0074 0308; # LATIN SMALL LETTER T WITH DIAERESIS 1E98; F; 0077 030A; # LATIN SMALL LETTER W WITH RING ABOVE 1E99; F; 0079 030A; # LATIN SMALL LETTER Y WITH RING ABOVE 1E9A; F; 0061 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING 1E9B; C; 1E61; # LATIN SMALL LETTER LONG S WITH DOT ABOVE 1E9E; F; 0073 0073; # LATIN CAPITAL LETTER SHARP S 1E9E; S; 00DF; # LATIN CAPITAL LETTER SHARP S 1EA0; C; 1EA1; # LATIN CAPITAL LETTER A WITH DOT BELOW 1EA2; C; 1EA3; # LATIN CAPITAL LETTER A WITH HOOK ABOVE 1EA4; C; 1EA5; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE 1EA6; C; 1EA7; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE 1EA8; C; 1EA9; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE 1EAA; C; 1EAB; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE 1EAC; C; 1EAD; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW 1EAE; C; 1EAF; # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE 1EB0; C; 1EB1; # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE 1EB2; C; 1EB3; # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE 1EB4; C; 1EB5; # LATIN CAPITAL LETTER A WITH BREVE AND TILDE 1EB6; C; 1EB7; # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW 1EB8; C; 1EB9; # LATIN CAPITAL LETTER E WITH DOT BELOW 1EBA; C; 1EBB; # LATIN CAPITAL LETTER E WITH HOOK ABOVE 1EBC; C; 1EBD; # LATIN CAPITAL LETTER E WITH TILDE 1EBE; C; 1EBF; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE 1EC0; C; 1EC1; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE 1EC2; C; 1EC3; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE 1EC4; C; 1EC5; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE 1EC6; C; 1EC7; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW 1EC8; C; 1EC9; # LATIN CAPITAL LETTER I WITH HOOK ABOVE 1ECA; C; 1ECB; # LATIN CAPITAL LETTER I WITH DOT BELOW 1ECC; C; 1ECD; # LATIN CAPITAL LETTER O WITH DOT BELOW 1ECE; C; 1ECF; # LATIN CAPITAL LETTER O WITH HOOK ABOVE 1ED0; C; 1ED1; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE 1ED2; C; 1ED3; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE 1ED4; C; 1ED5; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE 1ED6; C; 1ED7; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE 1ED8; C; 1ED9; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW 1EDA; C; 1EDB; # LATIN CAPITAL LETTER O WITH HORN AND ACUTE 1EDC; C; 1EDD; # LATIN CAPITAL LETTER O WITH HORN AND GRAVE 1EDE; C; 1EDF; # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE 1EE0; C; 1EE1; # LATIN CAPITAL LETTER O WITH HORN AND TILDE 1EE2; C; 1EE3; # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW 1EE4; C; 1EE5; # LATIN CAPITAL LETTER U WITH DOT BELOW 1EE6; C; 1EE7; # LATIN CAPITAL LETTER U WITH HOOK ABOVE 1EE8; C; 1EE9; # LATIN CAPITAL LETTER U WITH HORN AND ACUTE 1EEA; C; 1EEB; # LATIN CAPITAL LETTER U WITH HORN AND GRAVE 1EEC; C; 1EED; # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE 1EEE; C; 1EEF; # LATIN CAPITAL LETTER U WITH HORN AND TILDE 1EF0; C; 1EF1; # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW 1EF2; C; 1EF3; # LATIN CAPITAL LETTER Y WITH GRAVE 1EF4; C; 1EF5; # LATIN CAPITAL LETTER Y WITH DOT BELOW 1EF6; C; 1EF7; # LATIN CAPITAL LETTER Y WITH HOOK ABOVE 1EF8; C; 1EF9; # LATIN CAPITAL LETTER Y WITH TILDE 1EFA; C; 1EFB; # LATIN CAPITAL LETTER MIDDLE-WELSH LL 1EFC; C; 1EFD; # LATIN CAPITAL LETTER MIDDLE-WELSH V 1EFE; C; 1EFF; # LATIN CAPITAL LETTER Y WITH LOOP 1F08; C; 1F00; # GREEK CAPITAL LETTER ALPHA WITH PSILI 1F09; C; 1F01; # GREEK CAPITAL LETTER ALPHA WITH DASIA 1F0A; C; 1F02; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA 1F0B; C; 1F03; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA 1F0C; C; 1F04; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA 1F0D; C; 1F05; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA 1F0E; C; 1F06; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI 1F0F; C; 1F07; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI 1F18; C; 1F10; # GREEK CAPITAL LETTER EPSILON WITH PSILI 1F19; C; 1F11; # GREEK CAPITAL LETTER EPSILON WITH DASIA 1F1A; C; 1F12; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA 1F1B; C; 1F13; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA 1F1C; C; 1F14; # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA 1F1D; C; 1F15; # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA 1F28; C; 1F20; # GREEK CAPITAL LETTER ETA WITH PSILI 1F29; C; 1F21; # GREEK CAPITAL LETTER ETA WITH DASIA 1F2A; C; 1F22; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA 1F2B; C; 1F23; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA 1F2C; C; 1F24; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA 1F2D; C; 1F25; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA 1F2E; C; 1F26; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI 1F2F; C; 1F27; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI 1F38; C; 1F30; # GREEK CAPITAL LETTER IOTA WITH PSILI 1F39; C; 1F31; # GREEK CAPITAL LETTER IOTA WITH DASIA 1F3A; C; 1F32; # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA 1F3B; C; 1F33; # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA 1F3C; C; 1F34; # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA 1F3D; C; 1F35; # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA 1F3E; C; 1F36; # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI 1F3F; C; 1F37; # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI 1F48; C; 1F40; # GREEK CAPITAL LETTER OMICRON WITH PSILI 1F49; C; 1F41; # GREEK CAPITAL LETTER OMICRON WITH DASIA 1F4A; C; 1F42; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA 1F4B; C; 1F43; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA 1F4C; C; 1F44; # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA 1F4D; C; 1F45; # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA 1F50; F; 03C5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI 1F52; F; 03C5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA 1F54; F; 03C5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA 1F56; F; 03C5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI 1F59; C; 1F51; # GREEK CAPITAL LETTER UPSILON WITH DASIA 1F5B; C; 1F53; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA 1F5D; C; 1F55; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA 1F5F; C; 1F57; # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI 1F68; C; 1F60; # GREEK CAPITAL LETTER OMEGA WITH PSILI 1F69; C; 1F61; # GREEK CAPITAL LETTER OMEGA WITH DASIA 1F6A; C; 1F62; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA 1F6B; C; 1F63; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA 1F6C; C; 1F64; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA 1F6D; C; 1F65; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA 1F6E; C; 1F66; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI 1F6F; C; 1F67; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI 1F80; F; 1F00 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI 1F81; F; 1F01 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI 1F82; F; 1F02 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI 1F83; F; 1F03 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI 1F84; F; 1F04 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI 1F85; F; 1F05 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI 1F86; F; 1F06 03B9; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI 1F87; F; 1F07 03B9; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI 1F88; F; 1F00 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI 1F88; S; 1F80; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI 1F89; F; 1F01 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI 1F89; S; 1F81; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI 1F8A; F; 1F02 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1F8A; S; 1F82; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1F8B; F; 1F03 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1F8B; S; 1F83; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1F8C; F; 1F04 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1F8C; S; 1F84; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1F8D; F; 1F05 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1F8D; S; 1F85; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1F8E; F; 1F06 03B9; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1F8E; S; 1F86; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1F8F; F; 1F07 03B9; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1F8F; S; 1F87; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1F90; F; 1F20 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI 1F91; F; 1F21 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI 1F92; F; 1F22 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI 1F93; F; 1F23 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI 1F94; F; 1F24 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI 1F95; F; 1F25 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI 1F96; F; 1F26 03B9; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI 1F97; F; 1F27 03B9; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI 1F98; F; 1F20 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI 1F98; S; 1F90; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI 1F99; F; 1F21 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI 1F99; S; 1F91; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI 1F9A; F; 1F22 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1F9A; S; 1F92; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1F9B; F; 1F23 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1F9B; S; 1F93; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1F9C; F; 1F24 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1F9C; S; 1F94; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1F9D; F; 1F25 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1F9D; S; 1F95; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1F9E; F; 1F26 03B9; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1F9E; S; 1F96; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1F9F; F; 1F27 03B9; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1F9F; S; 1F97; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1FA0; F; 1F60 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI 1FA1; F; 1F61 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI 1FA2; F; 1F62 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI 1FA3; F; 1F63 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI 1FA4; F; 1F64 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI 1FA5; F; 1F65 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI 1FA6; F; 1F66 03B9; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI 1FA7; F; 1F67 03B9; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI 1FA8; F; 1F60 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI 1FA8; S; 1FA0; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI 1FA9; F; 1F61 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI 1FA9; S; 1FA1; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI 1FAA; F; 1F62 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1FAA; S; 1FA2; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI 1FAB; F; 1F63 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1FAB; S; 1FA3; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI 1FAC; F; 1F64 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1FAC; S; 1FA4; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI 1FAD; F; 1F65 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1FAD; S; 1FA5; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI 1FAE; F; 1F66 03B9; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1FAE; S; 1FA6; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI 1FAF; F; 1F67 03B9; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1FAF; S; 1FA7; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI 1FB2; F; 1F70 03B9; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI 1FB3; F; 03B1 03B9; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI 1FB4; F; 03AC 03B9; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI 1FB6; F; 03B1 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI 1FB7; F; 03B1 0342 03B9; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI 1FB8; C; 1FB0; # GREEK CAPITAL LETTER ALPHA WITH VRACHY 1FB9; C; 1FB1; # GREEK CAPITAL LETTER ALPHA WITH MACRON 1FBA; C; 1F70; # GREEK CAPITAL LETTER ALPHA WITH VARIA 1FBB; C; 1F71; # GREEK CAPITAL LETTER ALPHA WITH OXIA 1FBC; F; 03B1 03B9; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI 1FBC; S; 1FB3; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI 1FBE; C; 03B9; # GREEK PROSGEGRAMMENI 1FC2; F; 1F74 03B9; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI 1FC3; F; 03B7 03B9; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI 1FC4; F; 03AE 03B9; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI 1FC6; F; 03B7 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI 1FC7; F; 03B7 0342 03B9; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI 1FC8; C; 1F72; # GREEK CAPITAL LETTER EPSILON WITH VARIA 1FC9; C; 1F73; # GREEK CAPITAL LETTER EPSILON WITH OXIA 1FCA; C; 1F74; # GREEK CAPITAL LETTER ETA WITH VARIA 1FCB; C; 1F75; # GREEK CAPITAL LETTER ETA WITH OXIA 1FCC; F; 03B7 03B9; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI 1FCC; S; 1FC3; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI 1FD2; F; 03B9 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA 1FD3; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA 1FD6; F; 03B9 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI 1FD7; F; 03B9 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI 1FD8; C; 1FD0; # GREEK CAPITAL LETTER IOTA WITH VRACHY 1FD9; C; 1FD1; # GREEK CAPITAL LETTER IOTA WITH MACRON 1FDA; C; 1F76; # GREEK CAPITAL LETTER IOTA WITH VARIA 1FDB; C; 1F77; # GREEK CAPITAL LETTER IOTA WITH OXIA 1FE2; F; 03C5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA 1FE3; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA 1FE4; F; 03C1 0313; # GREEK SMALL LETTER RHO WITH PSILI 1FE6; F; 03C5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI 1FE7; F; 03C5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI 1FE8; C; 1FE0; # GREEK CAPITAL LETTER UPSILON WITH VRACHY 1FE9; C; 1FE1; # GREEK CAPITAL LETTER UPSILON WITH MACRON 1FEA; C; 1F7A; # GREEK CAPITAL LETTER UPSILON WITH VARIA 1FEB; C; 1F7B; # GREEK CAPITAL LETTER UPSILON WITH OXIA 1FEC; C; 1FE5; # GREEK CAPITAL LETTER RHO WITH DASIA 1FF2; F; 1F7C 03B9; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI 1FF3; F; 03C9 03B9; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI 1FF4; F; 03CE 03B9; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI 1FF6; F; 03C9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI 1FF7; F; 03C9 0342 03B9; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI 1FF8; C; 1F78; # GREEK CAPITAL LETTER OMICRON WITH VARIA 1FF9; C; 1F79; # GREEK CAPITAL LETTER OMICRON WITH OXIA 1FFA; C; 1F7C; # GREEK CAPITAL LETTER OMEGA WITH VARIA 1FFB; C; 1F7D; # GREEK CAPITAL LETTER OMEGA WITH OXIA 1FFC; F; 03C9 03B9; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI 1FFC; S; 1FF3; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI 2126; C; 03C9; # OHM SIGN 212A; C; 006B; # KELVIN SIGN 212B; C; 00E5; # ANGSTROM SIGN 2132; C; 214E; # TURNED CAPITAL F 2160; C; 2170; # ROMAN NUMERAL ONE 2161; C; 2171; # ROMAN NUMERAL TWO 2162; C; 2172; # ROMAN NUMERAL THREE 2163; C; 2173; # ROMAN NUMERAL FOUR 2164; C; 2174; # ROMAN NUMERAL FIVE 2165; C; 2175; # ROMAN NUMERAL SIX 2166; C; 2176; # ROMAN NUMERAL SEVEN 2167; C; 2177; # ROMAN NUMERAL EIGHT 2168; C; 2178; # ROMAN NUMERAL NINE 2169; C; 2179; # ROMAN NUMERAL TEN 216A; C; 217A; # ROMAN NUMERAL ELEVEN 216B; C; 217B; # ROMAN NUMERAL TWELVE 216C; C; 217C; # ROMAN NUMERAL FIFTY 216D; C; 217D; # ROMAN NUMERAL ONE HUNDRED 216E; C; 217E; # ROMAN NUMERAL FIVE HUNDRED 216F; C; 217F; # ROMAN NUMERAL ONE THOUSAND 2183; C; 2184; # ROMAN NUMERAL REVERSED ONE HUNDRED 24B6; C; 24D0; # CIRCLED LATIN CAPITAL LETTER A 24B7; C; 24D1; # CIRCLED LATIN CAPITAL LETTER B 24B8; C; 24D2; # CIRCLED LATIN CAPITAL LETTER C 24B9; C; 24D3; # CIRCLED LATIN CAPITAL LETTER D 24BA; C; 24D4; # CIRCLED LATIN CAPITAL LETTER E 24BB; C; 24D5; # CIRCLED LATIN CAPITAL LETTER F 24BC; C; 24D6; # CIRCLED LATIN CAPITAL LETTER G 24BD; C; 24D7; # CIRCLED LATIN CAPITAL LETTER H 24BE; C; 24D8; # CIRCLED LATIN CAPITAL LETTER I 24BF; C; 24D9; # CIRCLED LATIN CAPITAL LETTER J 24C0; C; 24DA; # CIRCLED LATIN CAPITAL LETTER K 24C1; C; 24DB; # CIRCLED LATIN CAPITAL LETTER L 24C2; C; 24DC; # CIRCLED LATIN CAPITAL LETTER M 24C3; C; 24DD; # CIRCLED LATIN CAPITAL LETTER N 24C4; C; 24DE; # CIRCLED LATIN CAPITAL LETTER O 24C5; C; 24DF; # CIRCLED LATIN CAPITAL LETTER P 24C6; C; 24E0; # CIRCLED LATIN CAPITAL LETTER Q 24C7; C; 24E1; # CIRCLED LATIN CAPITAL LETTER R 24C8; C; 24E2; # CIRCLED LATIN CAPITAL LETTER S 24C9; C; 24E3; # CIRCLED LATIN CAPITAL LETTER T 24CA; C; 24E4; # CIRCLED LATIN CAPITAL LETTER U 24CB; C; 24E5; # CIRCLED LATIN CAPITAL LETTER V 24CC; C; 24E6; # CIRCLED LATIN CAPITAL LETTER W 24CD; C; 24E7; # CIRCLED LATIN CAPITAL LETTER X 24CE; C; 24E8; # CIRCLED LATIN CAPITAL LETTER Y 24CF; C; 24E9; # CIRCLED LATIN CAPITAL LETTER Z 2C00; C; 2C30; # GLAGOLITIC CAPITAL LETTER AZU 2C01; C; 2C31; # GLAGOLITIC CAPITAL LETTER BUKY 2C02; C; 2C32; # GLAGOLITIC CAPITAL LETTER VEDE 2C03; C; 2C33; # GLAGOLITIC CAPITAL LETTER GLAGOLI 2C04; C; 2C34; # GLAGOLITIC CAPITAL LETTER DOBRO 2C05; C; 2C35; # GLAGOLITIC CAPITAL LETTER YESTU 2C06; C; 2C36; # GLAGOLITIC CAPITAL LETTER ZHIVETE 2C07; C; 2C37; # GLAGOLITIC CAPITAL LETTER DZELO 2C08; C; 2C38; # GLAGOLITIC CAPITAL LETTER ZEMLJA 2C09; C; 2C39; # GLAGOLITIC CAPITAL LETTER IZHE 2C0A; C; 2C3A; # GLAGOLITIC CAPITAL LETTER INITIAL IZHE 2C0B; C; 2C3B; # GLAGOLITIC CAPITAL LETTER I 2C0C; C; 2C3C; # GLAGOLITIC CAPITAL LETTER DJERVI 2C0D; C; 2C3D; # GLAGOLITIC CAPITAL LETTER KAKO 2C0E; C; 2C3E; # GLAGOLITIC CAPITAL LETTER LJUDIJE 2C0F; C; 2C3F; # GLAGOLITIC CAPITAL LETTER MYSLITE 2C10; C; 2C40; # GLAGOLITIC CAPITAL LETTER NASHI 2C11; C; 2C41; # GLAGOLITIC CAPITAL LETTER ONU 2C12; C; 2C42; # GLAGOLITIC CAPITAL LETTER POKOJI 2C13; C; 2C43; # GLAGOLITIC CAPITAL LETTER RITSI 2C14; C; 2C44; # GLAGOLITIC CAPITAL LETTER SLOVO 2C15; C; 2C45; # GLAGOLITIC CAPITAL LETTER TVRIDO 2C16; C; 2C46; # GLAGOLITIC CAPITAL LETTER UKU 2C17; C; 2C47; # GLAGOLITIC CAPITAL LETTER FRITU 2C18; C; 2C48; # GLAGOLITIC CAPITAL LETTER HERU 2C19; C; 2C49; # GLAGOLITIC CAPITAL LETTER OTU 2C1A; C; 2C4A; # GLAGOLITIC CAPITAL LETTER PE 2C1B; C; 2C4B; # GLAGOLITIC CAPITAL LETTER SHTA 2C1C; C; 2C4C; # GLAGOLITIC CAPITAL LETTER TSI 2C1D; C; 2C4D; # GLAGOLITIC CAPITAL LETTER CHRIVI 2C1E; C; 2C4E; # GLAGOLITIC CAPITAL LETTER SHA 2C1F; C; 2C4F; # GLAGOLITIC CAPITAL LETTER YERU 2C20; C; 2C50; # GLAGOLITIC CAPITAL LETTER YERI 2C21; C; 2C51; # GLAGOLITIC CAPITAL LETTER YATI 2C22; C; 2C52; # GLAGOLITIC CAPITAL LETTER SPIDERY HA 2C23; C; 2C53; # GLAGOLITIC CAPITAL LETTER YU 2C24; C; 2C54; # GLAGOLITIC CAPITAL LETTER SMALL YUS 2C25; C; 2C55; # GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL 2C26; C; 2C56; # GLAGOLITIC CAPITAL LETTER YO 2C27; C; 2C57; # GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS 2C28; C; 2C58; # GLAGOLITIC CAPITAL LETTER BIG YUS 2C29; C; 2C59; # GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS 2C2A; C; 2C5A; # GLAGOLITIC CAPITAL LETTER FITA 2C2B; C; 2C5B; # GLAGOLITIC CAPITAL LETTER IZHITSA 2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC 2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A 2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE 2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR 2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE 2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE 2C64; C; 027D; # LATIN CAPITAL LETTER R WITH TAIL 2C67; C; 2C68; # LATIN CAPITAL LETTER H WITH DESCENDER 2C69; C; 2C6A; # LATIN CAPITAL LETTER K WITH DESCENDER 2C6B; C; 2C6C; # LATIN CAPITAL LETTER Z WITH DESCENDER 2C6D; C; 0251; # LATIN CAPITAL LETTER ALPHA 2C6E; C; 0271; # LATIN CAPITAL LETTER M WITH HOOK 2C6F; C; 0250; # LATIN CAPITAL LETTER TURNED A 2C72; C; 2C73; # LATIN CAPITAL LETTER W WITH HOOK 2C75; C; 2C76; # LATIN CAPITAL LETTER HALF H 2C80; C; 2C81; # COPTIC CAPITAL LETTER ALFA 2C82; C; 2C83; # COPTIC CAPITAL LETTER VIDA 2C84; C; 2C85; # COPTIC CAPITAL LETTER GAMMA 2C86; C; 2C87; # COPTIC CAPITAL LETTER DALDA 2C88; C; 2C89; # COPTIC CAPITAL LETTER EIE 2C8A; C; 2C8B; # COPTIC CAPITAL LETTER SOU 2C8C; C; 2C8D; # COPTIC CAPITAL LETTER ZATA 2C8E; C; 2C8F; # COPTIC CAPITAL LETTER HATE 2C90; C; 2C91; # COPTIC CAPITAL LETTER THETHE 2C92; C; 2C93; # COPTIC CAPITAL LETTER IAUDA 2C94; C; 2C95; # COPTIC CAPITAL LETTER KAPA 2C96; C; 2C97; # COPTIC CAPITAL LETTER LAULA 2C98; C; 2C99; # COPTIC CAPITAL LETTER MI 2C9A; C; 2C9B; # COPTIC CAPITAL LETTER NI 2C9C; C; 2C9D; # COPTIC CAPITAL LETTER KSI 2C9E; C; 2C9F; # COPTIC CAPITAL LETTER O 2CA0; C; 2CA1; # COPTIC CAPITAL LETTER PI 2CA2; C; 2CA3; # COPTIC CAPITAL LETTER RO 2CA4; C; 2CA5; # COPTIC CAPITAL LETTER SIMA 2CA6; C; 2CA7; # COPTIC CAPITAL LETTER TAU 2CA8; C; 2CA9; # COPTIC CAPITAL LETTER UA 2CAA; C; 2CAB; # COPTIC CAPITAL LETTER FI 2CAC; C; 2CAD; # COPTIC CAPITAL LETTER KHI 2CAE; C; 2CAF; # COPTIC CAPITAL LETTER PSI 2CB0; C; 2CB1; # COPTIC CAPITAL LETTER OOU 2CB2; C; 2CB3; # COPTIC CAPITAL LETTER DIALECT-P ALEF 2CB4; C; 2CB5; # COPTIC CAPITAL LETTER OLD COPTIC AIN 2CB6; C; 2CB7; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE 2CB8; C; 2CB9; # COPTIC CAPITAL LETTER DIALECT-P KAPA 2CBA; C; 2CBB; # COPTIC CAPITAL LETTER DIALECT-P NI 2CBC; C; 2CBD; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI 2CBE; C; 2CBF; # COPTIC CAPITAL LETTER OLD COPTIC OOU 2CC0; C; 2CC1; # COPTIC CAPITAL LETTER SAMPI 2CC2; C; 2CC3; # COPTIC CAPITAL LETTER CROSSED SHEI 2CC4; C; 2CC5; # COPTIC CAPITAL LETTER OLD COPTIC SHEI 2CC6; C; 2CC7; # COPTIC CAPITAL LETTER OLD COPTIC ESH 2CC8; C; 2CC9; # COPTIC CAPITAL LETTER AKHMIMIC KHEI 2CCA; C; 2CCB; # COPTIC CAPITAL LETTER DIALECT-P HORI 2CCC; C; 2CCD; # COPTIC CAPITAL LETTER OLD COPTIC HORI 2CCE; C; 2CCF; # COPTIC CAPITAL LETTER OLD COPTIC HA 2CD0; C; 2CD1; # COPTIC CAPITAL LETTER L-SHAPED HA 2CD2; C; 2CD3; # COPTIC CAPITAL LETTER OLD COPTIC HEI 2CD4; C; 2CD5; # COPTIC CAPITAL LETTER OLD COPTIC HAT 2CD6; C; 2CD7; # COPTIC CAPITAL LETTER OLD COPTIC GANGIA 2CD8; C; 2CD9; # COPTIC CAPITAL LETTER OLD COPTIC DJA 2CDA; C; 2CDB; # COPTIC CAPITAL LETTER OLD COPTIC SHIMA 2CDC; C; 2CDD; # COPTIC CAPITAL LETTER OLD NUBIAN SHIMA 2CDE; C; 2CDF; # COPTIC CAPITAL LETTER OLD NUBIAN NGI 2CE0; C; 2CE1; # COPTIC CAPITAL LETTER OLD NUBIAN NYI 2CE2; C; 2CE3; # COPTIC CAPITAL LETTER OLD NUBIAN WAU A640; C; A641; # CYRILLIC CAPITAL LETTER ZEMLYA A642; C; A643; # CYRILLIC CAPITAL LETTER DZELO A644; C; A645; # CYRILLIC CAPITAL LETTER REVERSED DZE A646; C; A647; # CYRILLIC CAPITAL LETTER IOTA A648; C; A649; # CYRILLIC CAPITAL LETTER DJERV A64A; C; A64B; # CYRILLIC CAPITAL LETTER MONOGRAPH UK A64C; C; A64D; # CYRILLIC CAPITAL LETTER BROAD OMEGA A64E; C; A64F; # CYRILLIC CAPITAL LETTER NEUTRAL YER A650; C; A651; # CYRILLIC CAPITAL LETTER YERU WITH BACK YER A652; C; A653; # CYRILLIC CAPITAL LETTER IOTIFIED YAT A654; C; A655; # CYRILLIC CAPITAL LETTER REVERSED YU A656; C; A657; # CYRILLIC CAPITAL LETTER IOTIFIED A A658; C; A659; # CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS A65A; C; A65B; # CYRILLIC CAPITAL LETTER BLENDED YUS A65C; C; A65D; # CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS A65E; C; A65F; # CYRILLIC CAPITAL LETTER YN A662; C; A663; # CYRILLIC CAPITAL LETTER SOFT DE A664; C; A665; # CYRILLIC CAPITAL LETTER SOFT EL A666; C; A667; # CYRILLIC CAPITAL LETTER SOFT EM A668; C; A669; # CYRILLIC CAPITAL LETTER MONOCULAR O A66A; C; A66B; # CYRILLIC CAPITAL LETTER BINOCULAR O A66C; C; A66D; # CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O A680; C; A681; # CYRILLIC CAPITAL LETTER DWE A682; C; A683; # CYRILLIC CAPITAL LETTER DZWE A684; C; A685; # CYRILLIC CAPITAL LETTER ZHWE A686; C; A687; # CYRILLIC CAPITAL LETTER CCHE A688; C; A689; # CYRILLIC CAPITAL LETTER DZZE A68A; C; A68B; # CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK A68C; C; A68D; # CYRILLIC CAPITAL LETTER TWE A68E; C; A68F; # CYRILLIC CAPITAL LETTER TSWE A690; C; A691; # CYRILLIC CAPITAL LETTER TSSE A692; C; A693; # CYRILLIC CAPITAL LETTER TCHE A694; C; A695; # CYRILLIC CAPITAL LETTER HWE A696; C; A697; # CYRILLIC CAPITAL LETTER SHWE A722; C; A723; # LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF A724; C; A725; # LATIN CAPITAL LETTER EGYPTOLOGICAL AIN A726; C; A727; # LATIN CAPITAL LETTER HENG A728; C; A729; # LATIN CAPITAL LETTER TZ A72A; C; A72B; # LATIN CAPITAL LETTER TRESILLO A72C; C; A72D; # LATIN CAPITAL LETTER CUATRILLO A72E; C; A72F; # LATIN CAPITAL LETTER CUATRILLO WITH COMMA A732; C; A733; # LATIN CAPITAL LETTER AA A734; C; A735; # LATIN CAPITAL LETTER AO A736; C; A737; # LATIN CAPITAL LETTER AU A738; C; A739; # LATIN CAPITAL LETTER AV A73A; C; A73B; # LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR A73C; C; A73D; # LATIN CAPITAL LETTER AY A73E; C; A73F; # LATIN CAPITAL LETTER REVERSED C WITH DOT A740; C; A741; # LATIN CAPITAL LETTER K WITH STROKE A742; C; A743; # LATIN CAPITAL LETTER K WITH DIAGONAL STROKE A744; C; A745; # LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE A746; C; A747; # LATIN CAPITAL LETTER BROKEN L A748; C; A749; # LATIN CAPITAL LETTER L WITH HIGH STROKE A74A; C; A74B; # LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY A74C; C; A74D; # LATIN CAPITAL LETTER O WITH LOOP A74E; C; A74F; # LATIN CAPITAL LETTER OO A750; C; A751; # LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER A752; C; A753; # LATIN CAPITAL LETTER P WITH FLOURISH A754; C; A755; # LATIN CAPITAL LETTER P WITH SQUIRREL TAIL A756; C; A757; # LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER A758; C; A759; # LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE A75A; C; A75B; # LATIN CAPITAL LETTER R ROTUNDA A75C; C; A75D; # LATIN CAPITAL LETTER RUM ROTUNDA A75E; C; A75F; # LATIN CAPITAL LETTER V WITH DIAGONAL STROKE A760; C; A761; # LATIN CAPITAL LETTER VY A762; C; A763; # LATIN CAPITAL LETTER VISIGOTHIC Z A764; C; A765; # LATIN CAPITAL LETTER THORN WITH STROKE A766; C; A767; # LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER A768; C; A769; # LATIN CAPITAL LETTER VEND A76A; C; A76B; # LATIN CAPITAL LETTER ET A76C; C; A76D; # LATIN CAPITAL LETTER IS A76E; C; A76F; # LATIN CAPITAL LETTER CON A779; C; A77A; # LATIN CAPITAL LETTER INSULAR D A77B; C; A77C; # LATIN CAPITAL LETTER INSULAR F A77D; C; 1D79; # LATIN CAPITAL LETTER INSULAR G A77E; C; A77F; # LATIN CAPITAL LETTER TURNED INSULAR G A780; C; A781; # LATIN CAPITAL LETTER TURNED L A782; C; A783; # LATIN CAPITAL LETTER INSULAR R A784; C; A785; # LATIN CAPITAL LETTER INSULAR S A786; C; A787; # LATIN CAPITAL LETTER INSULAR T A78B; C; A78C; # LATIN CAPITAL LETTER SALTILLO FB00; F; 0066 0066; # LATIN SMALL LIGATURE FF FB01; F; 0066 0069; # LATIN SMALL LIGATURE FI FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL FB03; F; 0066 0066 0069; # LATIN SMALL LIGATURE FFI FB04; F; 0066 0066 006C; # LATIN SMALL LIGATURE FFL FB05; F; 0073 0074; # LATIN SMALL LIGATURE LONG S T FB06; F; 0073 0074; # LATIN SMALL LIGATURE ST FB13; F; 0574 0576; # ARMENIAN SMALL LIGATURE MEN NOW FB14; F; 0574 0565; # ARMENIAN SMALL LIGATURE MEN ECH FB15; F; 0574 056B; # ARMENIAN SMALL LIGATURE MEN INI FB16; F; 057E 0576; # ARMENIAN SMALL LIGATURE VEW NOW FB17; F; 0574 056D; # ARMENIAN SMALL LIGATURE MEN XEH FF21; C; FF41; # FULLWIDTH LATIN CAPITAL LETTER A FF22; C; FF42; # FULLWIDTH LATIN CAPITAL LETTER B FF23; C; FF43; # FULLWIDTH LATIN CAPITAL LETTER C FF24; C; FF44; # FULLWIDTH LATIN CAPITAL LETTER D FF25; C; FF45; # FULLWIDTH LATIN CAPITAL LETTER E FF26; C; FF46; # FULLWIDTH LATIN CAPITAL LETTER F FF27; C; FF47; # FULLWIDTH LATIN CAPITAL LETTER G FF28; C; FF48; # FULLWIDTH LATIN CAPITAL LETTER H FF29; C; FF49; # FULLWIDTH LATIN CAPITAL LETTER I FF2A; C; FF4A; # FULLWIDTH LATIN CAPITAL LETTER J FF2B; C; FF4B; # FULLWIDTH LATIN CAPITAL LETTER K FF2C; C; FF4C; # FULLWIDTH LATIN CAPITAL LETTER L FF2D; C; FF4D; # FULLWIDTH LATIN CAPITAL LETTER M FF2E; C; FF4E; # FULLWIDTH LATIN CAPITAL LETTER N FF2F; C; FF4F; # FULLWIDTH LATIN CAPITAL LETTER O FF30; C; FF50; # FULLWIDTH LATIN CAPITAL LETTER P FF31; C; FF51; # FULLWIDTH LATIN CAPITAL LETTER Q FF32; C; FF52; # FULLWIDTH LATIN CAPITAL LETTER R FF33; C; FF53; # FULLWIDTH LATIN CAPITAL LETTER S FF34; C; FF54; # FULLWIDTH LATIN CAPITAL LETTER T FF35; C; FF55; # FULLWIDTH LATIN CAPITAL LETTER U FF36; C; FF56; # FULLWIDTH LATIN CAPITAL LETTER V FF37; C; FF57; # FULLWIDTH LATIN CAPITAL LETTER W FF38; C; FF58; # FULLWIDTH LATIN CAPITAL LETTER X FF39; C; FF59; # FULLWIDTH LATIN CAPITAL LETTER Y FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z 10400; C; 10428; # DESERET CAPITAL LETTER LONG I 10401; C; 10429; # DESERET CAPITAL LETTER LONG E 10402; C; 1042A; # DESERET CAPITAL LETTER LONG A 10403; C; 1042B; # DESERET CAPITAL LETTER LONG AH 10404; C; 1042C; # DESERET CAPITAL LETTER LONG O 10405; C; 1042D; # DESERET CAPITAL LETTER LONG OO 10406; C; 1042E; # DESERET CAPITAL LETTER SHORT I 10407; C; 1042F; # DESERET CAPITAL LETTER SHORT E 10408; C; 10430; # DESERET CAPITAL LETTER SHORT A 10409; C; 10431; # DESERET CAPITAL LETTER SHORT AH 1040A; C; 10432; # DESERET CAPITAL LETTER SHORT O 1040B; C; 10433; # DESERET CAPITAL LETTER SHORT OO 1040C; C; 10434; # DESERET CAPITAL LETTER AY 1040D; C; 10435; # DESERET CAPITAL LETTER OW 1040E; C; 10436; # DESERET CAPITAL LETTER WU 1040F; C; 10437; # DESERET CAPITAL LETTER YEE 10410; C; 10438; # DESERET CAPITAL LETTER H 10411; C; 10439; # DESERET CAPITAL LETTER PEE 10412; C; 1043A; # DESERET CAPITAL LETTER BEE 10413; C; 1043B; # DESERET CAPITAL LETTER TEE 10414; C; 1043C; # DESERET CAPITAL LETTER DEE 10415; C; 1043D; # DESERET CAPITAL LETTER CHEE 10416; C; 1043E; # DESERET CAPITAL LETTER JEE 10417; C; 1043F; # DESERET CAPITAL LETTER KAY 10418; C; 10440; # DESERET CAPITAL LETTER GAY 10419; C; 10441; # DESERET CAPITAL LETTER EF 1041A; C; 10442; # DESERET CAPITAL LETTER VEE 1041B; C; 10443; # DESERET CAPITAL LETTER ETH 1041C; C; 10444; # DESERET CAPITAL LETTER THEE 1041D; C; 10445; # DESERET CAPITAL LETTER ES 1041E; C; 10446; # DESERET CAPITAL LETTER ZEE 1041F; C; 10447; # DESERET CAPITAL LETTER ESH 10420; C; 10448; # DESERET CAPITAL LETTER ZHEE 10421; C; 10449; # DESERET CAPITAL LETTER ER 10422; C; 1044A; # DESERET CAPITAL LETTER EL 10423; C; 1044B; # DESERET CAPITAL LETTER EM 10424; C; 1044C; # DESERET CAPITAL LETTER EN 10425; C; 1044D; # DESERET CAPITAL LETTER ENG 10426; C; 1044E; # DESERET CAPITAL LETTER OI 10427; C; 1044F; # DESERET CAPITAL LETTER EW libdc0-0.3.24~svn3121/dclib/unicode/gen-case-folding-src.cpp0000644000175000017500000000542011141131203022303 0ustar sikonsikon/*************************************************************************** gen-case-folding-src.cpp - Converts CaseFolding.txt to case statements ------------------- begin : Thu Jul 17 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * @author Edward Sheldrake * * This just converts the unicode case folding table into * a huge list of case statements. * * Alternatively it could have been written in gawk or perl * or something. * * Compile: * g++ -Wall -Wformat -o gensrc gen-case-folding-src.cpp * * Run: * ./gensrc < CaseFolding-5.1.0.txt > ccasefolder-generated-code.cpp */ #include #include int main(int, char**) { char buffer[1024]; unsigned int source; char type; unsigned int res1, res2, res3, res4; int matched = EOF + 1; char * read = buffer; /* print header info */ printf("/* Automatically generated file do not edit. */\n"); printf("/* It's useless on it's own and is included */\n"); printf("/* at the correct place in ccasefolder.cpp */\n"); while ( read != 0 ) { read = fgets( buffer, 1024, stdin ); if ( read == 0 ) { return 0; } matched = sscanf(buffer, "%5x; %1c; %5x %5x %5x %5x;", &source, &type, &res1, &res2, &res3, &res4); if ( matched == 0 ) { continue; } else if ( (matched >= 3) && (matched <= 5) ) { if ( (type == 'C') || (type == 'F') ) { printf("case 0x%05X:\n",source); printf("\tfolded[outpos] = 0x%05X;\n",res1); printf("\t++outpos;\n"); if ( matched >= 4 ) { printf("\tfolded[outpos] = 0x%05X;\n",res2); printf("\t++outpos;\n"); } if ( matched == 5 ) { printf("\tfolded[outpos] = 0x%05X;\n",res3); printf("\t++outpos;\n"); } printf("\tbreak;\n"); } } else if ( matched > 5 ) { printf("Error: converting 1 char to more than 3 chars isn't supported.\n"); return 1; } if ( errno == EOF ) { return 0; } else if ( errno != 0 ) { perror("gensrc "); return 1; } } return 0; } libdc0-0.3.24~svn3121/dclib/cfilemanager.cpp0000644000175000017500000010443711176113057017432 0ustar sikonsikon/*************************************************************************** cfilemanager.cpp - description ------------------- begin : Sat Aug 03 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cfilemanager.h" #ifndef WIN32 #include #include #endif #include #include "core/cbytearray.h" #include "cconfig.h" #include "core/cdir.h" #include "core/cfile.h" #include "cdownloadmanager.h" #include "dclib.h" #include "core/cmanager.h" #include "csearchindex.h" #include "csharelist.h" #include "core/cbase32.h" #include "core/ccallback.h" #include "hash/compat.h" #include "hash/MerkleTree.h" /* for proper case-insensitive searching */ #include "ccasefolder.h" /** */ CFileManager::CFileManager() { m_pFileNameSet = 0; m_nFileBaseIndex = 0; m_pSearchIndex = new CSearchIndex(); m_pShareList = new CShareList(); m_pHashMemory = 0; m_pFileManagerInfo = new CFileManagerInfo(); m_pFileManagerInfo->m_nProgress = 100; InitFileTypeList(); if ( m_pShareList->Load() ) { if ( m_pSearchIndex->LoadedOK() ) // CSearchIndex::LoadIndex() is called in CSearchIndex constructor { m_pShareList->CreateList(m_pSearchIndex); } else { CreateShareList(); } if ( CConfig::Instance()->GetAutoRecreateShareList() ) { // this test was always broken before since m_pShareList->CreateList(m_pSearchIndex) had not been called // let's just always re-create it if the setting is true // it is unlikely but possible that files have changed but the total size is still the same //if ( CalcShareSize() != m_pShareList->GetShareSize() ) //{ CreateShareList(); //} } } else { CreateShareList(); } if ( CConfig::Instance()->GetRecreateShareListTime() != 0 ) { m_tCreateShareListTimeout = time(0)+CConfig::Instance()->GetRecreateShareListTime()*60*60; } else { m_tCreateShareListTimeout = 0; } // init timer m_pFileManagerCallback = new CCallback0( this, &CFileManager::FileManagerCallback ); CManager::Instance()->Add( m_pFileManagerCallback ); } /** */ CFileManager::~CFileManager() { Stop(); SetInstance(0); Lock(); if ( m_pFileManagerCallback ) { CManager::Instance()->Remove(m_pFileManagerCallback); delete m_pFileManagerCallback; } if ( m_pFileNameSet ) { m_pFileNameSet->clear(); delete m_pFileNameSet; m_pFileNameSet = 0; } delete m_pFileManagerInfo; m_pFileManagerInfo = 0; m_FileTypeMap.clear(); delete m_pShareList; m_pShareList = 0; delete m_pSearchIndex; m_pSearchIndex = 0; delete m_pHashMemory; m_pHashMemory = 0; UnLock(); } /** */ int CFileManager::GetShareBuffer( eShareBufferType type, CByteArray * sharebuffer, bool decompress ) { return m_pShareList->GetShareBuffer( type, sharebuffer, decompress ); } /** */ void CFileManager::GetPartialListing( const CString & dir, CString & result, int depth ) { m_pShareList->GetPartialListing( dir, result, depth, m_pSearchIndex ); } /** */ unsigned long CFileManager::GetShareBufferSize( eShareBufferType type ) { return m_pShareList->GetShareBufferSize(type); } /** */ ulonglong CFileManager::GetShareSize() { if ( m_pShareList ) return m_pShareList->GetShareSize(); else return 0; } /** */ void CFileManager::InitFileTypeList() { m_FileTypeMap.clear(); // MP3 2 m_FileTypeMap["A52"] = eftMP3; m_FileTypeMap["AAC"] = eftMP3; m_FileTypeMap["AC3"] = eftMP3; m_FileTypeMap["APE"] = eftMP3; m_FileTypeMap["AIFF"] = eftMP3; m_FileTypeMap["AU"] = eftMP3; m_FileTypeMap["DTS"] = eftMP3; m_FileTypeMap["FLA"] = eftMP3; m_FileTypeMap["FLAC"] = eftMP3; m_FileTypeMap["MID"] = eftMP3; m_FileTypeMap["MOD"] = eftMP3; m_FileTypeMap["M4A"] = eftMP3; m_FileTypeMap["M4P"] = eftMP3; m_FileTypeMap["MPC"] = eftMP3; m_FileTypeMap["MP1"] = eftMP3; m_FileTypeMap["MP2"] = eftMP3; m_FileTypeMap["MP3"] = eftMP3; m_FileTypeMap["OGG"] = eftMP3; m_FileTypeMap["RA"] = eftMP3; m_FileTypeMap["SHN"] = eftMP3; m_FileTypeMap["SPX"] = eftMP3; m_FileTypeMap["WAV"] = eftMP3; m_FileTypeMap["WMA"] = eftMP3; m_FileTypeMap["WV"] = eftMP3; // ARCHIVE 3 m_FileTypeMap["7Z"] = eftARCHIVE; m_FileTypeMap["ACE"] = eftARCHIVE; m_FileTypeMap["BZ2"] = eftARCHIVE; m_FileTypeMap["CAB"] = eftARCHIVE; m_FileTypeMap["EX_"] = eftARCHIVE; m_FileTypeMap["GZ"] = eftARCHIVE; m_FileTypeMap["LZH"] = eftARCHIVE; m_FileTypeMap["RAR"] = eftARCHIVE; m_FileTypeMap["RPM"] = eftARCHIVE; m_FileTypeMap["TAR"] = eftARCHIVE; m_FileTypeMap["TGZ"] = eftARCHIVE; m_FileTypeMap["ZIP"] = eftARCHIVE; m_FileTypeMap["ZOO"] = eftARCHIVE; m_FileTypeMap["Z"] = eftARCHIVE; // DOCUMENT 4 m_FileTypeMap["CFG"] = eftDOCUMENT; m_FileTypeMap["CONF"] = eftDOCUMENT; m_FileTypeMap["CPP"] = eftDOCUMENT; m_FileTypeMap["CSS"] = eftDOCUMENT; m_FileTypeMap["C"] = eftDOCUMENT; m_FileTypeMap["DIZ"] = eftDOCUMENT; m_FileTypeMap["DOC"] = eftDOCUMENT; m_FileTypeMap["H"] = eftDOCUMENT; m_FileTypeMap["HLP"] = eftDOCUMENT; m_FileTypeMap["HTM"] = eftDOCUMENT; m_FileTypeMap["HTML"] = eftDOCUMENT; m_FileTypeMap["INI"] = eftDOCUMENT; m_FileTypeMap["INF"] = eftDOCUMENT; m_FileTypeMap["LOG"] = eftDOCUMENT; m_FileTypeMap["NFO"] = eftDOCUMENT; m_FileTypeMap["ODG"] = eftDOCUMENT; m_FileTypeMap["ODP"] = eftDOCUMENT; m_FileTypeMap["ODS"] = eftDOCUMENT; m_FileTypeMap["ODT"] = eftDOCUMENT; m_FileTypeMap["PDF"] = eftDOCUMENT; m_FileTypeMap["PHP"] = eftDOCUMENT; m_FileTypeMap["PPT"] = eftDOCUMENT; m_FileTypeMap["PS"] = eftDOCUMENT; m_FileTypeMap["PDF"] = eftDOCUMENT; m_FileTypeMap["SHTML"] = eftDOCUMENT; m_FileTypeMap["SXC"] = eftDOCUMENT; m_FileTypeMap["SXD"] = eftDOCUMENT; m_FileTypeMap["SXI"] = eftDOCUMENT; m_FileTypeMap["SXW"] = eftDOCUMENT; m_FileTypeMap["TXT"] = eftDOCUMENT; m_FileTypeMap["RFT"] = eftDOCUMENT; m_FileTypeMap["RDF"] = eftDOCUMENT; m_FileTypeMap["XML"] = eftDOCUMENT; m_FileTypeMap["XLS"] = eftDOCUMENT; // APPL 5 m_FileTypeMap["BAT"] = eftAPPLICATION; m_FileTypeMap["CGI"] = eftAPPLICATION; m_FileTypeMap["COM"] = eftAPPLICATION; m_FileTypeMap["DLL"] = eftAPPLICATION; m_FileTypeMap["EXE"] = eftAPPLICATION; m_FileTypeMap["HQX"] = eftAPPLICATION; m_FileTypeMap["JS"] = eftAPPLICATION; m_FileTypeMap["SH"] = eftAPPLICATION; m_FileTypeMap["SO"] = eftAPPLICATION; m_FileTypeMap["SYS"] = eftAPPLICATION; m_FileTypeMap["VXD"] = eftAPPLICATION; // PICTURE 6 m_FileTypeMap["3DS"] = eftPICTURE; m_FileTypeMap["A11"] = eftPICTURE; m_FileTypeMap["ACB"] = eftPICTURE; m_FileTypeMap["ADC"] = eftPICTURE; m_FileTypeMap["ADI"] = eftPICTURE; m_FileTypeMap["AFI"] = eftPICTURE; m_FileTypeMap["AI"] = eftPICTURE; m_FileTypeMap["AIS"] = eftPICTURE; m_FileTypeMap["ANS"] = eftPICTURE; m_FileTypeMap["ART"] = eftPICTURE; m_FileTypeMap["B8"] = eftPICTURE; m_FileTypeMap["BMP"] = eftPICTURE; m_FileTypeMap["CBM"] = eftPICTURE; m_FileTypeMap["EPS"] = eftPICTURE; m_FileTypeMap["GIF"] = eftPICTURE; m_FileTypeMap["ICO"] = eftPICTURE; m_FileTypeMap["IMG"] = eftPICTURE; m_FileTypeMap["JPEG"] = eftPICTURE; m_FileTypeMap["JPG"] = eftPICTURE; m_FileTypeMap["PCT"] = eftPICTURE; m_FileTypeMap["PCX"] = eftPICTURE; m_FileTypeMap["PIC"] = eftPICTURE; m_FileTypeMap["PICT"] = eftPICTURE; m_FileTypeMap["PNG"] = eftPICTURE; m_FileTypeMap["PS"] = eftPICTURE; m_FileTypeMap["PSP"] = eftPICTURE; m_FileTypeMap["RLE"] = eftPICTURE; m_FileTypeMap["TGA"] = eftPICTURE; m_FileTypeMap["TIF"] = eftPICTURE; m_FileTypeMap["TIFF"] = eftPICTURE; m_FileTypeMap["XPM"] = eftPICTURE; // VIDEO 7 m_FileTypeMap["AVI"] = eftVIDEO; m_FileTypeMap["ASF"] = eftVIDEO; m_FileTypeMap["ASX"] = eftVIDEO; m_FileTypeMap["DAT"] = eftVIDEO; m_FileTypeMap["DIVX"] = eftVIDEO; m_FileTypeMap["DV"] = eftVIDEO; m_FileTypeMap["FLV"] = eftVIDEO; m_FileTypeMap["M1V"] = eftVIDEO; m_FileTypeMap["M2V"] = eftVIDEO; m_FileTypeMap["M4V"] = eftVIDEO; m_FileTypeMap["MKV"] = eftVIDEO; m_FileTypeMap["MOV"] = eftVIDEO; m_FileTypeMap["MOVIE"] = eftVIDEO; m_FileTypeMap["MP4"] = eftVIDEO; m_FileTypeMap["MPEG"] = eftVIDEO; m_FileTypeMap["MPEG1"] = eftVIDEO; m_FileTypeMap["MPEG2"] = eftVIDEO; m_FileTypeMap["MPEG4"] = eftVIDEO; m_FileTypeMap["MPG"] = eftVIDEO; m_FileTypeMap["OGM"] = eftVIDEO; m_FileTypeMap["PXP"] = eftVIDEO; m_FileTypeMap["QT"] = eftVIDEO; m_FileTypeMap["RM"] = eftVIDEO; m_FileTypeMap["RMVB"] = eftVIDEO; m_FileTypeMap["VIV"] = eftVIDEO; m_FileTypeMap["VOB"] = eftVIDEO; m_FileTypeMap["WMV"] = eftVIDEO; } /** return the filetype */ eFileTypes CFileManager::GetFileType( CString file ) { // set the filetype CString ext = CDir::Extension(file).ToUpper(); if ( ext.NotEmpty() ) { FileTypeMap::const_iterator it = m_FileTypeMap.find(ext); if ( it != m_FileTypeMap.end() ) { return it->second; } #if 0 printf("unknown extension: %s\n",ext.Data()); #endif } return eftUNKNOWN; } /** */ std::set * CFileManager::Search( unsigned int maxresults, std::list * words ) { CString filename; struct filebaseobject fbo; std::list::const_iterator it; bool notfound = false; unsigned int count = 0; std::set * results = new std::set; /* CSearchIndex::IndexCount() does a division */ const unsigned long indexcount = m_pSearchIndex->IndexCount(); for ( unsigned long fbi = 0; fbi < indexcount; ++fbi ) { /* for speed the return value or if filename is empty are not checked */ m_pSearchIndex->GetCaseFoldedName(fbi,&fbo,filename); notfound = false; for ( it = words->begin(); it != words->end(); ++it ) { if ( filename.Find(*it) == -1 ) { notfound = true; break; } } if ( notfound ) { continue; } results->insert(fbi); ++count; if ( count == maxresults ) { break; } } return results; } /** */ std::set * CFileManager::Search( unsigned int maxresults, std::list * words, eFileTypes etype ) { CString filename; struct filebaseobject fbo; std::list::const_iterator it; bool notfound = false; unsigned int count = 0; std::set * results = new std::set; /* stupid compiler warning */ const unsigned int type = (unsigned int) etype; /* CSearchIndex::IndexCount() does a division */ const unsigned long indexcount = m_pSearchIndex->IndexCount(); for ( unsigned long fbi = 0; fbi < indexcount; ++fbi ) { /* for speed the return value or if filename is empty are not checked */ m_pSearchIndex->GetCaseFoldedName(fbi,&fbo,filename); if ( fbo.m_eFileType != type ) { continue; } notfound = false; for ( it = words->begin(); it != words->end(); ++it ) { if ( filename.Find(*it) == -1 ) { notfound = true; break; } } if ( notfound ) { continue; } results->insert(fbi); ++count; if ( count == maxresults ) { break; } } return results; } /** */ std::set * CFileManager::SearchAtLeast( unsigned int maxresults, std::list * words, ulonglong size ) { CString filename; struct filebaseobject fbo; std::list::const_iterator it; bool notfound = false; unsigned int count = 0; std::set * results = new std::set; /* CSearchIndex::IndexCount() does a division */ const unsigned long indexcount = m_pSearchIndex->IndexCount(); for ( unsigned long fbi = 0; fbi < indexcount; ++fbi ) { /* for speed the return value or if filename is empty are not checked */ m_pSearchIndex->GetCaseFoldedName(fbi,&fbo,filename); if ( fbo.m_nSize < size ) { continue; } notfound = false; for ( it = words->begin(); it != words->end(); ++it ) { if ( filename.Find(*it) == -1 ) { notfound = true; break; } } if ( notfound ) { continue; } results->insert(fbi); ++count; if ( count == maxresults ) { break; } } return results; } /** */ std::set * CFileManager::SearchAtLeast( unsigned int maxresults, std::list * words, ulonglong size, eFileTypes etype ) { CString filename; struct filebaseobject fbo; std::list::const_iterator it; bool notfound = false; unsigned int count = 0; std::set * results = new std::set; /* stupid compiler warning */ const unsigned int type = (unsigned int) etype; /* CSearchIndex::IndexCount() does a division */ const unsigned long indexcount = m_pSearchIndex->IndexCount(); for ( unsigned long fbi = 0; fbi < indexcount; ++fbi ) { /* for speed the return value or if filename is empty are not checked */ m_pSearchIndex->GetCaseFoldedName(fbi,&fbo,filename); if ( fbo.m_eFileType != type ) { continue; } if ( fbo.m_nSize < size ) { continue; } notfound = false; for ( it = words->begin(); it != words->end(); ++it ) { if ( filename.Find(*it) == -1 ) { notfound = true; break; } } if ( notfound ) { continue; } results->insert(fbi); ++count; if ( count == maxresults ) { break; } } return results; } /** */ std::set * CFileManager::SearchAtMost( unsigned int maxresults, std::list * words, ulonglong size ) { CString filename; struct filebaseobject fbo; std::list::const_iterator it; bool notfound = false; unsigned int count = 0; std::set * results = new std::set; /* CSearchIndex::IndexCount() does a division */ const unsigned long indexcount = m_pSearchIndex->IndexCount(); for ( unsigned long fbi = 0; fbi < indexcount; ++fbi ) { /* for speed the return value or if filename is empty are not checked */ m_pSearchIndex->GetCaseFoldedName(fbi,&fbo,filename); if ( fbo.m_nSize > size ) { continue; } notfound = false; for ( it = words->begin(); it != words->end(); ++it ) { if ( filename.Find(*it) == -1 ) { notfound = true; break; } } if ( notfound ) { continue; } results->insert(fbi); ++count; if ( count == maxresults ) { break; } } return results; } /** */ std::set * CFileManager::SearchAtMost( unsigned int maxresults, std::list * words, ulonglong size, eFileTypes etype ) { CString filename; struct filebaseobject fbo; std::list::const_iterator it; bool notfound = false; unsigned int count = 0; std::set * results = new std::set; /* stupid compiler warning */ const unsigned int type = (unsigned int) etype; /* CSearchIndex::IndexCount() does a division */ const unsigned long indexcount = m_pSearchIndex->IndexCount(); for ( unsigned long fbi = 0; fbi < indexcount; ++fbi ) { /* for speed the return value or if filename is empty are not checked */ m_pSearchIndex->GetCaseFoldedName(fbi,&fbo,filename); if ( fbo.m_eFileType != type ) { continue; } if ( fbo.m_nSize > size ) { continue; } notfound = false; for ( it = words->begin(); it != words->end(); ++it ) { if ( filename.Find(*it) == -1 ) { notfound = true; break; } } if ( notfound ) { continue; } results->insert(fbi); ++count; if ( count == maxresults ) { break; } } return results; } /** */ std::set * CFileManager::SearchHash( CString s ) { CByteArray dst; if ( !m_pSearchIndex ) return 0; //if ( m_pFileManagerInfo->m_eFileManagerStatus != efmsNONE ) // return 0; if ( CBase32::Decode(&dst,&s) != dcpp::TigerTree::BYTES ) return 0; return m_pSearchIndex->SearchHash(dst.Data()); } /** */ CString CFileManager::GetHash( unsigned long hbi ) { if ( !m_pSearchIndex ) return CString(); //if ( m_pFileManagerInfo->m_eFileManagerStatus != efmsNONE ) // return CString(); return m_pSearchIndex->GetHash(hbi); } /** */ bool CFileManager::GetFileBaseObject( unsigned long index, struct filebaseobject * fbo, CString & filename ) { if ( !m_pSearchIndex ) return false; //if ( m_pFileManagerInfo->m_eFileManagerStatus != efmsNONE ) // return false; return m_pSearchIndex->GetFileBaseObject(index,fbo,filename); } /** */ bool CFileManager::CreateShareList() { bool err = false; if ( m_pFileManagerInfo->m_eFileManagerStatus != efmsNONE ) return err; Lock(); if ( Start() == -1 ) { UnLock(); return err; } /* CConfig::GetSharedFolders clears the list */ m_pShareFolder = 0; m_sShareIndexBuffer.Empty(); if ( CConfig::Instance()->GetSharedFolders(&m_SharedFolders) > 0 ) { m_pSearchIndex->PrepareUpdate(); if ( m_pFileNameSet ) { m_pFileNameSet->clear(); delete m_pFileNameSet; } m_pFileNameSet = new FileNameSet(); m_pFileManagerInfo->m_nProgress = 0; m_pFileManagerInfo->m_eFileManagerStatus = efmsCREATESHARELIST; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); err = true; } else { m_pShareList->SetIndexBuffer( m_sShareIndexBuffer ); m_pShareList->CreateList(m_pSearchIndex); m_pSearchIndex->SaveIndex(); UnLock(); Stop(); return err; } UnLock(); return err; } void CFileManager::CreateSearchIndex() { if ( m_pFileManagerInfo->m_eFileManagerStatus == efmsIDLE ) { m_nFileBaseIndex = 0; m_pFileManagerInfo->m_nProgress = 0; m_pFileManagerInfo->m_eFileManagerStatus = efmsCREATESEARCHINDEX; Start(); } } /** */ bool CFileManager::CreateHashList() { bool res = false; if ( m_pFileManagerInfo->m_eFileManagerStatus == efmsIDLE ) { m_nFileBaseIndex = 0; m_pFileManagerInfo->m_nProgress = 0; m_pFileManagerInfo->m_eFileManagerStatus = efmsCREATEHASHLIST; Start(); res = true; } return res; } /** */ void CFileManager::ThreadCreateSearchIndex() { int k; CString filename,folded; struct filebaseobject fbo; double percent; CCaseFolder casefolder; for(k=0;k<100;k++) { filename.Empty(); m_pSearchIndex->GetFileBaseObjectDuringUpdate(m_nFileBaseIndex,&fbo,filename); if ( filename.NotEmpty() ) { if ( casefolder.Fold( filename, folded ) == false ) { // failed, fallback folded = filename.ToLower(); } m_pSearchIndex->AddSearchIndex(folded); m_nFileBaseIndex++; } else { DPRINTF("case folded names list created\n"); // not yet, only do it once after hash list refresh finished //m_pSearchIndex->SaveIndex(); m_pFileManagerInfo->m_nProgress = 100; m_pFileManagerInfo->m_eFileManagerStatus = efmsIDLE; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); CreateHashList(); return; } } if ( m_pSearchIndex->IndexCountDuringUpdate() > 0 ) { percent = (m_nFileBaseIndex*100.0)/m_pSearchIndex->IndexCountDuringUpdate(); if ( m_pFileManagerInfo->m_nProgress != percent ) { m_pFileManagerInfo->m_nProgress = percent; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); } } } /** */ void CFileManager::ThreadCreateShareList() { CString s,s1; CDir dir; if ( (m_pShareFolder=m_SharedFolders.Next(m_pShareFolder)) != 0 ) { // directory s = m_pShareFolder->m_sPath; // is valid ? if ( dir.cd(s) ) { s = dir.Path(); s1 = dir.DirName(); if ( s1.NotEmpty() ) { s = s.Left( s.Length()-s1.Length() ); } ThreadCreateShareList( 0, CString(), CString(), 100/m_SharedFolders.Count() ); } else { printf("Can't change dir: '%s'\n",s.Data()); } } else { m_pFileManagerInfo->m_nProgress = 100; DPRINTF("finished listing files\n"); m_pShareList->SetIndexBuffer( m_sShareIndexBuffer ); /* free no longer required large string */ m_sShareIndexBuffer.Empty(); // m_pShareList->CreateList will be called after hashing finishes // don't call it here to avoid serving up filelists without TTHs in //m_pShareList->CreateList(m_pSearchIndex); if ( m_pFileNameSet ) { m_pFileNameSet->clear(); delete m_pFileNameSet; m_pFileNameSet = 0; } m_pFileManagerInfo->m_eFileManagerStatus = efmsIDLE; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); CreateSearchIndex(); if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); } } /** */ void CFileManager::ThreadCreateShareList( int depth, CString curr, CString rel, double percent ) { CDir dir; CList list; CString d,s; CString path; CString aliaspath; CFileInfo *fileinfo=0; int x,z; unsigned long index; if ( Stopped() ) return; d = m_pShareFolder->m_sPath; d += DIRSEPARATOR; d += curr; d += DIRSEPARATOR; d += rel; path = CDir::SimplePath(d); d = m_pShareFolder->m_sAlias; d += DIRSEPARATOR; d += curr; d += DIRSEPARATOR; d += rel; aliaspath = CDir::SimplePath(d); if ( CConfig::Instance()->GetDontShareDotFiles() && (rel.NotEmpty() && (rel.Data()[0] == '.')) ) { DPRINTF( "Not sharing folder \"%s\" due to dot files setting.\n", path.Data() ); return; } dir.SetPath(path); d.Empty(); z = depth; // printf("%s\n",curr.Data()); // create depth string for(x=depth;x>0;x--) d+="\x9"; z++; // use alias if ( depth == 0 ) { m_sShareIndexBuffer += m_pShareFolder->m_sAlias; m_sShareIndexBuffer += "\xd\xa"; } else { m_sShareIndexBuffer += d; m_sShareIndexBuffer += rel; m_sShareIndexBuffer += "\xd\xa"; } d += "\x9"; // add folder so it can be a search result fileinfo = new CFileInfo(); if ( depth == 0 ) { fileinfo->name = m_pShareFolder->m_sAlias; } else { fileinfo->name = rel; } fileinfo->size = 0; fileinfo->m_bSymlink = false; fileinfo->st_a_time = 0; fileinfo->st_m_time = 0; fileinfo->st_c_time = 0; if ( depth == 0 ) { m_pSearchIndex->AddIndex( fileinfo, DIRSEPARATOR, eftFOLDER ); } else { m_pSearchIndex->AddIndex( fileinfo, CDir::SimplePath(m_pShareFolder->m_sAlias+DIRSEPARATOR+curr), eftFOLDER ); } delete fileinfo; fileinfo = 0; // get all files if ( dir.ReadEntrys( CDir::Files, &list ) ) { // add files fileinfo = 0; while( (fileinfo=list.Next(fileinfo)) != 0 ) { if ( Stopped() ) return; if ( fileinfo->name.NotEmpty() ) { if ( CConfig::Instance()->GetDontShareDotFiles() && (fileinfo->name.Data()[0] == '.') ) { DPRINTF( "Not sharing file \"%s\" due to dot files setting.\n", fileinfo->name.Data() ); continue; } if ( fileinfo->m_bSymlink ) s = dir.Canonicalize(path+DIRSEPARATOR+fileinfo->name); else s = CDir::SimplePath(path+DIRSEPARATOR+fileinfo->name); if ( !s.IsEmpty() ) { std::pair ret = m_pFileNameSet->insert(s); if ( ret.second ) { if ( dclibVerbose() > 1 ) printf("CreateShareList: Add file: '%s/%s'\n",path.Data(),fileinfo->name.Data()); // add file to the file manager ... index = m_pSearchIndex->AddIndex( fileinfo, aliaspath, GetFileType(fileinfo->name) ); m_sShareIndexBuffer += d; m_sShareIndexBuffer += fileinfo->name; m_sShareIndexBuffer += '|'; m_sShareIndexBuffer += CString::number(index); m_sShareIndexBuffer += "\xd\xa"; } else { DPRINTF("CreateShareList: file '%s/%s' already shared\n",path.Data(),fileinfo->name.Data()); } } } } } if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); // get all dirs if ( dir.ReadEntrys( CDir::Dirs, &list ) ) { if ( list.Count() > 0 ) percent /= list.Count(); else m_pFileManagerInfo->m_nProgress += percent; // add dir fileinfo = 0; while( (fileinfo=list.Next(fileinfo)) != 0 ) { if ( Stopped() ) return; if ( (fileinfo->name != ".") && (fileinfo->name != "..") ) { if ( fileinfo->m_bSymlink ) s = dir.Canonicalize(path+DIRSEPARATOR+fileinfo->name); else s = CDir::SimplePath(path+DIRSEPARATOR+fileinfo->name); if ( !s.IsEmpty() ) { std::pair ret = m_pFileNameSet->insert(s); if ( ret.second ) { if ( dclibVerbose() > 0 ) printf("CreateShareList: Add path: '%s/%s'\n",path.Data(),fileinfo->name.Data()); ThreadCreateShareList(z,curr+DIRSEPARATOR+rel,fileinfo->name,percent); } else { m_pFileManagerInfo->m_nProgress += percent; DPRINTF("CreateShareList: dir '%s/%s' already shared\n",path.Data(),fileinfo->name.Data()); } } } else m_pFileManagerInfo->m_nProgress += percent; } } } /** */ ulonglong CFileManager::CalcShareSize() { CString s,s1; CDir dir; ulonglong iSSize; iSSize = 0; m_pShareFolder=0; if ( CConfig::Instance()->GetSharedFolders(&m_SharedFolders) == 0 ) { printf("No share folderfound !"); return 0; } while ( (m_pShareFolder=m_SharedFolders.Next(m_pShareFolder)) != 0 ) { // directory s = m_pShareFolder->m_sPath; // is valid ? if ( dir.cd(s) ) { s = dir.Path(); s1 = dir.DirName(); if ( s1.NotEmpty() ) { s = s.Left( s.Length()-s1.Length() ); } iSSize += CalcShareSize( 0, s, s1, CString() ); } else { printf("Can't change to dir: '%s'\n",s.Data()); } } return iSSize; } /** */ ulonglong CFileManager::CalcShareSize( int depth, CString base, CString curr, CString relpath ) { ulonglong lShareSize; CDir dir; CList list; CString d,s; CString path; CString rpath; CFileInfo *fileinfo; int x,z; lShareSize = 0; if ( relpath.IsEmpty() ) { rpath = curr; } else { rpath = relpath; rpath += DIRSEPARATOR; rpath += curr; } if ( base.IsEmpty() ) { path = curr; } else { path = base; path += DIRSEPARATOR; path += curr; } dir.SetPath(path); d.Empty(); z = depth; // create depth string if ( curr.NotEmpty() ) { for(x=depth;x>0;x--) d+="\x9"; z++; d += "\x9"; } // get all files if ( dir.ReadEntrys( CDir::Files, &list ) ) { fileinfo = 0; while( (fileinfo=list.Next(fileinfo)) != 0 ) { if ( fileinfo->name.NotEmpty() ) { if ( fileinfo->m_bSymlink ) s = dir.Canonicalize(path+DIRSEPARATOR+fileinfo->name); else s = CDir::SimplePath(path+DIRSEPARATOR+fileinfo->name); if ( s.NotEmpty() ) { lShareSize += fileinfo->size; } } } } // get all dirs if ( dir.ReadEntrys( CDir::Dirs, &list ) ) { fileinfo = 0; while( (fileinfo=list.Next(fileinfo)) != 0 ) { if ( (fileinfo->name != ".") && (fileinfo->name != "..") ) { if ( fileinfo->m_bSymlink ) s = dir.Canonicalize(path+DIRSEPARATOR+fileinfo->name); else s = CDir::SimplePath(path+DIRSEPARATOR+fileinfo->name); if ( s.NotEmpty() ) { lShareSize += CalcShareSize(z,path,fileinfo->name,rpath); } } } } return lShareSize; } /** */ void CFileManager::ThreadCreateHashList() { CString s,pa; struct filebaseobject fbo; unsigned long hbi; int len; CFile f; CDir cdir; double percent; if ( !m_pHashMemory ) { m_pHashMemory = new CByteArray(); m_pHashMemory->SetSize(1024*1024); } if ( m_pSearchIndex->GetFileBaseObjectDuringUpdate(m_nFileBaseIndex,&fbo,s) ) { pa = CConfig::Instance()->AliasToPath(s); if ( pa.IsEmpty() ) { m_nFileBaseIndex++; return; } // check if we have the hash if ( m_pSearchIndex->FindHashBaseIndexDuringUpdate(&fbo,&hbi) ) { if ( dclibVerbose() > 1 ) printf("hash found, no changes in file %s\n", pa.Data()); fbo.m_nHashIndex = hbi; m_pSearchIndex->UpdateIndex(m_nFileBaseIndex,&fbo); } else { if ( (CConfig::Instance()->GetDisableHashList() == false) && (cdir.IsDir( pa, false ) == false) ) { if ( dclibVerbose() > 0 ) printf("calculate new hash for %s\n", pa.Data()); if ( f.Open( pa, IO_RAW | IO_READONLY ) ) { dcpp::TigerTree hasher( std::max( dcpp::TigerTree::calcBlockSize(cdir.getFileSize(pa,false),10) , ((int64_t) 64*1024) ) ); while ( (len = f.Read( (char*)m_pHashMemory->Data(), 1024*1024)) > 0 ) { hasher.update(m_pHashMemory->Data(),len); if ( Stopped() ) break; } f.Close(); if ( !Stopped() ) { hasher.finalize(); ByteVector leaves = hasher.getLeafData(); m_pSearchIndex->AddHashIndex(m_nFileBaseIndex, hasher.getRoot().data, &leaves[0],leaves.size()); } else { printf("create hash stopped\n"); m_pFileManagerInfo->m_eFileManagerStatus = efmsIDLE; } } } } m_nFileBaseIndex++; if ( m_pSearchIndex->IndexCountDuringUpdate() > 0 ) { percent = (m_nFileBaseIndex*100.0)/m_pSearchIndex->IndexCountDuringUpdate(); if ( (percent-m_pFileManagerInfo->m_nProgress) > 1.0 ) { m_pFileManagerInfo->m_nProgress = percent; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); } } } else { m_pFileManagerInfo->m_eFileManagerStatus = efmsIDLE; } if ( m_pFileManagerInfo->m_eFileManagerStatus == efmsIDLE ) { DPRINTF("finished hashing files\n"); m_pFileManagerInfo->m_nProgress = 100; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); delete m_pHashMemory; m_pHashMemory = 0; m_pSearchIndex->FinishUpdate(); m_pSearchIndex->SaveIndex(); m_pShareList->CreateList(m_pSearchIndex); DPRINTF("sharelist generated\n"); m_pFileManagerInfo->m_eFileManagerStatus = efmsNONE; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); Stop(false); } } /** */ void CFileManager::Thread() { int wait = 50; Lock(); switch(m_pFileManagerInfo->m_eFileManagerStatus) { case efmsCREATESHARELIST: ThreadCreateShareList(); break; case efmsCREATESEARCHINDEX: ThreadCreateSearchIndex(); wait = 0; break; case efmsCREATEHASHLIST: ThreadCreateHashList(); wait = 0; break; case efmsREBUILDLISTS: ThreadRebuildLists(); wait = 0; break; case efmsVALIDATELEAVES: ThreadValidateLeaves(); wait = 0; break; default: break; } UnLock(); NanoSleep(wait); } /** */ int CFileManager::FileManagerCallback() { if ( CConfig::Instance()->GetRecreateShareListTime() != 0 ) { if ( m_tCreateShareListTimeout != 0 ) { if ( time(0) > m_tCreateShareListTimeout ) { CreateShareList(); m_tCreateShareListTimeout = time(0)+CConfig::Instance()->GetRecreateShareListTime()*60*60; } } else { m_tCreateShareListTimeout = time(0)+CConfig::Instance()->GetRecreateShareListTime()*60*60; } } else { m_tCreateShareListTimeout = 0; } return 0; } /** */ CString CFileManager::GetFileName( unsigned long fboid ) { struct filebaseobject fbo; CString filename; if ( GetFileBaseObject(fboid,&fbo,filename) ) { return filename; } else { return CString(); } } /** */ bool CFileManager::IsCreateShareListRunning() { if (m_pFileManagerInfo->m_eFileManagerStatus == efmsNONE) { return false; } else { return true; } } /** */ CByteArray * CFileManager::GetHashLeaves( CString tth ) { return m_pSearchIndex->GetHashLeaves( tth ); } /** */ bool CFileManager::RebuildLists() { bool err = false; //DPRINTF("CFileManager::RebuildLists() called\n"); if ( m_pFileManagerInfo->m_eFileManagerStatus != efmsNONE ) { return err; } Lock(); m_pFileManagerInfo->m_eFileManagerStatus = efmsREBUILDLISTS; Start(); err = true; UnLock(); return err; } /** */ void CFileManager::ThreadRebuildLists() { //DPRINTF("CFileManager::ThreadRebuildLists() called\n"); // CSearchIndex has direct access to the byte arrays so do it there if ( m_pSearchIndex->RebuildLists() == 0 ) { m_pSearchIndex->SaveIndex(); m_pFileManagerInfo->m_eFileManagerStatus = efmsNONE; Stop(false); return; } // recreate search index (also redoes hash lists) // needed bits copied out of CFileManager::CreateShareList // the mutex is already locked // the thread is already running // we already know m_eFileManagerStatus m_pShareFolder = 0; m_sShareIndexBuffer.Empty(); if ( CConfig::Instance()->GetSharedFolders(&m_SharedFolders) > 0 ) { m_pSearchIndex->PrepareUpdate(); if ( m_pFileNameSet ) { m_pFileNameSet->clear(); delete m_pFileNameSet; } m_pFileNameSet = new FileNameSet; m_pFileManagerInfo->m_nProgress = 0; m_pFileManagerInfo->m_eFileManagerStatus = efmsCREATESHARELIST; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); } else { m_pShareList->SetIndexBuffer( m_sShareIndexBuffer ); m_pShareList->CreateList(m_pSearchIndex); m_pSearchIndex->SaveIndex(); m_pFileManagerInfo->m_eFileManagerStatus = efmsNONE; Stop(false); } //DPRINTF("CFileManager::ThreadRebuildLists() finished\n"); } /** */ bool CFileManager::ValidateLeaves() { bool ok = false; if ( m_pFileManagerInfo->m_eFileManagerStatus != efmsNONE ) { return ok; } Lock(); m_pFileManagerInfo->m_eFileManagerStatus = efmsVALIDATELEAVES; Start(); ok = true; UnLock(); return ok; } /** */ void CFileManager::ThreadValidateLeaves() { if ( m_pSearchIndex->ValidateHashLeaves() == 0 ) { m_pFileManagerInfo->m_eFileManagerStatus = efmsNONE; Stop(false); return; } else { /* start CreateShareList */ m_pShareFolder = 0; m_sShareIndexBuffer.Empty(); if ( CConfig::Instance()->GetSharedFolders(&m_SharedFolders) > 0 ) { m_pSearchIndex->PrepareUpdate(); if ( m_pFileNameSet ) { m_pFileNameSet->clear(); delete m_pFileNameSet; } m_pFileNameSet = new FileNameSet; m_pFileManagerInfo->m_nProgress = 0; m_pFileManagerInfo->m_eFileManagerStatus = efmsCREATESHARELIST; if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->SendFileManagerInfo(m_pFileManagerInfo); } else { m_pShareList->SetIndexBuffer( m_sShareIndexBuffer ); m_pShareList->CreateList(m_pSearchIndex); m_pSearchIndex->SaveIndex(); m_pFileManagerInfo->m_eFileManagerStatus = efmsNONE; Stop(false); } } } libdc0-0.3.24~svn3121/dclib/csearchsocket.h0000644000175000017500000000503111112363266017270 0ustar sikonsikon/*************************************************************************** csearchsocket.h - description ------------------- begin : Thu May 27 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSEARCHSOCKET_H #define CSEARCHSOCKET_H /** *@author Mathias Küster * * This class receives UDP packets and parses them into search results. * Because originally dclib did not terminate it's search results with a |, * the parser adds one. I think only 1 result is allowed per packet, * but like with most of the NMDC protocol it's probably undefined. */ #include #include #include #include #include class CMessageSearchResult; class CSearchSocket : private CSocket { public: /** */ CSearchSocket(); /** */ virtual ~CSearchSocket(); /** */ void SetCallBackFunction( _CCallback1 * callback ); /** CSocket function made public and protected by mutex */ eConnectState Connect( CString Host, int Port, bool iAsync ); /** CSocket function made public and protected by mutex */ int Disconnect(); /** * Receives up to maxpackets UDP packets, * returning earlier if no more data available from the socket. * Parses the data and sends the results over the callback. */ void Receive( int maxpackets = 25 ); private: /** callback function */ _CCallback1 * m_pCallback; /** */ CMutex m_SearchSocketMutex; /** */ CByteArray m_Buffer; }; /** */ inline void CSearchSocket::SetCallBackFunction( _CCallback1 * callback ) { m_SearchSocketMutex.Lock(); delete m_pCallback; m_pCallback = callback; m_SearchSocketMutex.UnLock(); } #endif libdc0-0.3.24~svn3121/dclib/cfilehasher.cpp0000644000175000017500000002574711455415612017302 0ustar sikonsikon/*************************************************************************** cfilehasher.cpp - Calculate the TTH root and leaves for a file ------------------- begin : Fri May 16 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cfilehasher.h" #include "core/cbytearray.h" #include "core/cbase32.h" #include "core/cdir.h" #include "hash/compat.h" #include "hash/MerkleTree.h" #include //for memcmp() /** */ CTreeVerificationReport::CTreeVerificationReport( const CTreeVerificationReport & other ) { filename = other.filename; tthRoot = other.tthRoot; filesize = other.filesize; allgood = other.allgood; if ( other.segments ) { segments = new CList(); CHashedSegment * hs = 0; /* FIXME stop casting away the const once CList is fixed / replaced */ while ( (hs = ((CTreeVerificationReport&)other).segments->Next(hs)) != 0 ) { segments->Add( new CHashedSegment(*hs) ); } } else { segments = 0; } } /** */ CString CTreeVerificationReport::ToString() const { CString s = "CTreeVerificationReport\nFileName: "; s += filename; s += "\nFileSize: "; s += CString::number(filesize); s += "\nActual TTH root: "; s += tthRoot; s += "\nAll hashes OK: "; if ( allgood ) { s += "YES"; } else { s += "NO"; } s += "\nNumber of segments: "; s += CString::number(segments->Count()); // 18446744073709551615 18446744073709551615 ORQ6K7F5U2QGJOUKEKPEDJ2XXM3FTVYQ2BLWQOI ORQ6K7F5U2QGJOUKEKPEDJ2XXM3FTVYQ2BLWQOI s += "\n\nStart Size Expected TTH of block Actual TTH of block\n"; CHashedSegment * segment = 0; while ( (segment = segments->Next(segment)) != 0 ) { s += CString::number(segment->start).RightJustify(20); s += ' '; s += CString::number(segment->size).RightJustify(20); s += ' '; s += segment->expected; s += ' '; s += segment->actual; if ( segment->expected != segment->actual ) { s += " *** MISMATCH ***"; } s += "\n"; } return s; } /** */ CFileHasher::CFileHasher( const CString filename, CByteArray * workmem ) { status = efhsNotStarted; m_bStop = false; m_pRootData = 0; m_pLeafData = 0; filesize = 0; m_nProgress = 0; if ( file.Open( filename, IO_RAW | IO_READONLY ) ) { m_pWorkMem = workmem; usingOwnMem = false; filesize = CDir().getFileSize( filename, false ); if ( m_pWorkMem == 0 ) { m_pWorkMem = new CByteArray( 16*1024 ); usingOwnMem = true; } if ( m_pWorkMem == 0 ) { status = efhsError; } else { status = efhsReady; } } else { m_pWorkMem = 0; status = efhsError; } } /** delete stuff, close file */ CFileHasher::~CFileHasher() { delete m_pRootData; m_pRootData = 0; delete m_pLeafData; m_pLeafData = 0; if ( usingOwnMem && (m_pWorkMem != 0) ) { delete m_pWorkMem; m_pWorkMem = 0; } if ( file.IsOpen() ) { file.Close(); } } /** */ unsigned long CFileHasher::HashSize() { return dcpp::TigerTree::BYTES; } /** */ CString CFileHasher::GetHashRoot() { CString s; if ( (status == efhsFinished) && m_pRootData && (m_pRootData->Size() == dcpp::TigerTree::BYTES) ) { CBase32::Encode( &s, m_pRootData ); } return s; } /** */ CByteArray * CFileHasher::GetHashRootRaw() { CByteArray * result = 0; if ( (status == efhsFinished) && m_pRootData && (m_pRootData->Size() == dcpp::TigerTree::BYTES) ) { result = new CByteArray(); result->Append( m_pRootData->Data(), m_pRootData->Size() ); } return result; } /** */ CByteArray * CFileHasher::GetLeafData() { CByteArray * result = 0; if ( (status == efhsFinished) && m_pLeafData ) { result = new CByteArray(); result->Append( m_pLeafData->Data(), m_pLeafData->Size() ); } return result; } /** */ void CFileHasher::StopHashing() { m_bStop = true; } /** */ void CFileHasher::ComputeHash( const eFileHasherStatus endStatus ) { if ( status == efhsReady ) { status = efhsWorking; dcpp::TigerTree hasher( std::max(dcpp::TigerTree::calcBlockSize(filesize,10), ((int64_t) 64*1024) ) ); long len; while ( ((len = file.Read( (char*)m_pWorkMem->Data(), m_pWorkMem->Size() )) > 0) && (m_bStop == false) ) { hasher.update(m_pWorkMem->Data(),len); m_nProgress += len; } file.Close(); if ( m_bStop ) { status = efhsError; } else { hasher.finalize(); m_pRootData = new CByteArray(); m_pRootData->Append( hasher.getRoot().data, dcpp::TigerTree::BYTES ); vector leafdata = hasher.getLeafData(); m_pLeafData = new CByteArray(); m_pLeafData->Append( &leafdata[0], leafdata.size() ); status = endStatus; } if ( usingOwnMem ) { delete m_pWorkMem; m_pWorkMem = 0; } } } /** from DownloadManager::endData in the DC++ source */ int64_t CFileHasher::GetBlockSize( const unsigned long leavesSize, const int64_t filesize ) { int64_t blocksize = 1024; while ( blocksize * leavesSize/sizeof(dcpp::TigerTree::MerkleValue) < filesize ) { blocksize = blocksize * 2; } return blocksize; } /** */ bool CFileHasher::ValidateHashLeaves( CString tth, CByteArray * leaves, const ulonglong filesize ) { CByteArray dst; if ( CBase32::Decode( &dst, &tth ) != dcpp::TigerTree::BYTES ) { return false; } else { return ValidateHashLeaves( &dst, leaves, filesize ); } } /** */ bool CFileHasher::ValidateHashLeaves( CByteArray * root, CByteArray * leaves, const ulonglong filesize ) { if ( (root == 0) || (leaves == 0) ) { return false; } if ( root->Size() != dcpp::TigerTree::BYTES ) { return false; } else if ( leaves->Size() < dcpp::TigerTree::BYTES ) { return false; } else if ( leaves->Size() == dcpp::TigerTree::BYTES ) // optimisation { if ( memcmp(root->Data(),leaves->Data(),dcpp::TigerTree::BYTES) == 0 ) { return true; } } int64_t size = (int64_t) filesize; if ( size < 0 ) { return false; } int64_t blocksize = GetBlockSize( leaves->Size(), size ); dcpp::TigerTree hasher(size,blocksize,leaves->Data()); if ( memcmp(hasher.getRoot().data,root->Data(),dcpp::TigerTree::BYTES) == 0 ) { return true; } else { return false; } } /** */ CByteArray * CFileHasher::HashByteArray( CByteArray * data, unsigned long length ) { CByteArray * result = new CByteArray(); dcpp::TigerTree hasher; hasher.update( data->Data(), length ); hasher.finalize(); result->Append( hasher.getRoot().data, dcpp::TigerTree::BYTES ); return result; } /** */ void CFileHasherThread::Thread() { Lock(); ComputeHash(); UnLock(); /* do not try to pthread_join ourself */ Stop(false); } /** */ CFileTreeVerifier::CFileTreeVerifier( const CString filename, CByteArray * leaves, CByteArray * workmem ) : CFileHasher ( filename, workmem ) { m_pLeaves = leaves; m_pReport = new CTreeVerificationReport(); m_pReport->filename = filename; m_nPass = 0; } /** */ CFileTreeVerifier::~CFileTreeVerifier() { delete m_pReport; m_pReport = 0; } /** */ CTreeVerificationReport * CFileTreeVerifier::GetReport() { CTreeVerificationReport * pointer = 0; if ( GetStatus() == efhsFinished ) { pointer = m_pReport; m_pReport = 0; } return pointer; } /** */ void CFileTreeVerifier::Thread() { Lock(); m_nPass = 1; ComputeHash( efhsWorking ); if ( status == efhsWorking ) { m_nPass = 2; m_nProgress = 0; bool ok = true; /* first get segment size, we need it for either method */ int leafcount = m_pLeaves->Size() / dcpp::TigerTree::BYTES; unsigned long blocksize = 1024; while ( blocksize * leafcount < filesize ) { blocksize = blocksize * 2; } /* Can we do this? Or could two lists of tth leaves the same length be from differently structured trees? */ /* This should not take to long, no need to check m_bStop */ if ( m_pLeaves->Size() == HashLeavesDirect()->Size() ) { CByteArray expected_in; CByteArray actual_in; for ( unsigned long i = 0; i < m_pLeaves->Size(); i = i + dcpp::TigerTree::BYTES ) { expected_in.SetSize(0); actual_in.SetSize(0); expected_in.Append( m_pLeaves->Data()+i, dcpp::TigerTree::BYTES ); actual_in.Append( HashLeavesDirect()->Data()+i, dcpp::TigerTree::BYTES ); CHashedSegment * segment = new CHashedSegment(); CBase32::Encode( &(segment->expected), &expected_in ); CBase32::Encode( &(segment->actual), &actual_in ); if ( memcmp(expected_in.Data(),actual_in.Data(),dcpp::TigerTree::BYTES) != 0 ) { ok = false; } segment->start = i * blocksize; segment->size = blocksize; if ( segment->start + segment->size > filesize ) { segment->size = filesize - segment->start; } m_pReport->segments->Add(segment); } m_pReport->tthRoot = GetHashRoot(); m_pReport->filesize = filesize; m_pReport->allgood = ok; status = efhsFinished; } else { /* Otherwise, we need to hash each segement of the file */ if ( file.Open( m_pReport->filename, IO_RAW | IO_READONLY ) ) { CByteArray expected_in; for ( int i = 0; i < leafcount; i++ ) { expected_in.SetSize(0); expected_in.Append( m_pLeaves->Data()+(i*dcpp::TigerTree::BYTES), dcpp::TigerTree::BYTES ); CByteArray * buffer = new CByteArray( blocksize ); long read = file.Read( (char*) buffer->Data(), blocksize ); if ( read > 0 ) { CByteArray * actual_in = HashByteArray( buffer, (unsigned long)read ); CHashedSegment * segment = new CHashedSegment(); CBase32::Encode( &(segment->expected), &expected_in ); CBase32::Encode( &(segment->actual), actual_in ); delete actual_in; if ( segment->expected != segment->actual ) { ok = false; } segment->start = m_nProgress; segment->size = read; m_pReport->segments->Add(segment); m_nProgress += read; } else { status = efhsError; } delete buffer; if ( m_bStop || (status == efhsError) ) { status = efhsError; break; } } file.Close(); if ( status == efhsWorking ) { status = efhsFinished; m_pReport->tthRoot = GetHashRoot(); m_pReport->filesize = filesize; m_pReport->allgood = ok; } } else { status = efhsError; } } } UnLock(); /* do not try to pthread_join ourself */ Stop(false); } libdc0-0.3.24~svn3121/dclib/csearchmanager.cpp0000644000175000017500000004053311112363266017753 0ustar sikonsikon/*************************************************************************** csearchmanager.cpp - description ------------------- begin : Thu May 27 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "csearchmanager.h" #include #include #ifndef WIN32 #include #else #include #endif #include "dclib.h" #include "dcobject.h" #include "cconfig.h" #include "core/cmanager.h" #include "cconnectionmanager.h" #include "cfilemanager.h" #include "cdownloadmanager.h" #define SEARCH_TIMEOUT 60 #define SEARCH_CLIENT_TIMEOUT 60 // no longer defined because we are using a configured value //define SEARCH_SPAM_TIMEOUT 60 #define SEARCH_PASSIVE_CLIENT_REMOVE_TIMEOUT 5 #define SEARCH_ACTIVE_CLIENT_REMOVE_TIMEOUT 60 /** */ CSearchManager::CSearchManager() { SearchState(esNONE); m_eSearchType = estyNONE; m_eClientMode = ecmNONE; m_pClientList = 0; m_pHubList = 0; m_nMaxClients = 0; m_sCurrentHub = 0; m_pParentCallback = 0; m_bEnableTag = false; m_bHandleUserList = false; // set manager callback m_pCallback = new CCallback0( this, &CSearchManager::CallBackManager ); CManager::Instance()->Add( m_pCallback ); // set udp socket callback m_SearchSocket.SetCallBackFunction( new CCallback1( this, &CSearchManager::CallBackSearchSocket ) ); } /** */ CSearchManager::~CSearchManager() { SetInstance(0); // disconnect listen udp socket m_SearchSocket.Disconnect(); if ( CManager::Instance() ) CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; } /** */ long CSearchManager::HubCount() { long res = 0; m_Mutex.Lock(); if ( m_pHubList ) { res = m_pHubList->Count(); } m_Mutex.UnLock(); return res; } /** */ eSearchError CSearchManager::StartSearch( eSearchMode mode, eSearchType type, CList * querylist, CStringList * serverlist ) { if ( SearchState() != esNONE ) { return eseALREADYRUN; } if ( !querylist ) { DPRINTF("empty query list\n"); return eseNONE; } // check hubs if ( (mode != esmCONNECTEDSINGLE) && (mode != esmCONNECTEDALL) ) { // get hublist if ( !serverlist ) { if ( mode == esmPUBLIC ) { // get public hublist serverlist = CConfig::Instance()->GetPublicHubServerList(); } else if ( mode == esmBOOKMARK ) { // get bookmark hublist serverlist = CConfig::Instance()->GetBookmarkHubServerList(); } } // check hublist if ( !serverlist ) { DPRINTF("empty hublist\n"); return eseNONE; } if ( serverlist->Count() == 0 ) { DPRINTF("empty hublist 0\n"); return eseNONE; } } else { // get connected hub count if ( CConnectionManager::Instance()->GetConnectedHubCount() == 0 ) { DPRINTF("no connected hub\n"); return eseNONE; } if ( mode == esmCONNECTEDSINGLE ) { if ( !serverlist || (serverlist->Count() == 0) ) { DPRINTF("empty hublist\n"); return eseNONE; } } } // start listen if ( CConfig::Instance()->GetMode() != ecmPASSIVE ) { m_eClientMode = ecmACTIVE; if ( m_SearchSocket.Connect( CString(), CConfig::Instance()->GetUDPListenPort(), false ) != ecsSUCCESS ) { return eseNONE; } } else { m_eClientMode = ecmPASSIVE; } // now we can start the search m_eSearchType = type; m_eSearchMode = mode; m_nHubIndex = 0; m_nHubError = 0; m_pCurrentSearchObject = 0; m_pSearchList = querylist; m_pHubList = serverlist; // set start time m_tStartTime = time(0); // reset timeout m_tTimeoutTime = 0; SearchState(esSEARCH); DPRINTF("start search\n"); DPRINTF("M: %d T: %d QC: %ld\n", mode, type, querylist->Count()); return eseNONE; } /** */ void CSearchManager::StopSearch() { if ( SearchState() != esNONE ) { SearchState(esSTOP); // disconnect listen udp socket m_SearchSocket.Disconnect(); } } /** */ int CSearchManager::CallBackManager() { // no search running if ( SearchState() == esNONE ) { return 0; } m_SearchSocket.Receive(); // check for search timeout if ( SearchState() == esTIMEOUT ) { // DPRINTF("timeout\n"); if ( (time(0)-m_tTimeoutTime) >= SEARCH_TIMEOUT ) { StopSearch(); } } // check for stop search if ( SearchState() == esSTOP ) { DPRINTF("stop\n"); // disconnect all clients DisconnectClients(); // remove all clients if ( RemoveClients() ) { delete m_pClientList; m_pClientList = 0; DPRINTF("end\n"); // no more clients, reset search SearchState(esNONE); // disconnect listen udp socket m_SearchSocket.Disconnect(); m_eSearchType = estyNONE; return 0; } } // update all clients UpdateClients(); if ( SearchState() == esSEARCH ) { switch (m_eSearchMode) { case esmCONNECTEDSINGLE: case esmCONNECTEDALL: if ( (time(0) - m_tTimeoutTime) >= (CConfig::Instance()->GetAutoSearchInterval()) ) { if ( DoSearch(0) == false ) { SearchState(esTIMEOUT); } m_tTimeoutTime = time(0); } break; case esmPUBLIC: case esmBOOKMARK: bool b1,b2; // add new clients b1 = AddClients(); // remove disconnected clients b2 = RemoveClients(); if ( (b1 == false) && b2 ) { // search done SearchState(esTIMEOUT); m_tTimeoutTime = time(0); } break; default: break; } } return 0; } /** */ bool CSearchManager::AddClients() { if ( m_pHubList == 0 ) { return false; } if ( m_pHubList->Count() == m_nHubIndex ) { return false; } m_Mutex.Lock(); if ( m_pClientList == 0 ) { m_pClientList = new CList(); } while( m_pClientList->Count() < m_nMaxClients ) { if ( AddClient() == false ) { break; } } m_Mutex.UnLock(); return true; } /** */ bool CSearchManager::AddClient() { CSearchClient * client; // check for hublist done if ( m_pHubList->Next(&m_sCurrentHub) == 0 ) { DPRINTF("no new hubserver\n"); return false; } m_nHubIndex++; DPRINTF("add client: '%s'\n",m_sCurrentHub->Data()); if (m_sCurrentHub != 0) { CMessageLog * msglog = new CMessageLog(); msglog->sMessage += "Add client on "; msglog->sMessage += *m_sCurrentHub; //DPRINTF("%s\n", msglog->sMessage.Data()); if ( !SendObject(msglog) ) { delete msglog; } } //else //{ // DPRINTF("m_sCurrentHub == 0\n"); //} client = new CSearchClient(); // set default values for search client->m_tSearchTimeout = time(0); // client settings client->SetNick(CConfig::Instance()->GetSearchNick()); client->SetComment(CConfig::Instance()->GetDescription(!m_bEnableTag)); client->SetConnectionType(CConfig::Instance()->GetSpeed()); client->SetEMail(CConfig::Instance()->GetEMail()); client->SetShareSize(CFileManager::Instance()->GetShareSize()); client->SetMode(CConfig::Instance()->GetMode()); client->SetHandleUserList(m_bHandleUserList); client->SetHandleSearch(false); client->SetHandleMyinfo(false); client->SetHandleForceMove(false); client->SetHandleTransfer(false); client->SetCallBackFunction( new CCallback2( this, &CSearchManager::CallBackClient ) ); // SendDebug( "Start search on: [" + CString::number(m_nCurrentHub) + "] " + server ); // add client to client list m_pClientList->Add(client); // final connect client->Connect(*m_sCurrentHub); return true; } /** */ void CSearchManager::UpdateClients() { m_Mutex.Lock(); // sanity check if ( m_pClientList != 0 ) { CSearchClient * client = 0; // update all clients from the client list while ( ( (client = m_pClientList->Next(client)) != NULL) ) { client->Thread(); // connection timeout if ( (client->m_bSearchRemove == false) && (client->m_bSearchEnable == false) ) { if ( (time(0) - client->m_tSearchTimeout) >= SEARCH_CLIENT_TIMEOUT ) { DPRINTF("remove client timeout\n"); // remove client, connection timeout client->m_bSearchRemove = true; client->m_tSearchTimeout = 0; } } // send search else if ( client->m_bSearchEnable ) { if ( (time(0) - client->m_tSearchTimeout) >= (CConfig::Instance()->GetAutoSearchInterval()) ) { if ( DoSearch(client) == false ) { // no more searches client->m_bSearchEnable = false; client->m_bSearchRemove = true; } // update timeout client->m_tSearchTimeout = time(0); DPRINTF("search enabled\n"); } } } } m_Mutex.UnLock(); } /** */ bool CSearchManager::RemoveClients() { bool res; m_Mutex.Lock(); res = false; // sanity check if ( m_pClientList != 0 ) { CSearchClient * client = 0; // remove clients from the client list while ( ( (client = m_pClientList->Next(client)) != NULL) ) { if ( client->m_bSearchRemove ) { if ( client->m_tSearchTimeout == 0 ) { client->SetCallBackFunction(0); m_pClientList->Remove(client); delete client; client = 0; } // remove timeout else { if ( ((m_eClientMode == ecmACTIVE) && ((time(0) - client->m_tSearchTimeout) >= SEARCH_ACTIVE_CLIENT_REMOVE_TIMEOUT)) || ((m_eClientMode == ecmPASSIVE) && ((time(0) - client->m_tSearchTimeout) >= SEARCH_PASSIVE_CLIENT_REMOVE_TIMEOUT)) ) { client->m_tSearchTimeout = 0; client->Disconnect(true); } } } } // ready on empty client list if ( m_pClientList->Count() == 0 ) { res = true; } } else { res = true; } m_Mutex.UnLock(); return res; } /** */ void CSearchManager::DisconnectClients() { m_Mutex.Lock(); // sanity check if ( m_pClientList != 0 ) { CSearchClient * client = 0; // disconnect all clients while ( ( (client = m_pClientList->Next(client)) != NULL) ) { // disconnect client if ( (client->GetConnectionState() != estNONE) && (client->GetConnectionState() != estDISCONNECTING) ) { client->Disconnect(true); } } } m_Mutex.UnLock(); } /** send search to the client */ bool CSearchManager::DoSearch( CSearchClient * HubSearchClient ) { bool res = false; if ( HubSearchClient != 0 ) { // active search, get current search object m_pCurrentSearchObject = HubSearchClient->m_pCurrentSearchObject; } while ( (res == false) && ((m_pCurrentSearchObject=m_pSearchList->Next(m_pCurrentSearchObject)) != 0) ) { switch ( m_pCurrentSearchObject->m_eType ) { case DC_MESSAGE_SEARCH_USER: { CMessageSearchUser * msg = (CMessageSearchUser*)m_pCurrentSearchObject; if ( !HubSearchClient ) { CList list; DCHubObject * HubObject; CString s; if ( m_eSearchMode == esmCONNECTEDSINGLE ) { m_sCurrentHub = 0; if ( m_pHubList->Next(&m_sCurrentHub) != 0 ) s = *m_sCurrentHub; } if ( CConnectionManager::Instance()->IsUserOnline( msg->m_sNick, s, CString(), &list ) ) { HubObject = 0; while ( (HubObject=list.Next(HubObject)) != 0 ) { CMessageSearchResultUser * MessageSearchResultUser = new CMessageSearchResultUser(); MessageSearchResultUser->m_sHubName = HubObject->m_sHubName; MessageSearchResultUser->m_sNick = msg->m_sNick; if ( !SendObject(MessageSearchResultUser) ) delete MessageSearchResultUser; } list.Clear(); } } else { if ( HubSearchClient->UserList()->IsUserOnline( msg->m_sNick ) ) { CMessageSearchResultUser * MessageSearchResultUser = new CMessageSearchResultUser(); MessageSearchResultUser->m_sHubName = HubSearchClient->GetHubName(); MessageSearchResultUser->m_sNick = msg->m_sNick; if ( !SendObject(MessageSearchResultUser) ) delete MessageSearchResultUser; } } break; } case DC_MESSAGE_SEARCH_FILE: { CMessageSearchFile * msg = (CMessageSearchFile*)m_pCurrentSearchObject; if ( m_eSearchType == estyMULTI ) msg->m_bMulti = true; else msg->m_bMulti = false; DPRINTF("send search\n"); if ( HubSearchClient ) { HubSearchClient->SendSearch(msg); } else { if ( m_eSearchMode == esmCONNECTEDSINGLE ) { m_sCurrentHub = 0; if ( m_pHubList->Next(&m_sCurrentHub) != 0 ) { CConnectionManager::Instance()->SendSearchToConnectedServers(msg,*m_sCurrentHub); } } else { if ( SearchType() == estyEXTERNAL ) { m_CallbackMutex.Lock(); if ( m_pParentCallback != 0 ) { CMessageLog * log = new CMessageLog(); log->sMessage = "Auto search for \""; log->sMessage += msg->m_sString; log->sMessage += "\" on all connected hubs"; if ( m_pParentCallback->notify( log ) != 0 ) { delete log; } } m_CallbackMutex.UnLock(); } CConnectionManager::Instance()->SendSearchToConnectedServers(msg); } } res = true; break; } default: { break; } } } if ( HubSearchClient != 0 ) { // active search, set last search object HubSearchClient->m_pCurrentSearchObject = m_pCurrentSearchObject; } // check for last search if ( !m_pCurrentSearchObject ) res = false; else if ( !m_pSearchList->Next(m_pCurrentSearchObject) ) res = false; return res; } /** */ bool CSearchManager::SendObject( CDCMessage * dcmessage ) { bool res = false; if ( SearchType() == estyEXTERNAL ) { if ( dcmessage->m_eType == DC_MESSAGE_SEARCHRESULT ) { /* always returns false, ignore that */ CDownloadManager::Instance()->DLM_HandleSearch((CMessageSearchResult *)dcmessage); } /* otherwise CSearchSocket will print out "CallBack failed (state)..." */ delete dcmessage; res = true; } else { m_CallbackMutex.Lock(); if ( m_pParentCallback != 0 ) { if ( m_pParentCallback->notify( dcmessage ) == 0 ) res = true; } m_CallbackMutex.UnLock(); } return res; } /** */ bool CSearchManager::HandleSearch( CDCMessage * dcmessage ) { return SendObject(dcmessage); } /** */ int CSearchManager::CallBackSearchSocket( CMessageSearchResult * result ) { int err = -1; if ( SendObject(result) ) { err = 0; } return err; } /** */ int CSearchManager::CallBackClient( CClient * Client, CDCMessage * cmsg ) { CSearchClient * c = (CSearchClient*)Client; if ( (c == 0) || (cmsg == 0) ) { return -1; } switch ( cmsg->m_eType ) { case DC_MESSAGE_CONNECTION_STATE: { CMessageConnectionState *msg = (CMessageConnectionState*) cmsg; switch(msg->m_eState) { case estCONNECTED: { break; } case estSOCKETERROR: { DPRINTF("socket error\n"); m_nHubError++; break; } case estDISCONNECTED: { DPRINTF("disconnect\n"); c->m_bSearchRemove = true; c->m_tSearchTimeout = 0; } default: { break; } } break; } case DC_MESSAGE_VALIDATEDENIDE: { //SendDebug( "Validate denide " + c->GetIP() + CString(":") + CString::number(c->GetPort()) ); c->Disconnect(true); break; } case DC_MESSAGE_HUBISFULL: { //SendDebug( "Hub is full on " + c->GetIP() + CString(":") + CString::number(c->GetPort()) ); c->Disconnect(true); break; } case DC_MESSAGE_FORCEMOVE: { //SendDebug( "Force move on " + c->GetIP() + CString(":") + CString::number(c->GetPort()) ); c->Disconnect(true); break; } case DC_MESSAGE_MYINFO: { CMessageMyInfo * MessageMyInfo = (CMessageMyInfo *)cmsg; if ( MessageMyInfo->m_sNick == CConfig::Instance()->GetSearchNick() ) { DPRINTF("enable search\n"); c->m_bSearchEnable = true; c->m_tSearchTimeout = 0; } break; } default: break; } delete cmsg; return 0; } libdc0-0.3.24~svn3121/dclib/ccasefolder.h0000644000175000017500000000501311101144617016714 0ustar sikonsikon/*************************************************************************** ccasefolder.h - Get a case folded version of a string ------------------- begin : Thu Jul 17 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCASEFOLDER_H #define CCASEFOLDER_H /** * author Edward Sheldrake * * This class produces a case folded version of a string, required to * make comparisions / searching case insensitive. It does not matter * if it's uppercase, lowercase or some mixture, just that both strings * have been processed by the same algorithm. * * This does full case mapping and the output may be longer than the * input. * * The data is based on CaseFolding-5.1.0.txt from the Unicode Character * Database. * * This class appears to be necessary because the C function toupper() * does not handle UTF-8 and converting to wchar_t and using towupper() * also leaves all the accented characters unconverted. * * Other software: Shakespeer seems to have various unicode data * tables in it's source under splib/unicode-spec but DC++ relies * on CharLowerW on Windows and towlower() elsewhere. * * QT's QString class works entirely in unicode and has a toLower() * function that handles everything, not just ascii A-Z. */ #include #include #include class CCaseFolder { public: /** Constructor */ CCaseFolder(); /** Destructor */ ~CCaseFolder(); /** * Do the case folding. To reduce copying, a CString to put the * output in is a parameter. * * Returns true if everything suceeded. */ bool Fold( const CString & input, CString & output ); private: /** local to UCS-4 */ iconv_t to_ucs4; /** UCS-4 to local */ iconv_t from_ucs4; }; #endif // CCASEFOLDER_H libdc0-0.3.24~svn3121/dclib/cdcproto.cpp0000644000175000017500000003451211233301711016614 0ustar sikonsikon/*************************************************************************** cdcproto.cpp - description ------------------- begin : Sun Dec 15 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cdcproto.h" #include #include #ifndef WIN32 #include #else #include #include #endif #include #include "dcobject.h" // needed for remote encoding setting #include "cconfig.h" #include CDCProto::CDCProto( CString remote ) { CString from = "UTF-8"; if ( CConfig::Instance() != 0 ) { from = CConfig::Instance()->GetLocalEncoding(); if ( remote.IsEmpty() ) { remote = CConfig::Instance()->GetRemoteEncoding(); } } m_pLocalToRemote = new CIconv( from, remote ); m_pLocalToUTF8 = new CIconv( from, "UTF-8" ); } CDCProto::~CDCProto() { delete m_pLocalToRemote; m_pLocalToRemote = 0; delete m_pLocalToUTF8; m_pLocalToUTF8 = 0; } /** */ int CDCProto::SendChat( CString sNick, CString s ) { DCProtoMutex.Lock(); s = s.Replace( "$", "$"); s = s.Replace( "|", "|"); CString t = '<'; t += m_pLocalToRemote->encode(sNick); t += "> "; t += m_pLocalToRemote->encode(s); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendVersion() { DCProtoMutex.Lock(); const CString t = "$Version 1,0091|"; /* taken out to remove the confusion in some scripts reporting a version # of 0 Hopefully will prevent users from getting kicked for Hacked Clients. SMiLeaf t += sVersion; */ const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendMyInfo( CMessageMyInfo * myinfo ) { DCProtoMutex.Lock(); char c; CString t = "$MyINFO $ALL "; t += m_pLocalToRemote->encode(myinfo->m_sNick); t += ' '; t += m_pLocalToRemote->encode(myinfo->m_sComment); t += "$ $"; // ??? t += m_pLocalToRemote->encode(myinfo->m_sUserSpeed); if ( myinfo->m_eAwayMode == euamAWAY ) { c = emsfAway; } else { c = emsfNormal; } if ( myinfo->m_bServerFlag ) { c = c | emsfServer; } if ( myinfo->m_bFireballFlag ) { c = c | emsfFireball; } if ( myinfo->m_bTLSFlag ) { c = c | emsfTLS; } t += c; t += '$'; t += m_pLocalToRemote->encode(myinfo->m_sEMail); t += '$'; t += CString::number(myinfo->m_nShared); t += '$'; // share t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendKey( CString s ) { DCProtoMutex.Lock(); CString t = "$Key "; t += s; t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendValidateNick( CString sNick ) { DCProtoMutex.Lock(); CString t = "$ValidateNick "; t += m_pLocalToRemote->encode(sNick); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendMyNick( CString sNick, const CString & ref ) { DCProtoMutex.Lock(); CString t = "$MyNick "; t += m_pLocalToRemote->encode(sNick); t += "|$Lock EXTENDEDPROTOCOLABCABCABCABCABCABC Pk=DCGUI"; t += DCLIB_VERSION_STRING; t += "ABCABC Ref="; t += ref; t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick ) { DCProtoMutex.Lock(); CString t = "$To: "; t += m_pLocalToRemote->encode(sTo); t += " From: "; t += m_pLocalToRemote->encode(sNick); t += " $<"; if ( sFromNick.IsEmpty() ) t += m_pLocalToRemote->encode(sNick); else t += m_pLocalToRemote->encode(sFromNick); sMsg = sMsg.Replace( "$", "$"); sMsg = sMsg.Replace( "|", "|"); sMsg = m_pLocalToRemote->encode(sMsg); t += "> "; t += sMsg; t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::RequestNickList() { DCProtoMutex.Lock(); const CString t = "$GetNickList|"; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendDirection( eDirection Direction, int level ) { DCProtoMutex.Lock(); CString t = "$Direction "; if (Direction == edUPLOAD) t += "Upload"; else if (Direction == edDOWNLOAD) t += "Download"; t += ' '; t += CString::number(level); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendGet( CString file, ulonglong pos, ulonglong size ) { DCProtoMutex.Lock(); CString t = "$Get "; t += m_pLocalToRemote->encode(file); t += '$'; t += CString::number(pos); if ( size != 0 ) { t += '$'; t += CString::number(size); } t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendGetZBlock( CString file, ulonglong pos, ulonglong size ) { DCProtoMutex.Lock(); CString t = "$GetZBlock "; t += CString::number(pos); t += ' '; if (size == (ulonglong)-1) { t += "-1 "; } else { t += CString::number(size); t += ' '; } t += m_pLocalToRemote->encode(file); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** Send "$UGetBlock startPos numBytes fileNameInUTF8|" */ int CDCProto::SendUGetBlock( CString file, ulonglong pos, ulonglong size ) { DCProtoMutex.Lock(); CString t = "$UGetBlock "; t += CString::number(pos); t += ' '; if (size == (ulonglong)-1) { t += "-1 "; } else { t += CString::number(size); t += ' '; } t += m_pLocalToUTF8->encode(file); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** Send "$UGetZBlock startPos numBytes fileNameInUTF8|" */ int CDCProto::SendUGetZBlock( CString file, ulonglong pos, ulonglong size ) { DCProtoMutex.Lock(); CString t = "$UGetZBlock "; t += CString::number(pos); t += ' '; if (size == (ulonglong)-1) { t += "-1 "; } else { t += CString::number(size); t += ' '; } t += m_pLocalToUTF8->encode(file); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendRevConnectToMe( CString sNick, CString sDstNick ) { DCProtoMutex.Lock(); CString t = "$RevConnectToMe "; t += m_pLocalToRemote->encode(sNick); t += ' '; t += m_pLocalToRemote->encode(sDstNick); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendSend() { DCProtoMutex.Lock(); const CString t = "$Send|"; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendError( CString message ) { DCProtoMutex.Lock(); CString t = "$Error "; t += m_pLocalToRemote->encode(message); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendFileLength( ulonglong len ) { DCProtoMutex.Lock(); CString t = "$FileLength "; t += CString::number(len); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendListLen( ulonglong len ) { DCProtoMutex.Lock(); CString t = "$ListLen "; t += CString::number(len); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendGetListLen() { DCProtoMutex.Lock(); const CString t = "$GetListLen|"; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendConnectToMe( CString sDstNick, CString host, bool crypto ) { DCProtoMutex.Lock(); CString t = "$ConnectToMe "; t += m_pLocalToRemote->encode(sDstNick); t += ' '; t += host; if ( crypto ) { t += 'S'; } t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendCanceled() { DCProtoMutex.Lock(); const CString t = "$Canceled|"; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** send string */ int CDCProto::SendString( CString message, bool encode ) { DCProtoMutex.Lock(); int err; if ( encode ) { CString enc = m_pLocalToRemote->encode(message); err = Write((const unsigned char*)enc.Data(),enc.Length()); } else { err = Write((const unsigned char*)message.Data(),message.Length()); } DCProtoMutex.UnLock(); return err; } /** send password */ int CDCProto::SendPass( CString pass ) { DCProtoMutex.Lock(); CString t = "$MyPass "; t += pass; t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** operator kick */ int CDCProto::SendKick( CString nick ) { DCProtoMutex.Lock(); CString t = "$Kick "; t += m_pLocalToRemote->encode(nick); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** operator force move a user */ int CDCProto::SendOpForceMove( CString nick, CString host, CString message ) { DCProtoMutex.Lock(); CString t = "$OpForceMove $Who:"; t += m_pLocalToRemote->encode(nick); t += "$Where:"; t += host; t += "$Msg:"; t += m_pLocalToRemote->encode(message); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendMaxedOut() { DCProtoMutex.Lock(); const CString t = "$MaxedOut|"; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendGetInfo( CString sNick, CString sMyNick ) { DCProtoMutex.Lock(); CString t = "$GetINFO "; t += m_pLocalToRemote->encode(sNick); t += ' '; t += m_pLocalToRemote->encode(sMyNick); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendSupports( std::vector & supported, bool shuffle ) { DCProtoMutex.Lock(); CString t = "$Supports "; if ( shuffle ) { random_shuffle( supported.begin(), supported.end() ); } for ( std::vector::const_iterator it = supported.begin(); it != supported.end(); ++it ) { t += *it; t += ' '; } t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** */ int CDCProto::SendSearch( CMessageSearchFile * msg ) { DCProtoMutex.Lock(); CString s; if ( msg->m_bLocal ) { s = "$Search Hub:"; } else if ( msg->m_bMulti ) { s = "$MultiSearch "; } else { s = "$Search "; } s += m_pLocalToRemote->encode(msg->m_sSource); s += " "; if ( msg->m_bSizeLimit == false ) s += "F?"; else s += "T?"; if ( msg->m_eSizeType == esstATMOST ) s += "T?"; else s += "F?"; s += CString::number(msg->m_nSize); s += '?'; s += CString::number(msg->m_eFileType); s += '?'; if ( msg->m_eFileType == eftHASH ) { s += "TTH:"; /* a Base32 TTH does not need encoding or escaping */ s += msg->m_sString; } else { s += m_pLocalToRemote->encode(msg->m_sString.Replace("$","$").Replace("|","|").Replace(' ',"$")); } s += '|'; const int err = Write((const unsigned char*)s.Data(),s.Length()); DCProtoMutex.UnLock(); return err; } /** $Sending numBytes| */ int CDCProto::SendSending( ulonglong length ) { DCProtoMutex.Lock(); CString t = "$Sending "; t += CString::number(length); t += '|'; const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** $ADCGET file TTH/PPUROLR2WSYTGPLCM3KV4V6LJC36SCTFQJFDJKA 0 1154 ZL1| */ int CDCProto::SendADCGet( eADCType type, CString tth, ulonglong pos, long long size, bool zlib, CString file ) { DCProtoMutex.Lock(); CString t = "$ADCGET "; switch ( type ) { case eAdcFile: t += "file "; break; case eAdcTTHL: t += "tthl "; break; case eAdcList: t += "list "; break; default: DCProtoMutex.UnLock(); return -1; } if ( tth.IsEmpty() ) { // escape spaces file = file.Replace( " ", "\\ " ); t += m_pLocalToUTF8->encode(file); } else { t += "TTH/"; t += tth; } t += ' '; t += CString::number(pos); t += ' '; t += CString::number(size); if (zlib) { t += " ZL1"; } t += '|'; //printf("Sending ADCGet: %s\n", t.Data()); const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } /** $ADCSND file TTH/PPUROLR2WSYTGPLCM3KV4V6LJC36SCTFQJFDJKA 0 1154 ZL1|*/ int CDCProto::SendADCSnd( eADCType type, CString tth, ulonglong pos, long long size, bool zlib, CString file ) { DCProtoMutex.Lock(); CString t = "$ADCSND "; switch ( type ) { case eAdcFile: t += "file "; break; case eAdcTTHL: t += "tthl "; break; case eAdcList: t += "list "; break; default: DCProtoMutex.UnLock(); return -1; } if ( tth.IsEmpty() ) { // escape spaces file = file.Replace( " ", "\\ " ); t += m_pLocalToUTF8->encode(file); } else { t += "TTH/"; t += tth; } t += ' '; t += CString::number(pos); t += ' '; t += CString::number(size); if (zlib) { t += " ZL1"; } t += '|'; //printf("Sending ADCSnd: %s\n", t.Data()); const int err = Write((const unsigned char*)t.Data(),t.Length()); DCProtoMutex.UnLock(); return err; } libdc0-0.3.24~svn3121/dclib/cconfig.h0000644000175000017500000011013311233301711016046 0ustar sikonsikon/*************************************************************************** cconfig.h - description ------------------- begin : Tue May 14 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCONFIG_H #define CCONFIG_H /** *@author Mathias Küster * * This stores all of dclib's settings and also the list of bookmarked * and public hubs. * * The main problem with the config handling is that adding anything * requires adding more functions, plus writing out the config files * erases any previous settings, including anything not known to * this version of dclib. */ #include #include #include #include #include #include #include #define DCGUI_CHATLOG_PATH "chatlog" #define DCGUI_PLUGINCONFIG_PATH "plugin" #define DCGUI_IMAGE_PATH "image" #define DCGUI_FILELIST_PATH "filelist" #include #include #include class CConfig; class CXml; class DCConfigHubProfile { public: /** */ DCConfigHubProfile() { m_bComment = false; m_bEMail = false; m_bAutoConnect = false; m_bSSL = false; m_bTag = true; m_bExtHubCount = true; }; /** */ DCConfigHubProfile( DCConfigHubProfile * p ) { m_sName = p->m_sName; m_sPassword = p->m_sPassword; m_sNick = p->m_sNick; m_sComment = p->m_sComment; m_sEMail = p->m_sEMail; m_sRemoteEncoding = p->m_sRemoteEncoding; m_sSuppressedNicks = p->m_sSuppressedNicks; m_bComment = p->m_bComment; m_bEMail = p->m_bEMail; m_bAutoConnect = p->m_bAutoConnect; m_bSSL = p->m_bSSL; m_bTag = p->m_bTag; m_bExtHubCount = p->m_bExtHubCount; }; /** */ ~DCConfigHubProfile() {}; /** profile name */ CString m_sName; /** password */ CString m_sPassword; /** nick */ CString m_sNick; /** comment */ CString m_sComment; /** email */ CString m_sEMail; /** Remote encoding setting, to override global setting */ CString m_sRemoteEncoding; /** Regexp of nicks to not open chat windows for */ CString m_sSuppressedNicks; /** use comment */ bool m_bComment; /** use email */ bool m_bEMail; /** auto connect on startup */ bool m_bAutoConnect; /** ssl hub */ bool m_bSSL; /** tag */ bool m_bTag; /** If true, use H:3/2/1, if false, use H:6 */ bool m_bExtHubCount; }; /* small number of profiles, sorted map is fine */ typedef std::map HubProfileMap; class DCConfigHubItem { /* so CConfig can change m_nPosition but nothing else can */ friend class CConfig; public: /** */ DCConfigHubItem() { m_nID = 0; m_nUserCount = 0; m_nShared = 0; m_nMinShare = 0; m_nPosition = -1; }; /** */ DCConfigHubItem( DCConfigHubItem * p ) { m_nID = p->m_nID; m_sProfile = p->m_sProfile; m_sName = p->m_sName; m_sHost = p->m_sHost; m_sDescription = p->m_sDescription; m_nUserCount = p->m_nUserCount; m_sCountry = p->m_sCountry; m_sExtra = p->m_sExtra; m_nShared = p->m_nShared; m_nMinShare = p->m_nMinShare; m_nPosition = p->m_nPosition; }; /** */ ~DCConfigHubItem() {}; /** the hub identify like mldonkey only used by http plugin */ unsigned long m_nID; /** hubname */ CString m_sName; /** hub host */ CString m_sHost; /** hub description */ CString m_sDescription; /** user count */ ulonglong m_nUserCount; /** profile name */ CString m_sProfile; /** geographic location of the hub */ CString m_sCountry; /** total shared on the hub */ ulonglong m_nShared; /** minimum share allowed for entry */ ulonglong m_nMinShare; /** any extra xml fields in the form Key=Value */ CString m_sExtra; private: /* user changeable order in bookmark list */ int m_nPosition; }; typedef std::map OrderedBookmarkMap; class DCConfigHubListUrl { public: /** */ DCConfigHubListUrl() { bEnabled = false; }; /** */ ~DCConfigHubListUrl() {}; /** */ CString sUrl; /** */ bool bEnabled; }; class DCConfigShareFolder { public: /** */ DCConfigShareFolder() {}; /** */ ~DCConfigShareFolder() {}; /** */ CString m_sPath; /** */ CString m_sAlias; }; class CByteArray; class DCTransferQueueObject; class DCFileChunkObject; class CConfig : public CSingleton { public: /** */ CConfig( CString configpath = CString() ); /** */ virtual ~CConfig(); /** */ int LoadDCLib(); /** */ int SaveDCLib(); /** */ void ParseDCLibConfig( CXml * xml ); /** */ int LoadDCTra( CStringList > * queue, CStringList * chunks ); /** */ int SaveDCTra( CStringList > * queue, CStringList * chunks ); /** Get plugin folder */ CString GetDCLibPluginPath() const; /** Set plugin folder */ void SetDCLibPluginPath( CString s ); /** */ CString ParseVersion( CString s ); /** */ CString GetListenHostString(); /** */ CString GetTCPHostString( bool addport = true, bool crypt = false ); /** */ CString GetUDPHostString( bool addport = true ); /** */ bool GetAutoRecreateShareList() const; /** */ void SetAutoRecreateShareList( bool b ); /** */ int GetDownloadQueueTime() const; /** */ void SetDownloadQueueTime( int i ); /** */ CString GetEMail( bool raw = false ); /** */ void SetEMail( CString email ); /** */ CString GetNick() const; /** */ void SetNick( CString nick ); /** */ CString GetNick( CString hubname, CString hubhost ); /** */ CString GetSearchNick() const; /** */ void SetSearchNick( CString searchnick ); /** */ CString GetAwayMessage() const; /** */ void SetAwayMessage( CString s ); /** */ CString GetFloodOpKickMessage() const; /** */ void SetFloodOpKickMessage( CString s ); /** */ CString GetDownloadFolder() const; /** */ void SetDownloadFolder( CString downloadfolder ); /** */ CString GetDownloadFinishedFolder() const; /** */ void SetDownloadFinishedFolder( CString s ); /** */ bool GetTransferAutoSearch() const; /** */ void SetTransferAutoSearch( bool b ); /** */ bool GetCreateFile() const; /** */ void SetCreateFile( bool b ); /** */ eClientMode GetMode( bool setting = false ); /** */ void SetMode( eClientMode mode ); /** */ CString GetDescription( bool raw = false, CString hubname = CString(), CString hubhost = CString() ); /** */ void SetDescription( CString description ); /** */ bool GetDescriptionTag() const; /** */ void SetDescriptionTag( bool b ); /** */ CString GetAwayPrefix() const; /** */ void SetAwayPrefix( CString s ); /** */ CString GetSpeed() const; /** */ void SetSpeed( CString speed ); /** */ int GetTCPListenPort() const; /** */ void SetTCPListenPort( int port ); /** Get listen port for fully encrypted transfers */ int GetCryptoListenPort() const; /** Set listen port for fully encrypted transfers */ void SetCryptoListenPort( int port ); /** */ int GetUDPListenPort() const; /** */ void SetUDPListenPort( int port ); /** */ CString GetHost() const; /** */ void SetHost( CString host ); /** */ CString GetListenHost() const; /** */ void SetListenHost( CString host ); /** */ bool GetAntiSpam() const; /** */ void SetAntiSpam( bool antispam ); /** */ bool GetExternalIP() const; /** */ void SetExternalIP( bool b ); /** */ int GetMaxUpload() const; /** */ void SetMaxUpload( int maxupload ); /** */ int GetUserUploadSlots() const; /** */ void SetUserUploadSlots( int i ); /** */ virtual void SetAwayMode( eUserAwayMode mode ); /** */ eUserAwayMode GetAwayMode() const; /** */ long GetSharedFolders( CList * list ); /** */ void SetSharedFolders( CList * list ); /** */ bool GetLogFile() const; /** */ void SetLogFile( bool logfile ); /** True if we should log finished downloads */ bool GetLogFinishedDownloads() const; /** Set to true to log finished downloads */ void SetLogFinishedDownloads( bool logdl ); /** True if we should log finished uploads */ bool GetLogFinishedUploads() const; /** Set to true to log finished uploads */ void SetLogFinishedUploads( bool logul ); /** True if we should log the details in the log tab */ bool GetLogDetails() const; /** Set to true to log details in the log tab */ void SetLogDetails( bool logdet ); /** */ CString GetLogFileName() const; /** */ void SetLogFileName( CString logfile ); /** */ bool GetSendMessageOnActiveModeRequest() const; /** */ void SetSendMessageOnActiveModeRequest( bool b ); /** */ CString GetLogPath() const { return sConfigPath; }; /** */ CString GetImagePath() const { return sConfigPath+DCGUI_IMAGE_PATH+DIRSEPARATOR; }; /** */ CString GetConfigPath() const { return sConfigPath; }; /** */ CString GetChatLogPath() const { return sConfigPath+DCGUI_CHATLOG_PATH+DIRSEPARATOR; }; /** */ CString GetPluginConfigPath() const { return sConfigPath+DCGUI_PLUGINCONFIG_PATH+DIRSEPARATOR; }; /** */ CString GetFileListPath() const { return sConfigPath+DCGUI_FILELIST_PATH+DIRSEPARATOR; }; /** */ int LoadDCHub(); /** */ int SaveDCHub(); /** */ int SaveDCPublicHub(); /** */ int SaveDCBookHub(); /** */ void ParseDCHubConfig( CXml * xml ); /** */ void ParseDCBookHubConfig( CXml * xml ); /** */ long GetBookmarkHubList( CList * list ); /** */ CStringList * GetBookmarkHubServerList(); /** */ bool RemoveBookmarkHub( CString name, CString host, CString description ); /** */ bool AddBookmarkHub( CString name, CString host, CString description ); /** */ bool UpdateBookmarkHub( CString name, CString host, CString description ); /** * Move a bookmark in the ordered list. * The bookmark at oldpos is moved to newpos and * the bookmark at newpos is moved to oldpos. * The bookmarks must be next to each other. */ bool MoveBookmarkHub( int oldpos, int newpos ); /** * Re-order all the bookmarks. */ bool ReorderBookmarkHubs( const std::vector & newpositions ); /** */ bool SetBookmarkHubProfile( CString name, CString profile ); /** */ bool GetBookmarkHubProfile( CString name, CString host, DCConfigHubProfile * p ); /** */ long GetPublicHubList( CList * list ); /** */ long GetPublicHubListSize() const; /** */ CStringList * GetPublicHubServerList(); /** */ bool GetBookmarkHub( CString name, DCConfigHubItem * hubitem ); /** */ bool GetBookmarkHub( unsigned long id, DCConfigHubItem * hubitem ); /** */ bool GetPublicHub( CString name, DCConfigHubItem * hubitem ); /** */ bool GetPublicHub( unsigned long id, DCConfigHubItem * hubitem ); /** */ bool RemovePublicHub( CString name, CString host, CString description ); /** */ bool AddPublicHub( const CString & name, const CString & host, const CString & description, const ulonglong usercount, const CString country = CString(), const ulonglong shared = 0, const ulonglong minshare = 0, const CString extra = CString() ); /** */ void ClearPublicHubList(); /** */ long GetHubListUrlList( CList * list ); /** */ void SetHubListUrlList( CList * list ); /** */ bool AddHubProfile( DCConfigHubProfile * p ); /** */ bool DelHubProfile( CString name ); /** */ bool GetHubProfile( CString name, DCConfigHubProfile * p ); /** */ bool SaveHubProfile(); /** */ bool LoadHubProfile(); /** */ std::list * GetHubProfileNames(); /** */ int GetReloadHubListTime() const; /** */ void SetReloadHubListTime( int i ); /** */ int GetRecreateShareListTime() const; /** */ void SetRecreateShareListTime( int i ); /** */ bool GetHubListStoreLocal() const; /** */ void SetHubListStoreLocal( bool b ); /** */ int GetReconnectCount() const; /** */ void SetReconnectCount( int reconnectcount ); /** */ int GetReconnectTimeout() const; /** */ void SetReconnectTimeout( int reconnecttimeout ); /** */ bool GetCheckPrivateAddressSpace() const; /** */ void SetCheckPrivateAddressSpace( bool b ); /** get allow private address space only */ bool GetPrivateAddressSpaceOnly() const; /** set allow private address space only */ void SetPrivateAddressSpaceOnly( bool b ); /** */ int GetTransferResendTimeout() const; /** */ void SetTransferResendTimeout( int i ); /** */ int GetTransferResponseTimeout() const; /** */ void SetTransferResponseTimeout( int i ); /** */ eCloseType GetHubOfflineTransferClose() const; /** set the reaction on leaving hub */ void SetHubOfflineTransferClose( eCloseType ect ); /** */ bool GetForceMoveEnabled() const; /** */ void SetForceMoveEnabled( bool forcemoveenabled ); /** */ ulonglong GetMaxUploadRate() const; /** */ void SetMaxUploadRate( ulonglong n ); /** */ ulonglong GetMaxDownloadRate() const; /** */ void SetMaxDownloadRate( ulonglong n ); /** */ bool GetDynamicUploadRate() const; /** */ void SetDynamicUploadRate( bool b ); /** * Open extra slots if total upload rate is less than this. * Rate is in bytes/second. * 0 is special value to disable. */ ulonglong GetExtraSlotsRate() const; /** * Set rate for open extra slots. * Rate is in bytes/second. * 0 is special value to disable. */ void SetExtraSlotsRate( ulonglong n ); /** * Get maximum number of extra slots to open when upload rate is slow. * 0 will also disable this feature. */ int GetMaxExtraSlots() const; /** * Set maximum number of extra slots to open when upload rate is slow. * 0 will also disable this feature. */ void SetMaxExtraSlots( int n ); /** */ bool GetChatSendToOffline() const; /** */ void SetChatSendToOffline( bool b ); /** */ bool GetChatRecvFromOffline() const; /** */ void SetChatRecvFromOffline( bool b ); /** */ CString GetTransferCert() const; /** */ void SetTransferCert( CString s ); /** */ CString GetTransferKey() const; /** */ void SetTransferKey( CString s ); /** Get old dclib specific ssl mode support */ bool GetOldSSLSupport() const; /** Set old dclib specific ssl mode support */ void SetOldSSLSupport( bool b ); /** */ bool GetDisableHashList() const; /** */ void SetDisableHashList( bool b ); /** */ bool GetCompressedTransfers() const; /** */ void SetCompressedTransfers( bool b ); /** Get the time in seconds between auto searches */ long GetAutoSearchInterval() const; /** Set the time, in seconds, between auto searches */ void SetAutoSearchInterval( long seconds ); /** Get the maximum size of file to give MiniSlots for */ ulonglong GetSmallFileSize() const; /** Set the maximum size of file to give MiniSlots for */ void SetSmallFileSize( ulonglong s ); /** If true, use H:3/2/1, if false, use H:6 */ bool GetUseExtendedHubCount() const; /** */ void SetUseExtendedHubCount( bool b ); /** If true, do not share files/folders starting with "."*/ bool GetDontShareDotFiles() const; /** */ void SetDontShareDotFiles( bool b ); /** Get remote encoding setting */ CString GetRemoteEncoding() const; /** Get remote encoding for the given hub, falling back to global setting */ CString GetRemoteEncoding( CString hubname, CString hubhost ); /** Get local operating system encoding*/ CString GetLocalEncoding() const; /** Set remote encoding setting */ void SetRemoteEncoding( CString name ); /** If true, use IP provided by UserIP2 */ bool GetUserIP2Enabled() const; /** Set if the IP provided by UserIP2 will be used */ void SetUserIP2Enabled( bool b ); /** Get ZPipe support enabled - currently ZPipe0 */ bool GetZPipeEnabled() const; /** Set ZPipe support enabled - currently ZPipe0 */ void SetZPipeEnabled( bool b ); /** Get session starting value of total downloaded */ ulonglong GetStartDownloaded() const; /** Get session starting value of total uploaded */ ulonglong GetStartUploaded() const; /** Reset session totals to zero */ void ResetSessionStats(); /** Get read file buffer size */ long GetReadFileBufferSize() const; /** Set read file buffer size */ void SetReadFileBufferSize( long newsize ); /** Get disable ADCGet when hash list is disabled */ bool GetDisableADCGetWithoutTTH() const; /** Set disable ADCGet when hash list is disabled */ void SetDisableADCGetWithoutTTH( bool b ); /** Get disable XML list when hash list is disabled */ bool GetDisableXMLListWithoutTTH() const; /** Set disable XML list when hash list is disabled */ void SetDisableXMLListWithoutTTH( bool b ); /** Get enable obsolete protocol extensions */ bool GetEnableObsoleteExt() const; /** Set enable obsolete protocol extensions */ void SetEnableObsoleteExt( bool b ); /** Get shuffle support strings */ bool GetShuffleSupports() const; /** Set shuffle support strings */ void SetShuffleSupports( bool shuffle ); /** Really a valknut setting, if true shows hub commands in the menus */ bool GetEnableUserCommand() const; /** Really a valknut setting, if true shows hub commands in the menus */ void SetEnableUserCommand( bool b ); /** Get minimum segment size in bytes */ ulonglong GetMinSegSize() const; /** Set minimum segment size in bytes */ void SetMinSegSize( ulonglong bytes ); /** */ CString AliasToPath( CString file ); private: /** */ CString sEMail; /** */ CString sNick; /** */ CString sSearchNick; /** */ CString sAwayMessage; /** */ CString sFloodOpKickMessage; /** */ CString sDownloadFolder; /** */ CString sDownloadFinishedFolder; /** */ eClientMode eMode; /** */ CString sDescription; /** */ CString sAwayPrefix; /** */ bool bDescriptionTag; /** */ CString sSpeed; /** */ int iTCPListenPort; /** Port for fully encrypted transfers */ int iCryptoListenPort; /** */ int iUDPListenPort; /** */ CString m_sHost; /** */ CString m_sHostCache; /** */ CString m_sListenHost; /** */ time_t m_tHostTimeout; /** */ CString m_sTransferCert; /** */ CString m_sTransferKey; /** */ bool bAntiSpam; /** */ bool bLogFile; /** */ bool bLogFinishedDownloads; /** */ bool bLogFinishedUploads; /** */ bool bLogDetails; /** */ bool bCheckPrivateAddressSpace; /** */ bool bPrivateAddressSpaceOnly; /** */ CString sLogFile; /** */ bool m_bExternalIP; /** */ bool bSendMessageOnActiveModeRequest; /** */ int iMaxUpload; /** */ int iUserUploadSlots; /** */ ulonglong lMaxDownloadRate; /** */ ulonglong lMaxUploadRate; /** */ int iReconnectCount; /** */ int iReconnectTimeout; /** */ int iTransferResendTimeout; /** */ int iTransferResponseTimeout; /** */ eCloseType eHubOfflineTransferClose; /** */ bool bForceMoveEnabled; /** */ bool bHubListStoreLocal; /** */ eUserAwayMode eAwayMode; /** */ CList SharedFolders; /** */ bool bAutoRecreateShareList; /** Bookmark hubs, in order */ OrderedBookmarkMap * pOrderedBookmarks; /** */ CStringList * pBookmarkHubList; /** */ CStringList * pBookmarkHubList_HostIndex; /** */ CStringList * pPublicHubList; /** */ CStringList * pPublicHubList_HostIndex; /** */ HubProfileMap * pHubProfileMap; /** */ CList pHubListUrlList; /** */ int iDownloadQueueTime; /** Plugin folder */ CString m_sDCLibPluginPath; /** */ bool bDynamicUploadRate; /** */ bool bChatSendToOffline; /** */ bool bChatRecvFromOffline; /** */ bool bTransferAutoSearch; /** */ unsigned long m_nPublicHubID; /** */ unsigned long m_nBookHubID; /** */ int m_nReloadHubListTime; /** */ int m_nRecreateShareListTime; /** */ bool m_bCreateFile; /** */ bool m_bDisableHashList; /** True if compressed transfers are enabled */ bool m_bCompressedTransfers; /** The time in seconds between auto searches */ long m_nAutoSearchInterval; /** The maximum size of files for which MiniSlots are granted */ ulonglong m_nSmallFileSize; /** If true, use H:3/2/1, if false, use H:6 */ bool m_bUseExtendedHubCount; /** If true, don't share files and folders starting with "." */ bool m_bDontShareDotFiles; /** The remote text encoding */ CString m_sRemoteEncoding; /** The local system encoding */ CString m_sLocalEncoding; /** If true, use the IP address provided by the hub via UserIP2 */ bool m_bUserIP2Enabled; /** If true, enable ZPipe support - currently ZPipe0 */ bool m_bEnableZPipe; /** Session starting value of total downloaded */ ulonglong m_nStartDownloaded; /** Session starting value of total uploaded */ ulonglong m_nStartUploaded; /** Size of each file read when uploading */ long m_nReadFileBufferSize; /** Disable ADCGet support when hash list is disabled */ bool m_bDisableADCGetWithoutTTH; /** Disable XML filelist support when hash list is disabled */ bool m_bDisableXMLListWithoutTTH; /** Enable obsolete CHUNK BZList GetZBlock SSL */ bool m_bEnableObsoleteExt; /** Randomize order of $Supports strings */ bool m_bShuffleSupports; /** If true valknut will show hub commands in the menus */ bool m_bEnableUserCommand; /** Enable support for dclib <= 0.3.18 ssl transfers */ bool m_bOldSSLSupport; /** Miminum segment size in bytes */ ulonglong m_nMinSegSize; /** When uploading below this total rate open extra slots */ ulonglong m_nExtraSlotsRate; /** Open maximum of this many extra slots */ int m_nMaxExtraSlots; protected: /** */ CMutex m_Mutex; /** */ CString sConfigPath; }; /** inline functions */ /** */ inline void CConfig::SetEMail( CString email ) { m_Mutex.Lock(); sEMail = email; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetNick() const { return sNick.Replace(' ',"\xa0"); } /** */ inline void CConfig::SetNick( CString nick ) { m_Mutex.Lock(); sNick = nick; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetSearchNick() const { return sSearchNick.Replace(' ',"\xa0"); } /** */ inline void CConfig::SetSearchNick( CString searchnick ) { m_Mutex.Lock(); sSearchNick = searchnick; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetAwayMessage() const { return sAwayMessage; } /** */ inline void CConfig::SetAwayMessage( CString s ) { m_Mutex.Lock(); sAwayMessage = s; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetFloodOpKickMessage() const { return sFloodOpKickMessage; } /** */ inline void CConfig::SetFloodOpKickMessage( CString s ) { m_Mutex.Lock(); sFloodOpKickMessage = s; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetDownloadFolder() const { return sDownloadFolder; } /** */ inline void CConfig::SetDownloadFolder( CString downloadfolder ) { m_Mutex.Lock(); sDownloadFolder = downloadfolder; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetDownloadFinishedFolder() const { return sDownloadFinishedFolder; } /** */ inline void CConfig::SetDownloadFinishedFolder( CString s ) { m_Mutex.Lock(); sDownloadFinishedFolder = s; m_Mutex.UnLock(); } /** */ inline void CConfig::SetMode( eClientMode mode ) { m_Mutex.Lock(); eMode = mode; m_Mutex.UnLock(); } /** */ inline void CConfig::SetDescription( CString description ) { m_Mutex.Lock(); sDescription = description; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetDescriptionTag() const { return bDescriptionTag; } /** */ inline void CConfig::SetDescriptionTag( bool b ) { m_Mutex.Lock(); bDescriptionTag = b; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetSpeed() const { return sSpeed; } /** */ inline void CConfig::SetSpeed( CString speed ) { m_Mutex.Lock(); sSpeed = speed; m_Mutex.UnLock(); } /** */ inline int CConfig::GetTCPListenPort() const { return iTCPListenPort; } /** */ inline void CConfig::SetTCPListenPort( int port ) { m_Mutex.Lock(); iTCPListenPort = port; m_Mutex.UnLock(); } /** */ inline int CConfig::GetCryptoListenPort() const { return iCryptoListenPort; } /** */ inline void CConfig::SetCryptoListenPort( int port ) { m_Mutex.Lock(); iCryptoListenPort = port; m_Mutex.UnLock(); } /** */ inline int CConfig::GetUDPListenPort() const { return iUDPListenPort; } /** */ inline void CConfig::SetUDPListenPort( int port ) { m_Mutex.Lock(); iUDPListenPort = port; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetHost() const { return m_sHost; } /** */ inline CString CConfig::GetListenHost() const { return m_sListenHost; } /** */ inline void CConfig::SetListenHost( CString host ) { m_Mutex.Lock(); m_sListenHost = host; m_sHostCache = ""; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetAntiSpam() const { return bAntiSpam; } /** */ inline void CConfig::SetAntiSpam( bool antispam ) { m_Mutex.Lock(); bAntiSpam = antispam; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetExternalIP() const { return m_bExternalIP; } /** */ inline void CConfig::SetExternalIP( bool b ) { m_Mutex.Lock(); m_bExternalIP = b; m_Mutex.UnLock(); } /** */ inline int CConfig::GetMaxUpload() const { return iMaxUpload; } /** */ inline void CConfig::SetMaxUpload( int maxupload ) { m_Mutex.Lock(); iMaxUpload = maxupload; m_Mutex.UnLock(); } /** */ inline int CConfig::GetUserUploadSlots() const { return iUserUploadSlots; } /** */ inline void CConfig::SetUserUploadSlots( int i ) { m_Mutex.Lock(); iUserUploadSlots = i; m_Mutex.UnLock(); } /** */ inline ulonglong CConfig::GetMaxUploadRate() const { if ( lMaxUploadRate < 512 ) return 0; return lMaxUploadRate; } /** */ inline void CConfig::SetMaxUploadRate( ulonglong n ) { m_Mutex.Lock(); if ( n < 512 ) n = 0; lMaxUploadRate = n; m_Mutex.UnLock(); } /** */ inline ulonglong CConfig::GetMaxDownloadRate() const { return lMaxDownloadRate; } /** */ inline void CConfig::SetMaxDownloadRate( ulonglong n ) { m_Mutex.Lock(); lMaxDownloadRate = n; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetDynamicUploadRate() const { return bDynamicUploadRate; } /** */ inline void CConfig::SetDynamicUploadRate( bool b ) { m_Mutex.Lock(); bDynamicUploadRate = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetHubListStoreLocal() const { return bHubListStoreLocal; } /** */ inline void CConfig::SetHubListStoreLocal( bool b ) { m_Mutex.Lock(); bHubListStoreLocal = b; m_Mutex.UnLock(); } /** */ inline int CConfig::GetReconnectCount() const { return iReconnectCount; } /** */ inline void CConfig::SetReconnectCount( int reconnectcount ) { m_Mutex.Lock(); iReconnectCount = reconnectcount; m_Mutex.UnLock(); } /** */ inline int CConfig::GetReconnectTimeout() const { return iReconnectTimeout; } /** */ inline void CConfig::SetReconnectTimeout( int reconnecttimeout ) { m_Mutex.Lock(); iReconnectTimeout = reconnecttimeout; m_Mutex.UnLock(); } /** */ inline int CConfig::GetTransferResendTimeout() const { return iTransferResendTimeout; } /** */ inline void CConfig::SetTransferResendTimeout( int i ) { m_Mutex.Lock(); iTransferResendTimeout = i; m_Mutex.UnLock(); } /** */ inline int CConfig::GetTransferResponseTimeout() const { return iTransferResponseTimeout; } /** */ inline void CConfig::SetTransferResponseTimeout( int i ) { m_Mutex.Lock(); iTransferResponseTimeout = i; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetForceMoveEnabled() const { return bForceMoveEnabled; } /** */ inline void CConfig::SetForceMoveEnabled( bool forcemoveenabled ) { m_Mutex.Lock(); bForceMoveEnabled = forcemoveenabled; m_Mutex.UnLock(); } /** */ inline eUserAwayMode CConfig::GetAwayMode() const { return eAwayMode; } /** */ inline int CConfig::GetDownloadQueueTime() const { return iDownloadQueueTime; } /** */ inline void CConfig::SetDownloadQueueTime( int i ) { m_Mutex.Lock(); iDownloadQueueTime = i; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetSendMessageOnActiveModeRequest() const { return bSendMessageOnActiveModeRequest; } /** */ inline void CConfig::SetSendMessageOnActiveModeRequest( bool b ) { m_Mutex.Lock(); bSendMessageOnActiveModeRequest = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetLogFile() const { return bLogFile; } /** */ inline void CConfig::SetLogFile( bool logfile ) { m_Mutex.Lock(); bLogFile = logfile; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetLogFinishedDownloads() const { return bLogFinishedDownloads; } /** */ inline void CConfig::SetLogFinishedDownloads( bool logdl ) { m_Mutex.Lock(); bLogFinishedDownloads = logdl; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetLogFinishedUploads() const { return bLogFinishedUploads; } /** */ inline void CConfig::SetLogFinishedUploads( bool logul ) { m_Mutex.Lock(); bLogFinishedUploads = logul; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetLogDetails() const { return bLogDetails; } /** */ inline void CConfig::SetLogDetails( bool logdet ) { m_Mutex.Lock(); bLogDetails = logdet; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetLogFileName() const { return sLogFile; } /** */ inline void CConfig::SetLogFileName( CString logfile ) { m_Mutex.Lock(); sLogFile = logfile; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetCheckPrivateAddressSpace() const { return bCheckPrivateAddressSpace; } /** */ inline void CConfig::SetCheckPrivateAddressSpace( bool b ) { m_Mutex.Lock(); bCheckPrivateAddressSpace = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetPrivateAddressSpaceOnly() const { return bPrivateAddressSpaceOnly; } /** */ inline void CConfig::SetPrivateAddressSpaceOnly( bool b ) { m_Mutex.Lock(); bPrivateAddressSpaceOnly = b; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetDCLibPluginPath() const { return m_sDCLibPluginPath; } /** */ inline void CConfig::SetDCLibPluginPath( CString s ) { m_Mutex.Lock(); m_sDCLibPluginPath = s; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetChatSendToOffline() const { return bChatSendToOffline; } /** */ inline void CConfig::SetChatSendToOffline( bool b ) { m_Mutex.Lock(); bChatSendToOffline = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetChatRecvFromOffline() const { return bChatRecvFromOffline; } /** */ inline void CConfig::SetChatRecvFromOffline( bool b ) { m_Mutex.Lock(); bChatRecvFromOffline = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetAutoRecreateShareList() const { return bAutoRecreateShareList; } /** */ inline void CConfig::SetAutoRecreateShareList( bool b ) { m_Mutex.Lock(); bAutoRecreateShareList = b; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetTransferCert() const { return m_sTransferCert; } /** */ inline void CConfig::SetTransferCert( CString s ) { m_Mutex.Lock(); m_sTransferCert = s; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetTransferKey() const { return m_sTransferKey; } /** */ inline void CConfig::SetTransferKey( CString s ) { m_Mutex.Lock(); m_sTransferKey = s; m_Mutex.UnLock(); } /** */ inline eCloseType CConfig::GetHubOfflineTransferClose() const { return eHubOfflineTransferClose; } /** */ inline void CConfig::SetHubOfflineTransferClose( eCloseType ect ) { m_Mutex.Lock(); eHubOfflineTransferClose = ect; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetTransferAutoSearch() const { return bTransferAutoSearch; } /** */ inline void CConfig::SetTransferAutoSearch( bool b ) { m_Mutex.Lock(); bTransferAutoSearch = b; m_Mutex.UnLock(); } /** */ inline int CConfig::GetReloadHubListTime() const { return m_nReloadHubListTime; } /** */ inline void CConfig::SetReloadHubListTime( int i ) { m_Mutex.Lock(); m_nReloadHubListTime = i; m_Mutex.UnLock(); } /** */ inline int CConfig::GetRecreateShareListTime() const { return m_nRecreateShareListTime; } /** */ inline void CConfig::SetRecreateShareListTime( int i ) { m_Mutex.Lock(); m_nRecreateShareListTime = i; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetAwayPrefix() const { return sAwayPrefix; } /** */ inline void CConfig::SetAwayPrefix( CString s ) { m_Mutex.Lock(); sAwayPrefix = s; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetCreateFile() const { return m_bCreateFile; } /** */ inline void CConfig::SetCreateFile( bool b ) { m_Mutex.Lock(); m_bCreateFile = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetDisableHashList() const { return m_bDisableHashList; } /** */ inline void CConfig::SetDisableHashList( bool b ) { m_Mutex.Lock(); m_bDisableHashList = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetCompressedTransfers() const { return m_bCompressedTransfers; } /** */ inline void CConfig::SetCompressedTransfers( bool b ) { m_Mutex.Lock(); m_bCompressedTransfers = b; m_Mutex.UnLock(); } /** */ inline long CConfig::GetAutoSearchInterval() const { return m_nAutoSearchInterval; } /** */ inline void CConfig::SetAutoSearchInterval( long seconds ) { m_Mutex.Lock(); m_nAutoSearchInterval = seconds; m_Mutex.UnLock(); } /** */ inline ulonglong CConfig::GetSmallFileSize() const { return m_nSmallFileSize; } /** */ inline void CConfig::SetSmallFileSize( ulonglong s ) { m_Mutex.Lock(); m_nSmallFileSize = s; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetUseExtendedHubCount() const { return m_bUseExtendedHubCount; } /** */ inline void CConfig::SetUseExtendedHubCount( bool b ) { m_Mutex.Lock(); m_bUseExtendedHubCount = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetDontShareDotFiles() const { return m_bDontShareDotFiles; } /** */ inline void CConfig::SetDontShareDotFiles( bool b ) { m_Mutex.Lock(); m_bDontShareDotFiles = b; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetRemoteEncoding() const { return m_sRemoteEncoding; } /** */ inline void CConfig::SetRemoteEncoding( CString name ) { m_Mutex.Lock(); m_sRemoteEncoding = name; m_Mutex.UnLock(); } /** */ inline CString CConfig::GetLocalEncoding() const { return m_sLocalEncoding; } /** */ inline bool CConfig::GetUserIP2Enabled() const { return m_bUserIP2Enabled; } /** */ inline void CConfig::SetUserIP2Enabled( bool b ) { m_Mutex.Lock(); m_bUserIP2Enabled = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetZPipeEnabled() const { return m_bEnableZPipe; } /** */ inline void CConfig::SetZPipeEnabled( bool b ) { m_Mutex.Lock(); m_bEnableZPipe = b; m_Mutex.UnLock(); } /** */ inline ulonglong CConfig::GetStartDownloaded() const { return m_nStartDownloaded; } /** */ inline ulonglong CConfig::GetStartUploaded() const { return m_nStartUploaded; } /** */ inline void CConfig::ResetSessionStats() { m_Mutex.Lock(); m_nStartDownloaded = 0; m_nStartUploaded = 0; m_Mutex.UnLock(); } /** */ inline long CConfig::GetReadFileBufferSize() const { return m_nReadFileBufferSize; } /** */ inline void CConfig::SetReadFileBufferSize( long newsize ) { m_Mutex.Lock(); m_nReadFileBufferSize = newsize; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetDisableADCGetWithoutTTH() const { return m_bDisableADCGetWithoutTTH; } /** */ inline void CConfig::SetDisableADCGetWithoutTTH( bool b ) { m_Mutex.Lock(); m_bDisableADCGetWithoutTTH = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetDisableXMLListWithoutTTH() const { return m_bDisableXMLListWithoutTTH; } /** */ inline void CConfig::SetDisableXMLListWithoutTTH( bool b ) { m_Mutex.Lock(); m_bDisableXMLListWithoutTTH = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetEnableObsoleteExt() const { return m_bEnableObsoleteExt; } /** */ inline void CConfig::SetEnableObsoleteExt( bool b ) { m_Mutex.Lock(); m_bEnableObsoleteExt = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetShuffleSupports() const { return m_bShuffleSupports; } /** */ inline void CConfig::SetShuffleSupports( bool shuffle ) { m_Mutex.Lock(); m_bShuffleSupports = shuffle; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetEnableUserCommand() const { return m_bEnableUserCommand; } /** */ inline void CConfig::SetEnableUserCommand( bool b ) { m_Mutex.Lock(); m_bEnableUserCommand = b; m_Mutex.UnLock(); } /** */ inline bool CConfig::GetOldSSLSupport() const { return m_bOldSSLSupport; } /** */ inline void CConfig::SetOldSSLSupport( bool b ) { m_Mutex.Lock(); m_bOldSSLSupport = b; m_Mutex.UnLock(); } /** */ inline ulonglong CConfig::GetMinSegSize() const { return m_nMinSegSize; } /** */ inline void CConfig::SetMinSegSize( ulonglong bytes ) { m_Mutex.Lock(); m_nMinSegSize = bytes; m_Mutex.UnLock(); } /** */ inline ulonglong CConfig::GetExtraSlotsRate() const { return m_nExtraSlotsRate; } /** */ inline void CConfig::SetExtraSlotsRate( ulonglong n ) { m_Mutex.Lock(); m_nExtraSlotsRate = n; m_Mutex.UnLock(); } /** */ inline int CConfig::GetMaxExtraSlots() const { return m_nMaxExtraSlots; } /** */ inline void CConfig::SetMaxExtraSlots( int n ) { m_Mutex.Lock(); m_nMaxExtraSlots = n; m_Mutex.UnLock(); } #endif libdc0-0.3.24~svn3121/dclib/clistenmanager.h0000644000175000017500000000521111101144617017436 0ustar sikonsikon/*************************************************************************** clistenmanager.h - description ------------------- begin : Sun Feb 29 2004 copyright : (C) 2004-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CLISTENMANAGER_H #define CLISTENMANAGER_H /** *@author Mathias Küster * * This is for incoming peer connections, which go to * CDownloadManager. * * ConnectionWait was a counter but was not used anywhere * and got removed. */ #include #include #include #include #include class CListen; class CListenManagerBase { public: /** */ unsigned int GetListenPort(); /** */ CString GetSocketErrorMsg() { return m_sSocketError; }; protected: /** */ CListenManagerBase(); /** */ virtual ~CListenManagerBase(); /** called by CManager, no parameters */ int ManagerCallback(); /** called by a CListen with a socket descriptor int */ int ListenCallback( int fd ); /** A pure virtual function */ virtual _CCallback1 * CreateListenCallback() = 0; /** */ _CCallback0 * m_pCallback; /** */ bool m_bCrypto; private: /** */ void StartListen(); /** current used port */ unsigned int m_nListenPort; /** socket error message */ CString m_sSocketError; /** */ CMutex m_Mutex; /** */ CListen * m_pListen; }; class CListenManager : public CSingleton, public CListenManagerBase { public: /** */ CListenManager(); /** */ virtual ~CListenManager(); protected: /** */ virtual _CCallback1 * CreateListenCallback(); }; class CCryptoListenManager: public CSingleton, public CListenManagerBase { public: /** */ CCryptoListenManager(); /** */ virtual ~CCryptoListenManager(); protected: /** */ virtual _CCallback1 * CreateListenCallback(); }; #endif libdc0-0.3.24~svn3121/dclib/dcobject.h0000644000175000017500000006422211216761757016247 0ustar sikonsikon/*************************************************************************** dcobject.h - description ------------------- begin : Fri Feb 22 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef _DCOBJECT_H_ #define _DCOBJECT_H_ /** *@author Mathias Küster * * These are various dclib objects, usually there is one object * for each NMDC protocol command, but some objects may be for * more than one command e.g. $Get / $GetZBlock / $UGetBlock * all use CMessageGet. * * There are also dclib objects, usually sent to valknut * with information about a file or transfer. * * An alternative system is to have one object to handle all * protocol commands, with an enum for which command and then * a map of parameters and their values. Mainly for ADC, * where all commands have a common format. */ #include #include #include #include #include #include #include #define DC_USER_FILELIST_HE3 "MyList.DcLst" #define DC_USER_FILELIST DC_USER_FILELIST_HE3 #define DC_USER_FILELIST_BZ "MyList.bz2" #define DC_USER_FILELIST_XMLBZ "files.xml.bz2" #define DC_USER_FILELIST_XML "files.xml" #define DC_USER_INDEXLIST "index.lst" enum eDCMessage { DC_MESSAGE_PARSE_ERROR=0, DC_MESSAGE_CONNECTION_STATE, // internal con. state DC_MESSAGE_TRANSFER, // transfer state DC_MESSAGE_UNKNOWN, // direct connect proto DC_MESSAGE_LOCK, DC_MESSAGE_HELLO, DC_MESSAGE_HUBNAME, DC_MESSAGE_CHAT, DC_MESSAGE_MYINFO, DC_MESSAGE_QUIT, DC_MESSAGE_NICKLIST, // 10 DC_MESSAGE_OPLIST, DC_MESSAGE_CONNECTTOME, DC_MESSAGE_KEY, DC_MESSAGE_PRIVATECHAT, DC_MESSAGE_REVCONNECTTOME, DC_MESSAGE_SEARCHRESULT, DC_MESSAGE_FORCEMOVE, DC_MESSAGE_MYNICK, // connect to me DC_MESSAGE_DIRECTION, // 20 connect to me DC_MESSAGE_MAXEDOUT, DC_MESSAGE_FILELENGTH, DC_MESSAGE_ERROR, // file not found ... DC_MESSAGE_GET, DC_MESSAGE_GETLISTLEN, DC_MESSAGE_VALIDATEDENIDE, DC_MESSAGE_GETINFO, DC_MESSAGE_AGE, DC_MESSAGE_HUBISFULL, DC_MESSAGE_LISTLEN, // 30 DC_MESSAGE_SEND, DC_MESSAGE_PING, DC_MESSAGE_GETPASS, // user need a password DC_MESSAGE_BADPASS, // wrong password DC_MESSAGE_LOGEDIN, // admin DC_MESSAGE_CANCEL, // cancel a transfer DC_MESSAGE_CANCELED, // the transfer is canceled DC_MESSAGE_SUPPORTS, // download manager types DC_MESSAGE_FILE_OBJECT, // 40 DC_MESSAGE_TRANSFER_OBJECT, DC_MESSAGE_FILELIST_OBJECT, DC_MESSAGE_SLOT_OBJECT, DC_MESSAGE_LOG, DC_MESSAGE_DM_INFO, // search manager types DC_MESSAGE_SEARCH_FILE, DC_MESSAGE_SEARCH_USER, DC_MESSAGE_SEARCHRESULT_USER, // file manager DC_MESSAGE_FM_INFO, // traffic control DC_MESSAGE_TRAFFIC, // file transferrate DC_MESSAGE_FILE_TRANSFER_RATE, DC_MESSAGE_GETHUBLIST, DC_MESSAGE_CONNECT_CLIENT, // verlihub extension DC_MESSAGE_HUB_TOPIC, // nmdc DC_MESSAGE_GET_NET_INFO, // user command DC_MESSAGE_USER_COMMAND, // ZLIB compression DC_MESSAGE_GETZBLOCK, DC_MESSAGE_SENDING, //DC_MESSAGE_FAILED // ADCGET DC_MESSAGE_ADCGET, DC_MESSAGE_ADCSND, // UserIP2 message DC_MESSAGE_USERIP }; /* * The initialization phase of the constructor has to be used * because m_eType is const, and it really does not make * any sense for m_eType NOT to be const. Alternatively * a virtual type() function could return a hard coded value. */ class CDCMessage { public: /** */ CDCMessage() : m_eType( DC_MESSAGE_UNKNOWN ) {}; /** */ virtual ~CDCMessage() {}; /** */ const eDCMessage m_eType; protected: /** */ CDCMessage( eDCMessage type ) : m_eType ( type ) {}; }; class CMessagePing : public CDCMessage { public: /** */ CMessagePing() : CDCMessage(DC_MESSAGE_PING) {}; /** */ virtual ~CMessagePing() {}; }; class CMessageHubTopic : public CDCMessage { public: /** */ CMessageHubTopic() : CDCMessage(DC_MESSAGE_HUB_TOPIC) {}; /** */ virtual ~CMessageHubTopic() {}; /** */ CMessageHubTopic & operator = (const CMessageHubTopic & p) { m_sTopic = p.m_sTopic; return *this; }; /** */ CString m_sTopic; }; class CMessageGetInfo : public CDCMessage { public: /** */ CMessageGetInfo() : CDCMessage(DC_MESSAGE_GETINFO) {}; /** */ virtual ~CMessageGetInfo() {}; /** */ CMessageGetInfo & operator = (const CMessageGetInfo & p) { m_sSrcNick = p.m_sSrcNick; m_sDstNick = p.m_sDstNick; return *this; }; /** */ CString m_sSrcNick; /** */ CString m_sDstNick; }; class CMessageGetNetInfo : public CDCMessage { public: /** */ CMessageGetNetInfo() : CDCMessage(DC_MESSAGE_GET_NET_INFO) {}; /** */ virtual ~CMessageGetNetInfo() {}; }; class CMessageConnectionState : public CDCMessage { public: /** */ CMessageConnectionState() : CDCMessage(DC_MESSAGE_CONNECTION_STATE) { m_eState = estNONE; }; /** */ virtual ~CMessageConnectionState() {}; /** */ CMessageConnectionState & operator = (const CMessageConnectionState & p) { m_eState = p.m_eState; m_sMessage = p.m_sMessage; return *this; }; /** */ eConnectionState m_eState; /** */ CString m_sMessage; }; class CMessageTransfer : public CDCMessage { public: /** */ CMessageTransfer() : CDCMessage(DC_MESSAGE_TRANSFER) { m_eDirection = edNONE; m_nTransfered = 0; m_nLength = 0; }; /** */ virtual ~CMessageTransfer() {}; /** */ CMessageTransfer & operator = (const CMessageTransfer & p) { m_eDirection = p.m_eDirection; m_nTransfered = p.m_nTransfered; m_nLength = p.m_nLength; return *this; }; /** */ eDirection m_eDirection; /** */ ulonglong m_nTransfered; /** */ ulonglong m_nLength; }; class CMessageFileTransferRate : public CDCMessage { public: /** */ CMessageFileTransferRate() : CDCMessage(DC_MESSAGE_FILE_TRANSFER_RATE) { m_nRate = 0; }; /** */ virtual ~CMessageFileTransferRate() {}; /** */ CMessageFileTransferRate & operator = (const CMessageFileTransferRate & p) { m_sLocalFile = p.m_sLocalFile; m_nRate = p.m_nRate; return *this; }; /** */ CString m_sLocalFile; /** */ ulonglong m_nRate; }; class CMessageSupports : public CDCMessage { public: /** */ CMessageSupports(); /** */ virtual ~CMessageSupports(); /** */ CMessageSupports & operator = (const CMessageSupports & p); /** */ CString m_sContent; /** */ bool m_bBZList; /** */ bool m_bSSL; /** */ bool m_bChunk; /** */ bool m_bMiniSlots; /** */ bool m_bXMLBZList; /** */ bool m_bZBlock; /** */ bool m_bADCGet; /** */ bool m_bTTHL; /** */ bool m_bTTHF; /** */ bool m_bZLIG; }; class CMessageError : public CDCMessage { public: /** */ CMessageError() : CDCMessage(DC_MESSAGE_ERROR) {}; /** */ virtual ~CMessageError() {}; /** */ CMessageError & operator = (const CMessageError & p) { m_sError = p.m_sError; return *this; }; /** */ CString m_sError; }; class CMessageGet : public CDCMessage { public: /** */ CMessageGet() : CDCMessage(DC_MESSAGE_GET) { m_nPos = 0; m_nSize = 0; m_bUGet = false; m_bZLib = false; }; /** */ virtual ~CMessageGet() {}; /** */ CMessageGet & operator = (const CMessageGet & p) { m_sFilename = p.m_sFilename; m_nPos = p.m_nPos; m_nSize = p.m_nSize; m_bUGet = p.m_bUGet; m_bZLib = p.m_bZLib; return *this; }; /** */ CString m_sFilename; /** */ ulonglong m_nPos; /** */ ulonglong m_nSize; /** True if remote did $UGetBlock, false if $Get was used */ bool m_bUGet; /** True if remote did $GetZBlock / $UGetZBlock */ bool m_bZLib; }; class CMessageADCGet : public CDCMessage { public: /** */ CMessageADCGet() : CDCMessage(DC_MESSAGE_ADCGET) { m_eADCType = eAdcFile; m_nPos = 0; m_nSize = -1; m_bZlib = false; }; /** */ virtual ~CMessageADCGet() {}; /** */ CMessageADCGet & operator = (const CMessageADCGet & p) { m_eADCType = p.m_eADCType; m_sTTH = p.m_sTTH; m_nPos = p.m_nPos; m_nSize = p.m_nSize; m_bZlib = p.m_bZlib; m_sFile = p.m_sFile; return *this; }; /** file, tthl, or list */ eADCType m_eADCType; /** TTH without prefix or empty if using file */ CString m_sTTH; /** */ ulonglong m_nPos; /** */ long long m_nSize; /** */ bool m_bZlib; /** File if not using TTH, empty otherwise */ CString m_sFile; }; class CMessageADCSnd : public CDCMessage { public: /** */ CMessageADCSnd() : CDCMessage(DC_MESSAGE_ADCSND) { m_eADCType = eAdcFile; m_nPos = 0; m_nSize = -1; m_bZlib = false; }; /** */ virtual ~CMessageADCSnd() {}; /** */ CMessageADCSnd & operator = (const CMessageADCSnd & p) { m_eADCType = p.m_eADCType; m_sTTH = p.m_sTTH; m_nPos = p.m_nPos; m_nSize = p.m_nSize; m_bZlib = p.m_bZlib; m_sFile = p.m_sFile; return *this; }; /** file, tthl, or list */ eADCType m_eADCType; /** TTH without prefix or empty if using file*/ CString m_sTTH; /** */ ulonglong m_nPos; /** */ long long m_nSize; /** */ bool m_bZlib; /** File if not using TTH, empty otherwise */ CString m_sFile; }; class CMessageGetPass : public CDCMessage { public: /** */ CMessageGetPass() : CDCMessage(DC_MESSAGE_GETPASS) {}; /** */ virtual ~CMessageGetPass() {}; }; class CMessageCancel : public CDCMessage { public: /** */ CMessageCancel() : CDCMessage(DC_MESSAGE_CANCEL) {}; /** */ virtual ~CMessageCancel() {}; }; class CMessageCanceled : public CDCMessage { public: /** */ CMessageCanceled() : CDCMessage(DC_MESSAGE_CANCELED) {}; /** */ virtual ~CMessageCanceled() {}; }; class CMessageKey : public CDCMessage { public: /** */ CMessageKey() : CDCMessage(DC_MESSAGE_KEY) {}; /** */ virtual ~CMessageKey() {}; }; class CMessageBadPass : public CDCMessage { public: /** */ CMessageBadPass() : CDCMessage(DC_MESSAGE_BADPASS) {}; /** */ virtual ~CMessageBadPass() {}; }; class CMessageLogedIn : public CDCMessage { public: /** */ CMessageLogedIn() : CDCMessage(DC_MESSAGE_LOGEDIN) {}; /** */ virtual ~CMessageLogedIn() {}; /** */ CMessageLogedIn & operator = (const CMessageLogedIn & p) { m_sNick = p.m_sNick; return *this; }; /** */ CString m_sNick; }; class CMessageSend : public CDCMessage { public: /** */ CMessageSend() : CDCMessage(DC_MESSAGE_SEND) {}; /** */ virtual ~CMessageSend() {}; }; class CMessageValidateDenide : public CDCMessage { public: /** */ CMessageValidateDenide() : CDCMessage(DC_MESSAGE_VALIDATEDENIDE) {}; /** */ virtual ~CMessageValidateDenide() {}; }; class CMessageHubIsFull : public CDCMessage { public: /** */ CMessageHubIsFull() : CDCMessage(DC_MESSAGE_HUBISFULL) {}; /** */ virtual ~CMessageHubIsFull() {}; }; class CMessageMaxedOut : public CDCMessage { public: /** */ CMessageMaxedOut() : CDCMessage(DC_MESSAGE_MAXEDOUT) {}; /** */ virtual ~CMessageMaxedOut() {}; }; class CMessageGetListLen : public CDCMessage { public: /** */ CMessageGetListLen() : CDCMessage(DC_MESSAGE_GETLISTLEN) {}; /** */ virtual ~CMessageGetListLen() {}; }; class CMessageLock : public CDCMessage { public: /** */ CMessageLock() : CDCMessage(DC_MESSAGE_LOCK) { m_eClientVersion = eucvNONE; m_bExtProtocol = false; m_nVersionMajor = 0; m_nVersionMinor = 0; m_nVersionPatch = 0; }; /** */ virtual ~CMessageLock() {}; /** */ CMessageLock & operator = (const CMessageLock & p) { m_sPK = p.m_sPK; m_sData = p.m_sData; m_eClientVersion = p.m_eClientVersion; m_sVersionString = p.m_sVersionString; m_nVersionMajor = p.m_nVersionMajor; m_nVersionMinor = p.m_nVersionMinor; m_nVersionPatch = p.m_nVersionPatch; m_bExtProtocol = p.m_bExtProtocol; return *this; }; /** */ CString m_sPK; /** */ CString m_sData; /** */ eUserClientVersion m_eClientVersion; /** */ CString m_sVersionString; /** */ int m_nVersionMajor; /** */ int m_nVersionMinor; /** */ int m_nVersionPatch; /** */ bool m_bExtProtocol; }; class CMessageFileLength : public CDCMessage { public: /** */ CMessageFileLength() : CDCMessage(DC_MESSAGE_FILELENGTH) { m_nFileLength = 0; }; /** */ virtual ~CMessageFileLength() {}; /** */ CMessageFileLength & operator = (const CMessageFileLength & p) { m_nFileLength = p.m_nFileLength; return *this; }; /** */ ulonglong m_nFileLength; }; class CMessageSending : public CDCMessage { public: /** */ CMessageSending() : CDCMessage(DC_MESSAGE_SENDING) { m_nLength = 0; }; /** */ virtual ~CMessageSending() {}; /** */ CMessageSending & operator = (const CMessageSending & p) { m_nLength = p.m_nLength; return *this; }; /** */ ulonglong m_nLength; }; class CMessageDirection : public CDCMessage { public: /** */ CMessageDirection() : CDCMessage(DC_MESSAGE_DIRECTION) { m_nLevel = 0; m_eDirection = edNONE; }; /** */ virtual ~CMessageDirection() {}; /** */ CMessageDirection & operator = (const CMessageDirection & p) { m_eDirection = p.m_eDirection; m_nLevel = p.m_nLevel; return *this; }; /** */ eDirection m_eDirection; /** */ int m_nLevel; }; class CMessageNickList : public CDCMessage { public: /** */ CMessageNickList(); /** * Copy constructor that does a deep copy of the list. */ CMessageNickList( const CMessageNickList & other ); /** */ virtual ~CMessageNickList(); /** */ CMessageNickList & operator = (const CMessageNickList & rhs); /** */ CList m_NickList; }; class CMessageOpList : public CDCMessage { public: /** */ CMessageOpList(); /** * Copy constructor that does a deep copy of the list. */ CMessageOpList( const CMessageOpList & other ); /** */ virtual ~CMessageOpList(); /** */ CMessageOpList & operator = (const CMessageOpList & rhs); /** */ CList m_NickList; }; class CMessageMyNick : public CDCMessage { public: /** */ CMessageMyNick() : CDCMessage(DC_MESSAGE_MYNICK) {}; /** */ virtual ~CMessageMyNick() {}; CMessageMyNick & operator = (const CMessageMyNick & p) { m_sNick = p.m_sNick; return *this; }; /** */ CString m_sNick; }; class CMessageHello : public CDCMessage { public: /** */ CMessageHello() : CDCMessage(DC_MESSAGE_HELLO) {}; /** */ virtual ~CMessageHello() {}; CMessageHello & operator = (const CMessageHello & p) { m_sNick = p.m_sNick; return *this; }; /** */ CString m_sNick; }; class CMessageQuit : public CDCMessage { public: /** */ CMessageQuit() : CDCMessage(DC_MESSAGE_QUIT) {}; /** */ virtual ~CMessageQuit() {}; CMessageQuit & operator = (const CMessageQuit & p) { m_sNick = p.m_sNick; return *this; }; /** */ CString m_sNick; }; class CMessageChat : public CDCMessage { public: /** */ CMessageChat() : CDCMessage(DC_MESSAGE_CHAT) {}; /** */ virtual ~CMessageChat() {}; CMessageChat & operator = (const CMessageChat & p) { m_sNick = p.m_sNick; m_sMessage = p.m_sMessage; return *this; }; /** */ CString m_sNick; /** */ CString m_sMessage; }; class CMessageMyInfo : public CDCMessage { public: /** */ CMessageMyInfo(); /** */ virtual ~CMessageMyInfo(); /** */ CMessageMyInfo & operator = (const CMessageMyInfo & p); /** */ CMessageLock m_MessageLock; /** */ CMessageSupports m_MessageSupports; /** the nickname */ CString m_sNick; /** the comment */ CString m_sComment; /** */ CString m_sUnknown; /** the speed string */ CString m_sUserSpeed; /** the email */ CString m_sEMail; /** version */ CString m_sVerComment; /** */ CString m_sTransferHost; /** sharesize */ ulonglong m_nShared; /** parsed speed */ eUserSpeed m_eUserSpeed; /** away mode */ eUserAwayMode m_eAwayMode; /** parsed client version */ eUserClientVersion m_eClientVersion; /** client mode */ eClientMode m_eClientMode; /** true if myinfo recv. */ bool m_bValid; /** operator status */ bool m_bOperator; /** Server flag set - special icon */ bool m_bServerFlag; /** Fireball flag set - special icon */ bool m_bFireballFlag; /** Supports NMDC TLS port */ bool m_bTLSFlag; protected: /** For CMessageSearchResultUser */ CMessageMyInfo( eDCMessage type ); }; class CMessageConnectToMe : public CDCMessage { public: /** */ CMessageConnectToMe() : CDCMessage(DC_MESSAGE_CONNECTTOME) { m_nPort = 0; m_bCrypto = false; }; /** */ virtual ~CMessageConnectToMe() {}; CMessageConnectToMe & operator = (const CMessageConnectToMe & p) { m_sNick = p.m_sNick; m_sHost = p.m_sHost; m_nPort = p.m_nPort; m_bCrypto = p.m_bCrypto; return *this; }; /** */ CString m_sNick; /** */ CString m_sHost; /** */ int m_nPort; /** StrongDC NMDC TLS port extension */ bool m_bCrypto; }; class CMessageRevConnectToMe : public CDCMessage { public: /** */ CMessageRevConnectToMe() : CDCMessage(DC_MESSAGE_REVCONNECTTOME) {}; /** */ virtual ~CMessageRevConnectToMe() {}; CMessageRevConnectToMe & operator = (const CMessageRevConnectToMe & p) { m_sNick = p.m_sNick; m_sDstNick = p.m_sDstNick; return *this; }; /** */ CString m_sNick; /** */ CString m_sDstNick; }; class CMessageForceMove : public CDCMessage { public: /** */ CMessageForceMove() : CDCMessage(DC_MESSAGE_FORCEMOVE) { m_nPort = 0; }; /** */ virtual ~CMessageForceMove() {}; /** */ CMessageForceMove & operator = (const CMessageForceMove & p) { m_sHost = p.m_sHost; m_nPort = p.m_nPort; return *this; }; /** */ CString m_sHost; /** */ int m_nPort; }; class CMessageSearchResult : public CDCMessage { public: /** */ CMessageSearchResult() : CDCMessage(DC_MESSAGE_SEARCHRESULT) { m_nFreeSlot = 0; m_nMaxSlot = 0; m_nSize = 0; m_bFolder = false; }; /** */ virtual ~CMessageSearchResult() {}; /** */ CMessageSearchResult & operator = (const CMessageSearchResult & p) { m_sNick = p.m_sNick; m_sFile = p.m_sFile; m_nSize = p.m_nSize; m_sHubName = p.m_sHubName; m_sHubHost = p.m_sHubHost; m_sHash = p.m_sHash; m_sSrcIP = p.m_sSrcIP; m_nFreeSlot = p.m_nFreeSlot; m_nMaxSlot = p.m_nMaxSlot; m_bFolder = p.m_bFolder; return *this; }; /** */ CString m_sNick; /** */ CString m_sFile; /** */ ulonglong m_nSize; /** */ CString m_sHubName; /** */ CString m_sHubHost; /** */ CString m_sHash; /** * The source (client not hub) IP if you are in active mode, * always empty if you are in passive mode. */ CString m_sSrcIP; /** */ unsigned int m_nFreeSlot; /** */ unsigned int m_nMaxSlot; /** True if the result is a folder, false if the result is a file*/ bool m_bFolder; }; class CMessagePrivateChat : public CDCMessage { public: /** */ CMessagePrivateChat() : CDCMessage(DC_MESSAGE_PRIVATECHAT) { m_eSecureState = esecsNONE; }; /** */ virtual ~CMessagePrivateChat() {}; /** */ CMessagePrivateChat & operator = (const CMessagePrivateChat & p) { m_sDstNick = p.m_sDstNick; m_sSrcNick = p.m_sSrcNick; m_sMultiSrcNick = p.m_sMultiSrcNick; m_sMessage = p.m_sMessage; m_eSecureState = p.m_eSecureState; return *this; }; /** */ CString m_sDstNick; /** */ CString m_sSrcNick; /** */ CString m_sMultiSrcNick; /** */ CString m_sMessage; /** */ eSecureState m_eSecureState; }; class CMessageHubName : public CDCMessage { public: /** */ CMessageHubName() : CDCMessage(DC_MESSAGE_HUBNAME) {}; /** */ virtual ~CMessageHubName() {}; /** */ CMessageHubName & operator = (const CMessageHubName & p) { m_sHubName = p.m_sHubName; m_sOldHubName = p.m_sOldHubName; return *this; }; /** */ CString m_sHubName; /** */ CString m_sOldHubName; }; // download manager object classes class CMessageDMFileObject : public CDCMessage { public: /** */ CMessageDMFileObject(); /** Copy constructor that does deep copy */ CMessageDMFileObject( const CMessageDMFileObject & other ); /** */ virtual ~CMessageDMFileObject(); /** */ CMessageDMFileObject & operator = (const CMessageDMFileObject & p); /** */ CString m_sNick; /** */ CString m_sHubName; /** */ CString m_sHubHost; /** remote file */ CString m_sRemoteFile; /** the local file */ CString m_sLocalFile; /** */ CString m_sTTH; /** */ time_t m_tTimeout; /** */ eTransferWaitState m_eTransferWaitState; /** */ int m_nConnections; /** */ eTransferFileState m_eTransferFileState; /** file size */ ulonglong m_nSize; /** current file position */ ulonglong m_nStartPosition; /** current file position */ ulonglong m_nCurrentPosition; /** file end position */ ulonglong m_nEndPosition; /** */ int m_nPriority; /** list of directories to download */ std::list * m_pDirList; /** */ bool m_bMulti; /** */ bool m_bRemoveFile; }; class CMessageDMTransferObject : public CDCMessage { public: /** */ CMessageDMTransferObject(); /** */ virtual ~CMessageDMTransferObject(); /** */ CMessageDMTransferObject & operator = (const CMessageDMTransferObject & p); /** */ ulonglong m_nTransferID; /** */ CString m_sSrcNick; /** */ CString m_sDstNick; /** */ CString sHost; /** */ CString m_sHubHost; /** */ CString sHubName; /** remote file */ CString m_sDstFile; /** local file */ CString m_sSrcFile; /** */ CString m_sTTH; /** */ eConnectionState eState; /** file size */ ulonglong lSize; /** file size done */ ulonglong lSizeDone; /** rate of transfer */ ulonglong lRate; /** rate of all transfers */ ulonglong m_nMultiRate; /** */ ulonglong lStartPosition; /** */ ulonglong lTransfered; /** */ ulonglong lEndPosition; /** */ bool bRemoveTransfer; /** */ bool m_bEncrypted; }; class CMessageDMFileListObject : public CDCMessage { public: /** */ CMessageDMFileListObject(); /** Does a deep copy of the optional list */ CMessageDMFileListObject( const CMessageDMFileListObject & other ); /** */ virtual ~CMessageDMFileListObject(); /** */ CMessageDMFileListObject & operator = (const CMessageDMFileListObject & p); /** */ CString sNick; /** */ CString sHubName; /** */ CString sHubHost; /** */ CString sLocalFile; /** open filelist at file/folder */ CString sJumpTo; /** list of directories to download */ std::list * m_pDirList; }; class CMessageDMSlotObject : public CDCMessage { public: /** */ CMessageDMSlotObject() : CDCMessage(DC_MESSAGE_SLOT_OBJECT) { iSlots = 0; bPermanent = false; }; /** */ virtual ~CMessageDMSlotObject() {}; /** */ CString sNick; /** */ CString sHubName; /** */ int iSlots; /** */ bool bPermanent; }; class CMessageLog : public CDCMessage { public: /** */ CMessageLog() : CDCMessage(DC_MESSAGE_LOG) {}; /** */ virtual ~CMessageLog() {}; /** */ CString sMessage; }; class CMessageSearchUser : public CDCMessage { public: /** */ CMessageSearchUser() : CDCMessage(DC_MESSAGE_SEARCH_USER) {}; /** */ virtual ~CMessageSearchUser() {}; /** */ CString m_sNick; }; class CMessageSearchResultUser : public CMessageMyInfo { public: /** */ CMessageSearchResultUser() : CMessageMyInfo( DC_MESSAGE_SEARCHRESULT_USER ) {}; /** */ virtual ~CMessageSearchResultUser() {}; CMessageSearchResultUser & operator = (const CMessageSearchResultUser & rhs) { (CMessageMyInfo&)*this = (CMessageMyInfo&)rhs; m_sHubName = rhs.m_sHubName; return *this; }; /** */ CString m_sHubName; }; class CMessageSearchFile : public CDCMessage { public: /** */ CMessageSearchFile(); /** */ virtual ~CMessageSearchFile(); CMessageSearchFile & operator = (const CMessageSearchFile & rhs); /** search string */ CString m_sString; /** the source, nick or host */ CString m_sSource; /** if source a host, this is the port */ int m_nPort; /** search options */ enum eSearchSizeType m_eSizeType; /** search options */ ulonglong m_nSize; /** search options */ eFileTypes m_eFileType; /** search options */ bool m_bSizeLimit; /** local or global search */ bool m_bLocal; /** extended protocol */ bool m_bExtended; /** hub network search */ bool m_bMulti; }; class DCHubObject { public: /** */ DCHubObject() { m_bActive = false; }; /** */ DCHubObject( DCHubObject * o ) { m_bActive = o->m_bActive; m_sHubName = o->m_sHubName; m_sHubHost = o->m_sHubHost; }; /** */ ~DCHubObject() {}; /** */ bool m_bActive; /** */ CString m_sHubName; /** */ CString m_sHubHost; }; class DCMessageTraffic : public CDCMessage { public: /** */ DCMessageTraffic() : CDCMessage(DC_MESSAGE_TRAFFIC) { m_nRx = 0; m_nTx = 0; m_nDataRx = 0; m_nDataTx = 0; m_nControlRx = 0; m_nControlTx = 0; }; /** */ virtual ~DCMessageTraffic() {}; DCMessageTraffic & operator = (const DCMessageTraffic & s) { m_nRx = s.m_nRx; m_nTx = s.m_nTx; m_nDataRx = s.m_nDataRx; m_nDataTx = s.m_nDataTx; m_nControlRx = s.m_nControlRx; m_nControlTx = s.m_nControlTx; return *this; }; /** */ ulonglong m_nRx; /** */ ulonglong m_nTx; /** */ ulonglong m_nDataRx; /** */ ulonglong m_nDataTx; /** */ ulonglong m_nControlRx; /** */ ulonglong m_nControlTx; }; class DCMessageGetHubList : public CDCMessage { public: /** */ DCMessageGetHubList() : CDCMessage(DC_MESSAGE_GETHUBLIST) { m_bRun = false; }; /** */ virtual ~DCMessageGetHubList() {}; /** */ bool m_bRun; }; class DCMessageConnectClient : public CDCMessage { public: /** */ DCMessageConnectClient() : CDCMessage(DC_MESSAGE_CONNECT_CLIENT) {}; /** */ virtual ~DCMessageConnectClient() {}; /** */ CString m_sHubName; /** */ CString m_sHubHost; }; class CMessageUserIP : public CDCMessage { public: /** Creates a new UserIP object */ CMessageUserIP() : CDCMessage(DC_MESSAGE_USERIP) {}; /** */ virtual ~CMessageUserIP() {}; /** List of nicks */ std::list m_lNicks; /** List of IPs */ std::list m_lIPs; }; class CMessageUserCommand : public CDCMessage { public: /** */ CMessageUserCommand() : CDCMessage(DC_MESSAGE_USER_COMMAND) { type = -1; context = -1; }; /** */ virtual ~CMessageUserCommand() {}; /** Command type - raw, raw once, remove or clear commands etc. */ int type; /** Command context - which menus it goes in */ int context; /** Command name */ CString name; /** The command itself */ CString command; }; #endif libdc0-0.3.24~svn3121/dclib/cconnectionmanager.h0000644000175000017500000001035311125260136020303 0ustar sikonsikon/*************************************************************************** cconnectionmanager.h - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCONNECTIONMANAGER_H #define CCONNECTIONMANAGER_H /** *@author Mathias Küster * * This handles the list of hub connections. * * The main thing lacking here is some threading, so that all the hubs * are not run on the one dclib thread. */ #include #include #include #include #include enum eHubState { ehsNONE, ehsONLINE, ehsOFFLINE }; class CClient; class DCHubObject; class CMessageSearchFile; class CDCMessage; class CMessageMyInfo; class _CCallback0; #include class CConnectionManager : public CSingleton { public: /** */ CConnectionManager(); /** */ virtual ~CConnectionManager(); /** */ void ConnectClient( CString hubname, CString server ); /** send message to all connected servers */ int SendStringToConnectedServers( CString s, CString hubname = CString(), bool encode = true ); /** send a search string (extracted from message) to all connected servers */ int SendSearchToConnectedServers( CMessageSearchFile *sf, CString hubhost = CString() ); /** send myinfo to all connected servers */ int SendMyInfoToConnectedServers(); /** 0: send -1: user offline -2: hub not ready (connection state/handshake) -3: hub offline -4: send error */ int SendConnectionRequest( CString nick, CString hubname, CString hubhost ); /** */ bool SetUserTransferInfo( CString hubname, CString hubhost, CString nick, CDCMessage * msg ); /** */ bool IsUserOnline( CString nick, CString hubname, CString hubhost, CList * list = 0 ); /** */ eHubState IsHubOnline( CString hubname, CString hubhost ); /** */ bool IsAdmin( CString hubname, CString hubhost, CString nick = CString() ); /** */ bool GetUserMyInfo( CString hubname, CString hubhost, CString nick, CMessageMyInfo * p ); /** */ CString GetHubHost( CString hubname ); /** */ CString GetNick( CString hubname, CString hubhost ); /** * Fills in the paramaters with hubname, hubhost and hubip for the first * hub whose hubname, hubhost or hubip matches id. * * Returns true if the details have been filled in. */ bool GetHubDetails( const CString & id, CString & name, CString & host, CString & ip ); /** */ long GetConnectedHubCount( bool admin = false ); /** Returns the number of hubs which we logged into with a password */ long GetConnectedHubPasswordCount(); /** */ std::map * GetConnectedHubServerMap(); /** */ void Connect( CString hubname, CString server, CClient * client, bool sslconnect = false ); /** callback function */ virtual int DC_CallBack( CDCMessage * ) { return -1; }; protected: /** */ void AddHub( CClient * client ); /** */ void RemoveHub( CClient * client ); /** */ CClient * GetHub( CString hubname, CString hubhost ); /** */ CMutex m_Mutex; /** FIXME why two mutexes? */ CMutex * m_pClientListMutex; /** client list */ CList * m_pClientList; private: /** */ CClient * GetHubObject( CString hubname, CString hubhost ); /** */ void UpdateMyInfo( CClient* client ); /** Called by CManager via the callback instead of starting out own thread */ int Callback(); /** */ bool m_bUpdateMyinfo; /** */ _CCallback0 * m_pCallback; }; #endif libdc0-0.3.24~svn3121/dclib/chttp.h0000644000175000017500000000644111125260136015573 0ustar sikonsikon/*************************************************************************** chttp.h - description ------------------- begin : Mon Jul 29 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CHTTP_H #define CHTTP_H /** *@author Mathias Küster * * HTTP protocol class for downloading filelists, valknut uses * QT's QHttp instead. */ #include #include #include #include class CDCMessage; enum eUrlMethod { eumGET, eumPOST }; class CHttp : public CConnection { public: /** */ CHttp(); /** */ virtual ~CHttp(); /** */ int GetUrl( CString url, CString postdata = CString() ); /** */ bool GetData( CByteArray * ba ); /** callback function */ virtual int DC_CallBack( CDCMessage * ) { return -1; }; /** */ virtual void ConnectionState( eConnectionState ); /** */ virtual void DataAvailable( const char *, int ); /** */ virtual void DataSend(); /** */ virtual void DataTimeout(); /** */ virtual void Notify(); /** */ void SetCallBackFunction( _CCallback1 * callback ); /** */ CString GetUrl() { return m_sUrl; } /** */ CString GetLocation() { return m_sLocation; } /** */ int GetHttpError() { return m_nErrorCode; } /** */ static CString Encode( CString s ); /** */ static CString Decode( CString s ); /** Parses "user:pass@host:port" user, pass, port optional, port defaults to 8080 */ static bool ParseProxy( char * proxy, CString & user, CString & pass, CString & host, unsigned int & port ); private: /** Called by CManager to run this instead of starting it's own thread */ int Callback(); /** */ int CallBack_SendObject( CDCMessage * DCMessage ); /** */ void AppendData( const char * buffer, int len ); /** */ CList * m_pMessageList; /** */ eConnectionState m_eMode; /** */ CString m_sUrl; /** */ CString m_sHost; /** */ CString m_sPort; /** */ CString m_sProxy; /** */ CString m_sProxyPort; /** */ CString m_sProxyUser; /** */ CString m_sProxyPass; /** */ eUrlMethod m_eUrlMethod; /** */ int m_nErrorCode; /** */ bool m_bData; /** */ CString m_sLocation; /** */ CString m_sHeader; /** */ CString m_sPostData; /** */ long m_nContentLength; /** */ CByteArray m_baData; /** */ _CCallback1 * m_pHttpCallback; /** */ _CCallback0 * m_pCallback; }; inline void CHttp::SetCallBackFunction( _CCallback1 * callback ) { delete m_pHttpCallback; m_pHttpCallback = callback; } #endif libdc0-0.3.24~svn3121/dclib/cfilemanager.h0000644000175000017500000001313711101144617017065 0ustar sikonsikon/*************************************************************************** cfilemanager.h - description ------------------- begin : Sat Aug 03 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CFILEMANAGER_H #define CFILEMANAGER_H /** *@author Mathias Küster * * This handles the files in the share and the filelist, much of which * is handled by the CSearchIndex and CShareList classes. * * This handles putting data into CSearchIndex. Looking for files * by TTH is done in CSearchIndex but keyword searches are now * handled here. */ #include #include #include #include #include #include #include #include #include #if ( (DCLIB_USES_UNORDERED_SET == 1) && (DCLIB_ALLOWS_CSTRING_KEY == 1) ) #include #include #include typedef std::unordered_set FileNameSet; #elif ( (DCLIB_USES_TR1_UNORDERED_SET == 1) && (DCLIB_ALLOWS_CSTRING_KEY == 1) ) #include #include #include typedef std::tr1::unordered_set FileNameSet; #else typedef std::set FileNameSet; #endif #include typedef std::map FileTypeMap; class CFileManagerInfo; class CByteArray; class CSearchIndex; class CShareList; class DCConfigShareFolder; class _CCallback0; class CFileManager : public CSingleton, public CThread { public: /** */ CFileManager(); /** */ virtual ~CFileManager(); /** */ ulonglong GetShareSize(); /** */ unsigned long GetShareBufferSize( eShareBufferType type ); /** */ int GetShareBuffer( eShareBufferType type, CByteArray * sharebuffer, bool decompress = false ); /** * Gets a partial XML list, use depth = -1 for all, */ void GetPartialListing( const CString & dir, CString & result, int depth = 0 ); /** Search with any size any type */ std::set * Search( unsigned int maxresults, std::list * words ); /** Search with any size of specified type */ std::set * Search( unsigned int maxresults, std::list * words, eFileTypes type ); /** Search for at least size any type */ std::set * SearchAtLeast( unsigned int maxresults, std::list * words, ulonglong size ); /** Search for at least size of specified type */ std::set * SearchAtLeast( unsigned int maxresults, std::list * words, ulonglong size, eFileTypes type ); /** Search for at most size any type */ std::set * SearchAtMost( unsigned int maxresults, std::list * words, ulonglong size ); /** Search for at most size of specified type */ std::set * SearchAtMost( unsigned int maxresults, std::list * words, ulonglong size, eFileTypes type ); /** */ std::set * SearchHash( CString s ); /** */ bool GetFileBaseObject( unsigned long index, struct filebaseobject * fbo, CString & filename ); /** */ CString GetHash( unsigned long hbi ); /** Get the TTH leaves for the given TTH */ CByteArray * GetHashLeaves( CString tth ); /** */ bool CreateShareList(); /** */ bool CreateHashList(); /** */ void CreateSearchIndex(); /** called on /rebuild command */ bool RebuildLists(); /** called to start hash leaf data verification */ bool ValidateLeaves(); /** */ ulonglong CalcShareSize(); /** thread callbackfunction */ virtual void Thread(); /** */ CString GetFileName( unsigned long fboid ); /** Returns true if a filelist refresh is in progress, otherwise returns false. */ bool IsCreateShareListRunning(); /** return the filetype */ eFileTypes GetFileType( CString file ); private: /** */ void ThreadCreateSearchIndex(); /** */ void ThreadCreateHashList(); /** */ void ThreadCreateShareList(); /** */ void ThreadCreateShareList( int depth, CString curr, CString relpath, double percent ); /** /rebuild lists */ void ThreadRebuildLists(); /** */ void ThreadValidateLeaves(); /** Called by CManager (via the callback) */ int FileManagerCallback(); /** */ ulonglong CalcShareSize( int depth, CString base, CString curr, CString relpath ); /** */ void InitFileTypeList(); /** */ FileNameSet * m_pFileNameSet; /** */ FileTypeMap m_FileTypeMap; /** */ CList m_SharedFolders; /** */ DCConfigShareFolder * m_pShareFolder; /** */ unsigned long m_nFileBaseIndex; /** */ CString m_sShareIndexBuffer; /** */ time_t m_tCreateShareListTimeout; /** */ CFileManagerInfo * m_pFileManagerInfo; /** */ _CCallback0 * m_pFileManagerCallback; /** search index class */ CSearchIndex * m_pSearchIndex; /** sharelist class */ CShareList * m_pShareList; /** */ CByteArray * m_pHashMemory; }; #endif libdc0-0.3.24~svn3121/dclib/cencrypt.cpp0000644000175000017500000000533511105673230016635 0ustar sikonsikon/*************************************************************************** cencrypt.cpp - description ------------------- begin : Sat Sep 29 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cencrypt.h" CEncrypt::CEncrypt() { } CEncrypt::~CEncrypt() { } /** */ void CEncrypt::Encrypt( CString s, CString & d ) { int v; int i; unsigned char u,l,o; d.Empty(); if ( s.Length() <= 3 ) { return; } u = s.Data()[0]; l = s.Data()[s.Length()-1]; o = s.Data()[s.Length()-2]; u = (char)(u ^ l ^ o ^ 0x05); v = ((u<<4)|(u>>4))&0xFF; Encode(v,d); for(i=1;i>4))&0xFF; Encode(v,d); } } /** */ void CEncrypt::Encode( int c, CString & d ) { // convert direct connect numerics switch(c&0xFF) { case 126: d.Append("/%DCN126%/"); break; case 124: d.Append("/%DCN124%/"); break; case 96: d.Append("/%DCN096%/"); break; case 36: d.Append("/%DCN036%/"); break; case 5: d.Append("/%DCN005%/"); break; case 0: d.Append("/%DCN000%/"); break; default: d.Append((char)c); break; } } /** */ CString CEncrypt::Encode( CString s ) { long i; CString tmp; for(i=0;i #include #include class CSearchIndex; class CShareTreeFolder { public: /** Constructor */ CShareTreeFolder( const CString & name, const CShareTreeFolder * parent ); /** Destructor - virtual in case something extends this class */ virtual ~CShareTreeFolder(); /** Gets the name */ const CString & GetName() const; /** Gets the parent folder object */ const CShareTreeFolder * GetParent() const; /** * Gets the list of child folders. * * Returns 0 not an empty list if no children. */ std::list * GetChildren() const; /** Adds a new subfolder */ CShareTreeFolder * AddFolder( const CString & name ); /** * Gets the list of files. * * Returns 0 not an empty list if no files. */ std::list * GetFiles() const; /** Adds a file */ void AddFile( const unsigned long int fbi ); /** * Gets the XML to given depth. * depth = -1 for unlimited */ CString GetXML( int depth, CSearchIndex * si ) const; /** */ private: /** The folder name */ const CString m_sName; /** The parent folder */ const CShareTreeFolder * m_pParent; /** List of folders */ std::list * m_pFolderList; /** List of files */ std::list * m_pFileList; }; #endif // CSHARETREEFOLDER_H libdc0-0.3.24~svn3121/dclib/cdcproto.h0000644000175000017500000001040311233301711016252 0ustar sikonsikon/*************************************************************************** cdcproto.h - description ------------------- begin : Sun Dec 15 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CDCPROTO_H #define CDCPROTO_H /** *@author Mathias Küster * * This builds various NMDC protocol strings and sends them. * * There are various legacy commands here, worst is * dclib's own chunked Get, also GetZBlock and UGetBlock are no * longer supported, ADCGET by filename is no longer * supported, and the escaping for the filename with that is not * the same as the current ADC protocol. */ #include #include #include #include #include #include class CMessageSearchFile; class CMessageMyInfo; class CDCProto : public CConnection { public: /** */ CDCProto( CString remoteEncoding = CString() ); /** */ virtual ~CDCProto(); /** chat message */ int SendChat( CString sNick, CString s ); /** send version info */ int SendVersion(); /** send myinfo */ int SendMyInfo( CMessageMyInfo * myinfo ); /** send key */ int SendKey( CString s ); /** send validate nick */ int SendValidateNick( CString sNick ); /** send send */ int SendSend(); /** send my nick and lock */ int SendMyNick( CString sNick, const CString & ref ); /** send get */ int SendGet( CString file, ulonglong pos, ulonglong size = 0 ); /** send GetZBlock */ int SendGetZBlock( CString file, ulonglong pos, ulonglong size = (ulonglong)-1 ); /** send UGetBlock */ int SendUGetBlock( CString file, ulonglong pos, ulonglong size = (ulonglong)-1 ); /** send UGetZBlock */ int SendUGetZBlock( CString file, ulonglong pos, ulonglong size = (ulonglong)-1 ); /** send direction */ int SendDirection( eDirection Direction, int level ); /** send private message */ virtual int SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick = CString() ); /** send request nick list */ virtual int RequestNickList(); /** send rev connect to me */ int SendRevConnectToMe( CString sNick, CString sDstNick ); /** send error */ int SendError( CString message ); /** */ int SendFileLength( ulonglong len ); /** */ int SendListLen( ulonglong len ); /** */ int SendGetListLen(); /** */ int SendConnectToMe( CString sDstNick, CString host, bool encrypt = false ); /** */ int SendCanceled(); /** send string */ int SendString( CString message, bool encode = true ); /** send password */ int SendPass( CString pass ); /** operator kick */ int SendKick( CString nick ); /** operator force move a user */ int SendOpForceMove( CString nick, CString host, CString message ); /** */ int SendMaxedOut(); /** */ int SendGetInfo( CString sNick, CString sMyNick ); /** */ int SendSupports( std::vector & supported, bool shuffle = true ); /** */ int SendSearch( CMessageSearchFile * msg ); /** $Sending numBytes| */ int SendSending( ulonglong length ); /** */ int SendADCGet( eADCType type, CString tth, ulonglong pos, long long size, bool zlib = false, CString file = CString() ); /** */ int SendADCSnd( eADCType type, CString tth, ulonglong pos, long long size, bool zlib = false, CString file = CString() ); private: /** */ CMutex DCProtoMutex; /** CIconv object for doing text encoding from local to remote */ CIconv * m_pLocalToRemote; /** CIconv object for doing local to UTF-8 for certain commands */ CIconv * m_pLocalToUTF8; }; #endif libdc0-0.3.24~svn3121/dclib/cmessagehandler.h0000644000175000017500000001117211101144617017572 0ustar sikonsikon/*************************************************************************** cmessagehandler.h - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CMESSAGEHANDLER_H #define CMESSAGEHANDLER_H /** *@author Mathias Küster * * This parses protocol strings and returns dclib objects. * * This always handles all protocol commands, although * some commands may only make sense for peer or hub connections, * or when those connections are in certain states. * * Also there may be some coding by copy and paste, since * some commands have the same content e.g. $ADCGET / $ADCSND. * * There are various legacy commands parsed, plus the protocol is * somewhat undefined, mostly anything unknown from the hub must be * shown as chat, what strings hubs are supposed to return in their * Supports response was apparently left open to interpretation, * some of the parameters for UserCommand may be optional although * they shouldn't be e.g. spacers without names. * * DC++ does not use LogedIn, so it should not be used. */ #include #include #include class CIconv; class CMessageHandler { public: /** */ CMessageHandler( CString remoteEncoding = CString() ); /** */ virtual ~CMessageHandler(); /** */ eDCMessage Parse( const CString * sMessage, int & pointer, CDCMessage ** DCMessage ); private: /** */ bool GetContent( const CString sMessage, const CString * sData, CString & sContent ); /** */ CDCMessage * ParseLock( const CString & sContent ); /** */ CDCMessage * ParseHello( const CString & sContent ); /** */ CDCMessage * ParseMyNick( const CString & sContent ); /** */ CDCMessage * ParseChat( const CString & sContent ); /** */ CDCMessage * ParseMyInfo( const CString & sContent ); /** */ CDCMessage * ParseNickList( const CString & sContent ); /** */ CDCMessage * ParseOpList( const CString & sContent ); /** */ CDCMessage * ParseConnectToMe( const CString & sContent ); /** */ CDCMessage * ParseRevConnectToMe( const CString & sContent ); /** */ CDCMessage * ParseQuit( const CString & sContent ); /** */ CDCMessage * ParseSearch( const CString & sContent ); /** */ CDCMessage * ParseSearchResult( const CString & sContent ); /** */ CDCMessage * ParseSearchResultFile( const CString & sContent ); /** */ CDCMessage * ParseSearchResultFolder( const CString & sContent ); /** */ CDCMessage * ParsePrivateChat( const CString & sContent ); /** */ CDCMessage * ParseForceMove( const CString & sContent ); /** */ CDCMessage * ParseDirection( const CString & sContent ); /** */ CDCMessage * ParseFileLength( const CString & sContent ); /** */ CDCMessage * ParseGet( const CString & sContent ); /** */ CDCMessage * ParseUGetBlock( const CString & sContent ); /** */ CDCMessage * ParseUGetZBlock( const CString & sContent ); /** */ CDCMessage * ParseError( const CString & sContent ); /** */ CDCMessage * ParseGetInfo( const CString & sContent ); /** */ CDCMessage * ParseHubName( const CString & sContent ); /** */ CDCMessage * ParseLogedIn( CString sContent ); /** */ CDCMessage * ParseSupports( CString sContent ); /** */ CDCMessage * ParseHubTopic( const CString & sContent ); /** */ CDCMessage * ParseUserCommand( const CString & sContent ); /** */ CDCMessage * ParseGetZBlock( const CString & sContent ); /** */ CDCMessage * ParseSending( const CString & sContent ); /** */ CDCMessage * ParseADCGet( const CString & sContent ); /** */ CDCMessage * ParseADCSnd( const CString & sContent ); /** Parse UserIP message */ CDCMessage * ParseUserIP( CString sContent ); /** CIconv object for doing text encoding remote to local */ CIconv * m_pRemoteToLocal; /** CIconv object for doing UTF-8 to local for certain commands */ CIconv * m_pUTF8ToLocal; }; #endif libdc0-0.3.24~svn3121/dclib/csharelist.h0000644000175000017500000000546011101144617016611 0ustar sikonsikon/*************************************************************************** csharelisr.h - description ------------------- begin : Mon May 12 2003 copyright : (C) 2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSHARELIST_H #define CSHARELIST_H /** *@author Mathias Küster * * This generates the filelist, both in obsolete text, and XML * formats. The index.lst text file is used because CSearchIndex * does not store directory structure. index.lst is basically a text * filelist but with indexes to the file in CSearchIndex in place of * the file size. * * To handle partial list requests ($ADCGET list ...), * CShareTreeFolder was added, which forms a tree structure, rather * than attempting to parse index.lst. */ #include #include #include #include class CByteArray; class CSearchIndex; class CShareTreeFolder; class CShareList { public: /** */ CShareList(); /** */ virtual ~CShareList(); /** */ bool Load(); /** */ void SetIndexBuffer( const CString & s ); /** * The share index buffer (contents of index.lst) is * no longer kept in memory after being used * so either Load() or SetIndexBuffer() must be used * before creating the listings. */ void CreateList( CSearchIndex * si ); /** */ ulonglong GetShareSize() const; /** */ unsigned long GetShareBufferSize( eShareBufferType type ); /** */ int GetShareBuffer( eShareBufferType type, CByteArray * sharebuffer, bool decompress = false ); /** */ void GetPartialListing( const CString & dir, CString & result, int depth, CSearchIndex * si ); private: /** */ void CreateBuffer( enum eShareBufferType e, const CString & sharebuffer ); /** */ void Save(); /** */ ulonglong m_nShareSize; /** */ CString m_sIndexShareBuffer; /** */ CByteArray * m_pHE3ShareBuffer; /** */ CByteArray * m_pBZShareBuffer; /** */ CByteArray * m_pXMLBZShareBuffer; /** */ CMutex m_MutexShareList; /** */ CShareTreeFolder * m_pRootItem; }; #endif libdc0-0.3.24~svn3121/dclib/cutils.cpp0000644000175000017500000001337411104415015016305 0ustar sikonsikon/*************************************************************************** cutils.cpp - description ------------------- begin : Fri May 16 2003 copyright : (C) 2003-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cutils.h" #include "chttp.h" /** */ CUtils::CUtils() { } /** */ CUtils::~CUtils() { } /** */ CString CUtils::GetSizeString( const ulonglong size, eUnit unit ) { CString s, suffix; double f; if ( (size > (1.0*1024*1024*1024*1024)) && (unit == euAUTO) ) { suffix = " TiB"; #ifndef WIN32 f = (size*1.0)/(1.0*1024*1024*1024*1024); #else f = ((longlong)size*1.0)/(1.0*1024*1024*1024*1024); #endif } else if ( ((size > (1024*1024*1024)) && (unit == euAUTO)) || (unit == euGBYTE) ) { suffix = " GiB"; #ifndef WIN32 f = (size*1.0)/(1024*1024*1024); #else f = ((longlong)size*1.0)/(1024*1024*1024); #endif } else if ( ((size > (1024*1024)) && (unit == euAUTO)) || (unit == euMBYTE) ) { suffix = " MiB"; #ifndef WIN32 f = (size*1.0)/(1024*1024); #else f = ((longlong)size*1.0)/(1024*1024); #endif } else if ( ((size > 1024) && (unit == euAUTO)) || (unit == euKBYTE) ) { suffix = " KiB"; #ifndef WIN32 f = (size*1.0)/1024; #else f = ((longlong)size*1.0)/1024; #endif } else if ( (unit == euAUTO) || (unit == euBYTE) ) { suffix = " B"; f = 0; } else { f = 0; } if ( f != 0 ) { s = CString::number(f,2); } else { s = CString::number(size); } s += suffix; return s; } /* This will Convert Total Secs to how much time is * remaining X Days + X Hrs + X Mins + X Secs */ CString CUtils::GetTimeString( const ulonglong sec ) { CString s; CString r = " S"; ulonglong rate = sec; if ( rate >= (60*60*24) ) { s += CString::number(rate/(60*60*24)); s += " D "; rate %= (60*60*24); } if ( rate >= (60*60) ) { s+= CString::number(rate/(60*60)).RightJustify(2,'0'); s+=':'; rate %= (60*60); } else { s+= "00:"; } if ( rate >= 60 ) { s += CString::number(rate/60).RightJustify(2,'0'); s += ':'; rate %= 60; } else { s+= "00:"; } s += CString::number(rate).RightJustify(2,'0'); return s; } /** */ CString CUtils::GetTransferString( const ulonglong rate ) { CString s; double f; if ( rate >= (1024*1024) ) { s = " MiB/s"; f = (rate*1.0)/(1024*1024); } else if ( rate >= 1024 ) { s = " KiB/s"; f = (rate*1.0)/(1024); } else { s = " B/s"; f = (rate*1.0); } return CString::number(f,2) + s; } /** */ bool CUtils::ConvertDCLink( CString link, CString & hubhost, CString & hubname, CString & nick, ulonglong & size, CString & file, CString & tth ) { bool res = false; long i,i1; CString s; CString tag; //printf("'%s'\n",link.Data()); if ( link.FindCase("DCFILE://") != 0 ) { return res; } link = link.Right( link.Length()-9 ); if ( (i=link.Find('?')) == -1 ) { return res; } hubhost = link.Left(i); link = "&" + link.Right( link.Length()-i-1 ); while( link.NotEmpty() ) { i1 = link.Find('&'); i = link.Find('&',i1+1); if ( i1 == -1 ) { break; } if ( i == -1 ) { i = link.Length(); } s = link.Left(i); link = link.Right( link.Length()-i ); if ( s.FindCase("&FILE=") == 0 ) file = CHttp::Decode(s.Right( s.Length()-6 )); else if ( s.FindCase("&NICK=") == 0 ) nick = CHttp::Decode(s.Right( s.Length()-6 )); else if ( s.FindCase("&HUB=") == 0 ) hubname = CHttp::Decode(s.Right( s.Length()-5 )); else if ( s.FindCase("&SIZE=") == 0 ) size = CHttp::Decode(s.Right( s.Length()-6 )).asULL(); else if ( s.FindCase("&HASH=") == 0 ) { tth = s.Right( s.Length()-6 ); if ( tth.Left(4).ToUpper() == "TTH:" ) { tth = tth.Mid(4); } } } //printf("'%s'\n",hubhost.Data()); //printf("'%s'\n",hubname.Data()); //printf("'%s'\n",nick.Data()); //printf("'%lld'\n",size); //printf("'%s'\n",file.Data()); if ( (hubhost.NotEmpty()) && (hubname.NotEmpty()) && (nick.NotEmpty()) && (file.NotEmpty()) ) { res = true; } return res; } /** */ bool CUtils::ParseVersionTag( const CString tag, int & major, int & minor, int & micro ) { int start = tag.Find("V:"); if ( start == -1 ) { return false; } start += 2; // length of "V:" int end = tag.Find(',',start); if ( end == -1 ) { return false; } CString ver = tag.Mid(start,end-start); //printf("start=%d end=%d ver=\"%s\"\n", start, end, ver.Data()); ver.Append('.'); CString first = ver.Section('.',0,0); CString second = ver.Section('.',1,1); CString third = ver.Section('.',2,2); //printf("first=%s second=%s third=%s\n", first.Data(), second.Data(), third.Data()); bool res = false; int i = first.asINT(); /* 0.3.22svn should parse to 0 3 22 */ if ( first.StartsWith(CString::number(i)) ) { res = true; major = i; } else { return false; } i = second.asINT(); if ( second.StartsWith(CString::number(i)) ) { minor = i; } else if ( res ) { minor = 0; } i = third.asINT(); if ( third.StartsWith(CString::number(i)) ) { micro = i; } else if ( res ) { micro = 0; } return res; } libdc0-0.3.24~svn3121/dclib/dcobject.cpp0000644000175000017500000002577211112566665016605 0ustar sikonsikon/*************************************************************************** dcobject.cpp - Various data objects used in dclib ------------------- begin : Thu Aug 21 2008 copyright : (C) 2002-2004 by Mathias Küster copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** * @author Edward Sheldrake * * 1. Some functions are way too big to be "inline". * 2. Everything with a list or pointer should have a proper copy constructor. * * So some "inline" code was moved out of dcobject.h to here. */ #include "dcobject.h" /** eveything is set to false */ CMessageSupports::CMessageSupports() : CDCMessage( DC_MESSAGE_SUPPORTS ) { m_bBZList = false; m_bSSL = false; m_bChunk = false; m_bMiniSlots = false; m_bXMLBZList = false; m_bZBlock = false; m_bADCGet = false; m_bTTHL = false; m_bTTHF = false; m_bZLIG = false; } /** */ CMessageSupports::~CMessageSupports() { // nothing } /** */ CMessageSupports & CMessageSupports::operator = ( const CMessageSupports & rhs ) { m_sContent = rhs.m_sContent; m_bBZList = rhs.m_bBZList; m_bSSL = rhs.m_bSSL; m_bChunk = rhs.m_bChunk; m_bMiniSlots = rhs.m_bMiniSlots; m_bXMLBZList = rhs.m_bXMLBZList; m_bZBlock = rhs.m_bZBlock; m_bADCGet = rhs.m_bADCGet; m_bTTHL = rhs.m_bTTHL; m_bTTHF = rhs.m_bTTHF; m_bZLIG = rhs.m_bZLIG; return *this; } /** */ CMessageNickList::CMessageNickList() : CDCMessage( DC_MESSAGE_NICKLIST ) { // nothing } /** */ CMessageNickList::CMessageNickList( const CMessageNickList & rhs ) : CDCMessage( DC_MESSAGE_NICKLIST ) { CString * it = 0; /* FIXME remove casting away the const once CList is fixed / removed */ while ( (it = ((CMessageNickList&)rhs).m_NickList.Next(it)) != 0 ) { m_NickList.Add( new CString(*it) ); } } /** */ CMessageNickList::~CMessageNickList() { // nothing } /** */ CMessageNickList & CMessageNickList::operator = (const CMessageNickList & rhs) { m_NickList.Clear(); CString * it = 0; /* FIXME remove casting away the const once CList is fixed / removed */ while ( (it = ((CMessageNickList&)rhs).m_NickList.Next(it)) != 0 ) { m_NickList.Add( new CString(*it) ); } return *this; } /** */ CMessageOpList::CMessageOpList() : CDCMessage( DC_MESSAGE_OPLIST ) { // nothing } /** */ CMessageOpList::CMessageOpList( const CMessageOpList & rhs ) : CDCMessage( DC_MESSAGE_OPLIST ) { CString * it = 0; /* FIXME remove casting away the const once CList is fixed / removed */ while ( (it = ((CMessageOpList&)rhs).m_NickList.Next(it)) != 0 ) { m_NickList.Add( new CString(*it) ); } } /** */ CMessageOpList::~CMessageOpList() { // nothing } /** */ CMessageOpList & CMessageOpList::operator = (const CMessageOpList & rhs) { m_NickList.Clear(); CString * it = 0; /* FIXME remove casting away the const once CList is fixed / removed */ while ( (it = ((CMessageOpList&)rhs).m_NickList.Next(it)) != 0 ) { m_NickList.Add( new CString(*it) ); } return *this; } /** */ CMessageMyInfo::CMessageMyInfo() : CDCMessage( DC_MESSAGE_MYINFO ) { m_nShared = 0; m_eUserSpeed = eusUNKNOWN; m_eAwayMode = euamNONE; m_eClientVersion = eucvNONE; m_eClientMode = ecmNONE; m_bValid = false; m_bOperator = false; m_bServerFlag = false; m_bFireballFlag = false; m_bTLSFlag = false; } /** */ CMessageMyInfo::CMessageMyInfo( eDCMessage type ) : CDCMessage( type ) { m_nShared = 0; m_eUserSpeed = eusUNKNOWN; m_eAwayMode = euamNONE; m_eClientVersion = eucvNONE; m_eClientMode = ecmNONE; m_bValid = false; m_bOperator = false; m_bServerFlag = false; m_bFireballFlag = false; m_bTLSFlag = false; } /** */ CMessageMyInfo::~CMessageMyInfo() { // nothing } /** */ CMessageMyInfo & CMessageMyInfo::operator = (const CMessageMyInfo & rhs ) { m_MessageLock = rhs.m_MessageLock; m_MessageSupports = rhs.m_MessageSupports; m_sNick = rhs.m_sNick; m_sComment = rhs.m_sComment; m_sUnknown = rhs.m_sUnknown; m_sUserSpeed = rhs.m_sUserSpeed; m_sEMail = rhs.m_sEMail; m_sVerComment = rhs.m_sVerComment; m_sTransferHost = rhs.m_sTransferHost; m_nShared = rhs.m_nShared; m_eUserSpeed = rhs.m_eUserSpeed; m_eAwayMode = rhs.m_eAwayMode; m_eClientVersion = rhs.m_eClientVersion; m_eClientMode = rhs.m_eClientMode; m_bValid = rhs.m_bValid; m_bOperator = rhs.m_bOperator; m_bServerFlag = rhs.m_bServerFlag; m_bFireballFlag = rhs.m_bFireballFlag; m_bTLSFlag = rhs.m_bTLSFlag; return *this; } /** */ CMessageDMFileObject::CMessageDMFileObject() : CDCMessage( DC_MESSAGE_FILE_OBJECT ) { m_tTimeout = 0; m_eTransferWaitState = etwsWAIT; m_nConnections = 0; m_eTransferFileState = etfsNONE; m_nSize = 0; m_nStartPosition = 0; m_nCurrentPosition = 0; m_nEndPosition = 0; m_bMulti = false; m_bRemoveFile = false; m_nPriority = 0; m_pDirList = 0; } /** */ CMessageDMFileObject::CMessageDMFileObject( const CMessageDMFileObject & rhs ) : CDCMessage( DC_MESSAGE_FILE_OBJECT ) { m_sNick = rhs.m_sNick; m_sHubName = rhs.m_sHubName; m_sHubHost = rhs.m_sHubHost; m_sRemoteFile = rhs.m_sRemoteFile; m_sLocalFile = rhs.m_sLocalFile; m_sTTH = rhs.m_sTTH; m_tTimeout = rhs.m_tTimeout; m_eTransferWaitState = rhs.m_eTransferWaitState; m_nConnections = rhs.m_nConnections; m_eTransferFileState = rhs.m_eTransferFileState; m_nSize = rhs.m_nSize; m_nStartPosition = rhs.m_nStartPosition; m_nCurrentPosition = rhs.m_nCurrentPosition; m_nEndPosition = rhs.m_nEndPosition; m_nPriority = rhs.m_nPriority; m_bMulti = rhs.m_bMulti; m_bRemoveFile = rhs.m_bRemoveFile; if ( rhs.m_pDirList ) { m_pDirList = new std::list(); *m_pDirList = *(rhs.m_pDirList); } else { m_pDirList = 0; } } /** */ CMessageDMFileObject::~CMessageDMFileObject() { delete m_pDirList; m_pDirList = 0; } /** */ CMessageDMFileObject & CMessageDMFileObject::operator = (const CMessageDMFileObject & rhs) { m_sNick = rhs.m_sNick; m_sHubName = rhs.m_sHubName; m_sHubHost = rhs.m_sHubHost; m_sRemoteFile = rhs.m_sRemoteFile; m_sLocalFile = rhs.m_sLocalFile; m_sTTH = rhs.m_sTTH; m_tTimeout = rhs.m_tTimeout; m_eTransferWaitState = rhs.m_eTransferWaitState; m_nConnections = rhs.m_nConnections; m_eTransferFileState = rhs.m_eTransferFileState; m_nSize = rhs.m_nSize; m_nStartPosition = rhs.m_nStartPosition; m_nCurrentPosition = rhs.m_nCurrentPosition; m_nEndPosition = rhs.m_nEndPosition; m_nPriority = rhs.m_nPriority; m_bMulti = rhs.m_bMulti; m_bRemoveFile = rhs.m_bRemoveFile; if ( m_pDirList ) { if ( rhs.m_pDirList ) { *m_pDirList = *(rhs.m_pDirList); } else { delete m_pDirList; m_pDirList = 0; } } else if ( rhs.m_pDirList ) { m_pDirList = new std::list(); *m_pDirList = *(rhs.m_pDirList); } return *this; } /** */ CMessageDMTransferObject::CMessageDMTransferObject() : CDCMessage( DC_MESSAGE_TRANSFER_OBJECT ) { m_nTransferID = 0; eState = estNONE; lSize = 0; lSizeDone = 0; lRate = 0; m_nMultiRate = 0; lStartPosition = 0; lTransfered = 0; lEndPosition = 0; bRemoveTransfer = false; m_bEncrypted = false; } /** */ CMessageDMTransferObject::~CMessageDMTransferObject() { // nothing } /** */ CMessageDMTransferObject & CMessageDMTransferObject::operator = (const CMessageDMTransferObject & rhs) { m_nTransferID = rhs.m_nTransferID; m_sSrcNick = rhs.m_sSrcNick; m_sDstNick = rhs.m_sDstNick; sHost = rhs.sHost; m_sHubHost = rhs.m_sHubHost; sHubName = rhs.sHubName; m_sDstFile = rhs.m_sDstFile; m_sSrcFile = rhs.m_sSrcFile; m_sTTH = rhs.m_sTTH; eState = rhs.eState; lSize = rhs.lSize; lSizeDone = rhs.lSizeDone; lRate = rhs.lRate; m_nMultiRate = rhs.m_nMultiRate; lStartPosition = rhs.lStartPosition; lTransfered = rhs.lTransfered; lEndPosition = rhs.lEndPosition; bRemoveTransfer = rhs.bRemoveTransfer; m_bEncrypted = rhs.m_bEncrypted; return *this; } /** */ CMessageDMFileListObject::CMessageDMFileListObject() : CDCMessage( DC_MESSAGE_FILELIST_OBJECT ) { m_pDirList = 0; } /** */ CMessageDMFileListObject::CMessageDMFileListObject( const CMessageDMFileListObject & rhs ) : CDCMessage( DC_MESSAGE_FILELIST_OBJECT ) { sNick = rhs.sNick; sHubName = rhs.sHubName; sHubHost = rhs.sHubHost; sLocalFile = rhs.sLocalFile; sJumpTo = rhs.sJumpTo; if ( rhs.m_pDirList ) { m_pDirList = new std::list(); *m_pDirList = *(rhs.m_pDirList); } else { m_pDirList = 0; } } /** */ CMessageDMFileListObject::~CMessageDMFileListObject() { delete m_pDirList; m_pDirList = 0; } /** */ CMessageDMFileListObject & CMessageDMFileListObject::operator = (const CMessageDMFileListObject & rhs) { sNick = rhs.sNick; sHubName = rhs.sHubName; sHubHost = rhs.sHubHost; sLocalFile = rhs.sLocalFile; sJumpTo = rhs.sJumpTo; if ( m_pDirList ) { if ( rhs.m_pDirList ) { *m_pDirList = *(rhs.m_pDirList); } else { delete m_pDirList; m_pDirList = 0; } } else if ( rhs.m_pDirList ) { m_pDirList = new std::list(); *m_pDirList = *(rhs.m_pDirList); } return *this; } /** */ CMessageSearchFile::CMessageSearchFile() : CDCMessage( DC_MESSAGE_SEARCH_FILE ) { m_nPort = 0; m_eSizeType = esstATLEAST; m_nSize = 0; m_eFileType = eftUNKNOWN; m_bSizeLimit = false; m_bLocal = false; m_bExtended = false; m_bMulti = false; } /** */ CMessageSearchFile::~CMessageSearchFile() { // nothing } CMessageSearchFile & CMessageSearchFile::operator = (const CMessageSearchFile & rhs) { m_sString = rhs.m_sString; m_sSource = rhs.m_sSource; m_nPort = rhs.m_nPort; m_eSizeType = rhs.m_eSizeType; m_nSize = rhs.m_nSize; m_eFileType = rhs.m_eFileType; m_bSizeLimit = rhs.m_bSizeLimit; m_bLocal = rhs.m_bLocal; m_bExtended = rhs.m_bExtended; m_bMulti = rhs.m_bMulti; return *this; } libdc0-0.3.24~svn3121/dclib/ctransfer.h0000644000175000017500000003307311131224633016440 0ustar sikonsikon/*************************************************************************** ctransfer.h - description ------------------- begin : Fri Feb 22 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CTRANSFER_H #define CTRANSFER_H /** *@author Mathias Küster * * This class handles a file transfer, reading or writing to the file, * possibly doing zlib compression or decompression. * * Perhaps the worst thing missing from this class, and dclib overall, is * that there is no verification of the data received using the TTH leaf data. * * The TTH leaf data should basically be a list of TTHs, for sections of the * file, you can check the leaf data matches the root (by hashing it), and * then hash the data as it is received. * * This class is an awful mess mainly for all the obsolete protocol command * support, but also due to compressed transfers (most things are not even * compressible anyway). */ #include #include #include #include #include #include #include #ifndef WIN32 #include #endif class CByteArray; enum eTransferState { etsNONE, etsREADY, etsIDLE }; /* * Warning: these are not in order the types of slot are allocated. * Changes for 0.3.22: * - total upload rate dependant extra normal slots added (O: in DC++ tag) * - if a user is granted a slot, the user may still get a normal slot, * and this still uses up the granted slot * - operator slots were fixed, and now may actually be allocated after special slots * * Previously operator slots were broken (never given), which is lucky * because they would have prevented operators getting small files when * normal users could. Also slots granted to users caused that * user to not use a normal slot. I think the idea of slots granted to * users is to allow friends to get files when normal slots are used, not to * allow normal users to get files while your friends are busy downloading. * * SETTINGS, RATE_EXTRA and USER are all normal slots allowing all uploads, * but SPECIAL is limited and OPERATOR more limited. So 3 types of slot * but 5 ways for some kind of slot to be given (3,1,1 for normal,mini,op). */ enum eTransferType { ettNONE, /* unknown */ ettSETTINGS, /* normal slot from settings slot limit */ ettOPERATOR, /* 1 of 4 slots for operators to get the filelist */ ettUSER, /* normal slot granted to a user */ ettSPECIAL, /* 1 of 4 slots for small files,filelist,leaves */ ettRATE_EXTRA /* normal slot allocated because total upload rate was below minimum */ }; typedef struct sAverageTransferRate { struct timeval tv[10]; ulonglong transfered[10]; int index; } sAverageTransferRate; class CTransfer : public CDCProto { public: /** */ CTransfer( bool listener = false ); /** */ virtual ~CTransfer(); /** callback function */ virtual int DC_CallBack( CDCMessage * ) { return -1; }; /** */ virtual void DataAvailable( const char * buffer, int len ); /** */ virtual void DataSend(); /** */ virtual void DataTimeout(); /** */ virtual void ConnectionState( eConnectionState state ); /** */ virtual void Notify(); /** */ void SetCallBackFunction( _CCallback2 * callback ); /** */ int StartDownload( CString dstfile, ulonglong startposition, ulonglong endposition, ulonglong size, ulonglong chunksize, CString srcfile, CString adcTTH = CString() ); /** */ int StartUpload( CString dstfile, ulonglong length, ulonglong pos, ulonglong chunksize, CString srcfile, bool uget = false, bool adcget = false, CString adcTTH = CString(), bool compress = false ); /** */ int CallBack_SendObject( CDCMessage * DCMessage ); /** */ int CallBack_SendError( CString msg ); /** */ ulonglong GetTransferrate(); /** */ ulonglong GetBytesForTransferrate( ulonglong rate ); /** */ void AddTraffic( long n ); /** */ ulonglong GetTraffic(); /** */ int HandleMessage( char * c, int len ); /** */ void CloseFile() { m_File.Close(); }; /** */ ulonglong GetTransferID() const; /** */ void SetTransferID( ulonglong transferid ); /** */ CString GetDstFilename() const; /** */ void SetDstFilename( CString filename ); /** */ CString GetSrcFilename() const; /** */ void SetSrcFilename( CString filename ); /** */ CString GetDstNick() const; /** */ CString GetHubHost() const; /** */ void SetHubHost( CString hubhost ); /** */ CString GetHubName() const; /** */ void SetHubName( CString hubname ); /** */ eltMedium GetMedium() const; /** */ void SetMedium( eltMedium medium ); /** */ long GetBuffer( CByteArray *ba ); /** */ bool SaveBufferToFile( const CString & filename ); /** */ void SetBuffer( CByteArray *ba ); /** * This is to avoid creating an intermediate CByteArray for ADCGET list transfers. */ void ClearAndAppendBuffer( const unsigned char * data, const unsigned long length ); /** */ eDirection GetSrcDirection() const; /** */ void SetSrcDirection( eDirection direction ); /** */ eDirection GetDstDirection() const; /** */ void SetDstDirection( eDirection direction ); /** */ int GetSrcLevel() const; /** */ int GetDstLevel() const; /** */ eConnectionState GetMode() const; /** */ void SetMode( eConnectionState mode ); /** */ ulonglong GetStartPosition() const; /** */ void SetStartPosition( ulonglong pos ); /** */ ulonglong GetEndPosition() const; /** */ void SetEndPosition( ulonglong pos ); /** */ ulonglong GetLength() const; /** */ void SetLength( ulonglong length ); /** */ ulonglong GetTransfered() const; /** */ void SetTransfered( ulonglong n ) { m_nTransfered = n; }; /** */ ulonglong GetChunkSize() const { return m_nChunkSize; }; /** */ void SetChunkSize( ulonglong n ) { m_nChunkSize = n; }; /** */ void InitTime(); /** */ void SetNick( CString nick ); /** */ CString GetNick(); /** */ void SetRate( ulonglong rate ); /** */ ulonglong GetRate() const; /** */ bool IsIdle() const; /** */ void SetDone( eTransferState e ); /** */ eTransferState GetDone() const; /** */ time_t GetStartTime() const; /** */ void SetStartTime( time_t t ); /** */ eTransferType GetTransferType() const; /** */ void SetTransferType( eTransferType type ); /** */ CMessageSupports GetSupport() { return m_MessageSupports; } /** */ bool GetEncrypted(); /** */ bool SupportsChunks() const; /** */ CString GetTTH() const; /** */ void SetTTH( const CString & newtth ); /** */ bool IsListener() const { return m_bListener; }; private: /** */ bool DoInitDownload(); /** */ void DoInitUpload(); /** */ int HandleFileTransfer( const char * buffer, int len ); /** */ int HandleBufferTransfer( const char * buffer, int len ); /** */ int HandleControlTransfer( const char * buffer, int len ); /** Send SSL messages to GUI */ void SendSSLInfo(); /** */ int m_nDataType; /** */ ulonglong m_nTransferID; /** */ CString sNick; /** */ CString sBuffer; /** remote filesize */ ulonglong m_nFileSize; /** start transfer from this fileposition */ ulonglong m_nStartPosition; /** */ ulonglong m_nEndPosition; /** bytes transfered */ ulonglong m_nTransfered; /** wanted bytes */ ulonglong m_nChunkSize; /** */ bool m_bListener; /** */ long m_nFileBufferPos; /** */ long m_nFileBufferSize; /** */ ulonglong m_nTransferRate; /** */ eConnectionState eMode; /** */ eltMedium eMedium; /** */ bool m_bIdle; /** */ CFile m_File; /** */ CByteArray * pByteArray; /** local filename */ CString sSrcFilename; /** remote filename */ CString sDstFilename; /** local direction */ eDirection eSrcDirection; /** remote direction */ eDirection eDstDirection; /** remote nick */ CString sDstNick; /** local level */ int m_nSrcLevel; /** local level */ int m_nDstLevel; /** identifier hubname */ CString sHubName; /** identifier hubhost:hubport */ CString sHubHost; /** */ struct timeval starttime; /** */ ulonglong m_nPendingSendBytes; /** */ CMutex TransferMutex; /** callback function */ _CCallback2 * pCallback; /** */ eTransferState m_eTransferState; /** */ eTransferType m_eTransferType; /** */ CMessageSupports m_MessageSupports; /** Disable XML filelists for DC++ >= 0.307 and <= 0.403 */ bool m_bDisableXML; /** */ struct sAverageTransferRate m_AverageTransferRate; /** */ CZLib m_ZLib; /** used to compress uploads */ CDeflater m_Deflater; /** size of read buffer */ long m_nReadFileBufferSize; /** last return value from czlib/cdeflater */ int m_nZlibStatus; /** file TTH */ CString m_sTTH; }; /** */ inline CString CTransfer::GetDstFilename() const { return sDstFilename; } /** */ inline void CTransfer::SetDstFilename( CString filename ) { TransferMutex.Lock(); sDstFilename=filename; TransferMutex.UnLock(); } /** */ inline CString CTransfer::GetSrcFilename() const { return sSrcFilename; } /** */ inline void CTransfer::SetSrcFilename( CString filename ) { TransferMutex.Lock(); sSrcFilename=filename; TransferMutex.UnLock(); } /** */ inline CString CTransfer::GetDstNick() const { return sDstNick; } /** */ inline CString CTransfer::GetHubHost() const { return sHubHost; } /** */ inline void CTransfer::SetHubHost( CString hubhost ) { TransferMutex.Lock(); sHubHost=hubhost; TransferMutex.UnLock(); } /** */ inline CString CTransfer::GetHubName() const { return sHubName; } /** */ inline void CTransfer::SetHubName( CString hubname ) { TransferMutex.Lock(); sHubName=hubname; TransferMutex.UnLock(); } /** */ inline void CTransfer::SetMedium( eltMedium medium ) { TransferMutex.Lock(); eMedium=medium; TransferMutex.UnLock(); } /** */ inline eltMedium CTransfer::GetMedium() const { return eMedium; } /** */ inline eDirection CTransfer::GetSrcDirection() const { return eSrcDirection; } /** */ inline void CTransfer::SetSrcDirection( eDirection direction ) { TransferMutex.Lock(); eSrcDirection = direction; TransferMutex.UnLock(); } /** */ inline eDirection CTransfer::GetDstDirection() const { return eDstDirection; } /** */ inline void CTransfer::SetDstDirection( eDirection direction ) { TransferMutex.Lock(); eDstDirection = direction; TransferMutex.UnLock(); } /** */ inline int CTransfer::GetSrcLevel() const { return m_nSrcLevel; } /** */ inline int CTransfer::GetDstLevel() const { return m_nDstLevel; } /** */ inline eConnectionState CTransfer::GetMode() const { return eMode; } /** */ inline void CTransfer::SetMode( eConnectionState mode ) { TransferMutex.Lock(); eMode = mode; TransferMutex.UnLock(); } /** */ inline ulonglong CTransfer::GetStartPosition() const { return m_nStartPosition; } /** */ inline void CTransfer::SetStartPosition( ulonglong pos ) { TransferMutex.Lock(); m_nStartPosition=pos; TransferMutex.UnLock(); } /** */ inline ulonglong CTransfer::GetEndPosition() const { return m_nEndPosition; } /** */ inline void CTransfer::SetEndPosition( ulonglong pos ) { TransferMutex.Lock(); m_nEndPosition=pos; TransferMutex.UnLock(); } /** */ inline ulonglong CTransfer::GetLength() const { return m_nFileSize; } /** */ inline void CTransfer::SetLength( ulonglong length ) { TransferMutex.Lock(); m_nFileSize = length; TransferMutex.UnLock(); } /** */ inline ulonglong CTransfer::GetTransfered() const { return m_nTransfered; } /** */ inline void CTransfer::SetNick(CString nick) { TransferMutex.Lock(); sNick=nick; TransferMutex.UnLock(); } /** */ inline CString CTransfer::GetNick() { return sNick; } /** */ inline void CTransfer::SetRate( ulonglong rate ) { TransferMutex.Lock(); m_nTransferRate=rate; TransferMutex.UnLock(); } /** */ inline ulonglong CTransfer::GetRate() const { return m_nTransferRate; } /** */ inline bool CTransfer::IsIdle() const { return m_bIdle; } /** */ inline void CTransfer::SetCallBackFunction( _CCallback2 * callback ) { TransferMutex.Lock(); delete pCallback; pCallback = callback; TransferMutex.UnLock(); } /** */ inline void CTransfer::SetDone( eTransferState e ) { TransferMutex.Lock(); m_eTransferState = e; TransferMutex.UnLock(); } /** */ inline eTransferState CTransfer::GetDone() const { return m_eTransferState; } /** */ inline time_t CTransfer::GetStartTime() const { return starttime.tv_sec; } /** */ inline void CTransfer::SetStartTime( time_t t ) { TransferMutex.Lock(); starttime.tv_sec = t; TransferMutex.UnLock(); } /** */ inline ulonglong CTransfer::GetTransferID() const { return m_nTransferID; } /** */ inline void CTransfer::SetTransferID( ulonglong transferid ) { TransferMutex.Lock(); m_nTransferID = transferid; TransferMutex.UnLock(); } /** */ inline eTransferType CTransfer::GetTransferType() const { return m_eTransferType; } /** */ inline void CTransfer::SetTransferType( eTransferType type ) { TransferMutex.Lock(); m_eTransferType = type; TransferMutex.UnLock(); } /** */ inline CString CTransfer::GetTTH() const { return m_sTTH; } /** */ inline void CTransfer::SetTTH( const CString & newtth ) { TransferMutex.Lock(); m_sTTH = newtth; TransferMutex.UnLock(); } #endif libdc0-0.3.24~svn3121/dclib/cencrypt.h0000644000175000017500000000304311101144617016272 0ustar sikonsikon/*************************************************************************** cencrypt.h - description ------------------- begin : Sat Sep 29 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CENCRYPT_H #define CENCRYPT_H /** *@author Mathias Küster * * This class is just badly named, it does the lock to key * routine, including the %DCN???% escaping. */ #include #include class CEncrypt { public: /** */ static void Encrypt( CString s, CString & d ); /** */ static void Encode( int c, CString & d ); /** */ static CString Encode( CString s ); /** */ static CString Decode( CString s ); protected: /** */ CEncrypt(); /** */ virtual ~CEncrypt(); }; #endif libdc0-0.3.24~svn3121/dclib/cdownloadqueue.cpp0000644000175000017500000002406511123245702020025 0ustar sikonsikon/*************************************************************************** cdownloadqueue.cpp - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cdownloadqueue.h" #include #include "core/cmutex.h" #include "cconnectionmanager.h" /** */ CDownloadQueue::CDownloadQueue() { pQueueMutex = new CMutex(); pQueue = new CStringList >(); pChunksMutex = new CMutex(); pChunkList = new CStringList(); } /** */ CDownloadQueue::~CDownloadQueue() { delete pQueue; pQueue = 0; delete pQueueMutex; pQueueMutex = 0; delete pChunkList; pChunkList = 0; delete pChunksMutex; pChunksMutex = 0; } /** */ CStringList * CDownloadQueue::GetUserHubList( CString nick ) { CStringList * StringList = 0; if ( pQueue->Get( nick, &StringList ) == 0 ) { return StringList; } return 0; } /** */ bool CDownloadQueue::RenameNick( CString srcnick, CString dstnick, CString srchubname, CString dsthubname ) { CStringList * StringList = 0; DCTransferQueueObject * TransferObject = 0; bool res = false; // get the transferobject if ( (TransferObject = GetUserTransferObject( srcnick, srchubname, CString() )) != 0 ) { // made changes TransferObject->sNick = dstnick; TransferObject->sHubName = dsthubname; // update the lists if ( pQueue->Get( srcnick, &StringList ) == 0 ) { StringList->Remove( srchubname ); if ( StringList->Count() == 0 ) pQueue->Del(srcnick); if ( pQueue->Get( dstnick, &StringList ) != 0 ) { StringList = new CStringList(); pQueue->Add( dstnick, StringList ); } StringList->Add( dsthubname, TransferObject ); res = true; } } return res; } /** */ DCTransferQueueObject * CDownloadQueue::GetUserTransferObject( CString nick, CString hubname, CString /* hubhost */ ) { CStringList * StringList = 0; DCTransferQueueObject * TransferObject = 0; if ( (StringList = GetUserHubList( nick )) != 0 ) { if ( StringList->Get( hubname, &TransferObject ) == 0 ) { return TransferObject; } else if ( CConnectionManager::Instance() ) { CString name, host, ip; if ( CConnectionManager::Instance()->GetHubDetails( hubname, name, host, ip ) ) { if ( StringList->Get( ip, &TransferObject ) == 0 ) { return TransferObject; } else if ( StringList->Get( name, &TransferObject ) == 0 ) { return TransferObject; } else if ( StringList->Get( host, &TransferObject ) == 0 ) { return TransferObject; } } } } return 0; } /** */ DCTransferFileObject * CDownloadQueue::GetUserFileObject( CString nick, CString hubname, CString hubhost, CString remotename ) { DCTransferFileObject * TransferFileObject = 0; DCTransferQueueObject * TransferObject = 0; if ( (TransferObject = GetUserTransferObject( nick, hubname, hubhost )) != 0 ) { if ( TransferObject->pTransferFileList.Get( remotename, &TransferFileObject ) == 0 ) { return TransferFileObject; } } return 0; } /** */ bool CDownloadQueue::DelUserFileObject( CString nick, CString hubname, CString hubhost, CString remotefile ) { bool res = false,err; CStringList * StringList = 0; DCTransferQueueObject * TransferObject = 0; DCTransferFileObject * TransferFileObject = 0; if ( (TransferObject = GetUserTransferObject( nick, hubname, hubhost ) ) != 0 ) { if ( remotefile.NotEmpty() ) { // remove a single file if ( TransferObject->pTransferFileList.Get( remotefile, &TransferFileObject ) == 0 ) { if ( TransferFileObject->m_eState == etfsTRANSFER ) { printf("warning ! file transfer is running ...\n"); } else { RemoveChunk(TransferFileObject->m_sLocalFile); TransferObject->pTransferFileList.Del(remotefile); res = true; } } } else { // remove a file tree TransferFileObject = 0; err = false; while ( TransferObject->pTransferFileList.Next( &TransferFileObject ) ) { if ( TransferFileObject->m_eState == etfsTRANSFER ) { printf("warning ! file transfer is running ...\n"); err = true; break; } else { RemoveChunk(TransferFileObject->m_sLocalFile); } } if ( err == false ) { if ( (StringList = GetUserHubList(nick)) != 0 ) { StringList->Del(hubname); if ( StringList->Count() == 0 ) { pQueue->Del(nick); } res = true; } } } } else { printf("warning ! queue not found ...\n"); } return res; } /** */ bool CDownloadQueue::RemoveChunk( CString localfile ) { bool res = false; DCFileChunkObject * FileChunkObject = 0; // update file chunks pChunksMutex->Lock(); if ( pChunkList->Get( localfile, &FileChunkObject ) == 0 ) { res = true; FileChunkObject->m_nReferenceCount--; if ( FileChunkObject->m_nReferenceCount == 0 ) { pChunkList->Del(localfile); } } pChunksMutex->UnLock(); return res; } /** */ DCFileChunkObject * CDownloadQueue::GetFileChunkObject( CString file ) { DCFileChunkObject * FileChunkObject = 0; pChunkList->Get( file, &FileChunkObject ); return FileChunkObject; } /** */ DCTransferFileObject::DCTransferFileObject() { m_eMedium = eltNONE; m_eState = etfsNONE; m_nSize = 0; m_bMulti = false; m_nPriority = 0; m_pDirList = 0; } /** */ DCTransferFileObject::DCTransferFileObject( const DCTransferFileObject & other ) { m_stHash = other.m_stHash; m_sHash = other.m_sHash; m_eMedium = other.m_eMedium; m_sRemoteFile = other.m_sRemoteFile; m_sLocalFile = other.m_sLocalFile; m_sLocalPath = other.m_sLocalPath; m_sLocalFileName = other.m_sLocalFileName; m_eState = other.m_eState; m_nSize = other.m_nSize; m_bMulti = other.m_bMulti; m_nPriority = other.m_nPriority; m_sJumpTo = other.m_sJumpTo; if ( other.m_pDirList ) { m_pDirList = new std::list(); *m_pDirList = *(other.m_pDirList); } else { m_pDirList = 0; } } /** */ DCTransferFileObject::~DCTransferFileObject() { delete m_pDirList; m_pDirList = 0; } /** */ void DCTransferFileObject::copy( DCTransferFileObject * TransferFileObject ) { if( !TransferFileObject ) { return; } m_stHash = TransferFileObject->m_stHash; m_sHash = TransferFileObject->m_sHash; m_eMedium = TransferFileObject->m_eMedium; m_sRemoteFile = TransferFileObject->m_sRemoteFile; m_sLocalFile = TransferFileObject->m_sLocalFile; m_sLocalPath = TransferFileObject->m_sLocalPath; m_sLocalFileName = TransferFileObject->m_sLocalFileName; m_eState = TransferFileObject->m_eState; m_nSize = TransferFileObject->m_nSize; m_bMulti = TransferFileObject->m_bMulti; m_nPriority = TransferFileObject->m_nPriority; m_sJumpTo = TransferFileObject->m_sJumpTo; if ( TransferFileObject->m_pDirList ) { if ( !m_pDirList ) { m_pDirList = new std::list(); } *m_pDirList = *(TransferFileObject->m_pDirList); } else if ( m_pDirList ) { delete m_pDirList; m_pDirList = 0; } } /** */ DCFileChunkObject::DCFileChunkObject() { m_bMulti = false; m_nSize = 0; m_nSizeDone = 0; m_nReferenceCount = 0; } /** */ DCFileChunkObject::DCFileChunkObject( const DCFileChunkObject & other ) { m_sLocalFile = other.m_sLocalFile; m_stHash = other.m_stHash; m_sHash = other.m_sHash; m_bMulti = other.m_bMulti; m_nSize = other.m_nSize; m_nSizeDone = other.m_nSizeDone; m_nReferenceCount = other.m_nReferenceCount; DCChunkObject * ChunkObject = 0; /* FIXME remove casting away the const once CList is fixed / removed */ while ( (ChunkObject=((DCFileChunkObject&)other).m_Chunks.Next(ChunkObject)) != 0 ) { m_Chunks.Add( new DCChunkObject(ChunkObject) ); } } /** */ DCFileChunkObject::DCFileChunkObject( const DCFileChunkObject * other ) { m_sLocalFile = other->m_sLocalFile; m_stHash = other->m_stHash; m_sHash = other->m_sHash; m_bMulti = other->m_bMulti; m_nSize = other->m_nSize; m_nSizeDone = other->m_nSizeDone; m_nReferenceCount = other->m_nReferenceCount; DCChunkObject * ChunkObject = 0; /* FIXME remove casting away the const once CList is fixed / removed */ while ( (ChunkObject=((DCFileChunkObject*)other)->m_Chunks.Next(ChunkObject)) != 0 ) { m_Chunks.Add( new DCChunkObject(ChunkObject) ); } } /** */ DCFileChunkObject::~DCFileChunkObject() { // nothing due to CList auto-delete } /** */ bool DCTransferWait::Match( const CString & nick, const CString & userhost ) { if ( sNick.NotEmpty() ) { if ( sNick == nick ) { if ( sUserHost.NotEmpty() ) { if ( sUserHost == userhost ) { // printf("DCTransferWait::Match: matched nick and userhost\n"); return true; } } else { sUserHost = userhost; // printf("DCTransferWait::Match: set userhost for %s to %s\n",sNick.Data(),sUserHost.Data()); return true; } } } else if ( sUserHost.NotEmpty() ) { if ( sUserHost == userhost ) { sNick = nick; // printf("DCTransferWait::Match: set nick for %s to %s\n",sUserHost.Data(),sNick.Data()); return true; } } return false; } libdc0-0.3.24~svn3121/dclib/Makefile.am0000644000175000017500000000302311144263010016320 0ustar sikonsikonlib_LTLIBRARIES = libdc.la SUBDIRS = gnulib core hash libdc_la_SOURCES = \ ccasefolder.cpp \ cclient.cpp \ cclientssl.cpp \ cconfig.cpp \ cconnectionmanager.cpp \ cdcproto.cpp \ cdownloadmanager.cpp \ cdownloadqueue.cpp \ cencrypt.cpp \ cfilehasher.cpp \ cfilemanager.cpp \ chttp.cpp \ chublistmanager.cpp \ clistenmanager.cpp \ cmessagehandler.cpp \ cpluginmanager.cpp \ cquerymanager.cpp \ csearchindex.cpp \ csearchmanager.cpp \ csearchsocket.cpp \ csharelist.cpp \ csharetreefolder.cpp \ ctransfer.cpp \ cuserlist.cpp \ cutils.cpp \ dclib.cpp \ dcobject.cpp libdc_la_LDFLAGS = -version-info 5:0:0 $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SSL_LDFLAGS) $(LIBICONV) -rdynamic libdc_la_LIBADD = core/libcore.la hash/libhash.la AM_CXXFLAGS = @CXXFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir) $(PACKAGE_FLAGS) -DDCLIB_PLUGINDIR='"$(pkglibdir)/plugin"' $(SSL_CPPFLAGS) library_includedir=$(includedir)/dclib-0.3/dclib library_include_HEADERS = \ ccasefolder.h \ cclient.h \ cclientssl.h \ cconfig.h \ cconnectionmanager.h \ cdcproto.h \ cdownloadmanager.h \ cdownloadqueue.h \ cencrypt.h \ cfilehasher.h \ cfilemanager.h \ chttp.h \ chublistmanager.h \ clistenmanager.h \ cmessagehandler.h \ cpluginmanager.h \ cquerymanager.h \ csearchindex.h \ csearchmanager.h \ csearchsocket.h \ csharelist.h \ csharetreefolder.h \ ctransfer.h \ cuserlist.h \ cutils.h \ dclib.h \ dclib-ssl-use.h \ dclib-stl-use.h \ dcobject.h \ dcos.h install-data-local: $(mkinstalldirs) $(DESTDIR)$(pkglibdir) $(mkinstalldirs) $(DESTDIR)$(pkglibdir)/plugin libdc0-0.3.24~svn3121/dclib/cpluginmanager.cpp0000644000175000017500000001071611101154437020000 0ustar sikonsikon/*************************************************************************** cpluginmanager.cpp - description ------------------- begin : Fri Sep 27 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cpluginmanager.h" #ifdef HAVE_CONFIG_H #include #endif #include #ifndef WIN32 #include #endif #include "core/cdir.h" #include "cconfig.h" /** */ CPluginManager::CPluginManager() { m_pPluginList = new CList(); } /** */ CPluginManager::~CPluginManager() { SetInstance(0); delete m_pPluginList; m_pPluginList = 0; } typedef ePluginStruct* (*PLUGIN_INIT_FUNC)(); typedef int (*PLUGIN_DEINIT_FUNC)(); /** */ void CPluginManager::Load( CString path ) { CDir dir; CList list; CFileInfo *fileinfo; PLUGIN_INIT_FUNC dclib_plugin_init; CPluginObject * Plugin; #ifndef WIN32 void *h; #else HINSTANCE h; #endif // set default path if ( path.IsEmpty() ) path = CConfig::Instance()->GetDCLibPluginPath(); /* Empty setting to disable plugin load */ if ( path.IsEmpty() ) return; printf("Searching for plugins in '%s'\n", path.Data()); // set pluginpath dir.SetPath(path); // get all files if ( dir.ReadEntrys( CDir::Files, &list ) ) { fileinfo = 0; while( (fileinfo=list.Next(fileinfo)) != 0 ) { #ifdef WIN32 if ( dir.Extension(fileinfo->name).ToUpper() != "DLL" ) #else if ( dir.Extension(fileinfo->name).ToUpper() != "SO" ) #endif continue; printf("Found plugin: '%s'\n",fileinfo->name.Data()); #ifdef WIN32 if ( (h = LoadLibraryEx((path+DIRSEPARATOR+fileinfo->name).Data(),NULL,0)) == NULL ) { #else if ( (h = dlopen( (path+DIRSEPARATOR+fileinfo->name).Data(), RTLD_LAZY )) == NULL ) { printf("Error dlopen %s\n",dlerror()); #endif continue; } /* The "fix" for the warning: * * ISO C++ forbids casting between pointer-to-function and pointer-to-object * * as documented in dlopen(3) does not appear to make much * sense and generates a: * * dereferencing type-punned pointer will break strict-aliasing rules * * warning but we already have plenty of those. Trying other things * like reinterpret_cast is no help. */ #ifdef WIN32 dclib_plugin_init = (PLUGIN_INIT_FUNC) GetProcAddress(h,"dclib_plugin_init"); #else *(void**) (&dclib_plugin_init) = dlsym(h, "dclib_plugin_init"); #endif if ( dclib_plugin_init == NULL ) { #ifndef WIN32 printf("Error dlsym %s\n",dlerror()); dlclose(h); #else FreeLibrary(h); #endif } else { Plugin = new CPluginObject(); Plugin->m_sFileName = path + fileinfo->name; Plugin->m_Handle = h; Plugin->m_ePluginStruct = dclib_plugin_init(); Plugin->m_ePluginStruct->init(); //ps->deinit(); /* if ( Plugin->m_eType == eptNONE ) { printf("Error init plugin\n"); #ifndef WIN32 dlclose(h); #else FreeLibrary(h); #endif delete Plugin; continue; } */ m_pPluginList->Add(Plugin); } } } } /** */ void CPluginManager::InitPlugins() { CPluginObject * plugin = 0; while ( (plugin = m_pPluginList->Next(plugin)) != 0 ) { if ( Init(plugin) == false ) { printf("Init Failed\n"); } } } /** */ void CPluginManager::DeInitPlugins() { CPluginObject * plugin = 0; while ( (plugin = m_pPluginList->Next(0)) != 0 ) { plugin->m_ePluginStruct->deinit(); #ifndef WIN32 dlclose(plugin->m_Handle); #else FreeLibrary(plugin->m_Handle); #endif m_pPluginList->Remove(plugin); delete plugin; } } /** */ bool CPluginManager::Init( CPluginObject * plugin ) { if ( plugin->m_ePluginStruct->m_eType != eptLIB ) { printf("Plugin != LIB not for me ...\n"); return false; } return true; } libdc0-0.3.24~svn3121/dclib/cclient.cpp0000644000175000017500000005266711233301711016433 0ustar sikonsikon/*************************************************************************** cclient.cpp - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cclient.h" #include #include #ifndef WIN32 #include #include #include #include #include #endif #include "core/clist.h" #include "dcobject.h" #include "cquerymanager.h" #include "cdownloadmanager.h" #include "cconnectionmanager.h" #include "cencrypt.h" #include "cmessagehandler.h" #include "cconfig.h" #include "csearchmanager.h" #include "clistenmanager.h" #include "dclib-ssl-use.h" // need to decompress zpipe data #include "core/czlib.h" #include "core/cbytearray.h" // for DPRINTF #include "dclib.h" // IsPrivateI4() and IsValidI4() #include "core/cnetaddr.h" CClient::CClient( CString remoteEncoding ) : CDCProto( remoteEncoding ) { m_pCallback = 0; m_bHandshake = true; m_bHandleUserList = true; m_bHandleSearch = true; m_bHandleMyinfo = true; m_bHandleForceMove = true; m_bHandleTransfer = true; m_bUpdateMyinfo = false; m_bSendMyinfo = true; m_bSSLMode = false; m_nNickListHandler = 0; m_bUsedPassword = false; // set reconnect parameter m_eReconnectState = ersNONE; m_nReconnectCount = 0; m_timeReconnectTimeout = 0; m_timeMyinfoTimeout = 0; // initialise settings used since hub supports message cannot be used m_bExtProtocol = false; m_bGotIP = false; // zpipe handling m_pZLib = 0; m_bZMode = false; // message parser m_pMessageHandler = new CMessageHandler( remoteEncoding ); #if DCLIB_HAS_SSL == 1 if ( CConfig::Instance() ) { m_MyInfo.m_bTLSFlag = ( CConfig::Instance()->GetTransferCert().NotEmpty() && CConfig::Instance()->GetTransferKey().NotEmpty() ); } #endif } CClient::~CClient() { SetCallBackFunction(0); delete m_pZLib; m_pZLib = 0; delete m_pMessageHandler; m_pMessageHandler = 0; } /** */ void CClient::ConnectionState( eConnectionState state ) { int err = -1; CMessageConnectionState *Object = new CMessageConnectionState(); if ( (state == estCONNECTED) || (state == estDISCONNECTED) ) { // reset all values m_sBuffer.Empty(); m_bHandshake = true; m_timeMyinfoTimeout = time(0); m_nNickListHandler = 0; m_bExtProtocol = false; m_bGotIP = false; m_UserList.Clear(); m_bZMode = false; delete m_pZLib; m_pZLib = 0; #if DCLIB_HAS_SSL == 1 m_pMessageSSL.Init(); #endif // update reconnect state if ( state == estCONNECTED ) { UpdateReconnect( ersNONE ); if ( m_bSSLMode && CConfig::Instance() ) { if ( ChangeSocketMode( esmSSLCLIENT, CConfig::Instance()->GetTransferCert(), CConfig::Instance()->GetTransferKey() ) == false ) { printf("change ssl mode failed\n"); } } } else { if ( m_eReconnectState == ersFORCEMOVE ) { UpdateReconnect( ersNONE ); } else { UpdateReconnect( ersENABLED ); } } } Object->m_eState = state; Object->m_sMessage = GetSocketError(); if ( m_pCallback != 0 ) { err = m_pCallback->notify( this, Object ); } else { err = DC_CallBack( Object ); } // callback failed if ( err == -1 ) { delete Object; } // update myinfo if ( m_bHandleMyinfo && CConnectionManager::Instance() ) { CConnectionManager::Instance()->SendMyInfoToConnectedServers(); } } /** */ void CClient::DataAvailable( const char * buffer, int len ) { CString s; int i = 0; if ( len <= 0 ) { return; } // add traffic control CSocket::m_Traffic.AddTraffic(ettCONTROLRX,len); if ( m_bZMode ) { int inlen = len; CString trailing; if ( m_pZLib == 0 ) { m_pZLib = new CZLib(); } int outlen = 1024*100; // same as what CTransfer uses CByteArray * out = new CByteArray(outlen); //printf( "before inlen=%d outlen=%d ", inlen, outlen ); const int zlibstatus = m_pZLib->InflateZBlock( buffer, &inlen, (char*)out->Data(), &outlen ); //printf( "after inlen=%d outlen=%d\n", inlen, outlen ); if ( zlibstatus == -1 ) { printf("CClient: ZPipe decompress error, returning to normal mode\n"); delete m_pZLib; m_pZLib = 0; m_bZMode = false; } else if ( zlibstatus == 0 ) { //printf("ZPipe: finished decompressing data, leaving zmode\n"); delete m_pZLib; m_pZLib = 0; m_bZMode = false; /* * Check for uncompressed data after compressed data. * In 0.3.19 there was usually data after the compressed data * which got ignored, because it put the compressed data * into m_sBuffer and did not send it to zlib until * some more data was received. */ if ( inlen < len ) { trailing.Set( buffer+inlen, len-inlen ); } } if ( ((zlibstatus == 0) || (zlibstatus == 1)) && (outlen > 0) ) { s = m_sBuffer + CString().Set((char*)out->Data(),outlen); m_sBuffer.Empty(); if ( trailing.NotEmpty() ) { s += trailing; } //printf("ZPipe result: '%s'\n",s.Data()); } delete out; } else { s = m_sBuffer + CString().Set(buffer,len); /* contents of buffer have been used, empty it to make sure it does not get used again */ m_sBuffer.Empty(); } /* If ZPipe is enabled, we must search forwards for $ZOn| * in case there is a | within the compressed data. * * And since hub supports negotiation is useless, we had better * assume ZPipe is always enabled. */ i = s.Find("$ZOn|"); if ( i >= 0 ) { /* Handle all messages up to but not including $ZOn| */ HandleMessage( s.Mid(0,i) ); /* Handle $ZOn| and advance i */ m_bZMode = true; i += 5; if ( i < s.Length() ) { /* * Handle the compressed data. */ DataAvailable( s.Data()+i, s.Length()-i ); } return; } /* No ZPipe support or $ZOn| not found */ i = s.FindRev('|') + 1; if ( i > 0 ) { HandleMessage( s.Mid(0,i) ); } if ( i < s.Length() ) { m_sBuffer = s.Mid( i, s.Length()-i ); } } /** */ void CClient::DataTimeout() { SendString("|"); } /** */ void CClient::Notify() { if ( !CConfig::Instance() ) return; // check away mode if ( (m_bHandshake == false) && ((time(0)-m_timeMyinfoTimeout) >= 30) ) { if ( CConfig::Instance()->GetAwayMode() != m_MyInfo.m_eAwayMode) { m_MyInfo.m_eAwayMode = CConfig::Instance()->GetAwayMode(); m_bUpdateMyinfo = true; } } if ( (m_bHandshake == false) && m_bUpdateMyinfo && ((time(0)-m_timeMyinfoTimeout) >= 30) ) { m_bUpdateMyinfo = false; m_timeMyinfoTimeout = time(0); if ( m_bSendMyinfo ) SendMyInfo( &m_MyInfo ); } if ( m_eReconnectState == ersENABLED ) { if ( m_nReconnectCount >= CConfig::Instance()->GetReconnectCount() ) { UpdateReconnect( ersNONE, 0 ); } else { if ( GetConnectionState() != estNONE ) { printf("warning, wrong reconnect state, you are connected !\n"); } // init timer if ( m_timeReconnectTimeout == 0 ) { m_timeReconnectTimeout = time(0); } if ( (time(0)-m_timeReconnectTimeout) >= CConfig::Instance()->GetReconnectTimeout() ) { UpdateReconnect( ersNONE ); if ( CConfig::Instance()->GetReconnectCount() != 9999 ) { m_nReconnectCount++; } Connect(); } } } } /** */ void CClient::UpdateReconnect( eReconnectState state, int count ) { if ( !CConfig::Instance() ) return; // reconnect disabled if ( CConfig::Instance()->GetReconnectCount() == 0 ) { m_eReconnectState = ersNONE; return; } // don't change state if reconnect disables if ( (m_eReconnectState == ersDISABLED) && (state != ersNONE) ) { return; } // update state m_eReconnectState = state; // reset timeout m_timeReconnectTimeout = 0; // update counter if ( count != -1 ) { m_nReconnectCount = count; } } /** */ int CClient::HandleMessage( const CString & message ) { int err; int pointer; eDCMessage type; CDCMessage * Object = 0; CString sAnswer,s; if ( message.IsEmpty() ) { return 0; } pointer = 0; while( (type=m_pMessageHandler->Parse(&message,pointer,&Object)) != DC_MESSAGE_PARSE_ERROR ) { if ( !Object ) { continue; } switch (type) { case DC_MESSAGE_LOCK: { CMessageLock * msg = (CMessageLock*)Object; // only handle the first lock in handshake mode if ( m_bHandshake ) { #if DCLIB_HAS_SSL == 1 if ( m_bSSLMode ) { SendSSLInfo(); } #endif CEncrypt::Encrypt(msg->m_sData,sAnswer); if ( msg->m_bExtProtocol ) { /* * Assumes NoHello NoGetINFO are supported. * The hub may not inform us what is actually enabled in its supports. */ m_bExtProtocol = true; // HubTopic No $Hellos No $GetINFO UserCommand /* * UserIP2 now enabled always, if disabled we just do not use * the value the hub gives us, but it gets stored in case * the setting is changed without reconnecting to the hub. * * Similarly TTHSearch is always enabled because CConfig::Instance()->GetDisableHashList() * only affects the hashing of new files. However NOTTH is added to the tag. */ std::vector supported; supported.push_back("HubTopic"); supported.push_back("NoHello"); supported.push_back("NoGetINFO"); supported.push_back("TTHSearch"); supported.push_back("UserCommand"); supported.push_back("UserIP2"); if ( CConfig::Instance() != 0 ) { if ( CConfig::Instance()->GetZPipeEnabled() ) { // this is what DC++ 0.699 sends // it may change later after testing finishes supported.push_back("ZPipe0"); } if ( CConfig::Instance()->GetCompressedTransfers() ) { supported.push_back("GetZBlock"); } } bool shuffle = true; if ( CConfig::Instance() ) { shuffle = CConfig::Instance()->GetShuffleSupports(); } SendSupports( supported, shuffle ); // quicklist ??? http://forum.dcstats.net/showthread.php?s=&threadid=802 } SendKey( sAnswer ); SendValidateNick( m_MyInfo.m_sNick ); } break; } case DC_MESSAGE_LOGEDIN: { // update myinfo // if ( m_bHandleMyinfo ) // CConnectionManager::Instance()->SendMyInfoToConnectedServers(); break; } case DC_MESSAGE_HUBNAME: { CMessageHubName * msg = (CMessageHubName*)Object; // set the old hubname in this message if ( GetHubName() != msg->m_sHubName ) msg->m_sOldHubName = GetHubName(); SetHubName(msg->m_sHubName); break; } case DC_MESSAGE_HUB_TOPIC: { CMessageHubTopic * msg = (CMessageHubTopic*) Object; SetHubTopic(msg->m_sTopic); break; } case DC_MESSAGE_HELLO: { CMessageHello * msg = (CMessageHello*)Object; if ( (msg->m_sNick == m_MyInfo.m_sNick) && m_bHandshake ) { SendVersion(); // get nicklist if ( m_bHandleUserList ) RequestNickList(); if ( m_bSendMyinfo ) SendMyInfo( &m_MyInfo ); m_bHandshake = false; // update myinfo if ( m_bHandleMyinfo && CConnectionManager::Instance() ) CConnectionManager::Instance()->SendMyInfoToConnectedServers(); } else if ( m_bHandleUserList ) { m_UserList.AppendUser(msg->m_sNick); } break; } case DC_MESSAGE_MYINFO: { CMessageMyInfo * msg = (CMessageMyInfo*)Object; if ( m_bHandleUserList ) { if ( m_UserList.UpdateUser(msg) == false ) { delete Object; Object = 0; } } break; } case DC_MESSAGE_QUIT: { CMessageQuit * msg = (CMessageQuit*)Object; if ( m_bHandleUserList ) { m_UserList.RemoveUser(msg->m_sNick); #if DCLIB_HAS_SSL == 1 m_pMessageSSL.LeaveHub(this,msg->m_sNick); #endif } break; } case DC_MESSAGE_NICKLIST: { CMessageNickList * msg = (CMessageNickList*)Object; if ( m_bHandleUserList ) { // 0: update nicklist 1: requested nicklist if ( m_nNickListHandler == 1 ) { m_UserList.Clear(); m_nNickListHandler = 0; } m_UserList.InitUserList(msg); if ( m_bExtProtocol == false ) { for ( CString * nick = 0; (nick=msg->m_NickList.Next(nick))!=0; ) { SendGetInfo(*nick,GetNick()); } } } break; } case DC_MESSAGE_OPLIST: { CMessageOpList * msg = (CMessageOpList*)Object; // operators allready in the userlist if ( m_bHandleUserList ) { // init operator list m_UserList.InitOperatorList(msg); } break; } case DC_MESSAGE_SEARCH_FILE: { bool search = true; CMessageSearchFile * msg = (CMessageSearchFile*)Object; if ( m_bHandleSearch ) { // check for loopback search if ( msg->m_bLocal ) { if ( msg->m_sSource == GetNick() ) { search = false; } } else { // disable global search, compare search with own ip and port // also check private address space settings and IP if ( CConfig::Instance() ) { if ( (msg->m_nPort == CConfig::Instance()->GetUDPListenPort()) && (msg->m_sSource == GetExternalIP(false)) ) { search = false; } else if ( ( CConfig::Instance()->GetCheckPrivateAddressSpace() && CNetAddr::IsPrivateI4(msg->m_sSource.Data()) ) || ( CConfig::Instance()->GetPrivateAddressSpaceOnly() && (CNetAddr::IsPrivateI4(msg->m_sSource.Data()) == false)) ) { DPRINTF("Ignoring search from %s due to private address space settings\n",msg->m_sSource.Data()); search = false; } } } if ( search && (CQueryManager::Instance() != 0) ) { CQueryManager::Instance()->SearchQuery( GetHubName(), GetResolvedIP(), GetNick(), msg ); } } break; } case DC_MESSAGE_SEARCHRESULT: { // fix hub name CMessageSearchResult * msg = (CMessageSearchResult *) Object; if ( msg->m_sHubName == msg->m_sHubHost ) { msg->m_sHubName = GetHubName(); } if ( CSearchManager::Instance() ) if ( CSearchManager::Instance()->HandleSearch( msg ) ) Object = 0; break; } case DC_MESSAGE_CONNECTTOME: { CMessageConnectToMe * msg = (CMessageConnectToMe*) Object; if ( m_bHandleTransfer ) { if ( CDownloadManager::Instance() ) CDownloadManager::Instance()->DLM_AddTransferRequest( msg->m_sHost, msg->m_nPort, msg->m_bCrypto, GetHubName(), GetHost() ); } break; } case DC_MESSAGE_REVCONNECTTOME: { CMessageRevConnectToMe * msg = (CMessageRevConnectToMe*) Object; if ( CConfig::Instance() && (GetMode() == ecmACTIVE) && m_bHandleTransfer ) { #if DCLIB_HAS_SSL == 1 CMessageMyInfo usermyinfo; bool crypto = ( m_MyInfo.m_bTLSFlag && m_UserList.GetUserMyInfo(msg->m_sDstNick,&usermyinfo) && usermyinfo.m_bTLSFlag ); #else bool crypto = false; #endif CString s = GetExternalIP( true, crypto ); if ( s.NotEmpty() ) { if ( CDownloadManager::Instance() && CDownloadManager::Instance()->DLM_AddTransferRequest( msg->m_sDstNick, CString(), GetHubName(), GetHost() ) ) { SendConnectToMe(msg->m_sDstNick,s,crypto); } } } break; } case DC_MESSAGE_FORCEMOVE: { CMessageForceMove * msg = (CMessageForceMove*) Object; if ( CConfig::Instance() && CConfig::Instance()->GetForceMoveEnabled() && m_bHandleForceMove ) { SetHubName(msg->m_sHost); UpdateReconnect( ersFORCEMOVE, 0 ); Connect(msg->m_sHost,msg->m_nPort); } break; } case DC_MESSAGE_PRIVATECHAT: { CMessagePrivateChat * msg = (CMessagePrivateChat*) Object; /* default to receiving all messages if no CConfig */ if ( CConfig::Instance() && (CConfig::Instance()->GetChatRecvFromOffline() == false) && (m_UserList.IsUserOnline(msg->m_sSrcNick) == false) ) { delete Object; Object = 0; msg = 0; } #if DCLIB_HAS_SSL == 1 if ( msg ) { m_pMessageSSL.PrivateChat(this,msg); } #endif break; } case DC_MESSAGE_SUPPORTS: { /* * Interesting. Since hubs may not send all the strings they support * it turns out there is currently nothing we can do with the supports message. */ break; } case DC_MESSAGE_USERIP: { CMessageUserIP * msg = (CMessageUserIP*) Object; std::list::const_iterator nick_it = msg->m_lNicks.begin(); std::list::const_iterator ip_it = msg->m_lIPs.begin(); while ( (nick_it != msg->m_lNicks.end()) && (ip_it != msg->m_lIPs.end()) ) { if ( m_bHandleUserList ) { m_UserList.SetUserIP( *nick_it, *ip_it ); } if ( GetNick() == *nick_it ) { if ( CNetAddr::IsValidI4( ip_it->Data() ) ) { m_sExternalIP = *ip_it; m_bGotIP = true; } } ++nick_it; ++ip_it; } break; } default: { break; } } if (Object) { if ( m_pCallback != 0 ) { err = m_pCallback->notify( this, Object ); } else { err = DC_CallBack( Object ); } if ( err == -1 ) { delete Object; } } } return 0; } /** */ bool CClient::SetUserTransferInfo( CString nick, CDCMessage * msg ) { int err; bool res = false; CMessageMyInfo myinfo,*mi; if ( m_UserList.SetUserTransferInfo(nick,msg) ) { if ( m_UserList.GetUserMyInfo( nick, &myinfo ) ) { mi = new CMessageMyInfo(); *mi = myinfo; if ( m_pCallback != 0 ) { err = m_pCallback->notify( this, mi ); } else { err = DC_CallBack( mi ); } if ( err == -1 ) { delete mi; } res = true; } } return res; } /** send private message */ int CClient::SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick ) { int i=-1; CString s; if ( (CConfig::Instance() && CConfig::Instance()->GetChatSendToOffline()) || m_UserList.IsUserOnline( sTo ) ) { #if DCLIB_HAS_SSL == 1 s = m_pMessageSSL.EncryptMessage( this, sTo, sMsg ); if ( s.NotEmpty() ) { sMsg = s; } #endif i = CDCProto::SendPrivateMessage( sNick, sTo, sMsg, sFromNick ); } return i; } /** */ int CClient::RequestNickList() { int res = 0; if ( m_nNickListHandler == 0 ) { res = CDCProto::RequestNickList(); // if set, we will never recv a nicklist // hubs may not put NoGetINFO into their supports even if it is enabled if ( m_bExtProtocol == false ) { m_nNickListHandler = 1; } } else { printf("We are still waiting for a NickList.\n"); } return res; } /** */ int CClient::Disconnect( bool force ) { UpdateReconnect( ersDISABLED ); SetUsedPassword(false); return CConnection::Disconnect(force); } /** */ CString CClient::GetExternalIP( bool addport, bool crypto ) const { /* * If the hub does not support UserIP2 then the value we got from CConfig * will be used. */ if ( CConfig::Instance() && (CConfig::Instance()->GetUserIP2Enabled() == false) ) { return CConfig::Instance()->GetTCPHostString( addport, crypto ); } else if ( m_bGotIP ) { if ( addport ) { unsigned int port = 0; if ( crypto ) { if ( CCryptoListenManager::Instance() ) { port = CCryptoListenManager::Instance()->GetListenPort(); } } else { if ( CListenManager::Instance() ) { port = CListenManager::Instance()->GetListenPort(); } } if ( port != 0 ) { return m_sExternalIP + ":" + CString::number(port); } else { return m_sExternalIP; } } else { return m_sExternalIP; } } else if ( CConfig::Instance() ) { return CConfig::Instance()->GetTCPHostString( addport, crypto ); } else { /* no IP from hub and no CConfig to get one from! */ return "127.0.0.1"; } } /** */ int CClient::SendSearch( CMessageSearchFile * msg ) { if ( msg->m_bLocal ) { /* fix nick for passive search */ msg->m_sSource = GetNick(); } else { /* * GetExternalIP() handles if we have an IP from the hub and if we are supposed to use it or not * it uses GetTCPHostString() but without adding the port this is the same as GetUDPHostString() */ msg->m_sSource = GetExternalIP(false,false) + ":" + CString::number(CConfig::Instance()->GetUDPListenPort()); } return CDCProto::SendSearch( msg ); } /** */ void CClient::SendSSLInfo() { CMessageLog * log1 = new CMessageLog(); log1->sMessage = GetSSLVersion(); log1->sMessage += " connection using "; log1->sMessage += GetSSLCipher(); int err; if ( m_pCallback ) { err = m_pCallback->notify( this, log1 ); } else { err = DC_CallBack( log1 ); } if ( err == -1 ) { delete log1; } CMessageLog * log2 = new CMessageLog(); log2->sMessage = VerifyPeerCertificate(); if ( m_pCallback ) { err = m_pCallback->notify( this, log2 ); } else { err = DC_CallBack( log2 ); } if ( err == -1 ) { delete log2; } } libdc0-0.3.24~svn3121/dclib/cconnectionmanager.cpp0000644000175000017500000003773711141131203020643 0ustar sikonsikon/*************************************************************************** cconnectionmanager.cpp - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cconnectionmanager.h" #include "cclient.h" #include "cconfig.h" #include "core/cmanager.h" #include "cdownloadmanager.h" #include "dcobject.h" #include "cfilemanager.h" #include "core/ccallback.h" #include "core/cnetaddr.h" #ifndef WIN32 #include #include #endif #include "dclib-ssl-use.h" #include /** */ CConnectionManager::CConnectionManager() { m_pClientListMutex = new CMutex(); m_pClientList = new CList(); m_pCallback = new CCallback0( this, &CConnectionManager::Callback ); CManager::Instance()->Add( m_pCallback ); m_bUpdateMyinfo = false; } /** */ CConnectionManager::~CConnectionManager() { SetInstance(0); CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; m_Mutex.Lock(); // this was the cause of the // pthread_mutex_destroy: Device or resource busy // message on valknut shutdown //m_pClientList->Lock(); delete m_pClientList; m_pClientList = 0; delete m_pClientListMutex; m_pClientListMutex = 0; m_Mutex.UnLock(); } /** thread callbackfunction */ int CConnectionManager::Callback() { CClient * client; m_Mutex.Lock(); // update all clients if ( m_pClientList ) { client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { client->Thread(); } // update myinfo from all clients if ( m_bUpdateMyinfo ) { client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() ) continue; UpdateMyInfo(client); } m_bUpdateMyinfo = false; } } m_Mutex.UnLock(); return 0; } /** */ void CConnectionManager::ConnectClient( CString hubname, CString server ) { DCMessageConnectClient *msg = new DCMessageConnectClient(); msg->m_sHubName = hubname; msg->m_sHubHost = server; if ( DC_CallBack(msg) == -1 ) { delete msg; Connect( hubname, server, NULL ); } } /** */ void CConnectionManager::Connect( CString hubname, CString server, CClient * client, bool sslconnect ) { if ( server.IsEmpty() ) { return; } if ( hubname.IsEmpty() ) { hubname = server; } if ( !client ) { m_Mutex.Lock(); client = (CClient*)GetHub(hubname,server); m_Mutex.UnLock(); if ( client ) { return; } client = new CClient(); } client->SetHubName(hubname); AddHub(client); client->SetNick(CConfig::Instance()->GetNick( hubname, server )); client->SetConnectionType(CConfig::Instance()->GetSpeed()); client->SetShareSize(CFileManager::Instance()->GetShareSize()); client->SetMode(CConfig::Instance()->GetMode()); client->SetAwayMode(CConfig::Instance()->GetAwayMode()); client->SetComment(CConfig::Instance()->GetDescription(false, hubname, server)); // set ssl mode, if profile exist use profile settings DCConfigHubProfile pConfigHubProfile; if ( CConfig::Instance()->GetBookmarkHubProfile( hubname, server, &pConfigHubProfile ) ) { if ( pConfigHubProfile.m_bEMail ) client->SetEMail(pConfigHubProfile.m_sEMail); else client->SetEMail(CConfig::Instance()->GetEMail()); client->SetSSLMode(pConfigHubProfile.m_bSSL); } else { client->SetEMail(CConfig::Instance()->GetEMail()); client->SetSSLMode(sslconnect); } client->Connect(server); } /** */ void CConnectionManager::AddHub( CClient * client ) { m_Mutex.Lock(); if ( m_pClientList ) { m_pClientListMutex->Lock(); m_pClientList->Add(client); m_pClientListMutex->UnLock(); } m_Mutex.UnLock(); } /** */ void CConnectionManager::RemoveHub( CClient * client ) { m_Mutex.Lock(); if ( m_pClientList ) { m_pClientListMutex->Lock(); client->SetCallBackFunction(0); m_pClientList->Remove(client); m_pClientListMutex->UnLock(); } m_Mutex.UnLock(); } /** */ long CConnectionManager::GetConnectedHubCount( bool admin ) { long i; CClient * client; if ( !m_pClientList ) { return 0; } m_pClientListMutex->Lock(); i = 0; client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() ) continue; if ( admin && (client->UserList()->IsAdmin(client->GetNick())) ) continue; i++; } m_pClientListMutex->UnLock(); return i; } /** */ long CConnectionManager::GetConnectedHubPasswordCount( ) { long i; CClient * client; if ( !m_pClientList ) { return 0; } m_pClientListMutex->Lock(); i = 0; client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() ) continue; if ( (client->GetUsedPassword() == false) ) continue; i++; } m_pClientListMutex->UnLock(); return i; } /** */ CClient * CConnectionManager::GetHub( CString hubname, CString hubhost ) { CClient* client = 0; if ( !m_pClientList ) { return client; } m_pClientListMutex->Lock(); client = GetHubObject(hubname,hubhost); m_pClientListMutex->UnLock(); return client; } /** */ CClient * CConnectionManager::GetHubObject( CString hubname, CString hubhost ) { CString o_host,s; unsigned int i; unsigned int o_port; CClient* client = 0, * client_candidate = 0; if ( !m_pClientList ) { return client; } CNetAddr::ParseHost( hubhost, o_host, o_port ); // set default port if ( o_port == 0 ) o_port = 411; o_host = o_host.ToUpper(); while( (client=m_pClientList->Next(client)) != 0 ) { // compare hubname if ( client->GetHubName() == hubname ) client_candidate = client; // compare hubhost CNetAddr::ParseHost( client->GetHost().ToUpper(), s, i ); if ( i == 0 ) i = 411; if ( s == o_host ) { // host and port match if ( i == o_port ) break; // host and hubname match, we can connect to the same hub on different ports if ( client->GetHubName() == hubname ) break; } // compare peer name CNetAddr::ParseHost( client->GetHost(true).ToUpper(), s, i ); if ( i == 0 ) i = 411; if ( s == o_host ) { // host and port match if ( i == o_port ) break; // host and hubname match, we can connect to the same hub on different ports if ( client->GetHubName() == hubname ) break; } } if ( client == 0 ) { // no client found client = client_candidate; } return client; } /** */ std::map * CConnectionManager::GetConnectedHubServerMap() { if ( !m_pClientList ) { return 0; } m_pClientListMutex->Lock(); std::map * hostmap = new std::map(); if ( m_pClientList->Count() > 0 ) { CClient * client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() ) { continue; } (*hostmap)[client->GetHubName()] = client->GetHost(); } } m_pClientListMutex->UnLock(); return hostmap; } /** send message to all connected servers */ int CConnectionManager::SendStringToConnectedServers( CString s, CString hubname, bool encode ) { int i; CClient* client; if ( !m_pClientList ) { return 0; } m_pClientListMutex->Lock(); i = 0; if ( s.NotEmpty() ) { client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() ) { continue; } if ( hubname.NotEmpty() ) { if ( hubname == client->GetHubName() ) { client->SendString(s, encode); i++; break; } else { continue; } } else { client->SendString(s, encode); } i++; } } m_pClientListMutex->UnLock(); return i; } /** send a search string (extracted from message) to connected servers */ int CConnectionManager::SendSearchToConnectedServers( CMessageSearchFile *sf, CString hubhost ) { int i; CClient* client; if ( !m_pClientList ) { return 0; } m_pClientListMutex->Lock(); i = 0; if ( hubhost.NotEmpty() ) { client = GetHubObject( CString(), hubhost ); if ( client ) { if ( client->IsHandshake() == false ) { client->SendSearch(sf); i++; } } else { printf("CConnectionManager::SendSearchToConnectedServers hub not found\n"); } } else { client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() ) { continue; } client->SendSearch(sf); i++; } } m_pClientListMutex->UnLock(); return i; } /** send myinfo to all connected servers */ int CConnectionManager::SendMyInfoToConnectedServers() { m_bUpdateMyinfo = true; return 0; } /** */ void CConnectionManager::UpdateMyInfo( CClient* client ) { CString description,speed,email; eUserAwayMode awaymode; DCConfigHubProfile pConfigHubProfile; if ( !m_pClientList || !CFileManager::Instance() || !CConfig::Instance() ) { return; } speed = CConfig::Instance()->GetSpeed(); awaymode = CConfig::Instance()->GetAwayMode(); // get description description = CConfig::Instance()->GetDescription(false,client->GetHubName(),client->GetHost()); // get hub profile if ( CConfig::Instance()->GetBookmarkHubProfile( client->GetHubName(), client->GetHost(), &pConfigHubProfile ) ) { if ( pConfigHubProfile.m_bEMail ) email = pConfigHubProfile.m_sEMail; else email = CConfig::Instance()->GetEMail(); } else { email = CConfig::Instance()->GetEMail(); } // update internal values client->SetComment(description); client->SetConnectionType(speed); client->SetEMail(email); client->SetShareSize(CFileManager::Instance()->GetShareSize()); client->SetAwayMode(awaymode); client->SetMode(CConfig::Instance()->GetMode()); #if DCLIB_HAS_SSL client->SetMyInfoTLSFlag( CConfig::Instance()->GetTransferCert().NotEmpty() && CConfig::Instance()->GetTransferKey().NotEmpty() ); #endif return; } /** */ int CConnectionManager::SendConnectionRequest( CString nick, CString hubname, CString hubhost ) { int res; CClient* client; if ( !m_pClientList ) { return 0; } m_pClientListMutex->Lock(); res = -3; client = GetHubObject(hubname,hubhost); if ( client ) { if ( client->IsHandshake() ) { res = -2; } else if ( client->UserList()->IsUserOnline( nick ) == false ) { res = -1; } else if ( client->GetMode() == ecmPASSIVE ) { // send connection request if ( client->SendRevConnectToMe( client->GetNick(), nick ) == 0 ) { res = 0; } else { res = -4; } } else if ( client->GetMode() == ecmACTIVE ) { #if DCLIB_HAS_SSL == 1 CMessageMyInfo usermyinfo; bool crypto = ( client->IsTLSInMyInfo() && client->UserList()->GetUserMyInfo(nick,&usermyinfo) && usermyinfo.m_bTLSFlag ); #else bool crypto = false; #endif CString s = client->GetExternalIP( true, crypto ); if ( s.NotEmpty() ) { // send connection request CDownloadManager::Instance()->DLM_AddTransferRequest( nick, CString(), hubname, client->GetHost() ); if ( client->SendConnectToMe( nick, s, crypto ) == 0 ) { res = 0; } else { res = -4; } } else { res = -4; } } } m_pClientListMutex->UnLock(); return res; } /** */ bool CConnectionManager::IsUserOnline( CString nick, CString hubname, CString hubhost, CList * list ) { bool res; CClient* client; DCHubObject * HubObject; if ( !m_pClientList ) { return false; } m_pClientListMutex->Lock(); res = false; client = 0; hubhost = hubhost.ToUpper(); while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->IsHandshake() == false ) { if ( hubname.IsEmpty() ) { if ( client->UserList()->IsUserOnline( nick ) ) { if ( list ) { HubObject = new DCHubObject(); HubObject->m_sHubName = client->GetHubName(); HubObject->m_sHubHost = client->GetHost(); list->Add(HubObject); } res = true; } } if ( (client->GetHubName() == hubname) || (client->GetHost().ToUpper() == hubhost) || (client->GetHost(true) == hubhost) ) { if ( client->UserList()->IsUserOnline( nick ) ) res = true; break; } } } m_pClientListMutex->UnLock(); return res; } /** */ bool CConnectionManager::SetUserTransferInfo( CString hubname, CString hubhost, CString nick, CDCMessage * msg ) { bool res = false; CClient* client; if ( !m_pClientList ) { return false; } m_pClientListMutex->Lock(); if ( (client = GetHubObject( hubname, hubhost )) != 0 ) { if ( client->IsHandshake() == false ) { res = client->SetUserTransferInfo(nick,msg); } else { printf("CConnectionManager::SetUserTransferInfo: hub offline\n"); } } else { printf("CConnectionManager::SetUserTransferInfo: can't find hub\n"); } m_pClientListMutex->UnLock(); return res; } /** */ eHubState CConnectionManager::IsHubOnline( CString hubname, CString hubhost ) { eHubState res; CClient* client; if ( !m_pClientList ) { return ehsNONE; } m_pClientListMutex->Lock(); res = ehsNONE; if ( (client = GetHubObject( hubname, hubhost )) != 0 ) { if ( client->IsHandshake() == false ) { res = ehsONLINE; } else { res = ehsOFFLINE; } } m_pClientListMutex->UnLock(); return res; } /** */ CString CConnectionManager::GetNick( CString hubname, CString hubhost ) { CString res; CClient* client; if ( !m_pClientList ) { return res; } m_pClientListMutex->Lock(); if ( (client = GetHubObject( hubname, hubhost )) != 0 ) { res = client->GetNick(); } m_pClientListMutex->UnLock(); return res; } /** */ bool CConnectionManager::IsAdmin( CString hubname, CString hubhost, CString nick ) { bool res; CClient* client; if ( !m_pClientList ) { return false; } m_pClientListMutex->Lock(); res = false; if ( (client = GetHubObject(hubname,hubhost)) != 0 ) { if ( client->IsHandshake() == false ) { if ( nick.IsEmpty() ) res = client->UserList()->IsAdmin( client->GetNick() ); else res = client->UserList()->IsAdmin(nick); } } m_pClientListMutex->UnLock(); return res; } /** */ bool CConnectionManager::GetUserMyInfo( CString hubname, CString hubhost, CString nick, CMessageMyInfo * p ) { bool res; CClient* client; if ( !m_pClientList ) { return false; } m_pClientListMutex->Lock(); res = false; if ( (client = GetHubObject(hubname,hubhost)) != 0 ) { if ( client->IsHandshake() == false ) { res = client->UserList()->GetUserMyInfo(nick,p); } } m_pClientListMutex->UnLock(); return res; } /** TODO: remove function ! (used in ctransferview) */ CString CConnectionManager::GetHubHost( CString hubname ) { CString res; CClient* client; if ( !m_pClientList ) { return res; } m_pClientListMutex->Lock(); client = 0; while( (client=m_pClientList->Next(client)) != 0 ) { if ( client->GetHubName() == hubname ) { res = client->GetIP(); res += ':'; res += CString::number(client->GetPort()); break; } } m_pClientListMutex->UnLock(); return res; } /** */ bool CConnectionManager::GetHubDetails( const CString & id, CString & name, CString & host, CString & ip ) { bool res = false; if ( !m_pClientList ) { return res; } m_pClientListMutex->Lock(); CClient * client = 0; while ( (client = m_pClientList->Next(client)) != 0 ) { if ( client->GetHubName() == id || client->GetResolvedIP() == id || client->GetHost() == id ) { name = client->GetHubName(); host = client->GetHost(); ip = client->GetResolvedIP(); res = true; break; } } m_pClientListMutex->UnLock(); return res; } libdc0-0.3.24~svn3121/dclib/cfilehasher.h0000644000175000017500000001476611125260136016737 0ustar sikonsikon/*************************************************************************** cfilehasher.h - Calculate the TTH root and leaves for a file ------------------- begin : Fri May 16 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CFILEHASHER_H #define CFILEHASHER_H /** * @author Edward Sheldrake * * It's a wrapper for the tiger tree hashing functions, which currently * come from the DC++ source. * * However it was designed to hash files, and was never used. Much more * useful is to hash the data as it is received to verify it, dclib doesn't * do that either. Only the ValidateHashLeaves() function is used for hash * database verification plus maybe HashSize() is used in valknut, since * the DC++ headers are not installed. */ #include #include #include #include #include /* The DC++ sources use different types than dclib: int64_t vs ulonglong */ #include class CByteArray; /** */ enum eFileHasherStatus { efhsNotStarted=0, efhsReady, efhsWorking, efhsFinished, efhsError }; class CHashedSegment { public: /** Constructor */ CHashedSegment() { start = 0; size = 0; }; /** Destructor */ ~CHashedSegment() { }; /** start position */ ulonglong start; /** chunk size */ ulonglong size; /** expected hash, base32 encoded */ CString expected; /** actual hash, base32 encoded */ CString actual; }; class CTreeVerificationReport { public: /** Constructor */ CTreeVerificationReport() { filesize = 0; allgood = false; segments = new CList; }; /** Copy constructor */ CTreeVerificationReport( const CTreeVerificationReport & other ); /** Destructor */ ~CTreeVerificationReport() { delete segments; segments = 0; }; /** Returns a nice string of the data that you can print out. */ CString ToString() const; /** full name of file */ CString filename; /** actual TTH root */ CString tthRoot; /** file size */ ulonglong filesize; /** true if all hashes matched */ bool allgood; /** the list of file segments and their hashes */ CList * segments; }; class CFileHasher { public: /** Constructor */ CFileHasher( const CString filename, CByteArray * workmem = 0 ); /** Destructor */ virtual ~CFileHasher(); /** * Calculate the hash. * Sets status to the given value when finished. */ void ComputeHash( const eFileHasherStatus doneStatus = efhsFinished ); /** Stop the hashing */ void StopHashing(); /** */ bool IsStop() const { return m_bStop; }; /** Get status */ eFileHasherStatus GetStatus() const { return status; }; /** Get progress as number of bytes hashed */ ulonglong GetProgress() const { return m_nProgress; }; /** Get the filesize */ ulonglong GetFileSize() const { return filesize; }; /** Get the TTH root as a base32 encoded cstring */ CString GetHashRoot(); /** Returns a newly allocated copy of the hash root data */ CByteArray * GetHashRootRaw(); /** Returns a newly allocated copy of the hash leaf data */ CByteArray * GetLeafData(); /** Returns a pointer to the hash root data, so be careful with it.*/ CByteArray * HashRootDirect() { return m_pRootData; }; /** Returns a pointer to the hash leaf data, so be careful with it.*/ CByteArray * HashLeavesDirect() { return m_pLeafData; }; /** Returns true if the base32 encoded TTH root matches the TTH leaf data */ static bool ValidateHashLeaves( const CString tth, CByteArray * leaves, const ulonglong filesize ); /** The same, but with the raw TTH root not the base32 encoded string */ static bool ValidateHashLeaves( CByteArray * root, CByteArray * leaves, const ulonglong filesize ); /** */ static int64_t GetBlockSize( const unsigned long leavesSize, const int64_t filesize ); /** Get the root TTH of a bytearray as raw */ static CByteArray * HashByteArray( CByteArray * data, unsigned long size ); /** Get the size in bytes of the unencoded TTH value */ static unsigned long HashSize(); protected: /** The file to hash */ CFile file; /** The size of the file */ ulonglong filesize; /** Number of bytes hashed so far */ ulonglong m_nProgress; /** Memory area to read file data to */ CByteArray * m_pWorkMem; /** True if we allocated our own */ bool usingOwnMem; /** Store the final TTH root data */ CByteArray * m_pRootData; /** Store the final leaf data */ CByteArray * m_pLeafData; /** Status */ eFileHasherStatus status; /** Set to true to stop the hashing */ bool m_bStop; }; class CFileHasherThread : public CFileHasher, public CThread { public: /** Constructor */ CFileHasherThread ( const CString filename, CByteArray * workmem = 0 ) : CFileHasher( filename, workmem ) { }; /** Destructor */ virtual ~CFileHasherThread() { }; /** Thread callback function */ virtual void Thread(); }; class CFileTreeVerifier: public CFileHasher, public CThread { public: /** Constructor */ CFileTreeVerifier( const CString filename, CByteArray * leaves, CByteArray * workmem = 0 ); /** Destructor */ virtual ~CFileTreeVerifier(); /** * Gets the results of the verification. * If finished, Returns the pointer to our report and sets m_pReport=0 * so we won't delete it when we're deleted. * Whoever gets it must delete it when done with it. * Otherwise returns 0 (and returns 0 the second time if you call it twice). */ CTreeVerificationReport * GetReport(); /** Thread callback function */ virtual void Thread(); /** */ int GetPass() const { return m_nPass; }; private: /** The hash leaves we are going to compare the file with */ CByteArray * m_pLeaves; /** The output of the verification */ CTreeVerificationReport * m_pReport; /** Set to 1 when hashing file or 2 when checking segments */ int m_nPass; }; #endif // CFILEHASHER_H libdc0-0.3.24~svn3121/dclib/csearchindex.cpp0000644000175000017500000010521111164113221017432 0ustar sikonsikon/*************************************************************************** csearchindex.cpp - description ------------------- begin : Mon May 14 2003 copyright : (C) 2003-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "csearchindex.h" #ifndef WIN32 #include #include #endif #include #include "core/cbytearray.h" #include "cconfig.h" #include "core/cdir.h" #include "core/cfile.h" #include "dclib.h" #include "cfilemanager.h" #include "core/cbase32.h" #include "hash/compat.h" #include "hash/MerkleTree.h" #include "cfilehasher.h" /* "9 levels of leaves" = max of 512 hashes, which is 12KiB, which I doubled */ #define MAX_LEAVES_SIZE 2*512*dcpp::TigerTree::BYTES /** */ CSearchIndex::CSearchIndex() { m_pBaseArray = new CByteArray(); m_pFileBaseArray = new CByteArray(); m_pPathBaseArray = new CByteArray(); m_pHashBaseArray = new CByteArray(); m_pHashFileBaseArray = new CByteArray(); m_pHashPathBaseArray = new CByteArray(); m_pHashIndex = new CByteArray(); m_pCaseFoldedBase = new CByteArray(); m_pCaseFoldedData = new CByteArray(); m_pNewHashLeaves = 0; hashleavessize = 0; // this will get set when m_pNewHashLeaves is created /* during list refresh, these are created and updated * and replace the old byte arrays when refresh stage is finished */ m_pUpdatingFileBaseArray = 0; m_pUpdatingPathBaseArray = 0; m_pUpdatingBaseArray = 0; m_pUpdatingHashBaseArray = 0; m_pUpdatingHashFileBaseArray = 0; m_pUpdatingHashPathBaseArray = 0; m_pUpdatingHashIndex = 0; m_pUpdatingCaseFoldedBase = 0; m_pUpdatingCaseFoldedData = 0; m_bLoadedOK = LoadIndex(); } /** */ CSearchIndex::~CSearchIndex() { delete m_pBaseArray; m_pBaseArray = 0; delete m_pFileBaseArray; m_pFileBaseArray = 0; delete m_pPathBaseArray; m_pPathBaseArray = 0; delete m_pHashBaseArray; m_pHashBaseArray = 0; delete m_pHashFileBaseArray; m_pHashFileBaseArray = 0; delete m_pHashPathBaseArray; m_pHashPathBaseArray = 0; delete m_pHashIndex; m_pHashIndex = 0; delete m_pCaseFoldedBase; m_pCaseFoldedBase = 0; delete m_pCaseFoldedData; m_pCaseFoldedData = 0; if ( m_pNewHashLeaves ) { DPRINTF("~CSearchIndex: warning new hash leaves not saved!\n"); SaveNewHashLeaves(); } delete m_pNewHashLeaves; m_pNewHashLeaves = 0; delete m_pUpdatingFileBaseArray; m_pUpdatingFileBaseArray = 0; delete m_pUpdatingPathBaseArray; m_pUpdatingPathBaseArray = 0; delete m_pUpdatingBaseArray; m_pUpdatingBaseArray = 0; delete m_pUpdatingHashBaseArray; m_pUpdatingHashBaseArray = 0; delete m_pUpdatingHashFileBaseArray; m_pUpdatingHashFileBaseArray = 0; delete m_pUpdatingHashPathBaseArray; m_pUpdatingHashPathBaseArray = 0; delete m_pUpdatingHashIndex; m_pUpdatingHashIndex = 0; delete m_pUpdatingCaseFoldedBase; m_pUpdatingCaseFoldedBase = 0; delete m_pUpdatingCaseFoldedData; m_pUpdatingCaseFoldedData = 0; } /** */ void CSearchIndex::PrepareUpdate() { // files list delete m_pUpdatingFileBaseArray; delete m_pUpdatingPathBaseArray; delete m_pUpdatingBaseArray; m_pUpdatingFileBaseArray = new CByteArray(0); m_pUpdatingPathBaseArray = new CByteArray(0); m_pUpdatingBaseArray = new CByteArray(0); // search lists of case folded path+filenames delete m_pUpdatingCaseFoldedBase; delete m_pUpdatingCaseFoldedData; m_pUpdatingCaseFoldedBase = new CByteArray(0); m_pUpdatingCaseFoldedData = new CByteArray(0); // hash lists delete m_pUpdatingHashBaseArray; delete m_pUpdatingHashFileBaseArray; delete m_pUpdatingHashPathBaseArray; delete m_pUpdatingHashIndex; m_pUpdatingHashBaseArray = new CByteArray(0); m_pUpdatingHashFileBaseArray = new CByteArray(0); m_pUpdatingHashPathBaseArray = new CByteArray(0); m_pUpdatingHashIndex = new CByteArray(0); m_pUpdatingHashBaseArray->Append( m_pHashBaseArray->Data(), m_pHashBaseArray->Size() ); m_pUpdatingHashFileBaseArray->Append( m_pHashFileBaseArray->Data(), m_pHashFileBaseArray->Size() ); m_pUpdatingHashPathBaseArray->Append( m_pHashPathBaseArray->Data(), m_pHashPathBaseArray->Size() ); m_pUpdatingHashIndex->Append( m_pHashIndex->Data(), m_pHashIndex->Size() ); } /** */ void CSearchIndex::FinishUpdate() { CByteArray * old1 = m_pFileBaseArray; CByteArray * old2 = m_pPathBaseArray; CByteArray * old3 = m_pBaseArray; CByteArray * old4 = m_pCaseFoldedBase; CByteArray * old5 = m_pCaseFoldedData; CByteArray * old7 = m_pHashBaseArray; CByteArray * old8 = m_pHashFileBaseArray; CByteArray * old9 = m_pHashPathBaseArray; CByteArray * old10 = m_pHashIndex; // swap to new lists / append new data - this section needs to be as fast as possible // essentially all operations need to be done simultaneously // it used to have some data appending, but now // it's just 7 pointer swaps, so it should be OK m_pFileBaseArray = m_pUpdatingFileBaseArray; m_pPathBaseArray = m_pUpdatingPathBaseArray; m_pBaseArray = m_pUpdatingBaseArray; m_pCaseFoldedBase = m_pUpdatingCaseFoldedBase; m_pCaseFoldedData = m_pUpdatingCaseFoldedData; m_pHashFileBaseArray = m_pUpdatingHashFileBaseArray; m_pHashPathBaseArray = m_pUpdatingHashPathBaseArray; m_pHashIndex = m_pUpdatingHashIndex; m_pHashBaseArray = m_pUpdatingHashBaseArray; // end of speed critical section m_pUpdatingFileBaseArray = 0; m_pUpdatingPathBaseArray = 0; m_pUpdatingBaseArray = 0; m_pUpdatingCaseFoldedBase = 0; m_pUpdatingCaseFoldedData = 0; m_pUpdatingHashBaseArray = 0; m_pUpdatingHashFileBaseArray = 0; m_pUpdatingHashPathBaseArray = 0; m_pUpdatingHashIndex = 0; delete old1; delete old2; delete old3; delete old4; delete old5; delete old7; delete old8; delete old9; delete old10; } /** */ void CSearchIndex::ResetHashIndex() { m_pHashBaseArray->SetSize(0); m_pHashFileBaseArray->SetSize(0); m_pHashPathBaseArray->SetSize(0); m_pHashIndex->SetSize(0); if ( m_pNewHashLeaves == 0 ) { m_pNewHashLeaves = new CByteArray(); } m_pNewHashLeaves->SetSize(0); m_pNewHashLeaves->SaveToFile(CConfig::Instance()->GetConfigPath()+"hashleaves.bin"); delete m_pNewHashLeaves; m_pNewHashLeaves = 0; } /** */ std::set * CSearchIndex::SearchHash( unsigned char * hash ) { unsigned long hbi,hi,bi; std::set * results = 0; hi = 0; while ( FindHash( hash, &hi ) ) { if ( HashBaseIndexFromHashIndex( hi, &hbi ) ) { if ( BaseIndexFromHashBaseIndex( hbi, &bi ) ) { if ( !results ) { results = new std::set; } results->insert(bi); } } hi+=dcpp::TigerTree::BYTES; } return results; } /** */ bool CSearchIndex::GetFileBaseObject( unsigned long index, struct filebaseobject * fbo ) { bool res = false; if ( (index*sizeof(struct filebaseobject)) < m_pBaseArray->Size() ) { memcpy( fbo, m_pBaseArray->Data()+(index*sizeof(struct filebaseobject)), sizeof(struct filebaseobject) ); res = true; } return res; } /** */ bool CSearchIndex::GetFileBaseObjectDuringUpdate( unsigned long index, struct filebaseobject * fbo ) { bool res = false; if ( (index*sizeof(struct filebaseobject)) < m_pUpdatingBaseArray->Size() ) { memcpy( fbo, m_pUpdatingBaseArray->Data()+(index*sizeof(struct filebaseobject)), sizeof(struct filebaseobject) ); res = true; } return res; } /** */ bool CSearchIndex::GetFileBaseObject( unsigned long index, struct filebaseobject * fbo, CString & filename ) { bool res = false; if ( GetFileBaseObject(index,fbo) ) { if ( m_pPathBaseArray->Size() > fbo->m_nPathIndex ) { filename = (char*)m_pPathBaseArray->Data()+fbo->m_nPathIndex; if ( filename.NotEmpty() ) { filename += DIRSEPARATOR; } } if ( m_pFileBaseArray->Size() > fbo->m_nFileIndex ) { filename += (char*)m_pFileBaseArray->Data()+fbo->m_nFileIndex; } res = true; } return res; } /** */ bool CSearchIndex::GetFileBaseObjectDuringUpdate( unsigned long index, struct filebaseobject * fbo, CString & filename ) { bool res = false; if ( GetFileBaseObjectDuringUpdate(index,fbo) ) { if ( m_pUpdatingPathBaseArray->Size() > fbo->m_nPathIndex ) { filename = (char*)m_pUpdatingPathBaseArray->Data()+fbo->m_nPathIndex; if ( filename.NotEmpty() ) { filename += DIRSEPARATOR; } } if ( m_pUpdatingFileBaseArray->Size() > fbo->m_nFileIndex ) { filename += (char*)m_pUpdatingFileBaseArray->Data()+fbo->m_nFileIndex; } res = true; } return res; } /** */ bool CSearchIndex::GetCaseFoldedName( unsigned long index, struct filebaseobject * fbo, CString & name ) { unsigned long bapos = index*sizeof(struct filebaseobject); unsigned long cfpos = index*sizeof(unsigned long); if ( (bapos < m_pBaseArray->Size()) && (cfpos < m_pCaseFoldedBase->Size()) ) { memcpy( fbo, m_pBaseArray->Data()+bapos, sizeof(struct filebaseobject) ); unsigned long cfi; memcpy( &cfi, m_pCaseFoldedBase->Data()+cfpos, sizeof(unsigned long) ); if ( cfi < m_pCaseFoldedData->Size() ) { name = (char*) m_pCaseFoldedData->Data()+cfi; return true; } } return false; } /** */ bool CSearchIndex::LoadIndex() { bool err = false; CDir d; ulonglong filesize; // first try to load hash index if ( m_pHashBaseArray->LoadFromFile(CConfig::Instance()->GetConfigPath()+"hashbase.bin") == false ) { err = true; } if ( err == false ) { if ( m_pHashFileBaseArray->LoadFromFile(CConfig::Instance()->GetConfigPath()+"hashfilebase.bin") == false ) { err = true; } } if ( err == false ) { if ( m_pHashPathBaseArray->LoadFromFile(CConfig::Instance()->GetConfigPath()+"hashpathbase.bin") == false ) { err = true; } } if ( err == false ) { if ( m_pHashIndex->LoadFromFile(CConfig::Instance()->GetConfigPath()+"hashindex.bin") == false ) { err = true; } } if ( err == true ) { ResetHashIndex(); err = false; } // sanity check filesize = d.getFileSize(CConfig::Instance()->GetConfigPath()+"database.bin",false); if ( (filesize%sizeof(struct filebaseobject)) != 0 ) { err = true; } // load the filelist if ( err == false ) { if ( m_pBaseArray->LoadFromFile(CConfig::Instance()->GetConfigPath()+"database.bin") == false ) { err = true; } } if ( err == false ) { if ( m_pFileBaseArray->LoadFromFile(CConfig::Instance()->GetConfigPath()+"filebase.bin") == false ) { err = true; } } if ( err == false ) { if ( m_pPathBaseArray->LoadFromFile(CConfig::Instance()->GetConfigPath()+"pathbase.bin") == false ) { err = true; } } if ( err ) { m_pBaseArray->SetSize(0); m_pFileBaseArray->SetSize(0); m_pPathBaseArray->SetSize(0); } if ( !err ) { filesize = d.getFileSize(CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin"); if ( filesize%sizeof(unsigned long) != 0 ) { err = true; } if ( !err ) { err = !(m_pCaseFoldedBase->LoadFromFile(CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin")); } if ( !err ) { err = !(m_pCaseFoldedData->LoadFromFile(CConfig::Instance()->GetConfigPath()+"casefoldeddata.bin")); } } return !err; } /** */ void CSearchIndex::SaveIndex() { /* * Hash leaves not being available does not matter as much and will not crash because * the file seek will just fail. */ bool ok = m_pHashIndex->SaveToFile(CConfig::Instance()->GetConfigPath()+"hashindex.bin.new"); ok = ok && m_pHashFileBaseArray->SaveToFile(CConfig::Instance()->GetConfigPath()+"hashfilebase.bin.new"); ok = ok && m_pHashPathBaseArray->SaveToFile(CConfig::Instance()->GetConfigPath()+"hashpathbase.bin.new"); ok = ok && m_pHashBaseArray->SaveToFile(CConfig::Instance()->GetConfigPath()+"hashbase.bin.new"); ok = ok && m_pFileBaseArray->SaveToFile(CConfig::Instance()->GetConfigPath()+"filebase.bin.new"); ok = ok && m_pPathBaseArray->SaveToFile(CConfig::Instance()->GetConfigPath()+"pathbase.bin.new"); ok = ok && m_pBaseArray->SaveToFile(CConfig::Instance()->GetConfigPath()+"database.bin.new"); ok = ok && m_pCaseFoldedData->SaveToFile(CConfig::Instance()->GetConfigPath()+"casefoldeddata.bin.new"); ok = ok && m_pCaseFoldedBase->SaveToFile(CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin.new"); if ( ok ) { CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashindex.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashfilebase.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashpathbase.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashbase.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"filebase.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"pathbase.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"database.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"casefoldeddata.bin" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"hashindex.bin.new", CConfig::Instance()->GetConfigPath()+"hashindex.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"hashfilebase.bin.new", CConfig::Instance()->GetConfigPath()+"hashfilebase.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"hashpathbase.bin.new", CConfig::Instance()->GetConfigPath()+"hashpathbase.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"hashbase.bin.new", CConfig::Instance()->GetConfigPath()+"hashbase.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"filebase.bin.new", CConfig::Instance()->GetConfigPath()+"filebase.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"pathbase.bin.new", CConfig::Instance()->GetConfigPath()+"pathbase.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"database.bin.new", CConfig::Instance()->GetConfigPath()+"database.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"casefoldeddata.bin.new", CConfig::Instance()->GetConfigPath()+"casefoldeddata.bin" ); CFile::Rename( CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin.new", CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin" ); if ( m_pNewHashLeaves ) { SaveNewHashLeaves(); } } else { CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashindex.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashfilebase.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashpathbase.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"hashbase.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"filebase.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"pathbase.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"database.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"casefoldeddata.bin.new" ); CFile::UnLink( CConfig::Instance()->GetConfigPath()+"casefoldedbase.bin.new" ); delete m_pNewHashLeaves; m_pNewHashLeaves = 0; } } /** */ unsigned long CSearchIndex::IndexCount() { unsigned long i = 0; if ( m_pBaseArray ) { i = m_pBaseArray->Size()/sizeof(struct filebaseobject); } return i; } /** */ unsigned long CSearchIndex::IndexCountDuringUpdate() { unsigned long i = 0; if ( m_pUpdatingBaseArray ) { i = m_pUpdatingBaseArray->Size()/sizeof(struct filebaseobject); } return i; } /** */ unsigned long CSearchIndex::AddIndex( CFileInfo *fileinfo, CString path, eFileTypes filetype ) { struct filebaseobject fbo; unsigned long i; fbo.m_eFileType = filetype; fbo.m_nFileIndex = m_pUpdatingFileBaseArray->Size(); fbo.m_nPathIndex = m_pUpdatingPathBaseArray->Size(); fbo.m_nHashIndex = (unsigned long)-1; fbo.m_nSize = fileinfo->size; fbo.m_tModTime = fileinfo->st_m_time; i = m_pUpdatingBaseArray->Size()/sizeof(struct filebaseobject); m_pUpdatingBaseArray->Append( (const char*)&fbo, sizeof(struct filebaseobject) ); m_pUpdatingFileBaseArray->Append( fileinfo->name.Data(), fileinfo->name.Length()+1 ); m_pUpdatingPathBaseArray->Append( path.Data(), path.Length()+1 ); return i; } /** Only used during update */ void CSearchIndex::AddSearchIndex( const CString & data ) { unsigned long pos = m_pUpdatingCaseFoldedData->Size(); m_pUpdatingCaseFoldedBase->Append( (const char*)&pos, sizeof(unsigned long) ); m_pUpdatingCaseFoldedData->Append( data.Data(), data.Length() + 1 ); } /** UpdateIndex is only used during update */ void CSearchIndex::UpdateIndex( unsigned long index, struct filebaseobject * fbo ) { if ( (index*sizeof(struct filebaseobject)) < m_pUpdatingBaseArray->Size() ) { memcpy( m_pUpdatingBaseArray->Data()+(index*sizeof(struct filebaseobject)), fbo, sizeof(struct filebaseobject) ); } } /** */ bool CSearchIndex::FindHash( unsigned char * hash, unsigned long * hi ) { unsigned long i; for(i=*hi;iSize();i+=dcpp::TigerTree::BYTES) if ( memcmp(hash,m_pHashIndex->Data()+i,dcpp::TigerTree::BYTES) == 0 ) { *hi = i; return true; } return false; } /** */ bool CSearchIndex::FindHashDuringUpdate( unsigned char * hash, unsigned long * hi ) { unsigned long i; for(i=*hi;iSize();i+=dcpp::TigerTree::BYTES) if ( memcmp(hash,m_pUpdatingHashIndex->Data()+i,dcpp::TigerTree::BYTES) == 0 ) { *hi = i; return true; } return false; } /** */ CString CSearchIndex::GetHash( unsigned long hbi ) { CString s; CByteArray src; struct hashbaseobject * hbo; if ( hbi < m_pHashBaseArray->Size() ) { hbo = (struct hashbaseobject *)(m_pHashBaseArray->Data()+hbi); src.Append(m_pHashIndex->Data()+hbo->m_nHashIndex,dcpp::TigerTree::BYTES); CBase32::Encode( &s, &src ); } return s; } /** */ bool CSearchIndex::HashBaseIndexFromHashIndex( unsigned long hi, unsigned long * hbi ) { unsigned long i; struct hashbaseobject * hbo; for(i=0;iSize();i+=sizeof(struct hashbaseobject)) { hbo = (struct hashbaseobject *)(m_pHashBaseArray->Data()+i); if ( hbo->m_nHashIndex == hi ) { *hbi = i; return true; } } return false; } /** */ bool CSearchIndex::HashBaseIndexFromHashIndexDuringUpdate( unsigned long hi, unsigned long * hbi ) { unsigned long i; struct hashbaseobject * hbo; for(i=0;iSize();i+=sizeof(struct hashbaseobject)) { hbo = (struct hashbaseobject *)(m_pUpdatingHashBaseArray->Data()+i); if ( hbo->m_nHashIndex == hi ) { *hbi = i; return true; } } return false; } /** */ bool CSearchIndex::BaseIndexFromHashBaseIndex( unsigned long hbi, unsigned long * bi ) { unsigned long i; struct filebaseobject * fbo; for(i=0;iSize();i+=sizeof(struct filebaseobject)) { fbo = (struct filebaseobject*)(m_pBaseArray->Data()+i); if ( fbo->m_nHashIndex == hbi ) { *bi = i/sizeof(struct filebaseobject); return true; } } return false; } /** */ bool CSearchIndex::FindHashBaseIndex( struct filebaseobject * fbo, unsigned long * hbi ) { unsigned long i; struct hashbaseobject * hbo; for(i=0;iSize();i+=sizeof(struct hashbaseobject)) { hbo = (struct hashbaseobject *)(m_pHashBaseArray->Data()+i); if ( Compare(fbo,hbo) ) { *hbi = i; return true; } } return false; } /** */ bool CSearchIndex::FindHashBaseIndexDuringUpdate( struct filebaseobject * fbo, unsigned long * hbi ) { unsigned long i; struct hashbaseobject * hbo; for(i=0;iSize();i+=sizeof(struct hashbaseobject)) { hbo = (struct hashbaseobject *)(m_pUpdatingHashBaseArray->Data()+i); if ( CompareDuringUpdate(fbo,hbo) ) { *hbi = i; return true; } } return false; } /** */ bool CSearchIndex::Compare( struct filebaseobject * fbo, struct hashbaseobject * hbo ) { if ( fbo->m_nSize != hbo->m_nSize ) return false; if ( fbo->m_tModTime != hbo->m_tModTime ) return false; CString s1,s2; s1 = (char*)m_pFileBaseArray->Data()+fbo->m_nFileIndex; s2 = (char*)m_pHashFileBaseArray->Data()+hbo->m_nFileIndex; if ( s1 != s2 ) return false; s1 = (char*)m_pPathBaseArray->Data()+fbo->m_nPathIndex; s2 = (char*)m_pHashPathBaseArray->Data()+hbo->m_nPathIndex; if ( s1 != s2 ) return false; return true; } /** */ bool CSearchIndex::CompareDuringUpdate( struct filebaseobject * fbo, struct hashbaseobject * hbo ) { if ( fbo->m_nSize != hbo->m_nSize ) return false; if ( fbo->m_tModTime != hbo->m_tModTime ) return false; CString s1,s2; s1 = (char*)m_pUpdatingFileBaseArray->Data()+fbo->m_nFileIndex; s2 = (char*)m_pUpdatingHashFileBaseArray->Data()+hbo->m_nFileIndex; if ( s1 != s2 ) return false; s1 = (char*)m_pUpdatingPathBaseArray->Data()+fbo->m_nPathIndex; s2 = (char*)m_pUpdatingHashPathBaseArray->Data()+hbo->m_nPathIndex; if ( s1 != s2 ) return false; return true; } /** */ void CSearchIndex::AddHashIndex( unsigned long filebaseindex, unsigned char * hash, unsigned char * leaves, unsigned long lsize ) { struct filebaseobject fbo; struct hashbaseobject hbo; char * c; unsigned long hi,hbi; ulonglong storedlsize; if ( !GetFileBaseObjectDuringUpdate(filebaseindex,&fbo) ) { return; } hi = 0; if ( FindHashDuringUpdate(hash,&hi) ) { if ( HashBaseIndexFromHashIndexDuringUpdate(hi,&hbi) ) { if ( CompareDuringUpdate(&fbo,(struct hashbaseobject *)(m_pUpdatingHashBaseArray->Data()+hbi)) ) { printf("hash found\n"); fbo.m_nHashIndex = hbi; UpdateIndex(filebaseindex,&fbo); return; } } } hbo.m_nSize = fbo.m_nSize; hbo.m_tModTime = fbo.m_tModTime; hbo.m_nFileIndex = m_pUpdatingHashFileBaseArray->Size(); hbo.m_nPathIndex = m_pUpdatingHashPathBaseArray->Size(); hbo.m_nHashIndex = m_pUpdatingHashIndex->Size(); if ( (lsize == 0) || (leaves == 0) ) { hbo.m_nHashLeavesIndex = (unsigned long)-1; } else { if ( m_pNewHashLeaves == 0 ) { m_pNewHashLeaves = new CByteArray(); hashleavessize = CDir().getFileSize(CConfig::Instance()->GetConfigPath()+"hashleaves.bin",false); } storedlsize = lsize; hbo.m_nHashLeavesIndex = hashleavessize + m_pNewHashLeaves->Size(); m_pNewHashLeaves->Append((unsigned char*)&storedlsize,sizeof(storedlsize)); m_pNewHashLeaves->Append(leaves,lsize); } fbo.m_nHashIndex = m_pUpdatingHashBaseArray->Size(); m_pUpdatingHashBaseArray->Append((const char*)&hbo, sizeof(struct hashbaseobject)); c = (char*)m_pUpdatingFileBaseArray->Data()+fbo.m_nFileIndex; m_pUpdatingHashFileBaseArray->Append(c,strlen(c)+1); c = (char*)m_pUpdatingPathBaseArray->Data()+fbo.m_nPathIndex; m_pUpdatingHashPathBaseArray->Append(c,strlen(c)+1); m_pUpdatingHashIndex->Append( hash, dcpp::TigerTree::BYTES ); UpdateIndex(filebaseindex,&fbo); } /** */ CString CSearchIndex::GetFileName( unsigned long i ) { CString s; struct filebaseobject * fbo; if ( (i*sizeof(struct filebaseobject)) < m_pBaseArray->Size() ) { fbo = (struct filebaseobject *) (m_pBaseArray->Data()+(i*sizeof(struct filebaseobject))); s = (char*) (m_pFileBaseArray->Data()+fbo->m_nFileIndex); } return s; } /** */ CString CSearchIndex::GetFileNameDuringUpdate( unsigned long i ) { CString s; struct filebaseobject * fbo; if ( (i*sizeof(struct filebaseobject)) < m_pUpdatingBaseArray->Size() ) { fbo = (struct filebaseobject *) (m_pUpdatingBaseArray->Data()+(i*sizeof(struct filebaseobject))); s = (char*) (m_pUpdatingFileBaseArray->Data()+fbo->m_nFileIndex); } return s; } /** */ CByteArray * CSearchIndex::GetHashLeaves( CString tth ) { CByteArray * ba = 0; unsigned long hi = 0, hbi = 0; struct hashbaseobject * hbo = 0; CByteArray dst; if (CBase32::Decode(&dst, &tth) != dcpp::TigerTree::BYTES) { DPRINTF("GetHashLeaves: Decoded TTH length != dcpp::TigerTree::BYTES\n"); return 0; } while ( FindHash(dst.Data(), &hi) ) { //DPRINTF("GetHashLeaves: HashIndex=%llu\n", hi); if ( HashBaseIndexFromHashIndex( hi, &hbi ) ) { //DPRINTF("GetHashLeaves: HashBaseIndex=%llu\n", hbi); hbo = (struct hashbaseobject *)(m_pHashBaseArray->Data()+hbi); if (hbo->m_nHashLeavesIndex == (unsigned long)-1) { DPRINTF("GetHashLeaves: No Leaves available.\n"); return 0; } //DPRINTF("GetHashLeaves: HashLeavesIndex=%llu\n", hli); /* New code for on disk hash leaves */ CFile leaffile; if ( leaffile.Open(CConfig::Instance()->GetConfigPath()+"hashleaves.bin", IO_RAW | IO_READONLY) == false ) { printf("GetHashLeaves: cannot open hashleaves.bin\n"); return 0; } ba = new CByteArray(); if ( ReadLeaves( &leaffile, hbo->m_nHashLeavesIndex, ba ) == false ) { printf("GetHashLeaves: hli=%lu tth=%s\n", hbo->m_nHashLeavesIndex, tth.Data()); printf("GetHashLeaves: failed to read hash leaves, try database validation\n"); delete ba; ba = 0; } leaffile.Close(); return ba; } /* wrong one, move on to next hash */ hi += dcpp::TigerTree::BYTES; } //printf("FindHash for %s failed\n", tth.Data()); return 0; } /** */ bool CSearchIndex::SaveNewHashLeaves() { bool res; if (m_pNewHashLeaves != 0) { CFile file; res = file.Open( CConfig::Instance()->GetConfigPath()+"hashleaves.bin", IO_RAW | IO_WRITEONLY | IO_APPEND | IO_CREAT, MO_IRUSR | MO_IWUSR ); if ( res == false ) { printf("CSearchIndex::SaveNewHashLeaves: open hashleaves.bin failed\n"); } else { long wrote = file.Write( (const char*) m_pNewHashLeaves->Data(), m_pNewHashLeaves->Size() ); if ( wrote == m_pNewHashLeaves->Size() ) { res = true; } else { printf("CSearchIndex::SaveNewHashLeaves: only wrote %ld out of %ld bytes\n",wrote,m_pNewHashLeaves->Size()); if ( wrote > 0 ) { printf("CSearchIndex::SaveNewHashLeaves: hashleaves.bin has been corrupted, do /rebuild\n"); } res = false; } file.Close(); /* If data was written to hashleaves.bin, even if only some, delete m_pNewHashLeaves */ if ( wrote > 0 ) { delete m_pNewHashLeaves; m_pNewHashLeaves = 0; } } } else { //DPRINTF("CSearchIndex::SaveNewHashLeaves: nothing to save\n"); res = false; } return res; } /** * Since the files database does not contain entries for files no * longer shared, all that is needed is for each entry in files * database, find entry in hash database and copy the data * to the new hash database. * * There is also the hash index in the files database so we * also need to make a new array of filebaseobjects but * the number of entries in it will not change. */ long CSearchIndex::RebuildLists() { CFile leaffile; if ( leaffile.Open( CConfig::Instance()->GetConfigPath()+"hashleaves.bin", IO_RAW | IO_READONLY ) == false ) { printf("CSearchIndex::RebuildLists: cannot open hashleaves.bin\n"); return 0; } CByteArray * pNewBaseArray = new CByteArray(); CByteArray * pNewHashBaseArray = new CByteArray(); CByteArray * pNewHashFileBaseArray = new CByteArray(); CByteArray * pNewHashPathBaseArray = new CByteArray(); CByteArray * pNewHashIndex = new CByteArray(); CByteArray * pNewHashLeaves = new CByteArray(); if ( dclibVerbose() > 0 ) { printf("##### Before Rebuild #####\n"); PrintDatabaseStats(); printf("##########################\n"); } struct filebaseobject fbo; struct hashbaseobject hbo; CString hashfilename, hashfilepath; /* FIXME shouldn't have been a ulonglong the max size is 12KiB */ ulonglong lsize; CByteArray leaves; CByteArray root(dcpp::TigerTree::BYTES); unsigned long errors = 0; for ( unsigned long fbi = 0; fbi < m_pBaseArray->Size(); fbi += sizeof(struct filebaseobject) ) { if ( CFileManager::Instance()->Stopped() ) { DPRINTF("CSearchIndex::RebuildLists: interrupted\n"); delete pNewBaseArray; delete pNewHashBaseArray; delete pNewHashFileBaseArray; delete pNewHashPathBaseArray; delete pNewHashIndex; delete pNewHashLeaves; leaffile.Close(); return 0; } memcpy( &fbo, m_pBaseArray->Data()+fbi, sizeof(struct filebaseobject) ); if ( fbo.m_nHashIndex != (unsigned long)-1 ) { if ( fbo.m_nHashIndex < m_pHashBaseArray->Size() ) { memcpy( &hbo, m_pHashBaseArray->Data()+fbo.m_nHashIndex, sizeof(struct hashbaseobject) ); if ( hbo.m_nPathIndex < m_pHashPathBaseArray->Size() ) { hashfilepath = (const char*) m_pHashPathBaseArray->Data()+hbo.m_nPathIndex; hbo.m_nPathIndex = pNewHashPathBaseArray->Size(); pNewHashPathBaseArray->Append( hashfilepath.Data(), hashfilepath.Length()+1 ); } else { ++errors; hbo.m_nPathIndex = (unsigned long)-1; } if ( hbo.m_nFileIndex < m_pHashFileBaseArray->Size() ) { hashfilename = (const char*) m_pHashFileBaseArray->Data()+hbo.m_nFileIndex; hbo.m_nFileIndex = pNewHashFileBaseArray->Size(); pNewHashFileBaseArray->Append( hashfilename.Data(), hashfilename.Length()+1 ); } else { ++errors; hbo.m_nFileIndex = (unsigned long)-1; } if ( hbo.m_nHashIndex != (unsigned long)-1 ) { if ( hbo.m_nHashIndex + dcpp::TigerTree::BYTES <= m_pHashIndex->Size() ) { memcpy( root.Data(), m_pHashIndex->Data()+hbo.m_nHashIndex, dcpp::TigerTree::BYTES ); hbo.m_nHashIndex = pNewHashIndex->Size(); fbo.m_nHashIndex = pNewHashIndex->Size(); pNewHashIndex->Append( root.Data(), dcpp::TigerTree::BYTES ); } else { ++errors; hbo.m_nHashIndex = (unsigned long)-1; } } if ( hbo.m_nHashLeavesIndex != (unsigned long)-1 ) { if ( ReadLeaves( &leaffile, hbo.m_nHashLeavesIndex, &leaves ) ) { hbo.m_nHashLeavesIndex = pNewHashLeaves->Size(); lsize = leaves.Size(); pNewHashLeaves->Append( (const unsigned char*) &lsize, sizeof(lsize) ); pNewHashLeaves->Append( leaves.Data(), leaves.Size() ); } else { ++errors; hbo.m_nHashLeavesIndex = (unsigned long)-1; } } fbo.m_nHashIndex = pNewHashBaseArray->Size(); pNewHashBaseArray->Append( (const unsigned char*) &hbo, sizeof(struct hashbaseobject) ); } else { ++errors; fbo.m_nHashIndex = (unsigned long)-1; } } pNewBaseArray->Append( (const unsigned char*) &fbo, sizeof(struct filebaseobject) ); } leaffile.Close(); /* swap the byte arrays */ CByteArray * tmp1 = m_pBaseArray; CByteArray * tmp2 = m_pHashBaseArray; CByteArray * tmp3 = m_pHashFileBaseArray; CByteArray * tmp4 = m_pHashPathBaseArray; CByteArray * tmp5 = m_pHashIndex; m_pBaseArray = pNewBaseArray; m_pHashBaseArray = pNewHashBaseArray; m_pHashFileBaseArray = pNewHashFileBaseArray; m_pHashPathBaseArray = pNewHashPathBaseArray; m_pHashIndex = pNewHashIndex; delete tmp1; delete tmp2; delete tmp3; delete tmp4; delete tmp5; /* write new hash leaves file */ pNewHashLeaves->SaveToFile( CConfig::Instance()->GetConfigPath()+"hashleaves.bin" ); delete pNewHashLeaves; if ( dclibVerbose() > 0 ) { printf("##### After Rebuild #####\n"); PrintDatabaseStats(); printf("#########################\n"); } DPRINTF("CSearchIndex::RebuildLists: %ld errors detected\n",errors); return errors; } /** */ void CSearchIndex::PrintDatabaseStats() { printf("BaseArray size=%lu itemsize=%lu items=%lu\n", m_pBaseArray->Size(), (unsigned long) sizeof(struct filebaseobject), m_pBaseArray->Size()/sizeof(struct filebaseobject) ); printf("FileBaseArray size=%lu\n", m_pFileBaseArray->Size()); printf("PathBaseArray size=%lu\n", m_pPathBaseArray->Size()); printf("CaseFoldedBase size=%lu itemsize=%lu items=%lu\n", m_pCaseFoldedBase->Size(), (unsigned long) sizeof(unsigned long), m_pCaseFoldedBase->Size()/sizeof(unsigned long) ); printf("CaseFoldedData size=%lu\n", m_pCaseFoldedData->Size()); printf("HashBaseArray size=%lu itemsize=%lu items=%lu\n", m_pHashBaseArray->Size(), (unsigned long) sizeof(struct hashbaseobject), m_pHashBaseArray->Size()/sizeof(struct hashbaseobject)); printf("HashFileBaseArray size=%lu\n", m_pHashFileBaseArray->Size()); printf("HashPathBaseArray size=%lu\n", m_pHashPathBaseArray->Size()); printf("HashIndex size=%lu itemsize=%lu items=%lu\n", m_pHashIndex->Size(), (unsigned long) dcpp::TigerTree::BYTES, m_pHashIndex->Size()/dcpp::TigerTree::BYTES); printf("HashLeaves size=%llu (on disk)\n", CDir().getFileSize(CConfig::Instance()->GetConfigPath()+"hashleaves.bin",false)); } /** */ long CSearchIndex::ValidateHashLeaves() { long removed = 0; bool valid; CFile leaffile; if ( leaffile.Open( CConfig::Instance()->GetConfigPath()+"hashleaves.bin", IO_RAW | IO_READONLY ) == false ) { printf("CSearchIndex::ValidateHashLeaves: cannot open hashleaves.bin\n"); return removed; } CByteArray * pNewHashBaseArray = new CByteArray(); struct hashbaseobject hbo; CByteArray root(dcpp::TigerTree::BYTES); CByteArray leaves; for ( unsigned long hbi = 0; hbi < m_pHashBaseArray->Size(); hbi += sizeof(struct hashbaseobject) ) { if ( CFileManager::Instance()->Stopped() ) { delete pNewHashBaseArray; leaffile.Close(); DPRINTF("CSearchIndex::ValidateHashLeaves: interrupted\n"); return 0; } valid = false; memcpy( &hbo, m_pHashBaseArray->Data()+hbi, sizeof(struct hashbaseobject) ); /* check pointer to hash root */ if ( hbo.m_nHashIndex + dcpp::TigerTree::BYTES <= m_pHashIndex->Size() ) { /* get hash root */ memcpy( root.Data(), m_pHashIndex->Data()+hbo.m_nHashIndex, dcpp::TigerTree::BYTES ); /* get hash leaves */ if ( ReadLeaves( &leaffile, hbo.m_nHashLeavesIndex, &leaves ) ) { /* got root and leaves, validate them */ valid = CFileHasher::ValidateHashLeaves( &root, &leaves, hbo.m_nSize ); } } if ( valid ) { pNewHashBaseArray->Append( (unsigned char*) &hbo, sizeof(struct hashbaseobject) ); } else { ++removed; } } leaffile.Close(); if ( removed > 0 ) { CByteArray * tmp = m_pHashBaseArray; m_pHashBaseArray = pNewHashBaseArray; delete tmp; } else { delete pNewHashBaseArray; } DPRINTF("CSearchIndex::ValidateHashLeaves: removed %ld invalid entries\n",removed); return removed; } /** */ bool CSearchIndex::ReadLeaves( CFile * file, unsigned long hli, CByteArray * dest ) { if ( file->Seek( hli, SEEK_SET ) ) { /* FIXME shouldn't have been a ulonglong the max size is 12KiB */ ulonglong lsize; if ( file->Read( (char*) &lsize, sizeof(lsize) ) == sizeof(lsize) ) { if ( lsize < MAX_LEAVES_SIZE ) { dest->SetSize( (unsigned long) lsize ); if ( file->Read( (char*) dest->Data(), (long) lsize ) == (long) lsize ) { return true; } } } } return false; } libdc0-0.3.24~svn3121/dclib/chublistmanager.cpp0000644000175000017500000003165111141131203020143 0ustar sikonsikon/*************************************************************************** chublistmanager.cpp - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "chublistmanager.h" #include "cconfig.h" #include "core/cmanager.h" #include "dcobject.h" #include "core/cbytearray.h" #include "chttp.h" #include "core/cbz.h" #include "core/cxml.h" #include "core/ccallback.h" #include "core/ciconv.h" #ifndef WIN32 #include #include #endif #include /** */ CHubListManager::CHubListManager() { m_pCallback = new CCallback0( this, &CHubListManager::Callback ); CManager::Instance()->Add( m_pCallback ); if ( CConfig::Instance()->GetReloadHubListTime() != 0 ) { m_nReloadHubListTimeout = time(0) + CConfig::Instance()->GetReloadHubListTime()*60*60; } else { m_nReloadHubListTimeout = 0; } // get hublist stuff m_pHttp = 0; m_pHubListUrlList = 0; m_pHubListUrl = 0; m_pHubListData = 0; m_bGetHubListDone = false; m_pXml = 0; m_pXmlHubs = new CList; } /** */ CHubListManager::~CHubListManager() { m_Thread.Stop(); SetInstance(0); CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; delete m_pXml; m_pXml = 0; delete m_pXmlHubs; m_pXmlHubs = 0; } /** thread callbackfunction */ int CHubListManager::Callback() { m_Thread.Lock(); // check reload hublist timeout if ( CConfig::Instance() ) { if ( CConfig::Instance()->GetReloadHubListTime() != 0 ) { if ( m_nReloadHubListTimeout != 0 ) { if ( time(0) >= m_nReloadHubListTimeout ) { GetPublicHubList(); m_nReloadHubListTimeout = time(0) + CConfig::Instance()->GetReloadHubListTime()*60*60; } } else // change from config { m_nReloadHubListTimeout = time(0) + CConfig::Instance()->GetReloadHubListTime()*60*60; } } else { m_nReloadHubListTimeout = 0; } } // cleanup all objects if ( m_bGetHubListDone ) { delete m_pHttp; m_pHttp = 0; delete m_pHubListUrlList; m_pHubListUrlList = 0; delete m_pHubListData; m_pHubListData = 0; if ( m_pXmlHubs ) { m_pXmlHubs->Clear(); } m_pHubListUrl = 0; DCMessageGetHubList * msg = new DCMessageGetHubList(); msg->m_bRun = false; if ( DC_CallBack(msg) == -1 ) { delete msg; } m_bGetHubListDone = false; } m_Thread.UnLock(); return 0; } /** http callback function */ int CHubListManager::HttpCallBack( CDCMessage * dcmsg ) { CByteArray in; switch ( dcmsg->m_eType ) { case DC_MESSAGE_CONNECTION_STATE: { CMessageConnectionState *msg = (CMessageConnectionState*)dcmsg; if ( msg->m_eState == estDISCONNECTED ) { if ( (m_pHttp->GetHttpError() == 200) && m_pHttp->GetData(&in) ) { HandleHubListData( m_pHttp->GetUrl(), &in ); } // redirect if ( m_pHttp->GetHttpError() == 302 ) { m_pHttp->GetUrl(m_pHttp->GetLocation()); } else if ( NextHubListUrl() == false ) { // parse public hub list in own thread m_Thread.SetThreadCallBackFunction( new CCallback0( this, &CHubListManager::ParsePublicHubList ) ); m_Thread.Start(); } } break; } case DC_MESSAGE_TRANSFER: { if ( DC_CallBack( (CMessageTransfer*)dcmsg ) != -1 ) { dcmsg = 0; } break; } default: { break; } } if ( dcmsg ) { delete dcmsg; } return 0; } /** */ void CHubListManager::HandleHubListData( const CString & url, CByteArray * in ) { CByteArray out; if ( url.Right(4).ToLower() == ".bz2" ) { if ( CBZ::Decompress( in, &out ) ) { if ( url.Right(8).ToLower() == ".xml.bz2" ) { if ( m_pXml == 0 ) { m_pXml = new CXml(); } if ( m_pXml->ParseFixMemory(&out) && m_pXml->DocFirstChild() ) { ParseXmlPublicHubList(); } else { printf("Failed to parse XML hublist.\n"); } delete m_pXml; m_pXml = 0; } else { m_pHubListData->Append(out.Data(),out.Size()); m_pHubListData->Append("\xD\xA",2); } } else { printf("bz2 decompress failed\n"); } } else { if ( url.Right(4).ToLower() == ".xml" ) { if ( m_pXml == 0 ) { m_pXml = new CXml(); } if ( m_pXml->ParseFixMemory(in) && m_pXml->DocFirstChild() ) { ParseXmlPublicHubList(); } else { printf("Failed to parse XML hublist.\n"); } delete m_pXml; m_pXml = 0; } else { m_pHubListData->Append(in->Data(),in->Size()); m_pHubListData->Append("\xD\xA",2); } } } /** */ bool CHubListManager::GetPublicHubList() { bool res = false; if ( m_pHttp != 0 ) { // get hublist allready running return res; } m_pHubListUrlList = new CList(); // get all hublist urls CConfig::Instance()->GetHubListUrlList(m_pHubListUrlList); // check hublist url count if ( m_pHubListUrlList->Count() == 0 ) { delete m_pHubListUrlList; m_pHubListUrlList = 0; return res; } // init first url m_pHubListUrl = 0; m_pHubListData = new CByteArray(); m_pHttp = new CHttp(); m_pHttp->SetCallBackFunction( new CCallback1( this, &CHubListManager::HttpCallBack ) ); res = NextHubListUrl(); if ( !res ) { m_bGetHubListDone = true; } else { DCMessageGetHubList * msg = new DCMessageGetHubList(); msg->m_bRun = true; if ( DC_CallBack(msg) == -1 ) { delete msg; } } return res; } /** */ int CHubListManager::ParsePublicHubList() { CString line; CString s; CString s1,s2,s3,s4; long i=0,i1=0; DCConfigHubItem * hubitem = 0; if ( (m_pHubListData->Size() == 0) && (m_pXmlHubs->Count() == 0) ) { m_Thread.Stop(false); m_Thread.SetThreadCallBackFunction(0); m_bGetHubListDone = true; return 0; } while ( (hubitem = m_pXmlHubs->Next(hubitem)) != 0 ) { // name, host, description, usercount, country, shared, minshare, extra CConfig::Instance()->AddPublicHub( hubitem->m_sName, hubitem->m_sHost, hubitem->m_sDescription, hubitem->m_nUserCount, hubitem->m_sCountry, hubitem->m_nShared, hubitem->m_nMinShare, hubitem->m_sExtra ); } if ( m_pHubListData->Size() > 0 ) { s.Set((const char*)m_pHubListData->Data(),m_pHubListData->Size()); CIconv * pIconv = new CIconv( CConfig::Instance()->GetRemoteEncoding(), CConfig::Instance()->GetLocalEncoding() ); while( (i = s.Find(0x0d,i)) != -1 ) { line = s.Mid(i1,i-i1); if ( !line.IsEmpty() ) { s1 = line.Section( '|', 0, 0 ); s2 = line.Section( '|', 1, 1 ); s3 = line.Section( '|', 2, 2 ); s4 = line.Section( '|', 3, 3 ); // replace all spaces s2 = s2.Replace(" ",""); // remove line ends s1 = s1.Replace("\n", ""); // name, host, description, usercount CConfig::Instance()->AddPublicHub( pIconv->encode(s1), pIconv->encode(s2), pIconv->encode(s3), s4.asULL() ); } i1 = i+2; i += 2; } delete pIconv; } // store the list if ( CConfig::Instance()->GetHubListStoreLocal() ) { CConfig::Instance()->SaveDCHub(); } m_Thread.Stop(false); m_Thread.SetThreadCallBackFunction(0); m_bGetHubListDone = true; return 0; } /** */ bool CHubListManager::NextHubListUrl() { bool res = false; while( (m_pHubListUrl=m_pHubListUrlList->Next(m_pHubListUrl)) != 0 ) { if ( m_pHubListUrl->bEnabled ) { if ( m_pHubListUrl->sUrl.Left(7) == "file://" ) { CByteArray * data = new CByteArray(); if ( data->LoadFromFile(m_pHubListUrl->sUrl.Mid(7)) ) { HandleHubListData( m_pHubListUrl->sUrl, data ); } delete data; if ( NextHubListUrl() == false ) { // parse public hub list in own thread m_Thread.SetThreadCallBackFunction( new CCallback0( this, &CHubListManager::ParsePublicHubList ) ); m_Thread.Start(); } res = true; break; } else if ( m_pHubListUrl->sUrl.NotEmpty() ) { m_pHttp->GetUrl(m_pHubListUrl->sUrl); res = true; break; } } } return res; } /** */ int CHubListManager::ParseXmlPublicHubList() { int count = 0; printf("Parse XML hub list...\n"); do { if ( (m_pXml->Name() == "Hublist") && m_pXml->FirstChild() ) { CList * cols = FindAndParseXmlColumns(); if ( !cols ) { /* * The column headings are only needed so that the Extra * field is filled in. */ printf("ParseXmlPublicHubList: no column headings found, trying with defaults\n"); cols = new CList; CXmlColumn * xmlcol = new CXmlColumn(); xmlcol->m_sName = "Name"; xmlcol->m_sType = "string"; cols->Add(xmlcol); xmlcol = new CXmlColumn(); xmlcol->m_sName = "Address"; xmlcol->m_sType = "string"; cols->Add(xmlcol); xmlcol = new CXmlColumn(); xmlcol->m_sName = "Description"; xmlcol->m_sType = "string"; cols->Add(xmlcol); xmlcol = new CXmlColumn(); xmlcol->m_sName = "Port"; xmlcol->m_sType = "int"; cols->Add(xmlcol); xmlcol = new CXmlColumn(); xmlcol->m_sName = "Users"; xmlcol->m_sType = "int"; cols->Add(xmlcol); } /* go back to start */ m_pXml->DocFirstChild(); m_pXml->FirstChild(); do { if ( (m_pXml->Name() == "Hubs") && m_pXml->FirstChild() ) { count += ParseXmlHubs( cols ); m_pXml->Parent(); } } while ( m_pXml->NextNode() ); m_pXml->Parent(); cols->Clear(); delete cols; } } while ( m_pXml->NextNode() ); printf("XML hublist: %d hubs\n", count); return count; } /** */ int CHubListManager::ParseXmlHubs( CList * cols ) { int count = 0; do { if ( (m_pXml->Name() == "Hub") ) { ParseXmlHub(cols); count++; } } while ( m_pXml->NextNode() ); return count; } /** */ CList * CHubListManager::FindAndParseXmlColumns() { CList * cols = 0; do { if ( (m_pXml->Name() == "Columns") && m_pXml->FirstChild() ) { cols = new CList; do { if ( m_pXml->Name() == "Column" ) { CXmlColumn * col = new CXmlColumn(); col->m_sName = m_pXml->Prop("Name"); col->m_sType = m_pXml->Prop("Type"); cols->Add(col); } } while ( m_pXml->NextNode() ); break; } if ( m_pXml->FirstChild() ) { do { if ( (m_pXml->Name() == "Columns") && m_pXml->FirstChild() ) { cols = new CList; do { if ( m_pXml->Name() == "Column" ) { CXmlColumn * col = new CXmlColumn(); col->m_sName = m_pXml->Prop("Name"); col->m_sType = m_pXml->Prop("Type"); cols->Add(col); } } while ( m_pXml->NextNode() ); break; } } while ( m_pXml->NextNode() ); if ( cols ) { break; } } } while ( m_pXml->NextNode() ); /* no CXml::Parent() called since ParseXmlPublicHubList() just goes back to the start */ return cols; } /** */ void CHubListManager::ParseXmlHub( CList * cols ) { CXmlColumn * col = 0; DCConfigHubItem * hubitem = new DCConfigHubItem(); CString port,namelc; while ( (col = cols->Next(col)) != 0 ) { col->m_sValue = m_pXml->Prop(col->m_sName); namelc = col->m_sName.ToLower(); if (namelc == "name") { hubitem->m_sName = col->m_sValue; } else if (namelc == "address") { hubitem->m_sHost = col->m_sValue; } else if (namelc == "description") { hubitem->m_sDescription = col->m_sValue; } else if (namelc == "users") { hubitem->m_nUserCount = col->m_sValue.asULL(); } else if (namelc == "port") { port = col->m_sValue; } else if (namelc == "country") { hubitem->m_sCountry = col->m_sValue; } else if (namelc == "minshare") { hubitem->m_nMinShare = col->m_sValue.asULL(); } else if (namelc == "shared") { hubitem->m_nShared = col->m_sValue.asULL(); } else { hubitem->m_sExtra += col->m_sName; hubitem->m_sExtra += '='; hubitem->m_sExtra += col->m_sValue; hubitem->m_sExtra += ' '; } //printf("Name=%s Type=%s Value=%s\n", col->m_sName.Data(), col->m_sType.Data(), col->m_sValue.Data()); } if ( (hubitem->m_sHost.Find(':') < 0) && (port.NotEmpty()) ) { hubitem->m_sHost += ':'; hubitem->m_sHost += port; } if ( hubitem->m_sName.IsEmpty() || hubitem->m_sHost.IsEmpty() ) { delete hubitem; } else { m_pXmlHubs->Add(hubitem); } } libdc0-0.3.24~svn3121/dclib/csearchmanager.h0000644000175000017500000001317011125260136017411 0ustar sikonsikon/*************************************************************************** csearchmanager.h - description ------------------- begin : Thu May 27 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSEARCHMANAGER_H #define CSEARCHMANAGER_H /** *@author Mathias Küster * * This whole class is mainly designed for automatically entering, doing * the search, and leaving, hubs, from some list. I doubt any other * client does this nor any hub would want this behaviour. * * What this class can not do is match search results to searches, nor can * it manage a changing list of searches. Results are either sent to * CDownloadManager for auto searches or via a single callback to one * search window. There is a list of searches, but that can only be set * when starting the search. * * Valknut may have been modified to allow more than one search window * but it does not allow more than one search to be running at a time. */ #include #include #include #include #include #include #include #include #include /** */ class CSearchClient : public CClient { public: /** */ CSearchClient() { m_bSearchRemove = false; m_bSearchEnable = false; m_pCurrentSearchObject = 0; m_tSearchTimeout = 0; }; /** */ virtual ~CSearchClient() {}; /** */ bool m_bSearchRemove; /** */ bool m_bSearchEnable; /** */ time_t m_tSearchTimeout; /** */ CDCMessage * m_pCurrentSearchObject; }; /** search modes */ enum eSearchMode { esmCONNECTEDSINGLE = 0, esmCONNECTEDALL, esmPUBLIC, esmBOOKMARK }; enum eSearchState { esNONE = 0, esSEARCH, esTIMEOUT, esSTOP }; /** */ enum eSearchError { eseNONE = 0, eseALREADYRUN }; /** */ enum eSearchType { estyNONE = 0, estySINGLE, estyMULTI, estyEXTERNAL }; /** */ class CSearchManager : public CSingleton { public: /** */ CSearchManager(); /** */ virtual ~CSearchManager(); /** */ int CallBackManager(); /** */ int CallBackClient( CClient * Client, CDCMessage * DCMessage ); /** */ int CallBackSearchSocket( CMessageSearchResult* ); /** */ eSearchError StartSearch( eSearchMode mode, eSearchType type, CList * querylist, CStringList * serverlist ); /** */ void StopSearch(); /** */ bool HandleSearch( CDCMessage * message ); /** */ enum eSearchType SearchType() { return m_eSearchType; } /** */ long MaxClients() { return m_nMaxClients; } /** */ void MaxClients( long n ) { m_nMaxClients = n; } /** */ void EnableTag( bool b ) { m_bEnableTag = b; } /** */ bool IsSearch() { return (m_eSearchType != estyNONE); } /** */ eSearchState SearchState() { eSearchState e; m_Mutex.Lock(); e = m_eSearchState; m_Mutex.UnLock(); return e; } /** */ void SearchState( eSearchState e ) { m_Mutex.Lock(); m_eSearchState = e; m_Mutex.UnLock(); } /** */ void SetCallBackFunction( _CCallback1 * callback ); /** */ _CCallback1 * GetCallBackFunction(); /** */ time_t StartTime() { return m_tStartTime; }; /** */ long HubCount(); /** */ long HubIndex() { return m_nHubIndex; }; /** */ long HubError() { return m_nHubError; }; protected: private: /** */ bool AddClients(); /** */ bool AddClient(); /** */ void UpdateClients(); /** */ bool RemoveClients(); /** */ void DisconnectClients(); /** */ bool DoSearch( CSearchClient * HubSearchClient ); /** */ bool SendObject( CDCMessage * DCMessage ); /** manager callback */ _CCallback0 * m_pCallback; /** */ CMutex m_Mutex; /** client list */ CList * m_pClientList; /** max simultan clients */ long m_nMaxClients; /** current hub index */ long m_nHubIndex; /** hub with errors */ long m_nHubError; /** current hub */ CString * m_sCurrentHub; /** hub list */ CStringList * m_pHubList; /** */ CList * m_pSearchList; /** only for passive searches */ CDCMessage * m_pCurrentSearchObject; /** */ bool m_bEnableTag; /** */ bool m_bHandleUserList; /** */ CSearchSocket m_SearchSocket; /** starttime */ time_t m_tStartTime; /** timeout */ time_t m_tTimeoutTime; /** search type */ enum eSearchType m_eSearchType; /** search state */ enum eSearchState m_eSearchState; /** search mode */ enum eSearchMode m_eSearchMode; /** client mode */ enum eClientMode m_eClientMode; /** callback function */ _CCallback1 * m_pParentCallback; /** mutex for changing callback */ CMutex m_CallbackMutex; }; /** */ inline void CSearchManager::SetCallBackFunction( _CCallback1 * callback ) { m_CallbackMutex.Lock(); m_pParentCallback = callback; m_CallbackMutex.UnLock(); } /** */ inline _CCallback1 * CSearchManager::GetCallBackFunction() { return m_pParentCallback; } #endif libdc0-0.3.24~svn3121/dclib/chublistmanager.h0000644000175000017500000000615611101144617017623 0ustar sikonsikon/*************************************************************************** chublistmanager.h - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CHUBLISTMANAGER_H #define CHUBLISTMANAGER_H /** *@author Mathias Küster * * This handles downloading and parsing hublist data, * the data is then sent to CConfig for storage. */ #include #include #include #include #include class CHubListManager; class CHttp; class DCConfigHubListUrl; class CByteArray; class DCConfigHubItem; class CXml; class CDCMessage; class _CCallback0; class CXmlColumn { public: /** */ CXmlColumn() {}; /** */ ~CXmlColumn() {}; /** Column name */ CString m_sName; /** Column type */ CString m_sType; /** Column value */ CString m_sValue; }; class CHubListManager : public CSingleton { public: /** */ CHubListManager(); /** */ virtual ~CHubListManager(); /** callback function */ virtual int DC_CallBack( CDCMessage * ) { return -1; }; protected: /** */ bool GetPublicHubList(); /** */ bool NextHubListUrl(); /** */ CThread m_Thread; /** */ CHttp * m_pHttp; /** */ CList * m_pHubListUrlList; /** */ DCConfigHubListUrl * m_pHubListUrl; /** data from old .config format hub lists */ CByteArray * m_pHubListData; /** data from xml hublists */ CList * m_pXmlHubs; private: /** http callback function */ int HttpCallBack( CDCMessage * msg ); /** called by CManager */ int Callback(); /** */ int ParsePublicHubList(); /** Parses XML hublist, adding items to m_pXmlHubs */ int ParseXmlPublicHubList(); /** Returns number of hubs parsed */ int ParseXmlHubs( CList * cols ); /** Searches for and gets column headings */ CList * FindAndParseXmlColumns(); /** Gets column values for one hub */ void ParseXmlHub( CList * cols ); /** Handle the hublist data, decompressing and parsing the xml if necessary */ void HandleHubListData( const CString & url, CByteArray * data ); /** */ time_t m_nReloadHubListTimeout; /** */ bool m_bGetHubListDone; /** CXml object for parsing XML hublists */ CXml * m_pXml; /** */ _CCallback0 * m_pCallback; }; #endif libdc0-0.3.24~svn3121/dclib/cdownloadmanager.cpp0000644000175000017500000036072611256404271020327 0ustar sikonsikon/*************************************************************************** cdownloadmanager.cpp - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cdownloadmanager.h" #include #include #include "dcobject.h" #include "cconfig.h" #include "core/cdir.h" #include "core/cfile.h" #include "cconnectionmanager.h" #include "cdownloadqueue.h" #include "core/clogfile.h" #include "core/cmanager.h" #include "cfilemanager.h" #include "dclib.h" #include "core/platform.h" #include "csearchmanager.h" #include "cutils.h" #include "core/ccallback.h" #include "core/cnetaddr.h" extern "C" { #include "gnulib/md5.h" } #ifdef WIN32 #include #else #include #include #include #endif #define TEST_CHUNK_SIZE (10*1024) /* search results by TTH are now returned in a set */ #include #include /** */ CDownloadManager::CDownloadManager() { m_nID = 0; m_eShutdownState = essNONE; m_tDownloadQueueTimeout = time(0); m_tUpdateTransferTimeout = time(0); m_tHubSearchTimeout = time(0); m_tSearchTimeout = 0; m_tLastRateExtra = time(0); m_tWaitListCleaned = time(0); m_pTransfersMutex = new CMutex(); m_pTransferList = new CStringList(); m_pBanListMutex = new CMutex(); m_pTransferBanList = new CStringList(); m_pExtraSlotsMutex = new CMutex(); m_pExtraUserSlotList = new CList(); m_pWaitListMutex = new CMutex(); m_pTransferWaitList = new CList(); m_pSearchList = new CList(); m_pSearchQueryList = new CList(); m_pDownloadQueue = new CDownloadQueue(); m_pCallback = 0; } /** */ CDownloadManager::~CDownloadManager() { SetInstance(0); CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; delete m_pExtraUserSlotList; m_pExtraUserSlotList = 0; delete m_pExtraSlotsMutex; m_pExtraSlotsMutex = 0; delete m_pTransferList; m_pTransferList = 0; delete m_pTransfersMutex; m_pTransfersMutex = 0; delete m_pTransferWaitList; m_pTransferWaitList = 0; delete m_pWaitListMutex; m_pWaitListMutex = 0; delete m_pTransferBanList; m_pTransferBanList = 0; delete m_pBanListMutex; m_pBanListMutex = 0; delete m_pSearchList; m_pSearchList = 0; delete m_pSearchQueryList; m_pSearchQueryList = 0; delete m_pDownloadQueue; m_pDownloadQueue = 0; } /** load the queue */ int CDownloadManager::DLM_LoadQueue() { int err = -1; CStringList * StringList = 0; m_pDownloadQueue->pQueueMutex->Lock(); m_pDownloadQueue->pQueue->Clear(); m_pDownloadQueue->pChunksMutex->Lock(); m_pDownloadQueue->pChunkList->Clear(); if ( CConfig::Instance() ) err = CConfig::Instance()->LoadDCTra( m_pDownloadQueue->pQueue, m_pDownloadQueue->pChunkList ); // send all files over the callback function if ( err == 0 ) { while( m_pDownloadQueue->pQueue->Next( &StringList) ) { DCTransferQueueObject * TransferObject = 0; while( StringList->Next( &TransferObject) ) { DCTransferFileObject * TransferFileObject = 0; while( TransferObject->pTransferFileList.Next( &TransferFileObject) ) { SendFileInfo( TransferObject, TransferFileObject ); } } } } m_pCallback = new CCallback0( this, &CDownloadManager::Callback ); if ( CManager::Instance() ) CManager::Instance()->Add( m_pCallback ); m_pDownloadQueue->pChunksMutex->UnLock(); m_pDownloadQueue->pQueueMutex->UnLock(); return err; } /** save the queue */ int CDownloadManager::DLM_SaveQueue() { int err = -1; m_pDownloadQueue->pQueueMutex->Lock(); m_pDownloadQueue->pChunksMutex->Lock(); if ( CConfig::Instance() ) err = CConfig::Instance()->SaveDCTra( m_pDownloadQueue->pQueue, m_pDownloadQueue->pChunkList ); m_pDownloadQueue->pChunksMutex->UnLock(); m_pDownloadQueue->pQueueMutex->UnLock(); return err; } /** disconnect all transfers for a clean shutdown */ void CDownloadManager::DLM_Shutdown() { CTransferObject * TransferObject = 0; // set shutdown state m_eShutdownState = essSHUTDOWN; SendLogInfo("Shutdown download manager ...\n"); m_pTransfersMutex->Lock(); DPRINTF("Running Transfers: %ld\n",m_pTransferList->Count()); while( m_pTransferList->Next( &TransferObject ) ) { TransferObject->m_pTransfer->Disconnect(true); } m_pTransfersMutex->UnLock(); } /** add a extra slot to the user */ void CDownloadManager::DLM_AddUserSlot( CString nick, CString hubname, int slot, bool permanent ) { CExtraUserSlot * ExtraUserSlot; m_pExtraSlotsMutex->Lock(); ExtraUserSlot = 0; while( (ExtraUserSlot=m_pExtraUserSlotList->Next(ExtraUserSlot)) != 0 ) { if ( (ExtraUserSlot->sNick == nick) && (ExtraUserSlot->sHubName == hubname) ) { if ( slot == 0 ) { ExtraUserSlot->iSlots = slot; } else { ExtraUserSlot->iSlots += slot; } ExtraUserSlot->bPermanent = permanent; break; } } if ( ExtraUserSlot == 0 ) { ExtraUserSlot = new CExtraUserSlot(); ExtraUserSlot->sNick = nick; ExtraUserSlot->sHubName = hubname; ExtraUserSlot->iSlots = slot; ExtraUserSlot->bPermanent = permanent; m_pExtraUserSlotList->Add(ExtraUserSlot); } SendSlotInfo(ExtraUserSlot); if ( (ExtraUserSlot->iSlots == 0) && (!ExtraUserSlot->bPermanent) ) { m_pExtraUserSlotList->Del(ExtraUserSlot); } m_pExtraSlotsMutex->UnLock(); } /** */ bool CDownloadManager::DLM_TransferConnect( CString nick, CString hubname ) { bool res = false; m_pDownloadQueue->pQueueMutex->Lock(); DCTransferQueueObject * TransferObject = 0; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() )) != 0 ) { TransferObject->tTimeout = 0; res = true; } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_TransferClose( ulonglong transferid ) { CTransferObject * TransferObject = 0; bool res = false; m_pTransfersMutex->Lock(); if ( m_pTransferList->Get( CString::number(transferid), &TransferObject ) == 0 ) { TransferObject->m_pTransfer->Disconnect(true); res = true; } m_pTransfersMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_TransferSetRate( ulonglong transferid, ulonglong rate ) { CTransferObject * TransferObject = 0; bool res = false; m_pTransfersMutex->Lock(); if ( m_pTransferList->Get( CString::number(transferid), &TransferObject ) == 0 ) { TransferObject->m_pTransfer->SetRate(rate); res = true; } m_pTransfersMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_TransferGetRate( ulonglong transferid, ulonglong & rate ) { CTransferObject * TransferObject = 0; bool res = false; m_pTransfersMutex->Lock(); if ( m_pTransferList->Get( CString::number(transferid), &TransferObject ) == 0 ) { rate = TransferObject->m_pTransfer->GetRate(); res = true; } m_pTransfersMutex->UnLock(); return res; } /** */ eDirection CDownloadManager::DLM_TransferDirection( ulonglong transferid ) { CTransferObject * TransferObject = 0; eDirection direction=edNONE; m_pTransfersMutex->Lock(); if ( m_pTransferList->Get( CString::number(transferid), &TransferObject ) == 0 ) { direction = TransferObject->m_pTransfer->GetSrcDirection(); } m_pTransfersMutex->UnLock(); return direction; } /** */ void CDownloadManager::DLM_QueueAdd( CString nick, CString hubname, CString hubhost, CString remotename, CString localname, CString localpath, CString localrootpath, eltMedium medium, ulonglong size, ulonglong startposition, ulonglong endposition, CString hash, bool multi ) { CDir dir; CString sfile; DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject = 0; DCHubObject * HubObject; /* * Although this may not be the best place for this, dclib got stuck in a loop of * get next chunk ... no more chunks when I tried to download a zero byte file. * This will mean zero byte files are never present in the queue, they are just * immediately created. */ if ( (size == 0) && (medium == eltFILE) ) { if ( startposition != 0 ) { CString logmsg = "Warning: 0B file has non-zero start position of "; logmsg += CString::number(startposition); SendLogInfo( logmsg ); } if ( endposition != 0 ) { CString logmsg = "Warning: 0B file has non-zero end position of "; logmsg += CString::number(endposition); SendLogInfo( logmsg ); } if ( localrootpath.IsEmpty() ) { sfile = CConfig::Instance()->GetDownloadFinishedFolder(); if ( sfile.IsEmpty() ) { sfile = CConfig::Instance()->GetDownloadFolder(); } } else { sfile = localrootpath; } localpath = localpath.Replace(':',""); localname = localname.Replace(':',""); sfile += '/'; sfile += localpath; sfile += '/'; sfile = CDir::SimplePath(sfile); if ( dir.IsDir( sfile, false ) == false ) { if ( dir.CreatePath( sfile ) == false ) { CString logmsg = "Create path '"; logmsg += sfile; logmsg += "' for 0B file '"; logmsg += localname; logmsg += "' failed"; SendLogInfo( logmsg ); return; } } sfile += localname; if ( dir.IsFile( sfile, false ) == false ) { CFile cfile; const int mode = IO_RAW | IO_READONLY | IO_CREAT; /* From CTransfer::DoInitDownload() */ const int acc = MO_IRUSR|MO_IWUSR|MO_IRGRP|MO_IWGRP|MO_IROTH|MO_IWOTH; if ( cfile.Open( sfile, mode, acc ) == false ) { CString logmsg = "Create 0B file '"; logmsg += sfile; logmsg += "' failed"; SendLogInfo( logmsg ); return; } else { cfile.Close(); } } /* Either already existed or has been created, send download finished message */ CString logmsg = "Transfer done '"; logmsg += remotename; logmsg += '\''; SendLogInfo( logmsg ); if ( CConfig::Instance()->GetLogFile() && CConfig::Instance()->GetLogFinishedDownloads() ) { logmsg = "Transfer done '"; logmsg += sfile; logmsg += '\''; CLogFile::Write(CConfig::Instance()->GetLogFileName(),eltINFO,logmsg); } return; } /* this never happens anymore, fixed in 0.3.18, unless something was missed in valknut */ if ((hash.Left(4)).ToUpper() == "TTH:") { DPRINTF("DLM_QueueAdd: Removed TTH: prefix from TTH\n"); hash = hash.Mid(4, hash.Length() - 4); } /* DPRINTF("add queue entry: %s %s %s %s %d %s %s %s %llu %llu\n", nick.Data(), remotename.Data(), hubname.Data(), hubhost.Data(), medium, localname.Data(), localpath.Data(), localrootpath.Data(), startposition, size );*/ m_pDownloadQueue->pQueueMutex->Lock(); CStringList * StringList = m_pDownloadQueue->GetUserHubList( nick ); if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, hubhost )) == 0 ) { TransferObject = new DCTransferQueueObject(); TransferObject->sNick = nick; TransferObject->sHubHost = hubhost; TransferObject->sHubName = hubname; TransferObject->eState = etwsIDLE; TransferObject->iConnections = 0; TransferObject->tTimeout = 0; HubObject = new DCHubObject(); HubObject->m_sHubName = hubname; HubObject->m_sHubHost = hubhost; HubObject->m_bActive = true; TransferObject->pHubList.Add(HubObject); if ( StringList == 0 ) { StringList = new CStringList(); m_pDownloadQueue->pQueue->Add( nick, StringList ); } StringList->Add( hubname, TransferObject ); //DPRINTF("transfer add\n"); } else { TransferFileObject = m_pDownloadQueue->GetUserFileObject( nick, hubname, hubhost, remotename ); } // file not found for the nick/hub if ( TransferFileObject == 0 ) { TransferFileObject = new DCTransferFileObject(); TransferFileObject->m_eState = etfsNONE; TransferFileObject->m_nSize = size; TransferFileObject->m_bMulti = multi; TransferFileObject->m_eMedium = medium; TransferFileObject->m_sRemoteFile = remotename; TransferFileObject->m_sHash = hash; if ( remotename == DC_USER_FILELIST ) { TransferFileObject->m_nPriority = 0; TransferFileObject->m_sJumpTo = localpath; localpath.Empty(); if ( localrootpath.NotEmpty() ) { TransferFileObject->m_pDirList = new std::list(); TransferFileObject->m_pDirList->push_back( localrootpath ); localrootpath.Empty(); } } else { TransferFileObject->m_nPriority = 2; } if ( localrootpath.IsEmpty() ) { sfile = CConfig::Instance()->GetDownloadFolder(); } else { sfile = localrootpath; } localpath = localpath.Replace(':',""); localname = localname.Replace(':',""); sfile += '/'; sfile += localpath; sfile += '/'; sfile += localname; sfile = CDir::SimplePath(sfile); TransferFileObject->m_sLocalFile = sfile; TransferFileObject->m_sLocalPath = localpath; TransferFileObject->m_sLocalFileName = localname; TransferObject->pTransferFileList.Add( remotename, TransferFileObject ); //DPRINTF("file add '%s' %ld\n",sfile.Data(),TransferObject->pTransferFileList.Count()); m_pDownloadQueue->pChunksMutex->Lock(); DCFileChunkObject * FileChunkObject; if ( remotename == DC_USER_FILELIST ) { DPRINTF("no chunk for userlists\n"); } else if ( m_pDownloadQueue->pChunkList->Get( sfile, &FileChunkObject ) != 0 ) { FileChunkObject = new DCFileChunkObject(); FileChunkObject->m_sLocalFile = sfile; FileChunkObject->m_sHash = hash; FileChunkObject->m_bMulti = multi; FileChunkObject->m_nSize = size; FileChunkObject->m_nSizeDone = startposition; FileChunkObject->m_nReferenceCount = 1; // create the first unfinished chunk DCChunkObject * ChunkObject = new DCChunkObject(); ChunkObject->m_nStart = startposition; ChunkObject->m_nEnd = size; if( endposition ) { endposition++; FileChunkObject->m_nSizeDone = size - (endposition - startposition); ChunkObject->m_nEnd = endposition; } FileChunkObject->m_Chunks.Add(ChunkObject); m_pDownloadQueue->pChunkList->Add( sfile, FileChunkObject ); //DPRINTF("add file chunk object\n"); } else { FileChunkObject->m_nReferenceCount++; DPRINTF("file chunk object found\n"); // fill in any missing information in case a source with TTH is // added to a download without TTH if ( (FileChunkObject->m_sHash.IsEmpty()) && (!hash.IsEmpty()) ) { FileChunkObject->m_sHash = hash; // we now need to iterate over the entire queue to fill in other missing TTHs for this local file // how to iterate over the queue was taken from InitSearch CStringList * sl = 0; while ( m_pDownloadQueue->pQueue->Next( &sl ) ) { DCTransferQueueObject * tqo = 0; while ( sl->Next( &tqo ) ) { DCTransferFileObject * tfo = 0; while ( tqo->pTransferFileList.Next( &tfo ) ) { if ( (tfo->m_sLocalFile == FileChunkObject->m_sLocalFile) && (tfo->m_sHash.IsEmpty()) ) { tfo->m_sHash = hash; // update GUI SendFileInfo( tqo, tfo ); } } } } } // fills in missing information from existing transfer // if source without TTH is added to one with a TTH if ( TransferFileObject->m_sHash.IsEmpty() ) { TransferFileObject->m_sHash = FileChunkObject->m_sHash; } } m_pDownloadQueue->pChunksMutex->UnLock(); } else { DPRINTF("file found ...\n"); if ( remotename == DC_USER_FILELIST ) { TransferFileObject->m_sJumpTo = localpath; if ( localrootpath.NotEmpty() ) { if ( TransferFileObject->m_pDirList ) { // do not download a folder that is inside one already queued // remove any folders that are inside this folder std::list::iterator it = TransferFileObject->m_pDirList->begin(); while ( it != TransferFileObject->m_pDirList->end() ) { if ( localrootpath.StartsWith( *it ) ) { break; } else if ( it->StartsWith( localrootpath ) ) { it = TransferFileObject->m_pDirList->erase( it ); } else { ++it; } } if ( it == TransferFileObject->m_pDirList->end() ) { TransferFileObject->m_pDirList->push_back( localrootpath ); } else { DPRINTF("'%s' already queued within '%s'\n",localrootpath.Data(),it->Data()); } } else { TransferFileObject->m_pDirList = new std::list(); TransferFileObject->m_pDirList->push_back( localrootpath ); } //DPRINTF("directory queue now %zd\n",TransferFileObject->m_pDirList->size()); DPRINTF("directory queue now %lu\n",(unsigned long) TransferFileObject->m_pDirList->size()); } } } SendFileInfo( TransferObject, TransferFileObject ); m_pDownloadQueue->pQueueMutex->UnLock(); } /** 0: file not in the queue 1: file already in the queue by same nick and hub 2: local file with same TTH (same size if no TTH) already in the queue (multi download) 3: local file with same TTH (same size if no TTH) already in the queue without multi (no multi download) 4: local file with different TTH (different size if no TTH) already in the queue (multi download error) */ int CDownloadManager::DLM_QueueCheck( CString nick, CString hubname, CString hubhost, CString remotename, CString localname, CString localpath, CString localrootpath, eltMedium, ulonglong size, CString tth ) { m_pDownloadQueue->pQueueMutex->Lock(); // this should really be fixed globally if ( tth.Left(4).ToUpper() == "TTH:" ) { tth = tth.Mid(4); } CDir dir; CString sfile; int res = 0; DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject = 0; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, hubhost )) != 0 ) { if ( (TransferFileObject = m_pDownloadQueue->GetUserFileObject( nick, hubname, hubhost, remotename )) != 0 ) { res = 1; } } // check if a local file allready exist if ( (res == 0) && (remotename != DC_USER_FILELIST) ) { if ( localrootpath.IsEmpty() ) { sfile = CConfig::Instance()->GetDownloadFolder(); } else { sfile = localrootpath; } localpath = localpath.Replace(':',""); localname = localname.Replace(':',""); sfile += '/'; sfile += localpath; sfile += '/'; sfile += localname; sfile = CDir::SimplePath(sfile); DCFileChunkObject * FileChunkObject; m_pDownloadQueue->pChunksMutex->Lock(); if ( m_pDownloadQueue->pChunkList->Get( sfile, &FileChunkObject ) == 0 ) { // allow manual addition of non-TTH sources to files with TTHs // and allow addition of TTH sources to files with no TTH if ( ((tth.IsEmpty() || FileChunkObject->m_sHash.IsEmpty()) && (FileChunkObject->m_nSize == size)) || (FileChunkObject->m_sHash == tth) ) { if ( FileChunkObject->m_bMulti ) { res = 2; } else { res = 3; } } else { res = 4; } } m_pDownloadQueue->pChunksMutex->UnLock(); } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** change the src-nick/hubname to dst-nick/hubname in the queue */ bool CDownloadManager::DLM_QueueEdit( CString srcnick, CString srchubname, CString dstnick, CString dsthubname, CString dsthubhost ) { bool res; DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject; m_pDownloadQueue->pQueueMutex->Lock(); res = false; // check if transfer run if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( srcnick, srchubname, CString() )) != 0 ) { if ( (TransferObject->eState != etwsWAIT) && (TransferObject->eState != etwsRUN) ) { // only rename if the new not exists if ( m_pDownloadQueue->GetUserTransferObject( dstnick, dsthubname, dsthubhost ) == 0 ) { // send remove all files TransferFileObject = 0; while( TransferObject->pTransferFileList.Next( &TransferFileObject ) ) { SendFileInfo( TransferObject, TransferFileObject, true ); } // rename old entry m_pDownloadQueue->RenameNick( srcnick, dstnick, srchubname, dsthubname ); // get hubhost from new entry if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( dstnick, dsthubname, dsthubhost )) != 0 ) { TransferObject->sHubHost = dsthubhost; // send new files TransferFileObject = 0; while( TransferObject->pTransferFileList.Next( &TransferFileObject ) ) { SendFileInfo( TransferObject, TransferFileObject ); } res = true; } } else { // update hubhost if ( TransferObject->sHubHost != dsthubhost ) { TransferObject->sHubHost = dsthubhost; SendFileInfo( TransferObject ); } } } } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_QueuePause( CString nick, CString hubname, CString remotefile, bool pause ) { bool res = false; DCTransferFileObject * TransferFileObject = 0; DCTransferQueueObject * TransferObject = 0; m_pDownloadQueue->pQueueMutex->Lock(); if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() )) != 0 ) { if ( remotefile.NotEmpty() ) { if ( (TransferFileObject = m_pDownloadQueue->GetUserFileObject( nick, hubname, CString(), remotefile )) != 0 ) { if ( TransferFileObject->m_eState != etfsTRANSFER ) { if ( pause ) TransferFileObject->m_eState = etfsPAUSE; else TransferFileObject->m_eState = etfsNONE; SendFileInfo( TransferObject, TransferFileObject ); res = true; } } } else { TransferFileObject = 0; while ( TransferObject->pTransferFileList.Next( &TransferFileObject ) ) { if ( TransferFileObject->m_eState != etfsTRANSFER ) { if ( pause ) TransferFileObject->m_eState = etfsPAUSE; else TransferFileObject->m_eState = etfsNONE; SendFileInfo( TransferObject, TransferFileObject ); res = true; } } } } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_QueueRemove( CString nick, CString hubname, CString remotefile ) { bool res; m_pDownloadQueue->pQueueMutex->Lock(); res = RemoveQueueFile( nick, hubname, remotefile ); m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_QueueRemove( CString localfile ) { bool res; m_pDownloadQueue->pQueueMutex->Lock(); res = RemoveQueueFile(localfile); m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ int CDownloadManager::DLM_QueueRemoveDirectory( CString nick, CString hubname, CString directory ) { int res; m_pDownloadQueue->pQueueMutex->Lock(); DCTransferFileObject * TransferFileObject = m_pDownloadQueue->GetUserFileObject( nick, hubname, CString(), DC_USER_FILELIST ); if ( TransferFileObject ) { if ( TransferFileObject->m_pDirList ) { std::list::iterator it = TransferFileObject->m_pDirList->begin(); for ( ; it != TransferFileObject->m_pDirList->end(); ++it ) { if ( *it == directory ) { break; } } if ( it == TransferFileObject->m_pDirList->end() ) { res = 3; } else { TransferFileObject->m_pDirList->erase( it ); if ( TransferFileObject->m_pDirList->empty() ) { delete TransferFileObject->m_pDirList; TransferFileObject->m_pDirList = 0; } res = 0; DCTransferQueueObject * TransferQueueObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() ); if ( TransferQueueObject ) { SendFileInfo( TransferQueueObject, TransferFileObject ); } } } else { res = 2; } } else { res = 1; } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_QueueSetFilePriority( CString nick, CString hubname, CString remotefile, int priority ) { m_pDownloadQueue->pQueueMutex->Lock(); bool res = false; DCTransferQueueObject * TransferObject = 0; DCTransferFileObject * TransferFileObject = 0; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() )) != 0 ) { if ( (remotefile.NotEmpty()) && (priority <= MAX_FILE_PRIORITY) ) { if ( (TransferFileObject = m_pDownloadQueue->GetUserFileObject( nick, hubname, CString(), remotefile )) != 0 ) { // we don't need check if transfer is running TransferFileObject->m_nPriority = priority; SendFileInfo( TransferObject, TransferFileObject ); res = true; } } } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::DLM_QueueGetFileInfo( CString nick, CString hubname, CString hubhost, CString remotefile, CUserFileInfo * UserFileInfo ) { bool res = false; if (!UserFileInfo) { return res; } m_pDownloadQueue->pQueueMutex->Lock(); DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, hubhost )) != 0 ) { UserFileInfo->eWaitState = TransferObject->eState; if ( remotefile.NotEmpty() ) { if ( TransferObject->pTransferFileList.Get( remotefile, &TransferFileObject ) == 0 ) { UserFileInfo->eFileState = TransferFileObject->m_eState; UserFileInfo->sLocalFile = TransferFileObject->m_sLocalFile; UserFileInfo->bMulti = TransferFileObject->m_bMulti; res = true; } } else { res = true; } } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ DCFileChunkObject * CDownloadManager::DLM_QueueGetFileChunk( CString file ) { m_pDownloadQueue->pQueueMutex->Lock(); DCFileChunkObject * FileChunkObject1, * FileChunkObject2=0; if ( (FileChunkObject1 = m_pDownloadQueue->GetFileChunkObject(file)) != 0 ) { FileChunkObject2 = new DCFileChunkObject(FileChunkObject1); } m_pDownloadQueue->pQueueMutex->UnLock(); return FileChunkObject2; } /** */ bool CDownloadManager::DLM_QueueUpdateHub( CString nick, CString hubname ) { m_pDownloadQueue->pQueueMutex->Lock(); bool res = false; DCConfigHubItem hubitem; DCTransferQueueObject * TransferObject; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() )) != 0 ) { if ( (res = CConfig::Instance()->GetPublicHub( hubname, &hubitem )) ) TransferObject->sHubHost = hubitem.m_sHost; else if ( (res = CConfig::Instance()->GetBookmarkHub( hubname, &hubitem )) ) TransferObject->sHubHost = hubitem.m_sHost; if ( res == true ) SendFileInfo( TransferObject ); } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ void CDownloadManager::DLM_QueueGetHub( CString nick, CString hubname, CList * list ) { DCTransferQueueObject * TransferObject; DCHubObject * HubObject1; if (!list) { return; } list->Clear(); m_pDownloadQueue->pQueueMutex->Lock(); if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() )) != 0 ) { HubObject1=0; while( (HubObject1=TransferObject->pHubList.Next(HubObject1)) != 0 ) list->Add( new DCHubObject(HubObject1) ); } m_pDownloadQueue->pQueueMutex->UnLock(); return; } /** */ bool CDownloadManager::DLM_AddTransferRequest( CString nick, CString userhost, CString hubname, CString hubhost ) { bool res; DCTransferWait * TransferWait; if ( m_eShutdownState != essNONE ) { return false; } m_pWaitListMutex->Lock(); res = false; TransferWait = 0; DPRINTF("ATR: '%s' '%s' '%s' '%s'\n",nick.Data(),userhost.Data(),hubname.Data(),hubhost.Data()); DPRINTF("ATR COUNT: %ld\n",m_pTransferWaitList->Count()); if ( m_pTransferWaitList->Count() < 250 ) { // check if the user allready in the waitlist while ( (TransferWait = m_pTransferWaitList->Next(TransferWait)) != 0 ) { if ( TransferWait->sHubName == hubname ) { // here one of "nick" or "userhost" will be empty if ( (TransferWait->sNick == nick) && (TransferWait->sUserHost == userhost) ) { DPRINTF("ATR FOUND\n"); // reset timeout, ignore it on to fast connections if ( (time(0)-TransferWait->tTimeout) > 2 ) { // count in requests from a client TransferWait->m_nCount++; TransferWait->tTimeout = time(0); res = true; } else { DPRINTF("ATR to fast connections\n"); } break; } } } if ( TransferWait == 0 ) { // user not found, add it DPRINTF("ATR ADD\n"); TransferWait = new DCTransferWait(); TransferWait->sNick = nick; TransferWait->sUserHost = userhost; TransferWait->sHubName = hubname; TransferWait->sHubHost = hubhost; TransferWait->tTimeout = time(0); TransferWait->m_nCount = 1; m_pTransferWaitList->Add(TransferWait); res = true; } } else { // TODO: warn message ... } m_pWaitListMutex->UnLock(); return res; } /** */ void CDownloadManager::DLM_AddTransferRequest( CString host, int port, bool crypto, CString hubname, CString hubhost ) { if ( m_eShutdownState != essNONE ) { return; } DPRINTF("ATR: '%s:%d' %d '%s' '%s'\n",host.Data(),port,crypto,hubname.Data(),hubhost.Data()); // check private address space if ( !((CConfig::Instance()->GetCheckPrivateAddressSpace() && CNetAddr::IsPrivateI4(host.Data())) || (CConfig::Instance()->GetPrivateAddressSpaceOnly() && (CNetAddr::IsPrivateI4(host.Data()) == false)) ) ) { // TODO: check if client allready in the transfer wait list // create a new transfer CTransferObject * TransferObject = new CTransferObject(); TransferObject->m_pTransfer = new CTransfer(); TransferObject->m_pTransfer->SetTransferID( GetNewID() ); TransferObject->m_pTransfer->SetNick( CConfig::Instance()->GetNick( hubname, hubhost ) ); TransferObject->m_pTransfer->SetHubName(hubname); TransferObject->m_pTransfer->SetHubHost(hubhost); TransferObject->m_pTransfer->SetHost( host, port ); TransferObject->m_pTransfer->SetRate( CConfig::Instance()->GetMaxUploadRate() ); if ( crypto ) { if ( TransferObject->m_pTransfer->ChangeSocketMode( esmFULLSSLCLIENT, CConfig::Instance()->GetTransferCert(), CConfig::Instance()->GetTransferKey() ) == false ) { DPRINTF("New transfer change to SSL client mode failed\n"); delete TransferObject; return; } } // add this transfer to the wait list if ( DLM_AddTransferRequest( CString(), TransferObject->m_pTransfer->GetHost(), hubname, hubhost ) == false ) { // request allready in the list delete TransferObject; } else { m_pTransfersMutex->Lock(); m_pTransferList->Add( CString::number(TransferObject->m_pTransfer->GetTransferID()), TransferObject ); TransferObject->m_pTransfer->SetCallBackFunction( new CCallback2( this, &CDownloadManager::DM_TransferCallBack ) ); DPRINTF("ATR CONNECT: %s:%d %d %s %s\n",host.Data(),port,crypto,hubname.Data(),hubhost.Data()); // connect to the client TransferObject->m_pTransfer->Connect(); m_pTransfersMutex->UnLock(); } } else { // send warning CString logmsg = "Ignoring connection to: "; logmsg += host; logmsg += ':'; logmsg += CString::number(port); logmsg += " at hub '"; logmsg += hubname; logmsg += "' ("; logmsg += hubhost; logmsg += ") due to private address space settings"; SendLogInfo( logmsg ); } } /** */ bool CDownloadManager::DLM_GetDownloadManagerInfo( CDownloadManagerInfo * pinfo ) { *pinfo = DownloadManagerInfo; return true; } /** handle search */ bool CDownloadManager::DLM_HandleSearch( CMessageSearchResult * MessageSearchResult ) { bool res = false; CMessageSearchResult * msg = 0; DCTransferFileObject * tfo1=0, * tfo2=0; while ( (msg = m_pSearchList->Next(msg)) != 0 ) { //MessageSearchResult->sNick += "+"; if ( msg->m_sHash == MessageSearchResult->m_sHash ) { // handle this file m_pDownloadQueue->pQueueMutex->Lock(); // check if this file allready in the queue if ( m_pDownloadQueue->GetUserFileObject( MessageSearchResult->m_sNick, MessageSearchResult->m_sHubName, MessageSearchResult->m_sHubHost, MessageSearchResult->m_sFile ) == 0 ) { // get original file if ( (tfo1=m_pDownloadQueue->GetUserFileObject( msg->m_sNick, msg->m_sHubName, msg->m_sHubHost, msg->m_sFile )) != 0 ) { tfo2 = new DCTransferFileObject(*tfo1); } } m_pDownloadQueue->pQueueMutex->UnLock(); if ( tfo2 ) break; } } if ( tfo2 ) { CDir dir; CString path,file; int adj = 0; dir.SplitPathFile( tfo2->m_sLocalFile, path, file ); // remove tfo2->m_sLocalPath from path if ( (path.Right(1) == DIRSEPARATOR) && (tfo2->m_sLocalPath.Right(1) != DIRSEPARATOR) ) { adj = 1; } else if ( (path.Right(1) != DIRSEPARATOR) && (tfo2->m_sLocalPath.Right(1) == DIRSEPARATOR) ) { adj = -1; } path = path.Left( path.Length() - (tfo2->m_sLocalPath.Length() + adj) ); DLM_QueueAdd( MessageSearchResult->m_sNick, MessageSearchResult->m_sHubName, MessageSearchResult->m_sHubHost, MessageSearchResult->m_sFile, tfo2->m_sLocalFileName, tfo2->m_sLocalPath, path, tfo2->m_eMedium, tfo2->m_nSize, 0, 0, MessageSearchResult->m_sHash, true ); delete tfo2; } return res; } /** */ void CDownloadManager::SendFileInfo( DCTransferQueueObject * TransferObject, DCTransferFileObject * TransferFileObject, bool bRemoveFile ) { if ( m_eShutdownState != essNONE ) return; LogMutex.Lock(); CMessageDMFileObject * fo = new CMessageDMFileObject(); fo->m_sNick = TransferObject->sNick; fo->m_sHubName = TransferObject->sHubName; fo->m_sHubHost = TransferObject->sHubHost; fo->m_eTransferWaitState = TransferObject->eState; fo->m_tTimeout = TransferObject->tTimeout; fo->m_bRemoveFile = bRemoveFile; fo->m_nConnections = TransferObject->iConnections; if ( TransferFileObject ) { fo->m_sRemoteFile = TransferFileObject->m_sRemoteFile; fo->m_sLocalFile = TransferFileObject->m_sLocalFile; fo->m_nSize = TransferFileObject->m_nSize; fo->m_eTransferFileState = TransferFileObject->m_eState; fo->m_bMulti = TransferFileObject->m_bMulti; fo->m_nPriority = TransferFileObject->m_nPriority; fo->m_sTTH = TransferFileObject->m_sHash; if ( TransferFileObject->m_pDirList ) { fo->m_pDirList = new std::list(); *(fo->m_pDirList) = *(TransferFileObject->m_pDirList); } } if ( DC_DownloadManagerCallBack(fo) == -1 ) delete fo; LogMutex.UnLock(); } /** */ CMessageDMTransferObject * CDownloadManager::CreateDMTransferObject( CTransfer * Transfer ) { DCFileChunkObject * FileChunkObject; CMessageDMTransferObject * to = new CMessageDMTransferObject(); to->m_nTransferID = Transfer->GetTransferID(); to->m_sSrcNick = Transfer->GetNick(); to->m_sDstNick = Transfer->GetDstNick(); to->sHost = Transfer->GetHost(); to->m_sHubHost = Transfer->GetHubHost(); to->sHubName = Transfer->GetHubName(); to->eState = Transfer->GetMode(); to->m_sDstFile = Transfer->GetDstFilename(); to->m_sSrcFile = Transfer->GetSrcFilename(); to->lSize = Transfer->GetLength(); to->lStartPosition = Transfer->GetStartPosition(); to->lEndPosition = Transfer->GetEndPosition(); to->lRate = Transfer->GetTransferrate(); to->lTransfered = Transfer->GetTransfered(); to->m_bEncrypted = Transfer->GetEncrypted(); to->m_sTTH = Transfer->GetTTH(); // get size done from the chunk list if ( Transfer->GetSrcDirection() == edUPLOAD ) { to->lSizeDone = to->lStartPosition + to->lTransfered; } else { m_pDownloadQueue->pChunksMutex->Lock(); if ( Transfer->GetMedium() == eltBUFFER ) { to->lSizeDone = to->lStartPosition + to->lTransfered; } else if ( (FileChunkObject = m_pDownloadQueue->GetFileChunkObject(Transfer->GetSrcFilename())) != 0 ) { to->lSizeDone = FileChunkObject->m_nSizeDone+to->lTransfered; } else { to->lSizeDone = to->lSize; } m_pDownloadQueue->pChunksMutex->UnLock(); } return to; } /** */ CList * CDownloadManager::DLM_TransferGetList() { CTransferObject * TransferObject = 0; CList * list; CMessageDMTransferObject * to; m_pTransfersMutex->Lock(); list = new CList(); while( m_pTransferList->Next( &TransferObject ) ) { to = CreateDMTransferObject(TransferObject->m_pTransfer); list->Add(to); } m_pTransfersMutex->UnLock(); return list; } /** */ void CDownloadManager::SendTransferInfo( CTransfer * Transfer, bool remove ) { LogMutex.Lock(); CMessageDMTransferObject * to = CreateDMTransferObject(Transfer); to->bRemoveTransfer = remove; if ( DC_DownloadManagerCallBack(to) == -1 ) delete to; LogMutex.UnLock(); } /** */ void CDownloadManager::SendSlotInfo( CExtraUserSlot * Object ) { LogMutex.Lock(); CMessageDMSlotObject * so = new CMessageDMSlotObject(); so->sNick = Object->sNick; so->sHubName = Object->sHubName; so->iSlots = Object->iSlots; so->bPermanent = Object->bPermanent; if ( DC_DownloadManagerCallBack(so) == -1 ) delete so; LogMutex.UnLock(); } /** */ void CDownloadManager::SendLogInfo( CString message, CTransfer * Transfer ) { LogMutex.Lock(); CMessageLog * log = new CMessageLog(); if ( Transfer != 0 ) { log->sMessage = "["; if ( Transfer->GetDstNick().IsEmpty() ) log->sMessage += "???"; else log->sMessage += Transfer->GetDstNick(); log->sMessage += "] "; } log->sMessage += message; // write message in log tab in transfer window to logfile if ( CConfig::Instance()->GetLogFile() && CConfig::Instance()->GetLogDetails() ) { CLogFile::Write(CConfig::Instance()->GetLogFileName(),eltINFO,log->sMessage); } if ( DC_DownloadManagerCallBack(log) == -1 ) delete log; LogMutex.UnLock(); } /** */ void CDownloadManager::SendDownloadManagerInfo( CDownloadManagerInfo * dminfo ) { if ( !dminfo ) { return; } LogMutex.Lock(); CDownloadManagerInfo * dmi = new CDownloadManagerInfo; *dmi = *dminfo; if ( DC_DownloadManagerCallBack(dmi) == -1 ) delete dmi; LogMutex.UnLock(); } /** */ void CDownloadManager::SendTrafficInfo() { LogMutex.Lock(); DCMessageTraffic * to = new DCMessageTraffic(); to->m_nRx = CSocket::m_Traffic.GetTraffic(ettRX); to->m_nTx = CSocket::m_Traffic.GetTraffic(ettTX); to->m_nDataRx = CSocket::m_Traffic.GetTraffic(ettDATARX); to->m_nDataTx = CSocket::m_Traffic.GetTraffic(ettDATATX); to->m_nControlRx = CSocket::m_Traffic.GetTraffic(ettCONTROLRX); to->m_nControlTx = CSocket::m_Traffic.GetTraffic(ettCONTROLTX); if ( DC_DownloadManagerCallBack(to) == -1 ) delete to; LogMutex.UnLock(); } /** */ void CDownloadManager::SendFileManagerInfo( CFileManagerInfo * info ) { if ( m_eShutdownState != essNONE ) { return; } if ( !info ) { return; } LogMutex.Lock(); CFileManagerInfo * fmi = new CFileManagerInfo(); *fmi = *info; if ( DC_DownloadManagerCallBack(fmi) == -1 ) delete fmi; LogMutex.UnLock(); } /** */ bool CDownloadManager::CheckUserSlot( CString nick, CString hubname ) { bool res; CExtraUserSlot * ExtraUserSlot; m_pExtraSlotsMutex->Lock(); res = false; ExtraUserSlot = 0; while( (ExtraUserSlot=m_pExtraUserSlotList->Next(ExtraUserSlot)) != 0 ) { if ( (ExtraUserSlot->sNick == nick) && (ExtraUserSlot->sHubName == hubname) ) { if ( ExtraUserSlot->bPermanent ) { res = true; } else if ( ExtraUserSlot->iSlots > 0 ) { ExtraUserSlot->iSlots--; SendSlotInfo(ExtraUserSlot); if ( ExtraUserSlot->iSlots == 0 ) { m_pExtraUserSlotList->Del(ExtraUserSlot); } res = true; } else { printf("Warning extra user slot for '%s' on '%s' with slots %d deleted!\n",ExtraUserSlot->sNick.Data(),ExtraUserSlot->sHubName.Data(),ExtraUserSlot->iSlots); m_pExtraUserSlotList->Del(ExtraUserSlot); } break; } } m_pExtraSlotsMutex->UnLock(); return res; } /** */ void CDownloadManager::FileListDone( CTransfer * Transfer, DCTransferFileObject * TransferFileObject ) { DCTransferQueueObject * TransferObject; CString fn; // CTransfer has been modified to: // set the correct src name DC_USER_FILELIST_XMLBZ or DC_USER_FILELIST_BZ or DC_USER_FILELIST_HE3 // and not bz2/he3 decompress the buffer // and provide a function to save it's buffer to a file if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost() )) != 0 ) { fn = Transfer->GetDstNick(); fn += '@'; fn += Transfer->GetHubHost(); // convert invalid characters - from dcchat.cpp line 1156 fn.Swap( '/', '_' ); fn.Swap( '\\', '_' ); fn.Swap( ':', '_' ); if ( Transfer->GetSrcFilename() == DC_USER_FILELIST_XMLBZ ) { fn += ".xml.bz2"; } else if ( Transfer->GetSrcFilename() == DC_USER_FILELIST_BZ ) { fn += ".bz2"; } else if ( Transfer->GetSrcFilename() == DC_USER_FILELIST_HE3 ) { fn += ".DcLst"; } else if ( Transfer->GetSrcFilename() == DC_USER_FILELIST_XML ) { fn += ".xml"; } else { printf("CDownloadManager::FileListDone: unknown filelist type '%s'\n", Transfer->GetSrcFilename().Data()); fn += ".filelist"; } fn = CConfig::Instance()->GetFileListPath() + fn; if ( Transfer->SaveBufferToFile(fn) ) { CMessageDMFileListObject * flo = new CMessageDMFileListObject(); flo->sNick = TransferObject->sNick; flo->sHubName = TransferObject->sHubName; flo->sHubHost = TransferObject->sHubHost; flo->sLocalFile = fn; flo->sJumpTo = TransferFileObject->m_sJumpTo; if ( TransferFileObject->m_pDirList ) { flo->m_pDirList = new std::list(); *(flo->m_pDirList) = *(TransferFileObject->m_pDirList); } LogMutex.Lock(); if ( DC_DownloadManagerCallBack(flo) == -1 ) delete flo; LogMutex.UnLock(); } else { TransferFileObject->m_eState = etfsERROR; SendFileInfo( TransferObject, TransferFileObject ); SendLogInfo( "Error saving filelist " + fn, Transfer ); } } } /** */ bool CDownloadManager::CheckHash( CTransfer * Transfer ) { bool res = false; CByteArray ba; DCTransferFileObject * TransferFileObject; DCFileChunkObject * FileChunkObject; md5_ctx * context = 0; unsigned char resbuf[16]; char c[3]; int i = 0; CString result; if ( (TransferFileObject = m_pDownloadQueue->GetUserFileObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost(), Transfer->GetDstFilename() )) != 0 ) { if ( Transfer->GetBuffer(&ba) != 0 ) { if ( (TransferFileObject->m_stHash.IsEmpty()) && TransferFileObject->m_bMulti ) { // calc hash context = new md5_ctx(); md5_init_ctx( context ); md5_process_bytes( ba.Data(), ba.Size(), context ); md5_finish_ctx( context, &resbuf ); delete context; // convert digest to hexadecimal for ( i = 0; i < 16; i++ ) { #ifdef WIN32 _snprintf( c, 3, "%02x", resbuf[i] ); #else snprintf( c, 3, "%02x", resbuf[i] ); #endif result += c; } TransferFileObject->m_stHash = result; DPRINTF("hash is :'%s'\n",TransferFileObject->m_stHash.Data()); m_pDownloadQueue->pChunksMutex->Lock(); if ( m_pDownloadQueue->pChunkList->Get( Transfer->GetSrcFilename(), &FileChunkObject ) == 0 ) { if ( FileChunkObject->m_stHash.IsEmpty() ) { DPRINTF("Set hash ...\n"); FileChunkObject->m_stHash = TransferFileObject->m_stHash; res = true; } else if ( FileChunkObject->m_stHash == TransferFileObject->m_stHash ) { DPRINTF("Hash ok...\n"); res = true; } else { DPRINTF("Wrong hash !!!\n"); TransferFileObject->m_eState = etfsERROR; } } else { DPRINTF("warning file chunk object not found\n"); } m_pDownloadQueue->pChunksMutex->UnLock(); } else { DPRINTF("warning hash not empty or no multi download\n"); } } else { DPRINTF("warning file object not found\n"); } } else { DPRINTF("warning get buffer error\n"); } return res; } /** bool CDownloadManager::SetMultiDownload( CString nick, CString hubname, CString remotefile ) { Lock(); bool res = false; DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject; DCFileChunkObject * FileChunkObject; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname )) != 0 ) { UserFileInfo->eWaitState = TransferObject->eState; UserFileInfo->sUserFileList = TransferObject->sUserFileList; if ( TransferObject->pTransferFileList.Get( remotefile, &TransferFileObject ) == 0 ) { if ( (TransferFileObject->eTransferFileState != etfsTRANSFER) && (TransferFileObject->bMulti == false) ) { m_pDownloadQueue->pChunksMutex->Lock(); if ( (FileChunkObject = m_pDownloadQueue->GetFileChunkObject(TransferFileObject->sLocalFile)) != 0 ) { DCChunkObject * ChunkObject = 0; while( (ChunkObject=FileChunkObject->pChunks.Next(ChunkObject)) != 0 ) { if ( ChunkObject->lStart <= TEST_CHUNK_SIZE ) { // error break; } } if ( ChunkObject == 0 ) } m_pDownloadQueue->pChunksMutex->UnLock(); } UserFileInfo->eFileState = TransferFileObject->eState; UserFileInfo->sLocalFile = TransferFileObject->sLocalFile; UserFileInfo->bMulti = TransferFileObject->bMulti; res = true; } } UnLock(); return res; } */ /** */ ulonglong CDownloadManager::GetNewID() { return ((++m_nID)==0) ? (++m_nID) : (m_nID); } /** */ bool CDownloadManager::RemoveQueueFile( CString localfile ) { bool res = false; CStringList * StringList = 0; DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject; // remove file from the chunk list m_pDownloadQueue->pChunksMutex->Lock(); m_pDownloadQueue->pChunkList->Del( localfile ); m_pDownloadQueue->pChunksMutex->UnLock(); // remove file from the queue while( m_pDownloadQueue->pQueue->Next( &StringList ) ) { TransferObject = 0; while( StringList->Next( &TransferObject) ) { TransferFileObject = 0; while( TransferObject->pTransferFileList.Next( &TransferFileObject) ) { if ( TransferFileObject->m_sLocalFile == localfile ) { // on file transfer don't remove the file if ( TransferFileObject->m_eState != etfsTRANSFER ) { SendFileInfo( TransferObject, TransferFileObject, true ); TransferObject->pTransferFileList.Del(TransferFileObject->m_sRemoteFile); TransferFileObject = 0; res = true; } else { DPRINTF("WARNING: RemoveQueueFile: file transfer is running\n"); } } } } } return res; } /** */ bool CDownloadManager::RemoveQueueFile( CString nick, CString hubname, CString remotefile ) { bool res = false; DCTransferFileObject * TransferFileObject = 0; DCTransferQueueObject * TransferObject = 0; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( nick, hubname, CString() )) != 0 ) { if ( remotefile.NotEmpty() ) { if ( (TransferFileObject = m_pDownloadQueue->GetUserFileObject( nick, hubname, CString(), remotefile )) != 0 ) { if ( TransferFileObject->m_eState != etfsTRANSFER ) { res = true; } else { DPRINTF("WARNING: RemoveQueueFile: file transfer is running\n"); } } } else { if ( TransferObject->eState != etwsRUN ) { res = true; } else { DPRINTF("WARNING: RemoveQueueFile: transfer is running\n"); } } if ( res ) { SendFileInfo( TransferObject, TransferFileObject, true ); res = m_pDownloadQueue->DelUserFileObject( nick, hubname, CString(), remotefile ); } } return res; } /** */ bool CDownloadManager::UpdateWaitTransfer( CTransfer * Transfer, bool rem ) { bool res = false; DCTransferWait * TransferWait = 0; CString thost; // search in the wait list ... m_pWaitListMutex->Lock(); /* * For an incoming connection the port it came from is random, so will * be different for each attempt, so do not put it in into the list. */ if ( Transfer->IsListener() ) { thost = Transfer->GetIP(); } else { thost = Transfer->GetHost(); } DPRINTF("UWT: Search user %s %s in the waitlist\n",Transfer->GetDstNick().Data(),thost.Data()); while ( (TransferWait = m_pTransferWaitList->Next(TransferWait)) != 0 ) { // here we have both nick and host from the CTransfer // search for the nick+host or one of them and fill in the other if ( TransferWait->Match( Transfer->GetDstNick(), thost ) ) { Transfer->SetHubName(TransferWait->sHubName); Transfer->SetHubHost(TransferWait->sHubHost); DPRINTF("UWT: User found\n"); res = true; break; } } if ( !TransferWait ) { DPRINTF("UWT: User not found\n"); } else { if ( rem ) { TransferWait->m_nCount--; DPRINTF("UWT: Remove user %lld\n",TransferWait->m_nCount); if ( TransferWait->m_nCount == 0 ) m_pTransferWaitList->Del(TransferWait); } } m_pWaitListMutex->UnLock(); return res; } /** */ eDirection CDownloadManager::CheckWaitTransfer( CTransfer * Transfer ) { m_pDownloadQueue->pQueueMutex->Lock(); eDirection res = edNONE; DCTransferQueueObject * TransferObject; DCTransferBanObject * TransferBanObject = 0; CString host; bool waittransfer; int port; bool ban = false; long int i; DPRINTF("CWT: '%s' on '%s'\n", Transfer->GetDstNick().Data(), Transfer->GetHubName().Data() ); // allow only 1 request in 30 seconds m_pBanListMutex->Lock(); if ( Transfer->GetPeerName( &host, &port ) == false ) { // error DPRINTF("CWT: Error: Can't get peername\n"); } else if ( m_pTransferBanList->Get( Transfer->GetDstNick(), &TransferBanObject ) != 0 ) { DPRINTF("CWT: Create new TransferBanObject '%s'\n",host.Data()); TransferBanObject = new DCTransferBanObject(); TransferBanObject->m_sIP = host; TransferBanObject->m_tTime = time(0); m_pTransferBanList->Add( Transfer->GetDstNick(), TransferBanObject ); DPRINTF("CWT: Banlist count %ld objects\n",m_pTransferBanList->Count()); } if ( TransferBanObject && (TransferBanObject->m_nRequestCount > 0) ) { i = lrint(ceil((time(0)-TransferBanObject->m_tTime)/60.0)*4); if ( i < TransferBanObject->m_nRequestCount ) { ban = true; } } waittransfer = UpdateWaitTransfer( Transfer ); DPRINTF("CWT: CheckWaitTransfer II: %s on %s\n", Transfer->GetDstNick().Data(), Transfer->GetHubName().Data() ); // now we check if we need to set the correct nick for the hub if ( Transfer->GetNick().IsEmpty() ) { Transfer->SetNick( CConfig::Instance()->GetNick( Transfer->GetHubName(), Transfer->GetHubHost() ) ); DPRINTF("CWT: Set transfer NICK: '%s'\n",Transfer->GetNick().Data() ); // send the correct nick Transfer->SendMyNick( Transfer->GetNick(), Transfer->GetHubHost() ); } if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost() )) != 0 ) { DPRINTF("CWT: Waiting: %s on %s %s\n", TransferObject->sNick.Data(), TransferObject->sHubName.Data(), TransferObject->sHubHost.Data() ); if ( TransferObject->eState == etwsIDLE ) { SendLogInfo( "WARNING: Increase the response timeout." ); } if ( (TransferObject->eState == etwsWAIT) || (TransferObject->eState == etwsIDLE) ) { DPRINTF("CWT: wait found ...\n"); TransferObject->eState = etwsRUN; TransferObject->iConnections++; // waiting transfer found ... res = edDOWNLOAD; SendFileInfo( TransferObject ); } else { DPRINTF("CWT: ERROR: wait in wrong state (please report!) (%d/%d)\n",TransferObject->eState,TransferObject->iConnections); } } if ( res == edNONE ) { if ( waittransfer ) { if ( TransferBanObject ) { TransferBanObject->m_nRequestCount++; DPRINTF("CWT: Requestcount is now %d\n",TransferBanObject->m_nRequestCount); } if ( ban ) { Transfer->Disconnect(true); SendLogInfo( "WARNING: Disconnect aggressive client " + host ); DPRINTF("CWT: Host banned\n"); } else { res = edUPLOAD; } } else { DPRINTF("CWT: Warning: no wait transfer found for '%s'\n",Transfer->GetDstNick().Data()); Transfer->Disconnect(true); } } m_pBanListMutex->UnLock(); m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::ChangeDirection( CTransfer * Transfer ) { bool res = false; DCTransferQueueObject * TransferObject; m_pDownloadQueue->pQueueMutex->Lock(); if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost() )) != 0 ) { DPRINTF("Waiting: %s on %s %s\n", TransferObject->sNick.Data(), TransferObject->sHubName.Data(), TransferObject->sHubHost.Data() ); // change to upload ... if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { if ( TransferObject->eState == etwsRUN ) { if ( TransferObject->iConnections > 0 ) TransferObject->iConnections--; else DPRINTF("WARNING: ChangeDirection: RUN:0\n"); if ( TransferObject->iConnections == 0 ) TransferObject->eState = etwsIDLE; SendFileInfo( TransferObject ); DPRINTF("change transfer -> upload ...\n"); res = true; } else { DPRINTF("can't change transfer upload ...\n"); } } } m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::SetNextFile( CTransfer * Transfer ) { bool res; m_pDownloadQueue->pQueueMutex->Lock(); res = SetFile(Transfer); m_pDownloadQueue->pQueueMutex->UnLock(); return res; } /** */ bool CDownloadManager::SetDirection( CTransfer * Transfer ) { CTransferObject * TransferObject; int i; bool res = false; // check if transfer mode correct if ( (Transfer->GetSrcDirection() == edNONE) || (Transfer->GetDstDirection() == edNONE) ) { // never use slots for wrong transfer modes return res; } // check max uploads for a user if ( Transfer->GetSrcDirection() == edUPLOAD ) { // check for max user upload slots TransferObject = 0; i = 0; // the list is allready locked by the thread while( m_pTransferList->Next( &TransferObject ) ) { if ( TransferObject->m_pTransfer->GetDstDirection() == edDOWNLOAD ) { if ( Transfer->GetDstNick() == TransferObject->m_pTransfer->GetDstNick() ) { i++; } } } // the current transfer is allready in the list if ( (CConfig::Instance()->GetUserUploadSlots() == 0) || (CConfig::Instance()->GetUserUploadSlots() >= i) ) { // check slot limit i = CConfig::Instance()->GetMaxUpload(); // unlimited slots == 0 or not all slots used if ( (i == 0) || (i > DownloadManagerInfo.slot_use_settings) ) { DownloadManagerInfo.slot_use_settings++; Transfer->SetTransferType(ettSETTINGS); res = true; } else if ( (CConfig::Instance()->GetExtraSlotsRate() > 0) && (DownloadManagerInfo.slot_use_rate_extra < CConfig::Instance()->GetMaxExtraSlots()) && (DownloadManagerInfo.Rate() < CConfig::Instance()->GetExtraSlotsRate()) ) { const time_t now = time(0); if ( now > (m_tLastRateExtra + 60) ) { DownloadManagerInfo.slot_use_rate_extra++; Transfer->SetTransferType(ettRATE_EXTRA); m_tLastRateExtra = now; res = true; } } /* check for extra user slots, they are used up even if they already got a free slot above */ if ( CheckUserSlot( Transfer->GetDstNick(), Transfer->GetHubName() ) ) { if ( res == false ) { DownloadManagerInfo.slot_use_user++; Transfer->SetTransferType(ettUSER); res = true; } // else they got a slot already but still used up a granted slot } if ( res == false ) // no normal slot granted, allocate special than operator slot { if ( Transfer->GetDstNick().IsEmpty() ) { DPRINTF("WARNING: get a free slot -> remote nick is empty\n"); } else { // no free normal slot - use special slot (lists, small files, leaves) // set special slot if available if ( DownloadManagerInfo.slot_use_special < 4 ) { DownloadManagerInfo.slot_use_special++; Transfer->SetTransferType(ettSPECIAL); res = true; } // no more special slots - use operator slot (list only) if ( !res && CConnectionManager::Instance()->IsAdmin(Transfer->GetHubName(),Transfer->GetHubHost(),Transfer->GetDstNick()) ) { // set operator slot if available if ( DownloadManagerInfo.slot_use_operator < 4 ) { DownloadManagerInfo.slot_use_operator++; Transfer->SetTransferType(ettOPERATOR); res = true; } } } } } } // allow all downloads else { res = true; } return res; } /** */ void CDownloadManager::OptimizeChunks( DCFileChunkObject * FileChunkObject ) { DCChunkObject *co, *co1; // get first not locked chunk co = 0; while ( (co=FileChunkObject->m_Chunks.Next(co)) != 0 ) { if ( co->m_eChunkState == ecsFREE ) { co1 = co; while ( (co1=FileChunkObject->m_Chunks.Next(co1)) != 0 ) { if ( co1 == co ) { continue; } if ( co1->m_eChunkState == ecsFREE ) { if ( co->m_nEnd == co1->m_nStart ) { co->m_nEnd = co1->m_nEnd; FileChunkObject->m_Chunks.Del(co1); co1 = co; } else if ( co->m_nStart == co1->m_nEnd ) { co->m_nStart = co1->m_nStart; FileChunkObject->m_Chunks.Del(co1); co1 = co; } } } } } } /** */ bool CDownloadManager::GetNextChunk( CString file, ulonglong * lstart, ulonglong * lend ) { bool res = false; DCFileChunkObject * FileChunkObject; DCChunkObject * ChunkObject, *co, *co1, *bigco, *firstco; ulonglong size; bool split, standalone; ulonglong minsegsize; if ( CConfig::Instance() ) { minsegsize = CConfig::Instance()->GetMinSegSize(); } else { minsegsize = 1048576; } DPRINTF("get the next chunk for '%s'\n",file.Data()); if ( (FileChunkObject = m_pDownloadQueue->GetFileChunkObject(file)) != 0 ) { OptimizeChunks(FileChunkObject); co = 0; ChunkObject = 0; bigco = 0; firstco = 0; size = 0; // get a free chunk while ( (ChunkObject=FileChunkObject->m_Chunks.Next(ChunkObject)) != 0 ) { if ( ChunkObject->m_eChunkState == ecsFREE ) { // find the biggest chunk if ( (ChunkObject->m_nEnd-ChunkObject->m_nStart) > size ) { bigco = ChunkObject; size = ChunkObject->m_nEnd-ChunkObject->m_nStart; } // find the first chunk with nothing before it standalone = true; while ( (co=FileChunkObject->m_Chunks.Next(co)) != 0 ) { if ( co->m_nEnd == ChunkObject->m_nStart ) { standalone = false; } } if (standalone) { if ( firstco == 0 || firstco->m_nStart > ChunkObject->m_nStart ) { firstco = ChunkObject; } } } } // prefer the first free chunk to the biggest if ( firstco != 0 ) { co = firstco; } else { co = bigco; } // found a free chunk if ( co != 0 ) { split = false; // split if the half chunk size > max. chunk size if ( ((co->m_nEnd-co->m_nStart)/2) > minsegsize ) { ChunkObject = 0; // check if a running chunk for this chunk while ( (ChunkObject=FileChunkObject->m_Chunks.Next(ChunkObject)) != 0 ) { if ( ChunkObject->m_eChunkState == ecsLOCKED ) { if ( ChunkObject->m_nEnd == co->m_nStart ) { split = true; } } } } ChunkObject = co; if ( ( (ChunkObject->m_nEnd - ChunkObject->m_nStart) > minsegsize ) && FileChunkObject->m_bMulti ) { // create a new chunk co = new DCChunkObject(); // split chunk if ( (ChunkObject->m_nStart == 0) || (split == false) ) { co->m_nStart = ChunkObject->m_nStart; co->m_nEnd = ChunkObject->m_nStart+minsegsize; ChunkObject->m_nStart += minsegsize; } else { DPRINTF("CHUNK SET 1: %llu %llu\n",ChunkObject->m_nStart,ChunkObject->m_nEnd); co->m_nStart = ChunkObject->m_nStart+((ChunkObject->m_nEnd - ChunkObject->m_nStart)/2); if ( (ChunkObject->m_nEnd-co->m_nStart) > minsegsize ) { co->m_nEnd = co->m_nStart+minsegsize; co1 = new DCChunkObject(); co1->m_nStart = co->m_nEnd; co1->m_nEnd = ChunkObject->m_nEnd; FileChunkObject->m_Chunks.Add(co1); DPRINTF("CHUNK SET 2: %llu %llu\n",co1->m_nStart,co1->m_nEnd); } else { co->m_nEnd = ChunkObject->m_nEnd; } ChunkObject->m_nEnd = co->m_nStart; DPRINTF("CHUNK SET 3: %llu %llu\n",ChunkObject->m_nStart,ChunkObject->m_nEnd); DPRINTF("CHUNK SET 4: %llu %llu\n",co->m_nStart,co->m_nEnd); } co->m_eChunkState = ecsLOCKED; FileChunkObject->m_Chunks.Add(co); *lstart = co->m_nStart; *lend = co->m_nEnd; DPRINTF("NEW CHUNK SPLIT/LOCKED: %llu %llu\n",*lstart,*lend); res = true; } else { ChunkObject->m_eChunkState = ecsLOCKED; *lstart = ChunkObject->m_nStart; *lend = ChunkObject->m_nEnd; DPRINTF("NEW CHUNK LOCKED: %llu %llu\n",*lstart,*lend); res = true; } } } else { DPRINTF("warning file not found in the chunk list\n"); } return res; } /** 0: not found; 1: found and update; 2: no more chunks (file download ok) */ int CDownloadManager::UpdateChunk( CString file, ulonglong lstart, ulonglong lend, ulonglong lcurrent ) { int res = 0; DCFileChunkObject * FileChunkObject; DCChunkObject * ChunkObject, *co; DPRINTF("update chunk for '%s'\n",file.Data()); m_pDownloadQueue->pChunksMutex->Lock(); if ( (FileChunkObject = m_pDownloadQueue->GetFileChunkObject(file)) != 0 ) { ChunkObject = 0; // search the chunk while ( (ChunkObject=FileChunkObject->m_Chunks.Next(ChunkObject)) != 0 ) { if ( (ChunkObject->m_nStart == lstart) && (ChunkObject->m_nEnd == lend) ) { // chunk found res = 1; if ( ChunkObject->m_eChunkState == ecsFREE ) { DPRINTF("warning wrong chunk state\n"); } ChunkObject->m_eChunkState = ecsFREE; if ( lstart != lcurrent ) { // update size done FileChunkObject->m_nSizeDone += (lcurrent-lstart); DPRINTF("FILESTATE: %llu %llu\n",FileChunkObject->m_nSizeDone,FileChunkObject->m_nSize); if ( lcurrent == lend ) { FileChunkObject->m_Chunks.Del(ChunkObject); ChunkObject = 0; } else { ChunkObject->m_nStart = lcurrent; } if ( FileChunkObject->m_nSizeDone == FileChunkObject->m_nSize ) { // remove the complete chunk from the list m_pDownloadQueue->pChunkList->Del(file); res = 2; break; } } if ( ChunkObject != 0 ) { co = 0; while ( (co=FileChunkObject->m_Chunks.Next(co)) != 0 ) { if ( co == ChunkObject ) continue; if ( ChunkObject->m_nEnd == co->m_nStart ) { if ( co->m_eChunkState == ecsFREE ) { co->m_nStart = ChunkObject->m_nStart; FileChunkObject->m_Chunks.Del(ChunkObject); ChunkObject = co; DPRINTF("CHUNK FIX1: %llu %llu\n",ChunkObject->m_nStart,ChunkObject->m_nEnd); } break; } } co = 0; while ( (co=FileChunkObject->m_Chunks.Next(co)) != 0 ) { if ( co == ChunkObject ) continue; if ( ChunkObject->m_nStart == co->m_nEnd ) { if ( co->m_eChunkState == ecsFREE ) { co->m_nEnd = ChunkObject->m_nEnd; FileChunkObject->m_Chunks.Del(ChunkObject); ChunkObject = 0; DPRINTF("CHUNK FIX2: %llu %llu\n",co->m_nStart,co->m_nEnd); } break; } } } break; } } } else { DPRINTF("warning file not found in the chunk list\n"); } m_pDownloadQueue->pChunksMutex->UnLock(); return res; } /** */ bool CDownloadManager::GetNewChunkEnd( CString file, ulonglong lstart, ulonglong lend, ulonglong lcurrent, ulonglong * lnstart, ulonglong *lnend ) { m_pDownloadQueue->pChunksMutex->Lock(); bool res = false; DCFileChunkObject * FileChunkObject; DCChunkObject * ChunkObject, *co1=0,*co2=0; ulonglong chunk_size; ulonglong minsegsize; if ( CConfig::Instance() ) { minsegsize = CConfig::Instance()->GetMinSegSize(); } else { minsegsize = 1048576; } if ( (FileChunkObject = m_pDownloadQueue->GetFileChunkObject(file)) != 0 ) { ChunkObject = 0; while ( (ChunkObject=FileChunkObject->m_Chunks.Next(ChunkObject)) != 0 ) { if ( (ChunkObject->m_nStart == lstart) && (ChunkObject->m_nEnd == lend) ) { // start chunk found co1 = ChunkObject; if ( co2 ) { // next chunk is set -> stop search break; } } else if ( ChunkObject->m_nStart == lend ) { // next chunk found if ( ChunkObject->m_eChunkState == ecsLOCKED ) { // the chunk after the original chunk is locked -> stop search break; } else { // set next chunk co2 = ChunkObject; if ( co1 ) { // start chunk is set -> stop search break; } } } } // found start and next chunk if ( (co1 != 0) && (co2 != 0) ) { DPRINTF("set new chunk end for '%s'\n",file.Data()); // calc chunk size if ( (lend-lcurrent) > minsegsize ) chunk_size = minsegsize; else chunk_size = minsegsize-(lend-lcurrent); // if chunk > max chunk split chunk to chunk size if ( (co2->m_nEnd-co2->m_nStart) > chunk_size ) { // set new chunk end co1->m_nEnd += chunk_size; // set correct new chunk start co2->m_nStart += chunk_size; } else { // set new chunk end co1->m_nEnd = co2->m_nEnd; // remote the chunk FileChunkObject->m_Chunks.Del(co2); } if ( (lcurrent-lstart) > 0 ) { FileChunkObject->m_nSizeDone += (lcurrent-lstart); co1->m_nStart = lcurrent; } *lnstart = co1->m_nStart; *lnend = co1->m_nEnd; DPRINTF("new chunk end set %llu -> %llu [%llu/%llu]\n",lend,*lnend,(*lnend)-(*lnstart),chunk_size); res = true; } } else { DPRINTF("warning file not found in the chunk list\n"); } m_pDownloadQueue->pChunksMutex->UnLock(); return res; } /** */ bool CDownloadManager::SetFile( CTransfer * Transfer ) { bool res; DCTransferQueueObject * TransferObject; ulonglong lstart,lend; int priority = 0; res = false; if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost() )) != 0 ) { if ( TransferObject->pTransferFileList.Count() > 0 ) { DCTransferFileObject * TransferFileObject = 0; while( (priority <= MAX_FILE_PRIORITY) && (TransferFileObject == 0) ) { while( TransferObject->pTransferFileList.Next(&TransferFileObject) ) { // check the priority if ( priority != TransferFileObject->m_nPriority ) continue; if ( TransferFileObject->m_eState == etfsNONE ) { DPRINTF("set file: '%s'\n",TransferFileObject->m_sRemoteFile.Data()); CString sPath,sLocalPath,sFile; CDir dir; if ( TransferFileObject->m_eMedium == eltFILE ) { sFile = TransferFileObject->m_sLocalFile; DPRINTF("DEBUG: file: '%s'\n",sFile.Data()); // extract file int pos = sFile.FindRev(DIRSEPARATOR); if( pos != -1 ) { sPath = sFile.Left(pos); } DPRINTF("DEBUG: path: '%s'\n", sPath.Data()); // create the path if ( dir.CreatePath(sPath) == false ) { TransferFileObject->m_eState = etfsERROR; SendFileInfo( TransferObject, TransferFileObject ); SendLogInfo( "Create path failed: " + sPath, Transfer ); DPRINTF("DEBUG: create path failed: '%s'\n", sPath.Data()); } else { DPRINTF("DOWNLOAD: '%s' %llu '%s'\n", TransferFileObject->m_sRemoteFile.Data(), TransferFileObject->m_nSize, sFile.Data()); res = true; } } else { res = true; } if ( res ) { // first we create the hash over the first 1MB of a multi download file in a buffer if ( TransferFileObject->m_bMulti && (TransferFileObject->m_stHash.IsEmpty())) { DPRINTF("create the hash for the file\n"); Transfer->SetMedium(eltBUFFER); lstart = 0; lend = TEST_CHUNK_SIZE; } else // get the next chunk of the file { if ( TransferFileObject->m_eMedium == eltCLIENTVERSION ) { DPRINTF("DEBUG: resolve client version ...\n"); lstart = 0; lend = 0; } else if ( TransferFileObject->m_sRemoteFile == DC_USER_FILELIST ) { lstart = 0; lend = 0; } else if ( GetNextChunk( TransferFileObject->m_sLocalFile, &lstart, &lend ) == false ) { // no more chunks DPRINTF("no more chunks ...\n"); continue; } Transfer->SetMedium(TransferFileObject->m_eMedium); } Transfer->SetDone(etsNONE); /* This no longer happens because prefixes are removed at the lowest possible level */ CString TTH = TransferFileObject->m_sHash; /* should be fixed since 0.3.18 and this check is unnecessary */ if ((TTH.Left(4)).ToUpper() == "TTH:") { DPRINTF("CDownloadManager::SetFile: Removed TTH: prefix from TTH\n"); TTH = TTH.Mid(4, TTH.Length() - 4); } if ( Transfer->StartDownload(TransferFileObject->m_sRemoteFile,lstart,lend,TransferFileObject->m_nSize,lend-lstart,sFile,TTH) == -1 ) { Transfer->Disconnect(); } else { // mark file as transfered TransferFileObject->m_eState = etfsTRANSFER; } } else { continue; } SendFileInfo( TransferObject, TransferFileObject ); break; } else { // DPRINTF("state file: '%s' %d\n",TransferFileItem->sRemoteName.Data(),TransferFileItem->eState); } } priority++; } } } if ( res == false ) { // set disconnect timeout ... save remote slot ;-) if ( Transfer->GetDone() != etsIDLE ) { Transfer->SetStartTime(time(0)); Transfer->SetDone(etsIDLE); } } return res; } /** */ void CDownloadManager::UpdateFileState( CTransfer * Transfer, eTransferFileState eState ) { DCTransferQueueObject * TransferObject; DCTransferFileObject * TransferFileObject; m_pDownloadQueue->pQueueMutex->Lock(); DPRINTF("updatefile\n"); if ( (TransferObject = m_pDownloadQueue->GetUserTransferObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost() )) != 0 ) { TransferFileObject = m_pDownloadQueue->GetUserFileObject( Transfer->GetDstNick(), Transfer->GetHubName(), Transfer->GetHubHost(), Transfer->GetDstFilename() ); if ( TransferFileObject != 0 ) { if ( TransferFileObject->m_eState != etfsTRANSFER ) { DPRINTF("warning, wrong state in updatefile\n"); } // if this a check hash dl ? else if ( (Transfer->GetMedium() == eltBUFFER) && TransferFileObject->m_bMulti ) { DPRINTF("updatefile hash\n"); if ( eState == etfsNONE ) { if ( (Transfer->GetStartPosition()+Transfer->GetTransfered()) == Transfer->GetEndPosition() ) { if ( CheckHash(Transfer) ) { CString logmsg = "Hash ok '"; logmsg += TransferFileObject->m_sRemoteFile; logmsg += '\''; SendLogInfo( logmsg, Transfer ); TransferFileObject->m_eState = etfsNONE; // reconnect if remote dont support chunk dl if ( Transfer->SupportsChunks() == false ) { // wan't a reconnect TransferObject->bReconnect = true; } } else { CString logmsg = "Hash failed '"; logmsg += TransferFileObject->m_sRemoteFile; logmsg += '\''; SendLogInfo( logmsg, Transfer ); TransferFileObject->m_eState = etfsERROR; } } else { TransferFileObject->m_eState = eState; } } else { TransferFileObject->m_eState = eState; } SendFileInfo( TransferObject, TransferFileObject ); } else { DPRINTF("updatefile normal\n"); int state=0; TransferFileObject->m_eState = eState; if ( Transfer->GetMedium() == eltCLIENTVERSION ) { state = 2; } // check if mylist.dclist done else if ( TransferFileObject->m_sRemoteFile == DC_USER_FILELIST ) { if ( (Transfer->GetLength() != 0) && (Transfer->GetLength() == Transfer->GetTransfered()) ) { FileListDone( Transfer, TransferFileObject ); state = 2; } } else { state = UpdateChunk( TransferFileObject->m_sLocalFile, Transfer->GetStartPosition(), Transfer->GetEndPosition(), Transfer->GetStartPosition()+Transfer->GetTransfered() ); } TransferFileObject->m_nSize = Transfer->GetLength(); // download finished if ( state == 2 ) { if ( Transfer->GetMedium() != eltCLIENTVERSION ) { CString logmsg = "Transfer done '"; logmsg += TransferFileObject->m_sRemoteFile; logmsg += '\''; SendLogInfo( logmsg, Transfer ); } SendFileInfo( TransferObject, TransferFileObject, true ); SendTransferInfo( Transfer, false ); // finished downloads are now a log option if ( (TransferFileObject->m_eMedium == eltFILE) && CConfig::Instance()->GetLogFile() && CConfig::Instance()->GetLogFinishedDownloads() && (TransferFileObject->m_sRemoteFile != DC_USER_FILELIST) ) { CString logfilemsg = "Transfer done '"; logfilemsg += TransferFileObject->m_sLocalFile; logfilemsg += '\''; CLogFile::Write(CConfig::Instance()->GetLogFileName(),eltINFO,logfilemsg); } // move the file to the finished path if ( (TransferFileObject->m_eMedium == eltFILE) && // only files (CConfig::Instance()->GetDownloadFinishedFolder().NotEmpty()) && // only if dlfolder set (TransferFileObject->m_sRemoteFile != DC_USER_FILELIST) && // only if this not a filelist (CDir::ConvertSeparators(TransferFileObject->m_sLocalFile).Find(CDir::ConvertSeparators(CConfig::Instance()->GetDownloadFolder())) == 0) ) // only if the download in the download folder { CString s; // close file Transfer->CloseFile(); CDir dir(CConfig::Instance()->GetDownloadFinishedFolder()); if ( dir.CreatePath(TransferFileObject->m_sLocalPath) ) { dir.SetPath(CConfig::Instance()->GetDownloadFinishedFolder()+DIRSEPARATOR+TransferFileObject->m_sLocalPath); #ifdef WIN32 s = "move "; s += '"'; s += TransferFileObject->m_sLocalFile; s += "\" \""; s += dir.Path(); s += '"'; DPRINTF("move file '%s'\n",s.Data()); if ( system(s.Data()) != 0 ) { DPRINTF("move failed !\n"); } #else s = dir.Path(); s += DIRSEPARATOR; s += TransferFileObject->m_sLocalFileName; DPRINTF("move file: '%s' ---> '%s'\n",TransferFileObject->m_sLocalFile.Data(), s.Data()); if ( rename(TransferFileObject->m_sLocalFile.Data(), s.Data()) != 0 ) { if (errno == EXDEV) { // we have to copy it manually if ( CFile::Copy( TransferFileObject->m_sLocalFile, s ) == false ) { DPRINTF("move failed !\n"); } else { unlink(TransferFileObject->m_sLocalFile.Data()); } } } #endif } else { DPRINTF("move failed (create path)!\n"); } } if ( TransferFileObject->m_bMulti ) { // remove all files from the wait queue RemoveQueueFile(TransferFileObject->m_sLocalFile); } else { // remove a userlist only from this user/hub RemoveQueueFile( TransferObject->sNick, TransferObject->sHubName, TransferFileObject->m_sRemoteFile ); } } else { SendFileInfo( TransferObject, TransferFileObject ); } } } } else { DPRINTF("updatefile no GetUserTransferObject\n"); } m_pDownloadQueue->pQueueMutex->UnLock(); } /** */ void CDownloadManager::UpdateBanList( time_t ttimeout ) { DCTransferBanObject * TransferBanObject = 0, * tbo = 0; // remove old entrys m_pBanListMutex->Lock(); if ( m_pTransferBanList->Count() > 0 ) { CString s; while ( m_pTransferBanList->Next( s, &TransferBanObject ) == 1 ) { if ( (ttimeout-TransferBanObject->m_tTime) > 180 ) { m_pTransferBanList->Del(s); TransferBanObject = tbo; } else { tbo = TransferBanObject; } } } m_pBanListMutex->UnLock(); } /** */ void CDownloadManager::UpdateTransferList( time_t ttimeout ) { long count,rate,tmprate; CTransferObject * TransferObject; CTransferObject *obj,*oobj; CStringList * ratelist=0; CMessageFileTransferRate * filetransferrate; CList * transferlist=0; m_pTransfersMutex->Lock(); count = m_pTransferList->Count(); // check if shutdown ready if ( (m_eShutdownState == essSHUTDOWN) && (count == 0) ) { m_eShutdownState = essSHUTDOWNREADY; } if ( (ttimeout-m_tUpdateTransferTimeout) >= 1 ) { // update slots DownloadManagerInfo.slot_max = CConfig::Instance()->GetMaxUpload(); DownloadManagerInfo.rate_ul_settings = 0; DownloadManagerInfo.rate_ul_operator = 0; DownloadManagerInfo.rate_ul_user = 0; DownloadManagerInfo.rate_ul_special = 0; DownloadManagerInfo.rate_ul_rate_extra = 0; DownloadManagerInfo.rate_dl = 0; UpdateBanList( ttimeout ); } if ( count > 0 ) { obj = oobj = 0; ratelist = new CStringList(); transferlist = new CList(); while( m_pTransferList->Next( &obj ) ) { TransferObject = obj; // check if user offline and disconnect if ( (ttimeout-TransferObject->m_UserDisconnectTimeout) > 180 ) { eCloseType closetype = CConfig::Instance()->GetHubOfflineTransferClose(); TransferObject->m_UserDisconnectTimeout = ttimeout; if ( CConnectionManager::Instance()->IsHubOnline( TransferObject->m_pTransfer->GetHubName(), TransferObject->m_pTransfer->GetHubHost() ) == ehsONLINE ) { if ( CConnectionManager::Instance()->IsUserOnline( TransferObject->m_pTransfer->GetDstNick(), TransferObject->m_pTransfer->GetHubName(), TransferObject->m_pTransfer->GetHubHost(), 0 ) == false ) { if ( (TransferObject->m_pTransfer->GetSrcDirection()==edDOWNLOAD) && ( (closetype==ectBOTH) || (closetype==ectDLD) ) ) { TransferObject->m_pTransfer->Disconnect(true); CString logmsg = "Disconnect offline user: "; logmsg += TransferObject->m_pTransfer->GetDstNick(); logmsg += '@'; logmsg += TransferObject->m_pTransfer->GetHubName(); SendLogInfo(logmsg); } else if ( (TransferObject->m_pTransfer->GetSrcDirection()==edUPLOAD) && ( (closetype==ectBOTH) || (closetype==ectUPLD) ) ) { TransferObject->m_pTransfer->Disconnect(true); CString logmsg = "Disconnect offline user: "; logmsg += TransferObject->m_pTransfer->GetDstNick(); logmsg += '@'; logmsg += TransferObject->m_pTransfer->GetHubName(); SendLogInfo(logmsg); } } } else { //DPRINTF("Not disconnecting user because hub is offline\n"); } } // refresh transfer TransferObject->m_pTransfer->Thread(); if ( (ttimeout-m_tUpdateTransferTimeout) >= 1 ) { // done==2 set new file or disconnect if ( (TransferObject->m_pTransfer->GetDone() == etsIDLE) && (m_eShutdownState == essNONE) ) { bool newfile = false; // set new file on download mode if ( TransferObject->m_pTransfer->GetSrcDirection() == edDOWNLOAD ) { while(1) { // stop if we cant set a new file if ( SetFile(TransferObject->m_pTransfer) == false ) { break; } // check for clientcheck if ( TransferObject->m_pTransfer->GetMedium() == eltCLIENTVERSION ) { // remove clientcheck from queue (we have the client info at connect) UpdateFileState(TransferObject->m_pTransfer,etfsNONE); } else { // new file set successful newfile = true; break; } } } // no new file or another transfer mode if ( newfile == false ) { // check timeout for ul/dl if ( TransferObject->m_pTransfer->GetStartTime() != 0 ) { if ( (ttimeout-TransferObject->m_pTransfer->GetStartTime()) >= 60 ) { TransferObject->m_pTransfer->SetStartTime(0); TransferObject->m_pTransfer->Disconnect(true); } } } SendTransferInfo(TransferObject->m_pTransfer); oobj = obj; } else if ( TransferObject->m_pTransfer->GetDone() == etsREADY ) { if ( TransferObject->m_pTransfer->GetDstDirection() == edDOWNLOAD ) { // TODO: update slot infos etc. in downloadmanager and gui if ( TransferObject->m_pTransfer->GetTransferType() == ettSETTINGS ) { if ( DownloadManagerInfo.slot_use_settings > 0 ) DownloadManagerInfo.slot_use_settings--; } else if ( TransferObject->m_pTransfer->GetTransferType() == ettOPERATOR ) { if ( DownloadManagerInfo.slot_use_operator > 0 ) DownloadManagerInfo.slot_use_operator--; } else if ( TransferObject->m_pTransfer->GetTransferType() == ettUSER ) { if ( DownloadManagerInfo.slot_use_user > 0 ) DownloadManagerInfo.slot_use_user--; } else if ( TransferObject->m_pTransfer->GetTransferType() == ettSPECIAL ) { if ( DownloadManagerInfo.slot_use_special > 0 ) DownloadManagerInfo.slot_use_special--; } else if ( TransferObject->m_pTransfer->GetTransferType() == ettRATE_EXTRA ) { if ( DownloadManagerInfo.slot_use_rate_extra > 0 ) { DownloadManagerInfo.slot_use_rate_extra--; } } // update used slots CConnectionManager::Instance()->SendMyInfoToConnectedServers(); } SendTransferInfo( TransferObject->m_pTransfer, true ); // update internal transfer state for this user/hubname // set to idle (this work only with 1 transfer per user/hubname ...) DCTransferQueueObject * TransferQueueObject; if ( TransferObject->m_pTransfer->GetSrcDirection() == edDOWNLOAD ) { if ( (TransferQueueObject = m_pDownloadQueue->GetUserTransferObject( TransferObject->m_pTransfer->GetDstNick(), TransferObject->m_pTransfer->GetHubName(), TransferObject->m_pTransfer->GetHubHost() )) != 0 ) { if ( TransferQueueObject->eState == etwsRUN ) { if ( TransferQueueObject->iConnections > 0 ) TransferQueueObject->iConnections--; else DPRINTF("WARNING: UpdateTransferList: RUN:0\n"); if ( TransferQueueObject->iConnections == 0 ) TransferQueueObject->eState = etwsIDLE; } else { DPRINTF("WARNING: UpdateTransferList: wrong queue state\n"); } // wan't reconnect ? if ( TransferQueueObject->bReconnect ) { TransferQueueObject->tTimeout = 0; TransferQueueObject->bReconnect = false; } else { TransferQueueObject->tTimeout = ttimeout; } SendFileInfo( TransferQueueObject ); } } m_pTransferList->Del( CString::number(TransferObject->m_pTransfer->GetTransferID()) ); obj = oobj; } else if ( m_eShutdownState == essNONE ) { if ( TransferObject->m_pTransfer->GetSrcDirection() == edUPLOAD ) { switch(TransferObject->m_pTransfer->GetTransferType()) { case ettSETTINGS: DownloadManagerInfo.rate_ul_settings += TransferObject->m_pTransfer->GetTransferrate(); break; case ettOPERATOR: DownloadManagerInfo.rate_ul_operator += TransferObject->m_pTransfer->GetTransferrate(); break; case ettUSER: DownloadManagerInfo.rate_ul_user += TransferObject->m_pTransfer->GetTransferrate(); break; case ettSPECIAL: DownloadManagerInfo.rate_ul_special += TransferObject->m_pTransfer->GetTransferrate(); break; case ettRATE_EXTRA: DownloadManagerInfo.rate_ul_rate_extra += TransferObject->m_pTransfer->GetTransferrate(); break; default: break; } SendTransferInfo(TransferObject->m_pTransfer); } else if ( TransferObject->m_pTransfer->GetSrcDirection() == edDOWNLOAD ) { DownloadManagerInfo.rate_dl += TransferObject->m_pTransfer->GetTransferrate(); // create the filetransferratelist if ( TransferObject->m_pTransfer->GetDstFilename() != DC_USER_FILELIST ) { filetransferrate = 0; if ( ratelist->Get( TransferObject->m_pTransfer->GetSrcFilename(), &filetransferrate ) == 0 ) { filetransferrate->m_nRate += TransferObject->m_pTransfer->GetTransferrate(); } else { filetransferrate = new CMessageFileTransferRate(); filetransferrate->m_sLocalFile = TransferObject->m_pTransfer->GetSrcFilename(); filetransferrate->m_nRate = TransferObject->m_pTransfer->GetTransferrate(); ratelist->Add( TransferObject->m_pTransfer->GetSrcFilename(), filetransferrate ); } } transferlist->Add(TransferObject->m_pTransfer); } else { SendTransferInfo(TransferObject->m_pTransfer); } oobj = obj; } else { oobj = obj; } } } } // send all download with global filetransferrate if ( (ratelist != 0) && (transferlist != 0) ) { CTransfer *tr=0; filetransferrate = 0; while ( (tr=transferlist->Next(0)) != 0 ) { if ( ratelist->Get( tr->GetSrcFilename(), &filetransferrate ) == 0 ) { LogMutex.Lock(); CMessageDMTransferObject * to = CreateDMTransferObject(tr); to->m_nMultiRate = filetransferrate->m_nRate; if ( DC_DownloadManagerCallBack(to) == -1 ) delete to; LogMutex.UnLock(); } else { SendTransferInfo(tr); } transferlist->Remove(tr); } delete ratelist; delete transferlist; } if ( ((ttimeout-m_tUpdateTransferTimeout) >= 1) && (count > 0) ) { // dynamic upload rate if ( CConfig::Instance()->GetDynamicUploadRate() && (CConfig::Instance()->GetMaxUploadRate() > 0) && (DownloadManagerInfo.slot_use_settings > 0) && (DownloadManagerInfo.slot_max > 0) && (DownloadManagerInfo.rate_ul_settings<(CConfig::Instance()->GetMaxUploadRate()*DownloadManagerInfo.slot_max)) ) { // calculate max rate for every slot rate = CConfig::Instance()->GetMaxUploadRate()*DownloadManagerInfo.slot_max; // this is the max rate for every slot but if a slot use less than // we give the other slots the "restrate" rate /= DownloadManagerInfo.slot_use_settings; if ( rate > 0 ) { obj = 0; count = 0; tmprate = 0; while( m_pTransferList->Next( &obj ) ) { TransferObject = obj; if ( (TransferObject->m_pTransfer->GetDone() == etsNONE) && (TransferObject->m_pTransfer->GetSrcDirection() == edUPLOAD) && (TransferObject->m_pTransfer->GetTransferType() == ettSETTINGS) ) { // check if the slot use less than 1/2 of the max rate if ( (TransferObject->m_pTransfer->GetTransferrate() < (TransferObject->m_pTransfer->GetRate()/2)) && ((ulonglong)rate >= TransferObject->m_pTransfer->GetRate()) ) { // set the new rate for this transfer (3/4) TransferObject->m_pTransfer->SetRate((TransferObject->m_pTransfer->GetRate()*3/4)); // give other slots the restrate tmprate += rate-TransferObject->m_pTransfer->GetRate(); } // check if the slot use less than 3/4 but more as 1/2 of the current rate we made no changes else if ( (TransferObject->m_pTransfer->GetTransferrate() < (TransferObject->m_pTransfer->GetRate()*3/4)) && ((ulonglong)rate >= TransferObject->m_pTransfer->GetRate()) ) { // give other slots the restrate tmprate += rate-TransferObject->m_pTransfer->GetRate(); } // all other slots use more as 3/4 or the max rate for a slot is less than the current rate for the transfer else { count++; tmprate += rate; } } } // calc new rate if ( (tmprate > 0) && (count > 0) ) { tmprate /= count; obj = 0; while( m_pTransferList->Next( &obj ) ) { TransferObject = obj; if ( (TransferObject->m_pTransfer->GetDone() == etsNONE) && (TransferObject->m_pTransfer->GetSrcDirection() == edUPLOAD) ) { if ( (TransferObject->m_pTransfer->GetTransferrate() >= (TransferObject->m_pTransfer->GetRate()*3/4)) || ((ulonglong)rate < TransferObject->m_pTransfer->GetRate()) ) { TransferObject->m_pTransfer->SetRate(tmprate); } } } } } } // send dl manager info SendDownloadManagerInfo(&DownloadManagerInfo); } if ( (ttimeout-m_tUpdateTransferTimeout) >= 1 ) { // send traffic info SendTrafficInfo(); } m_pTransfersMutex->UnLock(); } /** */ void CDownloadManager::UpdateQueueList( time_t ttimeout ) { int i; CString nick; CStringList * StringList = 0; CStringList * OldStringList = 0; CList hublist; DCHubObject * HubObject1 = 0, * HubObject2 = 0; CString hubname; while( m_pDownloadQueue->pQueue->Next( nick, &StringList) ) { DCTransferQueueObject * TransferObject = 0; while( StringList->Next( &TransferObject) ) { // check for empty filelist if ( TransferObject->pTransferFileList.Count() == 0 ) { // empty filelist and no connections if ( TransferObject->iConnections == 0 ) { // remove from queue SendFileInfo( TransferObject, 0, true ); StringList->Del(TransferObject->sHubName); } break; } // handle wait state else if ( (TransferObject->eState == etwsWAIT) && (m_eShutdownState == essNONE) ) { // check response timeout if ( (ttimeout-TransferObject->tTimeout) >= CConfig::Instance()->GetTransferResponseTimeout() ) { // set timeout TransferObject->eState = etwsIDLE; TransferObject->tTimeout = ttimeout; SendFileInfo( TransferObject ); } } // handle none wait state else if ( (m_eShutdownState == essNONE) && ( (TransferObject->eState == etwsIDLE) || (TransferObject->eState == etwsHUBOFFLINE) || (TransferObject->eState == etwsUSEROFFLINE) || (TransferObject->eState == etwsUSERBUSY) || (TransferObject->eState == etwsSENDERROR) ) ) { // idle state ... check for timeout to reconnect if ( TransferObject->tTimeout == 0 ) { // check for max download rate before new connection start if ( !((CConfig::Instance()->GetMaxDownloadRate() != 0) && (CConfig::Instance()->GetMaxDownloadRate() < DownloadManagerInfo.rate_dl)) ) { // reset hubname hubname = TransferObject->sHubName; // update internal hublist if ( CConnectionManager::Instance()->IsUserOnline( TransferObject->sNick, CString(), CString(), &hublist ) ) { DPRINTF("user is online on:\n"); HubObject1 = 0; while( (HubObject1=hublist.Next(HubObject1)) != 0 ) { DPRINTF("'%s' '%s'\n",HubObject1->m_sHubName.Data(),HubObject1->m_sHubHost.Data()); HubObject2 = 0; while( (HubObject2=TransferObject->pHubList.Next(HubObject2)) != 0 ) { if ( HubObject1->m_sHubName == HubObject2->m_sHubName ) break; } // add new entry if ( HubObject2 == 0 ) { DPRINTF("NEW '%s' '%s'\n",HubObject1->m_sHubName.Data(),HubObject1->m_sHubHost.Data()); HubObject2 = new DCHubObject(); HubObject2->m_sHubName = HubObject1->m_sHubName; HubObject2->m_sHubHost = HubObject1->m_sHubHost; HubObject2->m_bActive = true; TransferObject->pHubList.Add(HubObject2); } else // set entry to connect { if ( (hubname.IsEmpty()) && HubObject2->m_bActive ) { DPRINTF("USE '%s'\n",HubObject2->m_sHubName.Data()); hubname = HubObject2->m_sHubName; } } } hublist.Clear(); } // check for available files DCTransferFileObject * TransferFileObject = 0; while( TransferObject->pTransferFileList.Next( &TransferFileObject ) ) { if ( TransferFileObject->m_eState == etfsNONE ) { break; } } if ( TransferFileObject != 0 ) { // send connection request to the hub i = CConnectionManager::Instance()->SendConnectionRequest( TransferObject->sNick, hubname, TransferObject->sHubHost ); switch (i) { case 0: TransferObject->eState = etwsWAIT; break; case -1: TransferObject->eState = etwsUSEROFFLINE; break; case -2: case -3: TransferObject->eState = etwsHUBOFFLINE; break; case -4: TransferObject->eState = etwsSENDERROR; break; default: break; } } } // update timeout TransferObject->tTimeout = ttimeout; // send info SendFileInfo( TransferObject ); } // check resend timeout else if ( (ttimeout-TransferObject->tTimeout) >= CConfig::Instance()->GetTransferResendTimeout() ) { // reset timeout TransferObject->tTimeout = 0; // send info SendFileInfo( TransferObject ); } } } // remove nick on empty list if ( StringList->Count() == 0 ) { m_pDownloadQueue->pQueue->Del(nick); StringList = OldStringList; } else { OldStringList = StringList; } } } /** */ bool CDownloadManager::InitSearch( time_t /*ttimeout*/ ) { CStringList * StringList = 0; // clear searchlist // TODO: we can leave it and search again on the last break, // but we need a check against the current queue (traffic) m_pSearchList->Clear(); m_pSearchQueryList->Clear(); if ( !CSearchManager::Instance() ) { return false; } m_pDownloadQueue->pQueueMutex->Lock(); while( m_pDownloadQueue->pQueue->Next( &StringList ) ) { DCTransferQueueObject * TransferObject = 0; while( StringList->Next( &TransferObject ) ) { DCTransferFileObject * TransferFileObject = 0; while( TransferObject->pTransferFileList.Next( &TransferFileObject ) ) { if ( TransferFileObject->m_bMulti && // only if md enabled TransferFileObject->m_sHash.NotEmpty() && // only if we have a TTH (TransferFileObject->m_eMedium == eltFILE) ) // only if medium file { bool dupe = false; CMessageSearchResult * it = 0; while ( (it = m_pSearchList->Next(it)) != 0 ) { if ( it->m_sHash == TransferFileObject->m_sHash ) { dupe = true; break; } } if ( dupe ) { continue; } CMessageSearchResult * msg = new CMessageSearchResult(); msg->m_nSize = TransferFileObject->m_nSize; msg->m_sFile = TransferFileObject->m_sRemoteFile; msg->m_sNick = TransferObject->sNick; msg->m_sHubName = TransferObject->sHubName; msg->m_sHash = TransferFileObject->m_sHash; CMessageSearchFile * smsg = new CMessageSearchFile(); smsg->m_sString = TransferFileObject->m_sHash; smsg->m_eFileType = eftHASH; smsg->m_bLocal = (CConfig::Instance()->GetMode() == ecmPASSIVE); /* CClient sets the source (nick or IP) before sending the search */ m_pSearchList->Add(msg); m_pSearchQueryList->Add(smsg); } } } } m_pDownloadQueue->pQueueMutex->UnLock(); if ( m_pSearchList->Count() <= 0 ) { return false; } if ( CSearchManager::Instance()->StartSearch(esmCONNECTEDALL,estyEXTERNAL,m_pSearchQueryList,0) != eseNONE ) { return false; } return true; } /** thread callbackfunction */ int CDownloadManager::Callback() { int i; time_t ttimeout; if ( m_eShutdownState == essSHUTDOWNREADY ) { return 0; } ttimeout = time(0); if ( m_eShutdownState == essNONE ) { // save queue i = CConfig::Instance()->GetDownloadQueueTime(); if ( i > 0 ) { i *= 60; if ( (ttimeout-m_tDownloadQueueTimeout) > i ) { DLM_SaveQueue(); m_tDownloadQueueTimeout = ttimeout; } } } // update the transfer list UpdateTransferList(ttimeout); // update the queue list if ( (ttimeout-m_tUpdateTransferTimeout) >= 1 ) { m_pDownloadQueue->pQueueMutex->Lock(); if ( m_pDownloadQueue->pQueue->Count() > 0 ) { UpdateQueueList(ttimeout); } m_pDownloadQueue->pQueueMutex->UnLock(); } /* * If dclib sent a ConnectToMe but there was no response, * the entry was never removed from m_pTransferWaitList. * m_pTransferWaitList is limited to 250 entries, after which * no more transfers will be allowed, i.e. if you had 250 entries * stuck in it you had to restart valknut. */ if ( (ttimeout-m_tWaitListCleaned) >= 60 ) { m_pWaitListMutex->Lock(); DCTransferWait *tw = 0, *tw_prev = 0; int max_age = CConfig::Instance()->GetTransferResendTimeout() * 5; if ( max_age < 5*60 ) { max_age = 5*60; } while ( (tw = m_pTransferWaitList->Next(tw)) != 0 ) { /* * dclib 0.3.23 fills in the empty info, an * empty nick or user ip means this transfer * has not been established. */ if ( tw->sNick.IsEmpty() || tw->sUserHost.IsEmpty() ) { if ( (ttimeout - tw->tTimeout) > max_age ) { DPRINTF("Wait on %s/%s expired\n",tw->sNick.Data(),tw->sUserHost.Data()); m_pTransferWaitList->Del(tw); tw = tw_prev; } } tw_prev = tw; } m_pWaitListMutex->UnLock(); m_tWaitListCleaned = ttimeout; } if ( CConfig::Instance()->GetTransferAutoSearch() && CSearchManager::Instance() ) { // if there is no search running and the timeout is not set it can be set // but if the user searches the timeout must be unset and not be reset until the user // has finished searching if ( (m_tHubSearchTimeout == 0) && (CSearchManager::Instance()->SearchType() == estyNONE) ) { // start countdown m_tHubSearchTimeout = ttimeout; } else if ( (m_tHubSearchTimeout != 0) && ((CSearchManager::Instance()->SearchType() == estySINGLE) || (CSearchManager::Instance()->SearchType() == estyMULTI)) ) { // stop countdown m_tHubSearchTimeout = 0; } // search for new sources if ( (m_tHubSearchTimeout != 0) && (ttimeout-m_tHubSearchTimeout) >= CConfig::Instance()->GetAutoSearchInterval() ) { DPRINTF("init search\n"); if ( InitSearch(ttimeout) == false ) { DPRINTF("failed\n"); m_tHubSearchTimeout = ttimeout; } else { m_tHubSearchTimeout = 0; } } } // update timeout m_tUpdateTransferTimeout = ttimeout; return 0; } /** Called directly by either of the listen managers */ int CDownloadManager::ListenCallbackHandler( int handle, bool crypto ) { bool disc = false; if ( m_eShutdownState == essNONE ) { m_pWaitListMutex->Lock(); if ( m_pTransferWaitList->Count() == 0 ) { // no waiting transfers, disconnect incoming connection disc = true; } m_pWaitListMutex->UnLock(); } else { // dont accept connections on shutdown state disc = true; } if ( disc ) { #ifdef WIN32 closesocket(handle); #else close(handle); #endif handle = -1; } if ( handle == -1 ) { return -1; } CTransferObject * TransferObject = new CTransferObject(); TransferObject->m_pTransfer = new CTransfer(true); if ( crypto ) { if ( TransferObject->m_pTransfer->ChangeSocketMode( esmFULLSSLSERVER, CConfig::Instance()->GetTransferCert(), CConfig::Instance()->GetTransferKey() ) == false ) { DPRINTF("New transfer change to SSL server mode failed\n"); delete TransferObject; return -1; } } TransferObject->m_pTransfer->SetTransferID( GetNewID() ); TransferObject->m_pTransfer->SetRate( CConfig::Instance()->GetMaxUploadRate() ); TransferObject->m_pTransfer->SetCallBackFunction( new CCallback2( this, &CDownloadManager::DM_TransferCallBack ) ); if ( TransferObject->m_pTransfer->SetSocket(handle) == 0 ) { CString logmsg = "Incoming connection from '"; logmsg += TransferObject->m_pTransfer->GetHost(); logmsg += '\''; SendLogInfo(logmsg); m_pTransfersMutex->Lock(); m_pTransferList->Add( CString::number(TransferObject->m_pTransfer->GetTransferID()), TransferObject ); m_pTransfersMutex->UnLock(); } else { delete TransferObject; #ifdef WIN32 closesocket(handle); #else close(handle); #endif } return 0; } /** */ int CDownloadManager::DM_TransferCallBack( CTransfer * Transfer, CDCMessage * DCMsg ) { TransferCallBackMutex.Lock(); CByteArray ba; CString s,r; ulonglong len; CDir dir; bool remove,bdirec; eShareBufferType stype; eDirection direction; switch ( DCMsg->m_eType ) { case DC_MESSAGE_MYNICK: { // check with the nick for download or upload direction = CheckWaitTransfer( Transfer ); Transfer->SetSrcDirection(direction); DCMessageConnectClient mcc; mcc.m_sHubHost = Transfer->GetHost(); CConnectionManager::Instance()->SetUserTransferInfo( Transfer->GetHubName(), Transfer->GetHubHost(), Transfer->GetDstNick(), &mcc ); break; } case DC_MESSAGE_GET: { // remote want a file ... CMessageGet * msg = (CMessageGet*)DCMsg; if ( (Transfer->GetSrcDirection() == edUPLOAD) && (Transfer->GetDstDirection() == edDOWNLOAD) ) { // reset done flags Transfer->SetDone(etsNONE); // send a log info CString logmsg = "Upload: "; logmsg += msg->m_sFilename; logmsg += " ("; logmsg += CString::number(msg->m_nPos); logmsg += '/'; logmsg += CString::number(msg->m_nSize); logmsg += ')'; SendLogInfo( logmsg, Transfer ); stype = esbtNONE; if ( msg->m_sFilename == DC_USER_FILELIST_HE3 ) { stype = esbtHE3; } else if ( msg->m_sFilename == DC_USER_FILELIST_BZ ) { stype = esbtBZ; } else if ( msg->m_sFilename == DC_USER_FILELIST_XMLBZ ) { stype = esbtXMLBZ; } else if ( msg->m_sFilename == DC_USER_FILELIST_XML ) { stype = esbtXML; } else if ( Transfer->GetTransferType() == ettOPERATOR ) { SendLogInfo( "Operator Transfer not for the filelist", Transfer ); Transfer->SendMaxedOut(); Transfer->Disconnect(true); break; } // check special transfer file size if ( stype != esbtNONE ) { if ( (CFileManager::Instance()->GetShareBuffer( stype, &ba ) == 0) && (ba.Size() > 0) ) { // set send buffer Transfer->SetBuffer(&ba); // set local transfer medium to buffer Transfer->SetMedium(eltBUFFER); // start upload if ( Transfer->StartUpload( msg->m_sFilename, ba.Size(), msg->m_nPos-1, 0, msg->m_sFilename, msg->m_bUGet, false, CString(), msg->m_bZLib ) == -1 ) { Transfer->Disconnect(true); } } else { Transfer->SendError("File Not Available"); SendLogInfo( "Upload (no sharebuffer): " + msg->m_sFilename, Transfer ); } } else // remote download from the share ... { // search the wanted file in the share s = CConfig::Instance()->AliasToPath(msg->m_sFilename); if ( s.IsEmpty() ) { Transfer->SendError("File Not Available"); SendLogInfo( "Upload (File Not Available): " + msg->m_sFilename, Transfer ); } else { // file found, check filesize len = dir.getFileSize(s,false); if ( msg->m_nPos > len ) // if the wanted filepos > local length send an error { Transfer->SendError("File allready download."); } else if ( msg->m_nPos == 0 ) // we begin at 1 (see dc protocoll) { Transfer->SendError("Wrong file position."); } else // upload the wanted file ... { // special transfer only for files <= Configured small file size if ( (Transfer->GetTransferType() == ettSPECIAL) && (len > (CConfig::Instance()->GetSmallFileSize())) ) { // disconnect ... SendLogInfo( "Special Transfer not for files > " + CUtils::GetSizeString( CConfig::Instance()->GetSmallFileSize(), euAUTO ), Transfer ); Transfer->SendMaxedOut(); Transfer->Disconnect(true); } else { // set local transfer medium to buffer Transfer->SetMedium(eltFILE); // start upload if ( Transfer->StartUpload( msg->m_sFilename, len, msg->m_nPos-1, msg->m_nSize, s, msg->m_bUGet, false, CString(), msg->m_bZLib ) == -1 ) { Transfer->Disconnect(true); } } } } } } else { SendLogInfo( "Warning wrong mode", Transfer ); Transfer->Disconnect(true); } break; } case DC_MESSAGE_ADCGET: { // remote want a file by TTH (or files.xml.bz2) CMessageADCGet * msg = (CMessageADCGet*)DCMsg; if ( (Transfer->GetSrcDirection() == edUPLOAD) && (Transfer->GetDstDirection() == edDOWNLOAD) ) { // reset done flags Transfer->SetDone(etsNONE); if ( msg->m_eADCType == eAdcTTHL ) { if ( Transfer->GetTransferType() == ettOPERATOR ) { SendLogInfo( "Operator Transfer not for the filelist", Transfer ); Transfer->SendMaxedOut(); Transfer->Disconnect(true); } else { CByteArray * leaves = CFileManager::Instance()->GetHashLeaves( msg->m_sTTH ); if ( leaves ) { Transfer->SetMedium(eltTTHL); const unsigned long lsize = leaves->Size(); Transfer->ClearAndAppendBuffer( leaves->Data(), lsize ); delete leaves; CString logmsg = "Send leaves for "; logmsg += msg->m_sTTH; logmsg += " ("; logmsg += CString::number(msg->m_nPos); logmsg += '/'; logmsg += CString::number(lsize); logmsg += ')'; SendLogInfo( logmsg, Transfer ); // start upload if ( Transfer->StartUpload( CString(), lsize, msg->m_nPos, lsize, CString(), false, true, msg->m_sTTH, msg->m_bZlib ) == -1 ) { Transfer->Disconnect(true); } } else { /* alternatively could base32 decode the TTH and send those 24 bytes */ DPRINTF("Hash leaves not found for %s\n", msg->m_sTTH.Data()); SendLogInfo( "Hash leaves not found for " + msg->m_sTTH, Transfer ); Transfer->SendError("File Not Available"); Transfer->Disconnect(true); } } break; } else if ( msg->m_eADCType == eAdcList ) { Transfer->SetMedium(eltLIST); CString displayname = "Listing for "; displayname += msg->m_sFile; CString listing; /* * FIXME where do we get the depth from? msg->m_nPos is always 0. * It doesn't really matter because we are allowed to send * less than the requested depth. */ CFileManager::Instance()->GetPartialListing( msg->m_sFile, listing ); if ( listing.IsEmpty() ) { SendLogInfo( "Upload (File Not Available): " + displayname, Transfer ); Transfer->SendError("File Not Available"); Transfer->Disconnect(true); } else { CString logmsg = "Upload: "; logmsg += displayname; logmsg += " ("; logmsg += CString::number(msg->m_nPos); logmsg += '/'; logmsg += CString::number(listing.Length()); logmsg += ')'; SendLogInfo( logmsg, Transfer ); Transfer->ClearAndAppendBuffer( (const unsigned char*) listing.Data(), listing.Length() ); if ( Transfer->StartUpload( msg->m_sFile, listing.Length(), msg->m_nPos, listing.Length(), displayname, false, true, CString(), msg->m_bZlib ) == -1 ) { Transfer->Disconnect(true); } } break; } else if ( msg->m_eADCType != eAdcFile ) { CString logmsg = "Unknown ADCGET transfer type "; logmsg += CString::number(msg->m_eADCType); SendLogInfo( logmsg, Transfer ); Transfer->SendError(logmsg); Transfer->Disconnect(); break; } stype = esbtNONE; if ( msg->m_sFile == DC_USER_FILELIST_XMLBZ ) { stype = esbtXMLBZ; } else if ( msg->m_sFile == DC_USER_FILELIST_XML ) { stype = esbtXML; } else if ( Transfer->GetTransferType() == ettOPERATOR ) { SendLogInfo( "Operator Transfer not for the filelist", Transfer ); Transfer->SendMaxedOut(); Transfer->Disconnect(true); break; } // check special transfer file size if ( stype != esbtNONE ) { if ( (CFileManager::Instance()->GetShareBuffer( stype, &ba ) == 0) && (ba.Size() > 0) ) { // set send buffer Transfer->SetBuffer(&ba); // set local transfer medium to buffer Transfer->SetMedium(eltBUFFER); // start upload /* Filelists always start at 0 */ CString logmsg = "Upload: "; logmsg += msg->m_sFile; logmsg += " (0/"; logmsg += CString::number(ba.Size()); logmsg += ')'; SendLogInfo( logmsg, Transfer ); if ( Transfer->StartUpload( msg->m_sFile, ba.Size(), msg->m_nPos, 0, msg->m_sFile, false, true, CString(), msg->m_bZlib ) == -1 ) { Transfer->Disconnect(true); } } else { Transfer->SendError("File Not Available"); SendLogInfo( "Upload (no sharebuffer): " + msg->m_sFile, Transfer ); } } else // remote download from the share ... { CString fileName; if ( msg->m_sTTH.IsEmpty() ) { DPRINTF("Warning! ADCGet without TTH is undocumented behaviour!\n"); if ( msg->m_sFile.NotEmpty() && (msg->m_sFile.Data()[0] == '/') ) { // DPRINTF("Warning! Removing leading / from filename for ADCGet without TTH\n"); fileName = msg->m_sFile.Mid(1, msg->m_sFile.Length() - 1); } else { fileName = msg->m_sFile; } CString logmsg = "Upload: "; logmsg += fileName; logmsg += " ("; logmsg += CString::number(msg->m_nPos); logmsg += '/'; logmsg += CString::number(msg->m_nSize); logmsg += ')'; SendLogInfo( logmsg, Transfer ); } else { // search the share for the file matching the TTH, the "TTH/" prefix is now added/removed at a lower level std::set * results = CFileManager::Instance()->SearchHash( msg->m_sTTH ); if ( (results == 0) || (results->empty()) ) { Transfer->SendError("File Not Available"); SendLogInfo( "Upload: No file found for TTH:" + msg->m_sTTH, Transfer ); delete results; break; } else { if ( results->size() > 1 ) { SendLogInfo( "Upload: Warning: Multiple files match TTH:" + msg->m_sTTH, Transfer ); } fileName = CFileManager::Instance()->GetFileName(*(results->begin())); delete results; CString logmsg = "Upload: "; logmsg += fileName; logmsg += " ("; logmsg += msg->m_sTTH; logmsg += ") ("; logmsg += CString::number(msg->m_nPos); logmsg += '/'; logmsg += CString::number(msg->m_nSize); logmsg += ')'; SendLogInfo( logmsg, Transfer ); } } s = CConfig::Instance()->AliasToPath(fileName); if ( s.IsEmpty() ) { DPRINTF("Error: didn't find path to file from share alias!\n"); Transfer->SendError("File Not Available"); SendLogInfo( "Upload: File Not Available: " + fileName, Transfer ); } else { // file found, check filesize len = dir.getFileSize(s,false); if ( msg->m_nSize == -1 ) { msg->m_nSize = len - msg->m_nPos; } if ( msg->m_nPos > len ) // if the wanted filepos > local length send an error { Transfer->SendError("File already downloaded."); } else // upload the wanted file ... { // special transfer only for files <= Configured small file size if ( (Transfer->GetTransferType() == ettSPECIAL) && (len > (CConfig::Instance()->GetSmallFileSize())) ) { // disconnect ... SendLogInfo( "Special Transfer not for files > " + CUtils::GetSizeString( CConfig::Instance()->GetSmallFileSize(), euAUTO ), Transfer ); Transfer->SendMaxedOut(); Transfer->Disconnect(true); } else { Transfer->SetMedium(eltFILE); // start upload if ( Transfer->StartUpload( fileName, len, msg->m_nPos, msg->m_nSize, s, false, true, msg->m_sTTH, msg->m_bZlib ) == -1 ) { Transfer->Disconnect(true); } } } } } } else { SendLogInfo( "Warning wrong mode", Transfer ); Transfer->Disconnect(true); } break; } case DC_MESSAGE_DIRECTION: { break; } case DC_MESSAGE_KEY: { // direction message ... //CMessageDirection * msg = (CMessageDirection*)DCMsg; bdirec = false; DPRINTF("DIRECTION: level: LOCAL: %d REMOTE: %d\n",Transfer->GetSrcLevel(), Transfer->GetDstLevel() ); DPRINTF("DIRECTION: direc: LOCAL: %d REMOTE: %d\n",Transfer->GetSrcDirection(), Transfer->GetDstDirection() ); // equal direction ... if ( Transfer->GetDstDirection() == Transfer->GetSrcDirection() ) { // check the level ... if ( Transfer->GetDstLevel() < Transfer->GetSrcLevel() ) { // now we must change the dst direction if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { Transfer->SetDstDirection(edUPLOAD); bdirec = true; } else if ( Transfer->GetSrcDirection() == edUPLOAD ) { Transfer->SetDstDirection(edDOWNLOAD); bdirec = true; } } else if ( Transfer->GetDstLevel() > Transfer->GetSrcLevel() ) { if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { // change direction from download to upload and update the queue state if ( ChangeDirection(Transfer) ) { Transfer->SetSrcDirection(edUPLOAD); bdirec = true; } } else if ( (Transfer->GetSrcDirection() == edUPLOAD) && (Transfer->GetDstDirection() == edUPLOAD) ) { SendLogInfo( "Warning: remote want to upload a file !", Transfer ); } else { SendLogInfo( "Warning: change direction not supported !", Transfer ); } } } else { bdirec = true; } if ( bdirec ) { // now we try to set direction with a slot check (update slots) if ( SetDirection(Transfer) == false ) { bdirec = false; } } if ( bdirec == false ) { SendLogInfo( "Warning no more free slots", Transfer ); Transfer->SetDstDirection(edNONE); Transfer->SendMaxedOut(); Transfer->Disconnect(true); } // check if both modes set correct else if ( (Transfer->GetSrcDirection() == edNONE) || (Transfer->GetDstDirection() == edNONE)) { DPRINTF("DIRECTION: wrong mode ...\n"); SendLogInfo( "Warning wrong transfer mode", Transfer ); Transfer->SetDstDirection(edNONE); Transfer->Disconnect(true); } else { if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { DPRINTF("DIRECTION: download mode ...\n"); while (1) { if ( SetNextFile(Transfer) == false ) { DPRINTF("DIRECTION: download mode without destination file -> disconnecting!\n"); Transfer->Disconnect(true); break; } else if ( Transfer->GetMedium() == eltCLIENTVERSION ) { UpdateFileState(Transfer,etfsNONE); } else { break; } } } else if ( Transfer->GetSrcDirection() == edUPLOAD ) { DPRINTF("DIRECTION: we are in upload mode ...\n"); } } break; } case DC_MESSAGE_CONNECTION_STATE: { // connection-state message, generated by the ctransfer-class remove = true; CMessageConnectionState *msg = (CMessageConnectionState*)DCMsg; switch(msg->m_eState) { case estDISCONNECTED: SendLogInfo( "Disconnected from "+Transfer->GetHost(), Transfer ); break; // case estCONNECTED: // case estSOCKETERROR: // case estCONNECTIONTIMEOUT: default: remove = false; break; } if ( remove && (Transfer->GetSrcDirection() == edDOWNLOAD) ) { if ( Transfer->GetMedium() == eltBUFFER ) Transfer->SetStartPosition(0); UpdateFileState(Transfer,etfsNONE); } if ( remove ) { UpdateWaitTransfer(Transfer,true); Transfer->SetDone(etsREADY); } break; } case DC_MESSAGE_TRANSFER: { // transfer message, generated by the ctransfer-class // CMessageTransfer *msg = (CMessageTransfer*)DCMsg; // filetransfer done if ( Transfer->GetChunkSize() == Transfer->GetTransfered() ) { // download ready if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { bool b = false; // set new chunk-end if available if ( (Transfer->GetMedium() == eltFILE) && (Transfer->SupportsChunks() == false) ) { ulonglong lstart,lend; // get new chunk end if ( GetNewChunkEnd( Transfer->GetSrcFilename(), Transfer->GetStartPosition(), Transfer->GetEndPosition(), Transfer->GetStartPosition()+Transfer->GetTransfered(), &lstart, &lend ) ) { Transfer->SetStartPosition(lstart); Transfer->SetEndPosition(lend); Transfer->SetChunkSize(lend-lstart); Transfer->SetTransfered(0); // reset stattime Transfer->SetStartTime(time(0)); b = true; } } // no new chunkend set if ( b == false ) { UpdateFileState(Transfer,etfsNONE); // check if transfer in idle state and set next file if ( Transfer->IsIdle() ) { while ( SetNextFile(Transfer) ) { if ( Transfer->GetMedium() == eltCLIENTVERSION ) { UpdateFileState(Transfer,etfsNONE); } else { break; } } } } } else // upload ready { // set timeout to save local slots if ( Transfer->GetDone() != etsIDLE ) { Transfer->SetStartTime(time(0)); Transfer->SetDone(etsIDLE); } } } break; } case DC_MESSAGE_FILELENGTH: { // remote send a filelength CMessageFileLength * msg = (CMessageFileLength*)DCMsg; if ( msg->m_nFileLength == 0 ) { SendLogInfo( "Warning: Filelength is NULL.", Transfer ); if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { UpdateFileState(Transfer,etfsERROR); } Transfer->Disconnect(true); } else { SendTransferInfo(Transfer); } break; } case DC_MESSAGE_SENDING: { CMessageSending * msg = (CMessageSending*)DCMsg; if ( msg->m_nLength == 0) { SendLogInfo( "Warning: $Sending length is 0", Transfer ); } SendTransferInfo(Transfer); break; } case DC_MESSAGE_ADCSND: { CMessageADCSnd * msg = (CMessageADCSnd*)DCMsg; if ( msg->m_nSize == 0 ) { SendLogInfo( "Warning: $ADCSnd size is 0", Transfer ); } SendTransferInfo(Transfer); break; } case DC_MESSAGE_SEND: { // handled by CTransfer, but send message to update GUI SendTransferInfo(Transfer); break; } case DC_MESSAGE_MAXEDOUT: { // no free slots on the remote side SendLogInfo( "Busy", Transfer ); Transfer->Disconnect(true); break; } case DC_MESSAGE_GETLISTLEN: { // remote want the listlen if ( Transfer->GetSupport().m_bXMLBZList ) Transfer->SendListLen(CFileManager::Instance()->GetShareBufferSize(esbtXMLBZ)); else if ( Transfer->GetSupport().m_bBZList ) Transfer->SendListLen(CFileManager::Instance()->GetShareBufferSize(esbtBZ)); else Transfer->SendListLen(CFileManager::Instance()->GetShareBufferSize(esbtHE3)); break; } case DC_MESSAGE_ERROR: { // remote send a error message CMessageError * msg = (CMessageError*)DCMsg; SendLogInfo( "Error: " + msg->m_sError, Transfer ); if ( Transfer->GetSrcDirection() == edDOWNLOAD ) { UpdateFileState(Transfer,etfsERROR); while ( SetNextFile(Transfer) ) { if ( Transfer->GetMedium() == eltCLIENTVERSION ) { UpdateFileState(Transfer,etfsNONE); } else { break; } } } break; } case DC_MESSAGE_LOCK: { CMessageLock * msg = (CMessageLock*)DCMsg; CConnectionManager::Instance()->SetUserTransferInfo( Transfer->GetHubName(), Transfer->GetHubHost(), Transfer->GetDstNick(), msg ); CString s = "Client: "; switch(msg->m_eClientVersion) { case eucvDCPP: s += "DC++"; break; case eucvDCGUI: s += "Valknut"; // really dclib... break; case eucvMICRODC: s += "microdc"; break; case eucvSHAKESPEER: s += "ShakesPeer"; break; default: s += "Unknown"; break; } if ( msg->m_sVersionString.NotEmpty() ) { s += " ("; s += msg->m_sVersionString; s += ')'; } SendLogInfo( s, Transfer ); break; } case DC_MESSAGE_SUPPORTS: { CMessageSupports * msg = (CMessageSupports*)DCMsg; CConnectionManager::Instance()->SetUserTransferInfo( Transfer->GetHubName(), Transfer->GetHubHost(), Transfer->GetDstNick(), msg ); break; } case DC_MESSAGE_LOG: { SendLogInfo( ((CMessageLog*)DCMsg)->sMessage, Transfer ); break; } default: { DPRINTF("dctransfer unknown message: %d\n",DCMsg->m_eType); break; } } delete DCMsg; TransferCallBackMutex.UnLock(); return 0; } libdc0-0.3.24~svn3121/dclib/cconfig.cpp0000644000175000017500000023420611233301711016411 0ustar sikonsikon/*************************************************************************** cconfig.cpp - description ------------------- begin : Tue May 14 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cconfig.h" #define DCLIB_CONFIG "dclib.cfg" #define DCTRA_CONFIG "dctra.cfg" #define DCHUB_CONFIG "dchub.cfg" #define DCPROF_CONFIG "dcprof.cfg" #define DCBOOKHUB_CONFIG "dcbookhub.cfg" #define XML_DCLIB_CONFIG "dclib" #define XML_DCHUB_CONFIG "dchub" #define XML_DCBOOKHUB_CONFIG "dcbookhub" #define XML_DCTRA_CONFIG "dctra" #define XML_DCPROF_CONFIG "dcprof" #define XML_IDENTIFY "identify" #define XML_NICK "nick" #define XML_SEARCHNICK "searchnick" #define XML_AWAYMESSAGE "awaymessage" #define XML_EMAIL "email" #define XML_ANTISPAM "antispam" #define XML_SPEED "speed" #define XML_DESCRIPTION_TAG "descriptiontag" #define XML_EXTENDED_HUB_COUNT "extendedhubcount" #define XML_SUPPRESSED_NICKS "suppressednicks" #define XML_AWAY_PREFIX "awayprefix" #define XML_EMAIL_ENABLED "emailenabled" #define XML_DESCRIPTION_ENABLED "descriptionenabled" #define XML_LOGFILE "logfile" #define XML_LOGFILEON "logfileon" #define XML_LOGFILENAME "logfilename" #define XML_LOGDOWNLOADS "logdownloads" #define XML_LOGUPLOADS "loguploads" #define XML_LOGDETAILS "logdetails" #define XML_SECURITY "security" #define XML_FLOODOPKICKMESSAGE "floodopkickmessage" #define XML_TRANSFER "transfer" #define XML_DOWNLOADFOLDER "downloadfolder" #define XML_DOWNLOADFINISHEDFOLDER "downloadfinishedfolder" #define XML_MINSEGSIZE "minsegsize" #define XML_SHAREDFOLDER "sharedfolder" #define XML_MAXUPLOAD "maxupload" #define XML_MAXUPLOADRATE "maxuploadrate" #define XML_MAXDOWNLOADRATE "maxdownloadrate" #define XML_AUTORECREATESHARELIST "autorecreatesharelist" #define XML_SENDMESSAGEONACTIVEMODEREQUEST "sendmessageonactivemoderequest" #define XML_EXTRA_SLOTS_RATE "extra_slots_rate" #define XML_MAX_EXTRA_SLOTS "max_extra_slots" #define XML_CONNECTION "connection" #define XML_MODE "mode" #define XML_TCPLISTENPORT "tcplistenport" #define XML_CRYPTOLISTENPORT "cryptolistenport" #define XML_UDPLISTENPORT "udplistenport" #define XML_IP "ip" #define XML_EXTERNALIP "externalip" #define XML_NAME "name" #define XML_HUBNAME "hubname" #define XML_HUBHOST "hubhost" #define XML_DESCRIPTION "description" #define XML_SERVER "server" #define XML_HOST "host" #define XML_PORT "port" #define XML_LISTENHOST "listenhost" #define XML_BOOKMARK "bookmark" #define XML_PUBLIC "public" #define XML_USERCOUNT "usercount" #define XML_COUNTRY "country" #define XML_EXTRA "extra" #define XML_SHARED "shared" #define XML_MINSHARE "minshare" #define XML_PROFILE_NAME "profilename" #define XML_PROFILE "profile" #define XML_PASSWORD "password" #define XML_AUTO_CONNECT "autoconnect" #define XML_SSL "ssl" #define XML_ID "id" #define XML_TIME "time" #define XML_FILE "file" #define XML_FILEENTRY "fileentry" #define XML_TYPE "type" #define XML_PATH "path" #define XML_ALIAS "alias" #define XML_LOCALFILE "localfile" #define XML_LOCALPATH "localpath" #define XML_LOCALFILENAME "localfilename" #define XML_SIZE "size" #define XML_STATE "state" #define XML_PRIORITY "priority" #define XML_REMOTEFILE "remotefile" #define XML_MEDIUM "medium" #define XML_MEDIUM_FILE "file" #define XML_MEDIUM_BUFFER "buffer" #define XML_HASH "hash" #define XML_JUMPTO "jumpto" #define XML_DL_FOLDERS "dl_folders" #define XML_FILECHUNK "filechunk" #define XML_REFCOUNT "refcount" #define XML_CHUNK "chunk" #define XML_TEMPHASH "temphash" #define XML_SIZEDONE "sizedone" #define XML_MULTI "multi" #define XML_START "start" #define XML_END "end" #define XML_HUB "hub" #define XML_ACTIVE "active" #define XML_HUBLISTURL "hublisturl" #define XML_URL "url" #define XML_ENABLED "enabled" #define XML_OTHER "other" #define XML_HUBLISTSTORELOCAL "hubliststorelocal" #define XML_RECONNECTCOUNT "reconnectcount" #define XML_RECONNECTTIMEOUT "reconnecttimeout" #define XML_TRANSFERRESPONSETIMEOUT "transferresponsetimeout" #define XML_TRANSFERRESENDTIMEOUT "transferresendtimeout" #define XML_FORCEMOVEENABLED "forcemoveenabled" #define XML_DOWNLOADQUEUETIME "downloadqueuetime" #define XML_CHECKPRIVATEADDRESSSPACE "checkprivateaddressspace" #define XML_PRIVATEADDRESSSPACEONLY "privateaddressspaceonly" #define XML_DCLIB_PLUGINPATH "dclibpluginpath" #define XML_DYNAMICUPLOADRATE "dynamicuploadrate" #define XML_CHATSENDTOOFFLINE "chatsendtooffline" #define XML_CHATRECVFROMOFFLINE "chatrecvfromoffline" #define XML_DC "dc" #define XML_VERSION "version" #define XML_RELEASE "release" #define XML_MODE_ACTIVE "active" #define XML_MODE_PASSIVE "passive" #define XML_USER_UPLOAD_SLOTS "useruploadslots" #define XML_TRANSFER_CERT "transfercert" #define XML_TRANSFER_KEY "transferkey" #define XML_OLD_SSL_SUPPORT "old_ssl_support" #define XML_HUBOFFLINE_TRANSFERCLOSE "hubofflinetransferclose" #define XML_TRANSFER_AUTOSEARCH "transferautosearch" #define XML_RELOAD_HUBLIST_TIME "reloadhublisttime" #define XML_RECREATE_SHARELIST_TIME "recreatesharelisttime" #define XML_DISABLEHASHLIST "disablehashlist" #define XML_COMPRESSEDTRANSFERS "enablecompressedtransfers" #define XML_ENABLE_ZPIPE "enable_zpipe" #define XML_TRAFFIC_RX "trafficrx" #define XML_TRAFFIC_TX "traffictx" #define XML_TRAFFIC_DATA_RX "trafficdatarx" #define XML_TRAFFIC_DATA_TX "trafficdatatx" #define XML_TRAFFIC_CONTROL_RX "trafficcontrolrx" #define XML_TRAFFIC_CONTROL_TX "trafficcontroltx" #define XML_AUTOSEARCHINTERVAL "autosearchinterval" #define XML_SMALLFILESIZE "smallfilesize" #define XML_DONTSHAREDOTFILES "dontsharedotfiles" #define XML_REMOTE_ENCODING "remote_encoding" #define XML_USERIP2_ENABLED "userip2_enabled" #define XML_READ_FILE_BUFFER_SIZE "readfilebuffersize" #define XML_NO_ADCGET_WITHOUT_TTH "no_adcget_without_tth" #define XML_NO_XMLLIST_WITHOUT_TTH "no_xmllist_without_tth" #define XML_OBSOLETE_EXT "obsolete_ext" #define XML_SHUFFLE_SUPPORTS "shuffle_supports" #define XML_ENABLE_USER_COMMAND "enable_usercommand" #ifdef WIN32 #define DCGUI_CONFIG_PATH "\\dc" #else #define DCGUI_CONFIG_PATH "/.dc" #endif #include #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_LANGINFO_H #include #endif #include "core/cxml.h" #include "core/cdir.h" #include "core/csocket.h" #include "core/cnetaddr.h" #include "dcobject.h" #include "cconnectionmanager.h" #include "cdownloadmanager.h" #include "cdownloadqueue.h" #include "clistenmanager.h" #include /** * default hub url list - see dcpp/SettingsManager.cpp in the DC++ sources for more * This has been removed, defaults are added only if the list is empty in LoadDCLib(). * The first two XML lists are enabled and the .config lists are disabled. */ //const char * huburl_list[] = { // "http://hublist.hubtracker.com/hublist.xml.bz2", // "http://hublist.hubtracker.com/hublist.config.bz2", // "http://dchublist.com/hublist.xml.bz2", // "http://dchublist.com/hublist.config.bz2", // "http://dreamland.gotdns.org/PublicHubList.config.bz2", // "http://hublist.awenet.info/PublicHubList.config.bz2", // "http://www.hublist.org/PublicHubList.config.bz2", // "http://www.neo-modus.com/PublicHubList.config", // "http://dcplusplus.sourceforge.net/PublicHubList.config.bz2", // "http://axljab.homelinux.org:8080/PublicHubList.config.bz2", // "http://dreamland.gotdns.org/PublicHubList.config", // "http://dc-dreamland.dhs.org/PublicHubList.config", // "http://web.njit.edu/~cjm3//PublicHubList.config", // "http://ld.yi.org/dc/PublicHubList.config", // "http://www.p2pitalia.com/dclist/Publichublist.config", // "http://www.team-ppm.com/~dawson/PublicHubList.config", // "http://finhublist.no-ip.org/PublicHubList.config", // "http://freespace.morat.net/WUKY/PublicHubList.config", // "http://www.1stleg.com/PublicHubList.config", // 0 //}; /** */ CConfig::CConfig( CString configpath ) { CDir d; if ( configpath.IsEmpty() ) { sConfigPath = CDir::HomeDirPath(); } else { sConfigPath = configpath; } // create the configpath d.SetPath(sConfigPath); d.CreatePath(DCGUI_CONFIG_PATH); sConfigPath += DCGUI_CONFIG_PATH; sConfigPath += DIRSEPARATOR; // create chatlog path d.SetPath(sConfigPath); d.CreatePath(DCGUI_CHATLOG_PATH); // create plugin config path d.CreatePath(DCGUI_PLUGINCONFIG_PATH); // create image path d.CreatePath(DCGUI_IMAGE_PATH); // create filellist path d.CreatePath(DCGUI_FILELIST_PATH); // default settings sNick = "nick"; sSearchNick = "nick_search"; sSpeed = "28.8Kbps"; m_sHost = "127.0.0.1"; m_bExternalIP = true; m_tHostTimeout = time(0); eMode = ecmPASSIVE; eAwayMode = euamNORMAL; iTCPListenPort = 9176; iCryptoListenPort = 19176; iUDPListenPort = 9176; iMaxUpload = 3; lMaxUploadRate = 0; iUserUploadSlots = 1; lMaxDownloadRate = 0; iDownloadQueueTime = 0; iReconnectCount = 3; iReconnectTimeout = 60; bSendMessageOnActiveModeRequest = false; bHubListStoreLocal = true; bForceMoveEnabled = true; bAntiSpam = true; bDescriptionTag = true; m_bUseExtendedHubCount = true; bCheckPrivateAddressSpace = false; bPrivateAddressSpaceOnly = false; bDynamicUploadRate = false; bChatSendToOffline = false; bChatRecvFromOffline = true; bTransferAutoSearch = false; iTransferResendTimeout = 100; iTransferResponseTimeout = 60; eHubOfflineTransferClose = ectNONE; bAutoRecreateShareList = false; bLogFile = false; bLogFinishedDownloads = true; bLogFinishedUploads = true; bLogDetails = false; pBookmarkHubList = new CStringList(); pPublicHubList = new CStringList(); pHubProfileMap = new HubProfileMap(); pOrderedBookmarks = new OrderedBookmarkMap(); pPublicHubList_HostIndex = new CStringList(); pBookmarkHubList_HostIndex = new CStringList(); sFloodOpKickMessage = "Flooding"; m_nPublicHubID = 0; m_nBookHubID = 0; /* plugins disabled by default - leave string empty */ /* m_sDCLibPluginPath = DCLIB_PLUGINDIR; */ m_nReloadHubListTime = 0; m_nRecreateShareListTime = 0; m_bCreateFile = false; m_bDisableHashList = false; /* not a good idea since almost everything * in dclib runs on the same thread! (CManager) */ m_bCompressedTransfers = false; /* The previous hard coded interval was 10 minutes */ m_nAutoSearchInterval = 600; /* Previous valknut value was 16KiB, DC++ increased it to 64KiB */ m_nSmallFileSize = 65536; /** Default to false, share dot files (previous behaviour) */ m_bDontShareDotFiles = false; /* Default to CP1252 (DC++ NMDC English default) */ m_sRemoteEncoding = "WINDOWS-1252"; #if defined(__APPLE__) m_sLocalEncoding = "UTF-8"; #elif defined(WIN32) m_sLocalEncoding = "WINDOWS-1252"; #elif defined(HAVE_NL_LANGINFO) m_sLocalEncoding = nl_langinfo(CODESET); if ( m_sLocalEncoding.IsEmpty() ) { m_sLocalEncoding = "UTF-8"; } #else /** Read local encoding from $LANG */ m_sLocalEncoding = getenv("LANG"); int pos = m_sLocalEncoding.Find('.'); if ( pos == -1 ) { m_sLocalEncoding = "UTF-8"; } else { m_sLocalEncoding = m_sLocalEncoding.Mid(pos + 1); } #endif /** Default to UserIP2 support enabled because it's good */ m_bUserIP2Enabled = true; /** ZPipe support default disabled - it is a useless disaster */ m_bEnableZPipe = false; /** Used for calculating session transfer stats */ m_nStartDownloaded = 0; m_nStartUploaded = 0; /** Default to 40KiB */ m_nReadFileBufferSize = 40960; /* work around bugs in old clients */ m_bDisableADCGetWithoutTTH = false; m_bDisableXMLListWithoutTTH = false; /* obsolete peer extensions, original protocol unaffected */ m_bEnableObsoleteExt = true; /* UserCommand on by default */ m_bEnableUserCommand = true; /* Disabled by default since it cannot encrypt data before Supports including nick */ m_bOldSSLSupport = false; /* All previous versions used fixed 1MiB segments */ m_nMinSegSize = 1048576; /* Disabled, I have no idea how fast you expect to upload */ m_nExtraSlotsRate = 0; /* Not used when rate limit is 0, but set to same as default upload slots */ m_nMaxExtraSlots = 3; /* Enable randomizing of $Supports strings order */ m_bShuffleSupports = true; } /** */ CConfig::~CConfig() { SetInstance(0); delete pPublicHubList; pPublicHubList = 0; delete pOrderedBookmarks; pOrderedBookmarks = 0; delete pBookmarkHubList; pBookmarkHubList = 0; if ( pHubProfileMap ) { for ( HubProfileMap::const_iterator profile_it = pHubProfileMap->begin(); profile_it != pHubProfileMap->end(); ++profile_it ) { delete profile_it->second; } pHubProfileMap->clear(); delete pHubProfileMap; pHubProfileMap = 0; } delete pPublicHubList_HostIndex; pPublicHubList_HostIndex = 0; delete pBookmarkHubList_HostIndex; pBookmarkHubList_HostIndex = 0; } /** */ int CConfig::LoadDCLib() { int err = 0; CString s = sConfigPath + DCLIB_CONFIG; CXml * xml = new CXml(); if ( xml->ParseFile(s) && xml->DocFirstChild() ) { do { if ( (xml->Name() == XML_DCLIB_CONFIG) && xml->FirstChild() ) { ParseDCLibConfig(xml); xml->Parent(); } } while ( xml->NextNode() ); } else { err = -1; } // add default urls only if the list is empty if ( pHubListUrlList.Count() == 0 ) { /* adc:// or adcs:// hubs will not be shown */ DCConfigHubListUrl * hublisturl = new DCConfigHubListUrl(); hublisturl->sUrl = "http://hublist.openhublist.org/hublist.xml.bz2"; hublisturl->bEnabled = true; pHubListUrlList.Add(hublisturl); hublisturl = new DCConfigHubListUrl(); hublisturl->sUrl = "http://hublist.openhublist.org/hublist.config.bz2"; hublisturl->bEnabled = false; pHubListUrlList.Add(hublisturl); hublisturl = new DCConfigHubListUrl(); hublisturl->sUrl = "http://dchublist.com/hublist.xml.bz2"; hublisturl->bEnabled = true; pHubListUrlList.Add(hublisturl); hublisturl = new DCConfigHubListUrl(); hublisturl->sUrl = "http://dchublist.com/hublist.config.bz2"; hublisturl->bEnabled = false; pHubListUrlList.Add(hublisturl); } delete xml; return err; } /** */ int CConfig::SaveDCLib() { int err=0; CString s; CXml * xml = new CXml(); xml->NewDoc(XML_DCLIB_CONFIG); // identify xml->StartNewChild( XML_IDENTIFY ); xml->NewStringChild( XML_NICK, sNick ); xml->NewStringChild( XML_SEARCHNICK, sSearchNick ); xml->NewStringChild( XML_AWAYMESSAGE, sAwayMessage ); xml->NewStringChild( XML_EMAIL, sEMail ); xml->NewStringChild( XML_DESCRIPTION, sDescription ); xml->NewStringChild( XML_AWAY_PREFIX, sAwayPrefix ); xml->NewStringChild( XML_SPEED, sSpeed ); xml->NewBoolChild( XML_ANTISPAM, bAntiSpam ); xml->NewBoolChild( XML_DESCRIPTION_TAG, bDescriptionTag ); xml->NewBoolChild( XML_EXTENDED_HUB_COUNT, m_bUseExtendedHubCount ); xml->Parent(); // logfile xml->StartNewChild( XML_LOGFILE ); xml->NewBoolChild( XML_LOGFILEON, bLogFile ); xml->NewStringChild( XML_LOGFILENAME, sLogFile ); xml->NewBoolChild( XML_LOGDOWNLOADS, bLogFinishedDownloads ); xml->NewBoolChild( XML_LOGUPLOADS, bLogFinishedUploads ); xml->NewBoolChild( XML_LOGDETAILS, bLogDetails ); xml->NewStringChild( XML_FLOODOPKICKMESSAGE, sFloodOpKickMessage ); xml->Parent(); // transfer xml->StartNewChild( XML_TRANSFER ); xml->NewStringChild( XML_DOWNLOADFOLDER, sDownloadFolder ); xml->NewStringChild( XML_DOWNLOADFINISHEDFOLDER, sDownloadFinishedFolder ); xml->NewBoolChild( XML_TRANSFER_AUTOSEARCH, bTransferAutoSearch ); xml->NewNumericChild( XML_MINSEGSIZE, m_nMinSegSize ); DCConfigShareFolder * csf = 0; while( (csf=SharedFolders.Next(csf)) != 0 ) { xml->StartNewChild( XML_SHAREDFOLDER ); xml->NewStringChild( XML_PATH, csf->m_sPath ); xml->NewStringChild( XML_ALIAS, csf->m_sAlias ); xml->Parent(); } xml->NewBoolChild( XML_AUTORECREATESHARELIST, bAutoRecreateShareList ); xml->NewNumericChild( XML_RECREATE_SHARELIST_TIME, m_nRecreateShareListTime ); xml->NewNumericChild( XML_MAXUPLOAD, iMaxUpload ); xml->NewNumericChild( XML_USER_UPLOAD_SLOTS, iUserUploadSlots ); xml->NewNumericChild( XML_MAXUPLOADRATE, lMaxUploadRate ); xml->NewNumericChild( XML_MAXDOWNLOADRATE, lMaxDownloadRate ); xml->NewNumericChild( XML_EXTRA_SLOTS_RATE, m_nExtraSlotsRate ); xml->NewNumericChild( XML_MAX_EXTRA_SLOTS, m_nMaxExtraSlots ); xml->NewNumericChild( XML_DOWNLOADQUEUETIME, iDownloadQueueTime ); xml->NewBoolChild( XML_DYNAMICUPLOADRATE, bDynamicUploadRate ); xml->NewStringChild( XML_TRANSFER_CERT, m_sTransferCert ); xml->NewStringChild( XML_TRANSFER_KEY, m_sTransferKey ); xml->NewBoolChild( XML_OLD_SSL_SUPPORT, m_bOldSSLSupport ); xml->NewNumericChild( XML_HUBOFFLINE_TRANSFERCLOSE, eHubOfflineTransferClose ); xml->NewNumericChild( XML_TRAFFIC_RX, CSocket::m_Traffic.GetTraffic(ettRX) ); xml->NewNumericChild( XML_TRAFFIC_TX, CSocket::m_Traffic.GetTraffic(ettTX) ); xml->NewNumericChild( XML_TRAFFIC_DATA_RX, CSocket::m_Traffic.GetTraffic(ettDATARX) ); xml->NewNumericChild( XML_TRAFFIC_DATA_TX, CSocket::m_Traffic.GetTraffic(ettDATATX) ); xml->NewNumericChild( XML_TRAFFIC_CONTROL_RX, CSocket::m_Traffic.GetTraffic(ettCONTROLRX) ); xml->NewNumericChild( XML_TRAFFIC_CONTROL_TX, CSocket::m_Traffic.GetTraffic(ettCONTROLTX) ); xml->Parent(); // connection xml->StartNewChild( XML_CONNECTION ); if ( eMode == ecmPASSIVE ) s = XML_MODE_PASSIVE; else s = XML_MODE_ACTIVE; xml->NewStringChild( XML_MODE, s ); xml->NewNumericChild( XML_TCPLISTENPORT, iTCPListenPort ); xml->NewNumericChild( XML_CRYPTOLISTENPORT, iCryptoListenPort ); xml->NewNumericChild( XML_UDPLISTENPORT, iUDPListenPort ); xml->NewBoolChild( XML_EXTERNALIP, m_bExternalIP ); xml->NewStringChild( XML_IP, m_sHost ); xml->NewStringChild( XML_LISTENHOST, m_sListenHost ); xml->NewBoolChild( XML_SENDMESSAGEONACTIVEMODEREQUEST, bSendMessageOnActiveModeRequest ); xml->NewBoolChild( XML_CHECKPRIVATEADDRESSSPACE, bCheckPrivateAddressSpace ); xml->NewBoolChild( XML_PRIVATEADDRESSSPACEONLY, bPrivateAddressSpaceOnly ); xml->NewBoolChild( XML_USERIP2_ENABLED, m_bUserIP2Enabled ); xml->Parent(); // hublisturl xml->StartNewChild( XML_HUBLISTURL ); DCConfigHubListUrl *hublisturl = 0; while( (hublisturl=pHubListUrlList.Next(hublisturl)) != 0 ) { xml->StartNewChild( XML_URL ); xml->NewStringChild( XML_NAME, hublisturl->sUrl ); xml->NewBoolChild( XML_ENABLED, hublisturl->bEnabled ); xml->Parent(); } xml->Parent(); // other xml->StartNewChild( XML_OTHER ); xml->NewNumericChild( XML_RECONNECTCOUNT, iReconnectCount ); xml->NewNumericChild( XML_RECONNECTTIMEOUT, iReconnectTimeout ); xml->NewNumericChild( XML_TRANSFERRESPONSETIMEOUT, iTransferResponseTimeout ); xml->NewNumericChild( XML_TRANSFERRESENDTIMEOUT, iTransferResendTimeout ); xml->NewStringChild( XML_DCLIB_PLUGINPATH, m_sDCLibPluginPath ); xml->NewBoolChild( XML_CHATSENDTOOFFLINE, bChatSendToOffline ); xml->NewBoolChild( XML_CHATRECVFROMOFFLINE, bChatRecvFromOffline ); xml->NewBoolChild( XML_HUBLISTSTORELOCAL, bHubListStoreLocal ); xml->NewNumericChild( XML_RELOAD_HUBLIST_TIME, m_nReloadHubListTime ); xml->NewBoolChild( XML_FORCEMOVEENABLED, bForceMoveEnabled ); xml->NewBoolChild( XML_DISABLEHASHLIST, m_bDisableHashList ); xml->NewBoolChild( XML_COMPRESSEDTRANSFERS, m_bCompressedTransfers ); xml->NewBoolChild( XML_ENABLE_ZPIPE, m_bEnableZPipe ); xml->NewNumericChild( XML_AUTOSEARCHINTERVAL, m_nAutoSearchInterval ); xml->NewNumericChild( XML_SMALLFILESIZE, m_nSmallFileSize ); xml->NewBoolChild( XML_DONTSHAREDOTFILES, m_bDontShareDotFiles ); xml->NewStringChild( XML_REMOTE_ENCODING, m_sRemoteEncoding ); xml->NewNumericChild( XML_READ_FILE_BUFFER_SIZE, m_nReadFileBufferSize ); xml->NewBoolChild( XML_NO_ADCGET_WITHOUT_TTH, m_bDisableADCGetWithoutTTH ); xml->NewBoolChild( XML_NO_XMLLIST_WITHOUT_TTH, m_bDisableXMLListWithoutTTH ); xml->NewBoolChild( XML_OBSOLETE_EXT, m_bEnableObsoleteExt ); xml->NewBoolChild( XML_SHUFFLE_SUPPORTS, m_bShuffleSupports ); xml->NewBoolChild( XML_ENABLE_USER_COMMAND, m_bEnableUserCommand ); xml->Parent(); // save file s = sConfigPath + DCLIB_CONFIG; if ( xml->SaveConfigXmlViaTemp(s) == -1 ) { err = -1; } delete xml; return err; } /** */ int CConfig::LoadDCHub() { // load public hub list CString s = sConfigPath + DCHUB_CONFIG; CXml * xml = new CXml(); if ( xml->ParseFile(s) && xml->DocFirstChild() ) { do { if ( (xml->Name() == XML_DCHUB_CONFIG) && xml->FirstChild() ) { ParseDCHubConfig(xml); xml->Parent(); } } while ( xml->NextNode() ); } // load bookmark hub list s = sConfigPath + DCBOOKHUB_CONFIG; if ( xml->ParseFile(s) && xml->DocFirstChild() ) { do { if ( (xml->Name() == XML_DCBOOKHUB_CONFIG) && xml->FirstChild() ) { ParseDCBookHubConfig(xml); xml->Parent(); } } while ( xml->NextNode() ); } delete xml; // add default hub entry if ( pBookmarkHubList->Count() == 0 ) { DCConfigHubItem *hubitem = new DCConfigHubItem(); hubitem->m_nID = 1; hubitem->m_sName = "Valknut/DCLib Chat"; hubitem->m_sHost = "valknut.dyndns.info:59176"; hubitem->m_sDescription = "Valknut/DCLib Chat"; pBookmarkHubList->Add(hubitem->m_sName,hubitem); pBookmarkHubList_HostIndex->Add(hubitem->m_sHost.ToUpper(),new CString(hubitem->m_sName)); (*pOrderedBookmarks)[0] = hubitem; hubitem->m_nPosition = 0; // save bookmark list SaveDCBookHub(); } return 0; } /** */ int CConfig::SaveDCHub() { int err=0; SaveDCPublicHub(); SaveDCBookHub(); return err; } /** */ int CConfig::SaveDCPublicHub() { int err=0; CString s; CXml * xml = new CXml(); DCConfigHubItem *hubitem; xml->NewDoc( XML_DCHUB_CONFIG ); // bookmarks xml->StartNewChild( XML_SERVER ); // store public hub list if ( bHubListStoreLocal ) { hubitem = 0; while( pPublicHubList->Next(&hubitem) != 0 ) { xml->StartNewChild( XML_PUBLIC ); xml->NewNumericChild( XML_ID, hubitem->m_nID ); xml->NewStringChild( XML_NAME, hubitem->m_sName ); xml->NewStringChild( XML_HOST, hubitem->m_sHost ); xml->NewStringChild( XML_DESCRIPTION, hubitem->m_sDescription ); xml->NewNumericChild( XML_USERCOUNT, hubitem->m_nUserCount ); xml->NewStringChild( XML_COUNTRY, hubitem->m_sCountry ); xml->NewStringChild( XML_EXTRA, hubitem->m_sExtra ); xml->NewNumericChild( XML_SHARED, hubitem->m_nShared ); xml->NewNumericChild( XML_MINSHARE, hubitem->m_nMinShare ); xml->Parent(); } } xml->Parent(); // save file s = sConfigPath + DCHUB_CONFIG; if ( xml->SaveConfigXmlViaTemp(s) == -1 ) { err = -1; } delete xml; return err; } /** */ int CConfig::SaveDCBookHub() { int err=0; CString s; CXml * xml = new CXml(); DCConfigHubItem *hubitem; xml->NewDoc( XML_DCBOOKHUB_CONFIG ); // bookmarks xml->StartNewChild( XML_SERVER ); hubitem = 0; for ( OrderedBookmarkMap::const_iterator it = pOrderedBookmarks->begin(); it != pOrderedBookmarks->end(); ++it ) { hubitem = it->second; /* of course if should have been XML_BOOKMARK but changing it would cause more problems */ xml->StartNewChild( XML_PUBLIC ); xml->NewNumericChild( XML_ID, hubitem->m_nID ); xml->NewStringChild( XML_NAME, hubitem->m_sName ); xml->NewStringChild( XML_HOST, hubitem->m_sHost ); xml->NewStringChild( XML_DESCRIPTION, hubitem->m_sDescription ); xml->NewStringChild( XML_PROFILE_NAME, hubitem->m_sProfile ); xml->Parent(); } xml->Parent(); // save file s = sConfigPath + DCBOOKHUB_CONFIG; if ( xml->SaveConfigXmlViaTemp(s) == -1 ) { err = -1; } delete xml; return err; } /** */ int CConfig::LoadDCTra( CStringList > * queue, CStringList * chunks ) { CXml * xml = new CXml(); CString s, xml_name1, xml_name2; CStringList * sl1; DCTransferQueueObject * tqo2; DCHubObject * HubObject; s = sConfigPath + DCTRA_CONFIG; if ( !(xml->ParseFile(s) && xml->DocFirstChild()) ) { delete xml; return -1; } do { if ( (xml->Name() == XML_DCTRA_CONFIG) && xml->FirstChild() ) { do { if ( (xml->Name() == XML_TRANSFER) && xml->FirstChild() ) { DCTransferQueueObject * TransferObject = new DCTransferQueueObject(); TransferObject->eState = etwsIDLE; TransferObject->iConnections = 0; do { xml_name1 = xml->Name(); if ( xml_name1 == XML_NICK ) TransferObject->sNick = xml->Content(); else if ( xml_name1 == XML_HUBNAME ) TransferObject->sHubName = xml->Content(); else if ( xml_name1 == XML_HUBHOST ) TransferObject->sHubHost = xml->Content(); else if ( (xml_name1 == XML_HUB) && xml->FirstChild() ) { HubObject = new DCHubObject(); do { xml_name2 = xml->Name(); if ( xml_name2 == XML_HUBNAME ) HubObject->m_sHubName = xml->Content(); else if ( xml_name2 == XML_HUBHOST ) HubObject->m_sHubHost = xml->Content(); else if ( xml_name2 == XML_ACTIVE ) HubObject->m_bActive = xml->GetBoolChild(); } while ( xml->NextNode() ); xml->Parent(); TransferObject->pHubList.Add(HubObject); } else if ( (xml_name1 == XML_FILE) && xml->FirstChild() ) { DCTransferFileObject * TransferFileObject = new DCTransferFileObject(); do { xml_name2 = xml->Name(); if ( xml_name2 == XML_REMOTEFILE ) TransferFileObject->m_sRemoteFile = xml->Content(); else if ( xml_name2 == XML_LOCALFILENAME ) TransferFileObject->m_sLocalFileName = xml->Content(); else if ( xml_name2 == XML_SIZE ) TransferFileObject->m_nSize = xml->Content().asULL(); else if ( xml_name2 == XML_PRIORITY ) TransferFileObject->m_nPriority = xml->Content().asINT(); else if ( xml_name2 == XML_STATE ) TransferFileObject->m_eState = (eTransferFileState)xml->Content().asINT(); else if ( xml_name2 == XML_LOCALPATH ) TransferFileObject->m_sLocalPath = xml->Content(); else if ( xml_name2 == XML_LOCALFILE ) TransferFileObject->m_sLocalFile = xml->Content(); else if ( xml_name2 == XML_TEMPHASH ) TransferFileObject->m_stHash = xml->Content(); else if ( xml_name2 == XML_HASH ) TransferFileObject->m_sHash = xml->Content(); else if ( xml_name2 == XML_MEDIUM ) { if ( xml->Content() == XML_MEDIUM_BUFFER ) TransferFileObject->m_eMedium = eltBUFFER; else TransferFileObject->m_eMedium = eltFILE; } else if ( xml_name2 == XML_MULTI ) TransferFileObject->m_bMulti = xml->GetBoolChild(); else if ( xml_name2 == XML_JUMPTO ) TransferFileObject->m_sJumpTo = xml->Content(); else if ( xml_name2 == XML_DL_FOLDERS && xml->FirstChild() ) { TransferFileObject->m_pDirList = new std::list(); do { if ( xml->Name() == XML_PATH ) { TransferFileObject->m_pDirList->push_back( xml->Content() ); } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); xml->Parent(); // fix state if ( TransferFileObject->m_eState == etfsTRANSFER ) TransferFileObject->m_eState = etfsNONE; TransferObject->pTransferFileList.Add( TransferFileObject->m_sRemoteFile, TransferFileObject ); } } while ( xml->NextNode() ); xml->Parent(); if ( TransferObject->pTransferFileList.Count() == 0 ) { delete TransferObject; } else { if ( queue->Get( TransferObject->sNick, &sl1 ) == 0 ) { if ( sl1->Get( TransferObject->sHubName, &tqo2 ) == 0 ) { printf("load queue: error double entrys !!!!\n"); } else { sl1->Add( TransferObject->sHubName, TransferObject ); } } else { sl1 = new CStringList(); sl1->Add( TransferObject->sHubName, TransferObject ); queue->Add( TransferObject->sNick, sl1 ); } } } else if ( (xml->Name() == XML_FILECHUNK) && xml->FirstChild() ) { DCFileChunkObject * FileChunkObject = new DCFileChunkObject(); do { xml_name2 = xml->Name(); if ( xml_name2 == XML_LOCALFILE ) FileChunkObject->m_sLocalFile = xml->Content(); else if ( xml_name2 == XML_TEMPHASH ) FileChunkObject->m_stHash = xml->Content(); else if ( xml_name2 == XML_HASH ) FileChunkObject->m_sHash = xml->Content(); else if ( xml_name2 == XML_SIZE ) FileChunkObject->m_nSize = xml->Content().asULL(); else if ( xml_name2 == XML_SIZEDONE ) FileChunkObject->m_nSizeDone = xml->Content().asULL(); else if ( xml_name2 == XML_REFCOUNT ) FileChunkObject->m_nReferenceCount = xml->Content().asINT(); else if ( xml_name2 == XML_MULTI ) FileChunkObject->m_bMulti = xml->GetBoolChild(); else if ( (xml_name2 == XML_CHUNK) && xml->FirstChild() ) { DCChunkObject * ChunkObject = new DCChunkObject(); do { if ( xml->Name() == XML_START ) ChunkObject->m_nStart = xml->Content().asULL(); else if ( xml->Name() == XML_END ) ChunkObject->m_nEnd = xml->Content().asULL(); } while ( xml->NextNode() ); xml->Parent(); FileChunkObject->m_Chunks.Add(ChunkObject); } } while ( xml->NextNode() ); xml->Parent(); chunks->Add( FileChunkObject->m_sLocalFile, FileChunkObject ); } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); delete xml; return 0; } /** */ int CConfig::SaveDCTra( CStringList > * queue, CStringList * chunks ) { int err = 0; CString s; DCTransferQueueObject * TransferObject; DCFileChunkObject * FileChunkObject; DCChunkObject * ChunkObject; DCHubObject * HubObject; CStringList * sl1; CXml * xml = new CXml(); xml->NewDoc( XML_DCTRA_CONFIG ); // nick,stringlist sl1 = 0; while(queue->Next(&sl1)) { // hubname,transferobject TransferObject = 0; while(sl1->Next(&TransferObject)) { if ( TransferObject->pTransferFileList.Count() == 0 ) { continue; } xml->StartNewChild( XML_TRANSFER ); // store nick,hubhost and hubname xml->NewStringChild( XML_NICK, TransferObject->sNick); xml->NewStringChild( XML_HUBNAME, TransferObject->sHubName); xml->NewStringChild( XML_HUBHOST, TransferObject->sHubHost); HubObject = 0; while( (HubObject=TransferObject->pHubList.Next(HubObject)) != 0 ) { xml->StartNewChild( XML_HUB ); xml->NewStringChild( XML_HUBNAME, HubObject->m_sHubName ); xml->NewStringChild( XML_HUBHOST, HubObject->m_sHubHost ); xml->NewBoolChild( XML_ACTIVE, HubObject->m_bActive ); xml->Parent(); } // save files DCTransferFileObject * TransferFileObject = 0; while(TransferObject->pTransferFileList.Next(&TransferFileObject)) { xml->StartNewChild( XML_FILE ); xml->NewStringChild( XML_REMOTEFILE, TransferFileObject->m_sRemoteFile ); xml->NewStringChild( XML_LOCALFILENAME, TransferFileObject->m_sLocalFileName ); xml->NewNumericChild( XML_SIZE, TransferFileObject->m_nSize ); xml->NewNumericChild( XML_PRIORITY, TransferFileObject->m_nPriority ); xml->NewNumericChild( XML_STATE, TransferFileObject->m_eState ); xml->NewStringChild( XML_LOCALFILE, TransferFileObject->m_sLocalFile ); xml->NewStringChild( XML_LOCALPATH, TransferFileObject->m_sLocalPath ); if ( TransferFileObject->m_stHash.NotEmpty() ) { xml->NewStringChild( XML_TEMPHASH, TransferFileObject->m_stHash ); } if ( TransferFileObject->m_sHash.NotEmpty() ) { xml->NewStringChild( XML_HASH, TransferFileObject->m_sHash ); } if(TransferFileObject->m_eMedium==eltBUFFER) s = XML_MEDIUM_BUFFER; else s = XML_MEDIUM_FILE; xml->NewStringChild( XML_MEDIUM, s ); xml->NewBoolChild( XML_MULTI, TransferFileObject->m_bMulti ); if ( TransferFileObject->m_sJumpTo.NotEmpty() ) { xml->NewStringChild( XML_JUMPTO, TransferFileObject->m_sJumpTo ); } if ( TransferFileObject->m_pDirList ) { xml->StartNewChild( XML_DL_FOLDERS ); for ( std::list::const_iterator it = TransferFileObject->m_pDirList->begin(); it != TransferFileObject->m_pDirList->end(); ++it ) { xml->NewStringChild( XML_PATH, *it ); } xml->Parent(); } xml->Parent(); } xml->Parent(); } } FileChunkObject = 0; while( chunks->Next(&FileChunkObject) ) { xml->StartNewChild( XML_FILECHUNK ); xml->NewStringChild( XML_LOCALFILE, FileChunkObject->m_sLocalFile ); xml->NewStringChild( XML_TEMPHASH, FileChunkObject->m_stHash ); xml->NewStringChild( XML_HASH, FileChunkObject->m_sHash ); xml->NewNumericChild( XML_SIZE, FileChunkObject->m_nSize ); xml->NewNumericChild( XML_SIZEDONE, FileChunkObject->m_nSizeDone ); xml->NewNumericChild( XML_REFCOUNT, FileChunkObject->m_nReferenceCount ); xml->NewBoolChild( XML_MULTI, FileChunkObject->m_bMulti ); ChunkObject = 0; while( (ChunkObject=FileChunkObject->m_Chunks.Next(ChunkObject)) != 0 ) { xml->StartNewChild( XML_CHUNK ); xml->NewNumericChild( XML_START, ChunkObject->m_nStart ); xml->NewNumericChild( XML_END, ChunkObject->m_nEnd ); xml->Parent(); } xml->Parent(); } s = sConfigPath + DCTRA_CONFIG; if ( xml->SaveConfigXmlViaTemp(s) == -1 ) { err = -1; } delete xml; return err; } /** */ CString CConfig::ParseVersion( CString s ) { CString release; CXml * xml = new CXml(); if ( xml->ParseMemory( s.Data(), s.Length() ) && xml->DocFirstChild() ) { do { if ( (xml->Name() == XML_DC) && xml->FirstChild() ) { do { if ( (xml->Name() == XML_VERSION) && xml->FirstChild() ) { do { if ( xml->Name() == XML_RELEASE ) { release = xml->Content(); } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); } delete xml; return release; } /** */ void CConfig::ParseDCHubConfig( CXml * xml ) { DCConfigHubItem * hubitem; CString xml_name; do { /* parse server entrys */ if ( (xml->Name() == XML_SERVER) && xml->FirstChild() ) { do { // public hub list if ( (xml->Name() == XML_PUBLIC) && xml->FirstChild() ) { hubitem = new DCConfigHubItem(); do { xml_name = xml->Name(); if ( xml_name == XML_NAME ) hubitem->m_sName = xml->Content(); else if ( xml_name == XML_HOST ) hubitem->m_sHost = xml->Content(); else if ( xml_name == XML_DESCRIPTION ) hubitem->m_sDescription = xml->Content(); else if ( xml_name == XML_USERCOUNT ) hubitem->m_nUserCount = xml->Content().asULL(); else if ( xml_name == XML_COUNTRY ) hubitem->m_sCountry = xml->Content(); else if ( xml_name == XML_EXTRA ) hubitem->m_sExtra = xml->Content(); else if ( xml_name == XML_SHARED ) hubitem->m_nShared = xml->Content().asULL(); else if ( xml_name == XML_MINSHARE ) hubitem->m_nMinShare = xml->Content().asULL(); } while ( xml->NextNode() ); xml->Parent(); // remove spaces hubitem->m_sHost = hubitem->m_sHost.Replace(" ",""); // no port found if ( hubitem->m_sHost.Find(':') == -1 ) { // add default port hubitem->m_sHost += ":411"; } hubitem->m_nID = ++m_nPublicHubID; pPublicHubList->Add(hubitem->m_sName.ToUpper(),hubitem); pPublicHubList_HostIndex->Add(hubitem->m_sHost.ToUpper(),new CString(hubitem->m_sName)); } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); } /** */ void CConfig::ParseDCBookHubConfig( CXml * xml ) { DCConfigHubItem * hubitem; CString xml_name; do { /* parse server entrys */ if ( (xml->Name() == XML_SERVER) && xml->FirstChild() ) { do { // bookmark hub list if ( (xml->Name() == XML_PUBLIC) && xml->FirstChild() ) { hubitem = new DCConfigHubItem(); do { xml_name = xml->Name(); if ( xml_name == XML_NAME ) hubitem->m_sName = xml->Content(); else if ( xml_name == XML_HOST ) hubitem->m_sHost = xml->Content(); else if ( xml_name == XML_DESCRIPTION ) hubitem->m_sDescription = xml->Content(); else if ( xml_name == XML_PROFILE_NAME ) hubitem->m_sProfile = xml->Content(); } while ( xml->NextNode() ); xml->Parent(); // remove spaces hubitem->m_sHost = hubitem->m_sHost.Replace(" ",""); // no port found if ( hubitem->m_sHost.Find(':') == -1 ) { // add default port hubitem->m_sHost += ":411"; } hubitem->m_nID = ++m_nBookHubID; pBookmarkHubList->Add(hubitem->m_sName,hubitem); pBookmarkHubList_HostIndex->Add(hubitem->m_sHost.ToUpper(),new CString(hubitem->m_sName)); hubitem->m_nPosition = pOrderedBookmarks->size(); (*pOrderedBookmarks)[hubitem->m_nPosition] = hubitem; } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); } /** */ void CConfig::ParseDCLibConfig( CXml * xml ) { CString xml_name1, xml_name2; do { xml_name1 = xml->Name(); /* parse identify entrys */ if ( (xml_name1 == XML_IDENTIFY) && xml->FirstChild() ) { do { xml_name2 = xml->Name(); if ( xml_name2 == XML_NICK ) sNick = xml->Content(); else if ( xml_name2 == XML_SEARCHNICK ) sSearchNick = xml->Content(); else if ( xml_name2 == XML_AWAYMESSAGE ) sAwayMessage = xml->Content(); else if ( xml_name2 == XML_EMAIL ) sEMail = xml->Content(); else if ( xml_name2 == XML_ANTISPAM ) bAntiSpam = xml->GetBoolChild(); else if ( xml_name2 == XML_DESCRIPTION ) sDescription = xml->Content(); else if ( xml_name2 == XML_AWAY_PREFIX ) sAwayPrefix = xml->Content(); else if ( xml_name2 == XML_DESCRIPTION_TAG ) bDescriptionTag = xml->GetBoolChild(); else if ( xml_name2 == XML_SPEED ) sSpeed = xml->Content(); else if ( xml_name2 == XML_EXTENDED_HUB_COUNT ) m_bUseExtendedHubCount = xml->GetBoolChild(); } while ( xml->NextNode() ); xml->Parent(); } /* parse logfile entry */ else if ( (xml_name1 == XML_LOGFILE) && xml->FirstChild() ) { do { xml_name2 = xml->Name(); if ( xml_name2 == XML_LOGFILENAME ) sLogFile = xml->Content(); else if ( xml_name2 == XML_LOGFILEON ) bLogFile = xml->GetBoolChild(); else if ( xml_name2 == XML_LOGDOWNLOADS ) bLogFinishedDownloads = xml->GetBoolChild(); else if ( xml_name2 == XML_LOGUPLOADS ) bLogFinishedUploads = xml->GetBoolChild(); else if ( xml_name2 == XML_LOGDETAILS ) bLogDetails = xml->GetBoolChild(); } while ( xml->NextNode() ); xml->Parent(); } else if ( (xml_name1 == XML_SECURITY) && xml->FirstChild() ) { do { if ( xml->Name() == XML_FLOODOPKICKMESSAGE ) sFloodOpKickMessage = xml->Content(); } while ( xml->NextNode() ); xml->Parent(); } /* parse transfer entrys */ else if ( (xml_name1 == XML_TRANSFER) && xml->FirstChild() ) { do { xml_name2 = xml->Name(); if ( xml_name2 == XML_DOWNLOADFOLDER ) sDownloadFolder = xml->Content(); else if ( xml_name2 == XML_DOWNLOADFINISHEDFOLDER ) sDownloadFinishedFolder = xml->Content(); else if ( xml_name2 == XML_TRANSFER_AUTOSEARCH ) bTransferAutoSearch = xml->GetBoolChild(); else if ( xml_name2 == XML_MINSEGSIZE ) m_nMinSegSize = xml->Content().asULL(); else if ( (xml_name2 == XML_SHAREDFOLDER) && xml->FirstChild() ) { DCConfigShareFolder * csf = new DCConfigShareFolder(); do { if ( xml->Name() == XML_PATH ) csf->m_sPath = xml->Content(); else if ( xml->Name() == XML_ALIAS ) csf->m_sAlias = xml->Content(); } while ( xml->NextNode() ); xml->Parent(); if ( csf->m_sPath.IsEmpty() || csf->m_sAlias.IsEmpty() ) delete csf; else SharedFolders.Add( csf ); } else if ( xml_name2 == XML_AUTORECREATESHARELIST ) bAutoRecreateShareList = xml->GetBoolChild(); else if ( xml_name2 == XML_RECREATE_SHARELIST_TIME ) m_nRecreateShareListTime = xml->Content().asINT(); else if ( xml_name2 == XML_MAXUPLOAD ) iMaxUpload = xml->Content().asINT(); else if ( xml_name2 == XML_USER_UPLOAD_SLOTS ) iUserUploadSlots = xml->Content().asINT(); else if ( xml_name2 == XML_MAXUPLOADRATE ) lMaxUploadRate = xml->Content().asULL(); else if ( xml_name2 == XML_MAXDOWNLOADRATE ) lMaxDownloadRate = xml->Content().asULL(); else if ( xml_name2 == XML_EXTRA_SLOTS_RATE ) m_nExtraSlotsRate = xml->Content().asULL(); else if ( xml_name2 == XML_MAX_EXTRA_SLOTS ) m_nMaxExtraSlots = xml->Content().asINT(); else if ( xml_name2 == XML_DOWNLOADQUEUETIME ) iDownloadQueueTime = xml->Content().asINT(); else if ( xml_name2 == XML_DYNAMICUPLOADRATE ) bDynamicUploadRate = xml->GetBoolChild(); else if ( xml_name2 == XML_TRANSFER_CERT ) m_sTransferCert = xml->Content(); else if ( xml_name2 == XML_TRANSFER_KEY ) m_sTransferKey = xml->Content(); else if ( xml_name2 == XML_OLD_SSL_SUPPORT ) m_bOldSSLSupport = xml->GetBoolChild(); else if ( xml_name2 == XML_HUBOFFLINE_TRANSFERCLOSE ) eHubOfflineTransferClose = (eCloseType)xml->Content().asINT(); else if ( xml_name2 == XML_TRAFFIC_RX ) { m_nStartDownloaded = xml->Content().asULL(); CSocket::m_Traffic.AddTraffic( ettRX, m_nStartDownloaded ); } else if ( xml_name2 == XML_TRAFFIC_TX ) { m_nStartUploaded = xml->Content().asULL(); CSocket::m_Traffic.AddTraffic( ettTX, m_nStartUploaded ); } else if ( xml_name2 == XML_TRAFFIC_DATA_RX ) CSocket::m_Traffic.AddTraffic( ettDATARX, xml->Content().asULL() ); else if ( xml_name2 == XML_TRAFFIC_DATA_TX ) CSocket::m_Traffic.AddTraffic( ettDATATX, xml->Content().asULL() ); else if ( xml_name2 == XML_TRAFFIC_CONTROL_RX ) CSocket::m_Traffic.AddTraffic( ettCONTROLRX, xml->Content().asULL() ); else if ( xml_name2 == XML_TRAFFIC_CONTROL_TX ) CSocket::m_Traffic.AddTraffic( ettCONTROLTX, xml->Content().asULL() ); } while ( xml->NextNode() ); xml->Parent(); } /* parse connection entrys */ else if ( (xml_name1 == XML_CONNECTION) && xml->FirstChild() ) { do { xml_name2 = xml->Name(); if ( xml_name2 == XML_MODE ) { if ( xml->Content() == XML_MODE_PASSIVE ) eMode = ecmPASSIVE; else eMode = ecmACTIVE; } else if ( xml_name2 == XML_TCPLISTENPORT ) iTCPListenPort = xml->Content().asINT(); else if ( xml_name2 == XML_CRYPTOLISTENPORT ) iCryptoListenPort = xml->Content().asINT(); else if ( xml_name2 == XML_UDPLISTENPORT ) iUDPListenPort = xml->Content().asINT(); else if ( xml_name2 == XML_IP ) m_sHost = xml->Content(); else if ( xml_name2 == XML_LISTENHOST ) m_sListenHost = xml->Content(); else if ( xml_name2 == XML_EXTERNALIP ) m_bExternalIP = xml->GetBoolChild(); else if ( xml_name2 == XML_SENDMESSAGEONACTIVEMODEREQUEST ) bSendMessageOnActiveModeRequest = xml->GetBoolChild(); else if ( xml_name2 == XML_CHECKPRIVATEADDRESSSPACE ) bCheckPrivateAddressSpace = xml->GetBoolChild(); else if ( xml_name2 == XML_PRIVATEADDRESSSPACEONLY ) bPrivateAddressSpaceOnly = xml->GetBoolChild(); else if ( xml_name2 == XML_USERIP2_ENABLED ) m_bUserIP2Enabled = xml->GetBoolChild(); } while ( xml->NextNode() ); xml->Parent(); } /* other entrys */ else if ( (xml_name1 == XML_OTHER) && xml->FirstChild() ) { do { xml_name2 = xml->Name(); if ( xml_name2 == XML_HUBLISTSTORELOCAL ) bHubListStoreLocal = xml->GetBoolChild(); else if ( xml_name2 == XML_RECONNECTCOUNT ) iReconnectCount = xml->Content().asINT(); else if ( xml_name2 == XML_RECONNECTTIMEOUT ) iReconnectTimeout = xml->Content().asINT(); else if ( xml_name2 == XML_TRANSFERRESPONSETIMEOUT ) iTransferResponseTimeout = xml->Content().asINT(); else if ( xml_name2 == XML_TRANSFERRESENDTIMEOUT ) iTransferResendTimeout = xml->Content().asINT(); else if ( xml_name2 == XML_FORCEMOVEENABLED ) bForceMoveEnabled = xml->GetBoolChild(); else if ( xml_name2 == XML_DCLIB_PLUGINPATH ) m_sDCLibPluginPath = xml->Content(); else if ( xml_name2 == XML_CHATSENDTOOFFLINE ) bChatSendToOffline = xml->GetBoolChild(); else if ( xml_name2 == XML_CHATRECVFROMOFFLINE ) bChatRecvFromOffline = xml->GetBoolChild(); else if ( xml_name2 == XML_RELOAD_HUBLIST_TIME ) m_nReloadHubListTime = xml->Content().asINT(); else if ( xml_name2 == XML_DISABLEHASHLIST ) m_bDisableHashList = xml->GetBoolChild(); else if ( xml_name2 == XML_COMPRESSEDTRANSFERS ) m_bCompressedTransfers = xml->GetBoolChild(); else if ( xml_name2 == XML_ENABLE_ZPIPE ) m_bEnableZPipe = xml->GetBoolChild(); else if ( xml_name2 == XML_AUTOSEARCHINTERVAL ) m_nAutoSearchInterval = xml->Content().asLONG(); else if ( xml_name2 == XML_SMALLFILESIZE ) m_nSmallFileSize = xml->Content().asULL(); else if ( xml_name2 == XML_DONTSHAREDOTFILES ) m_bDontShareDotFiles = xml->GetBoolChild(); else if ( xml_name2 == XML_REMOTE_ENCODING ) m_sRemoteEncoding = xml->Content(); else if ( xml_name2 == XML_READ_FILE_BUFFER_SIZE ) m_nReadFileBufferSize = xml->Content().asLONG(); else if ( xml_name2 == XML_NO_ADCGET_WITHOUT_TTH ) m_bDisableADCGetWithoutTTH = xml->GetBoolChild(); else if ( xml_name2 == XML_NO_XMLLIST_WITHOUT_TTH ) m_bDisableXMLListWithoutTTH = xml->GetBoolChild(); else if ( xml_name2 == XML_OBSOLETE_EXT ) m_bEnableObsoleteExt = xml->GetBoolChild(); else if ( xml_name2 == XML_SHUFFLE_SUPPORTS ) m_bShuffleSupports = xml->GetBoolChild(); else if ( xml_name2 == XML_ENABLE_USER_COMMAND ) m_bEnableUserCommand = xml->GetBoolChild(); } while ( xml->NextNode() ); xml->Parent(); } /* parse server entrys */ else if ( (xml_name1 == XML_HUBLISTURL) && xml->FirstChild() ) { do { if ( (xml->Name() == XML_URL) && xml->FirstChild() ) { DCConfigHubListUrl * hublisturl = new DCConfigHubListUrl(); do { xml_name2 = xml->Name(); if ( xml_name2 == XML_NAME ) hublisturl->sUrl = xml->Content(); else if ( xml_name2 == XML_ENABLED ) hublisturl->bEnabled = xml->GetBoolChild(); } while ( xml->NextNode() ); xml->Parent(); if ( hublisturl->sUrl.IsEmpty() ) { delete hublisturl; } else { pHubListUrlList.Add(hublisturl); } } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); } /** */ CString CConfig::GetEMail( bool raw ) { m_Mutex.Lock(); CString s = sEMail; if ( (raw == false) && bAntiSpam ) { s = s.Replace( '@', " [at] " ); s = s.Replace( '.', " [dot] " ); } m_Mutex.UnLock(); return s; } /** */ CString CConfig::GetDescription( bool raw, CString hubname, CString hubhost ) { DCConfigHubProfile pConfigHubProfile; CString s; bool tag = false; bool prof = false; bool extHubCount = true; enum eClientMode mode; long normalHubs = 0; long regHubs = 0; long opHubs = 0; long totalHubs = 0; // check profile if ( (hubname.NotEmpty()) || (hubhost.NotEmpty()) ) { if ( GetBookmarkHubProfile( hubname, hubhost, &pConfigHubProfile ) ) { prof = true; } } mode = GetMode(); m_Mutex.Lock(); if ( (GetAwayMode() == euamAWAY) && (raw == false) ) { s += sAwayPrefix; } // set tag if ( prof ) { tag = pConfigHubProfile.m_bTag; extHubCount = pConfigHubProfile.m_bExtHubCount; } else { tag = bDescriptionTag; extHubCount = m_bUseExtendedHubCount; } // set description if ( prof && pConfigHubProfile.m_bComment ) { s += pConfigHubProfile.m_sComment; } else { s += sDescription; } // Fake share bug fix :) s.Swap( '$', '_' ); s.Swap( '|', '_' ); // all bots need to check start AND end tag if ( (s.Find('<') != -1) && (s.Find('>') != -1) ) { s.Swap( '<', '_' ); s.Swap( '>', '_' ); } if ( tag && (raw == false) ) { s += "GetConnectedHubCount(false)) > 0)) { opHubs = totalHubs - CConnectionManager::Instance()->GetConnectedHubCount(true); regHubs = CConnectionManager::Instance()->GetConnectedHubPasswordCount() - opHubs; normalHubs = totalHubs - (opHubs + regHubs); /* printf("Debug GetConnectedHubCount(false): %d\n", CConnectionManager::Instance()->GetConnectedHubCount(false)); * printf("Debug GetConnectedHubCount(true): %d\n", CConnectionManager::Instance()->GetConnectedHubCount(true)); * printf("Debug GetConnectedHubPasswordCount(): %d\n", CConnectionManager::Instance()->GetConnectedHubPasswordCount()); * printf("Debug total hub count: %d\n", totalHubs); * printf("Debug OP hub count: %d\n", opHubs); * printf("Debug reg hub count: %d\n", regHubs); * printf("Debug normal hub count: %d\n", normalHubs); */ // extra sanity check if (normalHubs < 0) { printf("Warning! normal user hub count < 0, setting to 0\n"); normalHubs = 0; } if (regHubs < 0) { printf("Warning! registered user hub count < 0, setting to 0\n"); regHubs = 0; } if (opHubs < 0) { printf("Warning! operator hub count < 0, setting to 0\n"); opHubs = 0; } // cannot be on zero hubs! // this sometimes happens when logging on to a hub // and the tag hasn't updated yet) if ( (normalHubs == 0) && (regHubs == 0) && (opHubs == 0) ) { normalHubs = 1; } s += CString::number(normalHubs); s += '/'; s += CString::number(regHubs); s += '/'; s += CString::number(opHubs); } else { s += "1/0/0"; } } else // short H:6 original valknut format { if ( CConnectionManager::Instance() && ((totalHubs = CConnectionManager::Instance()->GetConnectedHubCount(true)) > 0) ) { s += CString::number(totalHubs); } else { s += '1'; } } s += ",S:"; if ( (iMaxUpload == 0) || (!CDownloadManager::Instance()) ) { s += '*'; } else { /* total # of slots open more Hub Script DC++ Tag Checking friendly */ s += CString::number(iMaxUpload); } if ( (m_nExtraSlotsRate > 0) && (m_nMaxExtraSlots > 0) ) { s += ",O:"; s += CString::number( m_nExtraSlotsRate/1024 ); } if ( lMaxUploadRate > 0 ) { s += ",L:"; CString ratelimit = CString::number(lMaxUploadRate*1.0/1024,1); // remove trailing zero // in case decimal separator is "," if (ratelimit.Right(1) == "0") { ratelimit = ratelimit.Left(ratelimit.Length() - 2); } s += ratelimit; } if ( m_bDisableHashList ) { s += ",NOTTH"; } s += '>'; } m_Mutex.UnLock(); return s; } /** */ void CConfig::SetSharedFolders( CList * list ) { DCConfigShareFolder * csf = 0, *csf1; if (!list) { return; } SharedFolders.Clear(); while ( (csf=list->Next(csf)) != 0 ) { csf1 = new DCConfigShareFolder(); csf1->m_sPath = csf->m_sPath; csf1->m_sAlias = csf->m_sAlias; SharedFolders.Add( csf1 ); } return; } /** */ long CConfig::GetSharedFolders( CList * list ) { DCConfigShareFolder * csf = 0, *csf1; if (!list) { return 0; } list->Clear(); while ( (csf=SharedFolders.Next(csf)) != 0 ) { csf1 = new DCConfigShareFolder(); csf1->m_sPath = csf->m_sPath; csf1->m_sAlias = csf->m_sAlias; list->Add( csf1 ); } return list->Count(); } /** */ bool CConfig::RemoveBookmarkHub( CString name, CString /*host*/, CString /*description*/ ) { m_Mutex.Lock(); bool err = false; DCConfigHubItem * hubitem = 0; if ( pBookmarkHubList->Get(name,&hubitem) == 0 ) { int oldkey = hubitem->m_nPosition; pBookmarkHubList_HostIndex->Del(hubitem->m_sHost.ToUpper()); pBookmarkHubList->Del(hubitem->m_sName); // fix ordered bookmark map pOrderedBookmarks->clear(); hubitem = 0; while ( (pBookmarkHubList->Next( &hubitem )) != 0 ) { if ( hubitem->m_nPosition > oldkey ) { hubitem->m_nPosition--; } (*pOrderedBookmarks)[hubitem->m_nPosition] = hubitem; } err = true; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::AddBookmarkHub( CString name, CString host, CString description ) { m_Mutex.Lock(); bool err = true; DCConfigHubItem * hubitem; hubitem = 0; // remove spaces host = host.Replace(" ",""); // no port found if ( host.Find(':') == -1 ) { // add default port host += ":411"; } if ( pBookmarkHubList->Get(name,&hubitem) == 0 ) { // update hubitem->m_sHost = host; hubitem->m_sDescription = description; hubitem->m_sDescription = description; err = false; } if ( err ) { hubitem = new DCConfigHubItem(); hubitem->m_nID = (++m_nBookHubID); hubitem->m_sName = name; hubitem->m_sHost = host; hubitem->m_sDescription = description; pBookmarkHubList->Add(name,hubitem); pBookmarkHubList_HostIndex->Add(hubitem->m_sHost.ToUpper(),new CString(hubitem->m_sName)); hubitem->m_nPosition = pOrderedBookmarks->size(); (*pOrderedBookmarks)[hubitem->m_nPosition] = hubitem; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::UpdateBookmarkHub( CString name, CString host, CString description ) { m_Mutex.Lock(); bool err = false; DCConfigHubItem * hubitem; hubitem = 0; if ( pBookmarkHubList->Get(name,&hubitem) == 0 ) { // remove spaces host = host.Replace(" ",""); // no port found if ( host.Find(':') == -1 ) { // add default port host += ":411"; } // update hubitem->m_sHost = host; hubitem->m_sDescription = description; err = true; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::MoveBookmarkHub( int oldpos, int newpos ) { if ( oldpos == newpos ) { return true; } if ( ((oldpos - newpos) != 1) && ((newpos - oldpos) != 1) ) { printf("MoveBookmarkHub: can only move adjacent bookmarks\n"); return false; } bool suceeded = false; m_Mutex.Lock(); OrderedBookmarkMap::const_iterator it1 = pOrderedBookmarks->find( oldpos ); if ( it1 != pOrderedBookmarks->end() ) { OrderedBookmarkMap::const_iterator it2= pOrderedBookmarks->find( newpos ); if ( it2 != pOrderedBookmarks->end() ) { DCConfigHubItem * item1 = it1->second; DCConfigHubItem * item2 = it2->second; pOrderedBookmarks->erase( oldpos ); pOrderedBookmarks->erase( newpos ); item1->m_nPosition = newpos; item2->m_nPosition = oldpos; (*pOrderedBookmarks)[newpos] = item1; (*pOrderedBookmarks)[oldpos] = item2; suceeded = true; } else { printf("MoveBookmarkHub: new position not valid\n"); } } else { printf("MoveBookmarkHub: old position not valid\n"); } m_Mutex.UnLock(); return suceeded; } /** */ bool CConfig::ReorderBookmarkHubs( const std::vector & newpositions ) { if ( pOrderedBookmarks->size() != newpositions.size() ) { printf("ReorderBookmarkHubs: container size mismatch\n"); return false; } /* safety check everything first */ DCConfigHubItem * hubitem = 0; while( pBookmarkHubList->Next( &hubitem ) != 0 ) { if ( (hubitem->m_nPosition < 0) || (hubitem->m_nPosition > newpositions.size()) ) { printf("ReorderBookmarkHubs: Existing key for %s out of range at %d\n", hubitem->m_sName.Data(), hubitem->m_nPosition); return false; } } pOrderedBookmarks->clear(); hubitem = 0; while ( pBookmarkHubList->Next( &hubitem ) != 0 ) { //printf("%d goes to %d\n",hubitem->m_nPosition,newpositions[hubitem->m_nPosition]); hubitem->m_nPosition = newpositions[hubitem->m_nPosition]; (*pOrderedBookmarks)[hubitem->m_nPosition] = hubitem; } return true; } /** */ void CConfig::ClearPublicHubList() { m_Mutex.Lock(); m_nPublicHubID = 0; pPublicHubList->Clear(); pPublicHubList_HostIndex->Clear(); m_Mutex.UnLock(); } /** */ bool CConfig::RemovePublicHub( CString name, CString /*host*/, CString /*description*/ ) { m_Mutex.Lock(); bool err = false; DCConfigHubItem * hubitem; hubitem = 0; if ( pPublicHubList->Get(name.ToUpper(),&hubitem) == 0 ) { pPublicHubList_HostIndex->Del(hubitem->m_sHost); pPublicHubList->Del(hubitem->m_sName.ToUpper()); err = true; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::AddPublicHub( const CString & name, const CString & host, const CString & description, const ulonglong usercount, const CString country, const ulonglong shared, const ulonglong minshare, const CString extra ) { if ( name.IsEmpty() || host.IsEmpty() ) { return false; } bool badd = true; DCConfigHubItem * hubitem = 0; CString *ps; CString sname,shost,thost,fixedname; ulonglong ucount = usercount; // remove spaces thost = host.Replace(" ",""); // remove dchub:// if ( thost.Left(8).ToLower() == "dchub://" ) { thost = thost.Mid(8); } // no port found if ( thost.Find(':') == -1 ) { // add default port thost += ":411"; } shost = thost.ToUpper(); /* FIXME ADC protocol hubs not supported, so do not put into list */ if ( shost.StartsWith("ADC://",6) || shost.StartsWith("ADCS://",7) ) { return false; } fixedname = name; sname = name.ToUpper(); // check for negative user count if ( ((long long) ucount) < 0 ) { ucount = 0; } m_Mutex.Lock(); if ( pPublicHubList->Get(sname,&hubitem) == 0 ) { // hub found by name CString uppercurhost = hubitem->m_sHost.ToUpper(); if ( shost == uppercurhost ) { // remove from host index pPublicHubList_HostIndex->Del(uppercurhost); // if another hub with the new ip present ? if ( pPublicHubList_HostIndex->Get(shost,&ps) == 0 ) { printf("double found: '%s'\n",shost.Data()); if ( ps->ToUpper() != sname ) pPublicHubList->Del(ps->ToUpper()); pPublicHubList_HostIndex->Del(shost); } // remove hub from hublist pPublicHubList->Del(sname); } else { // same name but different host - append (2) etc. to name int n = 2; CString tempkey = sname; tempkey += " ("; tempkey += CString::number(n); tempkey += ')'; while ( pPublicHubList->Get(tempkey,&hubitem) == 0 ) { if ( thost == hubitem->m_sHost ) { badd = false; break; } n++; tempkey = sname; tempkey += " ("; tempkey += CString::number(n); tempkey += ')'; } sname = tempkey; fixedname += " ("; fixedname += CString::number(n); fixedname += ')'; } } else { // hub not found, check if hub exists in the host index if ( pPublicHubList_HostIndex->Get(shost,&ps) == 0 ) { // hub by host found if ( pPublicHubList->Get(ps->ToUpper(),&hubitem) == 0 ) { printf("double found: '%s'\n",shost.Data()); pPublicHubList->Del(ps->ToUpper()); pPublicHubList_HostIndex->Del(shost); } else { printf("warning public hub list inconsistent !\n"); } } } if ( badd ) { hubitem = new DCConfigHubItem(); hubitem->m_nID = (++m_nPublicHubID); hubitem->m_sName = fixedname; hubitem->m_sHost = thost; hubitem->m_sDescription = description; hubitem->m_nUserCount = ucount; hubitem->m_sCountry = country; hubitem->m_sExtra = extra; hubitem->m_nShared = shared; hubitem->m_nMinShare = minshare; pPublicHubList->Add(sname,hubitem); pPublicHubList_HostIndex->Add(shost,new CString(fixedname)); } m_Mutex.UnLock(); return badd; } /** */ CString CConfig::GetListenHostString() { m_Mutex.Lock(); CString s; if ( m_sListenHost.NotEmpty() ) { s = CNetAddr::GetHostI4(m_sListenHost.Replace(' ',"")); } m_Mutex.UnLock(); return s; } /** */ CString CConfig::GetTCPHostString( bool addport, bool crypto ) { CString s; unsigned int n = 0; // get current port from listenmanager if ( crypto ) { if ( CCryptoListenManager::Instance() ) { n = CCryptoListenManager::Instance()->GetListenPort(); } } else { if ( CListenManager::Instance() ) { n = CListenManager::Instance()->GetListenPort(); } } m_Mutex.Lock(); if ( m_sHost.NotEmpty() ) { if ( m_bExternalIP ) { // first we check for a cache update if ( (m_sHostCache.IsEmpty()) || ((time(0)-m_tHostTimeout) > 60) ) { m_sHostCache = CNetAddr::GetHostI4(m_sHost.Replace(' ',"")); m_tHostTimeout = time(0); } s = m_sHostCache; } else { s = CNetAddr::GetInterfaceI4( m_sHost ); } } if ( s.NotEmpty() && addport ) { if ( n != 0 ) { s += ':'; s += CString::number(n); } else { s.Empty(); } } m_Mutex.UnLock(); return s; } /** */ CString CConfig::GetUDPHostString( bool addport ) { m_Mutex.Lock(); CString s; if ( m_sHost.NotEmpty() ) { if ( m_bExternalIP ) { // first we check for a cache update if ( (m_sHostCache.IsEmpty()) || ((time(0)-m_tHostTimeout) > 60) ) { m_sHostCache = CNetAddr::GetHostI4(m_sHost.Replace(' ',"")); m_tHostTimeout = time(0); } s = m_sHostCache; } else { s = CNetAddr::GetInterfaceI4( m_sHost ); } } if ( s.NotEmpty() && addport ) { s += ':'; s += CString::number(iUDPListenPort); } m_Mutex.UnLock(); return s; } /** * check if we can resolve the ip in active mode */ eClientMode CConfig::GetMode( bool setting ) { if ( !setting && (eMode == ecmACTIVE) ) { if ( GetTCPHostString().IsEmpty() ) { return ecmPASSIVE; } } return eMode; } /** */ long CConfig::GetBookmarkHubList( CList * list ) { DCConfigHubItem * newitem; if (!list) { return 0; } list->Clear(); m_Mutex.Lock(); for ( OrderedBookmarkMap::const_iterator it = pOrderedBookmarks->begin(); it != pOrderedBookmarks->end(); ++it ) { newitem = new DCConfigHubItem( it->second ); list->Add(newitem); } m_Mutex.UnLock(); return list->Count(); } /** */ long CConfig::GetPublicHubList( CList * list ) { DCConfigHubItem * item = 0, *newitem; if (!list) { return 0; } list->Clear(); m_Mutex.Lock(); while ( pPublicHubList->Next(&item) != 0 ) { newitem = new DCConfigHubItem( item ); list->Add(newitem); } m_Mutex.UnLock(); return list->Count(); } /** */ long CConfig::GetPublicHubListSize() const { return pPublicHubList->Count(); } /** */ CStringList * CConfig::GetPublicHubServerList() { DCConfigHubItem * item = 0; CStringList * StringList = 0; CString * string; m_Mutex.Lock(); if ( pPublicHubList->Count() > 0 ) { StringList = new CStringList(); while ( pPublicHubList->Next(&item) != 0 ) { if ( StringList->Get( item->m_sHost, &string ) != 0 ) { StringList->Add(item->m_sHost, new CString(item->m_sHost)); } } } m_Mutex.UnLock(); return StringList; } /** */ CStringList * CConfig::GetBookmarkHubServerList() { DCConfigHubItem * item = 0; CStringList * StringList = 0; CString * string; m_Mutex.Lock(); if ( pBookmarkHubList->Count() > 0 ) { StringList = new CStringList(); while ( pBookmarkHubList->Next(&item) != 0 ) { if ( StringList->Get( item->m_sHost, &string ) != 0 ) { StringList->Add(item->m_sHost, new CString(item->m_sHost)); } } } m_Mutex.UnLock(); return StringList; } /** */ bool CConfig::GetBookmarkHub( CString name, DCConfigHubItem * hubitem ) { bool err = false; DCConfigHubItem * hubitem1; if ( !hubitem ) { return err; } hubitem1 = 0; m_Mutex.Lock(); if ( pBookmarkHubList->Get(name,&hubitem1) == 0 ) { // update hubitem->m_sName = hubitem1->m_sName; hubitem->m_sHost = hubitem1->m_sHost; hubitem->m_sDescription = hubitem1->m_sDescription; hubitem->m_nUserCount = hubitem1->m_nUserCount; hubitem->m_sProfile = hubitem1->m_sProfile; hubitem->m_sCountry = hubitem1->m_sCountry; hubitem->m_sExtra = hubitem1->m_sExtra; hubitem->m_nShared = hubitem1->m_nShared; hubitem->m_nMinShare = hubitem1->m_nMinShare; hubitem->m_nPosition = hubitem1->m_nPosition; err = true; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::GetBookmarkHub( unsigned long id, DCConfigHubItem * hubitem ) { bool err = false; DCConfigHubItem * hubitem1; if ( !hubitem ) { return err; } hubitem1 = 0; m_Mutex.Lock(); while ( (pBookmarkHubList->Next(&hubitem1)) == 1 ) { if ( hubitem1->m_nID == id ) { hubitem->m_sName = hubitem1->m_sName; hubitem->m_sHost = hubitem1->m_sHost; hubitem->m_sDescription = hubitem1->m_sDescription; hubitem->m_nUserCount = hubitem1->m_nUserCount; hubitem->m_sProfile = hubitem1->m_sProfile; hubitem->m_sCountry = hubitem1->m_sCountry; hubitem->m_sExtra = hubitem1->m_sExtra; hubitem->m_nShared = hubitem1->m_nShared; hubitem->m_nMinShare = hubitem1->m_nMinShare; hubitem->m_nPosition = hubitem1->m_nPosition; err = true; break; } } m_Mutex.UnLock(); return err; } /** */ CString CConfig::GetNick( CString hubname, CString hubhost ) { DCConfigHubItem * hubitem; DCConfigHubProfile * profile; CString * ps = 0; CString s; hubitem = 0; m_Mutex.Lock(); if ( pBookmarkHubList_HostIndex->Get( hubhost.ToUpper(), &ps ) == 0 ) { hubname = *ps; } if ( pBookmarkHubList->Get(hubname,&hubitem) == 0 ) { if ( hubitem->m_sProfile.NotEmpty() ) { HubProfileMap::const_iterator profile_it = pHubProfileMap->find( hubitem->m_sProfile ); if ( profile_it != pHubProfileMap->end() ) { profile = profile_it->second; if ( profile->m_sNick.NotEmpty() ) { m_Mutex.UnLock(); return profile->m_sNick.Replace(' ',"\xa0"); } } } } s = CConnectionManager::Instance()->GetNick(hubname,hubhost); if ( s.NotEmpty() ) { m_Mutex.UnLock(); return s; } m_Mutex.UnLock(); return GetNick(); } /** */ CString CConfig::GetRemoteEncoding( CString hubname, CString hubhost ) { DCConfigHubProfile profile; if ( GetBookmarkHubProfile( hubname, hubhost, &profile ) ) { if ( profile.m_sRemoteEncoding.NotEmpty() ) { return profile.m_sRemoteEncoding; } } return m_sRemoteEncoding; } /** */ bool CConfig::SetBookmarkHubProfile( CString name, CString profile ) { bool err = false; DCConfigHubItem * hubitem; m_Mutex.Lock(); if ( pBookmarkHubList->Get(name,&hubitem) == 0 ) { // update hubitem->m_sProfile = profile; err = true; } m_Mutex.UnLock(); // save bookmark list if ( err ) { SaveDCBookHub(); } return err; } /** */ bool CConfig::GetBookmarkHubProfile( CString name, CString host, DCConfigHubProfile * p ) { bool err = false; DCConfigHubItem * hubitem; m_Mutex.Lock(); if ( host.NotEmpty() ) { // remove spaces host = host.Replace(" ",""); // no port found if ( host.Find(':') == -1 ) { // add default port host += ":411"; } if ( pBookmarkHubList->Get(name,&hubitem) != 0 ) { CString * ps; if ( pBookmarkHubList_HostIndex->Get(host.ToUpper(),&ps) == 0 ) { name = *ps; } } } if ( pBookmarkHubList->Get(name,&hubitem) == 0 ) { if ( hubitem->m_sProfile.NotEmpty() ) { HubProfileMap::const_iterator profile_it = pHubProfileMap->find( hubitem->m_sProfile ); if ( profile_it != pHubProfileMap->end() ) { *p = profile_it->second; err = true; } } } m_Mutex.UnLock(); return err; } /** */ bool CConfig::GetPublicHub( CString name, DCConfigHubItem * hubitem ) { bool err = false; DCConfigHubItem * hubitem1; if ( !hubitem ) { return err; } hubitem1 = 0; m_Mutex.Lock(); if ( pPublicHubList->Get(name.ToUpper(),&hubitem1) == 0 ) { // update hubitem->m_sName = hubitem1->m_sName; hubitem->m_sHost = hubitem1->m_sHost; hubitem->m_sDescription = hubitem1->m_sDescription; hubitem->m_nUserCount = hubitem1->m_nUserCount; hubitem->m_sProfile = hubitem1->m_sProfile; hubitem->m_sCountry = hubitem1->m_sCountry; hubitem->m_sExtra = hubitem1->m_sExtra; hubitem->m_nShared = hubitem1->m_nShared; hubitem->m_nMinShare = hubitem1->m_nMinShare; err = true; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::GetPublicHub( unsigned long id, DCConfigHubItem * hubitem ) { bool err = false; DCConfigHubItem * hubitem1; if ( !hubitem ) { return err; } hubitem1 = 0; m_Mutex.Lock(); while ( (pPublicHubList->Next(&hubitem1)) == 1 ) { if ( hubitem1->m_nID == id ) { hubitem->m_sName = hubitem1->m_sName; hubitem->m_sHost = hubitem1->m_sHost; hubitem->m_sDescription = hubitem1->m_sDescription; hubitem->m_nUserCount = hubitem1->m_nUserCount; hubitem->m_sProfile = hubitem1->m_sProfile; hubitem->m_sCountry = hubitem1->m_sCountry; hubitem->m_sExtra = hubitem1->m_sExtra; hubitem->m_nShared = hubitem1->m_nShared; hubitem->m_nMinShare = hubitem1->m_nMinShare; err = true; break; } } m_Mutex.UnLock(); return err; } /** */ long CConfig::GetHubListUrlList( CList * list ) { DCConfigHubListUrl * item = 0, *newitem; if (!list) { return 0; } list->Clear(); m_Mutex.Lock(); while ( (item=pHubListUrlList.Next(item)) != 0 ) { newitem = new DCConfigHubListUrl(); newitem->bEnabled = item->bEnabled; newitem->sUrl = item->sUrl; list->Add(newitem); } m_Mutex.UnLock(); return list->Count(); } /** */ void CConfig::SetHubListUrlList( CList * list ) { DCConfigHubListUrl * item = 0, *newitem; pHubListUrlList.Clear(); if (!list) { return; } m_Mutex.Lock(); while ( (item=list->Next(item)) != 0 ) { newitem = new DCConfigHubListUrl(); newitem->bEnabled = item->bEnabled; newitem->sUrl = item->sUrl; pHubListUrlList.Add(newitem); } m_Mutex.UnLock(); return; } /** */ bool CConfig::AddHubProfile( DCConfigHubProfile * p ) { bool err = false; if ( !p ) { return err; } m_Mutex.Lock(); HubProfileMap::const_iterator profile_it = pHubProfileMap->find( p->m_sName ); if ( profile_it == pHubProfileMap->end() ) { // create new entry (*pHubProfileMap)[p->m_sName] = new DCConfigHubProfile(p); err = true; } else { // update *(profile_it->second) = *p; err = true; } m_Mutex.UnLock(); return err; } /** */ bool CConfig::DelHubProfile( CString name ) { bool res = false; m_Mutex.Lock(); HubProfileMap::iterator profile_it = pHubProfileMap->find( name ); if ( profile_it != pHubProfileMap->end() ) { delete profile_it->second; pHubProfileMap->erase( profile_it ); res = true; } m_Mutex.UnLock(); return res; } /** */ bool CConfig::GetHubProfile( CString name, DCConfigHubProfile * p ) { bool res = false; m_Mutex.Lock(); HubProfileMap::const_iterator profile_it = pHubProfileMap->find( name ); if ( profile_it != pHubProfileMap->end() ) { *p = *(profile_it->second); res = true; } m_Mutex.UnLock(); return res; } /** */ std::list * CConfig::GetHubProfileNames() { m_Mutex.Lock(); std::list * nameslist = new std::list(); for ( HubProfileMap::const_iterator profile_it = pHubProfileMap->begin(); profile_it != pHubProfileMap->end(); ++profile_it ) { nameslist->push_back(profile_it->second->m_sName); } m_Mutex.UnLock(); return nameslist; } /** */ bool CConfig::SaveHubProfile() { bool err = false; CString s; DCConfigHubProfile * pConfigHubProfile = 0; CXml * xml; m_Mutex.Lock(); xml = new CXml(); xml->NewDoc( XML_DCPROF_CONFIG ); for ( HubProfileMap::const_iterator profile_it = pHubProfileMap->begin(); profile_it != pHubProfileMap->end(); ++profile_it ) { pConfigHubProfile = profile_it->second; xml->StartNewChild( XML_PROFILE ); xml->NewStringChild( XML_NAME, pConfigHubProfile->m_sName); xml->NewStringChild( XML_NICK, pConfigHubProfile->m_sNick); xml->NewStringChild( XML_PASSWORD, pConfigHubProfile->m_sPassword); xml->NewStringChild( XML_EMAIL, pConfigHubProfile->m_sEMail); xml->NewBoolChild( XML_EMAIL_ENABLED, pConfigHubProfile->m_bEMail ); xml->NewStringChild( XML_DESCRIPTION, pConfigHubProfile->m_sComment); xml->NewBoolChild( XML_DESCRIPTION_ENABLED, pConfigHubProfile->m_bComment ); xml->NewBoolChild( XML_AUTO_CONNECT, pConfigHubProfile->m_bAutoConnect ); xml->NewBoolChild( XML_SSL, pConfigHubProfile->m_bSSL ); xml->NewBoolChild( XML_DESCRIPTION_TAG, pConfigHubProfile->m_bTag ); xml->NewBoolChild( XML_EXTENDED_HUB_COUNT, pConfigHubProfile->m_bExtHubCount ); xml->NewStringChild( XML_SUPPRESSED_NICKS, pConfigHubProfile->m_sSuppressedNicks ); xml->NewStringChild( XML_REMOTE_ENCODING, pConfigHubProfile->m_sRemoteEncoding ); xml->Parent(); } s = sConfigPath + DCPROF_CONFIG; if ( xml->SaveConfigXmlViaTemp(s) != -1 ) { err = true; } delete xml; m_Mutex.UnLock(); return err; } /** */ bool CConfig::LoadHubProfile() { bool err = true; CString s, xml_name; DCConfigHubProfile * pConfigHubProfile; CXml *xml; m_Mutex.Lock(); xml = new CXml(); s = sConfigPath + DCPROF_CONFIG; if ( xml->ParseFile(s) && xml->DocFirstChild() ) { do { if ( (xml->Name() == XML_DCPROF_CONFIG) && xml->FirstChild() ) { do { if ( (xml->Name() == XML_PROFILE) && xml->FirstChild() ) { pConfigHubProfile = new DCConfigHubProfile(); do { xml_name = xml->Name(); if ( xml_name == XML_NAME ) pConfigHubProfile->m_sName = xml->Content(); else if ( xml_name == XML_NICK ) pConfigHubProfile->m_sNick = xml->Content(); else if ( xml_name == XML_PASSWORD ) pConfigHubProfile->m_sPassword = xml->Content(); else if ( xml_name == XML_EMAIL ) pConfigHubProfile->m_sEMail = xml->Content(); else if ( xml_name == XML_DESCRIPTION ) pConfigHubProfile->m_sComment = xml->Content(); else if ( xml_name == XML_AUTO_CONNECT ) pConfigHubProfile->m_bAutoConnect = xml->GetBoolChild(); else if ( xml_name == XML_SSL ) pConfigHubProfile->m_bSSL = xml->GetBoolChild(); else if ( xml_name == XML_DESCRIPTION_TAG ) pConfigHubProfile->m_bTag = xml->GetBoolChild(); else if ( xml_name == XML_DESCRIPTION_ENABLED ) pConfigHubProfile->m_bComment = xml->GetBoolChild(); else if ( xml_name == XML_EMAIL_ENABLED ) pConfigHubProfile->m_bEMail = xml->GetBoolChild(); else if ( xml_name == XML_EXTENDED_HUB_COUNT ) pConfigHubProfile->m_bExtHubCount = xml->GetBoolChild(); else if ( xml_name == XML_SUPPRESSED_NICKS ) pConfigHubProfile->m_sSuppressedNicks = xml->Content(); else if ( xml_name == XML_REMOTE_ENCODING ) pConfigHubProfile->m_sRemoteEncoding = xml->Content(); } while ( xml->NextNode() ); xml->Parent(); if ( pConfigHubProfile->m_sName.IsEmpty() ) { delete pConfigHubProfile; } else { HubProfileMap::const_iterator profile_it = pHubProfileMap->find( pConfigHubProfile->m_sName ); if ( profile_it == pHubProfileMap->end() ) { (*pHubProfileMap)[pConfigHubProfile->m_sName] = pConfigHubProfile; } else { // duplicate profile name in config file, rename profile CString key; int i = 0; do { key = pConfigHubProfile->m_sName; key += " ("; key += CString::number(i); key += ")"; profile_it = pHubProfileMap->find( key ); } while ( (profile_it != pHubProfileMap->end()) && (i < 20) ); if ( profile_it == pHubProfileMap->end() ) { pConfigHubProfile->m_sName = key; (*pHubProfileMap)[pConfigHubProfile->m_sName] = pConfigHubProfile; } else { delete pConfigHubProfile; } } } } } while ( xml->NextNode() ); xml->Parent(); } } while ( xml->NextNode() ); } delete xml; m_Mutex.UnLock(); return err; } /** */ CString CConfig::AliasToPath( CString file ) { int i; CString s,s1,sfile,sdir; DCConfigShareFolder * csf; m_Mutex.Lock(); if ( SharedFolders.Count() <= 0 ) { m_Mutex.UnLock(); return s; } // simple filename sfile = CDir::SimplePath(file); if ( sfile.IsEmpty() ) { m_Mutex.UnLock(); return sfile; } // get the first directory i = sfile.Find(DIRSEPARATOR); if ( i <= 0 ) { // must be a top level directory, find it! csf = 0; while( (csf=SharedFolders.Next(csf)) != 0 ) { if ( sfile == CDir::SimplePath(csf->m_sAlias) ) { m_Mutex.UnLock(); return CDir::SimplePath(csf->m_sPath); } } } else { sdir = sfile.Left(i); sfile = sfile.Mid(i+1,sfile.Length()-1-i); } // this test remove because directories are indexed in 0.3.14 - ejs /* if ( sfile.IsEmpty() ) { // get directory ... m_Mutex.UnLock(); return sfile; } */ CDir dir; csf = 0; while( (csf=SharedFolders.Next(csf)) != 0 ) { // check for correct alias if ( csf->m_sAlias != sdir ) { continue; } // set correct path s = csf->m_sPath; // is valid ? if ( dir.cd(s) ) { if ( sfile.IsEmpty() ) { s1 = DIRSEPARATOR + sdir; } else { s1 = DIRSEPARATOR + sfile; } if ( dir.IsFile(s1) ) { s += DIRSEPARATOR; s += sfile; s = CDir::SimplePath(s); m_Mutex.UnLock(); return s; } else if ( dir.IsDir(s1) ) { if ( sfile.IsEmpty() ) { s += DIRSEPARATOR; s += sdir; } else { s += DIRSEPARATOR; s += sfile; } s = CDir::SimplePath(s); m_Mutex.UnLock(); return s; } } } m_Mutex.UnLock(); return CString(); } /** */ void CConfig::SetHost( CString newhost ) { if ( newhost != m_sHost ) { m_Mutex.Lock(); m_sHost = newhost; m_sHostCache.Empty(); m_Mutex.UnLock(); } } /** */ void CConfig::SetAwayMode( eUserAwayMode mode ) { m_Mutex.Lock(); eAwayMode = mode; m_Mutex.UnLock(); } libdc0-0.3.24~svn3121/dclib/cpluginmanager.h0000644000175000017500000000444111101144617017442 0ustar sikonsikon/*************************************************************************** cpluginmanager.h - description ------------------- begin : Fri Sep 27 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CPLUGINMANAGER_H #define CPLUGINMANAGER_H /** *@author Mathias Küster * * It loads plugins. Plugins have unrestricted access to dclib's * public functions, they are essentially just extra dclib code * but not included in the source. * * The only known plugin is the plugin for remote access via * http, which cannot do very much. * * In addition, the design of dclib doesn't appear to allow * for a stable API or ABI, but no version information is * stored so forgetting to recompile the plugin will cause a crash. */ #include #include #include #include class CPluginObject { public: /** */ CPluginObject() {}; /** */ ~CPluginObject() {}; /** Store filename loaded */ CString m_sFileName; /** */ ePluginStruct * m_ePluginStruct; /** */ #ifndef WIN32 void * m_Handle; #else HINSTANCE m_Handle; #endif }; class CPluginManager : public CSingleton { public: /** */ CPluginManager(); /** */ virtual ~CPluginManager(); /** */ void Load( CString path = CString() ); /** */ void InitPlugins(); /** */ void DeInitPlugins(); /** */ virtual bool Init( CPluginObject * plugin ); private: /** */ CList * m_pPluginList; }; #endif libdc0-0.3.24~svn3121/dclib/csharetreefolder.cpp0000644000175000017500000000766611101154437020337 0ustar sikonsikon/*************************************************************************** csharetreefolder.cpp - Object for storing a tree of folders ------------------- begin : Fri Jul 25 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "csharetreefolder.h" #include "csearchindex.h" #include "core/cxml.h" /** */ CShareTreeFolder::CShareTreeFolder( const CString & name, const CShareTreeFolder * parent ) : m_sName(name), m_pParent(parent), m_pFolderList(0), m_pFileList(0) { // all done in initialisation section // which is necessary due to the excessive const use } /** */ CShareTreeFolder::~CShareTreeFolder() { if ( m_pFolderList ) { for ( std::list::const_iterator it = m_pFolderList->begin(); it != m_pFolderList->end(); ++it ) { delete (*it); } m_pFolderList->clear(); delete m_pFolderList; m_pFolderList = 0; } delete m_pFileList; m_pFileList = 0; } /** */ const CString & CShareTreeFolder::GetName() const { return m_sName; } /** */ const CShareTreeFolder * CShareTreeFolder::GetParent() const { return m_pParent; } /** */ std::list * CShareTreeFolder::GetChildren() const { if ( m_pFolderList ) { std::list * newlist = new std::list(); (*newlist) = (*m_pFolderList); return newlist; } else { return 0; } } /** */ CShareTreeFolder * CShareTreeFolder::AddFolder( const CString & name ) { CShareTreeFolder * newfolder = new CShareTreeFolder( name, this ); if ( m_pFolderList == 0 ) { m_pFolderList = new std::list(); } m_pFolderList->push_back(newfolder); return newfolder; } /** */ std::list * CShareTreeFolder::GetFiles() const { if ( m_pFileList ) { std::list * newlist = new std::list(); (*newlist) = (*m_pFileList); return newlist; } else { return 0; } } /** */ void CShareTreeFolder::AddFile( const unsigned long int fbi ) { if ( m_pFileList == 0 ) { m_pFileList = new std::list(); } m_pFileList->push_back(fbi); } /** */ CString CShareTreeFolder::GetXML( int depth, CSearchIndex * si ) const { CString result; CXml cxml; if ( m_pFolderList ) { for ( std::list::const_iterator it = m_pFolderList->begin(); it != m_pFolderList->end(); ++it ) { result += "GetName() ); if ( depth == 0 ) { result += "\" Incomplete=\"1\"/>\n"; } else { result += "\">\n"; result += (*it)->GetXML( depth - 1, si ); result += "\n"; } } } if ( m_pFileList ) { struct filebaseobject fbo; for ( std::list::const_iterator it = m_pFileList->begin(); it != m_pFileList->end(); ++it ) { if ( si->GetFileBaseObject((*it),&fbo) ) { result += "GetFileName( (*it) ) ); result += "\" Size=\""; result += CString::number( fbo.m_nSize ); if ( fbo.m_nHashIndex != (unsigned long int)-1 ) { result += "\" TTH=\""; result += si->GetHash(fbo.m_nHashIndex); } result += "\"/>\n"; } } } return result; } libdc0-0.3.24~svn3121/dclib/cuserlist.cpp0000644000175000017500000001740511112566665017037 0ustar sikonsikon/*************************************************************************** cuserlist.cpp - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cuserlist.h" #include #include "core/clist.h" #include "dcobject.h" CUserList::CUserList() { m_nShareSize = 0; } CUserList::~CUserList() { Clear(); } /** */ void CUserList::Clear() { m_Mutex.Lock(); for ( MyInfoMap::iterator it = m_MyInfoMap.begin(); it != m_MyInfoMap.end(); ++it ) { delete it->second; } m_MyInfoMap.clear(); m_Mutex.UnLock(); m_nShareSize = 0; } /** */ void CUserList::InitUserList( CMessageNickList * nicklist ) { CString *nick; if (!nicklist) return; m_nShareSize = 0; for(nick=0;(nick=nicklist->m_NickList.Next(nick))!=0;) { AppendUser(*nick); } } /** */ void CUserList::InitOperatorList( CMessageOpList * oplist ) { CString *nick; // set in the nicklist the operator status for(nick=0;(nick=oplist->m_NickList.Next(nick))!=0;) { // add the user, some hubs send the oplist before nicklist or myinfo AppendUser(*nick); m_Mutex.Lock(); MyInfoMap::iterator it = m_MyInfoMap.find(nick->Data()); if ( it != m_MyInfoMap.end() ) { it->second->m_bOperator = true; } m_Mutex.UnLock(); } } /** */ bool CUserList::AppendUser( CString & nick, bool getinfo ) { bool res = false; if ( nick.IsEmpty() ) { return res; } CMessageMyInfo *myinfo=0; m_Mutex.Lock(); MyInfoMap::iterator it = m_MyInfoMap.find(nick); if ( it == m_MyInfoMap.end() ) { myinfo = new CMessageMyInfo(); myinfo->m_sNick = nick; myinfo->m_eAwayMode = euamNORMAL; m_MyInfoMap[nick] = myinfo; if ( getinfo ) res = true; } m_Mutex.UnLock(); return res; } /** */ void CUserList::RemoveUser( CString & nick ) { if ( nick.IsEmpty() ) { return; } CMessageMyInfo *myinfo=0; m_Mutex.Lock(); MyInfoMap::iterator it = m_MyInfoMap.find(nick); if ( it != m_MyInfoMap.end() ) { myinfo = it->second; if ( myinfo->m_nShared > m_nShareSize ) m_nShareSize = 0; else m_nShareSize -= myinfo->m_nShared; m_MyInfoMap.erase( it ); delete myinfo; } m_Mutex.UnLock(); } /** */ bool CUserList::UpdateUser( CMessageMyInfo * pMyInfo ) { bool res = false; CMessageMyInfo *myinfo=0; if (!pMyInfo) return res; if ( pMyInfo->m_sNick.IsEmpty() ) { return res; } m_Mutex.Lock(); MyInfoMap::iterator it = m_MyInfoMap.find(pMyInfo->m_sNick); if ( it != m_MyInfoMap.end() ) { myinfo = it->second; if ( myinfo->m_nShared >= m_nShareSize ) m_nShareSize = 0; else m_nShareSize -= myinfo->m_nShared; // don't send old data to the gui if ( myinfo->m_sNick != pMyInfo->m_sNick ) res = true; else if ( myinfo->m_sComment != pMyInfo->m_sComment ) res = true; else if ( myinfo->m_sUnknown != pMyInfo->m_sUnknown ) res = true; else if ( myinfo->m_eUserSpeed != pMyInfo->m_eUserSpeed ) res = true; else if ( myinfo->m_sUserSpeed != pMyInfo->m_sUserSpeed ) res = true; else if ( myinfo->m_sEMail != pMyInfo->m_sEMail ) res = true; else if ( myinfo->m_nShared != pMyInfo->m_nShared ) res = true; else if ( myinfo->m_eAwayMode != pMyInfo->m_eAwayMode ) res = true; else if ( pMyInfo->m_bOperator != myinfo->m_bOperator ) res = true; else if ( myinfo->m_sVerComment != pMyInfo->m_sVerComment ) res = true; else if ( myinfo->m_eClientVersion != pMyInfo->m_eClientVersion ) res = true; else if ( myinfo->m_eClientMode != pMyInfo->m_eClientMode ) res = true; else if ( myinfo->m_bServerFlag != pMyInfo->m_bServerFlag ) res = true; else if ( myinfo->m_bFireballFlag != pMyInfo->m_bFireballFlag ) res = true; else if ( myinfo->m_bTLSFlag != pMyInfo->m_bTLSFlag ) res = true; /* copy values that are stored but not in $MyINFO protocol message */ pMyInfo->m_bOperator = myinfo->m_bOperator; pMyInfo->m_MessageLock = myinfo->m_MessageLock; pMyInfo->m_MessageSupports = myinfo->m_MessageSupports; pMyInfo->m_sTransferHost = myinfo->m_sTransferHost; } else { myinfo = new CMessageMyInfo(); m_MyInfoMap[pMyInfo->m_sNick] = myinfo; res = true; } if ( res ) { *myinfo = *pMyInfo; } m_nShareSize += myinfo->m_nShared; m_Mutex.UnLock(); return res; } /** */ bool CUserList::IsUserOnline( CString & nick ) { bool res = false; if ( nick.IsEmpty() ) { return res; } m_Mutex.Lock(); res = ( m_MyInfoMap.find(nick) != m_MyInfoMap.end() ); m_Mutex.UnLock(); return res; } /** */ bool CUserList::IsAdmin( const CString & nick ) { bool res = false; if ( nick.IsEmpty() ) { return res; } m_Mutex.Lock(); MyInfoMap::const_iterator it = m_MyInfoMap.find(nick); if ( it != m_MyInfoMap.end() ) { res = it->second->m_bOperator; } m_Mutex.UnLock(); return res; } /** */ eUserClientVersion CUserList::GetUserClientVersion( const CString & nick ) { eUserClientVersion res = eucvNONE; if ( nick.IsEmpty() ) { return res; } m_Mutex.Lock(); MyInfoMap::const_iterator it = m_MyInfoMap.find(nick); if ( it != m_MyInfoMap.end() ) { res = it->second->m_eClientVersion; } m_Mutex.UnLock(); return res; } /** */ bool CUserList::GetUserMyInfo( CString nick, CMessageMyInfo * p ) { bool res = false; if ( nick.IsEmpty() ) { return res; } m_Mutex.Lock(); MyInfoMap::const_iterator it = m_MyInfoMap.find(nick); if ( it != m_MyInfoMap.end() ) { *p = *(it->second); res = true; } m_Mutex.UnLock(); return res; } /** */ bool CUserList::SetUserTransferInfo( CString nick, CDCMessage * msg ) { bool res = false; CMessageMyInfo *myinfo=0; if ( (msg) && (!nick.IsEmpty()) ) { m_Mutex.Lock(); MyInfoMap::iterator it = m_MyInfoMap.find(nick); if ( it != m_MyInfoMap.end() ) { myinfo = it->second; if ( msg->m_eType == DC_MESSAGE_CONNECT_CLIENT) { myinfo->m_sTransferHost = ((DCMessageConnectClient*)msg)->m_sHubHost; res = true; } else if ( msg->m_eType == DC_MESSAGE_LOCK) { myinfo->m_MessageLock = *((CMessageLock*)msg); res = true; } else if ( msg->m_eType == DC_MESSAGE_SUPPORTS) { myinfo->m_MessageSupports = *((CMessageSupports*)msg); res = true; } } m_Mutex.UnLock(); } return res; } /** */ CString CUserList::GetNextNick( const CString & nick ) { CString s; m_Mutex.Lock(); if ( ! m_MyInfoMap.empty() ) { MyInfoMap::iterator it; if ( nick.IsEmpty() ) { it = m_MyInfoMap.begin(); s = it->first; } else { it = m_MyInfoMap.find(nick); if ( it != m_MyInfoMap.end() ) { ++it; if ( it != m_MyInfoMap.end() ) { s = it->first; } } } } m_Mutex.UnLock(); return s; } /** */ bool CUserList::SetUserIP( const CString & nick, const CString & ip ) { if ( nick.IsEmpty() ) { return false; } bool res = false; m_Mutex.Lock(); MyInfoMap::const_iterator it = m_MyInfoMap.find( nick ); if ( it != m_MyInfoMap.end() ) { if ( it->second->m_sTransferHost != ip ) { it->second->m_sTransferHost = ip; res = true; } } m_Mutex.UnLock(); return res; } libdc0-0.3.24~svn3121/dclib/hash/0000755000175000017500000000000011556467000015225 5ustar sikonsikonlibdc0-0.3.24~svn3121/dclib/hash/MerkleTree.h0000644000175000017500000001471211175405211017433 0ustar sikonsikon/* * Copyright (C) 2001-2008 Jacek Sieka, arnetheduck on gmail point com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined(MERKLE_TREE_H) #define MERKLE_TREE_H #include "TigerHash.h" #include "HashValue.h" namespace dcpp { /** * A class that represents a Merkle Tree hash. Storing * only the leaves of the tree, it is rather memory efficient, * but can still take a significant amount of memory during / after * hash generation. * The root hash produced can be used like any * other hash to verify the integrity of a whole file, while * the leaves provide checking of smaller parts of the file. */ template class MerkleTree { public: static const size_t BITS = Hasher::BITS; static const size_t BYTES = Hasher::BYTES; static const size_t BASE_BLOCK_SIZE = baseBlockSize; typedef HashValue MerkleValue; typedef vector MerkleList; typedef typename MerkleList::iterator MerkleIter; MerkleTree() : fileSize(0), blockSize(baseBlockSize) { } MerkleTree(int64_t aBlockSize) : fileSize(0), blockSize(aBlockSize) { } /** * Loads a set of leaf hashes, calculating the root * @param data Pointer to (aFileSize + aBlockSize - 1) / aBlockSize) hash values, * stored consecutively left to right */ MerkleTree(int64_t aFileSize, int64_t aBlockSize, uint8_t* aData) : fileSize(aFileSize), blockSize(aBlockSize) { size_t n = calcBlocks(aFileSize, aBlockSize); for(size_t i = 0; i < n; i++) leaves.push_back(MerkleValue(aData + i * Hasher::BYTES)); calcRoot(); } /** Initialise a single root tree */ MerkleTree(int64_t aFileSize, int64_t aBlockSize, const MerkleValue& aRoot) : root(aRoot), fileSize(aFileSize), blockSize(aBlockSize) { leaves.push_back(root); } ~MerkleTree() { } static int64_t calcBlockSize(int64_t aFileSize, int maxLevels) { int64_t tmp = baseBlockSize; int64_t maxHashes = ((int64_t)1) << (maxLevels - 1); while((maxHashes * tmp) < aFileSize) tmp *= 2; return tmp; } static size_t calcBlocks(int64_t aFileSize, int64_t aBlockSize) { return max((size_t)((aFileSize + aBlockSize - 1) / aBlockSize), (size_t)1); } /** * Update the merkle tree. * @param len Length of data, must be a multiple of baseBlockSize, unless it's * the last block. */ void update(const void* data, size_t len) { uint8_t* buf = (uint8_t*)data; uint8_t zero = 0; size_t i = 0; // Skip empty data sets if we already added at least one of them... if(len == 0 && !(leaves.empty() && blocks.empty())) return; Hasher h; size_t n; do { n = min(baseBlockSize, len-i); h.reset(); h.update(&zero, 1); h.update(buf + i, n); if((int64_t)baseBlockSize < blockSize) { blocks.push_back(make_pair(MerkleValue(h.finalize()), baseBlockSize)); reduceBlocks(); } else { leaves.push_back(MerkleValue(h.finalize())); } i += n; } while(i < len); fileSize += len; } uint8_t* finalize() { // No updates yet, make sure we have at least one leaf for 0-length files... if(leaves.empty() && blocks.empty()) { update(0, 0); } while(blocks.size() > 1) { MerkleBlock& a = blocks[blocks.size()-2]; MerkleBlock& b = blocks[blocks.size()-1]; a.first = combine(a.first, b.first); blocks.pop_back(); } dcassert(blocks.size() == 0 || blocks.size() == 1); if(!blocks.empty()) { leaves.push_back(blocks[0].first); } calcRoot(); return root.data; } MerkleValue& getRoot() { return root; } const MerkleValue& getRoot() const { return root; } MerkleList& getLeaves() { return leaves; } const MerkleList& getLeaves() const { return leaves; } int64_t getBlockSize() const { return blockSize; } void setBlockSize(int64_t aSize) { blockSize = aSize; } int64_t getFileSize() const { return fileSize; } void setFileSize(int64_t aSize) { fileSize = aSize; } bool verifyRoot(const uint8_t* aRoot) { return memcmp(aRoot, getRoot().data(), BYTES) == 0; } void calcRoot() { root = getHash(0, fileSize); } ByteVector getLeafData() { ByteVector buf(getLeaves().size() * BYTES); uint8_t* p = &buf[0]; for(size_t i = 0; i < getLeaves().size(); ++i) { memcpy(p + i * BYTES, &getLeaves()[i], BYTES); } return buf; } private: typedef pair MerkleBlock; typedef vector MBList; MBList blocks; MerkleList leaves; MerkleValue root; /** Total size of hashed data */ int64_t fileSize; /** Final block size */ int64_t blockSize; MerkleValue getHash(int64_t start, int64_t length) { dcassert((start % blockSize) == 0); if(length <= blockSize) { dcassert((start / blockSize) < (int64_t)leaves.size()); return leaves[(uint32_t)(start / blockSize)]; } else { int64_t l = blockSize; while(l * 2 < length) l *= 2; return combine(getHash(start, l), getHash(start+l, length - l)); } } MerkleValue combine(const MerkleValue& a, const MerkleValue& b) { uint8_t one = 1; Hasher h; h.update(&one, 1); h.update(a.data, MerkleValue::BYTES); h.update(b.data, MerkleValue::BYTES); return MerkleValue(h.finalize()); } void reduceBlocks() { while(blocks.size() > 1) { MerkleBlock& a = blocks[blocks.size()-2]; MerkleBlock& b = blocks[blocks.size()-1]; if(a.second == b.second) { if(a.second*2 == blockSize) { leaves.push_back(combine(a.first, b.first)); blocks.pop_back(); blocks.pop_back(); } else { a.second *= 2; a.first = combine(a.first, b.first); blocks.pop_back(); } } else { break; } } } }; typedef MerkleTree TigerTree; typedef TigerTree::MerkleValue TTHValue; template struct TTFilter { TTFilter() : tt(aBlockSize) { } void operator()(const void* data, size_t len) { tt.update(data, len); } TigerTree& getTree() { return tt; } private: TigerTree tt; }; } // namespace dcpp #endif // !defined(MERKLE_TREE_H) libdc0-0.3.24~svn3121/dclib/hash/Makefile.am0000644000175000017500000000060011114062217017244 0ustar sikonsikonnoinst_LTLIBRARIES = libhash.la libhash_la_SOURCES = \ compat.h \ HashValue.h \ MerkleTree.h \ TigerHash.cpp \ TigerHash.h libhash_la_LDFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) AM_CFLAGS = @CFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) $(HIDESYMS) AM_CXXFLAGS = @CXXFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) $(HIDESYMS) AM_CPPFLAGS = -I$(top_srcdir) $(PACKAGE_FLAGS) VERSION = "0.0.1" libdc0-0.3.24~svn3121/dclib/hash/TigerHash.cpp0000644000175000017500000013611111175404735017615 0ustar sikonsikon/* * Copyright (C) 2001-2009 Jacek Sieka, arnetheduck on gmail point com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "compat.h" #include "TigerHash.h" namespace dcpp { #ifdef HAVE_CONFIG_H #include #endif /* * Convert autoconf defines to whatever this code is using. */ #ifdef WORDS_BIGENDIAN #define TIGER_BIG_ENDIAN #endif /* it works correctly, and uses less cpu, even on 32bit systems */ #define TIGER_ARCH64 #define PASSES 3 #define t1 (table) #define t2 (table+256) #define t3 (table+256*2) #define t4 (table+256*3) #define save_abc \ aa = a; \ bb = b; \ cc = c; #ifdef TIGER_ARCH64 #define round(a,b,c,x,mul) \ c ^= x; \ a -= t1[((c)>>(0*8))&0xFF] ^ t2[((c)>>(2*8))&0xFF] ^ \ t3[((c)>>(4*8))&0xFF] ^ t4[((c)>>(6*8))&0xFF] ; \ b += t4[((c)>>(1*8))&0xFF] ^ t3[((c)>>(3*8))&0xFF] ^ \ t2[((c)>>(5*8))&0xFF] ^ t1[((c)>>(7*8))&0xFF] ; \ b *= mul; #else #define round(a,b,c,x,mul) \ c ^= x; \ a -= t1[(uint8_t)(c)] ^ \ t2[(uint8_t)(((uint32_t)(c))>>(2*8))] ^ \ t3[(uint8_t)((c)>>(4*8))] ^ \ t4[(uint8_t)(((uint32_t)((c)>>(4*8)))>>(2*8))] ; \ b += t4[(uint8_t)(((uint32_t)(c))>>(1*8))] ^ \ t3[(uint8_t)(((uint32_t)(c))>>(3*8))] ^ \ t2[(uint8_t)(((uint32_t)((c)>>(4*8)))>>(1*8))] ^ \ t1[(uint8_t)(((uint32_t)((c)>>(4*8)))>>(3*8))]; \ b *= mul; #endif #define pass(a,b,c,mul) \ round(a,b,c,x0,mul) \ round(b,c,a,x1,mul) \ round(c,a,b,x2,mul) \ round(a,b,c,x3,mul) \ round(b,c,a,x4,mul) \ round(c,a,b,x5,mul) \ round(a,b,c,x6,mul) \ round(b,c,a,x7,mul) #define key_schedule \ x0 -= x7 ^ _ULL(0xA5A5A5A5A5A5A5A5); \ x1 ^= x0; \ x2 += x1; \ x3 -= x2 ^ ((~x1)<<19); \ x4 ^= x3; \ x5 += x4; \ x6 -= x5 ^ ((~x4)>>23); \ x7 ^= x6; \ x0 += x7; \ x1 -= x0 ^ ((~x7)<<19); \ x2 ^= x1; \ x3 += x2; \ x4 -= x3 ^ ((~x2)>>23); \ x5 ^= x4; \ x6 += x5; \ x7 -= x6 ^ _ULL(0x0123456789ABCDEF); #define feedforward \ a ^= aa; \ b -= bb; \ c += cc; #ifdef TIGER_ARCH64 #define compress \ save_abc \ pass(a,b,c,5) \ key_schedule \ pass(c,a,b,7) \ key_schedule \ pass(b,c,a,9) \ for(pass_no=3; pass_no 0) { size_t n = min(length, BLOCK_SIZE-tmppos); memcpy(tmp + tmppos, str, n); str += n; pos += n; length -= n; if((tmppos + n) == BLOCK_SIZE) { #ifdef TIGER_BIG_ENDIAN for(j=0; j=BLOCK_SIZE) { #ifdef TIGER_BIG_ENDIAN for(j=0; j (BLOCK_SIZE - sizeof(uint64_t))) { memset(tmp + tmppos, 0, BLOCK_SIZE - tmppos); #ifdef TIGER_BIG_ENDIAN for(j=0; j #endif #ifndef uint64_t #include #endif // standard includes #include #include #include #include using std::pair; using std::make_pair; using std::vector; using std::min; using std::max; // algorithm include added for min and max functions // also this typedef added for 0.707 from DCPlusPlus.h typedef std::vector ByteVector; // defines used by the DC++ code #ifndef _ULL #if !defined(__MINGW32__) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) #define _ULL(x) x##ul #else #define _ULL(x) x##ull #endif #endif #define dcassert(x) #endif //_INCLUDED_COMPAT_H_ libdc0-0.3.24~svn3121/dclib/hash/changes.txt0000644000175000017500000000124211175406626017401 0ustar sikonsikonHashValue.h - Removed FastAlloc.h , not required for dclib - Removed Encoder.h, not required for dclib - Removed tr1 definition, not required for dclib MerkleTree.h - Removed Encoder.h, not required at all - Re-use the Hasher rather than re-allocate it. Requires the TigerHash.h change. TigerHash.h - Add reset() so a TigerHash can be re-used. TigerHash.cpp - Replace stdinc.h and DCPlusPlus.h with compat.h for dclib - Use autoconf to determine if big endian. - Remove unused tigerCompress function, which was doing nothing besides expanding that macro one more time. - Always use TIGER_ARCH64 code. It works and is slightly more efficient even on 32bit systems. libdc0-0.3.24~svn3121/dclib/hash/HashValue.h0000644000175000017500000000310011104412031017227 0ustar sikonsikon/* * Copyright (C) 2001-2008 Jacek Sieka, arnetheduck on gmail point com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DCPLUSPLUS_DCPP_HASH_VALUE_H #define DCPLUSPLUS_DCPP_HASH_VALUE_H namespace dcpp { template struct HashValue { static const size_t BITS = Hasher::BITS; static const size_t BYTES = Hasher::BYTES; HashValue() { } explicit HashValue(uint8_t* aData) { memcpy(data, aData, BYTES); } HashValue(const HashValue& rhs) { memcpy(data, rhs.data, BYTES); } HashValue& operator=(const HashValue& rhs) { memcpy(data, rhs.data, BYTES); return *this; } bool operator!=(const HashValue& rhs) const { return !(*this == rhs); } bool operator==(const HashValue& rhs) const { return memcmp(data, rhs.data, BYTES) == 0; } bool operator<(const HashValue& rhs) const { return memcmp(data, rhs.data, BYTES) < 0; } uint8_t data[BYTES]; }; } // namespace dcpp #endif // !defined(HASH_VALUE_H) libdc0-0.3.24~svn3121/dclib/hash/dcpp-to-dclib.diff0000644000175000017500000001050211175406626020502 0ustar sikonsikon--- dcpp/HashValue.h 2008-09-04 13:30:52.000000000 +0100 +++ dclib/HashValue.h 2008-11-05 21:45:00.000000000 +0000 @@ -19,39 +19,24 @@ #ifndef DCPLUSPLUS_DCPP_HASH_VALUE_H #define DCPLUSPLUS_DCPP_HASH_VALUE_H -#include "FastAlloc.h" -#include "Encoder.h" - namespace dcpp { template -struct HashValue : FastAlloc >{ +struct HashValue { static const size_t BITS = Hasher::BITS; static const size_t BYTES = Hasher::BYTES; HashValue() { } explicit HashValue(uint8_t* aData) { memcpy(data, aData, BYTES); } - explicit HashValue(const std::string& base32) { Encoder::fromBase32(base32.c_str(), data, BYTES); } HashValue(const HashValue& rhs) { memcpy(data, rhs.data, BYTES); } HashValue& operator=(const HashValue& rhs) { memcpy(data, rhs.data, BYTES); return *this; } bool operator!=(const HashValue& rhs) const { return !(*this == rhs); } bool operator==(const HashValue& rhs) const { return memcmp(data, rhs.data, BYTES) == 0; } bool operator<(const HashValue& rhs) const { return memcmp(data, rhs.data, BYTES) < 0; } - std::string toBase32() const { return Encoder::toBase32(data, BYTES); } - std::string& toBase32(std::string& tmp) const { return Encoder::toBase32(data, BYTES, tmp); } - uint8_t data[BYTES]; }; } // namespace dcpp -namespace std { namespace tr1 { -template -struct hash > { - size_t operator()(const dcpp::HashValue& rhs) const { return *(size_t*)rhs.data; } -}; -} -} - #endif // !defined(HASH_VALUE_H) --- dcpp/MerkleTree.h 2008-09-04 13:30:40.000000000 +0100 +++ dclib/MerkleTree.h 2009-04-27 13:21:53.000000000 +0100 @@ -20,7 +20,6 @@ #define MERKLE_TREE_H #include "TigerHash.h" -#include "Encoder.h" #include "HashValue.h" namespace dcpp { @@ -97,9 +96,11 @@ public: if(len == 0 && !(leaves.empty() && blocks.empty())) return; + Hasher h; + size_t n; do { - size_t n = min(baseBlockSize, len-i); - Hasher h; + n = min(baseBlockSize, len-i); + h.reset(); h.update(&zero, 1); h.update(buf + i, n); if((int64_t)baseBlockSize < blockSize) { --- dcpp/TigerHash.h 2008-09-04 13:30:49.000000000 +0100 +++ dclib/TigerHash.h 2009-04-27 17:32:35.000000000 +0100 @@ -27,10 +27,8 @@ public: static const size_t BITS = 192; static const size_t BYTES = BITS / 8; - TigerHash() : pos(0) { - res[0]=_ULL(0x0123456789ABCDEF); - res[1]=_ULL(0xFEDCBA9876543210); - res[2]=_ULL(0xF096A5B4C3B2E187); + TigerHash() { + reset(); } ~TigerHash() { @@ -42,6 +40,15 @@ public: uint8_t* finalize(); uint8_t* getResult() { return (uint8_t*) res; } + + /** Initializes state, allowing for re-use. */ + void reset() + { + pos = 0; + res[0]=_ULL(0x0123456789ABCDEF); + res[1]=_ULL(0xFEDCBA9876543210); + res[2]=_ULL(0xF096A5B4C3B2E187); + } private: enum { BLOCK_SIZE = 512/8 }; /** 512 bit blocks for the compress function */ @@ -52,8 +59,6 @@ private: uint64_t pos; /** S boxes */ static uint64_t table[]; - - void tigerCompress(const uint64_t* data, uint64_t state[3]); }; } // namespace dcpp --- dcpp/TigerHash.cpp 2009-03-04 16:26:52.000000000 +0000 +++ dclib/TigerHash.cpp 2009-04-27 20:35:47.000000000 +0100 @@ -16,28 +16,25 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "stdinc.h" -#include "DCPlusPlus.h" +#include "compat.h" #include "TigerHash.h" namespace dcpp { -#ifdef _WIN32 -#if defined(_M_X64) -#define TIGER_ARCH64 +#ifdef HAVE_CONFIG_H +#include #endif -#if !(defined(_M_IX86) || defined(_M_X64)) + +/* + * Convert autoconf defines to whatever this code is using. + */ +#ifdef WORDS_BIGENDIAN #define TIGER_BIG_ENDIAN #endif -#else // _WIN32 -#if defined(__x86_64__) || defined(__alpha) + +/* it works correctly, and uses less cpu, even on 32bit systems */ #define TIGER_ARCH64 -#endif -#if !(defined(__i386__) || defined(__x86_64__) || defined(__alpha)) -#define TIGER_BIG_ENDIAN -#endif -#endif // _WIN32 #define PASSES 3 @@ -150,11 +147,6 @@ namespace dcpp { state[2] = c; \ } -/* The compress function is a function. Requires smaller cache? */ -void TigerHash::tigerCompress(const uint64_t *str, uint64_t state[3]) { - tiger_compress_macro(((const uint64_t*)str), ((uint64_t*)state)); -} - void TigerHash::update(const void* data, size_t length) { size_t tmppos = (uint32_t)(pos & (BLOCK_SIZE - 1)); #ifdef TIGER_BIG_ENDIAN libdc0-0.3.24~svn3121/dclib/clistenmanager.cpp0000644000175000017500000001262211103674075020005 0ustar sikonsikon/*************************************************************************** clistenmanager.cpp - description ------------------- begin : Sun Feb 29 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "clistenmanager.h" #include #ifdef WIN32 #include #else #include #include #include #endif #include "dcos.h" #include "dcobject.h" #include "core/clisten.h" #include "core/cmanager.h" #include "cdownloadmanager.h" #include "cconfig.h" /* most of these messages are normal and just informative */ #include "dclib.h" /** */ CListenManagerBase::CListenManagerBase() { m_pListen = 0; m_nListenPort = 0; m_bCrypto = false; m_pCallback = 0; } /** */ CListenManagerBase::~CListenManagerBase() { m_Mutex.Lock(); if ( m_pCallback ) { if ( CManager::Instance() ) CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; } delete m_pListen; m_pListen = 0; m_Mutex.UnLock(); } /** */ unsigned int CListenManagerBase::GetListenPort() { unsigned int n; m_Mutex.Lock(); n = m_nListenPort; m_Mutex.UnLock(); return n; } /** */ void CListenManagerBase::StartListen() { int n; delete m_pListen; m_pListen = 0; // reset listen port m_nListenPort = 0; // sanity check if ( CConfig::Instance() ) { if ( m_bCrypto ) { n = CConfig::Instance()->GetCryptoListenPort(); } else { n = CConfig::Instance()->GetTCPListenPort(); } if ( (n != 0) && (CConfig::Instance()->GetMode(true) == ecmACTIVE) ) { if ( m_bCrypto ) { DPRINTF("CCryptoListenManager"); } else { DPRINTF("CListenManager"); } DPRINTF("::StartListen: active mode port = %d\n",n); m_pListen = new CListen(); // start listen if ( m_pListen->StartListen( n, CConfig::Instance()->GetListenHostString() ) == 0 ) { m_pListen->SetCallBackFunction( CreateListenCallback() ); m_nListenPort = n; m_sSocketError.Empty(); } else { // print error message only one time if ( m_pListen->GetSocketError() != m_sSocketError ) { m_sSocketError = m_pListen->GetSocketError(); if ( m_bCrypto ) { printf("CCryptoListenManager"); } else { printf("CListenManager"); } printf("::StartListen error: '%s'\n",m_sSocketError.Data()); } } } else { if ( m_bCrypto ) { DPRINTF("CCryptoListenManager"); } else { DPRINTF("CListenManager"); } DPRINTF("::StartListen: passive mode\n"); if ( m_sSocketError.NotEmpty() ) { m_sSocketError.Empty(); } } } } /** */ int CListenManagerBase::ManagerCallback() { m_Mutex.Lock(); if ( CConfig::Instance() ) { if ( m_pListen ) { if ( CConfig::Instance()->GetMode(true) == ecmACTIVE ) { if ( m_pListen->IsConnect() == -1 ) { StartListen(); } if ( m_bCrypto ) { if ( CConfig::Instance()->GetCryptoListenPort() != m_nListenPort ) { StartListen(); } } else { if ( CConfig::Instance()->GetTCPListenPort() != m_nListenPort ) { StartListen(); } } } else { StartListen(); } } else { if ( CConfig::Instance()->GetMode(true) == ecmACTIVE ) { StartListen(); } } } m_Mutex.UnLock(); return 0; } /** */ int CListenManagerBase::ListenCallback( int handle ) { m_Mutex.Lock(); if ( m_bCrypto ) { DPRINTF("CCryptoListenManager"); } else { DPRINTF("CListenManager"); } DPRINTF(": incoming connection %d\n",handle); if ( CDownloadManager::Instance() ) { CDownloadManager::Instance()->ListenCallbackHandler( handle, m_bCrypto ); } else { #ifdef WIN32 closesocket(handle); #else close(handle); #endif } m_Mutex.UnLock(); return 0; } /** */ CListenManager::CListenManager() { m_bCrypto = false; m_pCallback = new CCallback0( this, &CListenManager::ManagerCallback ); CManager::Instance()->Add( m_pCallback ); } /** */ CListenManager::~CListenManager() { SetInstance(0); } /** */ _CCallback1 * CListenManager::CreateListenCallback() { return new CCallback1( this, &CListenManager::ListenCallback ); } /** */ CCryptoListenManager::CCryptoListenManager() { m_bCrypto = true; m_pCallback = new CCallback0( this, &CCryptoListenManager::ManagerCallback ); CManager::Instance()->Add( m_pCallback ); } /** */ CCryptoListenManager::~CCryptoListenManager() { SetInstance(0); } /** */ _CCallback1 * CCryptoListenManager::CreateListenCallback() { return new CCallback1( this, &CCryptoListenManager::ListenCallback ); } libdc0-0.3.24~svn3121/dclib/cutils.h0000644000175000017500000000430211101144617015745 0ustar sikonsikon/*************************************************************************** cutils.h - description ------------------- begin : Fri May 16 2003 copyright : (C) 2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CUTILS_H #define CUTILS_H /** *@author Mathias Küster * * Formatting of sizes, times and rates. Also parsing of dcfile:// links. * * This whole thing should probably be in valknut, QString is more * efficient and the units could be translated. I don't think dclib * ever has to process a dcfile:// link and valknut and other clients * use magnet links anyway. */ #include #include #include class CUtils { public: /** */ static CString GetSizeString( const ulonglong size, eUnit unit ); /* This will Convert Total Secs to how much time is * remaining X Days + X Hrs + X Mins + X Secs */ static CString GetTimeString( const ulonglong sec ); /** */ static CString GetTransferString( const ulonglong rate ); /** */ static bool ConvertDCLink( CString link, CString & hubhost, CString & hubname, CString & nick, ulonglong & size, CString & file, CString & tth ); /** Extract major, minor and micro version numbers from a DC tag, returns true if at least major is found */ static bool ParseVersionTag( const CString tag, int & major, int & minor, int & micro ); protected: /** */ CUtils(); /** */ ~CUtils(); }; #endif libdc0-0.3.24~svn3121/dclib/cclientssl.h0000644000175000017500000000344211101144617016611 0ustar sikonsikon/*************************************************************************** cclientssl.h - description ------------------- begin : Sat Dec 7 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCLIENTSSL_H #define CCLIENTSSL_H /** *@author Mathias Küster * * Class for the encrypted private chat dclib system. * Not really a protocol extension, just special private chat messages * for a client to interpret. */ #include #include #include class CClient; class CMessagePrivateChat; class CClientSSL : public CSSL { public: /** */ CClientSSL(); /** */ virtual ~CClientSSL(); /** */ void PrivateChat( CClient * client, CMessagePrivateChat * msg ); /** */ void Init(); /** */ CString EncryptMessage( CClient * client, CString nick, CString message ); /** */ void LeaveHub( CClient * client, CString nick ); private: /** */ CStringList * m_pCryptPrivateMessageList; }; #endif libdc0-0.3.24~svn3121/dclib/dcos.h.in0000644000175000017500000000411111237264674016015 0ustar sikonsikon/*************************************************************************** dcos.h - description ------------------- begin : Sat Oct 6 2001 copyright : (C) 2001-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef _OS_H_ #define _OS_H_ /* 24 in decimal is 18 in hex */ #define DCLIB_VERSION 0x000318 #define DCLIB_VERSION_STRING "@PACKAGE_VERSION@" #ifdef WIN32 #include #include #include #include #include #include #ifdef _DEBUG #ifndef _CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC #endif #include #include #else #include #endif /* same as QT4 qint64 / quint64, non gcc untested */ #if defined(_MSC_VER) typedef __int64 longlong; typedef unsigned __int64 ulonglong; #else typedef long long longlong; typedef unsigned long long ulonglong; #endif #define F_OK 0 #define R_OK 4 #define W_OK 2 #define RW_OK 6 #define DIRSEPARATOR '\\' #else /* !WIN32 */ typedef unsigned long long ulonglong; #define DIRSEPARATOR '/' #endif #ifndef SOCKET #define SOCKET int #endif #ifndef INVALID_SOCKET #define INVALID_SOCKET -1 #endif #ifndef SOCKET_ERROR #define SOCKET_ERROR -1 #endif /* stdint.h using exact width types is going to replace ulonglong */ #include #endif libdc0-0.3.24~svn3121/dclib/csearchsocket.cpp0000644000175000017500000000630511112363266017630 0ustar sikonsikon/*************************************************************************** csearchsocket.cpp - description ------------------- begin : Thu May 27 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "csearchsocket.h" #include #include "dclib.h" #include "core/cstring.h" #include "cmessagehandler.h" #include "dcobject.h" /** */ CSearchSocket::CSearchSocket() : CSocket( estUDP ) { m_pCallback = 0; /* * It's only for 1 packet but this is what * is was when this was a CConnection. */ m_Buffer.SetSize(50*1024); } /** */ CSearchSocket::~CSearchSocket() { SetCallBackFunction(0); } /** */ eConnectState CSearchSocket::Connect( CString Host, int Port, bool iAsync ) { m_SearchSocketMutex.Lock(); const eConnectState res = CSocket::Connect( Host, Port, iAsync ); m_SearchSocketMutex.UnLock(); return res; } /** */ int CSearchSocket::Disconnect() { m_SearchSocketMutex.Lock(); const int res = CSocket::Disconnect(); m_SearchSocketMutex.UnLock(); return res; } /** */ void CSearchSocket::Receive( int maxpackets ) { m_SearchSocketMutex.Lock(); int p, err, len; eDCMessage type; CDCMessage * Object; CMessageHandler * MessageHandler = 0; CString s; for ( int packets = 0; packets < maxpackets; ++packets ) { len = Read( (char*)m_Buffer.Data(), m_Buffer.Size(), 0, 1 ); if ( len <= 0 ) { break; } s.Set( (const char*) m_Buffer.Data(), len ); /* add '|' for parser, only old dclib did not terminate search results? */ s += '|'; /* add traffic control */ CSocket::m_Traffic.AddTraffic(ettCONTROLRX,len); p = 0; Object = 0; if ( !MessageHandler ) { MessageHandler = new CMessageHandler(); } while( (type=MessageHandler->Parse(&s,p,&Object)) != DC_MESSAGE_PARSE_ERROR ) { switch (type) { case DC_MESSAGE_SEARCHRESULT: { if ( Object ) { ((CMessageSearchResult*) Object)->m_sSrcIP = GetResolvedIP(); } break; } default: { // remove message delete Object; Object = 0; break; } } if ( Object ) { err = -1; if ( m_pCallback ) { err = m_pCallback->notify( (CMessageSearchResult*) Object ); } if ( err == -1 ) { printf("CSearchSocket::HandleMessage: CallBack failed (state)...\n"); delete Object; } } } } delete MessageHandler; m_SearchSocketMutex.UnLock(); } libdc0-0.3.24~svn3121/dclib/cquerymanager.cpp0000644000175000017500000003357511101154437017657 0ustar sikonsikon/*************************************************************************** cquerymanager.cpp - description ------------------- begin : Sat Jun 8 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cquerymanager.h" #include #ifndef WIN32 #include #endif #include "cconnectionmanager.h" #include "cdownloadqueue.h" #include "cdownloadmanager.h" #include "cfilemanager.h" #include "cconfig.h" #include "core/cmanager.h" #include "csearchindex.h" #include "core/ciconv.h" #include "core/cmutex.h" /* for proper case-insensitive searching */ #include "ccasefolder.h" #define MAX_SEARCH_RESULTS 10 #define MAX_SEARCH_RESULTS_PASSIVE 5 #define MAX_QUERY_QUEUE_COUNT 25 #define QUERY_TIMEOUT 10 #include /** */ CQueryManager::CQueryManager() { m_pQueueMutex = new CMutex(); m_pQueryQueue = new CList; m_pQuerySendList = new CList; m_nSearchCountActive = 0; m_nSearchCountPassive = 0; m_nSearchCountReject = 0; m_nSearchCountError = 0; m_nResultCount = 0; m_nResultCountError = 0; m_pCaseFolder = new CCaseFolder(); m_pCallback = new CCallback0( this, &CQueryManager::Callback ); CManager::Instance()->Add( m_pCallback ); } /** */ CQueryManager::~CQueryManager() { SetInstance(0); CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; delete m_pCaseFolder; delete m_pQueryQueue; delete m_pQuerySendList; delete m_pQueueMutex; } /** */ bool CQueryManager::CheckSize( CQueryObject * queryobject, struct filebaseobject * fbo ) { bool res = true; // check file size if ( queryobject->pMessageSearch->m_bSizeLimit ) { if ( queryobject->pMessageSearch->m_eSizeType == esstATMOST ) { if ( fbo->m_nSize > queryobject->pMessageSearch->m_nSize ) { res = false; } } else { if ( fbo->m_nSize < queryobject->pMessageSearch->m_nSize ) { res = false; } } } return res; } /** */ bool CQueryManager::CheckType( CQueryObject * queryobject, struct filebaseobject * fbo ) { bool res = true; // check file type switch(queryobject->pMessageSearch->m_eFileType) { case eftALL: case eftHASH: /* the TTH: prefix is now added/removed at the lowest level */ break; case eftMP3: case eftARCHIVE: case eftDOCUMENT: case eftAPPLICATION: case eftPICTURE: case eftVIDEO: case eftFOLDER: if ( queryobject->pMessageSearch->m_eFileType != eFileTypes(fbo->m_eFileType) ) { res = false; } break; default: res = false; break; } return res; } /** */ bool CQueryManager::AddResult( CQuerySendObject * querysendobject, CQueryObject * queryobject, struct filebaseobject * fbo, CString filename, CString hash ) { CString s, result; int slot_max,slot_free; CIconv ciconv( CConfig::Instance()->GetLocalEncoding(), CConfig::Instance()->GetRemoteEncoding() ); // get slot info slot_max = CConfig::Instance()->GetMaxUpload(); slot_free = CDownloadManager::Instance()->DLM_UsedSlots(); // unlimit slots if ( slot_max == 0 ) { slot_max = 99+slot_free; } // check for extra slots if ( slot_free > slot_max ) { slot_free = 0; } else { slot_free = slot_max-slot_free; } // create the searchresult s += ciconv.encode(filename); s.Swap('/','\\'); result = "$SR "; result += ciconv.encode(queryobject->sNick); result += ' '; // folder results do not have size if ( fbo->m_eFileType != eftFOLDER ) { result += s; result += "\x5"; result += CString::number(fbo->m_nSize); result += ' '; } else { s = s.Replace("\\\\", "\\"); if ( s.NotEmpty() && (s.Data()[0] == '\\') ) { s = s.Mid( 1, s.Length() - 1 ); } result += s; result += ' '; } result += CString::number(slot_free); result += '/'; result += CString::number(slot_max); result += "\x5"; // add hash or hubname to searchresult if ( hash.IsEmpty() ) { result += ciconv.encode(queryobject->sHubName); } else { result += "TTH:"; result += hash; } result += " ("; result += queryobject->sHubHost; result += ')'; // result found ! send it ... if ( queryobject->pMessageSearch->m_bLocal ) { result += "\x5"; result += ciconv.encode(queryobject->pMessageSearch->m_sSource); result += '|'; querysendobject->m_pList->push_back(result); // printf("ADD L RESULT: '%s'\n",result.Data()); } else { result += '|'; querysendobject->m_pList->push_back(result); // printf("ADD G RESULT: '%s'\n",result.Data()); } return true; } /** */ void CQueryManager::SendResults() { CQuerySendObject * querysendobject = 0; while ( (querysendobject=m_pQuerySendList->Next(querysendobject)) != 0 ) { if ( querysendobject->m_pSocket ) { eConnectState e; e = querysendobject->m_pSocket->Connect( querysendobject->m_sSource, querysendobject->m_nPort, true ); if ( e == ecsSUCCESS ) { for ( std::list::const_iterator it = querysendobject->m_pList->begin(); it != querysendobject->m_pList->end(); ++it ) { if ( querysendobject->m_pSocket->Write( (const unsigned char*)it->Data(), it->Length(), 2 ) <= 0 ) { m_nResultCountError++; break; } else { m_nResultCount++; } } querysendobject->m_pSocket->Disconnect(); m_pQuerySendList->Del(querysendobject); } else if ( e == ecsERROR ) { m_pQuerySendList->Del(querysendobject); m_nResultCountError++; } break; } else { for ( std::list::const_iterator it = querysendobject->m_pList->begin(); it != querysendobject->m_pList->end(); ++it ) { if ( CConnectionManager::Instance()->SendStringToConnectedServers(*it,querysendobject->m_sSource,false) == 0 ) { m_nResultCountError++; break; } else { m_nResultCount++; } } m_pQuerySendList->Del(querysendobject); break; } } } /** */ void CQueryManager::HandleQuery( CQueryObject * queryobject ) { CString search; CString filename; std::set * results = 0; struct filebaseobject FileBaseObject; CQuerySendObject * querysendobject; CString s,s1; long i; bool dummy = false; unsigned int resultcount; unsigned int maxresults; /* CFileManager now handles everything */ std::list words; // no passive to passive results, otherwise set max results if ( queryobject->pMessageSearch->m_bLocal ) { if ( CConfig::Instance() && (CConfig::Instance()->GetMode() == ecmPASSIVE) ) { return; } maxresults = MAX_SEARCH_RESULTS_PASSIVE; } else { maxresults = MAX_SEARCH_RESULTS; } // get searchstring if ( queryobject->pMessageSearch->m_eFileType == eftHASH ) { search = queryobject->pMessageSearch->m_sString.ToUpper(); } else { if ( m_pCaseFolder->Fold( queryobject->pMessageSearch->m_sString, search ) == false ) { // failed, fallback search = queryobject->pMessageSearch->m_sString.ToLower(); } } // sanity check if ( search.IsEmpty() ) { return; } // check for dummy search if ( search == "." ) { dummy = true; } if ( !dummy ) { if ( queryobject->pMessageSearch->m_eFileType == eftHASH ) { results = CFileManager::Instance()->SearchHash( search ); } else { // replace Windows dir separators with ours s = search; s.Swap('\\',DIRSEPARATOR); s += ' '; while( (i=s.Find(' ')) != -1 ) { // get substring s1 = s.Left(i); // remove substring from string s = s.Mid(i+1,s.Length()-i-1); i++; /* sanity check */ if ( s1.IsEmpty() ) { continue; } else { words.push_back(s1); } } if ( queryobject->pMessageSearch->m_bSizeLimit && !((queryobject->pMessageSearch->m_eSizeType == esstATLEAST) && (queryobject->pMessageSearch->m_nSize == 0)) ) { if ( queryobject->pMessageSearch->m_eSizeType == esstATLEAST ) { if ( queryobject->pMessageSearch->m_eFileType == eftALL ) { results = CFileManager::Instance()->SearchAtLeast( maxresults, &words, queryobject->pMessageSearch->m_nSize ); } else { results = CFileManager::Instance()->SearchAtLeast( maxresults, &words, queryobject->pMessageSearch->m_nSize, queryobject->pMessageSearch->m_eFileType ); } } else { if ( queryobject->pMessageSearch->m_eFileType == eftALL ) { results = CFileManager::Instance()->SearchAtMost( maxresults, &words, queryobject->pMessageSearch->m_nSize ); } else { results = CFileManager::Instance()->SearchAtMost( maxresults, &words, queryobject->pMessageSearch->m_nSize, queryobject->pMessageSearch->m_eFileType ); } } } else { if ( queryobject->pMessageSearch->m_eFileType == eftALL ) { results = CFileManager::Instance()->Search( maxresults, &words ); } else { results = CFileManager::Instance()->Search( maxresults, &words, queryobject->pMessageSearch->m_eFileType ); } } } } if ( ((results != 0) && (results->size() > 0)) || dummy ) { // results found ... resultcount = 0; // create resultobject querysendobject = new CQuerySendObject(); // init passive or active search result if ( queryobject->pMessageSearch->m_bLocal == false ) { querysendobject->m_pSocket = new CSocket(estUDP); querysendobject->m_sSource = queryobject->pMessageSearch->m_sSource; querysendobject->m_nPort = queryobject->pMessageSearch->m_nPort; } else { querysendobject->m_sSource = queryobject->sHubName; } // real query if ( dummy == false ) { std::set::const_iterator results_it = results->begin(); while( (results_it != results->end()) && (resultcount < maxresults) ) { // get the fileobject for this resultid if ( CFileManager::Instance()->GetFileBaseObject( *results_it, &FileBaseObject, filename ) ) { /* CFileManager now handles type and size of non-TTH searches */ if ( queryobject->pMessageSearch->m_eFileType == eftHASH ) { // check if filesize correct if ( CheckSize( queryobject, &FileBaseObject ) == false ) { ++results_it; continue; } // check if filetype correct if ( CheckType( queryobject, &FileBaseObject ) == false ) { ++results_it; continue; } } CString hash; hash = CFileManager::Instance()->GetHash(FileBaseObject.m_nHashIndex); // add result if ( AddResult( querysendobject, queryobject, &FileBaseObject, filename, hash ) == false ) { break; } resultcount++; } ++results_it; } } else { // add dummy result struct filebaseobject fbo; fbo.m_nSize = 0; AddResult( querysendobject, queryobject, &fbo, "." ); } if ( querysendobject->m_pList->empty() ) { delete querysendobject; } else { m_pQuerySendList->Add(querysendobject); } } if ( results ) { results->clear(); delete results; } } /** */ int CQueryManager::Callback() { CQueryObject * queryobject; m_pQueueMutex->Lock(); // get searches from the queue while ( (queryobject = m_pQueryQueue->Next(0)) != 0 ) { // remove it from the list m_pQueryQueue->Remove(queryobject); // query timeout in seconds if ( (time(0)-queryobject->tTimeout) > QUERY_TIMEOUT ) { // remove it delete queryobject; queryobject = 0; // reject statistic m_nSearchCountReject++; } else { break; } } m_pQueueMutex->UnLock(); // sanity check / object not rejected if (queryobject) { // handle query HandleQuery(queryobject); // remove object delete queryobject; } // send any results from the result queue SendResults(); return 0; } /** store all searches from the hub in a queue */ bool CQueryManager::SearchQuery( CString hubname, CString hubhost, CString nick, CMessageSearchFile * msg ) { bool res = false; CQueryObject * queryobject; // sanity check if ( msg == 0) { return res; } m_pQueueMutex->Lock(); // active/passive search statistic if ( msg->m_bLocal == false ) { m_nSearchCountActive++; } else { m_nSearchCountPassive++; } // queue overflow ? if ( m_pQueryQueue->Count() < MAX_QUERY_QUEUE_COUNT ) { // sanity check if ( (hubname.NotEmpty()) && (hubhost.NotEmpty()) ) { // create query object and add it to the queue queryobject = new CQueryObject(); queryobject->sHubName = hubname; queryobject->sHubHost = hubhost; queryobject->sNick = nick; queryobject->tTimeout = time(0); queryobject->pMessageSearch = new CMessageSearchFile(); *queryobject->pMessageSearch = *msg; m_pQueryQueue->Add(queryobject); res = true; } else { // error statistic m_nSearchCountError++; } } else { // reject statistic m_nSearchCountReject++; } m_pQueueMutex->UnLock(); return res; } /** query mananger stats */ ulonglong CQueryManager::GetStat( enum eSearchStat e ) { ulonglong res = 0; switch(e) { case essCOUNTACTIVE: res = m_nSearchCountActive; break; case essCOUNTPASSIVE: res = m_nSearchCountPassive; break; case essCOUNTREJECT: res = m_nSearchCountReject; break; case essCOUNTERROR: res = m_nSearchCountError; break; case essRESULTCOUNT: res = m_nResultCount; break; case essRESULTCOUNTERROR: res = m_nResultCountError; break; default: break; } return res; } libdc0-0.3.24~svn3121/dclib/dclib.h0000644000175000017500000000346311103434224015524 0ustar sikonsikon/*************************************************************************** dclib.h - description ------------------- begin : Mon May 5 2003 copyright : (C) 2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DCLIB_H #define DCLIB_H /* */ #include /** *@author Mathias Küster */ #include #ifdef __cplusplus extern "C" { #endif /** * Initialise used libraries. * Parameter must be argv[0]. * Parameter is only used if compiled for socks proxy support. */ void dclibInitDepLibs( char * argv0 ); /** cleanup used libraries */ void dclibDeInitDepLibs(); /** get dclib start time */ time_t dclibUptime(); /** get dclib version string */ const char * dclibVersion(); /** get dclib build date and if svn, the revision */ const char * dclibBuildInfo(); /** get dclib verbose setting */ int dclibVerbose(); /** set dclib verbose */ void setdclibVerbose( int n ); /** get SSL support */ bool dclibSupportsSSL(); #define DPRINTF if (dclibVerbose()) printf #ifdef __cplusplus } #endif #endif libdc0-0.3.24~svn3121/dclib/dclib.cpp0000644000175000017500000000500111103673767016066 0ustar sikonsikon/*************************************************************************** dclib.cpp - description ------------------- begin : Mon May 5 2003 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "dclib.h" #include "dclib-ssl-use.h" #include "core/cxml.h" #include "core/cssl.h" #include "core/csocket.h" #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_SOCKS extern "C" { #include } #endif static time_t sdclibUptime = time(0); static int sdclibVerbose = 0; /** initialise used libraries */ #ifdef HAVE_SOCKS extern "C" void dclibInitDepLibs( char * argv0 ) #else extern "C" void dclibInitDepLibs( char * /* argv0 */ ) #endif { #ifdef HAVE_SOCKS SOCKSinit(argv0); #endif CXml::InitParser(); CSSL::InitSSLLibrary(); /* * Any error is not checked, if WinSock2 doesn't startup nothing * network related will work, and probably all that can be done * is abort(). */ CSocket::SysInit(); } /** cleanup used libraries */ extern "C" void dclibDeInitDepLibs() { /* the reverse order to the startup makes sense */ CSocket::SysDeInit(); CSSL::DeInitSSLLibrary(); CXml::CleanupParser(); } /** get dclib start time */ extern "C" time_t dclibUptime() { return sdclibUptime; } /** get dclib version string */ extern "C" const char * dclibVersion() { return DCLIB_VERSION_STRING; } /** get dclib build data and if svn, the revision */ extern "C" const char * dclibBuildInfo() { return DCLIB_BUILD_INFO; } /** get dclib verbose setting */ extern "C" int dclibVerbose() { return sdclibVerbose; } /** set dclib verbose */ extern "C" void setdclibVerbose( int n ) { sdclibVerbose = n; } /** get SSL support */ extern "C" bool dclibSupportsSSL() { return (DCLIB_HAS_SSL == 1); } libdc0-0.3.24~svn3121/dclib/cuserlist.h0000644000175000017500000000571211112566665016502 0ustar sikonsikon/*************************************************************************** cuserlist.h - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CUSERLIST_H #define CUSERLIST_H /** *@author Mathias Küster * * The list of users is a map to nicks to CMessageMyInfo objects. * Using std::map means it is ordered by nick, but this property is * not required nor used. */ #include #include #include #include #include class CDCMessage; class CMessageNickList; class CMessageOpList; class CMessageMyInfo; typedef std::map MyInfoMap; class CUserList { public: /** */ CUserList(); /** */ virtual ~CUserList(); /** */ void Clear(); /** user list functions */ void InitUserList( CMessageNickList * NickList ); /** */ void InitOperatorList( CMessageOpList * OpList ); /** */ bool AppendUser( CString & nick, bool getinfo = true ); /** */ void RemoveUser( CString & nick ); /** */ bool UpdateUser( CMessageMyInfo * pMyInfo ); /** */ bool IsUserOnline( CString & nick ); /** */ bool IsAdmin( const CString & nick ); /** */ eUserClientVersion GetUserClientVersion( const CString & nick ); /** */ bool GetUserMyInfo( CString nick, CMessageMyInfo * p ); /** */ bool SetUserTransferInfo( CString nick, CDCMessage * msg ); /** * Sets the nick's IP. * * Returns true if there is a user and the IP was * different. This will not mean much since * details from transfers include the port but * details from the UserIP2 extensions do not. */ bool SetUserIP( const CString & nick, const CString & ip ); /** */ ulonglong ShareSize() { return m_nShareSize; }; /** * Returns the nick in the userlist after the given nick. * If nick is empty, returns the first nick. * Returns an empty string if there are no nicks in the list, * the given nick is not in the list, or the given nick is the last nick. */ CString GetNextNick( const CString & nick ); private: /** */ CMutex m_Mutex; /** */ MyInfoMap m_MyInfoMap; /** */ ulonglong m_nShareSize; }; #endif libdc0-0.3.24~svn3121/dclib/core/0000755000175000017500000000000011556467002015234 5ustar sikonsikonlibdc0-0.3.24~svn3121/dclib/core/cconnection.h0000644000175000017500000000742411103425621017703 0ustar sikonsikon/*************************************************************************** cconnection.h - description ------------------- begin : Sat Oct 6 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCONNECTION_H #define CCONNECTION_H /** *@author Mathias Küster * * A network connection, it extends CSocket to provide some * buffers and state, and also a loop to send and receive the data. * * Although it inherits CThread dclib does not start any, the * Thread() function is probably called by CConnectionManager for * hubs or CDownloadManager for peers, which in turn run on CManager's * thread. */ #include #include #include #include #include class CByteArray; class CMutex; class CConnection : public CThread, public CSocket { public: /** */ CConnection(); /** */ virtual ~CConnection(); /** */ int Connect(); /** */ int Connect( CString ip, eSocketType sockettype = estTCP ); /** */ int Connect( CString ip, int port, eSocketType sockettype = estTCP ); /** */ virtual int Disconnect( bool force = false ); /** */ int SetSocket( int handle, eSocketType sockettype = estTCP ); /** */ virtual void DataAvailable( const char *, int ) {}; /** */ virtual void DataSend() {}; /** */ virtual void DataTimeout() {}; /** */ virtual void Notify() {}; /** */ virtual void ConnectionState( eConnectionState ) {}; /** */ virtual void Thread(); /** * true if all data send from the queue and the queue is empty * false if data to send in the queue */ bool IsSendQueueEmpty(); /** */ virtual bool ChangeSocketMode( eSocketMode mode, CString cert = CString(), CString key = CString() ); /** */ void SetHost( CString ip, int port = 411 ); /** */ CString GetHost( bool peername = false ); /** */ CString GetIP() const; /** */ int GetPort() const; /** */ eConnectionState GetConnectionState() const; protected: /** */ int Write( const unsigned char * buffer, int len, bool direct = false ); private: /** */ void StateConnect(); /** */ void StateConnecting(); /** */ void StateRead(); /** */ void StateSend(); /** */ void StateDisconnect(); /** */ void connectionState( eConnectionState e ); /** */ eConnectionState m_eState; /** */ time_t m_timeNotify; /** check for connection/data timeout */ time_t m_timeConnection; /** */ CMutex * m_pConnMutex; /** */ bool m_bForceDisconnect; /** */ CString m_sIP; /** */ int m_nPort; /** */ CMutex * m_pSendListMutex; /** */ CList * m_pSendList; /** */ CByteArray * m_pBuffer; /** */ int m_nConnectTimeout; }; /** inline functions */ /** */ inline void CConnection::SetHost( CString ip, int port ) { m_sIP=ip;m_nPort=port; } /** */ inline CString CConnection::GetIP() const { return m_sIP; } /** */ inline int CConnection::GetPort() const { return m_nPort; } /** */ inline eConnectionState CConnection::GetConnectionState() const { return m_eState; } #endif libdc0-0.3.24~svn3121/dclib/core/cfile.cpp0000644000175000017500000002274411103425621017020 0ustar sikonsikon/*************************************************************************** cfile.cpp - description ------------------- begin : Wed Apr 3 2003 copyright : (C) 2003-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cfile.h" #include #include #include #include #ifndef WIN32 #include #include #include #endif #include "cbytearray.h" #define FILE_BUFFER_SIZE (100*1024) /** */ CFile::CFile() { m_nFD = -1; m_pBuffer = 0; } /** */ CFile::~CFile() { Close(); delete m_pBuffer; m_pBuffer = 0; } /** */ bool CFile::Open( CString filename, int mode, int acc ) { bool res = false; int m = 0, a = 0; if ( (m_nFD != -1) || filename.IsEmpty() ) { return res; } m_nMode = mode; m_nBufferPos = 0; #ifdef WIN32 if ( (mode & IO_RAW) != 0 ) m |= _O_BINARY; if ( (mode & IO_READONLY) != 0 ) m |= _O_RDONLY; if ( (mode & IO_WRITEONLY) != 0 ) m |= _O_WRONLY; if ( (mode & IO_READWRITE) != 0 ) m |= _O_RDWR; if ( (mode & IO_APPEND) != 0 ) m |= _O_APPEND; if ( (mode & IO_TRUNCATE) != 0 ) m |= _O_TRUNC; if ( (mode & IO_CREAT) != 0 ) m |= _O_CREAT; #else if ( (mode & IO_RAW) != 0 ) m |= 0; if ( (mode & IO_READONLY) != 0 ) m |= O_RDONLY; if ( (mode & IO_WRITEONLY) != 0 ) m |= O_WRONLY; if ( (mode & IO_READWRITE) != 0 ) m |= O_RDWR; if ( (mode & IO_APPEND) != 0 ) m |= O_APPEND; if ( (mode & IO_TRUNCATE) != 0 ) m |= O_TRUNC; if ( (mode & IO_CREAT) != 0 ) m |= O_CREAT; #endif #ifdef WIN32 if ( (acc & MO_IRWXU) != 0 ) a |= _S_IREAD | _S_IWRITE; if ( (acc & MO_IRUSR) != 0 ) a |= _S_IREAD; if ( (acc & MO_IWUSR) != 0 ) a |= _S_IWRITE; if ( (acc & MO_IRWXG) != 0 ) a |= _S_IREAD | _S_IWRITE; if ( (acc & MO_IRGRP) != 0 ) a |= _S_IREAD; if ( (acc & MO_IWGRP) != 0 ) a |= _S_IWRITE; if ( (acc & MO_IRWXO) != 0 ) a |= _S_IREAD | _S_IWRITE; if ( (acc & MO_IRGRP) != 0 ) a |= _S_IREAD; if ( (acc & MO_IWOTH) != 0 ) a |= _S_IWRITE; #else if ( (acc & MO_IRWXU) == MO_IRWXU ) a |= S_IRWXU; if ( (acc & MO_IRUSR) == MO_IRUSR ) a |= S_IRUSR; if ( (acc & MO_IWUSR) == MO_IWUSR ) a |= S_IWUSR; if ( (acc & MO_IXUSR) == MO_IXUSR ) a |= S_IXUSR; if ( (acc & MO_IRWXG) == MO_IRWXG ) a |= S_IRWXG; if ( (acc & MO_IRGRP) == MO_IRGRP ) a |= S_IRGRP; if ( (acc & MO_IWGRP) == MO_IWGRP ) a |= S_IWGRP; if ( (acc & MO_IXGRP) == MO_IXGRP ) a |= S_IXGRP; if ( (acc & MO_IRWXO) == MO_IRWXO ) a |= S_IRWXO; if ( (acc & MO_IRGRP) == MO_IRGRP ) a |= S_IROTH; if ( (acc & MO_IWOTH) == MO_IWOTH ) a |= S_IWOTH; if ( (acc & MO_IXOTH) == MO_IXOTH ) a |= S_IXOTH; #endif #ifdef WIN32 m_nFD = _open( filename.Data(), m, a ); #else m_nFD = open( filename.Data(), m, a ); #endif if ( m_nFD != -1 ) { res = true; // create write buffer if ( (mode & IO_WRITEONLY) != 0 ) { m_pBuffer = new CByteArray(FILE_BUFFER_SIZE); } } return res; } /** */ bool CFile::Close() { bool ok = false; if ( m_nFD != -1 ) { // flush write buffer if ( m_nBufferPos != 0 ) { Flush(); } #ifdef WIN32 if ( _close(m_nFD) == 0 ) #else if ( close(m_nFD) == 0 ) #endif { ok = true; } else { perror("CFile::Close"); } m_nFD = -1; m_nBufferPos = 0; delete m_pBuffer; m_pBuffer = 0; } return ok; } /** */ long CFile::Flush() { long i = 0; if ( (m_nFD != -1) && ((m_nMode & IO_WRITEONLY) != 0) && (m_nBufferPos != 0) ) { #ifdef WIN32 i = _write( m_nFD, m_pBuffer->Data(), m_nBufferPos ); #else i = write( m_nFD, m_pBuffer->Data(), m_nBufferPos ); #endif if ( i == -1 ) { perror("CFile::Flush"); } else if ( i < m_nBufferPos ) { // not all data flushed, fix buffer printf("CFile::Flush: write %ld : %d Bytes\n",i,m_nBufferPos); if ( i > 0 ) { memcpy(m_pBuffer->Data(),m_pBuffer->Data()+i,m_nBufferPos-i); m_nBufferPos -= i; } i = -1; } else { m_nBufferPos = 0; } } return i; } /** */ long CFile::Write( const char * buf, long count ) { long i = 0; if ( (m_nFD == -1) || (count <= 0) || (!buf) ) { return -1; } if ( (m_nMode & IO_WRITEONLY) != 0 ) { if ( count >= FILE_BUFFER_SIZE ) { i = Flush(); } else if ( (count+m_nBufferPos) > FILE_BUFFER_SIZE ) { i = Flush(); if ( i != -1 ) { m_nBufferPos = count; memcpy(m_pBuffer->Data(),buf,count); i = count; } } else { memcpy(m_pBuffer->Data()+m_nBufferPos,buf,count); m_nBufferPos += count; i = count; } } // check if flush failed if ( i != -1 ) { if ( m_nBufferPos == 0 ) { #ifdef WIN32 i = _write( m_nFD, buf, count ); #else i = write( m_nFD, buf, count ); #endif } } return i; } /** */ long CFile::Read( char * buf, long count ) { long i = -1; if ( (m_nFD == -1) || (count <= 0) || (!buf)) { return i; } #ifdef WIN32 i = _read( m_nFD, buf, count ); #else i = read( m_nFD, buf, count ); #endif return i; } /** */ bool CFile::Seek( int64_t offset, int how ) { bool res = false; if ( m_nFD == -1 ) { return res; } if ( Flush() == -1 ) { return res; } #ifdef WIN32 if ( _lseeki64( m_nFD, offset, how ) == -1 ) #else if ( lseek( m_nFD, offset, how ) == (off_t) -1 ) #endif { res = false; } else { res = true; } return res; } /** */ bool CFile::Rename( const CString & from, const CString & to ) { bool res = false; if ( from.IsEmpty() || to.IsEmpty() ) { return res; } if ( rename(from.Data(),to.Data()) == 0 ) { res = true; } else { perror("CFile::Rename"); } return res; } /** */ bool CFile::Remove( const CString & s ) { bool res = false; if ( s.IsEmpty() ) { return res; } if ( remove(s.Data()) == 0 ) { res = true; } else { perror("CFile::Remove"); } return res; } /** */ bool CFile::UnLink( const CString & absfile ) { bool res = false; if ( absfile.IsEmpty() ) { return res; } #ifdef WIN32 if ( _unlink( absfile.Data() ) == 0 ) #else if ( unlink( absfile.Data() ) == 0 ) #endif { res = true; } return res; } /** */ bool CFile::Copy( const CString & absfrom, const CString & absto ) { int from_fd, to_fd; ssize_t bytesread; char * buffer; #ifdef WIN32 from_fd = open( absfrom.Data(), _O_RDONLY | _O_BINARY, 0 ); #else from_fd = open( absfrom.Data(), O_RDONLY , 0 ); #endif if ( from_fd < 0 ) { printf("CFile::Copy: open for read '%s' failed\n",absfrom.Data()); return false; } #ifdef WIN32 to_fd = open( absto.Data(), _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, _S_IREAD | _S_IWRITE ); #else UnLink( absto ); to_fd = open( absto.Data(), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO ); #endif if ( to_fd < 0 ) { printf("CFile::Copy: open for write '%s' failed\n",absto.Data()); return false; } #ifdef WIN32 const long blocksize = 65536; #else struct stat statbuf; blksize_t blocksize; if ( fstat( to_fd, &statbuf ) == 0 ) { blocksize = statbuf.st_blksize; /* less necessary */ if ( (fstat(from_fd,&statbuf) == 0) && (statbuf.st_blksize > blocksize) ) { blocksize = statbuf.st_blksize; } } else { blocksize = 65536; } #endif buffer = (char*) malloc( blocksize ); if ( buffer == 0 ) { printf("CFile::Copy: malloc failed\n"); return false; } while ( (bytesread = read(from_fd,buffer,blocksize)) > 0 ) { if ( write(to_fd,buffer,bytesread) != bytesread ) { printf("CFile::Copy: write failed\n"); #ifdef WIN32 if ( _close(from_fd) != 0 ) #else if ( close(from_fd) != 0 ) #endif { printf("CFile::Copy: close '%s' also failed\n",absfrom.Data()); } #ifdef WIN32 if ( _close(to_fd) != 0 ) #else if ( close(to_fd) != 0 ) #endif { printf("CFile::Copy: close '%s' also failed\n",absto.Data()); } UnLink( absto ); free(buffer); return false; } } free(buffer); bool res = true; #ifdef WIN32 if ( _close(to_fd) != 0 ) #else if ( close(to_fd) != 0 ) #endif { printf("CFile::Copy: close '%s' failed\n",absto.Data()); UnLink( absto ); res = false; } #ifdef WIN32 if ( _close(from_fd) != 0 ) #else if ( close(from_fd) != 0 ) #endif { printf("CFile::Copy: close '%s' failed\n",absfrom.Data()); /* since target was sucessfully created true can be returned */ } return res; } /** */ bool CFile::OpenTemp( CString & filename ) { bool ok = false; if ( (m_nFD != -1) || filename.IsEmpty() ) { return ok; } m_nBufferPos = 0; m_nMode = IO_RAW | IO_WRITEONLY | IO_CREAT; CString tempname = filename; tempname += ".XXXXXX"; #ifdef WIN32 char * res = _mktemp( tempname.Data() ); if ( res ) { ok = Open( tempname, m_nMode ); if ( ok ) { filename = tempname; } } else { ok = false; } #else m_nFD = mkstemp( tempname.Data() ); if ( m_nFD != -1 ) { ok = true; m_pBuffer = new CByteArray(FILE_BUFFER_SIZE); filename = tempname; } #endif return ok; } libdc0-0.3.24~svn3121/dclib/core/clisten.h0000644000175000017500000000371511101144617017042 0ustar sikonsikon/*************************************************************************** clisten.h - description ------------------- begin : Fri Mar 22 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CLISTEN_H #define CLISTEN_H /** *@author Mathias Küster * * Class for waiting for an incoming connection, involving callbacks * and CManager. */ #include #include #include #include class CListen : public CSocket { public: /** */ CListen(); /** */ virtual ~CListen(); /** */ int StartListen( int port, CString ip = CString(), bool manager = true ); /** */ void StopListen(); /** callback function */ virtual int DC_ListenCallBack( int ) { return -1; }; /** */ void SetCallBackFunction( _CCallback1 * callback ); /** */ int Callback(); private: /** */ CMutex m_Mutex; /** */ _CCallback1 * m_pListenCallback; /** */ _CCallback0 * m_pCallback; }; /** */ inline void CListen::SetCallBackFunction( _CCallback1 * callback ) { m_Mutex.Lock(); delete m_pListenCallback; m_pListenCallback = callback; m_Mutex.UnLock(); } #endif libdc0-0.3.24~svn3121/dclib/core/csocket.h0000644000175000017500000001024311125260136017027 0ustar sikonsikon/*************************************************************************** csocket.h - description ------------------- begin : Sat Oct 6 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSOCKET_H #define CSOCKET_H /** *@author Mathias Küster * * A network socket, including SSL support. * * On WIN32 this class will not work until CSocket::SysInit() has been * called, normally by dclibInitDepLibs(), but that should * be better than initialising WinSock2 every time * a CSocket is created. */ #include #include #include #include #if DCLIB_USES_OPENSSL == 1 #include #include #else /* this may also work for SSL builds */ typedef struct ssl_st SSL; typedef struct ssl_ctx_st SSL_CTX; #endif enum eSocketType { estTCP=0, estUDP }; /* * esmSSLCLIENT and esmSSLSERVER are the old values for * changing to SSL mode during the NMDC protocol exchange * * esmFULLSSLCLIENT and esmFULLSSLSERVER are the new values * where the socket starts in SSL mode */ enum eSocketMode { esmSOCKET=0, esmSSLCLIENT, esmSSLSERVER, esmFULLSSLCLIENT, esmFULLSSLSERVER }; enum eSocketLog { eslNONE=0, eslSEND, eslRECV, eslBOTH }; enum eConnectState { ecsSUCCESS=0, ecsAGAIN, ecsERROR }; class CSocket { public: /** */ CSocket( eSocketType type = estTCP ); /** */ virtual ~CSocket(); /** */ static CTraffic m_Traffic; /** */ static eSocketLog m_eSocketLog; /** */ eConnectState Connect( CString Host, bool iAsync ); /** */ eConnectState Connect( CString Host, int Port, bool iAsync ); /** */ int IsConnect(); /** */ int Disconnect(); /** */ int Read( char * buffer, int len, int sec_timeout=0, int usec_timeout=0 ); /** */ int Write( const unsigned char * buffer, int len, int sec_timeout=0, int usec_timeout=0 ); /** */ int GetFreeSendBufferSize(); /** */ int SetSocket( int handle, eSocketType sockettype ); /** */ int Accept(); /** */ int Listen( int port, CString ip = CString() ); /** */ bool GetPeerName( CString * host, int * port ); /** */ CString GetSocketError() { return sError; }; /** */ virtual bool ChangeSocketMode( eSocketMode mode, CString cert = CString(), CString key = CString() ); /** Get SSL version */ CString GetSSLVersion(); /** Get SSL cipher */ CString GetSSLCipher(); /** Verify peer SSL certificate */ CString VerifyPeerCertificate(); /** */ eSocketMode GetSocketMode() { return m_eSocketMode; } /** Gets the IP address with port of most recent connection attempt */ CString GetResolvedIP() const { return m_sIP; } /** * Initialises WinSock2 DLL, does nothing on non WIN32. * Returns 0 if successful or some other WSA error code otherwise. * Should be called once on program startup. */ static int SysInit(); /** * Shuts down WinSock2 DLL, does nothing on non WIN32. * Returns 0 if successful or some other WSA error code otherwise. * Should be called once on program shutdown. */ static int SysDeInit(); protected: /** */ eSocketType SocketType; /** */ SOCKET iHandle; /** */ eSocketMode m_eSocketMode; /** */ SSL_CTX * m_pCTX; /** */ SSL * m_pSSL; private: /** */ int SocketError(); /** */ CString ext_strerror( int err ); /** */ CString sError; /** the IP address and port of the most recent connection attempt */ CString m_sIP; }; #endif libdc0-0.3.24~svn3121/dclib/core/csocket.cpp0000644000175000017500000006207011175136326017377 0ustar sikonsikon/*************************************************************************** csocket.cpp - description ------------------- begin : Sat Oct 6 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "csocket.h" #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef WIN32 #include #include #else #include #include #include #include #include #include #include #include #include #include // includes for sun os #ifdef HAVE_SYS_SOCKIO_H #include #endif #ifdef HAVE_SYS_TERMIOS_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif #endif #include #ifndef MSG_NOSIGNAL // 0x2000 /* don't raise SIGPIPE */ #define MSG_NOSIGNAL 0 #endif #include "../dcos.h" #include "casyncdns.h" #include "clogfile.h" #include "cssl.h" #include "cnetaddr.h" #ifdef HAVE_SOCKS extern "C" { #include } #endif // init static socket vars CTraffic CSocket::m_Traffic = CTraffic(); eSocketLog CSocket::m_eSocketLog = eslNONE; CSocket::CSocket( eSocketType type ) { SocketType = type; iHandle = INVALID_SOCKET; m_eSocketMode = esmSOCKET; m_pCTX = 0; m_pSSL = 0; } CSocket::~CSocket() { Disconnect(); #if DCLIB_USES_OPENSSL == 1 /* This is in case iHandle == INVALID_SOCKET but somehow m_pSSL / m_pCTX are still here */ if ( m_pSSL ) { SSL_free(m_pSSL); m_pSSL = 0; } if ( m_pCTX ) { SSL_CTX_free(m_pCTX); m_pCTX = 0; } #endif } /** */ int CSocket::SetSocket( int handle, eSocketType sockettype ) { if ( handle == INVALID_SOCKET ) { return -1; } if ( (sockettype != estTCP) && (sockettype != estUDP) ) { return -1; } SocketType = sockettype; iHandle = handle; #if DCLIB_USES_OPENSSL == 1 if ( (m_eSocketMode == esmFULLSSLSERVER) || (m_eSocketMode == esmFULLSSLCLIENT) ) { if ( SSL_set_fd(m_pSSL,iHandle) == 0 ) { sError = "CSocket::SetSocket: SSL_set_fd failed: "; sError += ERR_reason_error_string( ERR_get_error() ); return -1; } } #endif return 0; } /** */ int CSocket::GetFreeSendBufferSize() { int tot, free = 0; #ifndef WIN32 int unsent; #endif socklen_t ilen; if ( iHandle == INVALID_SOCKET ) { return free; } ilen = sizeof(int); if ( getsockopt(iHandle, SOL_SOCKET, SO_SNDBUF, (char*)&tot, &ilen) == 0 ) { // quick & dirty fix for free bsd free = tot; #ifndef WIN32 #ifndef __CYGWIN__ if ( ioctl(iHandle, TIOCOUTQ, &unsent) == 0 ) { free = tot - unsent; } #endif #endif } return free; } /** */ int CSocket::IsConnect() { int i,err; struct timeval tv; fd_set rset,wset,eset; if ( iHandle == INVALID_SOCKET ) { return -1; } FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(iHandle, &rset); FD_SET(iHandle, &wset); FD_SET(iHandle, &eset); tv.tv_sec = 0; tv.tv_usec = 1; err = -1; i = select(FD_SETSIZE, &rset, &wset, &eset, &tv); if ( (i > 0) && (!FD_ISSET(iHandle, &eset)) && (FD_ISSET(iHandle, &wset)) ) { err = 1; } else if ( i == 0 ) { err = 0; } else if ( err == -1 ) { err = SocketError(); if ( err != 0 ) { sError = ext_strerror(err); err = -1; } } FD_CLR(iHandle, &rset); FD_CLR(iHandle, &wset); FD_CLR(iHandle, &eset); return err; } /** */ int CSocket::SocketError() { int err = 0; socklen_t ilen; if ( iHandle == INVALID_SOCKET ) { return err; } ilen = sizeof(int); if ( getsockopt(iHandle, SOL_SOCKET, SO_ERROR, (char*)&err, &ilen) != 0 ) { err = 0; } return err; } /** */ eConnectState CSocket::Connect( CString Host, bool bAsync ) { unsigned int port; CString s; CNetAddr::ParseHost( Host, s, port ); // set default port if ( port == 0 ) { port = 411; } return Connect( s, port, bAsync ); } /** */ eConnectState CSocket::Connect( CString Host, int Port, bool bAsync ) { struct sockaddr_in sin,t_sin; SOCKET sockfd; eAsyncDns ead; if ( iHandle != INVALID_SOCKET ) { Disconnect(); } memset((void *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; if ( Host.IsEmpty() ) { if ( SocketType == estTCP ) { return ecsERROR; } else { sin.sin_addr.s_addr = htonl(INADDR_ANY); } } else { /* skip host lookup if it is a valid IP address */ #ifdef WIN32 sin.sin_addr.s_addr = inet_addr( Host.Data() ); if ( sin.sin_addr.s_addr != INADDR_NONE ) #else if ( inet_aton( Host.Data(), &sin.sin_addr ) != 0 ) #endif { m_sIP = Host; } else if ( bAsync == false ) { // use blocked getaddrinfo if ( CNetAddr::GetHostI4( Host.Data(), &t_sin, &sError ) == false ) { return ecsERROR; } else { memcpy((void *)&sin.sin_addr, (void *)&t_sin.sin_addr, sizeof(t_sin.sin_addr)); m_sIP = inet_ntoa(sin.sin_addr); } } else { // use async dns class if ( CAsyncDns::Instance() ) { ead = CAsyncDns::Instance()->GetHostI4( Host, &t_sin, &sError ); } else { return ecsERROR; } if ( ead == eadAGAIN ) { return ecsAGAIN; } else if ( ead == eadERROR ) { return ecsERROR; } else { memcpy((void *)&sin.sin_addr, (void *)&t_sin.sin_addr, sizeof(t_sin.sin_addr)); m_sIP = inet_ntoa(sin.sin_addr); } } } sin.sin_port = htons((unsigned short)Port); // update m_sIP m_sIP += ':'; m_sIP += CString::number(Port); // socket if ( SocketType == estTCP ) { if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { sError = ext_strerror(errno); return ecsERROR; } } else { if( (sockfd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0 ) { sError = ext_strerror(errno); return ecsERROR; } } // set async flag #ifdef WIN32 unsigned long flag = bAsync; if ( ioctlsocket(sockfd, FIONBIO, &flag ) != 0 ) #else int flag = bAsync; if ( ioctl(sockfd, FIONBIO, &flag ) != 0 ) #endif { sError = ext_strerror(errno); return ecsERROR; } if ( Host.NotEmpty() ) { // connect if ( connect(sockfd, (struct sockaddr *)&sin, sizeof(sin)) != 0 ) { #ifdef WIN32 int e = WSAGetLastError(); if ( (e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK) ) #else if ( errno != EINPROGRESS ) #endif { sError = ext_strerror(errno); #ifdef WIN32 closesocket(sockfd); #else close(sockfd); #endif return ecsERROR; } } } else { if ( bind(sockfd, (struct sockaddr *) &sin, sizeof(sin)) < 0 ) { sError = ext_strerror(errno); #ifdef WIN32 closesocket(sockfd); #else close(sockfd); #endif return ecsERROR; } } #if DCLIB_USES_OPENSSL == 1 if ( m_eSocketMode == esmFULLSSLCLIENT ) { if ( SSL_set_fd(m_pSSL, sockfd) == 0 ) { sError = "CSocket::Connect: SSL_set_fd failed: "; sError += ERR_reason_error_string( ERR_get_error() ); #ifdef WIN32 closesocket(sockfd); #else close(sockfd); #endif return ecsERROR; } } #endif /* DCLIB_USES_OPENSSL */ iHandle = sockfd; return ecsSUCCESS; } /** */ int CSocket::Disconnect() { if ( iHandle != INVALID_SOCKET ) { #if DCLIB_USES_OPENSSL == 1 if ( (m_eSocketMode != esmSOCKET) && (m_pSSL) ) { SSL_shutdown(m_pSSL); // FIXME check return value SSL_free(m_pSSL); m_pSSL = 0; } #endif #ifdef WIN32 closesocket(iHandle); #else close(iHandle); #endif #if DCLIB_USES_OPENSSL == 1 if ( (m_eSocketMode != esmSOCKET) && (m_pCTX) ) { SSL_CTX_free(m_pCTX); m_pCTX = 0; } #endif m_eSocketMode = esmSOCKET; iHandle = INVALID_SOCKET; } return 0; } /** */ int CSocket::Read( char * buffer, int len, int sec_timeout, int usec_timeout ) { int l = 0, i = 0; struct timeval tv; fd_set readset; struct sockaddr_in cli_addr; socklen_t cli_len = sizeof(cli_addr); if ( (iHandle == INVALID_SOCKET) || (!buffer) || (len <= 0) ) { return -1; } #if DCLIB_USES_OPENSSL == 1 if ( m_eSocketMode != esmSOCKET ) { l = SSL_read(m_pSSL, buffer, len); // if ( (l <= 0) && ((i=IsConnect()) != -1) ) if ( l <= 0 ) { // printf("READ: %d %d\n",l,i); l = SSL_get_error(m_pSSL,l); if ( (l != SSL_ERROR_WANT_READ) && (l != SSL_ERROR_WANT_WRITE) ) { l = -1; unsigned long sslerr = ERR_peek_error(); // ERR_get_error() if not printed ERR_print_errors_fp(stderr); sError = "SSL ERROR lib:"; sError += ERR_lib_error_string(sslerr); sError += " func:"; sError += ERR_func_error_string(sslerr); sError += " reason:"; sError += ERR_reason_error_string(sslerr); Disconnect(); } else { l = i = 0; } } } else #endif { if ( IsConnect() < 0 ) { i = 1; l = 0; } else { FD_ZERO(&readset); FD_SET(iHandle, &readset); tv.tv_sec = sec_timeout; tv.tv_usec = usec_timeout; i = select(FD_SETSIZE, &readset, NULL, NULL, &tv); if ( (i > 0) && (FD_ISSET(iHandle,&readset)) ) { // handle udp socket if ( SocketType == estUDP ) { if ( (l=recvfrom(iHandle,buffer,len,0,(struct sockaddr*)&cli_addr,&cli_len)) < 0 ) { #ifdef WIN32 int e = WSAGetLastError(); if ( (e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK) ) { #else int e = errno; if ( (e != EINPROGRESS) && (e != EAGAIN) ) { #endif sError = ext_strerror(e); } else { i = l = 0; } } else if ( l > 0 ) { m_sIP = inet_ntoa( cli_addr.sin_addr ); } } // handle tcp socket else if ( SocketType == estTCP ) { if ( (l=recv(iHandle,buffer,len,0)) < 0 ) { #ifdef WIN32 int e = WSAGetLastError(); if ( (e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK) ) { #else int e = errno; if ( (e != EINPROGRESS) && (e != EAGAIN) ) { #endif sError = ext_strerror(e); } else { i = l = 0; } } } } else if ( i < 0 ) { i = SocketError(); if ( i == 0 ) { l = i = 0; } else { sError = ext_strerror(i); i = l = -1; } } FD_CLR(iHandle, &readset); } } // log options TODO: fix if ( (CSocket::m_eSocketLog == eslRECV) || (CSocket::m_eSocketLog == eslBOTH) ) { if ( l > 0 ) { CString s = "RECV:"; s += CString::number(l); CLogFile::Write("dcsocket.log",eltINFO,s); if( l <= len ) { s.Set(buffer,l); CLogFile::Write("dcsocket.log",eltINFO,s); } } } /** we are disconnected */ if ( (i==1) && (l==0) ) { i = errno; l = SocketError(); // printf("1: %s\n",ext_strerror(i).Data()); // printf("2: %s\n",ext_strerror(l).Data()); if ( l == 0 ) l = i; // if ( (l != EINPROGRESS) && (l != EAGAIN) ) // { sError = ext_strerror(l); l = -1; // } // else // { // l = 0; // } } if ( l > 0 ) CSocket::m_Traffic.AddTraffic( ettRX, l ); return l; } /** */ int CSocket::Write( const unsigned char * buffer, int len, int sec_timeout, int usec_timeout ) { int i; struct timeval tv; fd_set writeset; if ( (iHandle == INVALID_SOCKET) || (!buffer) || (len <= 0) ) { return -1; } #if DCLIB_USES_OPENSSL == 1 if ( m_eSocketMode != esmSOCKET ) { i = SSL_write(m_pSSL, buffer, len); // if ( (i <= 0) && (IsConnect() != -1) ) if ( i <= 0 ) { // printf("WRITE: %d %d\n",i,IsConnect()); i = SSL_get_error(m_pSSL,i); if ( (i != SSL_ERROR_WANT_READ) && (i != SSL_ERROR_WANT_WRITE) ) { i = -1; unsigned long sslerr = ERR_peek_error(); // ERR_get_error() if not printed ERR_print_errors_fp(stderr); sError = "SSL ERROR lib:"; sError += ERR_lib_error_string(sslerr); sError += " func:"; sError += ERR_func_error_string(sslerr); sError += " reason:"; sError += ERR_reason_error_string(sslerr); Disconnect(); } else { i = 0; } } } else #endif { if ( IsConnect() < 0 ) { i = -1; } else { FD_ZERO(&writeset); FD_SET(iHandle, &writeset); tv.tv_sec = sec_timeout; tv.tv_usec = usec_timeout; i = select(FD_SETSIZE, NULL, &writeset, NULL, &tv); FD_CLR(iHandle, &writeset); } if ( i > 0 ) { i = send( iHandle, (const char*)buffer, len, MSG_NOSIGNAL ); // send error if ( i < 0 ) { #ifdef WIN32 int e = WSAGetLastError(); if ( (e != WSAEINPROGRESS) && (e != WSAEWOULDBLOCK) ) { #else int e = errno; if ( (e != EINPROGRESS) && (e != 0) && (e != EAGAIN) ) { #endif sError = ext_strerror(e); } else { i = 0; } } else if ( i == 0 ) { i = -1; } } else if ( i < 0 ) { i = SocketError(); if ( i != 0 ) { sError = ext_strerror(i); i = -1; } } } // log options TODO: fix if ( (CSocket::m_eSocketLog == eslSEND) || (CSocket::m_eSocketLog == eslBOTH) ) { if ( i > 0 ) { CString s = "SEND:"; s += CString::number(len); CLogFile::Write("dcsocket.log",eltINFO,s); s.Set( (const char*)buffer ,i ); CLogFile::Write("dcsocket.log",eltINFO,s); } } if ( i > 0 ) CSocket::m_Traffic.AddTraffic( ettTX, i ); return i; } /** */ int CSocket::Accept() { struct timeval tv; fd_set readset; struct sockaddr_in serv_addr; SOCKET s = INVALID_SOCKET; int i; socklen_t sin_size = sizeof(struct sockaddr_in); if ( iHandle == INVALID_SOCKET ) { return s; } FD_ZERO(&readset); FD_SET(iHandle, &readset); tv.tv_sec = 0; tv.tv_usec = 1; i = select(FD_SETSIZE, &readset, NULL, NULL, &tv); FD_CLR(iHandle, &readset); if ( i > 0 ) { if ((s = accept(iHandle, (struct sockaddr *)&serv_addr, &sin_size)) == INVALID_SOCKET) { sError = ext_strerror(SocketError()); return -1; } else { // set async flag #ifdef WIN32 unsigned long flag = 1; if ( ioctlsocket(s, FIONBIO, &flag ) != 0 ) #else int flag = 1; if ( ioctl(s, FIONBIO, &flag ) != 0 ) #endif { sError = ext_strerror(errno); return -1; } } } return s; } /** */ int CSocket::Listen( int port, CString ip ) { SOCKET sockfd; struct sockaddr_in serv_addr; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { #ifdef WIN32 sError = ext_strerror(WSAGetLastError()); #else sError = ext_strerror(errno); #endif return -1; } /* Let the kernel reuse the socket address. This lets us run twice in a row, without waiting for the (ip, port) tuple to time out. */ #ifdef WIN32 const char i = 1; #else int i = 1; #endif if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) != 0 ) { #ifdef WIN32 sError = ext_strerror(WSAGetLastError()); closesocket(sockfd); #else sError = ext_strerror(errno); close(sockfd); #endif return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons((unsigned short)port); if ( ip.NotEmpty() ) { #ifdef WIN32 serv_addr.sin_addr.s_addr = inet_addr( ip.Data() ); if ( serv_addr.sin_addr.s_addr == INADDR_NONE ) #else if ( inet_aton( ip.Data(), &serv_addr.sin_addr ) == 0 ) #endif { sError = "Invalid IP address"; return -1; } } else { serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); } if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1) { #ifdef WIN32 sError = ext_strerror(WSAGetLastError()); closesocket(sockfd); #else sError = ext_strerror(errno); close(sockfd); #endif return -1; } if (listen(sockfd, 5) == -1) { #ifdef WIN32 sError = ext_strerror(WSAGetLastError()); closesocket(sockfd); #else sError = ext_strerror(errno); close(sockfd); #endif return -1; } #if DCLIB_USES_OPENSSL == 1 if ( m_eSocketMode == esmFULLSSLSERVER ) { if ( SSL_set_fd(m_pSSL, sockfd) == 0 ) { sError = "CSocket::Listen: SSL_set_fd failed: "; sError += ERR_reason_error_string( ERR_get_error() ); #ifdef WIN32 closesocket(sockfd); #else close(sockfd); #endif return -1; } } #endif /* DCLIB_USES_OPENSSL */ iHandle = sockfd; return 0; } /** */ bool CSocket::GetPeerName( CString * host, int * port ) { struct sockaddr_in addr; socklen_t sin_size; if ( (iHandle == INVALID_SOCKET) || (!host) || (!port) ) { return false; } sin_size = sizeof(struct sockaddr_in); if ( getpeername( iHandle, (struct sockaddr*)&addr, &sin_size ) == -1 ) { sError = ext_strerror(SocketError()); return false; } *host = inet_ntoa(addr.sin_addr); *port = ntohs(addr.sin_port); return true; } /** */ #if DCLIB_USES_OPENSSL == 1 bool CSocket::ChangeSocketMode( eSocketMode mode, CString cert, CString key ) #else bool CSocket::ChangeSocketMode( eSocketMode mode, CString /* cert */, CString /* key */ ) #endif { bool res = false; switch(mode) { case esmSOCKET: { m_eSocketMode = mode; res = true; break; } #if DCLIB_USES_OPENSSL == 1 case esmSSLCLIENT: case esmSSLSERVER: case esmFULLSSLCLIENT: case esmFULLSSLSERVER: { if ( (cert.IsEmpty() || key.IsEmpty()) && ((mode == esmSSLSERVER) || (mode == esmFULLSSLSERVER)) ) { printf("no cert/key available\n"); return res; } if ( m_eSocketMode == esmSOCKET ) { if ( mode == esmFULLSSLCLIENT ) { m_pCTX = CSSL::NewTLSv1ClientCTX(); if ( m_pCTX == 0 ) { printf("CSocket::ChangeSocketMode NewTLSv1ClientCTX failed\n"); return res; } } else if ( mode == esmFULLSSLSERVER ) { m_pCTX = CSSL::NewTLSv1ServerCTX(); if ( m_pCTX == 0 ) { printf("CSocket::ChangeSocketMode NewTLSv1ServerCTX failed\n"); return res; } } else if ( mode == esmSSLCLIENT ) { m_pCTX = CSSL::InitClientCTX(); if ( m_pCTX == 0 ) { printf("InitClientCTX failed\n"); return res; } } else { m_pCTX = CSSL::InitServerCTX(); if ( m_pCTX == 0 ) { printf("InitServerCTX failed\n"); return res; } } if ( cert.NotEmpty() && key.NotEmpty() ) { if ( CSSL::LoadCertificates( m_pCTX, cert.Data(), key.Data() ) == false ) { SSL_CTX_free(m_pCTX); m_pCTX = 0; printf("load cert/key failed\n"); return res; } } SSL_CTX_set_mode(m_pCTX, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|SSL_MODE_ENABLE_PARTIAL_WRITE); if ( (m_pSSL = SSL_new(m_pCTX)) == 0 ) { printf("SSL_new failed\n"); SSL_CTX_free(m_pCTX); m_pCTX = 0; return res; } if ( (mode == esmSSLSERVER) || (mode == esmFULLSSLSERVER) ) { SSL_set_accept_state(m_pSSL); } else { SSL_set_connect_state(m_pSSL); } if ( SSL_set_fd(m_pSSL, iHandle) == 0 ) { printf("SSL_set_fd failed\n"); SSL_CTX_free(m_pCTX); m_pCTX = 0; SSL_free(m_pSSL); m_pSSL = 0; return res; } m_eSocketMode = mode; res = true; } else { printf("CSocket: wrong socket mode to change\n"); } break; } #endif default: break; } return res; } /** http://synergy2.sourceforge.net/ */ CString CSocket::ext_strerror( int err ) { #ifdef WIN32 // built-in windows function for looking up error message strings // may not look up network error messages correctly. we'll have // to do it ourself. static const struct { int m_code; const char* m_msg; } s_netErrorCodes[] = { /* 10004 */{WSAEINTR, "The (blocking) call was canceled via WSACancelBlockingCall"}, /* 10009 */{WSAEBADF, "Bad file handle"}, /* 10013 */{WSAEACCES, "The requested address is a broadcast address, but the appropriate flag was not set"}, /* 10014 */{WSAEFAULT, "WSAEFAULT"}, /* 10022 */{WSAEINVAL, "WSAEINVAL"}, /* 10024 */{WSAEMFILE, "No more file descriptors available"}, /* 10035 */{WSAEWOULDBLOCK, "Socket is marked as non-blocking and no connections are present or the receive operation would block"}, /* 10036 */{WSAEINPROGRESS, "A blocking Windows Sockets operation is in progress"}, /* 10037 */{WSAEALREADY, "The asynchronous routine being canceled has already completed"}, /* 10038 */{WSAENOTSOCK, "At least on descriptor is not a socket"}, /* 10039 */{WSAEDESTADDRREQ, "A destination address is required"}, /* 10040 */{WSAEMSGSIZE, "The datagram was too large to fit into the specified buffer and was truncated"}, /* 10041 */{WSAEPROTOTYPE, "The specified protocol is the wrong type for this socket"}, /* 10042 */{WSAENOPROTOOPT, "The option is unknown or unsupported"}, /* 10043 */{WSAEPROTONOSUPPORT,"The specified protocol is not supported"}, /* 10044 */{WSAESOCKTNOSUPPORT,"The specified socket type is not supported by this address family"}, /* 10045 */{WSAEOPNOTSUPP, "The referenced socket is not a type that supports that operation"}, /* 10046 */{WSAEPFNOSUPPORT, "BSD: Protocol family not supported"}, /* 10047 */{WSAEAFNOSUPPORT, "The specified address family is not supported"}, /* 10048 */{WSAEADDRINUSE, "The specified address is already in use"}, /* 10049 */{WSAEADDRNOTAVAIL, "The specified address is not available from the local machine"}, /* 10050 */{WSAENETDOWN, "The Windows Sockets implementation has detected that the network subsystem has failed"}, /* 10051 */{WSAENETUNREACH, "The network can't be reached from this hos at this time"}, /* 10052 */{WSAENETRESET, "The connection must be reset because the Windows Sockets implementation dropped it"}, /* 10053 */{WSAECONNABORTED, "The virtual circuit was aborted due to timeout or other failure"}, /* 10054 */{WSAECONNRESET, "The virtual circuit was reset by the remote side"}, /* 10055 */{WSAENOBUFS, "No buffer space is available or a buffer deadlock has occured. The socket cannot be created"}, /* 10056 */{WSAEISCONN, "The socket is already connected"}, /* 10057 */{WSAENOTCONN, "The socket is not connected"}, /* 10058 */{WSAESHUTDOWN, "The socket has been shutdown"}, /* 10059 */{WSAETOOMANYREFS, "BSD: Too many references"}, /* 10060 */{WSAETIMEDOUT, "Attempt to connect timed out without establishing a connection"}, /* 10061 */{WSAECONNREFUSED, "The attempt to connect was forcefully rejected"}, /* 10062 */{WSAELOOP, "Undocumented WinSock error code used in BSD"}, /* 10063 */{WSAENAMETOOLONG, "Undocumented WinSock error code used in BSD"}, /* 10064 */{WSAEHOSTDOWN, "Undocumented WinSock error code used in BSD"}, /* 10065 */{WSAEHOSTUNREACH, "No route to host"}, /* 10066 */{WSAENOTEMPTY, "Undocumented WinSock error code"}, /* 10067 */{WSAEPROCLIM, "Undocumented WinSock error code"}, /* 10068 */{WSAEUSERS, "Undocumented WinSock error code"}, /* 10069 */{WSAEDQUOT, "Undocumented WinSock error code"}, /* 10070 */{WSAESTALE, "Undocumented WinSock error code"}, /* 10071 */{WSAEREMOTE, "Undocumented WinSock error code"}, /* 10091 */{WSASYSNOTREADY, "Underlying network subsytem is not ready for network communication"}, /* 10092 */{WSAVERNOTSUPPORTED, "The version of WinSock API support requested is not provided in this implementation"}, /* 10093 */{WSANOTINITIALISED, "WinSock subsystem not properly initialized"}, /* 10101 */{WSAEDISCON, "Virtual circuit has gracefully terminated connection"}, /* 11001 */{WSAHOST_NOT_FOUND, "The specified host is unknown"}, /* 11002 */{WSATRY_AGAIN, "A temporary error occurred on an authoritative name server"}, /* 11003 */{WSANO_RECOVERY, "A non-recoverable name server error occurred"}, /* 11004 */{WSANO_DATA, "The requested name is valid but does not have an IP address"}, /* end */{0, NULL} }; for (unsigned int i = 0; s_netErrorCodes[i].m_code != 0; ++i) { if ( s_netErrorCodes[i].m_code == err ) { return s_netErrorCodes[i].m_msg; } } #endif return strerror(err); } /** */ CString CSocket::GetSSLVersion() { CString result; #if DCLIB_USES_OPENSSL == 1 if ( m_pSSL ) { result = SSL_get_cipher_version(m_pSSL); } #endif return result; } /** */ CString CSocket::GetSSLCipher() { CString result; #if DCLIB_USES_OPENSSL == 1 if ( m_pSSL ) { result = SSL_get_cipher(m_pSSL); } #endif return result; } /** */ CString CSocket::VerifyPeerCertificate() { CString result; #if DCLIB_USES_OPENSSL == 1 if ( m_pSSL ) { if ( SSL_get_peer_certificate(m_pSSL) == NULL ) { result = "No certificate"; } else { int certerr = SSL_get_verify_result(m_pSSL); if ( certerr == X509_V_OK ) { result = "Certificate verified"; } else { result = "Certificate verify failed: "; result += X509_verify_cert_error_string(certerr); } } } #endif return result; } /** */ int CSocket::SysInit() { #ifdef WIN32 /* According to the docs WSAStartup() * will fail if the requested version could not be * provided, plus 2.2 is the latest version and that * can even be installed on Windows 95. */ WORD wVersionRequested = MAKEWORD( 2, 2 ); WSADATA wsaData; return WSAStartup( wVersionRequested, &wsaData ); #else /* nothing to do */ return 0; #endif } /** */ int CSocket::SysDeInit() { #ifdef WIN32 return WSACleanup(); #else /* nothing to do */ return 0; #endif } libdc0-0.3.24~svn3121/dclib/core/cbytearray.h0000644000175000017500000000461611121012323017535 0ustar sikonsikon/*************************************************************************** cbytearray.h - description ------------------- begin : Fri Mar 22 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef _CBYTEARRAY_H_ #define _CBYTEARRAY_H_ /** *@author Mathias Küster * * It is a byte array, with almost no functions, SetSize() always deletes * any previous content. * * Appending (part of) a byte array to itself never used to work, memcpy() * does not handle memory areas that overlap, dclib does not * require this to work, but it should now work. */ #include #include class CByteArray { public: /** */ CByteArray( unsigned long nSize = 0 ); /** */ ~CByteArray(); /** */ void SetSize( unsigned long nNewSize ); /** * Does realloc() i.e. not like SetSize(), this * can shrink or grow the byte array preserving (some of) * the contents. */ bool Realloc( unsigned long newsize ); /** */ void Append( const unsigned char * pchSrc, unsigned long nSize ); /** */ void Append( const char * pchSrc, unsigned long nSize ) { Append( (const unsigned char*)pchSrc, nSize ); }; /** */ unsigned char * Data(); /** */ unsigned long Size() const; /** */ bool LoadFromFile( CString file ); /** */ bool SaveToFile( CString file ); private: /** */ void Clear(); /** */ unsigned char * m_pchBuffer; /** */ unsigned long m_nSize; /** */ unsigned long m_nBufferSize; }; /** */ inline unsigned char * CByteArray::Data() { return m_pchBuffer; } /** */ inline unsigned long CByteArray::Size() const { return m_nSize; } #endif libdc0-0.3.24~svn3121/dclib/core/cbase32.cpp0000644000175000017500000001017611104271251017153 0ustar sikonsikon/*************************************************************************** cbase32.cpp - description ------------------- begin : Sat Apr 24 2004 copyright : (C) 2004-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cbase32.h" #include #include #include "cbytearray.h" #include "cstring.h" const signed char CBase32::Index_32[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; const char CBase32::B32Chars[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; #define base32val(c) Index_32[(unsigned int)(c)] #define base32chars(c) B32Chars[(unsigned int)(c&0x3F)] /** */ CBase32::CBase32() { } /** */ CBase32::~CBase32() { } /* raw bytes to null-terminated base 64 string */ void CBase32::Encode( CString * dst, CByteArray * src ) { if ( !dst || !src ) { return; } unsigned char word; size_t index = 0, i = 0; const size_t len = src->Size(); dst->Empty(); while ( i < len ) { /* Is the current word going to span a byte boundary? */ if ( index > 3 ) { word = (src->Data()[i] & (0xFF >> index)); index = (index + 5) % 8; word <<= index; if ( (i + 1) < len ) { word |= src->Data()[i + 1] >> (8 - index); } i++; } else { word = (src->Data()[i] >> (8 - (index + 5))) & 0x1F; index = (index + 5) % 8; if ( index == 0 ) { i++; } } dst->Append( B32Chars[word] ); } } /* Convert '\0'-terminated base 64 string to raw bytes. * Returns length of returned buffer, or -1 on error */ unsigned long CBase32::Decode( CByteArray * dst, CString * src ) { unsigned char c = 0; size_t index = 0, offset = 0; signed char tmp; if ( !dst || !src ) { return -1; } dst->SetSize(0); for ( long i = 0; i < src->Length(); ++i ) { // Skip what we don't recognise tmp = Index_32[(const unsigned char) (src->Data()[i])]; if ( tmp == -1 ) { continue; } if ( index <= 3 ) { index = (index + 5) % 8; if ( index == 0 ) { if ( dst->Size() <= offset ) { c = 0; dst->Append(&c,1); } dst->Data()[offset] |= tmp; offset++; } else { if ( i < src->Length()-1 ) { if ( dst->Size() <= offset ) { c = 0; dst->Append(&c,1); } dst->Data()[offset] |= tmp << (8 - index); } } } else { index = (index + 5) % 8; if ( dst->Size() <= offset ) { c = 0; dst->Append(&c,1); } dst->Data()[offset] |= (tmp >> index); offset++; if ( i < src->Length()-1 ) { if ( dst->Size() <= offset ) { c = 0; dst->Append(&c,1); } dst->Data()[offset] |= tmp << (8 - index); } } } return dst->Size(); } libdc0-0.3.24~svn3121/dclib/core/platform.cpp0000644000175000017500000000254611104361305017557 0ustar sikonsikon/*************************************************************************** platform.cpp - description ------------------- begin : Thu Jun 5 2003 copyright : (C) 2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "platform.h" #include "../dcos.h" #ifdef WIN32 extern "C" { /* * gettimeofday() - QpThread archive */ int gettimeofday(struct timeval *tp, void * /*pv*/ ) { struct _timeb currSysTime; /* get current system time */ _ftime(&currSysTime); tp->tv_sec = currSysTime.time; tp->tv_usec = currSysTime.millitm * 1000; return 0; } } #endif libdc0-0.3.24~svn3121/dclib/core/cmutex.cpp0000644000175000017500000000444411074430057017246 0ustar sikonsikon/*************************************************************************** cmutex.cpp - mutex ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cmutex.h" #ifndef WIN32 #include #include #endif /** */ CMutex::CMutex() { #ifdef WIN32 InitializeCriticalSection(&m_CS); #else int i; if ( (i=pthread_mutex_init(&mutex,NULL)) == 0 ) { m_bMutexInit = true; } else { m_bMutexInit = false; printf("pthread_mutex_init: %s\n",strerror(i)); } #endif } /** */ CMutex::~CMutex() { #ifdef WIN32 DeleteCriticalSection(&m_CS); #else int i; if ( m_bMutexInit ) { if ( (i=pthread_mutex_destroy(&mutex)) != 0 ) { printf("pthread_mutex_destroy: %s\n",strerror(i)); } } m_bMutexInit = false; #endif } /** */ int CMutex::Lock() { #ifdef WIN32 EnterCriticalSection(&m_CS); return 0; #else int i = -1; if ( m_bMutexInit ) { if ( (i=pthread_mutex_lock(&mutex)) != 0 ) { printf("pthread_mutex_lock: %s\n",strerror(i)); } } return i; #endif } /** */ bool CMutex::TryLock() { #ifdef WIN32 return (TryEnterCriticalSection(&m_CS) != 0); #else if ( m_bMutexInit ) return ( pthread_mutex_trylock(&mutex) == 0 ); return false; #endif } /** */ int CMutex::UnLock() { #ifdef WIN32 LeaveCriticalSection(&m_CS); return 0; #else int i = -1; if ( m_bMutexInit ) { if ( (i=pthread_mutex_unlock(&mutex)) != 0 ) { printf("pthread_mutex_unlock: %s\n",strerror(i)); } } return i; #endif } libdc0-0.3.24~svn3121/dclib/core/cxml.h0000644000175000017500000001242411120302273016334 0ustar sikonsikon/*************************************************************************** cxml.h - description ------------------- begin : Sun Jun 9 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CXML_H #define CXML_H /** * @author Mathias Küster, Edward Sheldrake (changed API described below) * * The API was changed so that the rest of dclib * and valknut do not use libxml2 functions / objects directly. * * Instead the CXml object has a current node which is operated on * and functions to move to the next node, to it's first child * or back to the parent node. * There is no longer any xmlNodePtr parameter passing. * * The only disadvantage of the new API is that there are null * pointer checks in each CXml function. * * Also the API requires a do ... while loop instead of a for loop * and Parent() must be called once you have finished parsing or * adding the children. */ #include #include class CIconv; class CByteArray; struct _xmlDoc; struct _xmlNode; class CXml { public: /** */ CXml(); /** */ ~CXml(); /** */ CString Name(); /** */ CString Content(); /** */ CString Prop( const CString & prop ); /** */ CString Prop( const char * prop ); /** */ bool GetBoolChild(); /** * Moves to the document's first child node, and returns true if * it is not null. */ bool DocFirstChild(); /** * If the next node is not null, moves to it and returns true. * Otherwise returns false. * * Strangely there is no "PreviousNode" function because * dclib / valknut does not need it. */ bool NextNode(); /** * Moves the current node to the first child node if there is one. */ bool FirstChild(); /** * If the current node's parent is not null, moves to it and * returns true, otherwise returns false. * * This function is used both when reading and writing XML documents. */ bool Parent(); /** * Creates a new child node with the given name * which becomes the current node. * * All the NewBoolChild / NewNumericChild / NewStringChild functions * add a new node as a child of the current node. */ bool StartNewChild( const char * name ); /** */ bool NewBoolChild( const char * name, bool b ); /** */ bool NewNumericChild( const char * name, const int n ); /** */ bool NewNumericChild( const char * name, const unsigned int n ); /** */ bool NewNumericChild( const char * name, const long n ); /** */ bool NewNumericChild( const char * name, const unsigned long n ); /** */ bool NewNumericChild( const char * name, const long long n ); /** */ bool NewNumericChild( const char * name, const ulonglong n ); /** The almost unused create empty parameter was removed */ bool NewStringChild( const char * name, const CString & s ); /** The almost unused create empty parameter was removed */ bool NewStringChild( const char * name, const char * s ); /** */ bool NewStringProp( const CString & prop, const CString & value ); /** */ bool NewStringProp( const char * prop, const char * value ); /** * Now both creates a new document * and creates the document node with the given name. */ bool NewDoc( const char * docnodename ); /** */ bool ParseFile( CString name ); /** */ bool ParseMemory( const char * s, int size ); /** * Parses the memory, modifying it if necessary * so that it parses. For XML hublists. */ bool ParseFixMemory( CByteArray * ba ); /** * Saves the config file by first writing it to a temp file, * deleting the original, then renaming the temp file back to * the original name. * Returns 1000 if successful or -1 in case of error. * (The libxml2 functions now used do not return the total byte size of the file). */ int SaveConfigXmlViaTemp( CString name ); /** */ CString ToUTF8( const CString & s ); /** */ CString FromUtf8( const CString & s ); /** */ CString ToUTF8( const char * s ); /** */ CString FromUtf8( const char * s ); /** */ static CString EscapeSpecials( const CString & s ); /** */ static CString UnEscapeSpecials( const CString & s ); /** Must be called once on program startup */ static void InitParser(); /** Must be called once on program shutdown */ static void CleanupParser(); /** */ static const char * Libxml2CompiledVersion(); /** */ static const char * Libxml2RunningVersion(); private: /** */ void FreeDoc(); /** */ _xmlDoc * pDoc; /** */ _xmlNode * pNode; /** Encodes from local to UTF-8 */ CIconv * pToUTF8; /** Encodes from UTF-8 to local */ CIconv * pFromUTF8; }; #endif libdc0-0.3.24~svn3121/dclib/core/cfile.h0000644000175000017500000000711311101144617016457 0ustar sikonsikon/*************************************************************************** cfile.h - description ------------------- begin : Wed Apr 3 2003 copyright : (C) 2003-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CFILE_H #define CFILE_H /** *@author Mathias Küster * * Handles file reading and writing, with a write buffer. * * The Close() function used to not return any value and * the return value from close() was not checked. Nothing * much actually checks if Close() returns true or not, * even though write errors may not be reported until * the file is closed, says the man page. */ #include #include #define IO_RAW 0x0001 #define IO_READONLY 0x0002 #define IO_WRITEONLY 0x0004 #define IO_READWRITE 0x0008 #define IO_APPEND 0x0010 #define IO_TRUNCATE 0x0020 #define IO_CREAT 0x0040 #define MO_IRWXU 0x01C0 /* RWX mask for owner */ #define MO_IRUSR 0x0100 /* R for owner */ #define MO_IWUSR 0x0080 /* W for owner */ #define MO_IXUSR 0x0040 /* X for owner */ #define MO_IRWXG 0x0038 /* RWX mask for group */ #define MO_IRGRP 0x0020 /* R for group */ #define MO_IWGRP 0x0010 /* W for group */ #define MO_IXGRP 0x0008 /* X for group */ #define MO_IRWXO 0x0007 /* RWX mask for other */ #define MO_IROTH 0x0004 /* R for other */ #define MO_IWOTH 0x0002 /* W for other */ #define MO_IXOTH 0x0001 /* X for other */ class CByteArray; class CFile { public: /** */ CFile(); /** */ ~CFile(); /** */ bool Open( CString filename, int mode, int acc = 0 ); /** * Creates and opens a temp file, name based on supplied filename. * If successful, filename will be set to the temp file name. * The new name will have a dot and some numbers/letters added. */ bool OpenTemp( CString & filename ); /** */ bool IsOpen() { return (m_nFD!=-1); }; /** */ bool Close(); /** */ long Flush(); /** */ static bool Rename( const CString & absfrom, const CString & absto ); /** */ static bool Remove( const CString & absfile ); /** */ static bool UnLink( const CString & absfile ); /** * Copies the contents of absfrom to absto. * Since dclib only needs to copy files it created * there's no copying of ownership / permissions. * Since dclib only copies files it has just finished writing, * and utimes() only sets last access and modification times * not creation time, there's no setting of timestamps either. */ static bool Copy( const CString & absfrom, const CString & absto ); /** */ long Write( const char * buf, long count ); /** */ long Read( char * buf, long count ); /** */ bool Seek( int64_t offset, int how ); /** */ int GetBufferPos() { return m_nBufferPos; }; private: /** */ int m_nFD; /** */ int m_nMode; /** */ CByteArray * m_pBuffer; /** */ int m_nBufferPos; }; #endif libdc0-0.3.24~svn3121/dclib/core/casyncdns.cpp0000644000175000017500000001150011103425621017707 0ustar sikonsikon/*************************************************************************** casyncdns.cpp - description ------------------- begin : Mon Jun 10 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "casyncdns.h" #include "cnetaddr.h" #include #define HOST_LIST_TIMEOUT 60 #define HOST_CACHE_TIMEOUT 60 /** */ CAsyncDns::CAsyncDns() { m_pHostCache = new CStringList(4); m_pHostList = new CStringList(4); // start new thread Start(); } /** */ CAsyncDns::~CAsyncDns() { SetInstance(0); // stop thread Stop(true); Lock(); delete m_pHostCache; m_pHostCache = 0; delete m_pHostList; m_pHostList = 0; UnLock(); } /** call from application */ eAsyncDns CAsyncDns::GetHostI4( CString stringHost, struct sockaddr_in * sin, CString * errmsg ) { CAsyncDnsEntry * AsyncDnsEntry; eAsyncDns err; // return if lock failed if ( TryLock() == false ) { return eadAGAIN; } err = eadERROR; // sanity check if ( m_pHostCache && m_pHostList && (stringHost.NotEmpty()) && sin ) { if ( m_pHostCache->Get( stringHost, &AsyncDnsEntry ) != -1 ) { // host found in the m_pHostCache list, return first resolved ip memcpy( sin, &AsyncDnsEntry->m_sin, sizeof(struct sockaddr_in) ); m_pHostCache->Del(stringHost); err = eadSUCCESS; } if ( err == eadERROR ) { if ( m_pHostList->Get( stringHost, &AsyncDnsEntry ) == -1 ) { // host not found in the m_pHostList, add it AsyncDnsEntry = new CAsyncDnsEntry(); AsyncDnsEntry->m_sHost = stringHost; AsyncDnsEntry->m_bError = false; // set initial timeout AsyncDnsEntry->m_tTimeout = time(0); m_pHostList->Add( stringHost, AsyncDnsEntry ); err = eadAGAIN; } else if ( AsyncDnsEntry->m_bError == false ) { // dns query not finished err = eadAGAIN; } else { if ( errmsg != 0 ) { // return error message *errmsg = AsyncDnsEntry->m_sErrMsg; } // remove from hostlist m_pHostList->Del(AsyncDnsEntry->m_sHost); } } } UnLock(); return err; } /** */ void CAsyncDns::Thread() { CAsyncDnsEntry * AsyncDnsEntry = 0; Lock(); if ( m_pHostCache->Count() > 0 ) { // check cache timeout to avoid possible list overflows while ( m_pHostCache->Next( &AsyncDnsEntry ) != 0 ) { if ( (time(0)-AsyncDnsEntry->m_tTimeout) >= HOST_CACHE_TIMEOUT ) { // remove entry from m_pHostCache list m_pHostCache->Del(AsyncDnsEntry->m_sHost); AsyncDnsEntry = 0; break; } } } AsyncDnsEntry = 0; if ( m_pHostList->Count() > 0 ) { while ( m_pHostList->Next( &AsyncDnsEntry ) != 0 ) { if ( AsyncDnsEntry->m_bError == false ) { // no error break; } else if ( (time(0)-AsyncDnsEntry->m_tTimeout) >= HOST_LIST_TIMEOUT ) { // timeout, remove host from m_pHostList m_pHostList->Del(AsyncDnsEntry->m_sHost); AsyncDnsEntry = 0; break; } } } if ( AsyncDnsEntry != 0 ) { // no error, no timeout -> update entry CString s = AsyncDnsEntry->m_sHost; UnLock(); UpdateEntry(s); } else { UnLock(); } NanoSleep(50); } /** */ void CAsyncDns::UpdateEntry( CString stringHost ) { CAsyncDnsEntry * AsyncDnsEntry = 0; struct sockaddr_in sin; bool res; CString errmsg; // ask dns for ip res = CNetAddr::GetHostI4( stringHost.Data(), &sin, &errmsg ); Lock(); if ( m_pHostList->Get( stringHost, &AsyncDnsEntry ) == 0 ) { if ( !res ) { // error, update entry AsyncDnsEntry->m_bError = true; // update timeout to avoid list overflow AsyncDnsEntry->m_tTimeout = time(0); AsyncDnsEntry->m_sErrMsg = errmsg; } else { // no error, remove from m_pHostList and update m_pHostCache AsyncDnsEntry = new CAsyncDnsEntry(); AsyncDnsEntry->m_sHost = stringHost; AsyncDnsEntry->m_bError = false; // update timeout to avoid list overflow AsyncDnsEntry->m_tTimeout = time(0); memcpy( &AsyncDnsEntry->m_sin, &sin, sizeof(struct sockaddr_in) ); m_pHostList->Del(stringHost); m_pHostCache->Add(stringHost,AsyncDnsEntry); } } UnLock(); } libdc0-0.3.24~svn3121/dclib/core/che3.cpp0000644000175000017500000004122211074130777016564 0ustar sikonsikon/* rewrite to class without glib by Mathias Küster (2002) */ /* DCTC - a Direct Connect text clone for Linux * Copyright (C) 2001 Eric Prevoteau * * he3.c: Copyright (C) Eric Prevoteau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "che3.h" #include #include #include #include "../dcos.h" #include "clist.h" #include "cbytearray.h" #include "cstring.h" /******************************************************/ /* patch from David Toth for */ /* File sharing list Windows (DC) compatibiliy bugfix */ /* (byte 4 meaning and computation). */ /******************************************************/ /*********************************************************************/ /* When the file list of another user is retrieved, it is compressed */ /* The data format is described below. byte 0: 'H' byte 1: 'E' byte 2: '3' byte 3: 0xD byte 4: 8 bit parity of the decoded data (the result of all bytes "xor"-ed) byte 5 - 8 : it is a number encoded in little endian. It it the number of bytes to produce. byte 9 - 10: it is a number encoded in little endian. This number gives the number of couples. Let's name this number as N byte 11 - (10+2*N): this is a list of couple. The first byte is a character (the one before compression), the second byte gives the length of the compressed pattern. Let's name this value L. byte (11+2*N) - (11+2*N+ ((sum(L)+7)&~7): a bit barbare :) To simplify. Let's name K, the sum of all L values. Here, you find a string of K bits (byte aligned). The L0 first bits are the encoded value of caracter of couple 0. The next Lx bits are the encoded value of caractere of couple x. Note: each byte are used from the lower bit to the upper bit. after this string, you have the encoded string. When data are finally decoded. The format is always: directory name \xD\xA \x9 filename | filesize \xD\xA \x9 filename | filesize \xD\xA \x9 filename | filesize \xD\xA \x9 filename | filesize \xD\xA \x9 filename | filesize \xD\xA */ /* ============================================================================================= */ /* ============================================================================================= */ /* ==================================== Decoding functions ===================================== */ /* ============================================================================================= */ /* ============================================================================================= */ /******************************************************/ /*get 1 bit from the current bit position inside data */ /******************************************************/ unsigned long CHE3::get_bit(unsigned char *data, unsigned long *cur_pos) { unsigned long out; out=((unsigned long)(data[(*cur_pos)/8]>>((*cur_pos)&7)))&1; (*cur_pos)++; return out; } /*********************************************************/ /* get nb_bits from the current bit position inside data */ /*********************************************************/ unsigned long CHE3::get_bits(unsigned char *data, unsigned long *cur_pos, int nb_bit) { int i; unsigned long res=0; for(i=0;iData()[0]=='H')&&(data->Data()[1]=='E')&&(data->Data()[2]=='3')&&(data->Data()[3]==0xD)) { CByteArray *decode_array=NULL; int pos; int nb_couple; int max_len=0; /* max size of encoded pattern */ int ttl_len=0; /* total size of all encoded patterns */ unsigned long offset_pattern; unsigned long offset_encoded; int nb_output; /* compute the number of bytes to produce */ nb_output=(((int)(data->Data()[8]))&255); nb_output<<=8; nb_output|=(((int)(data->Data()[7]))&255); nb_output<<=8; nb_output|=(((int)(data->Data()[6]))&255); nb_output<<=8; nb_output|=(((int)(data->Data()[5]))&255); /* compute the number of couples */ nb_couple=data->Data()[9]; nb_couple+=((((int)(data->Data()[10]))&255)<<8); for(pos=0;posData()[12+pos*2]))&255); if(v>max_len) max_len=v; ttl_len+=v; } //decode_array=g_byte_array_new(); decode_array = new CByteArray(); //decode_array=g_byte_array_set_size(decode_array,1<<(max_len+1)); /* theorytically, max_len could reach up to 255 */ decode_array->SetSize(1<<(max_len+1)); /* but really, a value above 15 is not oftenly encountered */ /* thus the algorithm needs no more than ... 64KB */ /* raisonnable value is upto 23 (requires 8MB) */ { // CString *tmp; //tmp=g_string_new(""); // tmp = new CString(); // g_string_sprintf(tmp,"he3:max_len: %d",max_len); // disp_msg(INFO_MSG,"decode_he3_data",tmp->str,NULL); //g_string_free(tmp,true); // delete tmp; } if(decode_array!=NULL) { /* clear the decode array */ /* the decode array is technically a binary tree */ /* if the depth of the tree is big (let's say more than 10), */ /* storing the binary tree inside an array becomes very memory consumming */ /* but I am too lazy to program all binary tree creation/addition/navigation/destruction functions :) */ memset(decode_array->Data(),0,1<<(max_len+1)); offset_pattern=8*(11+nb_couple*2); /* position of the pattern block, it is just after the list of couples */ offset_encoded=offset_pattern + ((ttl_len+7)&~7); /* the encoded data are just after */ /* the pattern block (rounded to upper full byte) */ /* decode_array is a binary tree. byte 0 is the level 0 of the tree. byte 2-3, the level 1, byte 4-7, the level 2, */ /* in decode array, a N bit length pattern having the value K is its data at the position: */ /* 2^N + (K&((2^N)-1)) */ /* due to the fact K has always N bit length, the formula can be simplified into: */ /* 2^N + K */ for(pos=0;posData()[12+pos*2]))&255); /* the number of bit required */ value=get_bits(data->Data(),&offset_pattern,v_len); decode_array->Data()[(1<Data()[11+pos*2]; /* the character */ } /* now, its time to decode */ //while(output->len!=nb_output) int l=0; while(output->Length()!=nb_output) //while(l!=nb_output) { unsigned long cur_val; unsigned int nb_bit_val; cur_val=get_bit(data->Data(),&offset_encoded); /* get one bit */ nb_bit_val=1; while(decode_array->Data()[(1<Data(),&offset_encoded); nb_bit_val++; } //output=g_string_append_c(output,decode_array->data[(1<Data()[(1<Length()); l++; } //g_byte_array_free(decode_array,true); delete decode_array; } } { int i; unsigned char parity=0; for(i=0;iLength();i++) parity^=output->Data()[i]; // if ( data->Size()>5 ) // printf("PARITY : %d %d\n",data->Data()[4],parity); } return output; } #if 0 int main(int argc,char **argv) { CByteArray *in; CString *out; unsigned char tst[54]={0x48,0x45,0x33,0x0D,0x12,0x24,0x00,0x00,0x00,0x0B,0x00,0x09,0x04,0x0A,0x03,0x0D,0x04,0x2E,0x04,0x32,0x04,0x61,0x02,0x62,0x03,0x65,0x05,0x73,0x05,0x74,0x03,0x7C,0x04,0xA6,0xF4,0xE2,0x21,0xAE,0x01,0x61,0x71,0x29,0xFB,0xFF,0xFF,0xBE,0x75,0xA5,0x0C,0x00,0xF0,0xAD,0x2B,0x05}; //in=g_byte_array_new(); in = new CByteArray(); //in=g_byte_array_append(in,tst,54); in->Append(tst,54); out=decode_he3_data(in); //g_byte_array_free(in,true); delete in; printf("%s\n",out->str); } #endif /* ============================================================================================= */ /* ============================================================================================= */ /* ==================================== Encoding functions ===================================== */ /* ============================================================================================= */ /* ============================================================================================= */ //static gint huf_insert_glist(gconstpointer a, gconstpointer b) int CHE3::huf_insert_glist(void * a, void * b) { if(((const HUFNODE*)a)->occur<((const HUFNODE*)b)->occur) return -1; /* a is must be before b */ else if(((const HUFNODE*)a)->occur>((const HUFNODE*)b)->occur) return 1; /* a is must be after b */ /* if both have the same occurences, the one without son comes before */ if( (((const HUFNODE*)a)->left==NULL) && (((const HUFNODE*)b)->left==NULL) ) return -1; if(((const HUFNODE*)a)->left==NULL) return -1; return 1; } /**************************************************************************/ /* recursively scan all nodes of the huffman tree and fill encoding table */ /**************************************************************************/ void CHE3::use_hufnode(HUFENCODE tbl_enc[256], HUFNODE *node,unsigned int bits_len, unsigned long bits) { if(node->left!=NULL) { /* it is a node, right is always != NULL */ use_hufnode(tbl_enc,node->left,bits_len+1,(bits<<1)|0); use_hufnode(tbl_enc,node->right,bits_len+1,(bits<<1)|1); } else { /* it is a leaf, right is always NULL */ int idx=((int)node->val)&255; tbl_enc[idx].bits_len=bits_len; tbl_enc[idx].bits=bits; #if 0 printf("huf: bits_len: %u pattern: %lu ",bits_len,bits); printf("leaf: %d (%c)\n",idx,node->val); #endif // if(bits_len>8*sizeof(unsigned long)) /* compared with the size of unsigned long in bits */ // disp_msg(ERR_MSG,"user_hufnode","encoded value cannot fit into unsigned long",NULL); } return; } /*****************************************************************/ /* recursively free memory used by all nodes of the huffman tree */ /*****************************************************************/ void CHE3::free_hufnode(HUFNODE *node) { if(node==NULL) return; if(node->left!=NULL) free_hufnode(node->left); if(node->right!=NULL) free_hufnode(node->right); free(node); } CByteArray *CHE3::add_bit(CByteArray *data, unsigned long *bit_pos, unsigned char bit_value) { if(((*bit_pos)&7)==0) /* starting a new byte ? */ { unsigned char v=0; //data=g_byte_array_append(data,&v,1); data->Append(&v,1); } /* due to the fact we always add 0 as new byte, we don't have to set bit having 0 as value */ /* but just 1 */ if(bit_value!=0) { data->Data()[(*bit_pos)/8]|= (1<<((*bit_pos)&7)); } (*bit_pos)++; return data; } /**************************************/ /* append the pattern to data@bit_pos */ /**************************************/ CByteArray *CHE3::add_bits(CByteArray *data, unsigned long *bit_pos, unsigned long pattern, unsigned int pattern_length) { unsigned long i; for(i=0;i>(pattern_length-1-i))&1) ); /* use pattern from upper to lower bit */ } return data; } #if 0 static void disp_huf(GList *pre_tree) { int i; HUFNODE *w; printf("---\n"); //for(i=0;isize;i++) { w=g_list_nth_data(pre_tree,i); /* get the first HUFNODE of the list */ printf("occur: %ld, left=%p, right=%p, val=%02X\n",w->occur,w->left,w->right,w->val); } } #endif /*****************************************************************************************/ /* compress data compressed using an Huffman algorithm and store it in HE3 usable format */ /*****************************************************************************************/ /* input: a GString containing a string to compress */ /* output: a GByteArray containing compressed data or NULL */ /***********************************************************/ CByteArray *CHE3::encode_he3_data(const CString *str) { unsigned long occur[256]; HUFENCODE tbl_enc[256]; long i; CByteArray *data; //GList *pre_tree=NULL; CList *pre_tree=NULL; HUFNODE *root_huf=NULL; int nb_val=0; unsigned long bit_pos; if((str==NULL)||(str->Length()==0)) return NULL; /* count the number of times each character appears */ memset(occur,0,sizeof(occur)); //for(i=0;ilen;i++) for(i=0;iLength();i++) { occur[((int)(str->Data()[i]))&255]++; } /* now, we will build the huffman tree */ pre_tree = new CList(); /* stage 1: create all the leafs */ for(i=0;i<256;i++) { if(occur[i]!=0) { HUFNODE *nw; nw=(HUFNODE*)malloc(sizeof(HUFNODE)); nw->occur=occur[i]; nw->left=NULL; nw->right=NULL; nw->val=(unsigned char)i; //pre_tree=g_list_insert_sorted(pre_tree,nw, huf_insert_glist); pre_tree->InsertSorted((CString*)nw, huf_insert_glist); nb_val++; } } //while(g_list_length(pre_tree)>1) while(pre_tree->Count()>1) { HUFNODE *nw; nw=(HUFNODE*)malloc(sizeof(HUFNODE)); nw->left=(HUFNODE*)pre_tree->Next(0); /* get the first HUFNODE of the list */ pre_tree->Remove((CString*)nw->left); /* and remove it */ nw->right=(HUFNODE*)pre_tree->Next(0); /* get the second HUFNODE of the list */ pre_tree->Remove((CString*)nw->right); /* and remove it */ nw->occur=nw->left->occur+nw->right->occur; nw->val=0; /* add a new node having the 2 removed nodes as son */ //pre_tree=g_list_insert_sorted(pre_tree,nw, huf_insert_glist); pre_tree->InsertSorted((CString*)nw, huf_insert_glist); } #if 0 disp_huf(pre_tree); #endif /* now, the huffman tree is done */ //root_huf=g_list_nth_data(pre_tree,0); root_huf=(HUFNODE*)pre_tree->Next(0); //pre_tree=g_list_remove(pre_tree,root_huf); pre_tree->Remove((CString*)root_huf); memset(tbl_enc,0,sizeof(tbl_enc)); /* now, we will compute encoding pattern from huffman tree */ use_hufnode(tbl_enc,root_huf,0,0); /* well, encoding table is now done, we can encode the data */ //data=g_byte_array_new(); data = new CByteArray(); /* set the initial HE3 header */ { unsigned char he3_header[]={'H','E','3',0xD, 0, /* parity: all uncompressed bytes xor'ed */ 0,0,0,0, /* number of bytes to produce (little-endian) */ 0,0}; /* number of couples */ /* patch from David Toth (byte 4: parity computation) */ unsigned char parity=0; //for(i=0;ilen;i++) for(i=0;iLength();i++) parity^=str->Data()[i]; he3_header[4]=(unsigned char)(parity&255); //he3_header[5]=str->len&255; he3_header[5]=(unsigned char)(str->Length()&255); he3_header[6]=(unsigned char)((str->Length()>>8)&255); he3_header[7]=(unsigned char)((str->Length()>>16)&255); he3_header[8]=(unsigned char)((str->Length()>>24)&255); he3_header[9]=(unsigned char)(nb_val&255); he3_header[10]=(unsigned char)((nb_val>>8)&255); //data=g_byte_array_append(data,he3_header,11); data->Append(he3_header,11); } /* add the couple list (character, pattern length) */ for(i=0;i<256;i++) { if(occur[i]!=0) { unsigned char ent[2]; ent[0]=(unsigned char)i; ent[1]=(unsigned char)tbl_enc[i].bits_len; //data=g_byte_array_append(data,ent,2); data->Append(ent,2); } } /* and now, add all the patterns */ bit_pos=data->Size()*8; for(i=0;i<256;i++) { if(occur[i]!=0) { data=add_bits(data,&bit_pos,tbl_enc[i].bits, tbl_enc[i].bits_len); } } bit_pos=(bit_pos+7)&~7; /* move to the beginning of the next byte */ /* now, we encode the string */ for(i=0;iLength();i++) { int idx=((int)str->Data()[i])&255; data=add_bits(data,&bit_pos,tbl_enc[idx].bits, tbl_enc[idx].bits_len); } /* free huffman tree */ free_hufnode(root_huf); delete pre_tree; return data; } libdc0-0.3.24~svn3121/dclib/core/cstring.h0000644000175000017500000002401011102360525017040 0ustar sikonsikon/*************************************************************************** cstring.h - description ------------------- begin : Fri Sep 21 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSTRING_H #define CSTRING_H /** *@author Mathias Küster * * Now that CStringList is a template class, lots of classes, starting * with CString, no longer need to inherit CObject or have a virtual * destructor, which should make creating and destroying them * slightly faster. * * The appending functions no longer start by making a copy of the data * and then appending that. Instead there is some pointer checking, * for handling appending (part of) a string to itself. * * Despite dclib being full of "inline" functions, IsEmpty() is not inline. * * CString s = ""; * s.Data() == NULL; * * An empty CString generally contains a NULL pointer. NULL pointers usually * crash C library functions that take a "char *" parameter. * * CString has no idea what encoding the string is in, it's length is the * number of bytes which may well be more than the number of characters * for UTF-8. ToUpper() and ToLower() only handle ascii a-z -> A-Z. * * The main thing about CString is it does not having the implicit sharing * that the QT's QString and other classes, so it is not very efficient to * pass it around by value. */ #include class CString { public: /** Constructs a null string. This is a string that has not been assigned to anything, i.e. both the length and data pointer is 0. */ CString(); /** Constructs a string that is a deep copy of sz, interpreted as a classic C string. If sz is 0, then a null string is created. */ CString( const char * sz ); /** Constructs a string giving it a length of one character, assigning it the character ch. */ CString( const char ch ); /** Constructs a string that is a deep copy of stringSrc. */ CString( const CString & stringSrc ); /** Destroys the string and frees its buffer. */ ~CString(); /** */ void Empty(); /** */ bool IsEmpty() const; /** */ bool NotEmpty() const { return !IsEmpty(); } /** * This is supposed to be faster than doing * * s.Left(other.Length()) == other * * because it avoids Left() which creates a copy. * * In QT4 a null QString does not start with an empty QString. * However in dclib an empty CString is always null. * Therefore if other is empty StartsWith always returns true * even if this CString is also empty. */ bool StartsWith( const CString & other ) const; /** */ bool StartsWith( const char * other, long len ) const; /** */ inline CString& Set( const char * sz, long nLength ) { set(sz,nLength); return *this; } /** */ long Find( const char ch, long nStart = 0 ) const; /** */ long Find( const char * sz, long nStart = 0, bool cs = true ) const; /** */ long Find( const CString & string, long nStart = 0, bool cs = true ) const; /** */ long FindCase( const char * sz, long nStart = 0 ) const; /** */ long FindCase( const CString & string, long nStart = 0 ) const; /** */ long FindRev( char ch, long nStart = -1 ) const; /** */ long FindRev( const CString & string ) const; /** */ void Append( const char ch ); /** */ inline void Append( const char * sz ) { add(sz); } /** */ inline void Append( const CString & string ) { add(string.Data(),string.Length()); } /** */ inline CString Left( long nCount ) const { return Mid(0,nCount); } /** */ inline CString Right( long nCount ) const { return Mid(Length()-nCount,nCount); }; /** */ CString Mid( long nFirst, long nCount = -1 ) const; /** */ CString Section( const char sep, int start, int end ) const; /** */ CString RightJustify( long nNewLength, char chFill = ' ', bool truncate = false ); /** */ CString ToUpper() const; /** */ CString ToLower() const; /** */ CString Replace( CString src, CString string ) const; /** * Replaces all occurences of 'before' in the string * with 'after'. * * Although any normal string replace function would * return a reference to itself by returning *this, * CString::Swap() does not. */ void Swap( const char before, const char after ); /** * These all used to be called setNum but since * they didn't (did not modify the string), they just make * a new string and return it, they have been made static * and renamed for consistency with QString. */ static CString number( const int n ); /** */ static CString number( const unsigned int n ); /** */ static CString number( const long n ); /** */ static CString number( const unsigned long n ); /** */ static CString number( const long long n ); /** */ static CString number( const ulonglong n ); /** */ static CString number( const double n, const int p ); /** */ ulonglong asULL( int base = 10 ) const; /** */ unsigned int asUINT( int base = 10 ) const; /** */ unsigned long asULONG( int base = 10 ) const; /** */ int asINT( int base = 10 ) const; /** */ long asLONG( int base = 10 ) const; /** */ long long asLONGLONG( int base = 10 ) const; /** */ double asDOUBLE() const; /** */ unsigned char GetHash( long value = 0 ) const; /** */ inline CString& operator += ( const char ch ) { Append(ch); return *this; }; /** */ inline CString& operator += ( const char * sz ) { add(sz); return *this; }; /** */ inline CString& operator += ( const CString & string ) { add(string.Data(),string.Length()); return *this; }; /** */ inline CString & operator = ( const char * sz ) { set(sz); return *this; }; /** */ inline CString & operator = ( const CString & string ) { set(string.Data(),string.Length()); return *this; }; /** */ inline char * Data() const { return m_szBuffer; } /** */ inline long Length() const { return m_nStringLength; } /** * Returns 0 if strings are equal, <0 if other is less than this, >0 if other is greater than this. * So essentially it's just strcoll (which uses current locale). */ int Compare ( const CString & other ) const; /** */ int Compare ( const char * other ) const; private: /** */ long m_nStringLength; /** */ long m_nBufferSize; /** */ char * m_szBuffer; /** */ void set( const char * sz, long nLength = -1 ); /** */ void add( const char * sz, long nLength = -1 ); /** * This should never have been public unless you actually * want a function for leaking memory. */ void Init(); /** * For private use, to create a CString from an existing buffer. */ CString( char * buffer, long length, long bufsize ); }; /** */ bool operator == ( const CString & string1, const CString & string2 ); /** */ bool operator == ( const char * sz, const CString & string ); /** */ bool operator == ( const CString & string, const char * sz ); /** */ bool operator != ( const CString & string1, const CString & string2 ); /** */ bool operator != ( const char * sz, const CString & string ); /** */ bool operator != ( const CString & string1, const char * sz ); /** */ inline CString operator + ( const CString & string1, const CString & string2 ) { CString tmp(string1); tmp.Append(string2); return tmp; } /** */ inline CString operator + ( const char * sz, const CString & string ) { CString tmp(sz); return (tmp+string); } /** Returns true if lhs is less than rhs, false if equal or greater than */ inline bool operator < ( const CString & lhs, const CString & rhs ) { return (lhs.Compare(rhs) < 0); } /** Returns true if lhs is less than rhs, false if equal or greater than */ inline bool operator < ( const CString & lhs, const char * rhs ) { return (lhs.Compare(rhs) < 0); } /** Returns true if lhs is less than rhs, false if equal or greater than */ inline bool operator < ( const char * lhs, const CString & rhs ) { return (rhs.Compare(lhs) > 0); } /** Returns true if lhs is less than or equal to rhs, false if greater than */ inline bool operator <= ( const CString & lhs, const CString & rhs ) { return (lhs.Compare(rhs) <= 0); } /** Returns true if lhs is less than or equal to rhs, false if greater than */ inline bool operator <= ( const CString & lhs, const char * rhs ) { return (lhs.Compare(rhs) <= 0); } /** Returns true if lhs is less than or equal to rhs, false if greater than */ inline bool operator <= ( const char * lhs, const CString & rhs ) { return (rhs.Compare(lhs) >= 0); } /** Returns true if lhs is greater than rhs, false if equal or less than */ inline bool operator > ( const CString & lhs, const CString & rhs ) { return (lhs.Compare(rhs) > 0); } /** Returns true if lhs is greater than rhs, false if equal or less than */ inline bool operator > ( const CString & lhs, const char * rhs ) { return (lhs.Compare(rhs) > 0); } /** Returns true if lhs is greater than rhs, false if equal or less than */ inline bool operator > ( const char * lhs, const CString & rhs ) { return (rhs.Compare(lhs) < 0); } /** Returns true if lhs is greater than or equal to rhs, false if less than */ inline bool operator >= ( const CString & lhs, const CString & rhs ) { return (lhs.Compare(rhs) >= 0); } /** Returns true if lhs is greater than or equal to rhs, false if less than */ inline bool operator >= ( const CString & lhs, const char * rhs ) { return (lhs.Compare(rhs) >= 0); } /** Returns true if lhs is greater than or equal to rhs, false if less than */ inline bool operator >= ( const char * lhs, const CString & rhs ) { return (rhs.Compare(lhs) <= 0); } #endif libdc0-0.3.24~svn3121/dclib/core/cstring.cpp0000644000175000017500000003551211212460320017400 0ustar sikonsikon/*************************************************************************** cstring.cpp - description ------------------- begin : Fri Sep 21 2001 copyright : (C) 2001-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cstring.h" #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include /* for testing both code paths */ /* ifdef HAVE_STRCASESTR * undef HAVE_STRCASESTR * endif */ CString::CString() { Init(); } CString::CString( const char * sz ) { Init(); set(sz); } CString::CString( const char ch ) { Init(); set(&ch,1); } CString::CString( const CString & stringSrc ) { Init(); set(stringSrc.m_szBuffer,stringSrc.m_nStringLength); } CString::CString( char * buffer, long length, long bufsize ) { m_szBuffer = buffer; m_nStringLength = length; m_nBufferSize = bufsize; } CString::~CString() { if (m_szBuffer) { free(m_szBuffer); m_szBuffer = 0; } } /** */ void CString::Init() { m_szBuffer = 0; m_nStringLength = 0; m_nBufferSize = 0; } /** */ void CString::Empty() { if (m_szBuffer) { free(m_szBuffer); } Init(); } /** */ unsigned char CString::GetHash( long value ) const { if ( (m_nStringLength > 0) && (value < m_nStringLength) ) return ((unsigned char)(m_szBuffer[value]&0xFF)); else return 0; } /** */ long CString::Find( const char ch, long nStart ) const { if ( m_nStringLength == 0 ) { return -1; } if ( nStart > m_nStringLength ) return -1; for ( long i = nStart; i < m_nStringLength; ++i ) { if ( m_szBuffer[i] == ch ) return i; } return -1; } /** */ long CString::Find( const char * sz, long nStart, bool cs ) const { if ( !cs ) { return FindCase(sz,nStart); } if ( m_nStringLength == 0 ) { if ( sz != 0 ) return -1; else return 0; } if ( !sz ) return -1; const long len = strlen(sz); if ( (nStart+len) > m_nStringLength ) return -1; const char * location = strstr( m_szBuffer + nStart, sz ); if ( location == NULL ) { return -1; } else { return location - m_szBuffer; } } /** */ long CString::Find( const CString & string, long nStart, bool cs ) const { if ( !cs ) { return FindCase(string,nStart); } if ( m_nStringLength == 0 ) { if ( string.Length() == 0 ) return 0; else return -1; } if ( string.Data() == 0 ) return -1; if ( (nStart+string.Length()) > m_nStringLength ) return -1; const char * location = strstr( m_szBuffer + nStart, string.Data() ); if ( location == NULL ) { return -1; } else { return location - m_szBuffer; } } /** */ long CString::FindCase( const char * sz, long nStart ) const { if ( m_nStringLength == 0 ) { if ( sz != 0 ) return -1; else return 0; } if ( !sz ) return -1; const long len = strlen(sz); if ( (nStart+len) > m_nStringLength ) return -1; #ifdef HAVE_STRCASESTR const char * location = strcasestr( m_szBuffer + nStart, sz ); if ( location == NULL ) { return -1; } else { return location - m_szBuffer; } #else // HAVE_STRCASESTR for ( long i = nStart; i <= (m_nStringLength-len); ++i ) { #ifdef WIN32 if ( _strnicmp(sz,m_szBuffer+i,len) == 0 ) #else if ( strncasecmp(sz,m_szBuffer+i,len) == 0 ) #endif { return i; } } return -1; #endif // HAVE_STRCASESTR } /** */ long CString::FindCase( const CString & string, long nStart ) const { const char * sz = string.Data(); const long len = string.Length(); if ( m_nStringLength == 0 ) { if ( sz != 0 ) return -1; else return 0; } if ( !sz ) return -1; if ( (nStart+len) > m_nStringLength ) return -1; #ifdef HAVE_STRCASESTR const char * location = strcasestr( m_szBuffer + nStart, sz ); if ( location == NULL ) { return -1; } else { return location - m_szBuffer; } #else // HAVE_STRCASESTR for ( long i = nStart; i <= (m_nStringLength-len); ++i ) { #ifdef WIN32 if ( _strnicmp(sz,m_szBuffer+i,len) == 0 ) #else if ( strncasecmp(sz,m_szBuffer+i,len) == 0 ) #endif { return i; } } return -1; #endif // HAVE_STRCASESTR } /** */ long CString::FindRev( char ch, long nStart ) const { if ( m_nStringLength == 0 ) return -1; if ( nStart < 0 ) nStart = m_nStringLength-1; else if ( nStart > (m_nStringLength-1) ) return -1; for ( long i = nStart; i >= 0; --i ) { if (m_szBuffer[i]==ch) return i; } return -1; } /** */ long CString::FindRev( const CString & string ) const { const long len = string.Length(); if ( m_nStringLength == 0 ) { if ( len == 0 ) return 0; else return -1; } if ( len == 0 ) return -1; for ( long i = (m_nStringLength-len); i >= 0; --i ) { if ( strncmp( m_szBuffer+i, string.Data(), len ) == 0 ) { return i; } } return -1; } /** */ CString CString::Mid( long nFirst, long nCount ) const { CString ret; // added_by_frg for nFirst < 0 case: // which is needed in all occasions where we use str.Right(n) where n > str.Length() if (nFirst < 0) { nCount += nFirst; nFirst = 0; } // addition_end if ( m_nStringLength == 0 ) return ret; if ( nCount == -1 ) nCount = m_nStringLength-nFirst; if ( nCount <= 0 ) return ret; if( nFirst > m_nStringLength ) return ret; if( (nFirst+nCount) > m_nStringLength ) return ret; ret.set(m_szBuffer+nFirst,nCount); return ret; } /** */ CString CString::Section( const char sep, int start, int end ) const { int i,si,ei; if ( m_nStringLength == 0 ) return CString(); for(i=0,si=0;i= m_szBuffer) && ( sz <= m_szBuffer+m_nBufferSize ) ) { temp = (char*) malloc( l ); if ( temp == 0 ) { perror("CString::set malloc "); return; } memcpy(temp,sz,l); } else { temp = (char*) sz; } Empty(); m_szBuffer = (char*) malloc(l+1); //new char[l+1]; if ( m_szBuffer == 0 ) { printf("CString::set malloc [%ld]: %s\n",l+1,strerror(errno)); if ( temp != sz ) { free(temp); } return; } memcpy(m_szBuffer,temp,l); m_szBuffer[l] = 0; m_nStringLength = l; m_nBufferSize = l+1; if ( temp != sz ) { free(temp); } } /** */ void CString::add( const char * sz, long nLength ) { long l,len,i; char *p; char * temp; if (!sz) return; if( nLength == -1 ) l = strlen(sz); else l = nLength; if (l<=0) return; if(!m_szBuffer) { set(sz,l); } else { // if pointers overlap, copy input before realloc // which also means memcpy is safe (do not need memmove) if ( (sz >= m_szBuffer) && (sz <= m_szBuffer+m_nBufferSize) ) { temp = (char*) malloc( l ); if ( temp == 0 ) { perror("CString::add malloc "); return; } memcpy(temp,sz,l); } else { temp = (char*) sz; } len = m_nStringLength; if((l+len+1)>m_nBufferSize) { i = 1000+1+l; p = (char*) realloc(m_szBuffer,m_nBufferSize+i); if ( p == 0 ) { perror("CString::add realloc "); if ( temp != sz ) { free(temp); } return; } m_szBuffer = p; m_nBufferSize += i; } memset(m_szBuffer+len+l,0,1); memcpy(m_szBuffer+len,temp,l); m_nStringLength+=l; if ( temp != sz ) { free(temp); } } } /** */ void CString::Append( const char ch ) { if ( m_nStringLength + 2 > m_nBufferSize ) { char * newbuf = (char*) realloc( m_szBuffer, m_nBufferSize + 200 ); if ( newbuf == 0 ) { perror("CString::addchar realloc "); return; } m_szBuffer = newbuf; m_nBufferSize += 200; } m_szBuffer[m_nStringLength] = ch; m_szBuffer[m_nStringLength+1] = 0; ++m_nStringLength; } /** */ bool operator == ( const CString & string1, const CString & string2 ) { if ( string1.IsEmpty() ) { return string2.IsEmpty(); } if ( string1.Length() != string2.Length() ) return false; if ( memcmp( string1.Data(), string2.Data(), string1.Length() ) != 0 ) return false; return true; } /** */ CString CString::RightJustify( long nNewLength, char fill , bool /*truncate*/ ) { CString s; while( (s.m_nStringLength+m_nStringLength) < nNewLength ) s+=fill; return(s+*this); } /** */ bool operator == ( const char * sz, const CString & string ) { if ( sz == 0 ) { return string.IsEmpty(); } else { if ( strlen(sz) == (size_t) string.Length() ) { return ( memcmp( sz, string.Data(), string.Length() ) == 0 ); } else { return false; } } } /** */ bool operator == ( const CString & string, const char * sz ) { return ( sz == string ); } /** */ bool operator != ( const CString & string1, const CString & string2 ) { return (!(string1 == string2)); } /** */ bool operator != ( const char * sz, const CString & string ) { return (!(sz == string)); } /** */ bool operator != ( const CString & string, const char * sz ) { return (!(sz == string)); } /** */ int CString::Compare( const CString & other ) const { if ( m_nStringLength == 0 ) { if ( other.IsEmpty() ) { return 0; } else { return 1; } } else if ( other.IsEmpty() ) { return -1; } else { return strcoll( Data(), other.Data() ); } } /** */ int CString::Compare( const char * other ) const { if ( m_nStringLength == 0 ) { if ( other == NULL ) { return 0; } else { return 1; } } else if ( other == NULL ) { return -1; } else { return strcoll( Data(), other ); } } /** */ bool CString::StartsWith( const CString & other ) const { if ( other.Length() > m_nStringLength ) { return false; } else if ( other.Length() == 0 ) { return true; } else { return strncmp( m_szBuffer, other.Data(), other.Length() ) == 0; } } /** */ bool CString::StartsWith( const char * other, long len ) const { if ( len > m_nStringLength ) { return false; } else if ( len == 0 ) { return true; } else { return strncmp( m_szBuffer, other, len ) == 0; } } libdc0-0.3.24~svn3121/dclib/core/clist.h0000644000175000017500000001274611105406264016526 0ustar sikonsikon/*************************************************************************** clist.h - description ------------------- begin : Sat Mai 5 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CLIST_H #define CLIST_H /** *@author Mathias Küster * * A pointer based linked list with auto delete. */ #include typedef int (*CompareFunc) (void*, void*); template class CListObject { public: /** */ CListObject() {}; /** */ ~CListObject() {}; /** */ CListObject * prev; /** */ CListObject * next; /** */ type * Object; }; template class CList { public: /** */ CList(); /** */ ~CList(); /** */ int Add( type * Object ); /** */ int Del( type * Object ); /** */ void Clear(); /** */ int Remove( type * Object ); /** */ int InsertSorted( type * Object, CompareFunc func ); /** */ type * Prev( type * Object ); /** */ type * Next( type * Object ); /** */ long Count() const; private: /** */ long size; /** */ CListObject * pFirst; /** */ CListObject * pLast; /** */ CListObject * pCache; /** */ CListObject * FindListObject( type * Object ); }; /** */ template inline long CList::Count() const { return size; } /** */ template inline CList::CList() { pFirst = 0; pLast = 0; pCache = 0; size = 0; } /** */ template inline CList::~CList() { Clear(); } /** */ template inline int CList::InsertSorted( type * Object, CompareFunc func ) { CListObject * lb, *lb1; if (!Object) return -1; if (!pFirst) { Add(Object); return 0; } lb = pFirst; lb1 = 0; while(lb!=0) { if (func(Object,lb->Object)==-1) { lb1 = new CListObject(); lb1->Object = Object; lb1->prev = lb->prev; lb->prev = lb1; lb1->next = lb; if (pFirst==lb) pFirst=lb1; else lb1->prev->next = lb1; size++; pCache = 0; return 0; } lb = lb->next; } if ( lb1 == 0 ) { Add(Object); } return 0; } /** */ template inline int CList::Add( type * Object ) { if ( Object == 0 ) { return -1; } if ( pFirst == 0 ) { pFirst = pLast = new CListObject(); pFirst->prev = 0; pFirst->next = 0; pFirst->Object = Object; } else if ( pLast != 0 ) { pLast->next = new CListObject(); pLast->next->prev = pLast; pLast->next->next = 0; pLast->next->Object = Object; pLast = pLast->next; } else { // error } size++; pCache = 0; return 0; } /** */ template inline int CList::Del( type * Object ) { CListObject * lb = FindListObject( Object ); if ( lb == 0 ) return -1; delete lb->Object; if ( lb->prev != 0 ) lb->prev->next = lb->next; if ( lb->next != 0 ) lb->next->prev = lb->prev; if ( lb == pFirst ) pFirst = lb->next; if ( lb == pLast ) pLast = lb->prev; delete lb; size--; pCache = 0; return 0; } /** */ template inline void CList::Clear() { CListObject * lb = pFirst; while(lb!=0) { delete lb->Object; pLast = lb->next; delete lb; lb = pLast; } pFirst = 0; pLast = 0; pCache = 0; size = 0; } /** */ template inline int CList::Remove( type * Object ) { CListObject * lb = FindListObject( Object ); if ( lb == 0 ) return -1; if ( lb->prev != 0 ) lb->prev->next = lb->next; if ( lb->next != 0 ) lb->next->prev = lb->prev; if ( lb == pFirst ) pFirst = lb->next; if ( lb == pLast ) pLast = lb->prev; delete lb; size--; pCache = 0; return 0; } /** */ template inline type * CList::Prev( type * Object ) { CListObject * lb = 0; if (pLast==0) return 0; if ( Object == 0 ) { pCache = pLast; return pCache->Object; } if ( pCache != 0 ) if ( pCache->Object == Object ) lb = pCache; if ( lb == 0 ) if ( (lb = FindListObject( Object )) == 0 ) { pCache = 0; return 0; } pCache = lb->prev; if ( pCache == 0 ) return 0; return pCache->Object; } /** */ template inline type * CList::Next( type * Object ) { CListObject * lb = 0; if (pFirst==0) return 0; if ( Object == 0 ) { pCache = pFirst; return pCache->Object; } if ( pCache != 0 ) if ( pCache->Object == Object ) lb = pCache; if ( lb == 0 ) if ( (lb = FindListObject( Object )) == 0 ) { pCache = 0; return 0; } pCache = lb->next; if ( pCache == 0 ) return 0; return pCache->Object; } /** */ template inline CListObject * CList::FindListObject( type * Object ) { CListObject * lb = pFirst; while(lb!=0) { if (lb->Object == Object ) { return lb; } lb = lb->next; } return lb; } #endif libdc0-0.3.24~svn3121/dclib/core/cthread.h0000644000175000017500000000647411101172456017022 0ustar sikonsikon/*************************************************************************** cthread.h - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CTHREAD_H #define CTHREAD_H /** *@author Mathias Küster * * Threading in dclib: there isn't really any. Almost everything * runs on CManager's thread, there is a thread permanently waiting * to do DNS lookups, and a thread is started for filelist refresh * and to send public hubs data to CConfig. * * CConnection inherits CThread, so all hub, peer and http connections * are threads, but none are started, all their Thread() functions * get called by CConnectionManager, CDownloadManager or CManager * directly. * * This explains the unusual design of this class, the Thread() * virtual function (or the callback) is called repeatedly until * someone calls Stop(), to use it like a normal thread class * call Stop(false) at the end of your Thread() function. * * The Stop() function of course, does not halt the thread, just * stops the Thread() function being called again. It does however * wait for the thread to finish before returning unless you * call Stop(false). But it will not wait for a thread that has already * had Stop() called but hasn't finished running yet. */ #ifndef WIN32 #include #endif #include #include class _CCallback0; class CThread : public CMutex { public: /** */ CThread(); /** */ virtual ~CThread(); /** */ int Start(); /** */ int Stop( bool bHard = true ); /** */ bool Stopped() const; /** * To avoid changing Stop() this just does * pthread_join, i.e. it makes the calling thread * wait forever until the thread finishes. * * Returns true if pthread_join() returns 0 i.e. * was successful. * * If the thread isn't running according to iRun * pthread_join() is not called and false is returned. */ bool Join(); /** */ static void NanoSleep( unsigned long ); /** */ void SetThreadCallBackFunction( _CCallback0 * callback ); /** */ virtual void Thread() {}; protected: /** */ int iRun; private: /** callback function */ _CCallback0 * _thread_callback_function; #ifdef WIN32 /** */ HANDLE thread; #else /** */ pthread_t thread; #endif /** */ int iStop; /** */ #ifdef WIN32 static unsigned int __stdcall MainThread( void * object ); #else static void * MainThread(void *object); #endif }; /** */ inline bool CThread::Stopped() const { return (iStop==1); } #endif libdc0-0.3.24~svn3121/dclib/core/cxml.cpp0000644000175000017500000003460111237253343016704 0ustar sikonsikon/*************************************************************************** cxml.cpp - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cxml.h" #ifdef HAVE_CONFIG_H #include #endif #include /* for _open() modes */ #ifdef WIN32 #include #endif /* for close, mkstemp is in stdlib.h */ #include // for strlen, which is used instead of creating a temp CString #include #ifdef HAVE_LANGINFO_H #include #endif #include #if LIBXML_VERSION > 20406 #include #endif #include #include #include #include #define XML_FALSE "false" #define XML_TRUE "true" #include "ciconv.h" #include "cfile.h" #include "cbytearray.h" #if LIBXML_VERSION < 20617 #define XML_SAVE_FORMAT 1<<0 #endif #ifdef HAVE_MALLOC_H #include #endif /** */ CXml::CXml() { pDoc = 0; pNode = 0; #if defined(__APPLE__) CString local = "UTF-8"; #elif defined(WIN32) CString local = "WINDOWS-1252"; #elif defined(HAVE_NL_LANGINFO) CString local = nl_langinfo(CODESET); if ( local.IsEmpty() ) { local = "UTF-8"; } #else CString local = getenv("LANG"); int i = local.Find('.'); if ( i == -1 ) { local = "UTF-8"; } else { local = local.Mid(i + 1); } #endif /* * FIXME Bypassing the CIconv objects entirely may be better * since 99% of the time local is UTF-8 ... although * it's an inline function which checks a bool and then returns * the input, which should be just as fast as checking if * the object is null and then not calling anything. */ pToUTF8 = new CIconv( local, "UTF-8" ); pFromUTF8 = new CIconv( "UTF-8", local ); } /** */ CXml::~CXml() { FreeDoc(); delete pToUTF8; delete pFromUTF8; } /** */ void CXml::FreeDoc() { if (pDoc) { xmlFreeDoc(pDoc); pDoc = 0; pNode = 0; #ifdef HAVE_MALLOC_TRIM malloc_trim(0); #endif } } /** */ bool CXml::NewDoc( const char * docnodename ) { FreeDoc(); pDoc = xmlNewDoc((const xmlChar*)"1.0"); if ( pDoc ) { pNode = xmlNewDocNode( pDoc, 0, (const xmlChar*) docnodename, 0 ); if ( pNode ) { pDoc->children = pNode; return true; } else { /* nothing works without pNode */ FreeDoc(); } } return false; } /** */ bool CXml::ParseFile( CString name ) { FreeDoc(); if ( (pDoc = xmlRecoverFile(name.Data())) == 0 ) { return false; } return true; } /** */ bool CXml::ParseMemory( const char * s, int size ) { FreeDoc(); if ( (pDoc = xmlRecoverMemory(s,size)) == 0 ) { return false; } return true; } /** */ bool CXml::ParseFixMemory( CByteArray * ba ) { FreeDoc(); int tried = 0; xmlParserCtxt * cp = NULL; while ( tried < 100 ) { cp = xmlNewParserCtxt(); if ( cp == NULL ) { return false; } pDoc = xmlCtxtReadMemory( cp, (const char*) ba->Data(), ba->Size(), NULL, NULL, 0 ); if ( pDoc == NULL ) { long pos = xmlByteConsumed(cp); if ( (pos < 0) || (pos > ba->Size()) ) { tried = 300; } else if ( pos == ba->Size() ) { pDoc = xmlCtxtReadMemory( cp, (const char*) ba->Data(), ba->Size(), NULL, NULL, XML_PARSE_RECOVER ); tried = 200; } else { ba->Data()[pos] = '_'; ++tried; } } xmlFreeParserCtxt( cp ); if ( pDoc != NULL ) { break; } } return (pDoc != NULL); } /** */ int CXml::SaveConfigXmlViaTemp( CString filename ) { if ( pDoc == 0 ) { return -1; } CString tempname = filename + ".XXXXXX"; #ifdef WIN32 int fd = _open( tempname.Data(), _O_BINARY | _O_WRONLY | _O_CREAT | _O_TRUNC ); #else int fd = mkstemp( tempname.Data() ); #endif if ( fd == -1 ) { perror("CXml::SaveConfigXmlViaTemp: mkstemp"); return -1; } xmlSaveCtxt * savecontext = xmlSaveToFd( fd, "utf-8", XML_SAVE_FORMAT ); if ( savecontext == NULL ) { printf("CXml::SaveConfigXmlViaTemp: xmlSaveToFd failed\n"); return -1; } long ret1 = xmlSaveDoc( savecontext, pDoc ); int ret2 = xmlSaveClose( savecontext ); #ifdef WIN32 if ( _close( fd ) == -1 ) #else if ( close( fd ) == -1 ) #endif { perror("CXml::SaveConfigXmlViaTemp: close"); return -1; } if ( (ret1 != -1) && (ret2 != -1) ) { CFile::UnLink( filename ); if ( CFile::Rename( tempname, filename ) ) { return 1000; } else { /* * This is highly unlikely because being unable to rename a file * implies no write access to the directory, so mkstemp would have failed. */ return -1; } } else { printf("CXml::SaveConfigXmlViaTemp: xmlSaveDoc/xmlSaveClose failed\n"); return -1; } } /** */ CString CXml::Name() { if ( pNode ) { return CString( (const char*) pNode->name ); } else { return CString(); } } /** */ CString CXml::Content() { xmlChar * c; CString s; if ( pNode && ((c = xmlNodeGetContent(pNode)) != 0) ) { s = FromUtf8((char*)c); xmlFree(c); } return s; } /** */ CString CXml::Prop( const CString & prop ) { xmlChar *c; CString s; if ( pNode && ((c = xmlGetProp(pNode,(const xmlChar*)prop.Data())) != 0) ) { s = (char*)c; xmlFree(c); } return s; } /** */ CString CXml::Prop( const char * prop ) { xmlChar *c; CString s; if ( pNode && ((c = xmlGetProp(pNode,(const xmlChar*)prop)) != 0) ) { s = (char*)c; xmlFree(c); } return s; } /** */ bool CXml::GetBoolChild() { if ( Content() == XML_TRUE ) return true; else return false; } /** */ bool CXml::DocFirstChild() { if ( pDoc ) { xmlNode * node = pDoc->children; if ( node ) { pNode = node; return true; } } return false; } /** */ bool CXml::NextNode() { if ( pNode ) { xmlNode * node = pNode->next; if ( node ) { pNode = node; return true; } } return false; } /** */ bool CXml::FirstChild() { if ( pNode ) { xmlNode * node = pNode->children; if ( node ) { pNode = node; return true; } } return false; } /** */ bool CXml::Parent() { if ( pNode ) { xmlNode * node = pNode->parent; if ( node ) { pNode = node; return true; } } return false; } /** */ CString CXml::ToUTF8( const char * s ) { if ( (s == 0) || (s[0] == 0) ) { return CString(); } else { CString r = pToUTF8->encode(s); if ( xmlCheckUTF8( (const unsigned char*) r.Data() ) == false ) { printf("CXml::ToUTF8: iconv returned invalid UTF-8, doing ISO-8859-1 to UTF-8\n"); printf("input='%s' (char *) iconv='%s'\n",s,r.Data()); int inlen = strlen(s); int outlen = inlen * 4; unsigned char * b = (unsigned char*) calloc(1,outlen); if ( b != 0 ) { int res = isolat1ToUTF8( b, &outlen, (unsigned char*)s, &inlen ); if ( res >= 0 ) r = (char*)b; else printf("CXml::ToUTF8 isolat1ToUTF8 fail: '%s'\n",s); free(b); } } return EscapeSpecials(r); } } /** */ CString CXml::FromUtf8( const char * s ) { if ( (s == 0) || (s[0] == 0) ) { return CString(); } else { return UnEscapeSpecials( pFromUTF8->encode(s) ); } } /** */ CString CXml::ToUTF8( const CString & s ) { if ( s.IsEmpty() ) { return CString(); } else { CString r = pToUTF8->encode(s); if ( xmlCheckUTF8( (const unsigned char*) r.Data() ) == false ) { printf("CXml::ToUTF8: iconv returned invalid UTF-8, doing ISO-8859-1 to UTF-8\n"); printf("input='%s' (CString) iconv='%s'\n",s.Data(),r.Data()); int inlen = s.Length(); int outlen = inlen * 4; unsigned char * b = (unsigned char*) calloc(1,outlen); if ( b != 0 ) { int res = isolat1ToUTF8( b, &outlen, (unsigned char*)s.Data(), &inlen ); if ( res >= 0 ) r = (char*)b; else printf("CXml::ToUTF8 isolat1ToUTF8 fail: '%s'\n",s.Data()); free(b); } } return EscapeSpecials(r); } } /** */ CString CXml::FromUtf8( const CString & s ) { if ( s.IsEmpty() ) { return CString(); } else { return UnEscapeSpecials( pFromUTF8->encode(s) ); } } CString CXml::EscapeSpecials( const CString & s ) { int i; CString dst1; if ( s.IsEmpty() ) { return dst1; } // sorry, CString::Replace is too slow /* dst = s.Replace("&","&"); dst = dst.Replace("\'","'"); dst = dst.Replace("\"","""); dst = dst.Replace("<","<"); dst = dst.Replace(">",">"); */ /* 0x00 - 0x08, 0x0B, 0x0C, 0x0E - 0x1F have been declared to * be illegal in XML documents */ for(i=0;i= 0x00)) || (x == 0x0B) || (x <= 0x0C) || ((x <= 0x1F) && (x >= 0x0E)) ) { dst1 += "�"; dst1 += CString::number(x); dst1 += ';'; } else if ( x == '&' ) { dst1 += "&"; } else if ( x == '\'' ) { dst1 += "'"; } else if ( x == '"' ) { dst1 += """; } else if ( x == '<' ) { dst1 += "<"; } else if ( x == '>' ) { dst1 += ">"; } else { dst1 += s.Data()[i]; } } return dst1; } CString CXml::UnEscapeSpecials( const CString & s ) { int i,i1; CString res; CString temp; CString four,six; for(i=0;i"); res = res.Replace("&", "&"); */ return res; } /** */ bool CXml::StartNewChild( const char * name ) { if ( pNode ) { pNode = xmlNewChild( pNode, 0, (const xmlChar*) name, 0 ); return true; } return false; } /** */ bool CXml::NewBoolChild( const char * name, bool b ) { if ( pNode ) { if ( b ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)XML_TRUE ); } else { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)XML_FALSE ); } return true; } return false; } /** */ bool CXml::NewNumericChild( const char * name, const int n ) { if ( pNode ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)CString::number(n).Data() ); return true; } return false; } /** */ bool CXml::NewNumericChild( const char * name, const unsigned int n ) { if ( pNode ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)CString::number(n).Data() ); return true; } return false; } /** */ bool CXml::NewNumericChild( const char * name, const long n ) { if ( pNode ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)CString::number(n).Data() ); return true; } return false; } /** */ bool CXml::NewNumericChild( const char * name, const unsigned long n ) { if ( pNode ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)CString::number(n).Data() ); return true; } return false; } /** */ bool CXml::NewNumericChild( const char * name, const long long n ) { if ( pNode ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)CString::number(n).Data() ); return true; } return false; } /** */ bool CXml::NewNumericChild( const char * name, const ulonglong n ) { if ( pNode ) { xmlNewChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)CString::number(n).Data() ); return true; } return false; } /** */ bool CXml::NewStringChild( const char * name, const CString & s ) { if ( pNode ) { /* xmlNewTextChild actually can do the < to < for us */ xmlNewTextChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)ToUTF8(s).Data() ); return true; } return false; } /** */ bool CXml::NewStringChild( const char * name, const char * s ) { if ( pNode ) { /* xmlNewTextChild actually can do the < to < for us */ xmlNewTextChild( pNode, 0, (const xmlChar*) name, (const xmlChar*)ToUTF8(s).Data() ); return true; } return false; } /** */ bool CXml::NewStringProp( const CString & prop, const CString & value ) { if ( pNode ) { xmlNewProp( pNode, (const xmlChar*)prop.Data(), (const xmlChar*)ToUTF8(value).Data() ); return true; } return false; } /** */ bool CXml::NewStringProp( const char * prop, const char * value ) { if ( pNode ) { xmlNewProp( pNode, (const xmlChar*)prop, (const xmlChar*)ToUTF8(value).Data() ); return true; } return false; } /** */ void CXml::InitParser() { printf("Checking libxml2 version... "); LIBXML_TEST_VERSION; printf("compiled for '%s' using '%s'\n",LIBXML_VERSION_STRING,xmlParserVersion); if ( xmlParserVersion != CString("20510") ) { xmlInitParser(); } } /** */ void CXml::CleanupParser() { #if LIBXML_VERSION > 20510 if ( xmlParserVersion != CString("20510") ) { xmlCleanupParser(); } #endif } /** */ const char * CXml::Libxml2CompiledVersion() { return LIBXML_VERSION_STRING; } /** */ const char * CXml::Libxml2RunningVersion() { return xmlParserVersion; } libdc0-0.3.24~svn3121/dclib/core/cstringlist.h0000644000175000017500000001704011101144617017742 0ustar sikonsikon/*************************************************************************** cstringlist.h - description ------------------- begin : Sat Jun 1 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSTRINGLIST_H #define CSTRINGLIST_H /** *@author Mathias Küster * * Turned into a template class by Edward Sheldrake, * which makes the downloadmanager code a hell of a lot clearer. * * However this class and CList should still be removed entirely and replaced * with more appropriate STL classes (map, set, unordered_map). * * CStringList is a mapping class, not a list of strings. It is implemented * by containing lists per first key character. To handle more characters * of the key, the maxdepth parameter can be used, then it will contain * as many levels of CStringLists as necessary, each level handling * one character. * * CStringList's performance varies depending on how well * the items distribute, there is no real hash function to make * sure the items distribute evenly. * * The remove without deleting the item function never used to work * for CStringLists created with maxdepth > 0, the item was always * deleted. dclib does not require this to work, even if it was fixed. */ #include #include #include template class CStringListObject { public: /** */ CStringListObject() { m_pObject = 0; }; /** */ ~CStringListObject() {}; /** */ CString m_s; /** */ type * m_pObject; }; template class CStringList { public: /** */ CStringList( int maxdepth = 0, int depth = 0 ); /** */ ~CStringList(); /** */ int Add( const CString & s, type * object = 0 ); /** */ int Get( const CString & s, type ** object ); /** */ int Del( const CString & s, bool bdelobj = true ); /** */ int Remove( const CString & s ) { return Del(s,false); }; /** */ void Clear(); /** */ long Count() const; /** */ int Next( type ** object ); /** */ int Next( CString & s, type ** object ); private: /** */ int m_nDepth; /** */ int m_nMaxDepth; /** */ long m_nSize; /** */ long m_nCachePos; /** */ CStringListObject * m_nCacheObj; /** */ CStringList ** m_pStringList; /** */ CList > ** m_pList; }; /** */ template inline long CStringList::Count() const { return m_nSize; } #define HASH_TABLE_SIZE 0x100 #include #include template CStringList::CStringList( int maxdepth, int depth ) { m_nDepth = depth; m_nMaxDepth = maxdepth; m_nSize = 0; m_nCachePos = 0; m_nCacheObj = 0; m_pList = 0; m_pStringList = 0; if ( m_nDepth == m_nMaxDepth ) { m_pList = new CList >*[HASH_TABLE_SIZE]; memset(m_pList, 0, HASH_TABLE_SIZE*sizeof(CList >*)); } else { m_pStringList = new CStringList*[HASH_TABLE_SIZE]; memset(m_pStringList, 0, HASH_TABLE_SIZE*sizeof(CStringList*)); } } template CStringList::~CStringList() { Clear(); if ( m_nDepth == m_nMaxDepth ) delete [] m_pList; else delete [] m_pStringList; } /** */ template int CStringList::Add( const CString & s, type * object ) { int i = s.GetHash(m_nDepth); if ( m_nDepth == m_nMaxDepth ) { CStringListObject * o = new CStringListObject(); o->m_s = s; o->m_pObject = object; if ( m_pList[i] == 0 ) m_pList[i] = new CList >(); m_pList[i]->Add(o); } else { if ( m_pStringList[i] == 0 ) m_pStringList[i] = new CStringList(m_nMaxDepth,m_nDepth+1); m_pStringList[i]->Add(s,object); } m_nSize++; m_nCachePos = 0; m_nCacheObj = 0; return 0; } /** */ template int CStringList::Del( const CString & s, bool bdelobj ) { CStringListObject * o = 0; int i = s.GetHash(m_nDepth); if ( m_nDepth == m_nMaxDepth ) { if ( m_pList[i] == 0 ) return -1; while( (o=m_pList[i]->Next(o)) != 0 ) { if ( s == o->m_s ) break; } if (!o) return -1; m_pList[i]->Remove(o); if ( bdelobj ) delete o->m_pObject; delete o; if (m_pList[i]->Count() == 0 ) { delete m_pList[i]; m_pList[i]=0; } } else { if ( m_pStringList[i] == 0 ) return -1; m_pStringList[i]->Del(s,bdelobj); } m_nSize--; m_nCachePos = 0; m_nCacheObj = 0; return 0; } /** */ template int CStringList::Get( const CString & s, type ** object ) { CStringListObject * o = 0; int i = s.GetHash(m_nDepth); if ( m_nDepth == m_nMaxDepth ) { if ( !m_pList[i] ) return -1; while( (o=m_pList[i]->Next(o)) != 0 ) { if ( s == o->m_s ) break; } if (!o) return -1; *object = o->m_pObject; } else { if ( !m_pStringList[i] ) return -1; return m_pStringList[i]->Get(s,object); } return 0; } /** */ template void CStringList::Clear() { CStringListObject * o = 0; int i; for(i=0;iNext(0)) != 0 ) { delete o->m_pObject; o->m_pObject = 0; m_pList[i]->Del(o); } delete m_pList[i]; } m_pList[i]=0; } else { if(m_pStringList[i]) delete m_pStringList[i]; m_pStringList[i]=0; } } m_nSize = 0; m_nCachePos = 0; m_nCacheObj = 0; } /** */ template int CStringList::Next( type ** object ) { CString s; return Next(s,object); } /** */ template int CStringList::Next( CString & s, type ** object ) { int i; long l; CStringListObject * obj=0; if ( *object == 0 ) { m_nCachePos = 0; m_nCacheObj = 0; } for(i=0,l=0;(i0);i++) { if ( m_nDepth == m_nMaxDepth ) { if(!m_pList[i]) continue; // fix cache after del if ( (*object != 0) && (m_nCacheObj == 0) ) { obj = 0; while ( (obj=m_pList[i]->Next(obj)) != 0 ) { m_nCachePos++; if ( obj->m_pObject == *object ) { m_nCacheObj = obj; break; } } obj = 0; } else if ( (l<=m_nCachePos) && ((l+m_pList[i]->Count())>m_nCachePos) ) { if(l==m_nCachePos) m_nCacheObj=0; obj = m_pList[i]->Next(m_nCacheObj); if ( obj ) s = obj->m_s; else printf("WARNING: CStringList::Next nullpointer !\n"); m_nCachePos++; m_nCacheObj = obj; break; } l+=m_pList[i]->Count(); } else { if(!m_pStringList[i]) continue; if ( (l<=m_nCachePos) && ((l+m_pStringList[i]->Count())>m_nCachePos) ) { if(l==m_nCachePos) *object=0; m_nCachePos++; return m_pStringList[i]->Next(object); } l+=m_pStringList[i]->Count(); } } if ( obj ) *object = obj->m_pObject; else *object = 0; return (obj!=0); } #endif libdc0-0.3.24~svn3121/dclib/core/clisten.cpp0000644000175000017500000000427011074130777017405 0ustar sikonsikon/*************************************************************************** clisten.cpp - description ------------------- begin : Fri Mar 22 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "clisten.h" #include #include #include #ifndef WIN32 #include #endif #include "cmanager.h" /** */ CListen::CListen() { m_pListenCallback = 0; m_pCallback = 0; } /** */ CListen::~CListen() { SetCallBackFunction(0); StopListen(); } /** */ int CListen::StartListen( int port, CString ip, bool manager ) { int err; m_Mutex.Lock(); err = 0; if ( (CManager::Instance() == 0) && (manager) ) { err = -1; } else if ( Listen( port, ip ) != 0 ) { err = -1; } else if ( manager ) { m_pCallback = new CCallback0( this, &CListen::Callback ); CManager::Instance()->Add( m_pCallback ); } m_Mutex.UnLock(); return err; } /** */ void CListen::StopListen() { m_Mutex.Lock(); if ( m_pCallback ) { if ( CManager::Instance() ) CManager::Instance()->Remove( m_pCallback ); delete m_pCallback; m_pCallback = 0; } m_Mutex.UnLock(); Disconnect(); } /** */ int CListen::Callback() { int fd; m_Mutex.Lock(); fd = Accept(); if ( fd != -1 ) { if ( m_pListenCallback != 0 ) { m_pListenCallback->notify(fd); } else { DC_ListenCallBack(fd); } } m_Mutex.UnLock(); return 0; } libdc0-0.3.24~svn3121/dclib/core/ctraffic.h0000644000175000017500000000572611125260136017167 0ustar sikonsikon/*************************************************************************** ctraffic.h - dclib network traffic stats ------------------- begin : Fri Aug 09 2008 copyright : (C) 2001-2003 by Mathias Küster copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CTRAFFIC_H #define CTRAFFIC_H /** * @author Mathias Küster * * Class split out of csocket.h * It's just a counter for network usage. */ #include #include enum eTrafficType { ettRX=0, ettTX, ettDATARX, ettDATATX, ettCONTROLRX, ettCONTROLTX, ettRESET }; class CTraffic { public: /** Constructor - mutex must be locked until finished */ CTraffic() { ResetTraffic(); }; /** Destructor */ ~CTraffic() {}; /** Add bytes to the traffic stat */ void AddTraffic( eTrafficType type, ulonglong n ) { m_Mutex.Lock(); switch ( type ) { case ettRX: m_nRx += n; break; case ettTX: m_nTx += n; break; case ettDATARX: m_nDataRx += n; break; case ettDATATX: m_nDataTx += n; break; case ettCONTROLRX: m_nControlRx += n; break; case ettCONTROLTX: m_nControlTx += n; break; default: break; } m_Mutex.UnLock(); } /** Get bytes for the traffic stat */ ulonglong GetTraffic( eTrafficType type ) { ulonglong n; m_Mutex.Lock(); switch ( type ) { case ettRX: n = m_nRx; break; case ettTX: n = m_nTx; break; case ettDATARX: n = m_nDataRx; break; case ettDATATX: n = m_nDataTx; break; case ettCONTROLRX: n = m_nControlRx; break; case ettCONTROLTX: n = m_nControlTx; break; default: n = 0; break; } m_Mutex.UnLock(); return n; } /** Reset all traffic stats */ void ResetTraffic() { m_Mutex.Lock(); m_nRx = 0; m_nTx = 0; m_nDataRx = 0; m_nDataTx = 0; m_nControlRx = 0; m_nControlTx = 0; m_Mutex.UnLock(); } private: /** */ CMutex m_Mutex; /** */ ulonglong m_nRx; /** */ ulonglong m_nTx; /** */ ulonglong m_nDataRx; /** */ ulonglong m_nDataTx; /** */ ulonglong m_nControlRx; /** */ ulonglong m_nControlTx; }; #endif // CTRAFFIC_H libdc0-0.3.24~svn3121/dclib/core/ciconv.cpp0000644000175000017500000000616211164077503017224 0ustar sikonsikon/*************************************************************************** ciconv.cpp - DCLib C++ iconv wrapper ------------------- begin : Thu Sep 20 2007 copyright : (C) 2007 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "ciconv.h" #ifdef HAVE_CONFIG_H #include #endif #ifndef ICONV_CONST #define ICONV_CONST #endif #include #include #include /** calls iconv_open */ CIconv::CIconv( const CString & from, const CString & to ) { if ( from == to ) { disabled = true; } else { cd = iconv_open( to.Data(), from.Data() ); if ( cd == (iconv_t)(-1) ) { perror( "CIconv iconv_open" ); printf( "CIconv: encoding disabled - iconv_open failed\n" ); disabled = true; } else { disabled = false; } } } /** calls iconv_close */ CIconv::~CIconv() { if ( disabled == false ) { iconv_close( cd ); } } /** calls iconv */ CString CIconv::encode( const char * orig, const size_t origlen ) { if ( orig == 0 || origlen == 0 ) { return CString(); } CString result; size_t retval; size_t inleft = origlen; size_t outleft; if ( inleft < 1024 ) { outleft = inleft * 4; } else { outleft = 4096; } const char * inbuf = orig; // allocate an extra byte to ensure the data is \0 terminated char * outbuf = (char*) calloc( 1, outleft + 1 ); char * outstart = outbuf; while ( inleft > 0 ) { retval = iconv( cd, (ICONV_CONST char **)&inbuf, &inleft, &outbuf, &outleft ); if ( retval == (size_t) -1 ) { // handle invalid multibyte sequence if ( errno == EILSEQ ) { outstart[outbuf - outstart] = '_'; inbuf++; inleft--; outbuf++; outleft--; } else if ( errno == E2BIG ) // not enough room in output buffer for next char { // CString += uses strlen to compute the length // which will be correct since we zero filled the memory // with calloc, so we don't need to compute any sizes here result += outstart; free(outstart); outleft = 4096; outbuf = (char*) calloc( 1, outleft + 1 ); outstart = outbuf; } else { perror("CIconv::encode"); free(outstart); return orig; } } } result += outstart; free(outstart); //printf( "orig=\"%s\" len=%d\nresult=\"%s\" len=%d\n", orig.Data(), orig.Length(), result.Data(), result.Length() ); return result; } libdc0-0.3.24~svn3121/dclib/core/casyncdns.h0000644000175000017500000000460011125260136017361 0ustar sikonsikon/*************************************************************************** casyncdns.h - description ------------------- begin : Mon Jun 10 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CASYNCDNS_H #define CASYNCDNS_H /** *@author Mathias Küster * * This is a thread that is permanently running to do DNS * lookups so that they do not block the other dclib thread (CManager). * * The CNetAddr lookup function is supposed to be re-entrant since it * uses getaddrinfo(), so more than one lookup could be done * simultaneously, but this class does not do that. */ #include #ifndef WIN32 #include #endif #include #include #include #include #include /** */ enum eAsyncDns { eadSUCCESS, eadERROR, eadAGAIN }; class CAsyncDnsEntry { public: /** */ CAsyncDnsEntry() {}; /** */ ~CAsyncDnsEntry() {}; /** */ CString m_sHost; /** */ bool m_bError; /** socket error message */ CString m_sErrMsg; /** query timeout */ time_t m_tTimeout; /** */ struct sockaddr_in m_sin; }; class CAsyncDns : public CSingleton, public CThread { public: /** */ CAsyncDns(); /** */ virtual ~CAsyncDns(); /** */ eAsyncDns GetHostI4( CString stringHost, struct sockaddr_in * sin, CString * errmsg = 0 ); /** */ virtual void Thread(); private: /** */ void UpdateEntry( CString stringHost ); /** */ CStringList * m_pHostCache; /** */ CStringList * m_pHostList; }; #endif libdc0-0.3.24~svn3121/dclib/core/cbase64.h0000644000175000017500000000321011101177575016627 0ustar sikonsikon/*************************************************************************** cbase64.h - description ------------------- begin : Tue Jul 09 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CBASE64_H #define CBASE64_H /** *@author Mathias Küster * * Base64 encoder and decoder. */ #include #include class CByteArray; class CBase64 { public: /** */ static void Encode( CByteArray * dst, CByteArray * src ); /** */ static CString Encode( CString string ); /** */ static unsigned long Decode( CByteArray * dst, CByteArray * src ); /** */ static unsigned long Decode( CByteArray * dst, CString * string ); protected: /** */ CBase64(); /** */ ~CBase64(); private: /** */ static const signed char Index_64[128]; /** */ static const char B64Chars[64]; }; #endif libdc0-0.3.24~svn3121/dclib/core/Makefile.am0000644000175000017500000000223611256231515017266 0ustar sikonsikonnoinst_LTLIBRARIES = libcore.la libcore_la_SOURCES = \ casyncdns.cpp \ cbase32.cpp \ cbase64.cpp \ cbytearray.cpp \ cbz.cpp \ cconnection.cpp \ cdir.cpp \ cfile.cpp \ che3.cpp \ ciconv.cpp \ clisten.cpp \ clogfile.cpp \ cmanager.cpp \ cmutex.cpp \ cnetaddr.cpp \ csocket.cpp \ cssl.cpp \ cstring.cpp \ cthread.cpp \ cxml.cpp \ czlib.cpp \ platform.cpp libcore_la_LDFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(XML_LIBS) $(SSL_LDFLAGS) $(LIBICONV) -rdynamic libcore_la_LIBADD = ../gnulib/libgnulib.la AM_CXXFLAGS = @CXXFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir) $(PACKAGE_FLAGS) $(XML_CFLAGS) $(SSL_CPPFLAGS) if WIN32 libcore_la_LDFLAGS += -lws2_32 -liphlpapi -lcrtdll AM_CPPFLAGS += -DWINVER=0x501 endif WIN32 library_includedir=$(includedir)/dclib-0.3/dclib/core library_include_HEADERS = \ casyncdns.h \ cbase32.h \ cbase64.h \ cbytearray.h \ cbz.h \ ccallback.h \ cconnection.h \ cdir.h \ cfile.h \ che3.h \ ciconv.h \ clisten.h \ clist.h \ clogfile.h \ cmanager.h \ cmutex.h \ cnetaddr.h \ cplugin.h \ csingleton.h \ csocket.h \ cssl.h \ cstring.h \ cstringhash.h \ cstringlist.h \ cthread.h \ ctraffic.h \ cxml.h \ czlib.h \ platform.h \ types.h libdc0-0.3.24~svn3121/dclib/core/che3.h0000644000175000017500000000656411101144617016230 0ustar sikonsikon/*************************************************************************** che3.h - HE3 compression and decompression (for old format filelists) ------------------- begin : ? copyright : (C) 2001 Eric Prevoteau copyright : (C) 2002-2005 Mathias Küster ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef __HE3_H__ #define __HE3_H__ /** * This class compresses and decompresses ".DcLst" old format * filelists, which are based on Huffman encoding. * * The compression is probably worse than zlib, plus it * seems to be orientated on bits rather than bytes making * it horrible to implement. */ #include class CByteArray; class CString; typedef struct hufnode { unsigned long occur; struct hufnode *left,*right; /* son nodes (left and right are both either not null or either null) */ unsigned char val; /* if left&right!=NULL, val is the encoded character, else, it has no usage */ } HUFNODE; typedef struct { unsigned int bits_len; /* number of bits in the bitfield used to encode the value */ unsigned long bits; /* bitfield containing the encoding pattern */ /* a N bits_len pattern is stored inside bits from bit N-1 to bit 0 */ } HUFENCODE; class CHE3 { public: /**************************************************/ /* decompress data compressed using HE3 algorithm */ /**********************************************************/ /* input: a GByteArray containing HE3 compressed data */ /* output: a GString containing uncompressed data or NULL */ /**********************************************************/ CString *decode_he3_data(CByteArray *data); /*****************************************************************************************/ /* compress data compressed using an Huffman algorithm and store it in HE3 usable format */ /*****************************************************************************************/ /* input: a GString containing a string to compress */ /* output: a GByteArray containing compressed data or NULL */ /***********************************************************/ CByteArray *encode_he3_data(const CString *str); private: unsigned long get_bit(unsigned char *data, unsigned long *cur_pos); unsigned long get_bits(unsigned char *data, unsigned long *cur_pos, int nb_bit); static int huf_insert_glist(void * a, void * b); void use_hufnode(HUFENCODE tbl_enc[256], HUFNODE *node,unsigned int bits_len, unsigned long bits); void free_hufnode(HUFNODE *node); CByteArray *add_bit(CByteArray *data, unsigned long *bit_pos, unsigned char bit_value); CByteArray *add_bits(CByteArray *data, unsigned long *bit_pos, unsigned long pattern, unsigned int pattern_length); }; #endif libdc0-0.3.24~svn3121/dclib/core/cplugin.h0000644000175000017500000000341111125260136017034 0ustar sikonsikon/*************************************************************************** cplugin.h - description ------------------- begin : Fri Sep 27 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CPLUGIN_H #define CPLUGIN_H /** *@author Mathias Küster * * The interface for a dclib plugin which is almost completely * unused. */ #include #include enum ePluginType { eptNONE, eptLIB, eptGUI }; class CPlugin { public: /** */ CPlugin() {}; /** */ virtual ~CPlugin() {}; /** init function */ virtual bool Init() = 0; protected: /** It is called by CManager so takes no parameters */ virtual int PluginCallback() { return 0; }; }; typedef struct ePluginStruct { /** */ CPlugin * m_pPlugin; /** */ void (*init) (void); /** */ void (*deinit) (void); /** */ ePluginType m_eType; /** Short description */ CString m_sDesc; /** Version info */ CString m_sVersion; } ePluginStruct; #endif libdc0-0.3.24~svn3121/dclib/core/cnetaddr.h0000644000175000017500000000672511103673767017210 0ustar sikonsikon/*************************************************************************** cnetaddr.h - dclib network address functions ------------------- begin : Sat Aug 30 2008 copyright : (C) 2001-2003 by Mathias Küster copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CNETADDR_H #define CNETADDR_H /** * @author Mathias Küster, Edward Sheldrake. * * IP address functions, mainly the DNS lookup, but also getting the * address from network interfaces and some utility functions. * * Moved out of CSocket and gethostbyname() was replaced with getaddrinfo(). * Mutex not required by getaddrinfo(). * * Most of the names got shortened and end with I4 to indicate they * work with IPv4 addresses, and most functions take an optional CString* * for returning any error message. * * On WIN32 this class won't work until CSocket::SysInit() has initialised * WinSock2, dclibInitDepLibs() handles that and any other libraries. */ #include #include #include class CNetAddr { public: /** * Gets the list of network interfaces on this machine. * If there is some problem and error is not null then * if will be set to the error message. * * Returns the number of interfaces in the list. */ static long GetInterfaceList( CList * interfaceList, CString * error = 0 ); /** * Returns the IPv4 address for the network interface. * If there was some problem an empty string is returned * and if error is not null then it will be set to the error message. */ static CString GetInterfaceI4( CString hwif, CString * error = 0 ); /** * Puts the first IPv4 address for the host into sin.sin_addr and returns true. * If lookup fails returns false and sets error if it is not null. */ static bool GetHostI4( const char * host, struct sockaddr_in * sin, CString * error = 0 ); /** * Returns the first IPv4 address for the host as a CString. * If lookup fails returns an empty string and sets error if it is not null. */ static CString GetHostI4( CString host, CString * error = 0 ); /** * Splits host and port. */ static void ParseHost( CString host, CString & ip, unsigned int & port ); /** * Returns true if the IPv4 address (in dots and numbers format) * is in one of the private address space blocks. */ static bool IsPrivateI4( const char * ip ); /** * Returns true if the ip address (in dots and numbers format) * is a valid IPv4 address. */ static bool IsValidI4( const char * ip ); protected: /** Constructor - not created, all functions static */ CNetAddr() {}; /** Destructor - not destroyed, all functions static */ ~CNetAddr() {}; }; #endif // CNETADDR_H libdc0-0.3.24~svn3121/dclib/core/clogfile.cpp0000644000175000017500000000371411103425621017516 0ustar sikonsikon/*************************************************************************** clogfile.cpp - description ------------------- begin : Sat Dec 14 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "clogfile.h" #include #include #include "cmutex.h" /** */ CMutex CLogFile::m_LogFileMutex = CMutex(); /** */ CLogFile::CLogFile() { } /** */ CLogFile::~CLogFile() { } /** */ bool CLogFile::Write( CString file, eLogType /*type*/, CString message ) { bool res = false; char timestamp[23]; struct tm * t; time_t ti; FILE * logfile; m_LogFileMutex.Lock(); ti = time(0); t = localtime(&ti); strftime(timestamp, sizeof(timestamp), "[%F.%H:%M:%S] ", t); // TODO: fix logfiles and add option to set logpath ... /* if ( CConfig::Instance() ) { file = CConfig:Instance()->GetLogPath() + file; } */ if ( (logfile = fopen(file.Data(),"a")) != 0 ) { if ( fwrite(timestamp,22,1,logfile) == 1 ) { message += "\n"; if ( fwrite(message.Data(),message.Length(),1,logfile) == 1 ) { res = true; } } if ( fclose(logfile) != 0 ) { res = false; } } m_LogFileMutex.UnLock(); return res; } libdc0-0.3.24~svn3121/dclib/core/czlib.cpp0000644000175000017500000001564611074130777017060 0ustar sikonsikon/*************************************************************************** czlib.cpp - description ------------------- begin : Thu Oct 12 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "czlib.h" #include #include #include #include "cbytearray.h" /** */ CZLib::CZLib() { m_bInit = false; m_pZStream = new z_stream_s; } /** */ CZLib::~CZLib() { if ( m_bInit ) { inflateEnd(m_pZStream); } delete m_pZStream; } /** */ int CZLib::InflateZBlock( const char * in, int * inlen, char * out, int * outlen ) { int res = -1; int i; if ( m_bInit == false ) { m_bInit = true; m_pZStream->next_in = 0; m_pZStream->avail_in = 0; m_pZStream->opaque = Z_NULL; m_pZStream->zalloc = Z_NULL; m_pZStream->zfree = Z_NULL; m_pZStream->total_out = 0; inflateInit(m_pZStream); } // only update the zlib state if we have been given some data if ( (in != 0) && (*inlen != 0) ) { m_pZStream->next_in = (Bytef*)in; m_pZStream->avail_in = *inlen; } if ( (out != 0) && (*outlen != 0) ) { m_pZStream->next_out = (Bytef*)out; m_pZStream->avail_out = *outlen; } i = inflate(m_pZStream,Z_SYNC_FLUSH); /* Z_BUF_ERROR is non fatal, and means call the function again with more memory space */ if ( (i == Z_OK) || (i == Z_STREAM_END) || (i == Z_BUF_ERROR) ) { *outlen = *outlen - m_pZStream->avail_out; *inlen = *inlen - m_pZStream->avail_in; res = 1; // more data if ( i == Z_STREAM_END ) { inflateEnd(m_pZStream); m_bInit = false; res = 0; // finished } } else { inflateEnd(m_pZStream); m_bInit = false; *outlen = 0; res = -1; // error } /* printf("INFLATE: %d %d %d %d\n", i, m_pZStream->avail_in, m_pZStream->avail_out, m_pZStream->total_out ); */ return res; } /** */ unsigned long CZLib::GetTotalOut() const { return m_pZStream->total_out; } #define MAX_BUFFER_LEN 536870912 // 512MiB max memory /** */ unsigned long CZLib::OneShotInflate( const char * in, const unsigned long inlen, CByteArray * out ) { int res = 0; unsigned long outlen = inlen; char * buffer = 0; while ( true ) { outlen *= 2; if ( buffer ) { free(buffer); } if ( outlen < MAX_BUFFER_LEN ) { buffer = (char*) malloc(outlen); } if (!buffer) { printf("CZLib::OneShotInflate: malloc failed\n"); outlen = 0; break; } res = uncompress( (Bytef*)buffer, &outlen, (const Bytef*)in, inlen ); if ( res == Z_OK ) { out->Append( (const unsigned char*)buffer, outlen ); break; } else if ( res == Z_DATA_ERROR ) // corrupt source data { //printf("CZLib::OneShotInflate: corrupt data\n"); outlen = 0; break; } else if ( res == Z_MEM_ERROR ) // not enoungh memory { //printf("CZLib::OneShotInflate: zlib out of memory\n"); outlen = 0; break; } else if ( res == Z_BUF_ERROR ) // buffer too small { // nothing, try again } } if ( buffer ) { free(buffer); } return outlen; } /** */ CDeflater::CDeflater() { m_bInit = false; m_pZStream = new z_stream_s; } /** */ CDeflater::~CDeflater() { if ( m_bInit ) { /* happens whenever not finished transfer is diconnected */ /* int ret = deflateEnd(m_pZStream); if ( ret == Z_DATA_ERROR ) { printf("CDeflater::~CDeflater: warning: data discarded!\n"); } */ deflateEnd(m_pZStream); } delete m_pZStream; } /** */ int CDeflater::DeflateBlock( const char * in, int * inlen, char * out, int * outlen, bool more ) { int res = -1; int ret, flush; // if first block if ( m_bInit == false ) { m_bInit = true; m_pZStream->next_in = 0; m_pZStream->avail_in = 0; m_pZStream->next_out = 0; m_pZStream->avail_out = 0; m_pZStream->opaque = Z_NULL; m_pZStream->zalloc = Z_NULL; m_pZStream->zfree = Z_NULL; m_pZStream->total_out = 0; deflateInit( m_pZStream, Z_DEFAULT_COMPRESSION ); } // only update the zlib state if we have been given some data... if ( (in != 0) && (*inlen != 0) ) { m_pZStream->next_in = (Bytef*)in; m_pZStream->avail_in = *inlen; } if ( (out != 0) && (*outlen != 0) ) { m_pZStream->next_out = (Bytef*)out; m_pZStream->avail_out = *outlen; } if ( more ) { flush = Z_NO_FLUSH; } else { flush = Z_FINISH; } ret = deflate( m_pZStream, flush ); if ( more ) { if ( (ret == Z_OK) || (ret == Z_BUF_ERROR) ) { *outlen = *outlen - m_pZStream->avail_out; *inlen = *inlen - m_pZStream->avail_in; res = 1; // more data } else { deflateEnd(m_pZStream); m_bInit = false; *outlen = 0; res = -1; // error } } else { if ( (ret == Z_OK) || (ret == Z_BUF_ERROR) ) { *outlen = *outlen - m_pZStream->avail_out; *inlen = *inlen - m_pZStream->avail_in; res = 1; // more data } else if ( ret == Z_STREAM_END ) { *outlen = *outlen - m_pZStream->avail_out; *inlen = *inlen - m_pZStream->avail_in; res = 0; // finished deflateEnd(m_pZStream); m_bInit = false; } else { *outlen = 0; deflateEnd(m_pZStream); m_bInit = false; res = -1; // error } } //printf( "DEFLATE: %d %d %d %d\n", ret, m_pZStream->avail_in, m_pZStream->avail_out, m_pZStream->total_out ); return res; } /** */ unsigned long CDeflater::GetTotalOut() const { return m_pZStream->total_out; } /** */ unsigned long CDeflater::OneShotDeflate( const char * in, const unsigned long inlen, CByteArray * out ) { int res = 0; unsigned long outlen = inlen; char * buffer = 0; while ( true ) { outlen *= 2; if ( buffer ) { free(buffer); } if ( outlen < MAX_BUFFER_LEN ) { buffer = (char*) malloc(outlen); } if ( !buffer ) { printf("CDeflater::OneShotDeflate: malloc failed\n"); outlen = 0; break; } res = compress( (Bytef*)buffer, &outlen, (const Bytef*)in, inlen ); if ( res == Z_OK ) { out->Append( (const unsigned char*)buffer, outlen ); break; } else if ( res == Z_MEM_ERROR ) // not enoungh memory { printf("CDeflater::OneShotDeflate: zlib out of memory\n"); outlen = 0; break; } else if ( res == Z_BUF_ERROR ) // buffer too small { // nothing, try again } } if ( buffer ) { free(buffer); } return outlen; } libdc0-0.3.24~svn3121/dclib/core/cnetaddr.cpp0000644000175000017500000004410311102274042017511 0ustar sikonsikon/*************************************************************************** cnetaddr.cpp - dclib network address functions ------------------- begin : Sat Aug 30 2008 copyright : (C) 2001-2003 by Mathias Küster copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cnetaddr.h" #ifdef HAVE_CONFIG_H #include #endif /* getaddrinfo() */ #include #ifdef WIN32 /* Requires -D_WIN32_WINNT=0x0501 for mingw because * getaddrinfo needs >= Windows XP */ #include #include #include /* for error buffer */ #include "cbytearray.h" #else /* WIN32 */ #include #include /* if_nameindex() */ #include /* inet_ntoa() */ #include #include /* for getting address from network interface */ #include /* for SIOCGIFADDR on solaris */ #ifdef HAVE_SYS_SOCKIO_H #include #endif #endif /* WIN32 */ /* close() */ #include /* for the error messages */ #include #include /** */ long CNetAddr::GetInterfaceList( CList * interfacelist, CString * errmsg ) { if ( !interfacelist ) { return -1; } #ifdef WIN32 // get the interfaces from win32 LONG Status; ULONG Result; HKEY AdapKey,OneAdapKey; TCHAR AdapName[256]; DWORD dim; UCHAR buffer[256]; CString name,instance; int i; // ip-helper ULONG buf_size; DWORD getiftable_rc; char *buff = NULL; MIB_IFTABLE *ift; DWORD count; MIB_IFROW *ifr; IP_ADAPTER_INFO *ai; // iphelper interface table buf_size = 0; getiftable_rc = GetIfTable((PMIB_IFTABLE) buff, &buf_size, true); if (getiftable_rc == ERROR_INSUFFICIENT_BUFFER) { buff = (char *) malloc(buf_size); memset(buff, 0, buf_size); getiftable_rc = GetIfTable((PMIB_IFTABLE) buff, &buf_size, true); if (getiftable_rc == NO_ERROR) { ift = (MIB_IFTABLE *) buff; count = ift->dwNumEntries; for (i=0;itable) + i; if ( ifr->dwDescrLen > 0 ) { CString * s=0; while( (s=interfacelist->Next(s)) != 0 ) if ( *s == (const char*)ifr->bDescr ) break; if ( !s ) interfacelist->Add( new CString((const char*)ifr->bDescr) ); } } } free(buff); } // iphelper adapter info buf_size = 0; getiftable_rc = GetAdaptersInfo((PIP_ADAPTER_INFO) buff, &buf_size ); if (getiftable_rc == ERROR_BUFFER_OVERFLOW) { buff = (char *) malloc(buf_size); memset(buff, 0, buf_size); getiftable_rc = GetAdaptersInfo((PIP_ADAPTER_INFO) buff, &buf_size ); if (getiftable_rc == ERROR_SUCCESS) { ai = (IP_ADAPTER_INFO *) buff; for (;ai;ai=ai->Next) { CString * s=0; while( (s=interfacelist->Next(s)) != 0 ) if ( *s == (const char*)ai->Description ) break; if ( !s ) interfacelist->Add( new CString((const char*)ai->Description)); } } free(buff); } // win 95/98 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Class\\Net"), 0, KEY_READ, &AdapKey); if ( Status == ERROR_SUCCESS ) { i=0; // Get the size to allocate for the original device names while( (Result=RegEnumKey(AdapKey,i,AdapName,sizeof(AdapName)/2)) == ERROR_SUCCESS ) { Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&OneAdapKey); if ( Status == ERROR_SUCCESS ) { name.Empty(); instance = (char*)AdapName; dim = 256; Status = RegQueryValueEx(OneAdapKey,"DriverDesc",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { name = (char*)buffer; } RegCloseKey(OneAdapKey); if ( (instance.NotEmpty()) && (name.NotEmpty()) ) { // now we check if the interface exist instance = "SYSTEM\\CurrentControlSet\\Services\\Class\\NetTrans\\"+instance; Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(instance.Data()), 0, KEY_READ, &OneAdapKey); if ( Status == ERROR_SUCCESS ) { CString * s=0; while( (s=interfacelist->Next(s)) != 0 ) if ( *s == name ) break; if ( !s ) interfacelist->Add( new CString(name) ); RegCloseKey(OneAdapKey); } } } i++; } RegCloseKey(AdapKey); } // win nt/2k Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"), 0, KEY_READ, &AdapKey); if ( Status == ERROR_SUCCESS ) { i=0; // Get the size to allocate for the original device names while( (Result=RegEnumKey(AdapKey,i,AdapName,sizeof(AdapName)/2)) == ERROR_SUCCESS ) { Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&OneAdapKey); if ( Status == ERROR_SUCCESS ) { name.Empty(); instance.Empty(); dim = 256; Status = RegQueryValueEx(OneAdapKey,"NetCfgInstanceId",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { dim = 256; instance = (char*)buffer; Status = RegQueryValueEx(OneAdapKey,"DriverDesc",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { name = (char*)buffer; } } RegCloseKey(OneAdapKey); if ( (instance.NotEmpty()) && (name.NotEmpty()) ) { // now we check if the interface exist instance = "SYSTEM\\CurrentControlSet\\Services\\"+instance +"\\Parameters\\Tcpip"; Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(instance.Data()), 0, KEY_READ, &OneAdapKey); if ( Status == ERROR_SUCCESS ) { CString * s=0; while( (s=interfacelist->Next(s)) != 0 ) if ( *s == name ) break; if ( !s ) interfacelist->Add( new CString(name) ); RegCloseKey(OneAdapKey); } } } i++; } RegCloseKey(AdapKey); } return interfacelist->Count(); #else // NOT WIN32 #ifdef HAVE_IF_NAMEINDEX struct if_nameindex * nameslist = if_nameindex(); if ( nameslist ) { /* This list is terminated by an entry with NULL if_name */ struct if_nameindex * ptr; for ( ptr = nameslist; ptr && ptr->if_name; ++ptr ) { interfacelist->Add( new CString( ptr->if_name ) ); } if_freenameindex(nameslist); return interfacelist->Count(); } else { if ( errmsg ) { *errmsg = "if_nameindex(): "; *errmsg += strerror(errno); } return -1; } #else /* The old code was a hell of a mess, and I'm assuming everyone has if_nameindex(). */ if ( errmsg ) { *errmsg = "if_nameindex() function not available"; } return -1; #endif // HAVE_IF_NAMEINDEX #endif // WIN32 } /** */ CString CNetAddr::GetInterfaceI4( CString iface, CString * errmsg ) { CString s; #ifdef WIN32 // get the interfaces from win32 LONG Status; ULONG Result; HKEY AdapKey,OneAdapKey; TCHAR AdapName[256]; DWORD dim; DWORD RegType; DWORD DHCPEnabled; UCHAR buffer[256]; CString name,instance; int i; // ip-helper ULONG buf_size; DWORD getiftable_rc; char *buff = NULL; MIB_IFTABLE *ift; DWORD count; DWORD index=0xFFFFFFFF; MIB_IFROW *ifr; IP_ADAPTER_INFO *ai; MIB_IPADDRTABLE *ipt; MIB_IPADDRROW *ipr; // iphelper interface table buf_size = 0; buff = NULL; getiftable_rc = GetIfTable((PMIB_IFTABLE) buff, &buf_size, true); if (getiftable_rc == ERROR_INSUFFICIENT_BUFFER) { buff = (char *) malloc(buf_size); memset(buff, 0, buf_size); getiftable_rc = GetIfTable((PMIB_IFTABLE) buff, &buf_size, true); if (getiftable_rc == NO_ERROR) { ift = (MIB_IFTABLE *) buff; count = ift->dwNumEntries; for (i=0;itable) + i; if ( iface == (const char*)ifr->bDescr ) { index = ifr->dwIndex; break; } } } free(buff); } // get ip from nettable if ( index != 0xFFFFFFFF ) { buf_size = 0; buff = NULL; getiftable_rc = GetIpAddrTable((PMIB_IPADDRTABLE) buff, &buf_size, true ); if (getiftable_rc == ERROR_INSUFFICIENT_BUFFER) { buff = (char *) malloc(buf_size); memset(buff, 0, buf_size); getiftable_rc = GetIpAddrTable((PMIB_IPADDRTABLE) buff, &buf_size, true ); if (getiftable_rc == NO_ERROR) { ipt = (MIB_IPADDRTABLE *) buff; count = ipt->dwNumEntries; for (i=0;itable) + i; if ( ipr->dwIndex == index ) { struct in_addr in; in.s_addr = ipr->dwAddr; s = inet_ntoa(in); break; } } } } free(buff); } if ( s.NotEmpty() ) { return s; } // iphelper adapter info buf_size = 0; buff = NULL; getiftable_rc = GetAdaptersInfo((PIP_ADAPTER_INFO) buff, &buf_size ); if (getiftable_rc == ERROR_BUFFER_OVERFLOW) { buff = (char *) malloc(buf_size); memset(buff, 0, buf_size); getiftable_rc = GetAdaptersInfo((PIP_ADAPTER_INFO) buff, &buf_size ); if (getiftable_rc == ERROR_SUCCESS) { ai = (IP_ADAPTER_INFO *) buff; for (;ai;ai=ai->Next) { if ( iface == ai->Description ) { s = ai->IpAddressList.IpAddress.String; break; } } } free(buff); } if ( s.NotEmpty() ) { return s; } // win 95/98 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Class\\Net"), 0, KEY_READ, &AdapKey); if ( Status == ERROR_SUCCESS ) { i=0; // Get the size to allocate for the original device names while( (Result=RegEnumKey(AdapKey,i,AdapName,sizeof(AdapName)/2)) == ERROR_SUCCESS ) { Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&OneAdapKey); if ( Status == ERROR_SUCCESS ) { name.Empty(); instance = (char*)AdapName; dim = 256; Status = RegQueryValueEx(OneAdapKey,"DriverDesc",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { name = (char*)buffer; if ( name != iface ) { name.Empty(); } } RegCloseKey(OneAdapKey); if ( (instance.NotEmpty()) && (name.NotEmpty()) ) { // now we check if the interface exist instance = "SYSTEM\\CurrentControlSet\\Services\\Class\\NetTrans\\"+instance; Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(instance.Data()), 0, KEY_READ, &OneAdapKey); if ( Status == ERROR_SUCCESS ) { dim = 4; Status = RegQueryValueEx(OneAdapKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&dim); if ( Status != ERROR_SUCCESS ) { DHCPEnabled = 0; } if ( DHCPEnabled == 0 ) { dim = 265; Status=RegQueryValueEx(OneAdapKey,"IPAddress",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { s = (char*)buffer; } } else { dim = 256; Status = RegQueryValueEx(OneAdapKey,"DhcpIPAddress",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { s = (char*)buffer; } } RegCloseKey(OneAdapKey); break; } } } i++; } RegCloseKey(AdapKey); } if ( s.NotEmpty() ) { return s; } // win nt/2k Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"), 0, KEY_READ, &AdapKey); if ( Status == ERROR_SUCCESS ) { i=0; // Get the size to allocate for the original device names while( (Result=RegEnumKey(AdapKey,i,AdapName,sizeof(AdapName)/2)) == ERROR_SUCCESS ) { Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&OneAdapKey); if ( Status == ERROR_SUCCESS ) { name.Empty(); instance.Empty(); dim = 256; Status = RegQueryValueEx(OneAdapKey,"DriverDesc",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { name = (char*)buffer; if ( name == iface ) { // found dim = 256; Status = RegQueryValueEx(OneAdapKey,"NetCfgInstanceId",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { instance = (char*)buffer; } } } RegCloseKey(OneAdapKey); if ( (instance.NotEmpty()) && (name.NotEmpty()) ) { // now we get the ip instance = "SYSTEM\\CurrentControlSet\\Services\\"+instance+"\\Parameters\\Tcpip"; Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(instance.Data()), 0, KEY_READ, &OneAdapKey); if ( Status == ERROR_SUCCESS ) { dim = 4; Status = RegQueryValueEx(OneAdapKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&dim); if ( Status != ERROR_SUCCESS ) { DHCPEnabled = 0; } if ( DHCPEnabled == 0 ) { dim = 265; Status=RegQueryValueEx(OneAdapKey,"IPAddress",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { s = (char*)buffer; } } else { dim = 256; Status = RegQueryValueEx(OneAdapKey,"DhcpIPAddress",NULL,NULL,buffer,&dim); if ( Status == ERROR_SUCCESS ) { s = (char*)buffer; } } RegCloseKey(OneAdapKey); break; } } } i++; } RegCloseKey(AdapKey); } #else /* Apparently there's no higher-level function and we have to use SIOCGIFADDR ioctl */ struct ifreq request; memset( &request, 0, sizeof(struct ifreq) ); if ( (size_t) iface.Length() <= sizeof(request.ifr_name) ) { memcpy( request.ifr_name, iface.Data(), iface.Length() ); int sock = socket( AF_INET, SOCK_STREAM, 0 ); if ( sock != -1 ) { if ( ioctl( sock, SIOCGIFADDR, &request ) >= 0 ) { struct sockaddr * sa = &request.ifr_addr; if ( sa && sa->sa_family == AF_INET ) { s = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr); } else if ( errmsg ) { *errmsg = "No IPv4 address returned"; } } else if ( errmsg ) { *errmsg = "ioctl(): "; *errmsg += strerror(errno); } close(sock); } else if ( errmsg ) { *errmsg = "socket(): "; *errmsg += strerror(errno); } } else if ( errmsg ) { *errmsg = "Interface name too long"; } #endif return s; } /** */ bool CNetAddr::GetHostI4( const char * host, struct sockaddr_in * sin, CString * errmsg ) { if ( host && sin ) { memset( sin, 0, sizeof(struct sockaddr_in) ); struct addrinfo hints; memset( &hints, 0, sizeof(struct addrinfo) ); hints.ai_family = AF_INET; /* IPv4 */ struct addrinfo * results = 0; int res = getaddrinfo( host, NULL, &hints, &results ); if ( res == 0 ) { if ( results ) { bool found = false; for ( struct addrinfo * res = results; res; res = res->ai_next ) { if ( res->ai_family == AF_INET ) { memcpy( sin, res->ai_addr, res->ai_addrlen ); found = true; break; } } freeaddrinfo( results ); if ( found ) { return true; } else { if ( errmsg ) { *errmsg = "No IPv4 address found"; } return false; } } else { if ( errmsg ) { *errmsg = "No results"; } return false; } } else { if ( errmsg ) { #ifdef WIN32 /* * gai_strerror did not work on WIN32, probably because * it isn't thread safe, and the test program for this * does 10 lookups at once. * * Unfortunately Windows FormatMessage error to string * function looks horrible. * * Plus all I got for this was 1815 which is * ERROR_RESOURCE_LANG_NOT_FOUND. */ CByteArray buffer(1024); DWORD len = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, // ignored for above flag res, 0, // system language (LPTSTR) buffer.Data(), (DWORD) buffer.Size(), NULL ); if ( len > 0 ) { errmsg->Set( (const char*)buffer.Data(), len ); } else { *errmsg = "WinSock error "; *errmsg += CString::number( res ); *errmsg += " plus "; *errmsg += CString::number( GetLastError() ); } #else *errmsg = gai_strerror( res ); #endif } return false; } } else { if ( errmsg ) { *errmsg = "Null pointer"; } return false; } } /** */ CString CNetAddr::GetHostI4( CString host, CString * errmsg ) { CString result; if ( host.NotEmpty() ) { struct sockaddr_in sin; if ( GetHostI4( host.Data(), &sin, errmsg ) ) { result = inet_ntoa(sin.sin_addr); } } else { if ( errmsg ) { *errmsg = "Empty host"; } } return result; } /** */ void CNetAddr::ParseHost( CString host, CString & ip, unsigned int & port ) { ip.Empty(); // remove all spaces host = host.Replace(" ",""); int i = host.Find(':'); if ( i >= 0 ) { ip = host.Mid(i+1,host.Length()-i-1); } port = 0; if ( (i < 0) || (ip.IsEmpty()) ) { ip = host; } else { if ( ip.asINT() < 0 ) port += 65536; port += ip.asINT(); ip = host.Mid(0,i); } } /** */ bool CNetAddr::IsPrivateI4( const char * cp ) { struct in_addr in; // sanity check if ( !cp ) return false; #ifdef WIN32 /* InetNtop / InetPton need >= Vista ! */ in.s_addr = inet_addr( cp ); if ( in.s_addr == INADDR_NONE ) { return false; } #else if ( inet_aton( cp, &in ) == 0 ) return false; #endif // see Util.cpp isPrivateIp in the DC++ source unsigned long int h = ntohl(in.s_addr); if ( ((h & 0xff000000) == 0x0a000000) || // 10.0.0.0/8 ((h & 0xff000000) == 0x7f000000) || // 127.0.0.0/8 i.e. 127.0.0.1 ((h & 0xfff00000) == 0xac100000) || // 172.16.0.0/12 ((h & 0xffff0000) == 0xc0a80000) // 192.168.0.0/16 ) { return true; } return false; } /** */ bool CNetAddr::IsValidI4( const char * addr ) { if ( addr ) { struct in_addr in; #ifdef WIN32 in.s_addr = inet_addr( addr ); return in.s_addr != INADDR_NONE; #else return ( inet_aton( addr, &in ) != 0 ); #endif } else { return false; } } libdc0-0.3.24~svn3121/dclib/core/cbytearray.cpp0000644000175000017500000000772411121012323020073 0ustar sikonsikon/*************************************************************************** cbytearray.cpp - description ------------------- begin : Fri Mar 22 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cbytearray.h" #include #include #include #include "cfile.h" #include "cdir.h" /** */ CByteArray::CByteArray( unsigned long nSize ) { m_pchBuffer = NULL; // clear allready called by SetSize SetSize(nSize); } /** */ CByteArray::~CByteArray() { Clear(); } /** */ void CByteArray::Clear() { if (m_pchBuffer) { free(m_pchBuffer); m_pchBuffer = NULL; } m_nSize = 0; m_nBufferSize = 0; } /** */ void CByteArray::SetSize( unsigned long nNewSize ) { Clear(); // sanity check if( nNewSize > 0 ) { m_pchBuffer = (unsigned char*)malloc(nNewSize); if ( m_pchBuffer == NULL ) { perror("CByteArray::SetSize"); } else { m_nSize = m_nBufferSize = nNewSize; } } } /** */ bool CByteArray::Realloc( unsigned long newsize ) { /* * realloc() can be called with a NULL pointer or with size 0 * But with size 0 you cannot tell if it succeeded or not. */ if ( newsize == 0 ) { Clear(); return true; } else { void * p = realloc( m_pchBuffer, newsize ); if ( p == NULL ) { perror("CByteArray::Realloc"); return false; } else { m_pchBuffer = (unsigned char*) p; m_nSize = newsize; m_nBufferSize = newsize; return true; } } } /** */ void CByteArray::Append( const unsigned char * pchSrc, unsigned long nSize ) { unsigned char *p; unsigned char * temp; // sanity check if ( (nSize == 0) || (pchSrc == NULL) ) { return; } // check for overlapping memory areas if ( (pchSrc >= m_pchBuffer) && (pchSrc <= m_pchBuffer+m_nBufferSize) ) { temp = (unsigned char*) malloc( nSize ); if ( temp == NULL ) { perror("CByteArray::Append malloc"); return; } memcpy(temp,pchSrc,nSize); } else { temp = (unsigned char*) pchSrc; } if ( (m_nSize+nSize) > m_nBufferSize ) { // resize buffer m_nBufferSize += nSize + 10000; p = (unsigned char*) realloc(m_pchBuffer,m_nBufferSize); if ( p == NULL ) { m_nBufferSize -= (nSize + 10000); perror("CByteArray::Append realloc"); if ( temp != pchSrc ) { free(temp); } return; } m_pchBuffer = p; } // copy mem memcpy( m_pchBuffer+m_nSize, temp, nSize ); // update array size m_nSize += nSize; if ( temp != pchSrc ) { free(temp); } } /** */ bool CByteArray::LoadFromFile( CString file ) { CFile f; CDir d; ulonglong filesize; bool res = false; filesize = d.getFileSize(file,false); if ( f.Open( file, IO_RAW | IO_READONLY ) ) { SetSize(filesize); if ( f.Read( (char*)Data(), Size() ) == filesize ) { res = true; } f.Close(); } return res; } /** */ bool CByteArray::SaveToFile( CString file ) { CFile f; bool res = false; CString tempname = file; if ( f.OpenTemp( tempname ) ) { if ( (Size() == 0) || (f.Write( (const char*)Data(), Size() ) == Size()) ) { if ( f.Close() ) { /* ignore unlink error, may not already exist */ CFile::UnLink( file ); res = CFile::Rename( tempname, file ); } } } return res; } libdc0-0.3.24~svn3121/dclib/core/czlib.h0000644000175000017500000000436311101144617016504 0ustar sikonsikon/*************************************************************************** czlib.h - description ------------------- begin : Thu Oct 12 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CZLIB_H #define CZLIB_H /** *@author Mathias Küster * * This is a wrapper for zlib. */ #include class CByteArray; struct z_stream_s; class CZLib { public: /** */ CZLib(); /** */ ~CZLib(); /** * inflate block * -1 error * 0 finished (stream end) * 1 more data to process */ int InflateZBlock( const char * in, int * inlen, char * out, int * outlen ); /** */ unsigned long GetTotalOut() const; /** Returns size of decompressed output , or zero on error */ static unsigned long OneShotInflate( const char * in, const unsigned long inlen, CByteArray * out ); private: /** */ bool m_bInit; /** */ struct z_stream_s * m_pZStream; }; class CDeflater { public: /** Constructor */ CDeflater(); /** Destructor */ ~CDeflater(); /** * deflate block * -1 error * 0 finished (stream end) * 1 more data to process */ int DeflateBlock( const char * in, int * inlen, char * out, int * outlen, bool more ); /** */ unsigned long GetTotalOut() const; /** Returns size of compressed output, or zero on error */ static unsigned long OneShotDeflate( const char * in, const unsigned long inlen, CByteArray * out ); private: /** */ bool m_bInit; /** */ struct z_stream_s * m_pZStream; }; #endif libdc0-0.3.24~svn3121/dclib/core/platform.h0000644000175000017500000000316611104361305017223 0ustar sikonsikon/*************************************************************************** platform.h - description ------------------- begin : Thu Jun 5 2003 copyright : (C) 2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef _PLATFORM_H_ #define _PLATFORM_H_ /** *@author Mathias Küster * * Just gettimeofday() and lrint() remain after WIN32 * directory reading, using the MS C runtime library, added to CDir. * Both are also provided by mingw. */ #ifdef HAVE_CONFIG_H #include #endif /* * WIN32 */ #ifdef WIN32 #include #include #include #include #include #include extern "C" { int gettimeofday(struct timeval *tp, void * ); } #endif /* * lrint stuff */ #ifndef HAVE_LRINT #include #define lrint(flt) ((int) (flt)) #endif #endif libdc0-0.3.24~svn3121/dclib/core/cconnection.cpp0000644000175000017500000002472711106403602020241 0ustar sikonsikon/*************************************************************************** cconnection.cpp - description ------------------- begin : Sat Oct 6 2001 copyright : (C) 2001-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cconnection.h" #include #include #ifndef WIN32 #include #include #else #include #include #include #endif /* strangely missing... */ #include #include "cbytearray.h" #include "cmutex.h" #include "cnetaddr.h" #define BUFFER_SIZE 1024*50 #define DEFAULT_DC_PORT 411 #define CONNECTION_TIMEOUT 60 #define DATA_TIMEOUT 60 #define NOTIFY_TIMEOUT 1 CConnection::CConnection() { m_nPort = DEFAULT_DC_PORT; m_bForceDisconnect = false; // set connection timeout m_nConnectTimeout = CONNECTION_TIMEOUT; m_timeNotify = 0; m_timeConnection = 0; m_eState = estNONE; m_pBuffer = new CByteArray(BUFFER_SIZE); m_pSendListMutex = new CMutex(); m_pSendList = new CList(); m_pConnMutex = new CMutex(); } CConnection::~CConnection() { CSocket::Disconnect(); delete m_pBuffer; m_pBuffer = 0; delete m_pSendList; m_pSendList = 0; delete m_pSendListMutex; m_pSendListMutex = 0; delete m_pConnMutex; m_pConnMutex = 0; } /** */ int CConnection::Connect() { m_pConnMutex->Lock(); int err = -1; if ( m_eState != estNONE ) { StateDisconnect(); } m_eState = estCONNECT; m_bForceDisconnect = false; err = 0; m_pConnMutex->UnLock(); return err; } /** */ int CConnection::Connect( CString ip, eSocketType sockettype ) { unsigned int port; CString s; CNetAddr::ParseHost( ip, s, port ); if ( port == 0 ) { port = DEFAULT_DC_PORT; } return Connect( s, port, sockettype ); } /** */ int CConnection::Connect( CString ip, int port, eSocketType sockettype ) { m_pConnMutex->Lock(); m_sIP = ip; m_nPort = port; SocketType = sockettype; m_pConnMutex->UnLock(); return Connect(); } /** */ int CConnection::Disconnect( bool force ) { int err = -1; if ( force ) { err = 0; m_bForceDisconnect = true; } else { m_pConnMutex->Lock(); if ( m_eState != estNONE ) { m_eState = estDISCONNECTING; err = 0; } m_pConnMutex->UnLock(); } return err; } /** */ int CConnection::SetSocket( int handle, eSocketType sockettype ) { CString ip; int port; if ( m_eState != estNONE ) { return -1; } m_pConnMutex->Lock(); m_sIP.Empty(); m_nPort = 0; if ( CSocket::SetSocket(handle,sockettype) == -1 ) { m_pConnMutex->UnLock(); return -1; } // get remote host & port if ( GetPeerName( &ip, &port ) == false ) { m_pConnMutex->UnLock(); return -1; } // set remote host & port SetHost( ip, port ); m_bForceDisconnect = false; // init data timeout m_timeConnection = time(0); // init notify timer m_timeNotify = time(0); m_eState = estCONNECTED; if ( m_eSocketMode == esmSOCKET ) { connectionState(estCONNECTED); } else { connectionState(estSSLCONNECTED); } m_pConnMutex->UnLock(); return 0; } /** */ CString CConnection::GetHost( bool peername ) { CString s,host; int port; if ( peername ) { if ( !GetPeerName(&host,&port) ) { return s; } } else { port = GetPort(); host = GetIP(); } s = host + ':' + CString::number(port); return s; } /** */ bool CConnection::ChangeSocketMode( eSocketMode mode, CString cert, CString key ) { bool res = false; m_pConnMutex->Lock(); if ( m_eState == estCONNECTED ) { // flush all data StateSend(); if ( m_eState == estCONNECTED ) { res = CSocket::ChangeSocketMode(mode, cert, key ); if ( res && (mode != esmSOCKET) ) { m_eState = estCONNECTING; } } } else { res = CSocket::ChangeSocketMode(mode, cert, key ); } m_pConnMutex->UnLock(); return res; } /** */ bool CConnection::IsSendQueueEmpty() { bool res = true; if ( m_pSendList != 0 ) { m_pSendListMutex->Lock(); res = (m_pSendList->Count() == 0); m_pSendListMutex->UnLock(); } return res; } /** */ void CConnection::Thread() { int wait = 4; m_pConnMutex->Lock(); if (m_bForceDisconnect) { // first we flush all messages if ( m_eState == estCONNECTED ) StateSend(); // set disconnect state if ( m_eState != estNONE ) m_eState = estDISCONNECTING; m_bForceDisconnect = false; } switch(m_eState) { case estNONE: break; case estCONNECT: StateConnect(); if ( m_eState == estCONNECT ) wait = 100; break; case estCONNECTING: StateConnecting(); break; case estCONNECTED: // read data StateRead(); // send data if ( m_eState == estCONNECTED ) StateSend(); // send data from higher level if ( m_eState == estCONNECTED ) DataSend(); // check data timeout if ( m_eState == estCONNECTED ) { if ( (time(0)-m_timeConnection) >= DATA_TIMEOUT ) { DataTimeout(); m_timeConnection = time(0); } } break; case estDISCONNECTING: StateDisconnect(); break; case estDISCONNECTED: break; default: break; } if ( (time(0)-m_timeNotify) >= NOTIFY_TIMEOUT ) { m_pConnMutex->UnLock(); Notify(); m_pConnMutex->Lock(); m_timeNotify = time(0); } m_pConnMutex->UnLock(); if ( iRun == 1 ) { NanoSleep(wait); } } /** */ void CConnection::connectionState( eConnectionState e ) { m_pConnMutex->UnLock(); ConnectionState(e); m_pConnMutex->Lock(); } /** */ void CConnection::StateConnect() { eConnectState ecs; m_timeConnection = time(0); ecs = CSocket::Connect( m_sIP, m_nPort, true ); if ( ecs == ecsERROR ) { m_eState = estDISCONNECTING; connectionState(estSOCKETERROR); } else if ( ecs == ecsSUCCESS ) { m_eState = estCONNECTING; } } /** */ void CConnection::StateConnecting() { int err = CSocket::IsConnect(); if ( err < 0 ) { m_eState = estDISCONNECTING; connectionState(estSOCKETERROR); } else if ( err == 1 ) { // init data timeout m_timeConnection = time(0); // init notify timer m_timeNotify = time(0); m_eState = estCONNECTED; if ( m_eSocketMode == esmSOCKET ) connectionState(estCONNECTED); else connectionState(estSSLCONNECTED); } // check connection timeout else if ( (time(0) - m_timeConnection) >= m_nConnectTimeout ) { m_eState = estDISCONNECTING; connectionState(estCONNECTIONTIMEOUT); } } /** */ void CConnection::StateRead() { int len=1; int i; if ( m_pBuffer == 0 ) { return; } for (i=0;(i<25)&&(m_eState==estCONNECTED)&&(m_bForceDisconnect==false)&&(len>0);i++) { #if 0 /* this may also be useful for testing data buffering/read issues */ printf("CConnection::StateRead: debug mode memset\n"); memset( m_pBuffer->Data(), '~', BUFFER_SIZE ); #endif len = CSocket::Read((char*)m_pBuffer->Data(),BUFFER_SIZE-1,0,1); if ( len < 0 ) { m_eState = estDISCONNECTING; connectionState(estSOCKETERROR); break; } else if ( len > 0 ) { // update timeout m_timeConnection = time(0); /* this should be completely unnecessary however it is also not wrong */ // fix end m_pBuffer->Data()[len] = 0; // hack m_pConnMutex->UnLock(); #if 0 /* test data buffering by enabling this codepath */ printf("CConnection::StateRead: debug mode DataAvailable len=1 always\n"); for ( int bufpos = 0; bufpos < len; ++bufpos ) { DataAvailable( (char*)m_pBuffer->Data()+bufpos, 1 ); } #else DataAvailable((char*)m_pBuffer->Data(),len); #endif m_pConnMutex->Lock(); } else { break; } } } /** */ void CConnection::StateSend() { int err = 0; CByteArray * ba = 0; if ( m_pSendList != 0 ) { m_pSendListMutex->Lock(); // building one big package in now done in CConnection::Write ba = m_pSendList->Next(0); if ( ba ) { if ( ba->Size() > 0 ) { err = CSocket::Write( ba->Data(), ba->Size(), 0, 1 ); if ( (err > 0) && (err != ba->Size()) ) { // TODO: make this better ;-) CByteArray b; printf("CConnection: warning send %d %ld\n",err,ba->Size()); b.Append(ba->Data()+err,ba->Size()-err); ba->SetSize(0); ba->Append(b.Data(),b.Size()); // add traffic control CSocket::m_Traffic.AddTraffic(ettCONTROLTX,err); // update timeout m_timeConnection = time(0); } else if ( err == ba->Size() ) { // remove object from the list m_pSendList->Del(ba); // add traffic control CSocket::m_Traffic.AddTraffic(ettCONTROLTX,err); // update timeout m_timeConnection = time(0); } } else { printf("CConnection::StateSend: removed empty CByteArray from send list\n"); m_pSendList->Del(ba); } } m_pSendListMutex->UnLock(); } if ( err == -1 ) { m_eState = estDISCONNECTING; connectionState(estSOCKETERROR); } } /** */ void CConnection::StateDisconnect() { CSocket::Disconnect(); if (m_pSendList!=0) { m_pSendListMutex->Lock(); m_pSendList->Clear(); m_pSendListMutex->UnLock(); } m_eState = estNONE; connectionState(estDISCONNECTED); } /** */ int CConnection::Write( const unsigned char * buffer, int len, bool direct ) { int err = 0; if ( !direct ) { if ( (m_pSendList != 0) && ((m_eState == estCONNECTED) || (m_eState == estCONNECTING)) ) { if ( len > 0 ) { m_pSendListMutex->Lock(); /* * Warning: CList::Prev() (previously called Forw()) * is not used anywhere else in dclib or valknut. * Prev(0) gets the last item in the list. */ CByteArray * ba = m_pSendList->Prev(0); if ( ba && (ba->Size() < 1024) ) { ba->Append(buffer,len); } else { ba = new CByteArray(); ba->Append(buffer,len); m_pSendList->Add(ba); } m_pSendListMutex->UnLock(); } } } else { err = CSocket::Write( buffer, len, 0, 1 ); } if ( err == -1 ) { m_eState = estDISCONNECTING; ConnectionState(estSOCKETERROR); } return err; } libdc0-0.3.24~svn3121/dclib/core/ciconv.h0000644000175000017500000000475411101144617016666 0ustar sikonsikon/*************************************************************************** ciconv.h - DCLib C++ iconv wrapper ------------------- begin : Thu Sep 20 2007 copyright : (C) 2007 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CICONV_H #define CICONV_H /** * @author Edward Sheldrake * * It converts between encodings. * * The input is a CString and the output is another CString, really * it would have been better for a CString to be in some defined * encoding. */ #include #include #include #include class CIconv { public: /** * Constructor using specified encodings. * Note that from and to are the other way around * compared to the iconv_open. */ CIconv( const CString & from, const CString & to ); /** Destructor */ ~CIconv(); /** Encode text between the encodings. */ CString encode( const CString & text ); /** * Encode text between the encodings. * This one is slower than the first, since it needs to call strlen, * but faster than creating a CString since there's no copying of the input. */ CString encode( const char * data ); private: /** iconv structure used for encoding */ iconv_t cd; /** facility to disable encoding */ bool disabled; /** * Does the actual encoding. */ CString encode( const char * data, const size_t len ); }; /** inline functions */ /** */ inline CString CIconv::encode( const CString & text ) { if ( disabled ) { return text; } else { return encode( text.Data(), text.Length() ); } } /** */ inline CString CIconv::encode( const char * data ) { if ( disabled ) { return CString(data); } else { return encode( data, strlen(data) ); } } #endif // CICONV_H libdc0-0.3.24~svn3121/dclib/core/cbase32.h0000644000175000017500000000275611102612370016624 0ustar sikonsikon/*************************************************************************** cbase32.h - description ------------------- begin : Sat Apr 24 2004 copyright : (C) 2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CBASE32_H #define CBASE32_H /** *@author Mathias Küster * * Base32 encoder and decoder. */ #include class CByteArray; class CString; class CBase32 { public: /** */ static void Encode( CString * dst, CByteArray * src ); /** */ static unsigned long Decode( CByteArray * dst, CString * src ); protected: /** */ CBase32(); /** */ ~CBase32(); private: /** */ static const signed char Index_32[256]; /** */ static const char B32Chars[33]; }; #endif libdc0-0.3.24~svn3121/dclib/core/cbz.h0000644000175000017500000000364011102566022016153 0ustar sikonsikon/*************************************************************************** cbz.h - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CBZ_H #define CBZ_H /** *@author Mathias Küster * * Does bzip2 compression or decompression for a buffer. That is * all that is required for dclib, some stream functions are not * needed. */ #include class CByteArray; class CString; class CBZ { public: /** * If it fails, dst will be empty unless src is null or empty, * then dst is unchanged. */ static bool Decompress( CByteArray * src, CByteArray * dst ); /** * If it fails, dst will be empty unless src is null or empty, * then dst is unchanged. */ static bool Compress( CByteArray * src, CByteArray * dst ); /** * If it fails, dst will be empty unless src is null or empty, * then dst is unchanged. */ static bool Compress( const CString * src, CByteArray * dst ); protected: /** */ CBZ(); /** */ ~CBZ(); /** */ static bool Compress( char * src, unsigned int srclen, CByteArray * dst ); }; #endif libdc0-0.3.24~svn3121/dclib/core/ccallback.h0000644000175000017500000000763011101144617017300 0ustar sikonsikon/*************************************************************************** ccallback.h - description ------------------- begin : Thu Aug 1 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CCALLBACK_H #define CCALLBACK_H /** *@author Mathias Küster * * CObject replaced with templates by Edward Sheldrake. * * It's a callback, used when one class needs to * communicate with another class, without knowing what the other * class is. Virtual functions are also used for this, e.g. some * valknut classes inherit a dclib class and implement DC_Callback() * or similar. */ #include /** * _CCallback0 / CCallback0 now takes no parameters. * Mainly used for CThread and CManager. */ class _CCallback0 { public: /** */ _CCallback0() {}; /** */ virtual ~_CCallback0() {}; /** */ virtual int notify() = 0; }; template class CCallback0 : public _CCallback0 { public: /** */ CCallback0(Receiver* object, int (Receiver::*method)()) : myObject(object), myMethod(method) {} /** */ virtual ~CCallback0() {}; /** */ virtual int notify() { return (myObject->*myMethod)(); } private: /** */ Receiver* myObject; /** */ int (Receiver::*myMethod)(); }; /** * _CCallback1 / CCallback1 takes one argument usually CDCMessage* * but some are used to pass an int (a socket) around. */ template class _CCallback1 { public: /** Constructor - not created, CCallback is created */ _CCallback1() {}; /** Destructor */ virtual ~_CCallback1() {}; /** */ virtual int notify( Parameter ) = 0; }; template class CCallback1 : public _CCallback1 { public: /** Constructor */ CCallback1( Receiver * recv, int (Receiver::*method)(Parameter) ) : m_pRecv( recv ), m_pMethod( method ) {}; /** */ virtual ~CCallback1() {}; /** */ virtual int notify( Parameter p ) { return (m_pRecv->*m_pMethod)( p ); } private: /** Object whose method gets called */ Receiver * m_pRecv; /** The method that gets called */ int (Receiver::*m_pMethod)( Parameter ); }; /** * _CCallback2 / CCallback2 notify * takes two arguments - a pointer to the sender and the parameter. */ template class _CCallback2 { public: /** Constructor - not created, CCallback is created */ _CCallback2() {}; /** Destructor */ virtual ~_CCallback2() {}; /** */ virtual int notify( Sender*, Parameter ) = 0; }; template class CCallback2: public _CCallback2 { public: /** Constructor */ CCallback2( Receiver * recv, int (Receiver::*method)( Sender*, Parameter ) ) : m_pRecv( recv ), m_pMethod( method ) {}; /** Destructor */ virtual ~CCallback2() {}; /** */ virtual int notify( Sender* sender, Parameter p ) { return (m_pRecv->*m_pMethod)( sender, p ); } private: /** Object whose method gets called */ Receiver * m_pRecv; /** The method that gets called */ int (Receiver::*m_pMethod)( Sender*, Parameter ); }; #endif libdc0-0.3.24~svn3121/dclib/core/types.h0000644000175000017500000001003611125260136016540 0ustar sikonsikon/*************************************************************************** types.h - description ------------------- begin : Thu May 08 2003 copyright : (C) 2003-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef _TYPES_H #define _TYPES_H /** */ enum eUnit { euAUTO=0, euBYTE, euKBYTE, euMBYTE, euGBYTE }; /** transfer medium */ enum eltMedium { eltNONE=0, eltBUFFER, eltTTHL, eltFILE, eltLIST, eltCLIENTVERSION }; /** direction */ enum eDirection { edNONE=0, edUPLOAD, edDOWNLOAD }; /** chunk state */ enum eChunkState { ecsFREE=0, ecsFINISHED, ecsLOCKED }; /** crypt state */ enum eSecureState { esecsNONE=0, esecsHANDSHAKE, esecsENCRYPTED }; /** socket state */ enum eConnectionState { estNONE=0, estCONNECT, estCONNECTING, estCONNECTED, estSSLCONNECTED, estDISCONNECTING, estDISCONNECTED, estSOCKETERROR, estCONNECTIONTIMEOUT, estTRANSFERHANDSHAKE, estTRANSFERDOWNLOAD, estTRANSFERUPLOAD }; enum eTransferFileState { etfsNONE=0, etfsTRANSFER, etfsERROR, etfsPAUSE }; enum eTransferWaitState { etwsWAIT=0, etwsIDLE, etwsRUN, etwsHUBOFFLINE, etwsUSEROFFLINE, etwsUSERBUSY, etwsSENDERROR }; enum eClientMode { ecmNONE=0, ecmACTIVE, ecmPASSIVE }; enum eUserAwayMode { euamNONE=0, euamNORMAL, euamAWAY, euamONLINE, euamOFFLINE }; enum eFileTypes { eftUNKNOWN=0, eftALL, eftMP3, eftARCHIVE, eftDOCUMENT, eftAPPLICATION, eftPICTURE, eftVIDEO, eftFOLDER, eftHASH }; /* * There is no exact size search type in the NMDC protocol according to DC++ * which explains why auto search by exact size didn't work properly. * * Although valknut used to have an exact size option, the protocol did * not, a search with no size restriction was done, but only results * which by very unlikely chance had the right size would be shown. */ enum eSearchSizeType { esstATLEAST=0, esstATMOST }; enum eUserSpeed { eusUNKNOWN=0, eus288KBPS, eus336KBPS, eus56KBPS, eusMODEM, eusISDN, eusDSL, eusSATELLITE, eusCABLE, eusLANT1, eusLANT3, eusWIRELESS, eusMICROWAVE, eus0005, eus001, eus002, eus005, eus01, eus02, eus05, eus1, eus2, eus5, eus10, eus20, eus50, eus100, eus1000 }; enum eUserClientVersion { eucvNONE=0, eucvDCPP, eucvDCHPP, eucvPTOKAX, eucvDCGUI, eucvZPOC, eucvOPENDCD, eucvDCTC, eucvNMDC, eucvQUICKDC, eucvOPERADC, eucvSDDC, /* */ eucvSTRGDCPP, /* */ eucvRMDC, /* */ eucvDCPRO, /* */ eucvIDC, /* */ eucvPERLDC, /* Leaf's are the best! */ eucvMICRODC, eucvSHAKESPEER, eucvUNKNOWN }; enum eUserCommandType { euctSeparator, euctRaw, euctRawOnce, euctRemove, euctClear = 255 }; enum eUserCommandContext { euccHub = 0x01, euccChat = 0x02, euccSearch = 0x04, euccFilelist = 0x08, euccMask = euccHub | euccChat | euccSearch | euccFilelist }; enum eCloseType { ectNONE=0, ectBOTH, ectDLD, ectUPLD }; enum eShareBufferType { esbtNONE=0, esbtHE3, esbtBZ, esbtXMLBZ, esbtXML }; enum eMyInfoStatusFlags { emsfNormal = 0x01, emsfAway = 0x02, emsfServer = 0x04, emsfFireball = 0x08, emsfTLS = 0x10 }; enum eADCType { eAdcFile=0, eAdcTTHL, eAdcList }; #endif libdc0-0.3.24~svn3121/dclib/core/csingleton.h0000644000175000017500000000333511101144617017544 0ustar sikonsikon/*************************************************************************** csingleton.h - description ------------------- begin : Sun Jul 07 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSINGLETON_H #define CSINGLETON_H /** *@author Mathias Küster * * A class for having only one instance of a class, * except this does not handle the creation of the class to * ensure there's only one, so exactly what it does provide * is not clear. */ #include template class CSingleton { public: /** */ CSingleton() { }; /** */ virtual ~CSingleton() { type::_instance_ptr = 0; }; /** */ static type * Instance() { return type::_instance_ptr; }; /** */ static void SetInstance( type * t ) { type::_instance_ptr = t; }; protected: /** */ static type * _instance_ptr; }; template type* CSingleton ::_instance_ptr = 0; #endif libdc0-0.3.24~svn3121/dclib/core/cdir.h0000644000175000017500000000723311125260136016322 0ustar sikonsikon/*************************************************************************** cdir.h - description ------------------- begin : Tue May 14 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CDIR_H #define CDIR_H /** *@author Mathias Küster * * Mainly for reading directories, it also provides * SimplePath() which just removes "." ".." and multiple * directory separators from a path. */ #include #include #include #include class CFileInfo { public: /** */ CFileInfo() {}; /** */ ~CFileInfo() {}; /** */ CString name; /** */ ulonglong size; /** */ bool m_bSymlink; /** */ time_t st_a_time; /** */ time_t st_m_time; /** */ time_t st_c_time; }; class CDir { public: /** */ CDir(); /** */ CDir( CString path ); /** */ ~CDir(); /** * Using Dirs|Files is NOT supported, you would get nothing. * You would not be able to distinguish between files and * directories in the output anyway. */ enum FilterSpec { Dirs = 0x0001, Files = 0x0002 }; /** */ static CString HomeDirPath(); /** */ bool cd( CString path ); /** */ static CString Extension( CString file ); /** */ CString Path(); /** */ CString DirName(); /** */ static CString ConvertSeparators( CString path ); /** */ static CString SimplePath( CString path ); /** */ ulonglong getFileSize( CString filename, bool rel = true ); /** returns true if you have read access to the file */ bool canReadFile( const CString & file, bool rel = true ); /** * Resolves all .. . and symbolic links, and converts to an absolute * path relative to this directory's path. If the supplied path is * already absolute it is still simplified. All components of the path * must exist and be accessible. Repeated path separators are simplified */ CString Canonicalize( const CString & path ); /** */ static void SplitPathFile( CString string, CString & path, CString & file ); /** */ bool CreatePath( CString path ); /** */ bool ReadEntrys( FilterSpec filterspec, CList * list, const bool checkPerms = true ); /** */ bool IsDir( CString s, bool rel = true ); /** */ bool IsFile( CString s, bool rel = true ); /** */ void SetPath( CString path ); /** */ static bool FreeDiscSpace( CString path, ulonglong * res ); /** * Remove a directory specified by it's absolute path * which must be empty. Returns true it it succeeds. */ static bool RmDir( const CString & abspath ); private: #ifdef WIN32 /** */ bool GetStat( CString & s, struct _stati64 * buf, bool rel = true ); /** */ bool GetLStat( CString & s, struct _stati64 * buf, bool rel = true ); #else /** */ bool GetStat( CString & s, struct stat * buf, bool rel = true ); /** */ bool GetLStat( CString & s, struct stat * buf, bool rel = true ); #endif /** */ CString sPath; /** */ CString sDrive; }; #endif libdc0-0.3.24~svn3121/dclib/core/cthread.cpp0000644000175000017500000001152411200360161017335 0ustar sikonsikon/*************************************************************************** cthread.cpp - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cthread.h" #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "ccallback.h" #ifdef WIN32 #include #endif CThread::CThread() { _thread_callback_function = 0; iStop = 1; iRun = 0; #ifdef WIN32 thread = 0; #endif } CThread::~CThread() { iStop = 1; if ( iRun == 1 ) { #ifdef WIN32 WaitForSingleObject( thread, INFINITE ); #else pthread_join(thread,NULL); #endif } #ifdef WIN32 if ( thread != 0 ) { if ( CloseHandle(thread) ) { thread = 0; } else { printf("CThread::~CThread: CloseHandle failed\n"); } } #endif delete _thread_callback_function; _thread_callback_function = 0; } /** */ int CThread::Start() { if (iRun==1) return -1; if (iStop==0) return -1; iStop = 0; #ifdef WIN32 if ( thread != 0 ) { if ( CloseHandle(thread) ) { thread = 0; } else { return -1; } } /* HANDLE is void* and _beginthreadex() returns long unsigned int ... */ thread = (HANDLE) _beginthreadex( NULL, // default security 0, // default stacksize MainThread, // function to call this, // function parameter 0, // default creation flags - start running NULL // there's both an ID and a handle apparently... ); if ( thread == 0 ) { return -1; } else { return 0; } #else return pthread_create(&thread, 0, MainThread, this); #endif } /** */ int CThread::Stop( bool bHard ) { if (iRun==0) return -1; if (iStop==1) return -1; iStop=1; if ( bHard ) { #ifdef WIN32 WaitForSingleObject( thread, INFINITE ); if ( CloseHandle(thread) ) { thread = 0; } else { printf("CThread::MainThread: CloseHandle failed\n"); } #else pthread_join(thread,NULL); #endif } return 0; } /** */ bool CThread::Join() { if ( iRun == 0 ) { return false; } else { #ifdef WIN32 return (WaitForSingleObject( thread, INFINITE ) != WAIT_FAILED); #else return (pthread_join(thread,NULL) == 0); #endif } } /** */ void CThread::SetThreadCallBackFunction( _CCallback0 * callback ) { Lock(); delete _thread_callback_function; _thread_callback_function = callback; UnLock(); } /** */ #ifdef WIN32 unsigned int __stdcall CThread::MainThread( void * object ) #else void * CThread::MainThread( void * object ) #endif { #ifndef WIN32 int oldState = 0; #endif CThread * pThread = (CThread*)object; pThread->iRun = 1; #ifndef WIN32 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&oldState); #endif for(;;) { if ( pThread->iStop == 1 ) { break; } else { if ( pThread->_thread_callback_function != 0 ) { pThread->_thread_callback_function->notify(); } else { pThread->Thread(); } } } #ifndef WIN32 if ( (oldState = pthread_detach(pthread_self())) != 0 ) { printf("CThread: pthread_detach with %d\n",oldState); } #endif pThread->iRun = 0; #ifdef WIN32 /* it's supposed to be called automatically on return anyway */ _endthreadex(0); return 0; #else pthread_exit(0); /* * pthread_exit() cannot return, maybe this is just to keep the compiler happy, * return 0 probably works fine for non-WIN32. */ return (void*)1; #endif } /** * Sleep : milliseconds : 0,001 * usleep : microseconds : 0,000001 * nanosleep : nanoseconds : 0,000000001 */ void CThread::NanoSleep( unsigned long millisec ) { #ifndef WIN32 #ifdef HAVE_NANOSLEEP struct timespec req, rem; req.tv_sec = 0; req.tv_nsec = millisec*1000*1000; rem.tv_sec = 0; rem.tv_nsec = 0; while( (nanosleep(&req,&rem) == -1) ) { if ( errno != EINTR ) break; if ( rem.tv_nsec == 0 ) break; req.tv_sec = 0; req.tv_nsec = rem.tv_nsec; rem.tv_sec = 0; rem.tv_nsec = 0; } #elif HAVE_USLEEP usleep(millisec*1000); #else #error "nanosleep or usleep not supported" #endif #else Sleep(millisec); #endif } libdc0-0.3.24~svn3121/dclib/core/cmutex.h0000644000175000017500000000352411101144617016704 0ustar sikonsikon/*************************************************************************** cmutex.h - mutex ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CMUTEX_H #define CMUTEX_H /** * @author Mathias Küster * * It's a mutex, only one thread can lock a mutex at a time, other threads * attempting to lock it when it is already locked will be blocked until it * is unlocked. * * It is not a recursive mutex, a thread locking an already locked mutex * will permenantly hang. */ #ifndef WIN32 #include #endif #include class CMutex { public: /** */ CMutex(); /** */ virtual ~CMutex(); /** */ int Lock(); /** */ bool TryLock(); /** */ int UnLock(); private: #ifdef WIN32 /** * Everything returns void so there's no bool with it. * An exception may be thrown but dclib is not designed to * handle running out of memory. */ CRITICAL_SECTION m_CS; #else /** */ bool m_bMutexInit; /** */ pthread_mutex_t mutex; #endif }; #endif // CMUTEX_H libdc0-0.3.24~svn3121/dclib/core/cssl.cpp0000644000175000017500000003326311245161752016711 0ustar sikonsikon/*************************************************************************** cssl.cpp - description ------------------- begin : Sat Dec 7 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cssl.h" #include #include #include "cstring.h" #include "cbase64.h" #include "cbytearray.h" /* cmutex.h includes */ #include "cmutex.h" /* init static members */ CMutex * CSSL::mutexes = NULL; #if DCLIB_USES_OPENSSL == 1 /** free RSA */ CSSLObject::~CSSLObject() { if ( m_pRSA ) { RSA_free(m_pRSA); } } /** */ CSSL::CSSL() { m_pRSA = 0; m_pRandBuffer = 0; } /** */ CSSL::~CSSL() { if ( m_pRSA ) RSA_free(m_pRSA); if ( m_pRandBuffer ) free(m_pRandBuffer); } /** */ void CSSL::InitSSLLibrary() { mutexes = new CMutex[ CRYPTO_num_locks() ]; #ifndef WIN32 CRYPTO_set_id_callback( &CSSL::thread_id ); #endif CRYPTO_set_locking_callback( &CSSL::locking_callback ); SSL_load_error_strings(); SSL_library_init(); } /** */ void CSSL::DeInitSSLLibrary() { CRYPTO_set_locking_callback( NULL ); delete[] mutexes; mutexes = NULL; ERR_free_strings(); } /** */ SSL_CTX * CSSL::InitClientCTX() { #if OPENSSL_VERSION_NUMBER >= 0x10000000L const SSL_METHOD *method; #else SSL_METHOD *method; #endif SSL_CTX *ctx = NULL; method = SSLv23_client_method(); /* Create new client-method instance */ // sanity check if ( method != NULL ) { ctx = SSL_CTX_new(method); /* Create new context */ } // sanity check if ( ctx == NULL ) { ERR_print_errors_fp(stderr); } return ctx; } /** */ SSL_CTX * CSSL::InitServerCTX() { #if OPENSSL_VERSION_NUMBER >= 0x10000000L const SSL_METHOD *method; #else SSL_METHOD *method; #endif SSL_CTX *ctx = NULL; method = SSLv23_server_method(); /* Create new client-method instance */ if ( method != NULL ) { ctx = SSL_CTX_new(method); /* Create new context */ } if ( ctx == NULL ) { ERR_print_errors_fp(stderr); } return ctx; } /** */ SSL_CTX * CSSL::NewTLSv1ClientCTX() { #if OPENSSL_VERSION_NUMBER >= 0x10000000L const SSL_METHOD *method; #else SSL_METHOD *method; #endif SSL_CTX * ctx = NULL; method = TLSv1_client_method(); if ( method != NULL ) { ctx = SSL_CTX_new(method); } if ( ctx == NULL ) { ERR_print_errors_fp(stderr); } return ctx; } /** */ SSL_CTX * CSSL::NewTLSv1ServerCTX() { #if OPENSSL_VERSION_NUMBER >= 0x10000000L const SSL_METHOD *method; #else SSL_METHOD *method; #endif SSL_CTX * ctx = NULL; method = TLSv1_server_method(); if ( method != NULL ) { ctx = SSL_CTX_new(method); } if ( ctx == NULL ) { ERR_print_errors_fp(stderr); } return ctx; } /** */ bool CSSL::LoadCertificates( SSL_CTX * ctx, char * CertFile, char * KeyFile ) { bool res = false; // check if ( !ctx || !CertFile || !KeyFile ) { return res; } // set the local certificate from CertFile if ( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0 ) { ERR_print_errors_fp(stderr); } // set the private key from KeyFile (may be the same as CertFile) else if ( SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0 ) { ERR_print_errors_fp(stderr); } // verify private key else if ( !SSL_CTX_check_private_key(ctx) ) { fprintf(stderr, "Private key does not match the public certificate\n"); } // no error else { res = true; } return res; } void CSSL::InitRand() { if ( m_pRandBuffer ) { free(m_pRandBuffer); } m_pRandBuffer = (int *) malloc(sizeof(int)*1000); if ( !m_pRandBuffer ) { perror("CSSL::InitRand: malloc"); return; } InitRandArray((unsigned char*)m_pRandBuffer,sizeof(int)*1000); RAND_seed(m_pRandBuffer,sizeof(int)*1000); } /** */ bool CSSL::GenerateRsaKey() { bool res = false; if ( m_pRSA == 0 ) { InitRand(); m_pRSA = RSA_generate_key(2048,65537,NULL,NULL); if ( m_pRSA ) { if ( RSA_check_key(m_pRSA) == 1 ) res = true; } } return res; } /** */ void CSSL::InitRandArray( unsigned char * a, int len ) { int i; // sanity check if ( !a || (len <= 0) ) { return; } if ( RAND_bytes(a,len) != 1 ) { srand(time(NULL)); for(i=0;i 0 ) { bain.SetSize(i); buf = bain.Data(); // sanity check if ( buf ) { i = i2d_RSAPublicKey(m_pRSA,&buf); // sanity check if ( i > 0 ) { CBase64::Encode(&baout,&bain); s.Set((const char*)baout.Data(),baout.Size()); } } } } return s; } /** */ bool CSSL::SetPublicKey( CSSLObject * SSLObject, CString s ) { bool res = false; CByteArray bain,baout; unsigned char *buf; // sanity check if ( !SSLObject || (s.IsEmpty()) ) { return res; } bain.SetSize(0); bain.Append(s.Data(),s.Length()); if ( CBase64::Decode(&baout,&bain) > 0 ) { if ( SSLObject->m_pRSA ) RSA_free(SSLObject->m_pRSA); buf = baout.Data(); #if OPENSSL_VERSION_NUMBER >= 0x00907000L SSLObject->m_pRSA = d2i_RSAPublicKey(NULL,(const unsigned char**)&buf,baout.Size()); #else SSLObject->m_pRSA = d2i_RSAPublicKey(NULL,(unsigned char**)&buf,baout.Size()); #endif if ( SSLObject->m_pRSA ) res = true; } return res; } /** */ void CSSL::InitSessionKey( CSSLObject * SSLObject ) { // sanity check if ( SSLObject ) { InitRandArray( SSLObject->m_localkey, 16 ); InitRandArray( SSLObject->m_localiv, 8 ); } } /** */ CString CSSL::GetSessionKey( CSSLObject * SSLObject ) { int i; CByteArray bain,baout; CString s; // sanity check if ( !SSLObject ) { return s; } bain.SetSize(0); bain.Append( SSLObject->m_localkey, 16); bain.Append( SSLObject->m_localiv, 8); // printf("LOCAL\n"); // for(i=0;i<24;i++) printf("%02X ",bain.Data()[i]); // printf("\n"); baout.SetSize(500); i = RSA_public_encrypt(bain.Size(),bain.Data(),baout.Data(),SSLObject->m_pRSA,RSA_PKCS1_OAEP_PADDING); if ( i != 0 ) { bain.SetSize(0); bain.Append(baout.Data(),i); baout.SetSize(0); CBase64::Encode(&baout,&bain); s.Set((const char*)baout.Data(),baout.Size()); } else { printf("LOCAL SK error %d\n",i); } return s; } /** */ bool CSSL::SetSessionKey( CSSLObject * SSLObject, CString s ) { bool res = false; CByteArray bain,baout; int i; // sanity check if ( !SSLObject || (s.IsEmpty()) ) { return res; } bain.SetSize(0); bain.Append(s.Data(),s.Length()); if ( CBase64::Decode(&baout,&bain) > 0 ) { bain.SetSize(baout.Size()); i = RSA_private_decrypt(baout.Size(),baout.Data(),bain.Data(),m_pRSA,RSA_PKCS1_OAEP_PADDING); if ( i == 24 ) { // printf("REMOTE\n"); // for(i=0;i<24;i++) printf("%02X ",bain.Data()[i]); // printf("\n"); memcpy( SSLObject->m_remotekey, bain.Data()+0, 16 ); memcpy( SSLObject->m_remoteiv, bain.Data()+16, 8 ); res = true; } else { printf("SK error %d\n",i); } } return res; } /** */ CString CSSL::EncryptData( CSSLObject * SSLObject, CString s ) { CString res; CByteArray bain,baout; int i,tmplen; EVP_CIPHER_CTX ctx; // sanity check if ( !SSLObject || (s.IsEmpty()) ) { return res; } EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit(&ctx, EVP_bf_cbc(), SSLObject->m_remotekey, SSLObject->m_remoteiv); // init input array bain.SetSize(2); InitRandArray(bain.Data(),2); bain.Append(s.Data(),s.Length()); // init output array // input size + cipher_block_size for EVP_EncryptUpdate // plus cipher_block_size for EVP_EncryptFinal baout.SetSize( bain.Size() + ( 2 * EVP_CIPHER_CTX_block_size(&ctx) ) ); //printf("CSSL::EncryptData: wrong old size=%lu new size=%lu\n",bain.Size()*2,baout.Size()); i = baout.Size(); if ( EVP_EncryptUpdate(&ctx, baout.Data(), &i, bain.Data(), bain.Size() ) ) { if ( EVP_EncryptFinal(&ctx, baout.Data()+i, &tmplen) ) { i+=tmplen; bain.SetSize(0); bain.Append(baout.Data(),i); baout.SetSize(0); CBase64::Encode(&baout,&bain); res.Set((const char*)baout.Data(),baout.Size()); } } EVP_CIPHER_CTX_cleanup(&ctx); return res; } /** */ CString CSSL::DecryptData( CSSLObject * SSLObject, CString s ) { CString res; CByteArray bain,baout; int i,tmplen; EVP_CIPHER_CTX ctx; // sanity check if ( !SSLObject || (s.IsEmpty()) ) { return res; } EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit(&ctx, EVP_bf_cbc(), SSLObject->m_localkey, SSLObject->m_localiv); bain.SetSize(0); bain.Append(s.Data(),s.Length()); if ( CBase64::Decode(&baout,&bain) > 0 ) { bain.SetSize( baout.Size() + ( 2 * EVP_CIPHER_CTX_block_size(&ctx) ) ); //printf("CSSL::DecryptData: wrong old size=%lu new size=%lu\n",baout.Size()*2,bain.Size()); i = 0; if ( EVP_DecryptUpdate(&ctx, bain.Data(), &i, baout.Data(), (int)baout.Size() ) ) { tmplen = 0; if ( EVP_DecryptFinal(&ctx, bain.Data()+i, &tmplen) ) { i+=tmplen; res.Set((const char*)bain.Data()+2,i-2); } } } EVP_CIPHER_CTX_cleanup(&ctx); return res; } /** */ CString CSSL::GetSSLVersionString() { return CString(OPENSSL_VERSION_TEXT); } /** */ void CSSL::locking_callback( int mode, int type, const char * /* file */, int /* line */ ) { if ( mode & CRYPTO_LOCK ) { mutexes[type].Lock(); } else { mutexes[type].UnLock(); } } /* * Alternative implementations using other SSL libraries may go here but should probably be * moved into separate files. */ #else // DCLIB_USES_OPENSSL /* * The without SSL implementation of each method does nothing / returns 0 or empty * but will print a warning since they should not be used. Check for support with * DCLIB_HAS_SSL at dclib compile time or dclibSupportsSSL() at valknut runtime. */ /** */ CSSLObject::~CSSLObject() { // nothing } /** */ CSSL::CSSL() { m_pRSA = 0; m_pRandBuffer = 0; } /** */ CSSL::~CSSL() { // nothing } /** */ void CSSL::InitSSLLibrary() { // nothing } /** */ void CSSL::DeInitSSLLibrary() { // nothing } /** */ SSL_CTX * CSSL::InitClientCTX() { printf("dclib was compiled without SSL support so CSSL::InitClientCTX always returns 0\n"); return 0; } /** */ SSL_CTX * CSSL::InitServerCTX() { printf("dclib was compiled without SSL support so CSSL::InitServerCTX always returns 0\n"); return 0; } /** */ SSL_CTX * CSSL::NewTLSv1ClientCTX() { printf("dclib was compiled without SSL support so CSSL::NewTLSv1ClientCTX always returns 0\n"); return 0; } /** */ SSL_CTX * CSSL::NewTLSv1ServerCTX() { printf("dclib was compiled without SSL support so CSSL::NewTLSv1ServerCTX always returns 0\n"); return 0; } /** */ bool CSSL::LoadCertificates( SSL_CTX * /* ctx */, char * /* certfile */, char * /* keyfile */ ) { printf("dclib was compiled without SSL support so CSSL::LoadCertificates always returns false\n"); return false; } /** */ void CSSL::InitRand() { printf("dclib was compiled without SSL support so CSSL::InitRand does nothing\n"); } /** */ void CSSL::InitRandArray( unsigned char * /* a */, int /* len */ ) { printf("dclib was compiled without SSL support so CSSL::InitRandArray does nothing\n"); } /** */ bool CSSL::GenerateRsaKey() { printf("dclib was compiled without SSL support so CSSL::GenerateRsaKey always returns false\n"); return false; } /** */ CString CSSL::GetPublicRsaKey() { printf("dclib was compiled without SSL support so CSSL::GetPublicRsaKey always returns an empty string\n"); return CString(); } /** */ bool CSSL::SetPublicKey( CSSLObject * /* SSLObject */, CString /* s */ ) { printf("dclib was compiled without SSL support so CSSL::SetPublicKey always returns false\n"); return false; } /** */ void CSSL::InitSessionKey( CSSLObject * /* SSLObject */ ) { printf("dclib was compiled without SSL support so CSSL::InitSessionKey does nothing\n"); } /** */ CString CSSL::GetSessionKey( CSSLObject * /* SSLObject */ ) { printf("dclib was compiled without SSL support so CSSL::GetSessionKey always returns an empty string\n"); return CString(); } /** */ bool CSSL::SetSessionKey( CSSLObject * /* SSLObject */, CString /* s */ ) { printf("dclib was compiled without SSL support so CSSL::SetSessionKey always returns false\n"); return false; } /** */ CString CSSL::EncryptData( CSSLObject * /* SSLObject */, CString /* s */ ) { printf("dclib was compiled without SSL support so CSSL::EncryptData always returns an empty string\n"); return CString(); } /** */ CString CSSL::DecryptData( CSSLObject * /* SSLObject */, CString /* s */ ) { printf("dclib was compiled without SSL support so CSSL::DecryptData always returns an empty string\n"); return CString(); } /** */ CString CSSL::GetSSLVersionString() { return CString("None"); } /** */ void CSSL::locking_callback( int /* mode */, int /* type */, const char * /* file */, int /* line */ ) { return; } #endif // DCLIB_USES_OPENSSL /** This function does not use OpenSSL */ #ifndef WIN32 unsigned long CSSL::thread_id() { /* * This is bad because we are not supposed to know * or rely on what a pthread_t is, however it is an unsigned long, * and the OpenSSL docs don't provide any other code. */ return (unsigned long) pthread_self(); } #endif libdc0-0.3.24~svn3121/dclib/core/cmanager.cpp0000644000175000017500000000431311103425621017503 0ustar sikonsikon/*************************************************************************** cmanager.cpp - description ------------------- begin : Thu Jan 23 2003 copyright : (C) 2003-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cmanager.h" #ifndef WIN32 #include #endif #include "platform.h" #include "ccallback.h" /** */ CManager::CManager() { Start(); } /** */ CManager::~CManager() { SetInstance(0); Stop(); } /** */ void CManager::Add( _CCallback0 * callback ) { if ( callback ) { m_CallbacksMutex.Lock(); m_Callbacks.Add(callback); m_CallbacksMutex.UnLock(); } } /** */ void CManager::Remove( _CCallback0 * callback ) { if ( callback ) { m_CallbacksMutex.Lock(); m_Callbacks.Remove(callback); m_CallbacksMutex.UnLock(); } } /** */ void CManager::Thread() { struct timeval tv_old, tv_new; _CCallback0 * callback = 0; unsigned int i; gettimeofday(&tv_old, NULL); while( true ) { m_CallbacksMutex.Lock(); callback = m_Callbacks.Next(callback); m_CallbacksMutex.UnLock(); if ( !callback ) { break; } callback->notify(); } gettimeofday(&tv_new, NULL); i = 0; if ( (tv_new.tv_sec - tv_old.tv_sec) == 0 ) { i = (tv_new.tv_usec - tv_old.tv_usec); if ( i < 5000 ) { i = 10 - (i/1000); } else { i = 0; } } //malloc_stats(); //printf("%d %d %d\n",i,tv_new.tv_sec - tv_old.tv_sec,(tv_new.tv_usec - tv_old.tv_usec)/1000); NanoSleep(i); } libdc0-0.3.24~svn3121/dclib/core/cssl.h0000644000175000017500000000740611131224440016342 0ustar sikonsikon/*************************************************************************** cssl.h - description ------------------- begin : Sat Dec 7 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSSL_H #define CSSL_H /** *@author Mathias Küster * * This has some SSL utility functions and does some * cryptography for the "secure" private chat. */ #include #include #include #if DCLIB_USES_OPENSSL == 1 #include #include #include #include #include #include #else /* this may also work for SSL builds */ typedef struct rsa_st RSA; typedef struct ssl_ctx_st SSL_CTX; #endif class CMutex; class CSSLObject { public: /** */ CSSLObject() { m_bHandshakeState = 0; m_pRSA = 0; }; /** */ ~CSSLObject(); /** */ int m_bHandshakeState; /* */ RSA * m_pRSA; /** */ unsigned char m_localkey[16]; /** */ unsigned char m_localiv[8]; /** */ unsigned char m_remotekey[16]; /** */ unsigned char m_remoteiv[8]; }; class CSSL { public: /** */ CSSL(); /** */ virtual ~CSSL(); /** */ static SSL_CTX * InitClientCTX(); /** */ static SSL_CTX * InitServerCTX(); /** * As the name suggests it creates a new client SSL_CTX * that only supports >= TLSv1, required for * *DC++ compatibility. */ static SSL_CTX * NewTLSv1ClientCTX(); /** * As the name suggests it creates a new server SSL_CTX * that only supports >= TLSv1, required for * *DC++ compatibility. */ static SSL_CTX * NewTLSv1ServerCTX(); /** */ static bool LoadCertificates( SSL_CTX * ctx, char * CertFile, char * KeyFile ); /** Get SSL library version string */ static CString GetSSLVersionString(); /** Perform library initialisation functions */ static void InitSSLLibrary(); /** Perform library deinitialisation functions */ static void DeInitSSLLibrary(); protected: /** */ void InitRand(); /** */ void InitRandArray( unsigned char * a, int len ); /** */ bool GenerateRsaKey(); /** */ CString GetPublicRsaKey(); /** */ bool SetPublicKey( CSSLObject * SSLObject, CString s ); /** */ void InitSessionKey( CSSLObject * SSLObject ); /** */ CString GetSessionKey( CSSLObject * SSLObject ); /** */ bool SetSessionKey( CSSLObject * SSLObject, CString s ); /** */ CString EncryptData( CSSLObject * SSLObject, CString s ); /** */ CString DecryptData( CSSLObject * SSLObject, CString s ); /* */ RSA * m_pRSA; /** */ int * m_pRandBuffer; private: /** some mutexes for OpenSSL to use */ static CMutex * mutexes; /** * a function to give to OpenSSL for it to use the mutexes * FIXME that const will have been added in some version... * breaking things with older versions */ static void locking_callback( int mode, int type, const char * file, int line ); #ifndef WIN32 /** a thread id function, not required on Windows */ static unsigned long thread_id(); #endif /* WIN32 */ }; #endif libdc0-0.3.24~svn3121/dclib/core/clogfile.h0000644000175000017500000000306711125260136017166 0ustar sikonsikon/*************************************************************************** clogfile.h - description ------------------- begin : Sat Dec 14 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CLOGFILE_H #define CLOGFILE_H /** *@author Mathias Küster * * Writes text to a file, because it's a log file that * requires opening, writing, and closing to ensure it is saved. */ #include #include #include enum eLogType { eltINFO, eltWARNING, eltERROR }; class CLogFile { public: /** */ static bool Write( CString file, eLogType type, CString message ); protected: /** */ CLogFile(); /** */ ~CLogFile(); private: /** */ static CMutex m_LogFileMutex; }; #endif libdc0-0.3.24~svn3121/dclib/core/cbz.cpp0000644000175000017500000000755411176103337016525 0ustar sikonsikon/*************************************************************************** cbz.cpp - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cbz.h" #include #ifndef BZ_NO_STDIO #define BZ_NO_STDIO #endif #include #include "cbytearray.h" #include "cstring.h" #define MAX_BUFFER_LEN 536870912 // 512MiB max memory /** */ CBZ::CBZ() { } /** */ CBZ::~CBZ() { } /** */ bool CBZ::Compress( CByteArray * src, CByteArray * dst ) { if ( src && dst ) { return CBZ::Compress( (char*) src->Data(), src->Size(), dst ); } else { return false; } } /** */ bool CBZ::Compress( const CString * src, CByteArray * dst ) { if ( src && dst ) { return CBZ::Compress( src->Data(), src->Length(), dst ); } else { return false; } } /** */ bool CBZ::Compress( char * src, unsigned int inlen, CByteArray * dst ) { bool res = false; int i; unsigned int outlen = inlen; // src and dst already checked non null if ( inlen == 0 ) { return res; } while ( true ) { outlen *= 2; // check for max memory if ( outlen > MAX_BUFFER_LEN ) { printf("CBZ::Compress: max mem reached\n"); break; } // increase output capacity if ( dst->Realloc(outlen) == false ) { printf("CBZ::Compress: realloc 1 failed\n"); break; } i = BZ2_bzBuffToBuffCompress( (char*)dst->Data(), &outlen, src, inlen, 9, 0, 0); // check result if ( i == BZ_OK ) { res = true; break; } else if ( i == BZ_OUTBUFF_FULL ) { // nothing, try again } else { // another decompression error printf("CBZ::Compress: failed with %d\n",i); break; } } if ( res ) { /* shrink output to correct size */ if ( dst->Realloc(outlen) == false ) { printf("CBZ::Compress: realloc 2 failed\n"); dst->SetSize(0); res = false; } } else { /* otherwise empty output */ dst->SetSize(0); } return res; } /** */ bool CBZ::Decompress( CByteArray * src, CByteArray * dst ) { bool res = false; int i; unsigned int outlen = src->Size(); if ( (!src) || (!dst) || (src->Size() == 0) ) { return res; } while ( true ) { if ( outlen < (50 * 1024 * 1024) ) { outlen *= 10; } else { outlen += (50 * 1024 * 1024); } // check for max memory if ( outlen > MAX_BUFFER_LEN ) { printf("CBZ::Decompress: max mem reached\n"); break; } if ( dst->Realloc(outlen) == false ) { printf("CBZ::Decompress: realloc 1 failed\n"); break; } i = BZ2_bzBuffToBuffDecompress( (char*)dst->Data(), &outlen, (char*)src->Data(), src->Size(), 0, 0); if ( i == BZ_OK ) { res = true; break; } else if ( i == BZ_OUTBUFF_FULL ) { // nothing, try again } else { // another decompression error printf("CBZ::Decompress: failed with %d\n",i); break; } } if ( res ) { /* shrink output to correct size */ if ( dst->Realloc(outlen) == false ) { printf("CBZ::Compress: realloc 2 failed\n"); dst->SetSize(0); res = false; } } else { /* otherwise empty output */ dst->SetSize(0); } return res; } libdc0-0.3.24~svn3121/dclib/core/cstringhash.h0000644000175000017500000000543611555040725017730 0ustar sikonsikon/*************************************************************************** cstringhash.h - DCLib CString Hash function for STL unordered_map/set ------------------- begin : Fri Jun 27 2008 copyright : (C) 2008 by Edward Sheldrake email : ejs1920@yahoo.co.uk ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CSTRINGHASH_H #define CSTRINGHASH_H // plus the correct // or headers must be included before this file #include // ok so adding a hash function for CString to the standard namespace // is probably not the best solution... but it makes CString easier // to use until it's replaced with std::string namespace std { #if ( DCLIB_USES_TR1_UNORDERED_MAP == 1 ) || ( DCLIB_USES_TR1_UNORDERED_SET == 1 ) namespace tr1 { #endif // this is the same as the hash function for a std::string // but it probably only works with recent GCC since // _Fnv_hash is probably not part of any API template<> struct hash { size_t operator() (const CString & s) const { #if DCLIB_FNV_HASH_IS_PREFIXED == 1 #if DCLIB_FNV_HASH_IS_TEMPLATE == 1 return _Fnv_hash<>::hash( s.Data(), s.Length() ); #else return _Fnv_hash::hash( s.Data(), s.Length() ); #endif #else /* DCLIB_FNV_HASH_IS_PREFIXED */ #if DCLIB_FNV_HASH_IS_TEMPLATE == 1 return Fnv_hash<>::hash( s.Data(), s.Length() ); #else return Fnv_hash::hash( s.Data(), s.Length() ); #endif #endif /* DCLIB_FNV_HASH_IS_PREFIXED */ } }; template<> struct hash { size_t operator() (CString s) const { #if DCLIB_FNV_HASH_IS_PREFIXED == 1 #if DCLIB_FNV_HASH_IS_TEMPLATE == 1 return _Fnv_hash<>::hash( s.Data(), s.Length() ); #else return _Fnv_hash::hash( s.Data(), s.Length() ); #endif #else /* DCLIB_FNV_HASH_IS_PREFIXED */ #if DCLIB_FNV_HASH_IS_TEMPLATE == 1 return Fnv_hash<>::hash( s.Data(), s.Length() ); #else return Fnv_hash::hash( s.Data(), s.Length() ); #endif #endif /* DCLIB_FNV_HASH_IS_PREFIXED */ } }; #if ( DCLIB_USES_TR1_UNORDERED_MAP == 1 ) || ( DCLIB_USES_TR1_UNORDERED_SET == 1 ) } #endif } #endif // CSTRINGHASH_H libdc0-0.3.24~svn3121/dclib/core/cdir.cpp0000644000175000017500000003527711104361305016663 0ustar sikonsikon/*************************************************************************** cdir.cpp - description ------------------- begin : Tue May 14 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cdir.h" #ifdef HAVE_CONFIG_H #include #endif #ifdef WIN32 #include #else #include #include #include #include extern "C" { #include "../gnulib/fsusage.h" } #endif #include #include #include #include #include /** */ CDir::CDir() { } /** */ CDir::CDir( CString path ) { SetPath(path); } /** */ CDir::~CDir() { } /** */ CString CDir::Extension( CString file ) { int i; CString s; if ( (i = file.FindRev('.')) != -1 ) s = file.Mid(i+1,file.Length()-i-1); return s; } /** */ CString CDir::Path() { #ifdef WIN32 return ConvertSeparators(sDrive+DIRSEPARATOR+sPath); #else return sPath; #endif } /** */ void CDir::SetPath( CString path ) { // convert separators to internal path.Swap('\\','/'); #ifdef WIN32 // TODO: use _splitpath int i; // store drive letter if ( (i = path.Find(':',0)) == 1 ) { sDrive = path.Left(i+1); path = path.Mid(i+1,path.Length()-i-1); // remove first separator if ( path.Find('/') == 0 ) { path = path.Mid(1,path.Length()-1); } } #endif // remove last '/' if ( ((1+path.FindRev('/')) == path.Length()) && (path.Length() > 1) ) { sPath = path.Left( path.Length()-1 ); } else { sPath = path; } } /** */ CString CDir::HomeDirPath() { CString s; #ifdef WIN32 s = getenv("USERPROFILE"); if ( s.IsEmpty() ) { char buffer[_MAX_PATH]; /* Get the current working directory: */ if( _getcwd( buffer, _MAX_PATH ) != NULL ) { s = buffer; } } #else s = getenv("HOME"); #endif if ( s.IsEmpty() ) { s = DIRSEPARATOR; } return s; } /** */ bool CDir::cd( CString path ) { sPath.Empty(); if ( path == "." ) return true; if ( path.IsEmpty() ) return false; #ifdef WIN32 if ( _access( path.Data(), F_OK | R_OK ) == 0 ) #else if ( access( path.Data(), F_OK | R_OK ) == 0 ) #endif { SetPath(path); return true; } return false; } /** */ CString CDir::DirName() { int pos = sPath.FindRev('/'); if( pos == -1 ) return sPath; return sPath.Mid( pos + 1, sPath.Length() - 1 - pos ); } /** */ #ifdef WIN32 bool CDir::ReadEntrys( FilterSpec filterspec, CList * list, const bool /* checkPerms */ ) #else bool CDir::ReadEntrys( FilterSpec filterspec, CList * list, const bool checkPerms ) #endif { if ( !list ) return false; if ( Path().IsEmpty() ) return false; list->Clear(); #ifdef WIN32 struct _finddatai64_t filedata; CString pathstar = Path(); pathstar += DIRSEPARATOR; pathstar += '*'; intptr_t fhandle = _findfirsti64( pathstar.Data(), &filedata ); if ( fhandle == -1 ) { return false; } else { do { if ( ((filterspec == Files) && ((filedata.attrib & _A_SUBDIR) == 0)) || ((filterspec == Dirs) && ((filedata.attrib & _A_SUBDIR) == _A_SUBDIR)) ) { CFileInfo * fi = new CFileInfo(); fi->name = filedata.name; fi->size = filedata.size; fi->m_bSymlink = false; fi->st_a_time = filedata.time_access; fi->st_m_time = filedata.time_write; fi->st_c_time = filedata.time_create; list->Add(fi); } } while ( _findnexti64( fhandle, &filedata ) == 0 ); _findclose( fhandle ); } #else /* NOT WIN32 */ DIR * dir; CFileInfo * FileInfo; dirent *file; CString s,d_name; struct stat buf; /* * even though they are not needed for checkPerms == false * gcc thinks that they "may be used uninitialized in this function" * if the get calls are within if ( checkPerms ) { ... } */ const uid_t euid = geteuid(); const gid_t egid = getegid(); gid_t * groups = 0; int numgroups = 0; dir = opendir( Path().Data() ); if ( dir == 0 ) return false; if ( checkPerms ) { numgroups = getgroups( 0, NULL ); if ( numgroups > 0 ) { groups = (gid_t*) malloc( numgroups * sizeof(gid_t) ); if ( groups ) { if ( getgroups( numgroups, groups ) != numgroups ) { perror("CDir::ReadEntrys getgroups"); free( groups ); groups = 0; numgroups = 0; } } } } while ( (file = readdir(dir)) != 0 ) { d_name.Set(file->d_name,strlen(file->d_name)); if ( GetStat( d_name, &buf ) ) { if ( (filterspec == Dirs) && ((buf.st_mode&S_IFMT)&S_IFDIR) ) { FileInfo = new CFileInfo(); FileInfo->name = d_name; FileInfo->size = 0; FileInfo->m_bSymlink = false; FileInfo->st_a_time = buf.st_atime; FileInfo->st_c_time = buf.st_ctime; FileInfo->st_m_time = buf.st_mtime; if ( checkPerms ) { bool accessible = false; if ( (buf.st_mode & (S_IROTH | S_IXOTH)) == (S_IROTH | S_IXOTH) ) { accessible = true; } else if ( (buf.st_uid == euid) && ((buf.st_mode & (S_IRUSR | S_IXUSR)) == (S_IRUSR | S_IXUSR)) ) { accessible = true; } else if ( (buf.st_mode & (S_IRGRP | S_IXGRP)) == (S_IRGRP | S_IXGRP) ) { if ( buf.st_gid == egid ) { accessible = true; } else { for ( int i = 0; i < numgroups; ++i ) { if ( buf.st_gid == groups[i] ) { accessible = true; break; } } } } if ( !accessible ) { delete FileInfo; continue; } } if ( GetLStat( d_name, &buf) ) { FileInfo->m_bSymlink = ((buf.st_mode&S_IFLNK)==S_IFLNK); } else { delete FileInfo; continue; } list->Add(FileInfo); } else if ( (filterspec == Files) && ((buf.st_mode&S_IFMT)&S_IFREG) ) { FileInfo = new CFileInfo(); FileInfo->name = d_name; FileInfo->size = buf.st_size; FileInfo->m_bSymlink = false; FileInfo->st_a_time = buf.st_atime; FileInfo->st_c_time = buf.st_ctime; FileInfo->st_m_time = buf.st_mtime; if ( checkPerms ) { bool readable = false; if ( (buf.st_mode & S_IROTH) == S_IROTH ) { readable = true; } else if ( (buf.st_uid == euid) && ((buf.st_mode & S_IRUSR) == S_IRUSR) ) { readable = true; } else if ( (buf.st_mode & S_IRGRP) == S_IRGRP ) { if ( buf.st_gid == egid ) { readable = true; } else { for ( int i = 0; i < numgroups; ++i ) { if ( buf.st_gid == groups[i] ) { readable = true; break; } } } } if ( !readable ) { delete FileInfo; continue; } } if ( GetLStat( d_name, &buf) ) { FileInfo->m_bSymlink = ((buf.st_mode&S_IFLNK)==S_IFLNK); } else { delete FileInfo; continue; } list->Add(FileInfo); } } } closedir(dir); if ( groups ) { free( groups ); } #endif /* WIN32 */ return true; } /** */ bool CDir::IsDir( CString s, bool rel ) { #ifdef WIN32 struct _stati64 buf; #else struct stat buf; #endif if ( GetStat(s,&buf,rel) ) { if ((buf.st_mode&S_IFMT)&S_IFDIR) { return true; } } return false; } /** */ bool CDir::IsFile( CString s, bool rel ) { #ifdef WIN32 struct _stati64 buf; #else struct stat buf; #endif if ( GetStat(s,&buf,rel) ) { if ((buf.st_mode&S_IFMT)&S_IFREG) { return true; } } return false; } #ifdef WIN32 /** Some code repeated to avoid temp string when rel is false */ bool CDir::GetStat( CString & s, struct _stati64 * buf, bool rel ) { if ( !buf ) { return false; } if ( rel ) { CString p = Path(); p += DIRSEPARATOR; p += s; /* it's never empty because DIRSEPARATOR is not nothing */ return (_stati64( p.Data(), buf ) == 0); } else { if ( s.IsEmpty() ) { return false; } else { return (_stati64( s.Data(), buf ) == 0); } } } /** Does not exist on WIN32 */ bool CDir::GetLStat( CString & /* s */, struct _stati64 * /* buf */, bool /* rel */ ) { return false; } #else // WIN32 /** Some code repeated to avoid temp string when rel is false */ bool CDir::GetStat( CString & s, struct stat * buf, bool rel ) { if ( !buf ) { return false; } if ( rel ) { CString p = sPath; p += DIRSEPARATOR; p += s; /* it's never empty because DIRSEPARATOR is not nothing */ return (stat( p.Data(), buf ) == 0); } else { if ( s.IsEmpty() ) { return false; } else { return (stat( s.Data(), buf ) == 0); } } } /** Some code repeated to avoid temp string when rel is false */ bool CDir::GetLStat( CString & s, struct stat * buf, bool rel ) { if ( !buf ) { return false; } if ( rel ) { CString p = sPath; p += DIRSEPARATOR; p += s; /* it's never empty because DIRSEPARATOR is not nothing */ return (lstat( p.Data(), buf ) == 0); } else { if ( s.IsEmpty() ) { return false; } else { return (lstat( s.Data(), buf ) == 0); } } } #endif // WIN32 /** */ ulonglong CDir::getFileSize( CString s, bool rel ) { #ifdef WIN32 struct _stati64 buf; #else struct stat buf; #endif if ( rel ) { #ifdef WIN32 s = Path()+DIRSEPARATOR+s; #else s = sPath + DIRSEPARATOR + s; #endif } if ( s.IsEmpty() ) return 0; #ifdef WIN32 if ( _stati64( s.Data(), &buf ) != 0 ) #else if ( stat( s.Data(), &buf ) != 0 ) #endif { //printf("CDir::getFileSize: stat: '%s' '%s'\n",strerror(errno),s.Data()); return false; } return buf.st_size; } /** */ void CDir::SplitPathFile( CString s, CString & path, CString & file ) { int i; path.Empty(); file.Empty(); if ( (i = s.FindRev('\\')) == -1 ) i = s.FindRev('/'); // for unix-kind folders (never seen ...) if ( i == -1 ) { file = s; } else { path = s.Left(i+1); file = s.Mid(i+1,s.Length()-i-1); } } /** */ CString CDir::ConvertSeparators( CString path ) { return path.Replace('/',DIRSEPARATOR); } /** */ CString CDir::SimplePath( CString path ) { CString t; char c = 0; long i = 0; path.Swap('\\','/'); // convert first ../ if ( path.StartsWith( "../", 3 ) ) { path.Data()[0] = '/'; path.Data()[1] = '/'; } // convert '..' -> '//' while( (i=path.Find( "/.." ,i )) != -1 ) { if ( (path.Data()[i+3] == 0) || (path.Data()[i+3] == '/') ) { path.Data()[i+1] = '/'; path.Data()[i+2] = '/'; } i++; } // remove double '/' char * buffer = (char*) malloc( path.Length() + 1 ); if ( buffer == 0 ) { perror("CDir::SimplePath malloc"); return t; } long bufferpos = 0; for ( i = 0; i < path.Length(); ++i ) { if ( (c == '/') && (path.Data()[i] == '/') ) continue; c = path.Data()[i]; buffer[bufferpos] = c; ++bufferpos; } t.Set( buffer, bufferpos ); free(buffer); #ifdef WIN32 return ConvertSeparators(t); #else return t; #endif } /** */ bool CDir::CreatePath( CString path ) { int i; CString s,s1; s = SimplePath(path); #ifdef WIN32 if ( (i = s.Find(':',0)) != -1 ) { sDrive = s.Left(i+1); s = s.Mid(i+1,s.Length()-i-1); } #endif while ( s.NotEmpty() ) { if ( (i = s.Find(DIRSEPARATOR)) != -1 ) { if (s1.NotEmpty()) s1 = s1 + DIRSEPARATOR + s.Left(i); else s1 = s.Left(i); s = s.Mid(i+1,s.Length()-1-i); } else { if (s1.NotEmpty()) s1 = s1 + DIRSEPARATOR + s; else s1 = s; s.Empty(); } if ( s1.IsEmpty() ) { continue; } if ( IsDir(s1) == false ) { #ifdef WIN32 if ( _mkdir((Path()+DIRSEPARATOR+s1).Data()) != 0 ) #else if ( mkdir((sPath+DIRSEPARATOR+s1).Data(),0777) != 0 ) #endif { if ( errno != EEXIST ) { printf("mkdir Error: '%s' '%s'\n",strerror(errno),(sPath+DIRSEPARATOR+s1).Data()); } return false; } } } return true; } /** */ bool CDir::FreeDiscSpace( CString path, ulonglong * res ) { if ( !res ) { return false; } #ifdef WIN32 ULARGE_INTEGER lpFreeBytesAvailableToCaller; // receives the number of bytes on // disk available to the caller ULARGE_INTEGER lpTotalNumberOfBytes; // receives the number of bytes on disk ULARGE_INTEGER lpTotalNumberOfFreeBytes; // receives the free bytes on disk if ( GetDiskFreeSpaceEx( path.Data(), &lpFreeBytesAvailableToCaller, &lpTotalNumberOfBytes, &lpTotalNumberOfFreeBytes ) == true ) { *res = lpTotalNumberOfFreeBytes.QuadPart; return true; } else { return false; } #else struct fs_usage fsp; if ( get_fs_usage(path.Data(),path.Data(),&fsp) == 0 ) { // printf("ok %d\n",fsp.fsu_bavail_top_bit_set); *res = fsp.fsu_bavail*fsp.fsu_blocksize; return true; } else { perror("CDir::FreeDiscSpace"); return false; } #endif } /** */ bool CDir::canReadFile( const CString & file, bool rel ) { CString p; if ( rel ) { p = Path() + DIRSEPARATOR + file; } else { p = file; } #ifdef WIN32 return (_access( p.Data(), R_OK ) == 0); #else return (access( p.Data(), R_OK ) == 0); #endif } /** */ CString CDir::Canonicalize( const CString & path ) { #if defined(WIN32) /* windows GUI does not have symlinks, NTFS does have junctions */ return path; #else if ( path.IsEmpty() || (path == ".") ) { return Path(); } // convert dir separators to internal (unix) CString s = path; s.Swap('\\','/'); if ( s.Data()[0] != '/' ) { s = sPath + "/" + s; } #if defined(HAVE_CANONICALIZE_FILE_NAME) char * result = canonicalize_file_name( s.Data() ); if ( result == 0 ) { s.Empty(); } else { s = result; free(result); } #elif defined(HAVE_REALPATH) char * buffer = (char*) calloc(1,4100); if ( buffer == 0 ) { printf("CDir::Canonicalize calloc failed\n"); return CString(); } else { char * result = realpath( s.Data(), buffer ); if ( result == 0 ) { s.Empty(); } else { s = result; } free(buffer); } #else return path; #endif /* HAVE_CANONICALIZE_FILE_NAME or HAVE_REALPATH */ return s; #endif /* WIN32 */ } /** */ bool CDir::RmDir( const CString & abspath ) { /* * I think Windows "sort of" supports Unix directory * separators. */ if ( abspath.IsEmpty() ) { return false; } else { #ifdef WIN32 return _rmdir( abspath.Data() ) == 0; #else return rmdir( abspath.Data() ) == 0; #endif } } libdc0-0.3.24~svn3121/dclib/core/cbase64.cpp0000644000175000017500000001110011105121561017143 0ustar sikonsikon/*************************************************************************** cbase64.cpp - description ------------------- begin : Tue Jul 09 2002 copyright : (C) 2002-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cbase64.h" #include #include #include "cbytearray.h" // original from mutt const signed char CBase64::Index_64[128] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, 63,-1,-1,-1, 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1, }; const char CBase64::B64Chars[64] = { '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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ',' }; #define base64val(c) Index_64[(unsigned int)(c)] #define base64chars(c) B64Chars[(unsigned int)((c)&0x3F)] /** */ CBase64::CBase64() { } /** */ CBase64::~CBase64() { } /** */ CString CBase64::Encode( CString string ) { CString outs; CByteArray in,out; in.Append(string.Data(),string.Length()); Encode(&out,&in); outs.Set((const char*)out.Data(),out.Size()); return outs; } /* raw bytes to null-terminated base 64 string */ void CBase64::Encode( CByteArray * dst, CByteArray * src ) { unsigned char c; unsigned char *current = src->Data(); size_t len = src->Size(); while (len >= 3) { c = base64chars(current[0] >> 2); dst->Append( &c, 1); c = base64chars(((current[0] & 0x03) << 4) | (current[1] >> 4)); dst->Append( &c, 1); c = base64chars(((current[1] & 0x0f) << 2) | (current[2] >> 6)); dst->Append( &c, 1); c = base64chars(current[2] & 0x3f); dst->Append( &c, 1); len -= 3; current += 3; } /* clean up remainder */ if (len > 0) { c = base64chars(current[0] >> 2); dst->Append(&c,1); if ( len > 1 ) { c = base64chars(((current[0] & 0x03) << 4) | (current[1] >> 4)); dst->Append(&c,1); c = base64chars((current[1] & 0x0f) << 2); dst->Append(&c,1); c = '='; dst->Append(&c,1); } else { c = base64chars((current[0] & 0x03) << 4); dst->Append(&c,1); c = '='; dst->Append(&c,1); c = '='; dst->Append(&c,1); } } } /** */ unsigned long CBase64::Decode( CByteArray * dst, CString * string ) { CByteArray in; in.Append(string->Data(),string->Length()); return Decode(dst,&in); } /* Convert '\0'-terminated base 64 string to raw bytes. * Returns length of returned buffer, or -1 on error */ unsigned long CBase64::Decode( CByteArray * dst, CByteArray * src ) { unsigned char *current,*result; unsigned char c; int ch; unsigned long i=0,j=0; if ( (!dst) || (!src) ) return -1; if ( (src->Size() % 4) != 0 ) return -1; dst->SetSize(0); current = src->Data(); result = dst->Data(); for(i=0;iSize();i++) { ch = (current[i]&0x7F); if (ch == '=') break; if (ch == ' ') ch = '+'; ch = Index_64[ch]; if (ch < 0) return -1; switch(i % 4) { case 0: c = (unsigned char)((ch << 2) & 0xFF); dst->Append(&c,1); break; case 1: dst->Data()[j] |= ((ch >> 4) & 0xFF); j++; if(current[i+1]!='=') { c = (unsigned char)((ch << 4) & 0xFF); dst->Append(&c,1); } break; case 2: dst->Data()[j] |= ((ch >> 2) & 0x0f); j++; if(current[i+1]!='=') { c = (unsigned char)((ch << 6) & 0xFF); dst->Append(&c,1); } break; case 3: dst->Data()[j] |= ch; j++; break; } } return j; } libdc0-0.3.24~svn3121/dclib/core/cmanager.h0000644000175000017500000000417011101144617017152 0ustar sikonsikon/*************************************************************************** cmanager.h - description ------------------- begin : Thu Jan 23 2003 copyright : (C) 2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CMANAGER_H #define CMANAGER_H /** *@author Mathias Küster * * This is dclib's main thread, almost everything runs on this thread. * Killing valknut with SIGSEGV to show the backtrace will list * all the threads and what they were doing, normally there is * just CManager, CAsyncDns and the main thread running the gui, * how many hubs or transfers does not matter. * * Making this class use more than one thread wouldn't be very useful, * CManager does not know what it is managing, and having * all the hubs running on one thread while all the transfers run on * another thread is only slightly better. */ #include #include #include #include #include class CManager : public CSingleton, public CThread { public: /** */ CManager(); /** */ virtual ~CManager(); /** */ void Add( _CCallback0 * callback ); /** */ void Remove( _CCallback0 * callback ); /** */ virtual void Thread(); private: /** */ CMutex m_CallbacksMutex; /** */ CList<_CCallback0> m_Callbacks; }; #endif libdc0-0.3.24~svn3121/dclib/cdownloadmanager.h0000644000175000017500000003156711137716153017775 0ustar sikonsikon/*************************************************************************** cdownloadmanager.h - description ------------------- begin : Don Mai 16 2002 copyright : (C) 2002-2004 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CDOWNLOADMANAGER_H #define CDOWNLOADMANAGER_H /** *@author Mathias Küster * * This handles the queue of files and sources, the list of running * transfers, and starting auto searches. * * The download manager is lacking multi threading, also segment size * is fixed, and the number of download slots is not normally limited. * * Upload bandwith limiting is present, although not present in * mainline DC++ at the time of writing this. * * Calculating the MD5 checksum of the first 10KiB is mostly * useless and completely obsolete, but basically very little * was ever done to dclib's downloading ability between 0.3.7 and 0.3.22. */ #include #include #include #include /* * eCloseType has moved to here so * that cconfig.h does not need to include cdownloadmanager.h */ #include #include #define MAX_FILE_PRIORITY 5 enum eShutdownState { essNONE, essSHUTDOWN, essSHUTDOWNREADY }; class CUserFileInfo { public: /** */ CUserFileInfo() { bMulti = false; }; /** */ ~CUserFileInfo() {}; /** */ eTransferWaitState eWaitState; /** */ eTransferFileState eFileState; /** */ CString sLocalFile; /** */ bool bMulti; }; class CExtraUserSlot { public: /** */ CExtraUserSlot() { iSlots = 1; bPermanent = false; }; /** */ ~CExtraUserSlot() {}; /** */ CString sNick; /** */ CString sHubName; /** */ int iSlots; /** */ bool bPermanent; }; class DCTransferBanObject { public: /** */ DCTransferBanObject() { m_nRequestCount = 0; m_tTime = 0; }; /** */ ~DCTransferBanObject() {}; /** */ CString m_sIP; /** */ unsigned int m_nRequestCount; /** */ time_t m_tTime; }; class CDownloadManagerInfo : public CDCMessage { public: /** */ CDownloadManagerInfo() : CDCMessage(DC_MESSAGE_DM_INFO) { rate_ul_settings = 0; rate_ul_operator = 0; rate_ul_user = 0; rate_ul_special = 0; rate_ul_rate_extra = 0; rate_dl = 0; slot_max = 0; slot_use_settings = 0; slot_use_operator = 0; slot_use_user = 0; slot_use_special = 0; slot_use_rate_extra = 0; }; /** */ virtual ~CDownloadManagerInfo() {}; /** */ ulonglong Rate() { return rate_ul_settings + rate_ul_operator + rate_ul_user + rate_ul_special + rate_ul_rate_extra; } /** */ ulonglong rate_ul_settings; /** */ ulonglong rate_ul_operator; /** */ ulonglong rate_ul_user; /** */ ulonglong rate_ul_special; /** */ ulonglong rate_ul_rate_extra; /** */ ulonglong rate_dl; /** */ int slot_max; /** the number of normal slots from main config settings used */ int slot_use_settings; /** slot usage for operators (after all other slots used up) */ int slot_use_operator; /** slot usage for users (extra normal slots granted to users, only used if normal slots used up) */ int slot_use_user; /** slot usage for special transfers e.g. minimum filelength (after all normal used up) */ int slot_use_special; /** the number of extra slots that have been given because total upload rate is below a limit */ int slot_use_rate_extra; CDownloadManagerInfo & operator = (const CDownloadManagerInfo & s) { rate_ul_settings = s.rate_ul_settings; rate_ul_operator = s.rate_ul_operator; rate_ul_user = s.rate_ul_user; rate_ul_special = s.rate_ul_special; rate_ul_rate_extra = s.rate_ul_rate_extra; rate_dl = s.rate_dl; slot_max = s.slot_max; slot_use_settings = s.slot_use_settings; slot_use_operator = s.slot_use_operator; slot_use_user = s.slot_use_user; slot_use_special = s.slot_use_special; slot_use_rate_extra = s.slot_use_rate_extra; return *this; }; }; enum eFileManagerStatus { efmsNONE=0, efmsIDLE, efmsCREATESHARELIST, efmsCREATESEARCHINDEX, efmsCREATEHASHLIST, efmsREBUILDLISTS, efmsVALIDATELEAVES }; class CFileManagerInfo : public CDCMessage { public: /** */ CFileManagerInfo() : CDCMessage(DC_MESSAGE_FM_INFO) { m_eFileManagerStatus = efmsNONE; m_nProgress = 0; }; /** */ virtual ~CFileManagerInfo() {}; /** */ enum eFileManagerStatus m_eFileManagerStatus; /** */ double m_nProgress; CFileManagerInfo & operator = (const CFileManagerInfo & s) { m_eFileManagerStatus = s.m_eFileManagerStatus; m_nProgress = s.m_nProgress; return *this; }; }; class CDCMessage; class CListen; class CDownloadQueue; class DCFileChunkObject; class DCTransferQueueObject; class DCTransferFileObject; class DCTransferWait; class _CCallback0; class CTransferObject { public: /** */ CTransferObject() { m_pTransfer = 0; m_UserDisconnectTimeout = time(0); } /** */ ~CTransferObject() { delete m_pTransfer; m_pTransfer = 0; } /** */ CTransfer * m_pTransfer; /** */ time_t m_UserDisconnectTimeout; }; class CDownloadManager : public CSingleton { public: /** */ CDownloadManager(); /** */ virtual ~CDownloadManager(); /** load the queue */ int DLM_LoadQueue(); /** save the queue */ int DLM_SaveQueue(); /** disconnect all transfers for a clean shutdown */ void DLM_Shutdown(); /** return the current shutdownstate */ eShutdownState DLM_ShutdownState() const { return m_eShutdownState; } /** add a extra slot to the user */ void DLM_AddUserSlot( CString nick, CString hubname, int slot, bool permanent = false ); /** return current used upload slots */ int DLM_UsedSlots() const { return DownloadManagerInfo.slot_use_settings; } /** */ bool DLM_TransferConnect( CString nick, CString hubname ); /** */ bool DLM_TransferClose( ulonglong transferid ); /** */ bool DLM_TransferSetRate( ulonglong transferid, ulonglong rate ); /** */ bool DLM_TransferGetRate( ulonglong transferid, ulonglong & rate ); /** */ CList * DLM_TransferGetList(); /** */ eDirection DLM_TransferDirection( ulonglong transferid ); /** * For filelists, localpath is abused to set the file/folder to * open the list at (when downloaded from search) and localrootpath * is abused to download a directory. */ void DLM_QueueAdd( CString nick, CString hubname, CString hubhost, CString remotename, CString localname, CString localpath, CString localrootpath, eltMedium medium, ulonglong size, ulonglong startposition, ulonglong endposition, CString hash, bool multi = false ); /** */ int DLM_QueueCheck( CString nick, CString hubname, CString hubhost, CString remotename, CString localname, CString localpath, CString localrootpath, eltMedium medium, ulonglong size, CString tth ); /** change the src-nick/hubname to dst-nick/hubname in the queue */ bool DLM_QueueEdit( CString srcnick, CString srchubname, CString dstnick, CString dsthubname, CString dsthubhost ); /** */ bool DLM_QueuePause( CString nick, CString hubname, CString remotefile, bool pause ); /** */ bool DLM_QueueRemove( CString nick, CString hubname, CString remotefile ); /** */ bool DLM_QueueRemove( CString localfile ); /** * 0 = directory removed * 1 = user/hub not found * 2 = no directories queued * 3 = that directory not queued */ int DLM_QueueRemoveDirectory( CString nick, CString hubname, CString directory ); /** */ bool DLM_QueueSetFilePriority( CString nick, CString hubname, CString remotefile, int priority ); /** */ bool DLM_QueueGetFileInfo( CString nick, CString hubname, CString hubhost, CString file, CUserFileInfo * UserFileInfo ); /** */ DCFileChunkObject * DLM_QueueGetFileChunk( CString file ); /** */ bool DLM_QueueUpdateHub( CString nick, CString hubname ); /** */ void DLM_QueueGetHub( CString nick, CString hubname, CList * list ); /** */ bool DLM_AddTransferRequest( CString nick, CString userhost, CString hubname, CString hubhost ); /** */ void DLM_AddTransferRequest( CString host, int port, bool crypto, CString hubname, CString hubhost ); /** */ bool DLM_GetDownloadManagerInfo( CDownloadManagerInfo * pinfo ); /** handle search */ bool DLM_HandleSearch( CMessageSearchResult * MessageSearchResult ); /** callback function - Called by CManager */ int Callback(); /** callback function */ virtual int DC_DownloadManagerCallBack( CDCMessage * ) { return -1; }; /** * It's not given to a CCallback it's just directly called by the * listen managers so it can take whatever parameters are necessary. */ int ListenCallbackHandler( int fd, bool crypto ); protected: /** */ int DM_TransferCallBack( CTransfer * Transfer, CDCMessage * DCMessage ); /** */ void SendFileManagerInfo( CFileManagerInfo * info ); private: /** */ friend class CFileManager; /** */ void SendFileInfo( DCTransferQueueObject * TransferObject, DCTransferFileObject * TransferFileItem = 0, bool bRemoveFile = false ); /** */ void SendTransferInfo( CTransfer * Transfer, bool remove = false ); /** */ void SendSlotInfo( CExtraUserSlot * Object ); /** */ void SendLogInfo( CString message, CTransfer * Transfer = 0 ); /** */ void SendDownloadManagerInfo( CDownloadManagerInfo * dminfo ); /** */ void SendTrafficInfo(); /** create a messagedmtransferobject from a transfer */ CMessageDMTransferObject * CreateDMTransferObject( CTransfer * Transfer ); /** */ void FileListDone( CTransfer * Transfer, DCTransferFileObject * TransferFileObject ); /** */ bool CheckUserSlot( CString nick, CString hubname ); /** */ void OptimizeChunks( DCFileChunkObject * FileChunkObject ); /** */ bool GetNextChunk( CString file, ulonglong * lstart, ulonglong * lend ); /** */ int UpdateChunk( CString file, ulonglong lstart, ulonglong lend, ulonglong lcurrent ); /** */ bool GetNewChunkEnd( CString file, ulonglong lstart, ulonglong lend, ulonglong lcurrent, ulonglong * lnstart, ulonglong *lnend ); /** */ void UpdateQueueList( time_t ttimeout ); /** */ void UpdateTransferList( time_t ttimeout ); /** */ void UpdateBanList( time_t ttimeout ); /** */ eDirection CheckWaitTransfer( CTransfer * Transfer ); /** */ bool UpdateWaitTransfer( CTransfer * Transfer, bool rem = false ); /** */ bool ChangeDirection( CTransfer * Transfer ); /** */ bool SetNextFile( CTransfer * Transfer ); /** */ bool SetDirection( CTransfer * Transfer ); /** */ bool SetFile( CTransfer * Transfer ); /** */ void UpdateFileState( CTransfer * Transfer, eTransferFileState eState ); /** */ bool CheckHash( CTransfer * Transfer ); /** */ bool RemoveQueueFile( CString nick, CString hubname, CString remotefile ); /** */ bool RemoveQueueFile( CString localfile ); /** */ bool InitSearch( time_t ttimeout ); /** */ ulonglong GetNewID(); /** */ eShutdownState m_eShutdownState; /** mutex for extra slots list */ CMutex * m_pExtraSlotsMutex; /** */ CList * m_pExtraUserSlotList; /** */ _CCallback0 * m_pCallback; /** */ CDownloadManagerInfo DownloadManagerInfo; /** */ CMutex TransferCallBackMutex; /** */ CMutex LogMutex; /** */ ulonglong m_nID; /** */ time_t m_tDownloadQueueTimeout; /** */ time_t m_tUpdateTransferTimeout; /** timeout for a new hubsearch */ time_t m_tHubSearchTimeout; /** timeout for a single search */ time_t m_tSearchTimeout; /** * The last time an additional upload slot was given because * total upload rate was below a limit. This is needed so that * these slots are only given max 1 per minute so that there * is enough time for the new transfer to be included in * the total upload rate. */ time_t m_tLastRateExtra; /** * The time old entries were removed from m_pTransferWaitList. */ time_t m_tWaitListCleaned; /** */ CDownloadQueue * m_pDownloadQueue; /** mutex for transfers list */ CMutex * m_pTransfersMutex; /** */ CStringList * m_pTransferList; /** mutex for transfer wait list */ CMutex * m_pWaitListMutex; /** */ CList * m_pTransferWaitList; /** mutex for transfer ban list */ CMutex * m_pBanListMutex; /** */ CStringList * m_pTransferBanList; /** * The search result list was never locked/unlocked. */ CList * m_pSearchList; /** */ CList * m_pSearchQueryList; }; #endif libdc0-0.3.24~svn3121/dclib/cmessagehandler.cpp0000644000175000017500000013225511105151432020130 0ustar sikonsikon/*************************************************************************** cmessagehandler.cpp - description ------------------- begin : Sun Sep 30 2001 copyright : (C) 2001-2005 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cmessagehandler.h" #include #include #include "core/cbytearray.h" #include "core/cbase64.h" #include "core/cnetaddr.h" #include "core/ciconv.h" // needed for remote encoding setting #include "cconfig.h" // parsed messages #define DC_S_MESSAGE_CHAT "<" #define DC_S_MESSAGE_SEARCH "$Search " #define DC_S_MESSAGE_MYINFO "$MyINFO " #define DC_S_MESSAGE_HELLO "$Hello " #define DC_S_MESSAGE_QUIT "$Quit " #define DC_S_MESSAGE_NICKLIST "$NickList " #define DC_S_MESSAGE_OPLIST "$OpList " #define DC_S_MESSAGE_CONNECTTOME "$ConnectToMe " #define DC_S_MESSAGE_KEY "$Key " #define DC_S_MESSAGE_HUBNAME "$HubName " #define DC_S_MESSAGE_LOCK "$Lock " #define DC_S_MESSAGE_TO "$To: " #define DC_S_MESSAGE_FORCEMOVE "$ForceMove " #define DC_S_MESSAGE_REVCONNECTTOME "$RevConnectToMe " #define DC_S_MESSAGE_SR "$SR " #define DC_S_MESSAGE_MYNICK "$MyNick " #define DC_S_MESSAGE_DIRECTION "$Direction " #define DC_S_MESSAGE_MAXEDOUT "$MaxedOut" // no free slots #define DC_S_MESSAGE_FILELENGTH "$FileLength " // recv. file #define DC_S_MESSAGE_GET "$Get " #define DC_S_MESSAGE_ERROR "$Error " #define DC_S_MESSAGE_GETLISTLEN "$GetListLen" #define DC_S_MESSAGE_VALIDATEDENIDE "$ValidateDenide" //hub login failed ... #define DC_S_MESSAGE_HUBISFULL "$HubIsFull" #define DC_S_MESSAGE_LISTLEN "$ListLen " #define DC_S_MESSAGE_SEND "$Send" #define DC_S_MESSAGE_GETINFO "$GetINFO " #define DC_S_MESSAGE_PING "$Ping" #define DC_S_MESSAGE_GETPASS "$GetPass" #define DC_S_MESSAGE_BADPASS "$BadPass" #define DC_S_MESSAGE_LOGEDIN "$LogedIn" #define DC_S_MESSAGE_CANCEL "$Cancel" #define DC_S_MESSAGE_CANCELED "$Canceled" #define DC_S_MESSAGE_SUPPORTS "$Supports " #define DC_S_MESSAGE_HUB_TOPIC "$HubTopic " #define DC_S_MESSAGE_GET_NET_INFO "$GetNetInfo" #define DC_S_MESSAGE_USER_IP "$UserIP " // ignored messages #define DC_S_MESSAGE_MULTISEARCH "$MultiSearch " #define DC_S_MESSAGE_USER_COMMAND "$UserCommand " // ??? ( $UserCommand 0 / $UserCommand 1 Read Help$<%[mynick]> +help|<%[mynick]> -help| ) // todo: parse #define DC_S_MESSAGE_AGE "age=" // age=NEWS ... ??? #define DC_S_EXTRA_DCPLUS "$DCPlus " #define DC_S_MESSAGE_UGETBLOCK "$UGetBlock " #define DC_S_MESSAGE_UGETZBLOCK "$UGetZBlock " // ZLIB compression messages #define DC_S_MESSAGE_GETZBLOCK "$GetZBlock " #define DC_S_MESSAGE_SENDING "$Sending " #define DC_S_MESSAGE_FAILED "$Failed " //ADCGet command and response #define DC_S_MESSAGE_ADCGET "$ADCGET " #define DC_S_MESSAGE_ADCSND "$ADCSND " // ZPipe message - just $ZOn| // Although CMessageHandler may be able to parse the $ZOn| itself // it can not handle any compressed data so there's no point // parsing it, CClient already found it and can deal with it itself #define DC_S_MESSAGE_ZON "$ZOn" CMessageHandler::CMessageHandler( CString remote ) { CString to = "UTF-8"; if ( CConfig::Instance() != 0 ) { to = CConfig::Instance()->GetLocalEncoding(); if ( remote.IsEmpty() ) { remote = CConfig::Instance()->GetRemoteEncoding(); } } m_pRemoteToLocal = new CIconv( remote, to ); m_pUTF8ToLocal = new CIconv( "UTF-8", to ); } CMessageHandler::~CMessageHandler() { delete m_pRemoteToLocal; m_pRemoteToLocal = 0; delete m_pUTF8ToLocal; m_pUTF8ToLocal = 0; } bool CMessageHandler::GetContent( const CString sMessage, const CString * sData, CString & sContent ) { if ( sData->StartsWith(sMessage) ) { sContent = sData->Mid(sMessage.Length(),sData->Length()-sMessage.Length()); return true; } return false; } /** */ eDCMessage CMessageHandler::Parse( const CString * sMessage, int & pointer, CDCMessage ** Object ) { CString t; CString sContent; int old_index,index; old_index = index = pointer; *Object = 0; index = sMessage->Find('|',index); if ( index >= 0 ) { pointer = index+1; t = sMessage->Mid(old_index,index-old_index); if ( t.IsEmpty() ) { if ( old_index != index ) { printf("!!!!!!! PARSER ERROR index: %d %d\n",old_index,index); printf("%s\n",sMessage->Data()); } return DC_MESSAGE_UNKNOWN; } /* * Commands that you get more often should be higher in the if statement. * Main change was moving ADCGET / ADCSND towards the top of the list, which * is more important now DC++ does segmented downloading. */ // check chat /* well '<' != '$' so "check another chat" can catch it */ /* if ( t.Data()[0] == '<' ) { sContent = t; *Object = ParseChat(sContent); return DC_MESSAGE_CHAT; } */ // check another chat if ( t.Data()[0] != '$' ) { sContent = t; *Object = ParseChat(sContent); return DC_MESSAGE_CHAT; } else if ( GetContent(DC_S_MESSAGE_SEARCH,&t,sContent) ) { *Object = ParseSearch(sContent); return DC_MESSAGE_SEARCH_FILE; } else if ( GetContent(DC_S_MESSAGE_MYINFO,&t,sContent) ) { *Object = ParseMyInfo(sContent); return DC_MESSAGE_MYINFO; } else if ( GetContent(DC_S_MESSAGE_SR,&t,sContent) ) { *Object = ParseSearchResult(sContent); return DC_MESSAGE_SEARCHRESULT; } else if ( GetContent(DC_S_MESSAGE_ADCGET,&t,sContent) ) { *Object = ParseADCGet(sContent); return DC_MESSAGE_ADCGET; } else if ( GetContent(DC_S_MESSAGE_ADCSND,&t,sContent) ) { *Object = ParseADCSnd(sContent); return DC_MESSAGE_ADCSND; } else if ( GetContent(DC_S_MESSAGE_HELLO,&t,sContent) ) { *Object = ParseHello(sContent); return DC_MESSAGE_HELLO; } else if ( GetContent(DC_S_MESSAGE_QUIT,&t,sContent) ) { *Object = ParseQuit(sContent); return DC_MESSAGE_QUIT; } else if ( GetContent(DC_S_MESSAGE_NICKLIST,&t,sContent) ) { *Object = ParseNickList(sContent); return DC_MESSAGE_NICKLIST; } else if ( GetContent(DC_S_MESSAGE_OPLIST,&t,sContent) ) { *Object = ParseOpList(sContent); return DC_MESSAGE_OPLIST; } else if ( GetContent(DC_S_MESSAGE_SUPPORTS,&t,sContent) ) { *Object = ParseSupports(sContent); return DC_MESSAGE_SUPPORTS; } else if ( GetContent(DC_S_MESSAGE_CONNECTTOME,&t,sContent) ) { *Object = ParseConnectToMe(sContent); return DC_MESSAGE_CONNECTTOME; } else if ( GetContent(DC_S_MESSAGE_REVCONNECTTOME,&t,sContent) ) { *Object = ParseRevConnectToMe(sContent); return DC_MESSAGE_REVCONNECTTOME; } else if ( GetContent(DC_S_MESSAGE_KEY,&t,sContent) ) { *Object = new CMessageKey(); return DC_MESSAGE_KEY; } else if ( GetContent(DC_S_MESSAGE_HUBNAME,&t,sContent) ) { *Object = ParseHubName(sContent); return DC_MESSAGE_HUBNAME; } else if ( GetContent(DC_S_MESSAGE_LOCK,&t,sContent) ) { *Object = ParseLock(sContent); return DC_MESSAGE_LOCK; } else if ( GetContent(DC_S_MESSAGE_TO,&t,sContent) ) { *Object = ParsePrivateChat(sContent); return DC_MESSAGE_PRIVATECHAT; } else if ( GetContent(DC_S_MESSAGE_FORCEMOVE,&t,sContent) ) { *Object = ParseForceMove(sContent); return DC_MESSAGE_FORCEMOVE; } else if ( GetContent(DC_S_MESSAGE_MYNICK,&t,sContent) ) { *Object = ParseMyNick(sContent); return DC_MESSAGE_MYNICK; } else if ( GetContent(DC_S_MESSAGE_DIRECTION,&t,sContent) ) { *Object = ParseDirection(sContent); return DC_MESSAGE_DIRECTION; } else if ( GetContent(DC_S_MESSAGE_FILELENGTH,&t,sContent) ) { *Object = ParseFileLength(sContent); return DC_MESSAGE_FILELENGTH; } else if ( GetContent(DC_S_MESSAGE_LISTLEN,&t,sContent) ) { *Object = ParseFileLength(sContent); return DC_MESSAGE_LISTLEN; } else if ( GetContent(DC_S_MESSAGE_GET,&t,sContent) ) { *Object = ParseGet(sContent); return DC_MESSAGE_GET; } else if ( GetContent(DC_S_MESSAGE_UGETBLOCK,&t,sContent) ) { *Object = ParseUGetBlock(sContent); return DC_MESSAGE_GET; } else if ( GetContent(DC_S_MESSAGE_UGETZBLOCK,&t,sContent) ) { *Object = ParseUGetZBlock(sContent); return DC_MESSAGE_GET; } else if ( GetContent(DC_S_MESSAGE_ERROR,&t,sContent) ) { *Object = ParseError(sContent); return DC_MESSAGE_ERROR; } else if ( GetContent(DC_S_MESSAGE_GETINFO,&t,sContent) ) { *Object = ParseGetInfo(sContent); return DC_MESSAGE_GETINFO; } else if ( GetContent(DC_S_MESSAGE_MAXEDOUT,&t,sContent) ) { *Object = new CMessageMaxedOut(); return DC_MESSAGE_MAXEDOUT; } else if ( GetContent(DC_S_MESSAGE_CANCEL,&t,sContent) ) { *Object = new CMessageCancel(); return DC_MESSAGE_CANCEL; } else if ( GetContent(DC_S_MESSAGE_CANCELED,&t,sContent) ) { *Object = new CMessageCanceled(); return DC_MESSAGE_CANCELED; } else if ( GetContent(DC_S_MESSAGE_SENDING,&t,sContent) ) { *Object = ParseSending(sContent); return DC_MESSAGE_SENDING; } else if ( GetContent(DC_S_MESSAGE_SEND,&t,sContent) ) { *Object = new CMessageSend(); return DC_MESSAGE_SEND; } else if ( GetContent(DC_S_MESSAGE_GETLISTLEN,&t,sContent) ) { *Object = new CMessageGetListLen(); return DC_MESSAGE_GETLISTLEN; } else if ( GetContent(DC_S_MESSAGE_VALIDATEDENIDE,&t,sContent) ) { *Object = new CMessageValidateDenide(); return DC_MESSAGE_VALIDATEDENIDE; } else if ( GetContent(DC_S_MESSAGE_HUBISFULL,&t,sContent) ) { *Object = new CMessageHubIsFull(); return DC_MESSAGE_HUBISFULL; } else if ( GetContent(DC_S_MESSAGE_PING,&t,sContent) ) { *Object = new CMessagePing(); return DC_MESSAGE_PING; } else if ( GetContent(DC_S_MESSAGE_GETPASS,&t,sContent) ) { *Object = new CMessageGetPass(); return DC_MESSAGE_GETPASS; } else if ( GetContent(DC_S_MESSAGE_BADPASS,&t,sContent) ) { *Object = new CMessageBadPass(); return DC_MESSAGE_BADPASS; } else if ( GetContent(DC_S_MESSAGE_LOGEDIN,&t,sContent) ) { *Object = ParseLogedIn(sContent); return DC_MESSAGE_LOGEDIN; } else if ( GetContent(DC_S_MESSAGE_HUB_TOPIC,&t,sContent) ) { *Object = ParseHubTopic(sContent); return DC_MESSAGE_HUB_TOPIC; } else if ( GetContent(DC_S_MESSAGE_GET_NET_INFO,&t,sContent) ) { *Object = new CMessageGetNetInfo(); return DC_MESSAGE_GET_NET_INFO; } else if ( GetContent(DC_S_MESSAGE_USER_COMMAND,&t,sContent) ) { *Object = ParseUserCommand(sContent); return DC_MESSAGE_USER_COMMAND; } else if ( GetContent(DC_S_MESSAGE_GETZBLOCK,&t,sContent) ) { *Object = ParseGetZBlock(sContent); return DC_MESSAGE_GET; } else if ( GetContent(DC_S_MESSAGE_FAILED,&t,sContent) ) { *Object = ParseError(sContent); return DC_MESSAGE_ERROR; } else if ( GetContent(DC_S_MESSAGE_USER_IP,&t,sContent) ) { *Object = ParseUserIP(sContent); return DC_MESSAGE_USERIP; } else { printf("!!!!!!!!!!!!!! unknown start "); printf("index: %d %d!!!!!!!!!!!!!!\n",old_index,index); printf("%s\n",t.Data()); printf("!!!!!!!!!!!!!! unknown end !!!!!!!!!!!!!!\n"); return DC_MESSAGE_UNKNOWN; } } else { // printf("%s\n",sMessage.Data()); } return DC_MESSAGE_PARSE_ERROR; } /** */ CDCMessage * CMessageHandler::ParseLock( const CString & sContent ) { CMessageLock * msg = new CMessageLock(); int i,i1; i = sContent.Find(" Pk="); // lock without pk if ( i < 0 ) { msg->m_sData = sContent; } else { msg->m_sData = sContent.Left(i); msg->m_sPK = sContent.Mid(i+4,sContent.Length()-i-4); } // printf("TR: '%s' '%s'\n",msg->m_sData.Data(),msg->m_sPK.Data()); if ( msg->m_sData.StartsWith("EXTENDEDPROTOCOL",16) ) { msg->m_bExtProtocol = true; } // DC++ client if ( msg->m_sPK.StartsWith("DCPLUSPLUS",10) ) { msg->m_eClientVersion = eucvDCPP; if ( (i = msg->m_sPK.Find("ABC")) != -1 ) { msg->m_sVersionString = msg->m_sPK.Mid(10,i-10); } } // DC++H Hub else if ( msg->m_sPK.StartsWith("DCHUBPLUSPLUS",13) ) { msg->m_eClientVersion = eucvDCHPP; if ( (i = msg->m_sPK.Find("ABC")) != -1 ) { msg->m_sVersionString = msg->m_sPK.Mid(13,i-13); } } // PtokaX Hub else if ( msg->m_sPK.Left(6).ToUpper() == "PTOKAX" ) { msg->m_eClientVersion = eucvPTOKAX; } // ZPoc Hub - removed typoed CHRISITAN, // apparently it could also be ZDCROOMSERVERAABC but i doubt anyone cares else if ( msg->m_sPK.StartsWith("ZPOC",4) ) { msg->m_eClientVersion = eucvZPOC; } // opendcd Hub else if ( msg->m_sPK.StartsWith("opendcd",7) ) { msg->m_eClientVersion = eucvOPENDCD; } // dclib based valknut else if ( msg->m_sPK.StartsWith("DCGUI",5) ) { msg->m_eClientVersion = eucvDCGUI; if ( (i = msg->m_sPK.Find("ABC")) != -1 ) { msg->m_sVersionString = msg->m_sPK.Mid(5,i-5); } } // microdc client else if ( msg->m_sPK.StartsWith("MICRODC",7) ) { msg->m_eClientVersion = eucvMICRODC; } // shakespeer client else if ( msg->m_sPK.StartsWith("ShakesPeer",10) ) { msg->m_eClientVersion = eucvSHAKESPEER; if ( (i = msg->m_sPK.Find("ABC")) != -1 ) { msg->m_sVersionString = msg->m_sPK.Mid(10,i-10); } } if ( msg->m_sVersionString.NotEmpty() ) { if ( (i=msg->m_sVersionString.Find('.')) != -1 ) { msg->m_nVersionMajor = msg->m_sVersionString.Mid(0,i).asINT(); i++; if ( (i1=msg->m_sVersionString.Find('.',i)) != -1 ) { msg->m_nVersionMinor = msg->m_sVersionString.Mid(i,msg->m_sVersionString.Length()-i1).asINT(); i=i1+1; msg->m_nVersionPatch = msg->m_sVersionString.Mid(i,msg->m_sVersionString.Length()-i).asINT(); } else { msg->m_nVersionMinor = msg->m_sVersionString.Mid(i,msg->m_sVersionString.Length()-i).asINT(); } } } return msg; } /** */ CDCMessage * CMessageHandler::ParseHello( const CString & sContent ) { CMessageHello * msg = new CMessageHello(); msg->m_sNick = m_pRemoteToLocal->encode(sContent); return msg; } /** */ CDCMessage * CMessageHandler::ParseMyNick( const CString & sContent ) { CMessageMyNick * msg = new CMessageMyNick(); msg->m_sNick = m_pRemoteToLocal->encode(sContent); return msg; } /** */ CDCMessage * CMessageHandler::ParseChat( const CString & sContent ) { CMessageChat * msg = new CMessageChat(); int i=-1,i1=-1; if ( (i=sContent.Find('<')) == 0 ) i1 = sContent.Find('>',i+1); if ( (i != -1) && (i1 != -1) ) { msg->m_sNick = m_pRemoteToLocal->encode(sContent.Mid(i+1,i1-1)); // check if after the '>' a space if ( sContent.Data()[i1+1] == ' ' ) i1++; msg->m_sMessage = m_pRemoteToLocal->encode(sContent.Mid(i1+1,sContent.Length()-i1-1)); } else { // no < nick > found ... use complete message msg->m_sMessage = m_pRemoteToLocal->encode(sContent); } // reconvert dcproto chars msg->m_sMessage = msg->m_sMessage.Replace( "$", "$" ); msg->m_sMessage = msg->m_sMessage.Replace( "|", "|" ); return msg; } /** */ CDCMessage * CMessageHandler::ParseMyInfo( const CString & sContent ) { /* $MyINFO $ALL xyzzy desc$ $DSL$ejs1920@yahoo.co.uk$35036485563$| */ /* $MyINFO $ALL strongdc_test desc$ $0.005$email$1123919289$| */ CMessageMyInfo * msg=0; CString s; int i,i1,i2,i3,i4,i5,i6; // dest e.g. $ALL if ( (i=sContent.Find(' ')) < 0 ) return 0; if ( (i1=sContent.Find(' ',i+1)) < 0 ) return 0; if ( (i2=sContent.Find('$',i1+1)) < 0 ) return 0; if ( (i3=sContent.Find('$',i2+1)) < 0 ) return 0; if ( (i4=sContent.Find('$',i3+1)) < 0 ) return 0; if ( (i5=sContent.Find('$',i4+1)) < 0 ) return 0; if ( (i6=sContent.Find('$',i5+1)) < 0 ) return 0; msg = new CMessageMyInfo(); msg->m_sNick = m_pRemoteToLocal->encode(sContent.Mid(i +1,i1-i -1)); msg->m_sUnknown = m_pRemoteToLocal->encode(sContent.Mid(i2+1,i3-i2-1)); // check user mode if ( (i4-i3-1) > 0 ) { const char c = sContent.Data()[i4-1]; if ( c & emsfNormal ) { msg->m_eAwayMode = euamNORMAL; } else if ( c & emsfAway ) { msg->m_eAwayMode = euamAWAY; } if ( c & emsfServer ) { msg->m_bServerFlag = true; } if ( c & emsfFireball ) { msg->m_bFireballFlag = true; } if ( c & emsfTLS ) { msg->m_bTLSFlag = true; } } s = sContent.Mid(i3+1,i4-i3-2); if ( s == "28.8Kbps" ) msg->m_eUserSpeed = eus288KBPS; else if ( s == "33.6Kbps" ) msg->m_eUserSpeed = eus288KBPS; else if ( s == "56Kbps" ) msg->m_eUserSpeed = eus56KBPS; else if ( s == "Modem" ) msg->m_eUserSpeed = eusMODEM; else if ( s == "ISDN" ) msg->m_eUserSpeed = eusISDN; else if ( s == "DSL" ) msg->m_eUserSpeed = eusDSL; else if ( s == "Satellite" ) msg->m_eUserSpeed = eusSATELLITE; else if ( s == "Cable" ) msg->m_eUserSpeed = eusCABLE; else if ( s == "LAN(T1)" ) msg->m_eUserSpeed = eusLANT1; else if ( s == "LAN(T3)" ) msg->m_eUserSpeed = eusLANT3; else if ( s == "Wireless" ) msg->m_eUserSpeed = eusWIRELESS; else if ( s == "Microwave" ) msg->m_eUserSpeed = eusMICROWAVE; else if ( s == "0.005" ) msg->m_eUserSpeed = eus0005; else if ( s == "0.01" ) msg->m_eUserSpeed = eus001; else if ( s == "0.02" ) msg->m_eUserSpeed = eus002; else if ( s == "0.05" ) msg->m_eUserSpeed = eus005; else if ( s == "0.1" ) msg->m_eUserSpeed = eus01; else if ( s == "0.2" ) msg->m_eUserSpeed = eus02; else if ( s == "0.5" ) msg->m_eUserSpeed = eus05; else if ( s == "1" ) msg->m_eUserSpeed = eus1; else if ( s == "2" ) msg->m_eUserSpeed = eus2; else if ( s == "5" ) msg->m_eUserSpeed = eus5; else if ( s == "10" ) msg->m_eUserSpeed = eus10; else if ( s == "20" ) msg->m_eUserSpeed = eus20; else if ( s == "50" ) msg->m_eUserSpeed = eus50; else if ( s == "100" ) msg->m_eUserSpeed = eus100; else if ( s == "1000" ) msg->m_eUserSpeed = eus1000; else msg->m_eUserSpeed = eusUNKNOWN; msg->m_sUserSpeed = s; msg->m_sEMail = m_pRemoteToLocal->encode(sContent.Mid(i4+1,i5-i4-1)); s = sContent.Mid(i5+1,i6-i5-1); msg->m_nShared = s.asULL(); // parse comment s = sContent.Mid(i1+1,i2-i1-1); // find version start tag if ( (i=s.FindRev("<++ ")) != -1 ) msg->m_eClientVersion = eucvDCPP; else if ( (i=s.FindRev("m_eClientVersion = eucvDCGUI; else if ( (i=s.FindRev("m_eClientVersion = eucvDCTC; else if ( (i=s.FindRev("m_eClientVersion = eucvNMDC; else if ( (i=s.FindRev("m_eClientVersion = eucvQUICKDC; else if ( (i=s.FindRev("m_eClientVersion = eucvOPERADC; else if ( (i=s.FindRev("m_eClientVersion = eucvSDDC; else if ( (i=s.FindRev("m_eClientVersion = eucvSTRGDCPP; else if ( (i=s.FindRev("m_eClientVersion = eucvRMDC; else if ( (i=s.FindRev("m_eClientVersion = eucvDCPRO; else if ( (i=s.FindRev("m_eClientVersion = eucvIDC; else if ( (i=s.FindRev("m_eClientVersion = eucvPERLDC; else if ( (i=s.FindRev("m_eClientVersion = eucvMICRODC; else if ( (i=s.FindRev("m_eClientVersion = eucvSHAKESPEER; else if ( (i=s.FindRev("<")) != -1 ) msg->m_eClientVersion = eucvUNKNOWN; else msg->m_eClientVersion = eucvNONE; msg->m_eClientMode = ecmPASSIVE; // find version end tag if ( (i!=-1) && ((i1=s.Find('>',i)) != -1) ) { msg->m_sComment = m_pRemoteToLocal->encode(s.Left(i)); msg->m_sVerComment = s.Mid(i,i1-i+1); // try to find some default tags for unknown clients if ( msg->m_eClientVersion == eucvUNKNOWN ) { if ( (msg->m_sVerComment.Find("V:") == -1) || (msg->m_sVerComment.Find("M:") == -1) ) { msg->m_eClientVersion = eucvNONE; } } if ( msg->m_eClientVersion != eucvNONE ) { // search for the active tag // A: active, P: passive 5: socks5 if ( msg->m_sVerComment.Find("M:A") != -1 ) { msg->m_eClientMode = ecmACTIVE; } } } // reset values if ( msg->m_eClientVersion == eucvNONE ) { msg->m_sComment = m_pRemoteToLocal->encode(s); msg->m_sVerComment.Empty(); } // set myinfo valid flag msg->m_bValid = true; return msg; } /** */ CDCMessage * CMessageHandler::ParseConnectToMe( const CString & sContent ) { CMessageConnectToMe * msg=0; CString s; int i,i1; if ( (i=sContent.Find(' ')) < 0 ) { return 0; } if ( (i1=sContent.Find(':',i+1)) < 0 ) { return 0; } msg = new CMessageConnectToMe(); msg->m_sNick = m_pRemoteToLocal->encode(sContent.Mid(0,i)); msg->m_sHost = sContent.Mid(i+1,i1-i-1); /* connect using TLS specified by 'S' appended to port */ if ( sContent.Data()[sContent.Length()-1] == 'S' ) { msg->m_bCrypto = true; s = sContent.Mid(i1+1,sContent.Length()-i1-2); } else { /* m_bCrypto set to false in CMessageConnectToMe constructor */ s = sContent.Mid(i1+1,sContent.Length()-i1-1); } if ( s.IsEmpty() ) { msg->m_nPort = 411; } else { msg->m_nPort = s.asINT(); // fix negative ports if ( msg->m_nPort < 0 ) msg->m_nPort += 65536; } return msg; } /** */ CDCMessage * CMessageHandler::ParseRevConnectToMe( const CString & sContent ) { CMessageRevConnectToMe * msg=0; int i; if ( (i=sContent.Find(' ')) < 0 ) { return 0; } msg = new CMessageRevConnectToMe(); msg->m_sDstNick = m_pRemoteToLocal->encode(sContent.Mid(0,i)); msg->m_sNick = m_pRemoteToLocal->encode(sContent.Mid(i+1,sContent.Length()-i-1)); return msg; } /** */ CDCMessage * CMessageHandler::ParseNickList( const CString & sContent ) { CMessageNickList * msg = new CMessageNickList(); int i = 0, i1 = 0; while ( (i=sContent.Find('$',i)) >= 0 ) { msg->m_NickList.Add(new CString(m_pRemoteToLocal->encode(sContent.Mid(i1,i-i1)))); i+=2; i1=i; } return msg; } /** */ CDCMessage * CMessageHandler::ParseOpList( const CString & sContent ) { CMessageOpList * msg = new CMessageOpList(); int i = 0, i1 = 0; while ( (i=sContent.Find('$',i)) >= 0 ) { msg->m_NickList.Add(new CString(m_pRemoteToLocal->encode(sContent.Mid(i1,i-i1)))); i+=2; i1=i; } return msg; } /** */ CDCMessage * CMessageHandler::ParseQuit( const CString & sContent ) { CMessageQuit * msg = new CMessageQuit(); msg->m_sNick = m_pRemoteToLocal->encode(sContent); return msg; } /** */ CDCMessage * CMessageHandler::ParseSearch( const CString & sContent ) { CMessageSearchFile * msg=0; CString s,s1; int t,i,i1,i2,i3,i4,i5,i6; // printf("Entering PARSESEARCH\n"); if ( (i=sContent.Find(' ')) < 0 ) return 0; if ( (i1=sContent.Find('?',i+1)) < 0 ) return 0; if ( (i2=sContent.Find('?',i1+1)) < 0 ) return 0; if ( (i3=sContent.Find('?',i2+1)) < 0 ) return 0; if ( (i4=sContent.Find('?',i3+1)) < 0 ) return 0; s = sContent.Left(i); if ( (i5 = s.Find(':')) < 0 ) { return 0; } msg = new CMessageSearchFile(); s1 = s.Left(i5+1); if ( s1 == "Hub:" ) { msg->m_bLocal = true; msg->m_sSource = m_pRemoteToLocal->encode(s.Mid(i5+1,s.Length()-i5-1)); } else { // parse the host string msg->m_bLocal = false; i6 = s.Find(':'); if ( i6 > 0 ) { s1 = s.Mid(i6+1,s.Length()-i6-1); } else { s1.Empty(); } if ( (i6 < 0) || (s1.IsEmpty()) ) { msg->m_sSource = s; msg->m_nPort = 411; } else { msg->m_sSource = s.Mid(0,i6); msg->m_nPort = s1.asINT(); // fix negative ports if ( msg->m_nPort < 0 ) msg->m_nPort += 65536; } } // sizelimit if ( sContent.Mid(i+1,i1-i-1) == "F" ) msg->m_bSizeLimit = false; else msg->m_bSizeLimit = true; // at most or at least if ( sContent.Mid(i1+1,i2-i1-1) == "F" ) msg->m_eSizeType = esstATLEAST; else msg->m_eSizeType = esstATMOST; // size s1 = sContent.Mid(i2+1,i3-i2-1); msg->m_nSize = s1.asULL(); // type s1 = sContent.Mid(i3+1,i4-i3-1); t = s1.asINT(); switch(t) { case 1: msg->m_eFileType = eftALL; break; case 2: msg->m_eFileType = eftMP3; break; case 3: msg->m_eFileType = eftARCHIVE; break; case 4: msg->m_eFileType = eftDOCUMENT; break; case 5: msg->m_eFileType = eftAPPLICATION; break; case 6: msg->m_eFileType = eftPICTURE; break; case 7: msg->m_eFileType = eftVIDEO; break; case 8: msg->m_eFileType = eftFOLDER; break; case 9: msg->m_eFileType = eftHASH; break; default: msg->m_eFileType = eftUNKNOWN; break; } // the search string s = m_pRemoteToLocal->encode(sContent.Mid(i4+1,sContent.Length()-i4-1)); if ( msg->m_eFileType == eftHASH ) { s = s.Mid(4); } // check if ext proto /* STRING: EXT BASE64: XYEXT: X : PADDING TO EVEN LENGTH Y : UNSIGNED CHAR <> 0 */ msg->m_bExtended = false; if ( (i=s.Find("EXT")) == 0 ) { CByteArray in,out; s1 = s.Mid(i+3,s.Length()-i-3); in.SetSize(0); in.Append( (unsigned char*)s1.Data(), s1.Length()+1 ); i = CBase64::Decode(&out,&in); if ( i > 5 ) { s1.Set( (char*)out.Data(), out.Size() ); i=s1.Find("EXT:"); if ( (i == 1) || (i==2) ) { printf("Found ext decode: '%s'\n",s1.Data()); s = s1.Mid(i+4,s1.Length()-i-4); msg->m_bExtended = true; } } } s = s.Replace('$'," "); s = s.Replace("$","$"); msg->m_sString = s.Replace("|","|"); // printf("Quitting PARSESEARCH\n"); return msg; } /** */ CDCMessage * CMessageHandler::ParseSearchResult( const CString & sContent ) { int i; if ( (i=sContent.Find(0x05)) < 0 ) return 0; if ( sContent.Find(0x05,i+1) < 0 ) { return ParseSearchResultFolder(sContent); } else { return ParseSearchResultFile(sContent); } } /** * $SR <0x05> /<0x05> ()| * i i1 i2 i3 */ CDCMessage * CMessageHandler::ParseSearchResultFile( const CString & sContent ) { CMessageSearchResult * msg=0; CString s; int i,i1,i2,i3; /* for(i=0;im_sNick = m_pRemoteToLocal->encode(sContent.Mid(0,i)); msg->m_sFile = m_pRemoteToLocal->encode(sContent.Mid(i+1,i1-i-1)); s = sContent.Mid(i1+1,i2-i1-1); msg->m_nSize = s.asULL(); // parse the user slots s = sContent.Mid(i2+1,i3-i2-1); msg->m_nFreeSlot = 0; msg->m_nMaxSlot = 0; if ( (i1 = s.Find('/')) != -1 ) { msg->m_nFreeSlot = s.Mid(0,i1).asUINT(); msg->m_nMaxSlot = s.Mid(i1+1,s.Length()-i1-1).asUINT(); } s = sContent.Mid(i3+1,sContent.Length()-i3-1); if ( s.NotEmpty() ) { if ( (i1 = s.FindRev(')')) != -1 ) { if ( (i2 = s.FindRev('('),i1-1) != -1 ) { if ( i2 > 0 ) i2--; // remove space " (" msg->m_sHubName = m_pRemoteToLocal->encode(s.Mid(0,i2)); msg->m_sHubHost = s.Mid(i2+2,i1-i2-2); } } } // check negative ports CString ip; unsigned int port; CNetAddr::ParseHost( msg->m_sHubHost, ip, port ); msg->m_sHubHost = ip; if ( port != 0 ) { msg->m_sHubHost += ':'; msg->m_sHubHost += CString::number(port); } // parse special content in hubname if ( msg->m_sHubName.StartsWith("TTH:",4) ) { // tiger tree hash msg->m_sHash = msg->m_sHubName.Mid(4); // set dummy hubname msg->m_sHubName = msg->m_sHubHost; } /* printf("%s\n%s | %s | %s | %s | %s | %s\n",\ sContent.Data(), msg->sNick.Data(), msg->sFile.Data(), msg->sSize.Data(), msg->sSlot.Data(), msg->sHubName.Data(), msg->sHubHost.Data() );*/ msg->m_bFolder = false; return msg; } /** * $SR /<0x05> ()| * s1 s2 i1 */ CDCMessage * CMessageHandler::ParseSearchResultFolder( const CString & sContent ) { CMessageSearchResult * msg=0; CString s; int s1,s2,i1,slash,openBracket,closeBracket; /* for(i=0;im_sNick = m_pRemoteToLocal->encode(sContent.Mid(0,s1)); msg->m_sFile = m_pRemoteToLocal->encode(sContent.Mid(s1+1,s2-s1-1)); msg->m_nSize = 0; // parse the user slots s = sContent.Mid(s2+1,i1-s2-1); msg->m_nFreeSlot = 0; msg->m_nMaxSlot = 0; if ( (slash = s.Find('/')) != -1 ) { msg->m_nFreeSlot = s.Mid(0,slash).asUINT(); msg->m_nMaxSlot = s.Mid(slash+1,s.Length()-slash-1).asUINT(); } s = sContent.Mid(i1+1,sContent.Length()-i1-1); if ( s.NotEmpty() ) { if ( (closeBracket = s.FindRev(')')) != -1 ) { if ( (openBracket = s.FindRev('('),closeBracket-1) != -1 ) { if ( openBracket > 0 ) openBracket--; // remove space " (" msg->m_sHubName = m_pRemoteToLocal->encode(s.Mid(0,openBracket)); msg->m_sHubHost = s.Mid(openBracket+2,closeBracket-openBracket-2); } } } // check negative ports CString ip; unsigned int port; CNetAddr::ParseHost( msg->m_sHubHost, ip, port ); msg->m_sHubHost = ip; if ( port != 0 ) { msg->m_sHubHost += ':'; msg->m_sHubHost += CString::number(port); } // parse special content in hubname if ( msg->m_sHubName.StartsWith("TTH:",4) ) { // tiger tree hash msg->m_sHash = msg->m_sHubName.Mid(4); // set dummy hubname msg->m_sHubName = msg->m_sHubHost; } /* printf("%s\n%s : %s : %l : %s : %s : %s : %l : %l\n",\ sContent.Data(), msg->m_sNick.Data(), msg->m_sFile.Data(), msg->m_nSize, msg->m_sHubName.Data(), msg->m_sHubHost.Data(), msg->m_sHash.Data(), msg->m_nFreeSlot, msg->m_nMaxSlot ); */ msg->m_bFolder = true; return msg; } /** */ CDCMessage * CMessageHandler::ParsePrivateChat( const CString & sContent ) { /* $To: target nick From: source nick $ message text| */ /* "$To: " and "|" are already removed leaving */ /* target nick From: source nick $ message text */ int p1 = sContent.Find( " From:", 0 ); if ( p1 == -1 ) { return 0; } int p2 = sContent.Find( '$', p1+6 ); if ( p2 == -1 ) { return 0; } CMessagePrivateChat * msg = new CMessagePrivateChat(); msg->m_sDstNick = m_pRemoteToLocal->encode( sContent.Mid(0,p1) ); msg->m_sSrcNick = m_pRemoteToLocal->encode( sContent.Mid(p1+7,p2-p1-8) ); CString s = sContent.Mid(p2+1,sContent.Length()-p2-1); p1 = s.Find('<'); p2 = s.Find('>',p1+1); if ( (p1==-1) || (p2==-1) ) { msg->m_sMessage = m_pRemoteToLocal->encode(s); } else { msg->m_sMultiSrcNick = m_pRemoteToLocal->encode(s.Mid(p1+1,p2-p1-1)); if ( (s.Length() > p2+1) && (s.Data()[p2+1] == ' ') ) { ++p2; } msg->m_sMessage = m_pRemoteToLocal->encode(s.Mid(p2+1,s.Length()-p2-1)); } // reconvert dcproto chars msg->m_sMessage = msg->m_sMessage.Replace( "$", "$" ); msg->m_sMessage = msg->m_sMessage.Replace( "|", "|" ); /* printf("%s\n%s\n%s\n%s\n",\ sContent.Data(), msg->sNick.Data(), msg->sFrom.Data(), msg->sString.Data() ); */ return msg; } /** */ CDCMessage * CMessageHandler::ParseForceMove( const CString & sContent ) { if ( sContent.IsEmpty() ) { return 0; } int i = sContent.Find(':'); CString s; CMessageForceMove * msg = new CMessageForceMove(); if ( i > 0 ) { s = sContent.Mid(i+1,sContent.Length()-i-1); } if ( (i < 0) || (s.IsEmpty()) ) { msg->m_sHost = sContent; msg->m_nPort = 411; } else { msg->m_sHost = sContent.Mid(0,i); msg->m_nPort = s.asINT(); // fix negative ports if ( msg->m_nPort < 0 ) msg->m_nPort += 65536; } return msg; } /** */ CDCMessage * CMessageHandler::ParseDirection( const CString & sContent ) { int i; if ( (i=sContent.Find(' ')) < 0 ) return 0; CMessageDirection * msg = new CMessageDirection(); CString s = sContent.Mid(0,i); if ( s == "Upload" ) msg->m_eDirection = edUPLOAD; else if ( s == "Download" ) msg->m_eDirection = edDOWNLOAD; else msg->m_eDirection = edNONE; s = sContent.Mid(i+1,sContent.Length()-i-1); if ( s.IsEmpty() ) msg->m_nLevel = 0; else msg->m_nLevel = s.asINT(); return msg; } /** */ CDCMessage * CMessageHandler::ParseFileLength( const CString & sContent ) { CMessageFileLength * msg = new CMessageFileLength(); if ( sContent.IsEmpty() ) msg->m_nFileLength = 0; else msg->m_nFileLength = sContent.asULL(); return msg; } /** */ CDCMessage * CMessageHandler::ParseGet( const CString & sContent ) { int last,secondlast; CString pos, size; CMessageGet * msg = 0; // last $ will usually be 1-starting based file position // but will be size if using valknut CHUNK extension last = sContent.FindRev('$'); if ( last < 0 ) { return 0; } msg = new CMessageGet(); // second last $ may be in the filename // but will be file position if using valknut CHUNK extension secondlast = sContent.FindRev('$',last-1); if ( secondlast < 0 ) { pos = sContent.Mid(last+1); secondlast = last; } else { size = sContent.Mid(last+1); pos = sContent.Mid(secondlast+1,last-(secondlast+1)); if ( pos.asULL() == 0 ) // $Get starts at 1 { pos = size; size.Empty(); secondlast = last; } } msg->m_sFilename = m_pRemoteToLocal->encode(sContent.Mid(0,secondlast)); msg->m_nPos = pos.asULL(); if ( size.NotEmpty() ) { msg->m_nSize = size.asULL(); } //printf( "name=%s pos=%llu size=%llu\n", msg->m_sFilename.Data(), msg->m_nPos, msg->m_nSize ); return msg; } /** */ CDCMessage * CMessageHandler::ParseUGetBlock( const CString & sContent ) { /* This parser is copied and pasted into ParseGetZBlock */ int i,i1; CString s; CMessageGet * msg = new CMessageGet(); i = sContent.Find(' '); i1= sContent.Find(' ',i+1); msg->m_nPos = sContent.Mid(0,i).asULL(); msg->m_nSize = sContent.Mid(i+1,i1-i).asULL(); s = sContent.Mid(i1+1,sContent.Length()-i1-1); /* encode the filename from UTF-8 to local encoding */ msg->m_sFilename = m_pUTF8ToLocal->encode(s); msg->m_bUGet = true; // fix start position msg->m_nPos++; /* printf("UGET '%s'\n%llu %llu\n'%s'\n", sContent.Data(), msg->m_nPos, msg->m_nSize, msg->m_sFilename.Data()); */ return msg; } /** */ CDCMessage * CMessageHandler::ParseUGetZBlock( const CString & sContent ) { CMessageGet * msg = (CMessageGet*) ParseUGetBlock(sContent); msg->m_bZLib = true; return msg; } /** */ CDCMessage * CMessageHandler::ParseError( const CString & sContent ) { CMessageError * msg = new CMessageError(); msg->m_sError = m_pRemoteToLocal->encode(sContent); return msg; } /** */ CDCMessage * CMessageHandler::ParseHubName( const CString & sContent ) { CMessageHubName * msg = new CMessageHubName(); msg->m_sHubName = m_pRemoteToLocal->encode(sContent); return msg; } /** */ CDCMessage * CMessageHandler::ParseGetInfo( const CString & sContent ) { int i; if ( (i=sContent.Find(' ')) < 0 ) { return 0; } CMessageGetInfo * msg = new CMessageGetInfo(); msg->m_sDstNick = m_pRemoteToLocal->encode(sContent.Mid(0,i)); msg->m_sSrcNick = m_pRemoteToLocal->encode(sContent.Mid(i+1,sContent.Length()-i-1)); return msg; } /** */ CDCMessage * CMessageHandler::ParseLogedIn( CString sContent ) { CMessageLogedIn * msg = new CMessageLogedIn(); // remove the space if ( sContent.NotEmpty() && (sContent.Data()[0] == ' ') ) { sContent = sContent.Mid(1,sContent.Length()-1); } msg->m_sNick = m_pRemoteToLocal->encode(sContent); return msg; } #define DC_SUPPORT_TAG_MINISLOTS "MiniSlots " #define DC_SUPPORT_TAG_XMLBZLIST "XmlBZList " #define DC_SUPPORT_TAG_ADCGET "ADCGet " #define DC_SUPPORT_TAG_TTHL "TTHL " #define DC_SUPPORT_TAG_TTHF "TTHF " #define DC_SUPPORT_TAG_ZLIG "ZLIG " /* These are obsolete and should not be used. */ #define DC_SUPPORT_TAG_GETZBLOCK "GetZBlock " #define DC_SUPPORT_TAG_BZLIST "BZList " /* These are obsolete dclib extensions and should not be used. */ #define DC_SUPPORT_TAG_SSL "SSL " #define DC_SUPPORT_TAG_CHUNK "CHUNK " /* These are all ignored - either unused client extensions or hub extensions. */ #define DC_SUPPORT_TAG_GETTESTZBLOCK "GetTestZBlock " #define DC_SUPPORT_TAG_USER_CMD "UserCommand " #define DC_SUPPORT_TAG_NOGETINFO "NoGetINFO " #define DC_SUPPORT_TAG_USERIP "UserIP " #define DC_SUPPORT_TAG_USERIP2 "UserIP2 " #define DC_SUPPORT_TAG_XRULES "XRules " #define DC_SUPPORT_TAG_BOTINFO "BotINFO " #define DC_SUPPORT_TAG_BOTINFO_2 "BotInfo " #define DC_SUPPORT_TAG_NOHELLO "NoHello " #define DC_SUPPORT_TAG_OPPLUS "OpPlus " #define DC_SUPPORT_TAG_MCTO "MCTo " #define DC_SUPPORT_TAG_BOTLIST "BotList " #define DC_SUPPORT_TAG_CLIENTID "ClientID " #define DC_SUPPORT_TAG_SECUREDEXECUTOR "SecuredExecutor " #define DC_SUPPORT_TAG_FEED "Feed " #define DC_SUPPORT_TAG_ZLINE "ZLine " #define DC_SUPPORT_TAG_ZPIPE0 "ZPipe0 " #define DC_SUPPORT_TAG_CDM "CDM " #define DC_SUPPORT_TAG_GETCID "GetCID " #define DC_SUPPORT_TAG_BANMSG "BanMsg " /** */ CDCMessage * CMessageHandler::ParseSupports( CString sContent ) { int i = 0, i1 = 0; CString s; if ( sContent.Right(1) != " " ) { sContent += ' '; } CMessageSupports * msg = new CMessageSupports(); msg->m_sContent = sContent; while( (i1=sContent.Find(' ',i)) != -1 ) { ++i1; s = sContent.Mid(i,i1-i); if ( s == DC_SUPPORT_TAG_MINISLOTS ) { msg->m_bMiniSlots = true; } else if ( s == DC_SUPPORT_TAG_XMLBZLIST ) { msg->m_bXMLBZList = true; } else if ( s == DC_SUPPORT_TAG_ADCGET ) { msg->m_bADCGet = true; } else if ( s == DC_SUPPORT_TAG_TTHL ) { msg->m_bTTHL = true; } else if ( s == DC_SUPPORT_TAG_TTHF ) { msg->m_bTTHF = true; } else if ( s == DC_SUPPORT_TAG_ZLIG ) { msg->m_bZLIG = true; } else if ( s == DC_SUPPORT_TAG_GETZBLOCK ) /* obsolete */ { msg->m_bZBlock = true; } else if ( s == DC_SUPPORT_TAG_BZLIST ) /* obsolete */ { msg->m_bBZList = true; } else if ( s == DC_SUPPORT_TAG_SSL ) /* obsolete dclib specific */ { msg->m_bSSL = true; } else if ( s == DC_SUPPORT_TAG_CHUNK ) /* obsolete dclib specific */ { msg->m_bChunk = true; } #if 0 else if ( s == DC_SUPPORT_TAG_GETTESTZBLOCK ) { // ignore } else if ( s == DC_SUPPORT_TAG_USER_CMD ) { // ignore } else if ( s == DC_SUPPORT_TAG_NOGETINFO ) { // ignore } else if ( s == DC_SUPPORT_TAG_USERIP ) { // ignore } else if ( s == DC_SUPPORT_TAG_USERIP2 ) { // ignore } else if ( s == DC_SUPPORT_TAG_XRULES ) { // ignore } else if ( s == DC_SUPPORT_TAG_BOTINFO ) { // ignore } else if ( s == DC_SUPPORT_TAG_BOTINFO_2 ) { // ignore } else if ( s == DC_SUPPORT_TAG_NOHELLO ) { // ignore } else if ( s == DC_SUPPORT_TAG_OPPLUS ) { // ignore } else if ( s == DC_SUPPORT_TAG_MCTO ) { // ignore } else if ( s == DC_SUPPORT_TAG_BOTLIST ) { // ignore } else if ( s == DC_SUPPORT_TAG_CLIENTID ) { // ignore } else if ( s == DC_SUPPORT_TAG_SECUREDEXECUTOR ) { // ignore } else if ( s == DC_SUPPORT_TAG_FEED ) { // ignore } else if ( s == DC_SUPPORT_TAG_ZLINE ) { // ignore } else if ( s == DC_SUPPORT_TAG_ZPIPE0 ) { // ignore } else if ( s == DC_SUPPORT_TAG_CDM ) { // ignore } else if ( s == DC_SUPPORT_TAG_GETCID ) { // ignore } else if ( s == DC_SUPPORT_TAG_BANMSG ) { // ignore } else { printf("Unknown support tag: '%s'\n",s.Data()); } #endif i = i1; } return msg; } /** */ CDCMessage * CMessageHandler::ParseHubTopic( const CString & sContent ) { CMessageHubTopic * msg = new CMessageHubTopic(); msg->m_sTopic = m_pRemoteToLocal->encode(sContent); return msg; } /** $UserCommand 1 2 Menu\SubMenu\SayHello $<%[mynick]> hello|| */ CDCMessage * CMessageHandler::ParseUserCommand( const CString & sContent ) { int type = -1; int context = -1; CString name; CString command; int i = sContent.Find(' '); if ( i > 0 ) { type = sContent.Mid(0,i).asINT(); int i2 = sContent.Find(' ',i+1); if ( i2 > 0 ) { context = sContent.Mid(i+1,i2-i-1).asINT(); int i3 = sContent.Find('$',i2+1); if ( i3 > 0 ) { name = sContent.Mid(i2+1,i3-i2-1); command = sContent.Mid(i3+1); } else { name = sContent.Mid(i2+1); } } else { context = sContent.Mid(i+1).asINT(); } } else { type = sContent.asINT(); } if ( name.Right(1) == " " ) { name = name.Left(name.Length()-1); } name = m_pRemoteToLocal->encode(name); command = m_pRemoteToLocal->encode(command); command = command.Replace( "$", "$" ); command = command.Replace( "|", "|" ); // printf("UserCommand type=%d context=%d name='%s' command='%s'\n",type,context,name.Data(),command.Data()); CMessageUserCommand * msg = new CMessageUserCommand(); msg->type = type; msg->context = context; msg->name = name; msg->command = command; return msg; } /** */ CDCMessage * CMessageHandler::ParseGetZBlock( const CString & sContent ) { /* This parser is copied and pasted from ParseUGetBlock */ int i,i1; CString s; CMessageGet * msg = new CMessageGet(); i = sContent.Find(' '); i1= sContent.Find(' ',i+1); msg->m_nPos = sContent.Mid(0,i).asULL(); msg->m_nSize = sContent.Mid(i+1,i1-i).asULL(); s = sContent.Mid(i1+1,sContent.Length()-i1-1); /* encode the filename from remote to local encoding */ msg->m_sFilename = m_pRemoteToLocal->encode(s); msg->m_bZLib = true; // fix start position msg->m_nPos++; /* printf("GETZBLOCK '%s'\n%llu %llu\n'%s'\n", sContent.Data(), msg->m_nPos, msg->m_nSize, msg->m_sFilename.Data()); */ return msg; } /** */ CDCMessage * CMessageHandler::ParseSending( const CString & sContent ) { CMessageSending * msg = new CMessageSending(); if ( sContent.IsEmpty() ) msg->m_nLength = 0; else msg->m_nLength = sContent.asULL(); return msg; } /** $ADCGET file TTH/PPUROLR2WSYTGPLCM3KV4V6LJC36SCTFQJFDJKA 0 1154 ZL1| */ CDCMessage * CMessageHandler::ParseADCGet( const CString & sContent ) { //printf("sContent=\"%s\"\n", sContent.Data()); CMessageADCGet * msg = new CMessageADCGet(); int i = sContent.Find(' '); CString s = sContent.Mid(0,i); if ( s == "file" ) { msg->m_eADCType = eAdcFile; } else if ( s == "tthl" ) { msg->m_eADCType = eAdcTTHL; } else if ( s == "list" ) { msg->m_eADCType = eAdcList; } else { delete msg; printf("CMessageHandler::ParseADCGet: Unknown ADCGET type '%s'\n",s.Data()); return 0; } s = sContent.Mid(i+1,sContent.Length()-i-1); if (s.Right(4).ToUpper() == " ZL1") { msg->m_bZlib = true; s = s.Mid(0, s.Length() - 4); } else { msg->m_bZlib = false; } i = s.FindRev(' '); msg->m_nSize = s.Mid(i, s.Length() - i).asLONGLONG(); s = s.Mid(0, i); i = s.FindRev(' '); msg->m_nPos = s.Mid(i, s.Length() - i).asULL(); s = s.Mid(0, i); if ( s.StartsWith("TTH/",4) ) { msg->m_sTTH = s.Mid(4); } else { // unescape spaces s = s.Replace( "\\ ", " " ); msg->m_sFile = m_pUTF8ToLocal->encode(s); } //printf("ADCGET Type=%s TTH=%s Pos=%lld Size=%lld Zlib=%d\n File=%s\n", msg->m_sType.Data(), // msg->m_sTTH.Data(), msg->m_nPos, msg->m_nSize, msg->m_bZlib, msg->m_sFile.Data() ); return msg; } /** $ADCSND file TTH/PPUROLR2WSYTGPLCM3KV4V6LJC36SCTFQJFDJKA 0 1154 ZL1| */ CDCMessage * CMessageHandler::ParseADCSnd( const CString & sContent ) { //printf("sContent=\"%s\"\n", sContent.Data()); CMessageADCSnd * msg = new CMessageADCSnd(); int i = sContent.Find(' '); CString s = sContent.Mid(0,i); if ( s == "file" ) { msg->m_eADCType = eAdcFile; } else if ( s == "tthl" ) { msg->m_eADCType = eAdcTTHL; } else if ( s == "list" ) { msg->m_eADCType = eAdcList; } else { delete msg; printf("CMessageHandler::ParseADCGet: Unknown ADCSND type '%s'\n",s.Data()); return 0; } s = sContent.Mid(i+1,sContent.Length()-i-1); if (s.Right(4).ToUpper() == " ZL1") { msg->m_bZlib = true; s = s.Mid(0, s.Length() - 4); } else { msg->m_bZlib = false; } i = s.FindRev(' '); msg->m_nSize = s.Mid(i, s.Length() - i).asLONGLONG(); s = s.Mid(0, i); i = s.FindRev(' '); msg->m_nPos = s.Mid(i, s.Length() - i).asULL(); s = s.Mid(0, i); if ( s.StartsWith("TTH/",4) ) { msg->m_sTTH = s.Mid(4); } else { // unescape spaces s = s.Replace( "\\ ", " " ); msg->m_sFile = m_pUTF8ToLocal->encode(s); } //printf("ADCSND Type=%s TTH=%s Pos=%lld Size=%lld Zlib=%d File=%d\n", msg->m_sType.Data(), // msg->m_sTTH.Data(), msg->m_nPos, msg->m_nSize, msg->m_bZlib, msg->m_sFile.Data() ); return msg; } /** * $UserIP nick ip| * $UserIP nick1 ip1$$nick2 ip2$$| */ CDCMessage * CMessageHandler::ParseUserIP( CString sContent ) { int middle = sContent.Find(' '); if ( middle < 0 ) { return 0; } CMessageUserIP * msg = new CMessageUserIP(); if ( sContent.Right(2) != "$$" ) { sContent += "$$"; } int list_sep = sContent.Find("$$"); int start = 0; while ( (list_sep != -1) && (middle != -1) ) { msg->m_lNicks.push_back( m_pRemoteToLocal->encode(sContent.Mid(start,middle-start)) ); ++middle; msg->m_lIPs.push_back( sContent.Mid( middle, list_sep - middle ) ); start = list_sep + 2; list_sep = sContent.Find("$$",start); middle = sContent.Find(' ',start); } return msg; } libdc0-0.3.24~svn3121/dclib/cclientssl.cpp0000644000175000017500000002363611074130777017166 0ustar sikonsikon/*************************************************************************** cclientssl.cpp - description ------------------- begin : Sat Dec 7 2002 copyright : (C) 2002-2003 by Mathias Küster email : mathen@users.berlios.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cclientssl.h" #include #include #include "cclient.h" #include "core/types.h" // needed to parse tag to check version for backwards compatibility #include "cutils.h" #include "dclib-ssl-use.h" // define DEBUG_SSL_CHAT 1 /** */ CClientSSL::CClientSSL() { m_pCryptPrivateMessageList = new CStringList(); } /** */ CClientSSL::~CClientSSL() { delete m_pCryptPrivateMessageList; m_pCryptPrivateMessageList = 0; } #if DCLIB_HAS_SSL == 1 /** */ void CClientSSL::PrivateChat( CClient * client, CMessagePrivateChat * msg ) { /** * STATE: * * CLIENT1 CLIENT2 * none S0 none S0 * send request S0 --> receive req S1 * receive response S1 <-- send response S1 * send pk S2 --> receive pk S2 * receive pk S2 <-- send pk S2 * send sk S3 <-> send sk S3 * crypted <*> crypted * */ CSSLObject * SSLObject = 0; #ifdef DEBUG_SSL_CHAT printf("msg->m_sMessage=%s ", msg->m_sMessage.Data()); if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) { printf("no SSLObject\n"); } else { printf("m_bHandshakeState=%d\n", SSLObject->m_bHandshakeState); } SSLObject = 0; #endif if ( msg->m_sMessage == "" ) { // send response if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) m_pCryptPrivateMessageList->Add( msg->m_sSrcNick, SSLObject = new CSSLObject() ); bool isOldVersion = false; CMessageMyInfo remoteinfo; client->UserList()->GetUserMyInfo( msg->m_sSrcNick, &remoteinfo ); if ( remoteinfo.m_eClientVersion == eucvDCGUI ) { int major = 0; int minor = 0; int micro = 0; if ( CUtils::ParseVersionTag( remoteinfo.m_sVerComment, major, minor, micro ) ) { if ( (major > 0) || ((major == 0) && (minor > 3)) || ((major == 0) && (minor == 3) && (micro >= 14)) ) { // dclib 0.3.14 or higher, OK } else { #ifdef DEBUG_SSL_CHAT printf("Detected dclib <= 0.3.13, using old handshaking\n"); #endif isOldVersion = true; } } } if ( SSLObject->m_bHandshakeState != 0 ) { if ( isOldVersion ) { if ( SSLObject->m_bHandshakeState == 1 ) { #ifdef DEBUG_SSL_CHAT printf(" in wrong state %d, adjusting to 0 (old version)\n", SSLObject->m_bHandshakeState); #endif SSLObject->m_bHandshakeState = 0; } else { #ifdef DEBUG_SSL_CHAT printf(" in wrong state %d, ignoring (old version)\n", SSLObject->m_bHandshakeState); #endif } } else { #ifdef DEBUG_SSL_CHAT printf(" in wrong state %d, resetting (new version)\n", SSLObject->m_bHandshakeState); #endif SSLObject->m_bHandshakeState = 0; } // clear message msg->m_sMessage.Empty(); return; } msg->m_eSecureState = esecsHANDSHAKE; SSLObject->m_bHandshakeState = 2; /* * Before 0.3.14, each client had to start from getting a . * The problem with this is that hubs will block it for PM spam * It's now been changed so that a client can start from or */ //client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "" ); if ( isOldVersion ) { #ifdef DEBUG_SSL_CHAT printf("Sending extra for backwards compatibility\n"); #endif client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "" ); SSLObject->m_bHandshakeState = 1; } client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "" ); if ( isOldVersion == false ) { if ( !m_pRSA ) if ( GenerateRsaKey() == false ) SSLObject->m_bHandshakeState = 0; CString s = GetPublicRsaKey(); if ( s.IsEmpty() ) return; client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "PK:"+s ); } // clear message msg->m_sMessage.Empty(); } else if ( msg->m_sMessage == "" ) { // send pk if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) { m_pCryptPrivateMessageList->Add( msg->m_sSrcNick, SSLObject = new CSSLObject() ); SSLObject->m_bHandshakeState = 0; } // SSLObject->m_bHandshakeState may be 1 with dclib <= 0.3.13 if ( (SSLObject->m_bHandshakeState != 0) && (SSLObject->m_bHandshakeState != 1) ) { // SSLObject->m_bHandshakeState = 0; #ifdef DEBUG_SSL_CHAT printf(" in wrong state %d, ignoring\n", SSLObject->m_bHandshakeState); #endif msg->m_sMessage.Empty(); return; } if ( !m_pRSA ) if ( GenerateRsaKey() == false ) SSLObject->m_bHandshakeState = 0; CString s = GetPublicRsaKey(); if ( s.IsEmpty() ) return; msg->m_eSecureState = esecsHANDSHAKE; SSLObject->m_bHandshakeState = 2; client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "PK:"+s ); // clear message msg->m_sMessage.Empty(); } else if ( msg->m_sMessage.StartsWith("PK:",3) ) { // receive pk, send sk if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) return; if ( SSLObject->m_bHandshakeState != 2 ) { // SSLObject->m_bHandshakeState = 0; #ifdef DEBUG_SSL_CHAT printf("PK: in wrong state %d, ignoring\n", SSLObject->m_bHandshakeState); #endif msg->m_sMessage.Empty(); return; } if ( SetPublicKey( SSLObject, msg->m_sMessage.Mid(3,msg->m_sMessage.Length()-3) ) == false ) { SSLObject->m_bHandshakeState = 0; return; } InitSessionKey( SSLObject ); CString s = GetSessionKey(SSLObject); if ( s.IsEmpty() ) return; msg->m_eSecureState = esecsHANDSHAKE; SSLObject->m_bHandshakeState = 3; client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "SK:"+s ); // clear message msg->m_sMessage.Empty(); } else if ( msg->m_sMessage.StartsWith("SK:",3) ) { // now we have a secure line if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) return; if ( SSLObject->m_bHandshakeState != 3 ) { // SSLObject->m_bHandshakeState = 0; #ifdef DEBUG_SSL_CHAT printf("SK: in wrong state %d, ignoring\n", SSLObject->m_bHandshakeState); #endif msg->m_sMessage.Empty(); return; } if ( SetSessionKey( SSLObject, msg->m_sMessage.Mid(3,msg->m_sMessage.Length()-3) ) == false ) { SSLObject->m_bHandshakeState = 0; return; } msg->m_eSecureState = esecsENCRYPTED; SSLObject->m_bHandshakeState = 4; CString s = EncryptData( SSLObject, "Secure channel created." ); client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "SEC:"+s ); // clear message msg->m_sMessage.Empty(); } else if ( msg->m_sMessage.StartsWith("SEC:",4) ) { // secure data if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) return; if ( SSLObject->m_bHandshakeState != 4 ) { // you end up here after #ifdef DEBUG_SSL_CHAT printf("SEC: in wrong state %d, resetting\n", SSLObject->m_bHandshakeState); #endif SSLObject->m_bHandshakeState = 0; // clear message msg->m_sMessage.Empty(); return; } CString s = DecryptData( SSLObject, msg->m_sMessage.Mid(4,msg->m_sMessage.Length()-4) ); if ( s.NotEmpty() ) { msg->m_sMessage = s; if ( s == "" ) { SSLObject->m_bHandshakeState = 0; CString s = EncryptData( SSLObject, "" ); client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "SEC:"+s ); client->CDCProto::SendPrivateMessage( client->GetNick(), msg->m_sSrcNick, "Secure channel closed." ); // clear message msg->m_sMessage.Empty(); } else { msg->m_eSecureState = esecsENCRYPTED; } } } else { // unsecure data if ( m_pCryptPrivateMessageList->Get( msg->m_sSrcNick, &SSLObject ) != 0 ) return; // reset handshake mode SSLObject->m_bHandshakeState = 0; } } /** */ CString CClientSSL::EncryptMessage( CClient * /*client*/, CString nick, CString message ) { CString s; CSSLObject * SSLObject; if ( m_pCryptPrivateMessageList->Get( nick, &SSLObject ) == 0 ) { if ( SSLObject->m_bHandshakeState == 4 ) { s = EncryptData( SSLObject, message ); if ( s.NotEmpty() ) { s = "SEC:" + s; } } } return s; } /** */ void CClientSSL::LeaveHub( CClient * /*client*/, CString nick ) { CSSLObject * SSLObject; if ( m_pCryptPrivateMessageList->Get( nick, &SSLObject ) == 0 ) { SSLObject->m_bHandshakeState = 0; } } /** */ void CClientSSL::Init() { m_pCryptPrivateMessageList->Clear(); } #else // DCLIB_HAS_SSL /** */ void CClientSSL::PrivateChat( CClient * /* client */, CMessagePrivateChat * /* msg */ ) { // nothing } /** */ CString CClientSSL::EncryptMessage( CClient * /* client */, CString /* nick */, CString /* message */ ) { return CString(); } /** */ void CClientSSL::LeaveHub( CClient * /* client */, CString /* nick */ ) { // nothing } /** */ void CClientSSL::Init() { // nothing } #endif // DCLIB_HAS_SSL libdc0-0.3.24~svn3121/dclib/gnulib/0000755000175000017500000000000011556467002015564 5ustar sikonsikonlibdc0-0.3.24~svn3121/dclib/gnulib/fsusage.h0000644000175000017500000000270411013254606017365 0ustar sikonsikon/* fsusage.h -- declarations for file system space usage info Copyright (C) 1991, 1992, 1997, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Space usage statistics for a file system. Blocks are 512-byte. */ #if !defined FSUSAGE_H_ # define FSUSAGE_H_ # include # include struct fs_usage { uintmax_t fsu_blocksize; /* Size of a block. */ uintmax_t fsu_blocks; /* Total blocks. */ uintmax_t fsu_bfree; /* Free blocks available to superuser. */ uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ uintmax_t fsu_files; /* Total file nodes. */ uintmax_t fsu_ffree; /* Free file nodes. */ }; int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp); #endif libdc0-0.3.24~svn3121/dclib/gnulib/full-write.c0000644000175000017500000000437011013254606020016 0ustar sikonsikon/* An interface to read and write that retries (if necessary) until complete. Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include /* Specification. */ #ifdef FULL_READ # include "full-read.h" #else # include "full-write.h" #endif #include #ifdef FULL_READ # include "safe-read.h" # define safe_rw safe_read # define full_rw full_read # undef const # define const /* empty */ #else # include "safe-write.h" # define safe_rw safe_write # define full_rw full_write #endif #ifdef FULL_READ /* Set errno to zero upon EOF. */ # define ZERO_BYTE_TRANSFER_ERRNO 0 #else /* Some buggy drivers return 0 when one tries to write beyond a device's end. (Example: Linux 1.2.13 on /dev/fd0.) Set errno to ENOSPC so they get a sensible diagnostic. */ # define ZERO_BYTE_TRANSFER_ERRNO ENOSPC #endif /* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if interrupted or if a partial write(read) occurs. Return the number of bytes transferred. When writing, set errno if fewer than COUNT bytes are written. When reading, if fewer than COUNT bytes are read, you must examine errno to distinguish failure from EOF (errno == 0). */ size_t full_rw (int fd, const void *buf, size_t count) { size_t total = 0; const char *ptr = (const char *) buf; while (count > 0) { size_t n_rw = safe_rw (fd, ptr, count); if (n_rw == (size_t) -1) break; if (n_rw == 0) { errno = ZERO_BYTE_TRANSFER_ERRNO; break; } total += n_rw; ptr += n_rw; count -= n_rw; } return total; } libdc0-0.3.24~svn3121/dclib/gnulib/full-read.h0000644000175000017500000000215711013254606017605 0ustar sikonsikon/* An interface to read() that reads all it is asked to read. Copyright (C) 2002 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, read to the Free Software Foundation, along with this program. If not, see . */ #include /* Read COUNT bytes at BUF to descriptor FD, retrying if interrupted or if partial reads occur. Return the number of bytes successfully read, setting errno if that is less than COUNT. errno = 0 means EOF. */ extern size_t full_read (int fd, void *buf, size_t count); libdc0-0.3.24~svn3121/dclib/gnulib/md5.c0000644000175000017500000003336711042664757016437 0ustar sikonsikon/* Functions to compute MD5 message digest of files or memory blocks. according to the definition of MD5 in RFC 1321 from April 1992. Copyright (C) 1995,1996,1997,1999,2000,2001,2005,2006,2008 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Ulrich Drepper , 1995. */ #include #include "md5.h" #include #include #include #include #ifdef USE_UNLOCKED_IO # include "unlocked-io.h" #endif #ifdef _LIBC # include # if __BYTE_ORDER == __BIG_ENDIAN # define WORDS_BIGENDIAN 1 # endif /* We need to keep the namespace clean so define the MD5 function protected using leading __ . */ # define md5_init_ctx __md5_init_ctx # define md5_process_block __md5_process_block # define md5_process_bytes __md5_process_bytes # define md5_finish_ctx __md5_finish_ctx # define md5_read_ctx __md5_read_ctx # define md5_stream __md5_stream # define md5_buffer __md5_buffer #endif #ifdef WORDS_BIGENDIAN # define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #else # define SWAP(n) (n) #endif #define BLOCKSIZE 4096 #if BLOCKSIZE % 64 != 0 # error "invalid BLOCKSIZE" #endif /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ void md5_init_ctx (struct md5_ctx *ctx) { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } /* Copy the 4 byte value from v into the memory location pointed to by *cp, If your architecture allows unaligned access this is equivalent to * (uint32_t *) cp = v */ static inline void set_uint32 (char *cp, uint32_t v) { memcpy (cp, &v, sizeof v); } /* Put result from CTX in first 16 bytes following RESBUF. The result must be in little endian byte order. */ void * md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) { char *r = resbuf; set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); return resbuf; } /* Process the remaining bytes in the internal buffer and the usual prolog according to the standard and write the result to RESBUF. */ void * md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) { /* Take yet unprocessed bytes into account. */ uint32_t bytes = ctx->buflen; size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; /* Now count remaining bytes. */ ctx->total[0] += bytes; if (ctx->total[0] < bytes) ++ctx->total[1]; /* Put the 64-bit file length in *bits* at the end of the buffer. */ ctx->buffer[size - 2] = SWAP (ctx->total[0] << 3); ctx->buffer[size - 1] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); /* Process last bytes. */ md5_process_block (ctx->buffer, size * 4, ctx); return md5_read_ctx (ctx, resbuf); } /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ int md5_stream (FILE *stream, void *resblock) { struct md5_ctx ctx; char buffer[BLOCKSIZE + 72]; size_t sum; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Iterate over full file contents. */ while (1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ size_t n; sum = 0; /* Read block. Take care for partial reads. */ while (1) { n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); sum += n; if (sum == BLOCKSIZE) break; if (n == 0) { /* Check for the error flag IFF N == 0, so that we don't exit the loop after a partial read due to e.g., EAGAIN or EWOULDBLOCK. */ if (ferror (stream)) return 1; goto process_partial_block; } /* We've read at least one byte, so ignore errors. But always check for EOF, since feof may be true even though N > 0. Otherwise, we could end up calling fread after EOF. */ if (feof (stream)) goto process_partial_block; } /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ md5_process_block (buffer, BLOCKSIZE, &ctx); } process_partial_block: /* Process any remaining bytes. */ if (sum > 0) md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ md5_finish_ctx (&ctx, resblock); return 0; } /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ void * md5_buffer (const char *buffer, size_t len, void *resblock) { struct md5_ctx ctx; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ md5_process_bytes (buffer, len, &ctx); /* Put result in desired memory area. */ return md5_finish_ctx (&ctx, resblock); } void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) { /* When we already have some bits in our internal buffer concatenate both inputs first. */ if (ctx->buflen != 0) { size_t left_over = ctx->buflen; size_t add = 128 - left_over > len ? len : 128 - left_over; memcpy (&((char *) ctx->buffer)[left_over], buffer, add); ctx->buflen += add; if (ctx->buflen > 64) { md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ctx->buflen &= 63; /* The regions in the following copy operation cannot overlap. */ memcpy (ctx->buffer, &((char *) ctx->buffer)[(left_over + add) & ~63], ctx->buflen); } buffer = (const char *) buffer + add; len -= add; } /* Process available complete blocks. */ if (len >= 64) { #if !_STRING_ARCH_unaligned # define alignof(type) offsetof (struct { char c; type x; }, x) # define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0) if (UNALIGNED_P (buffer)) while (len > 64) { md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); buffer = (const char *) buffer + 64; len -= 64; } else #endif { md5_process_block (buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } } /* Move remaining bytes in internal buffer. */ if (len > 0) { size_t left_over = ctx->buflen; memcpy (&((char *) ctx->buffer)[left_over], buffer, len); left_over += len; if (left_over >= 64) { md5_process_block (ctx->buffer, 64, ctx); left_over -= 64; memcpy (ctx->buffer, &ctx->buffer[16], left_over); } ctx->buflen = left_over; } } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) { uint32_t correct_words[16]; const uint32_t *words = buffer; size_t nwords = len / sizeof (uint32_t); const uint32_t *endp = words + nwords; uint32_t A = ctx->A; uint32_t B = ctx->B; uint32_t C = ctx->C; uint32_t D = ctx->D; /* First increment the byte count. RFC 1321 specifies the possible length of the file up to 2^64 bits. Here we only compute the number of bytes. Do a double word increment. */ ctx->total[0] += len; if (ctx->total[0] < len) ++ctx->total[1]; /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp) { uint32_t *cwp = correct_words; uint32_t A_save = A; uint32_t B_save = B; uint32_t C_save = C; uint32_t D_save = D; /* First round: using the given function, the context and a constant the next context is computed. Because the algorithms processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ ++words; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* It is unfortunate that C does not provide an operator for cyclic rotation. Hope the C compiler is smart enough. */ #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) /* Before we start, one word to the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 Here is an equivalent invocation using Perl: perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Add the starting values of the context. */ A += A_save; B += B_save; C += C_save; D += D_save; } /* Put checksum in context given as argument. */ ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } libdc0-0.3.24~svn3121/dclib/gnulib/fsusage.c0000644000175000017500000001736411042664757017406 0ustar sikonsikon/* fsusage.c -- return space usage of mounted file systems Copyright (C) 1991, 1992, 1996, 1998, 1999, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "fsusage.h" #include #include #ifdef STAT_STATVFS /* POSIX 1003.1-2001 (and later) with XSI */ # include #else /* Don't include backward-compatibility files unless they're needed. Eventually we'd like to remove all this cruft. */ # include # include # include # ifdef HAVE_SYS_PARAM_H # include # endif # ifdef HAVE_SYS_MOUNT_H # include # endif # ifdef HAVE_SYS_VFS_H # include # endif # ifdef HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ # include # endif # if defined HAVE_SYS_FILSYS_H && !defined _CRAY # include /* SVR2 */ # endif # ifdef HAVE_SYS_STATFS_H # include # endif # ifdef HAVE_DUSTAT_H /* AIX PS/2 */ # include # endif # include "full-read.h" #endif /* The results of open() in this file are not used with fchdir, therefore save some unnecessary work in fchdir.c. */ #undef open #undef close /* Many space usage primitives use all 1 bits to denote a value that is not applicable or unknown. Propagate this information by returning a uintmax_t value that is all 1 bits if X is all 1 bits, even if X is unsigned and narrower than uintmax_t. */ #define PROPAGATE_ALL_ONES(x) \ ((sizeof (x) < sizeof (uintmax_t) \ && (~ (x) == (sizeof (x) < sizeof (int) \ ? - (1 << (sizeof (x) * CHAR_BIT)) \ : 0))) \ ? UINTMAX_MAX : (uintmax_t) (x)) /* Extract the top bit of X as an uintmax_t value. */ #define EXTRACT_TOP_BIT(x) ((x) \ & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1))) /* If a value is negative, many space usage primitives store it into an integer variable by assignment, even if the variable's type is unsigned. So, if a space usage variable X's top bit is set, convert X to the uintmax_t value V such that (- (uintmax_t) V) is the negative of the original value. If X's top bit is clear, just yield X. Use PROPAGATE_TOP_BIT if the original value might be negative; otherwise, use PROPAGATE_ALL_ONES. */ #define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) /* Fill in the fields of FSP with information about space usage for the file system on which FILE resides. DISK is the device on which FILE is mounted, for space-getting methods that need to know it. Return 0 if successful, -1 if not. When returning -1, ensure that ERRNO is either a system error value, or zero if DISK is NULL on a system that requires a non-NULL value. */ int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) { #if defined STAT_STATVFS /* POSIX */ struct statvfs fsd; if (statvfs (file, &fsd) < 0) return -1; /* f_frsize isn't guaranteed to be supported. */ fsp->fsu_blocksize = (fsd.f_frsize ? PROPAGATE_ALL_ONES (fsd.f_frsize) : PROPAGATE_ALL_ONES (fsd.f_bsize)); #elif defined STAT_STATFS2_FS_DATA /* Ultrix */ struct fs_data fsd; if (statfs (file, &fsd) != 1) return -1; fsp->fsu_blocksize = 1024; fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot); fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree); fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen); fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0; fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot); fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree); #elif defined STAT_READ_FILSYS /* SVR2 */ # ifndef SUPERBOFF # define SUPERBOFF (SUPERB * 512) # endif struct filsys fsd; int fd; if (! disk) { errno = 0; return -1; } fd = open (disk, O_RDONLY); if (fd < 0) return -1; lseek (fd, (off_t) SUPERBOFF, 0); if (full_read (fd, (char *) &fsd, sizeof fsd) != sizeof fsd) { close (fd); return -1; } close (fd); fsp->fsu_blocksize = (fsd.s_type == Fs2b ? 1024 : 512); fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.s_fsize); fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.s_tfree); fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.s_tfree); fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.s_tfree) != 0; fsp->fsu_files = (fsd.s_isize == -1 ? UINTMAX_MAX : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1)); fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode); #elif defined STAT_STATFS3_OSF1 struct statfs fsd; if (statfs (file, &fsd, sizeof (struct statfs)) != 0) return -1; fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); #elif defined STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ struct statfs fsd; if (statfs (file, &fsd) < 0) return -1; fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); # ifdef STATFS_TRUNCATES_BLOCK_COUNTS /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the struct statfs are truncated to 2GB. These conditions detect that truncation, presumably without botching the 4.1.1 case, in which the values are not truncated. The correct counts are stored in undocumented spare fields. */ if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0) { fsd.f_blocks = fsd.f_spare[0]; fsd.f_bfree = fsd.f_spare[1]; fsd.f_bavail = fsd.f_spare[2]; } # endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ #elif defined STAT_STATFS2_FSIZE /* 4.4BSD */ struct statfs fsd; if (statfs (file, &fsd) < 0) return -1; fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); #elif defined STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ # if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN # define f_bavail f_bfree # endif struct statfs fsd; if (statfs (file, &fsd, sizeof fsd, 0) < 0) return -1; /* Empirically, the block counts on most SVR3 and SVR3-derived systems seem to always be in terms of 512-byte blocks, no matter what value f_bsize has. */ # if _AIX || defined _CRAY fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); # else fsp->fsu_blocksize = 512; # endif #endif #if (defined STAT_STATVFS \ || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS)) fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail); fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0; fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files); fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree); #endif return 0; } #if defined _AIX && defined _I386 /* AIX PS/2 does not supply statfs. */ int statfs (char *file, struct statfs *fsb) { struct stat stats; struct dustat fsd; if (stat (file, &stats) != 0) return -1; if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) return -1; fsb->f_type = 0; fsb->f_bsize = fsd.du_bsize; fsb->f_blocks = fsd.du_fsize - fsd.du_isize; fsb->f_bfree = fsd.du_tfree; fsb->f_bavail = fsd.du_tfree; fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; fsb->f_ffree = fsd.du_tinode; fsb->f_fsid.val[0] = fsd.du_site; fsb->f_fsid.val[1] = fsd.du_pckno; return 0; } #endif /* _AIX && _I386 */ libdc0-0.3.24~svn3121/dclib/gnulib/safe-read.h0000644000175000017500000000214711013254606017560 0ustar sikonsikon/* An interface to read() that retries after interrupts. Copyright (C) 2002, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #ifdef __cplusplus extern "C" { #endif #define SAFE_READ_ERROR ((size_t) -1) /* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted. Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR upon error. */ extern size_t safe_read (int fd, void *buf, size_t count); #ifdef __cplusplus } #endif libdc0-0.3.24~svn3121/dclib/gnulib/Makefile.am0000644000175000017500000000061111074336645017621 0ustar sikonsikonnoinst_LTLIBRARIES = libgnulib.la libgnulib_la_SOURCES = \ md5.h \ md5.c if !WIN32 libgnulib_la_SOURCES += \ fsusage.h \ fsusage.c \ full-read.h \ full-read.c \ safe-read.h \ safe-read.c endif !WIN32 libgnulib_la_LDFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) AM_CFLAGS = @CFLAGS@ $(DEBUGCOMPILE) $(PTHREAD_CFLAGS) $(HIDESYMS) AM_CPPFLAGS = -I$(top_srcdir) $(PACKAGE_FLAGS) VERSION = "0.0.1" libdc0-0.3.24~svn3121/dclib/gnulib/safe-read.c0000644000175000017500000000412411013254606017550 0ustar sikonsikon/* An interface to read and write that retries after interrupts. Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include /* Specification. */ #ifdef SAFE_WRITE # include "safe-write.h" #else # include "safe-read.h" #endif /* Get ssize_t. */ #include #include #include #ifdef EINTR # define IS_EINTR(x) ((x) == EINTR) #else # define IS_EINTR(x) 0 #endif #include #ifdef SAFE_WRITE # define safe_rw safe_write # define rw write #else # define safe_rw safe_read # define rw read # undef const # define const /* empty */ #endif /* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if interrupted. Return the actual number of bytes read(written), zero for EOF, or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */ size_t safe_rw (int fd, void const *buf, size_t count) { /* Work around a bug in Tru64 5.1. Attempting to read more than INT_MAX bytes fails with errno == EINVAL. See . When decreasing COUNT, keep it block-aligned. */ enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 }; for (;;) { ssize_t result = rw (fd, buf, count); if (0 <= result) return result; else if (IS_EINTR (errno)) continue; else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count) count = BUGGY_READ_MAXIMUM; else return result; } } libdc0-0.3.24~svn3121/dclib/gnulib/md5.h0000644000175000017500000000770211013254606016420 0ustar sikonsikon/* Declaration of functions and data types used for MD5 sum computing library functions. Copyright (C) 1995-1997,1999,2000,2001,2004,2005,2006,2008 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _MD5_H #define _MD5_H 1 #include #include #define MD5_DIGEST_SIZE 16 #define MD5_BLOCK_SIZE 64 #ifndef __GNUC_PREREQ # if defined __GNUC__ && defined __GNUC_MINOR__ # define __GNUC_PREREQ(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) # else # define __GNUC_PREREQ(maj, min) 0 # endif #endif #ifndef __THROW # if defined __cplusplus && __GNUC_PREREQ (2,8) # define __THROW throw () # else # define __THROW # endif #endif #ifndef _LIBC # define __md5_buffer md5_buffer # define __md5_finish_ctx md5_finish_ctx # define __md5_init_ctx md5_init_ctx # define __md5_process_block md5_process_block # define __md5_process_bytes md5_process_bytes # define __md5_read_ctx md5_read_ctx # define __md5_stream md5_stream #endif /* Structure to save state of computation between the single steps. */ struct md5_ctx { uint32_t A; uint32_t B; uint32_t C; uint32_t D; uint32_t total[2]; uint32_t buflen; uint32_t buffer[32]; }; /* * The following three functions are build up the low level used in * the functions `md5_stream' and `md5_buffer'. */ /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is necessary that LEN is a multiple of 64!!! */ extern void __md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) __THROW; /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ extern void __md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) __THROW; /* Process the remaining bytes in the buffer and put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; /* Put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ extern int __md5_stream (FILE *stream, void *resblock) __THROW; /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ extern void *__md5_buffer (const char *buffer, size_t len, void *resblock) __THROW; #endif /* md5.h */ libdc0-0.3.24~svn3121/dclib/gnulib/full-read.c0000644000175000017500000000146611013254606017602 0ustar sikonsikon/* An interface to read that retries after partial reads and interrupts. Copyright (C) 2002, 2003 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define FULL_READ #include "full-write.c" libdc0-0.3.24~svn3121/m4/0000755000175000017500000000000011556466777013571 5ustar sikonsikonlibdc0-0.3.24~svn3121/m4/lib-ld.m40000644000175000017500000000653111014655145015155 0ustar sikonsikon# lib-ld.m4 serial 3 (gettext-0.13) dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) libdc0-0.3.24~svn3121/m4/lib-link.m40000644000175000017500000007205511165212160015510 0ustar sikonsikon# lib-link.m4 serial 13 (gettext-0.17) dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ(2.54) dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes undefine([Name]) undefine([NAME]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. If found, it dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" LIBS="$LIBS $LIB[]NAME" AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= LIB[]NAME[]_PREFIX= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) undefine([Name]) undefine([NAME]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl acl_libext, dnl acl_shlibext, dnl acl_hardcode_libdir_flag_spec, dnl acl_hardcode_libdir_separator, dnl acl_hardcode_direct, dnl acl_hardcode_minus_L. AC_DEFUN([AC_LIB_RPATH], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" acl_libext="$acl_cv_libext" acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE(rpath, [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Autoconf >= 2.61 supports dots in --with options. define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix], [ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= LIB[]NAME[]_PREFIX= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" dnl The same code as in the loop below: dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$acl_hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` LIB[]NAME[]_PREFIX="$basedir" additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) dnl For those cases where a variable contains several -L and -l options dnl referring to unknown libraries and directories, this macro determines the dnl necessary additional linker options for the runtime path. dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) dnl sets LDADDVAR to linker options needed together with LIBSVALUE. dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, dnl otherwise linking without libtool is assumed. AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], [ AC_REQUIRE([AC_LIB_RPATH]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) $1= if test "$enable_rpath" != no; then if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode directories into the resulting dnl binary. rpathdirs= next= for opt in $2; do if test -n "$next"; then dir="$next" dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem"; then rpathdirs="$rpathdirs $dir" fi next= else case $opt in -L) next=yes ;; -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem"; then rpathdirs="$rpathdirs $dir" fi next= ;; *) next= ;; esac fi done if test "X$rpathdirs" != "X"; then if test -n ""$3""; then dnl libtool is used for linking. Use -R options. for dir in $rpathdirs; do $1="${$1}${$1:+ }-R$dir" done else dnl The linker is used for linking directly. if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user dnl must pass all path elements in one option. alldirs= for dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="$flag" else dnl The -rpath options are cumulative. for dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="${$1}${$1:+ }$flag" done fi fi fi fi fi AC_SUBST([$1]) ]) libdc0-0.3.24~svn3121/m4/iconv.m40000644000175000017500000001375311165212160015125 0ustar sikonsikon# iconv.m4 serial AM6 (gettext-0.17) dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_func_iconv=yes) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_lib_iconv=yes am_cv_func_iconv=yes) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [ dnl This tests against bugs in AIX 5.1 and HP-UX 11.11. am_save_LIBS="$LIBS" if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi AC_TRY_RUN([ #include #include int main () { /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { static const char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } #if 0 /* This bug could be worked around by the caller. */ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ { iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) return 1; } } #endif /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is provided. */ if (/* Try standardized names. */ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) /* Try IRIX, OSF/1 names. */ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) /* Try AIX names. */ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) /* Try HP-UX names. */ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) return 1; return 0; }], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no], [case "$host_os" in aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; *) am_cv_func_iconv_works="guessing yes" ;; esac]) LIBS="$am_save_LIBS" ]) case "$am_cv_func_iconv_works" in *no) am_func_iconv=no am_cv_lib_iconv=no ;; *) am_func_iconv=yes ;; esac else am_func_iconv=no am_cv_lib_iconv=no fi if test "$am_func_iconv" = yes; then AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function and it works.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST(LIBICONV) AC_SUBST(LTLIBICONV) ]) AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL(am_cv_proto_iconv, [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([$]{ac_t:- }[$]am_cv_proto_iconv) AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, [Define as const if the declaration of iconv() needs const.]) fi ]) libdc0-0.3.24~svn3121/m4/acx_pthread.m40000644000175000017500000002536611033365002016272 0ustar sikonsikon##### http://autoconf-archive.cryp.to/acx_pthread.html # # SYNOPSIS # # ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. # It sets the PTHREAD_LIBS output variable to the threads library and # linker flags, and the PTHREAD_CFLAGS output variable to any special # C compiler flags that are needed. (The user can also force certain # compiler flags/libs to be tested by setting these environment # variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). # (This is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these # flags, but also link it with them as well. e.g. you should link # with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS # $LIBS # # If you are only building threads programs, you may wish to use # these variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute # constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # ACTION-IF-FOUND is a list of shell commands to run if a threads # library is found, and ACTION-IF-NOT-FOUND is a list of commands to # run it if it is not found. If ACTION-IF-FOUND is not specified, the # default action will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or # if you have any other suggestions or comments. This macro was based # on work by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) # (with help from M. Frigo), as well as ac_pthread and hb_pthread # macros posted by Alejandro Forero Cuervo to the autoconf macro # repository. We are also grateful for the helpful feedback of # numerous users. # # LAST MODIFICATION # # 2006-05-29 # # COPYLEFT # # Copyright (c) 2006 Steven G. Johnson # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # # As a special exception, the respective Autoconf Macro's copyright # owner gives unlimited permission to copy, distribute and modify the # configure scripts that are the output of Autoconf when processing # the Macro. You need not follow the terms of the GNU General Public # License when using or distributing such scripts, even though # portions of the text of the Macro appear in them. The GNU General # Public License (GPL) does govern all other use of the material that # constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the # Autoconf Macro released by the Autoconf Macro Archive. When you # make and distribute a modified version of the Autoconf Macro, you # may extend this special exception to the GPL to apply to your # modified version as well. AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD libdc0-0.3.24~svn3121/m4/fsusage.m40000644000175000017500000001753411014655145015454 0ustar sikonsikon#serial 23 # Obtaining file system usage information. # Copyright (C) 1997, 1998, 2000, 2001, 2003-2007 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Written by Jim Meyering. AC_DEFUN([gl_FSUSAGE], [ AC_CHECK_HEADERS_ONCE(sys/param.h) AC_CHECK_HEADERS_ONCE(sys/vfs.h sys/fs_types.h) AC_CHECK_HEADERS(sys/mount.h, [], [], [AC_INCLUDES_DEFAULT [#if HAVE_SYS_PARAM_H #include #endif]]) gl_FILE_SYSTEM_USAGE([gl_cv_fs_space=yes], [gl_cv_fs_space=no]) if test $gl_cv_fs_space = yes; then AC_LIBOBJ(fsusage) gl_PREREQ_FSUSAGE_EXTRA fi ]) # Try to determine how a program can obtain file system usage information. # If successful, define the appropriate symbol (see fsusage.c) and # execute ACTION-IF-FOUND. Otherwise, execute ACTION-IF-NOT-FOUND. # # gl_FILE_SYSTEM_USAGE([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) AC_DEFUN([gl_FILE_SYSTEM_USAGE], [ AC_MSG_NOTICE([checking how to get file system space usage]) ac_fsusage_space=no # Perform only the link test since it seems there are no variants of the # statvfs function. This check is more than just AC_CHECK_FUNCS(statvfs) # because that got a false positive on SCO OSR5. Adding the declaration # of a `struct statvfs' causes this test to fail (as it should) on such # systems. That system is reported to work fine with STAT_STATFS4 which # is what it gets when this test fails. if test $ac_fsusage_space = no; then # SVR4 AC_CACHE_CHECK([for statvfs function (SVR4)], fu_cv_sys_stat_statvfs, [AC_TRY_LINK([#include #if defined __GLIBC__ && !defined __BEOS__ Do not use statvfs on systems with GNU libc, because that function stats all preceding entries in /proc/mounts, and that makes df hang if even one of the corresponding file systems is hard-mounted, but not available. statvfs in GNU libc on BeOS operates differently: it only makes a system call. #endif #ifdef __osf__ "Do not use Tru64's statvfs implementation" #endif #include ], [struct statvfs fsd; statvfs (0, &fsd);], fu_cv_sys_stat_statvfs=yes, fu_cv_sys_stat_statvfs=no)]) if test $fu_cv_sys_stat_statvfs = yes; then ac_fsusage_space=yes AC_DEFINE(STAT_STATVFS, 1, [ Define if there is a function named statvfs. (SVR4)]) fi fi if test $ac_fsusage_space = no; then # DEC Alpha running OSF/1 AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1, [AC_TRY_RUN([ #include #include #include int main () { struct statfs fsd; fsd.f_fsize = 0; return statfs (".", &fsd, sizeof (struct statfs)) != 0; }], fu_cv_sys_stat_statfs3_osf1=yes, fu_cv_sys_stat_statfs3_osf1=no, fu_cv_sys_stat_statfs3_osf1=no)]) AC_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1) if test $fu_cv_sys_stat_statfs3_osf1 = yes; then ac_fsusage_space=yes AC_DEFINE(STAT_STATFS3_OSF1, 1, [ Define if statfs takes 3 args. (DEC Alpha running OSF/1)]) fi fi if test $ac_fsusage_space = no; then # AIX AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl member (AIX, 4.3BSD)]) AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize, [AC_TRY_RUN([ #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif int main () { struct statfs fsd; fsd.f_bsize = 0; return statfs (".", &fsd) != 0; }], fu_cv_sys_stat_statfs2_bsize=yes, fu_cv_sys_stat_statfs2_bsize=no, fu_cv_sys_stat_statfs2_bsize=no)]) AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize) if test $fu_cv_sys_stat_statfs2_bsize = yes; then ac_fsusage_space=yes AC_DEFINE(STAT_STATFS2_BSIZE, 1, [ Define if statfs takes 2 args and struct statfs has a field named f_bsize. (4.3BSD, SunOS 4, HP-UX, AIX PS/2)]) fi fi if test $ac_fsusage_space = no; then # SVR3 AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) AC_CACHE_VAL(fu_cv_sys_stat_statfs4, [AC_TRY_RUN([#include #include int main () { struct statfs fsd; return statfs (".", &fsd, sizeof fsd, 0) != 0; }], fu_cv_sys_stat_statfs4=yes, fu_cv_sys_stat_statfs4=no, fu_cv_sys_stat_statfs4=no)]) AC_MSG_RESULT($fu_cv_sys_stat_statfs4) if test $fu_cv_sys_stat_statfs4 = yes; then ac_fsusage_space=yes AC_DEFINE(STAT_STATFS4, 1, [ Define if statfs takes 4 args. (SVR3, Dynix, Irix, Dolphin)]) fi fi if test $ac_fsusage_space = no; then # 4.4BSD and NetBSD AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl member (4.4BSD and NetBSD)]) AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize, [AC_TRY_RUN([#include #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif int main () { struct statfs fsd; fsd.f_fsize = 0; return statfs (".", &fsd) != 0; }], fu_cv_sys_stat_statfs2_fsize=yes, fu_cv_sys_stat_statfs2_fsize=no, fu_cv_sys_stat_statfs2_fsize=no)]) AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize) if test $fu_cv_sys_stat_statfs2_fsize = yes; then ac_fsusage_space=yes AC_DEFINE(STAT_STATFS2_FSIZE, 1, [ Define if statfs takes 2 args and struct statfs has a field named f_fsize. (4.4BSD, NetBSD)]) fi fi if test $ac_fsusage_space = no; then # Ultrix AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) AC_CACHE_VAL(fu_cv_sys_stat_fs_data, [AC_TRY_RUN([#include #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_FS_TYPES_H #include #endif int main () { struct fs_data fsd; /* Ultrix's statfs returns 1 for success, 0 for not mounted, -1 for failure. */ return statfs (".", &fsd) != 1; }], fu_cv_sys_stat_fs_data=yes, fu_cv_sys_stat_fs_data=no, fu_cv_sys_stat_fs_data=no)]) AC_MSG_RESULT($fu_cv_sys_stat_fs_data) if test $fu_cv_sys_stat_fs_data = yes; then ac_fsusage_space=yes AC_DEFINE(STAT_STATFS2_FS_DATA, 1, [ Define if statfs takes 2 args and the second argument has type struct fs_data. (Ultrix)]) fi fi if test $ac_fsusage_space = no; then # SVR2 AC_TRY_CPP([#include ], AC_DEFINE(STAT_READ_FILSYS, 1, [Define if there is no specific function for reading file systems usage information and you have the header file. (SVR2)]) ac_fsusage_space=yes) fi AS_IF([test $ac_fsusage_space = yes], [$1], [$2]) ]) # Check for SunOS statfs brokenness wrt partitions 2GB and larger. # If exists and struct statfs has a member named f_spare, # enable the work-around code in fsusage.c. AC_DEFUN([gl_STATFS_TRUNCATES], [ AC_MSG_CHECKING([for statfs that truncates block counts]) AC_CACHE_VAL(fu_cv_sys_truncating_statfs, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if !defined(sun) && !defined(__sun) choke -- this is a workaround for a Sun-specific problem #endif #include #include ]], [[struct statfs t; long c = *(t.f_spare); if (c) return 0;]])], [fu_cv_sys_truncating_statfs=yes], [fu_cv_sys_truncating_statfs=no])]) if test $fu_cv_sys_truncating_statfs = yes; then AC_DEFINE(STATFS_TRUNCATES_BLOCK_COUNTS, 1, [Define if the block counts reported by statfs may be truncated to 2GB and the correct values may be stored in the f_spare array. (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. SunOS 4.1.1 seems not to be affected.)]) fi AC_MSG_RESULT($fu_cv_sys_truncating_statfs) ]) # Prerequisites of lib/fsusage.c not done by gl_FILE_SYSTEM_USAGE. AC_DEFUN([gl_PREREQ_FSUSAGE_EXTRA], [ AC_CHECK_HEADERS(dustat.h sys/fs/s5param.h sys/filsys.h sys/statfs.h) gl_STATFS_TRUNCATES ]) libdc0-0.3.24~svn3121/m4/libxml.m40000644000175000017500000001731011014655145015276 0ustar sikonsikon# Configure paths for LIBXML2 # Mike Hommey 2004-06-19 # use CPPFLAGS instead of CFLAGS # Toshio Kuratomi 2001-04-21 # Adapted from: # Configure paths for GLIB # Owen Taylor 97-11-3 dnl AM_PATH_XML2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for XML, and define XML_CPPFLAGS and XML_LIBS dnl AC_DEFUN([AM_PATH_XML2],[ AC_ARG_WITH(xml-prefix, [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)], xml_config_prefix="$withval", xml_config_prefix="") AC_ARG_WITH(xml-exec-prefix, [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)], xml_config_exec_prefix="$withval", xml_config_exec_prefix="") AC_ARG_ENABLE(xmltest, [ --disable-xmltest Do not try to compile and run a test LIBXML program],, enable_xmltest=yes) if test x$xml_config_exec_prefix != x ; then xml_config_args="$xml_config_args" if test x${XML2_CONFIG+set} != xset ; then XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config fi fi if test x$xml_config_prefix != x ; then xml_config_args="$xml_config_args --prefix=$xml_config_prefix" if test x${XML2_CONFIG+set} != xset ; then XML2_CONFIG=$xml_config_prefix/bin/xml2-config fi fi AC_PATH_PROG(XML2_CONFIG, xml2-config, no) min_xml_version=ifelse([$1], ,2.0.0,[$1]) AC_MSG_CHECKING(for libxml - version >= $min_xml_version) no_xml="" if test "$XML2_CONFIG" = "no" ; then no_xml=yes else XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_xmltest" = "xyes" ; then ac_save_CPPFLAGS="$CPPFLAGS" ac_save_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" LIBS="$XML_LIBS $LIBS" dnl dnl Now check if the installed libxml is sufficiently new. dnl (Also sanity checks the results of xml2-config to some extent) dnl rm -f conf.xmltest AC_TRY_RUN([ #include #include #include #include int main() { int xml_major_version, xml_minor_version, xml_micro_version; int major, minor, micro; char *tmp_version; system("touch conf.xmltest"); /* Capture xml2-config output via autoconf/configure variables */ /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = (char *)strdup("$min_xml_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string from xml2-config\n", "$min_xml_version"); exit(1); } free(tmp_version); /* Capture the version information from the header files */ tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); exit(1); } free(tmp_version); /* Compare xml2-config output to the libxml headers */ if ((xml_major_version != $xml_config_major_version) || (xml_minor_version != $xml_config_minor_version) || (xml_micro_version != $xml_config_micro_version)) { printf("*** libxml header files (version %d.%d.%d) do not match\n", xml_major_version, xml_minor_version, xml_micro_version); printf("*** xml2-config (version %d.%d.%d)\n", $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); return 1; } /* Compare the headers to the library to make sure we match */ /* Less than ideal -- doesn't provide us with return value feedback, * only exits if there's a serious mismatch between header and library. */ LIBXML_TEST_VERSION; /* Test that the library is greater than our minimum version */ if ((xml_major_version > major) || ((xml_major_version == major) && (xml_minor_version > minor)) || ((xml_major_version == major) && (xml_minor_version == minor) && (xml_micro_version >= micro))) { return 0; } else { printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", xml_major_version, xml_minor_version, xml_micro_version); printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", major, minor, micro); printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); printf("***\n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); printf("*** correct copy of xml2-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time))\n"); } return 1; } ],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CPPFLAGS="$ac_save_CPPFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_xml" = x ; then AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$XML2_CONFIG" = "no" ; then echo "*** The xml2-config script installed by LIBXML could not be found" echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the XML2_CONFIG environment variable to the" echo "*** full path to xml2-config." else if test -f conf.xmltest ; then : else echo "*** Could not run libxml test program, checking why..." CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" LIBS="$LIBS $XML_LIBS" AC_TRY_LINK([ #include #include ], [ LIBXML_TEST_VERSION; return 0;], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding LIBXML or finding the wrong" echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ]) CPPFLAGS="$ac_save_CPPFLAGS" LIBS="$ac_save_LIBS" fi fi XML_CPPFLAGS="" XML_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(XML_CPPFLAGS) AC_SUBST(XML_LIBS) rm -f conf.xmltest ]) libdc0-0.3.24~svn3121/m4/fstypename.m40000644000175000017500000000127711014655145016167 0ustar sikonsikon#serial 3 dnl From Jim Meyering. dnl dnl See if struct statfs has the f_fstypename member. dnl If so, define HAVE_F_FSTYPENAME_IN_STATFS. dnl AC_DEFUN([jm_FSTYPENAME], [ AC_CACHE_CHECK([for f_fstypename in struct statfs], fu_cv_sys_f_fstypename_in_statfs, [ AC_TRY_COMPILE( [ #include #include #include ], [struct statfs s; int i = sizeof s.f_fstypename;], fu_cv_sys_f_fstypename_in_statfs=yes, fu_cv_sys_f_fstypename_in_statfs=no ) ] ) if test $fu_cv_sys_f_fstypename_in_statfs = yes; then AC_DEFINE(HAVE_F_FSTYPENAME_IN_STATFS, 1, [Define if struct statfs has the f_fstypename member.]) fi ] ) libdc0-0.3.24~svn3121/m4/pkg.m40000644000175000017500000001206311033365002014557 0ustar sikonsikon# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [AC_MSG_RESULT([no]) $4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES libdc0-0.3.24~svn3121/m4/md5.m40000644000175000017500000000066711014655145014503 0ustar sikonsikon# md5.m4 serial 10 dnl Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_MD5], [ AC_LIBOBJ([md5]) dnl Prerequisites of lib/md5.c. AC_REQUIRE([AC_C_BIGENDIAN]) AC_REQUIRE([AC_C_INLINE]) : ]) libdc0-0.3.24~svn3121/m4/dclib-ssl-tests.m40000644000175000017500000000402611054474031017020 0ustar sikonsikon#serial 1 # Control SSL support: # --enable-ssl=yes/no # --with-ssl-library=openssl AC_DEFUN([DCLIB_CHECK_SSL], [ AC_ARG_ENABLE([ssl], [AS_HELP_STRING([--disable-ssl],[disable support for Secure Sockets Layer (default=enabled)])], [ ENABLE_SSL=$enableval ], [ ENABLE_SSL="yes"] ) AC_ARG_WITH([ssl-library], [AS_HELP_STRING([--with-ssl-library=openssl],[Which SSL library to use. Currently only "openssl" is supported. (default=openssl)])], [ SSL_TOOLKIT=$withval ], [ SSL_TOOLKIT="openssl" ] ) AC_MSG_CHECKING([if SSL support should be enabled]) if test "x${ENABLE_SSL}" = "xyes" then AC_MSG_RESULT([yes]) HAVE_SSL=1 if test "x${SSL_TOOLKIT}" = "xopenssl" then AC_MSG_NOTICE([OpenSSL is currently the only supported SSL library.]) USING_OPENSSL=1 AC_MSG_NOTICE([Looking for OpenSSL libraries via pkg-config...]) PKG_CHECK_MODULES([OPENSSL],[openssl >= 0.9.7], [SSL_LDFLAGS="${OPENSSL_LIBS}" SSL_CPPFLAGS="${OPENSSL_CFLAGS}" ], [AC_MSG_RESULT([$OPENSSL_PKG_ERRORS]) AC_MSG_NOTICE([using openssl in default directories]) SSL_LDFLAGS="-lssl -lcrypto" SSL_CPPFLAGS="" ]) AC_MSG_CHECKING([if the OpenSSL flags work]) ac_save_LIBS="$LIBS" ac_save_CPPFLAGS="$CPPFLAGS" LIBS="$LIBS $SSL_LDFLAGS" CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS" AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include #include int main() { SSL_load_error_strings(); SSL_library_init(); return 0; } ]] )], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_ERROR([no - the test OpenSSL program failed to link, check config.log for details]) ] ) LIBS="$ac_save_LIBS" CPPFLAGS="$ac_save_CPPFLAGS" else AC_MSG_ERROR([OpenSSL is currently the only supported SSL library.]) fi else AC_MSG_RESULT([no]) HAVE_SSL=0 USING_OPENSSL=0 SSL_LDFLAGS="" SSL_CPPFLAGS="" fi AC_SUBST(HAVE_SSL) AC_SUBST(USING_OPENSSL) AC_SUBST(SSL_LDFLAGS) AC_SUBST(SSL_CPPFLAGS) ]) libdc0-0.3.24~svn3121/m4/dclib-stl-tests.m40000644000175000017500000001542111555040725017027 0ustar sikonsikon#serial 1 # Check for C++ Standard Template Library headers # # The results are written into dclib-stl-use.h NOT config.h, since they are # used in dclib's installed headers, and dclib's config.h is not installed. # # Written by Edward Sheldrake, this file is part of dclib. # AC_DEFUN([DCLIB_CHECK_STL], [ AC_MSG_NOTICE([checking for C++ Standard Template Library features]) dnl these may or may not be used if unordered versions are available dnl but they always exist, standard part of C++ AC_CHECK_HEADER([map], [], [AC_MSG_ERROR([No std::map header found!])]) AC_CHECK_HEADER([set], [], [AC_MSG_ERROR([No std::set header found!])]) AC_CHECK_HEADER([vector], [], [AC_MSG_ERROR([No std::vector header found!])]) AC_CHECK_HEADER([algorithm], [], [AC_MSG_ERROR([No std::algorithm header found!])]) AC_ARG_ENABLE([unordered-stl], [AS_HELP_STRING([--disable-unordered-stl],[disable use of C++ classes unordered_map and unordered_set (default=used if present)])], [ UNORDERED_STL=$enableval ], [ UNORDERED_STL="yes"] ) AC_ARG_ENABLE([cstring-key], [AS_HELP_STRING([--disable-cstring-key],[disable use of CString as the key for unordered_map and unordered_set (default=enabled)])], [ CSTRING_KEY=$enableval ], [ CSTRING_KEY="yes"] ) dnl if the headers are not found the variables are defined to 0 dnl for making dclib-stl-use.h if test "x${UNORDERED_STL}" = "xyes" then dnl C++0x locations - not currently available without -std=c++0x AC_CHECK_HEADER([unordered_map], [HAVE_UNORDERED_MAP_H=1], [HAVE_UNORDERED_MAP_H=0] ) AC_CHECK_HEADER([unordered_set], [HAVE_UNORDERED_SET_H=1], [HAVE_UNORDERED_SET_H=0] ) if test $ac_cv_header_unordered_map != $ac_cv_header_unordered_set then AC_MSG_ERROR([C++0x STL headers inconsistent, only one of unordered_map / unordered_set available]) AC_MSG_ERROR([Re-run configure with --disable-unordered-stl]) fi if test "x$ac_cv_header_unordered_map" = "xno" then dnl TR1 locations AC_CHECK_HEADER([tr1/unordered_map], [HAVE_TR1_UNORDERED_MAP_H=1], [HAVE_TR1_UNORDERED_MAP_H=0] ) AC_CHECK_HEADER([tr1/unordered_set], [HAVE_TR1_UNORDERED_SET_H=1], [HAVE_TR1_UNORDERED_SET_H=0] ) else HAVE_TR1_UNORDERED_MAP_H=0 HAVE_TR1_UNORDERED_SET_H=0 fi if test x${CSTRING_KEY} = "xyes" then AC_MSG_CHECKING([for some Fnv_hash]) if test "x$ac_cv_header_unordered_map" = "xyes" then AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include int main() { const char * data = "abcdef"; size_t hash = std::Fnv_hash<>::hash( data, 6 ); return 0; } ]] )], [ALLOW_CSTRING_KEY=1 FNV_HASH_PREFIXED=0 FNV_HASH_IS_TEMPLATE=1 AC_MSG_RESULT([Fnv_hash<>])], [AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include int main() { const char * data = "abcdef"; size_t hash = std::_Fnv_hash<>::hash( data, 6 ); return 0; } ]] )], [ALLOW_CSTRING_KEY=1 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=1 AC_MSG_RESULT([_Fnv_hash<>])], [AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include int main() { const char * data = "abcdef"; size_t hash = std::_Fnv_hash::hash( data, 6 ); return 0; } ]] )], [ALLOW_CSTRING_KEY=1 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=0 AC_MSG_RESULT([_Fnv_hash])], [ALLOW_CSTRING_KEY=0 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=0 AC_MSG_RESULT([no])])])] ) AC_MSG_CHECKING([for unordered_set with a custom key]) if test "x$ALLOW_CSTRING_KEY" = "x1" then AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include class MyClass { public: MyClass() {}; ~MyClass() {}; int x; }; bool operator == ( const MyClass & lhs, const MyClass & rhs ) { return lhs.x == rhs.x; } namespace std { template<> struct hash { size_t operator() (const MyClass & param) const { return param.x + 33; } }; template<> struct hash { size_t operator() (MyClass param) const { return param.x + 33; } }; } int main() { std::unordered_set myset; MyClass c1; c1.x = 90; MyClass c2; c2.x = 71; myset.insert(c1); myset.insert(c2); return 0; } ]] )], [AC_MSG_RESULT([ok])], [AC_MSG_RESULT([didn't work]) ALLOW_CSTRING_KEY=0] ) else AC_MSG_RESULT([dclib requires some Fnv_hash for this]) fi else AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include int main() { const char * data = "abcdef"; size_t hash = std::tr1::Fnv_hash<>::hash( data, 6 ); return 0; } ]] )], [ALLOW_CSTRING_KEY=1 FNV_HASH_PREFIXED=0 FNV_HASH_IS_TEMPLATE=1 AC_MSG_RESULT([Fnv_hash<>])], [AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include int main() { const char * data = "abcdef"; size_t hash = std::tr1::_Fnv_hash<>::hash( data, 6 ); return 0; } ]] )], [ALLOW_CSTRING_KEY=1 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=1 AC_MSG_RESULT([_Fnv_hash<>])], [AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include int main() { const char * data = "abcdef"; size_t hash = std::tr1::_Fnv_hash::hash( data, 6 ); return 0; } ]] )], [ALLOW_CSTRING_KEY=1 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=0 AC_MSG_RESULT([_Fnv_hash])], [ALLOW_CSTRING_KEY=0 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=0 AC_MSG_RESULT([no])])])] ) AC_MSG_CHECKING([for unordered_set with a custom key]) if test "x$ALLOW_CSTRING_KEY" = "x1" then AC_LINK_IFELSE([AC_LANG_SOURCE( [[ #include class MyClass { public: MyClass() {}; ~MyClass() {}; int x; }; bool operator == ( const MyClass & lhs, const MyClass & rhs ) { return lhs.x == rhs.x; } namespace std { namespace tr1 { template<> struct hash { size_t operator() (const MyClass & param) const { return param.x + 33; } }; template<> struct hash { size_t operator() (MyClass param) const { return param.x + 33; } }; } } int main() { std::tr1::unordered_set myset; MyClass c1; c1.x = 90; MyClass c2; c2.x = 71; myset.insert(c1); myset.insert(c2); return 0; } ]] )], [AC_MSG_RESULT([ok])], [AC_MSG_RESULT([didn't work]) ALLOW_CSTRING_KEY=0] ) else AC_MSG_RESULT([dclib requires some Fnv_hash for this]) fi fi else AC_MSG_CHECKING([custom key class for unordered_set]) AC_MSG_RESULT([disabled]) ALLOW_CSTRING_KEY=0 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=0 fi else HAVE_UNORDERED_MAP_H=0 HAVE_UNORDERED_SET_H=0 HAVE_TR1_UNORDERED_MAP_H=0 HAVE_TR1_UNORDERED_SET_H=0 ALLOW_CSTRING_KEY=0 FNV_HASH_PREFIXED=1 FNV_HASH_IS_TEMPLATE=0 fi AC_SUBST(HAVE_UNORDERED_MAP_H) AC_SUBST(HAVE_UNORDERED_SET_H) AC_SUBST(HAVE_TR1_UNORDERED_MAP_H) AC_SUBST(HAVE_TR1_UNORDERED_SET_H) AC_SUBST(ALLOW_CSTRING_KEY) AC_SUBST(FNV_HASH_PREFIXED) AC_SUBST(FNV_HASH_IS_TEMPLATE) ]) libdc0-0.3.24~svn3121/m4/lib-prefix.m40000644000175000017500000001503611014655145016053 0ustar sikonsikon# lib-prefix.m4 serial 5 (gettext-0.15) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing dnl the basename of the libdir, either "lib" or "lib64". AC_DEFUN([AC_LIB_PREPARE_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. The current dnl practice is that on a system supporting 32-bit and 64-bit instruction dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit dnl libraries go under $prefix/lib. We determine the compiler's default dnl mode by looking at the compiler's library search path. If at least dnl of its elements ends in /lib64 or points to a directory whose absolute dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the dnl default, namely "lib". acl_libdirstem=lib searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ])