commit 7dc1039c56f1f1a35707aea31b6bf10028f6c20e from: Sergey Bronnikov date: Wed Sep 07 19:58:27 2016 UTC Add wwwconf sources commit - 0cc8edab99deae5a987db984e957b733a51816ba commit + 7dc1039c56f1f1a35707aea31b6bf10028f6c20e blob - /dev/null blob + 100bf7c26d33a82dcded3ac21b6f353f7c25cfbc (mode 644) --- /dev/null +++ ChangeLog.txt @@ -0,0 +1,531 @@ +04.10.2001 - 06.10.2001 +Code cleanup in dbase.cpp: completly rewrite code for using CFreeDB class, +changed semaphores to file locks (*nix only), now it can be compiled in Win32 +(however, without flock()) + +06.10.2001 - 07.10.2001 +Added nested tags support, some cleanup in boardtags.cpp code. +Fixed logoff disappearing in lite version 1.0. + +11.10.2001 - 13.10.2001 +Fixed some bugs: in boardtags.cpp bug with right parsing invalid smile code (in strcat_ParseSmiles()), +in dbase.cpp memory leaks with body of the message (now body addressed as char**) and bug with fwrite() at the end of file. +Also added some interface strings in design.h. + +14.10.2001 +Added Webbbs to WWWConf convertor to project. + +20.10.2001 +Added change message support. + +27.10.2001 +Fixed some bugs in Webbbs convertor, and add links and images support. +Also fixed bug with very long words in reindex.cpp. + +28.10.2001 +Some perfomance optimization in indexer.cpp (removed word check and dynamic memory allocation). +Added cached indexes. + +16.11.2001 +Session ID now will be stored throught cookie. + +20.11.2001 +Added Fsize support throught Win32 functions under WIN32. + +15.12.2001 +Fixed bug in message editing... + +19.02.2002 +Change way for logging in error.cpp, now it support formats and variable count +of variables. Also added support for loggin exact point where printhtmlerror() +was called. + +12.03.2002 +Added topic support. + +27.04.2002 +Changed the way of generation session id. Now it use other way of random generation based statistic algorithm. + +28.04.2002 +Fixed bug in indexer.cpp, have a stable version now. + +01.05.2002 +Added anti-spam for read counter. + +17.06.2002 ‘„…‹€’œ á«¥¤¨âì §  ⥬®© (â।®¬) !!! § ¯®¬¨­ âì â¥¬ë §  ª®â®à묨 ­ã¦­® á«¥¤¨âì ¢ ¯à®ä ©«¥ ¯®«ì§®¢ â¥«ï !!! +¬ ªá¨¬ã¬ ¤® 10-20 ⥬. + +24.10.2002 +Fixed bug with nested tags (buffer overflow and stack corruption if more than 8 nested tags was in the message). + +25.10.2002 + +03.11.2002 +Removed username/password from the post message form for the registred users. + +06.11.2002 +Global changes in user profile storing (profiles.cpp now use hashindex instead of common indexer), some code cleanup. +Added hashindex.cpp/hashindex.h. + +07.11.2002 +Fixed support of Win32 platform: added R/W file locking. Some code cleanup. + +08.11.2002 +Fixed problem with preview. +Message storing format was changed - now all messages saved after preparse with native WWWConf tags (w/o convertion to HTML). +ParseBoardTags also have preparse and enter convertion ability now. + +10.11.2002 +First topic (by number) int the thread will not be showed (we assume that it's default topic). + +11.11.2002 +Added support for email ackn. + +12.11.2002 +Automatic logon after registration. + +18.11.2002 +Fixed bug in hashindex.cpp (right storing strings with same hash index). + +29.11.2002 +Fixed bug with compilation with TOPICS_SYSTEM_SUPPORT == 0. + +01.12.2002 +A lot of small fixes, including webbbs convertor (work with indigo). + +03.12.2002 +Added new security value for the user - SecHeader. Changed profile format (transparently, because of decrementing PASSWORD length by 1). +Fixed problem with preview and quoted text. +Added incremental indexing. +New version b17. +Russian nicknames will now be allowed +Added Makefile for bbsconv + +04.12.2002 +Microfix for the long profile name viewing. +Added stopindex to indexer. +Added autologin checkbox to the message form when posting as unregistred user. + +05.12.2002 +Added user name info while posting as logged in user. +Merge with aleczander - topbanner and bottombanner can be compiled as defines now, added USE_TEXT_BOTTOMBANNER and USE_TEXT_TOPBANNER defines. +Start working with CSS re-design. + +7.12.2002 +Added additional view - only headers of thread. + +9.12.2002 +Added IPaddress to Message structure (transparently, because of decrementing HOSTNAME string length by 4). +Fixed bug in incremental reindexer (reindex.cpp). +Check and fix for "message w/o body" symbol at the end of the message header. +Started work with USER_PROFILES_SUPPORT define (not completed yet). +Returned email ackn. check box while posting as unreg. user. + +10.12.2002 +Some perfomance relative changes in bbsconv. + +12.12.2002 +Changed the way of signature interpretation in empty messages. Signature will be ignored from now. +Added reference to posted message in "post complete" message. +Fixed little bug in hostname resolve if strlen of hostname == 0. +Fixed little bug - title in browser incorrectly displayed after configure. + +17.12.2002 +Fixed problem with "+" through cookie w/o expiration time. +Added "To Message" when viewing large threads. +New version b18. + +18.12.2002 +Fixed small bug with +. +Do not allow name, header or body of the message containing spaces only. +Fixed possible buffer overflow with long host names. +Fixed some memory leaks. +Fixed topic dissapearing during message preview. + +19.12.2002 +Fixed problem with repeating No-message tag in the message (will be deleted from now). +Added message about index viewing style (Merges with aleczander). +Some fixes connected with css support (Merges with aleczander). +Added define for turn off locale setting (Merges with aleczander). + +20.12.2002 +Some fixes in logins.cpp (large session count problem). +ResetNew implemented as redirect now. +Added POST_ALLOW_UNDER_SAME_NICK define to allow modify behaviour of the board. +Fixed bug with AuthorName and Subject length. + +21.12.2002 +Fixed bug with nick names with spec. symbols. +Configure now will redirect to index page. +Fixed little bug in configuration form. + +22.12.2002 +Enabled email ackn (seems that it works). + +24.12.2002, alec +Added second bar with static links. +Partially fixed bug 'returning to index from rolled thread'. + +26.12.2002, alec +Added email printing to profman -v. + +29.12.2002 +Fixed memory damage in cookies. +Changed the way working with message flags during message post - now parent flags MESSAGE_IS_INVISIBLE, MESSAGE_COLLAPSED_THREAD and MESSAGE_IS_CLOSED will be applyed to child message too. It also completely fixed bug 'returning to index from rolled thread'. +Added lost password form. + +30.12.2002, alec +Translatation of email messages, acknowledgw and password retrival +Fixed in-thread navigation (MESSAGEHEAD_to_message link was broken in rolled threads). +Now we allow to post to the last 15k messages only. +Added logging for admin tasks: close, roll, hide, delete. + +03.01.2003, www +Fixed ***very important*** bug connected with absence fflush() call before unlock file. It could lead to database corruption. + +05.01.2003, www +Changed interpretation of ban rules... added allow and deny rules + +07.01.2003, www +Fixed bug with several collapsed threads going one after another. +New messages will be marked in collapsed threads too. +New version b19. + +11.01.2003, alec +Added new topic, links... + +12.01.2003, www +Added last user IP in user information structure in profile (visible only to admin). +Changed the way of interpretation of last login date of user. It's last access date now and updated after every access of the user. +Fixed bugs with showing several invisible and collapsed threads going one after another. +Added IP of poster in message view for administrator. + +13.01.2003, www +Added updating date and last IP address during posting as registred user. +Fixed bug with invisible threads corrupting message index for common users. + +14.01.2003, alec +Partially translated faq-help.html, fixed rules.html, authors.html. +Added link to rules.html to links bar. + +16.01.2003, www +Fixed bug (added 13.01.2003) with several collapsed thread going one after another. + +19.01.2003, www +Added pages to the search result. + +20.01.2003, www +Fixed problem connected with navigation problem to index when posting to the rolled thread. + +21.01.2003, www +Fixed problem showing collapsed thread when topic filter active. +Added modification to the profile system, added user status. +Added user modification form to the profile view (for admin). + +22.01.2003, alec +Moved from DL+DD to DIV+BR, div2.diff + board.css patching +Removed first style of viewing, MESSAGEHEAD_configure_showhronforward (div3.diff) + +22.01.2003, www +Added printing new message count in collapsed thread. +Disabled smile translation in PRE. + +23.01.2003, www +Fixed little problem with new message count in collapsed thread. +Added url autoparsing (expiremental). Very dirty code now. +alec: DL+DD<->DIV+BR autodetect for Links and Lynx useragents added (auto_dd.diff), + inserted board.css to messages.h +alec: rewrited Makefile + +24.01.2003, www +Fixed bug in url autoparsing. + +25.01.2003, www +alec: New version of *nix makefile (support dependencies now). +Added checking url flags during url autoparsing. +In [url] tag parser added autoadding http:// if it not specified in url. + +26.01.2003, www +Added quick topic modification. + +27.01.2003, alec +changed ALLOW_MARK_NEW_MESSAGES could be 1 or 2 now +cosmetic changes, devold/cosmetic1.diff + +30.01.2003, alec +* fixed bug: admin could not preview messages because of error in topic edit + form (devold/admin_preview.diff) +* fixed css, now works for mozilla (devold/css_fix.diff) + +31.01.2003, alec +* added javascript for check/uncheck all topics +* Mozilla/2.02 added to DL autodetect +* HTML cleanup, all TH -> TD (what's TH ? :)) +* one patch: devold/java_checkall.diff +* fixed my bug in RT_REDIRECT, now /board/index.cgi?read=XX is redirecting + to /index.cgi?read=XX + +02.02.2003, www +Fixed memory allocation bug in GenerateHashwordList() in hashindex.cpp. +alec/www: Added sort modes in user list (currently: by name, by access date, by post count, by ip). +Changed the way working with signatures, it will be added automatically to message w/o printing to form. +patches: (userlist.diff, userlist2.diff) + +03.02.2003, www +Minor fixes. +Added user right modification by admin. +New version b20. + +04.02.2003, alec +* added Topics_List_map for listing Topics in desired order in forms(topics_map.diff) +www: Fixed little bug with tag parsing like [hr]. + +14.02.2003 +Added personal message support. + +18.02.2003, alec +* simplified DB_Base::printhtmlmessage_in_index +* minor html changes in personal messages +* added target=_blank to search results + +21.02.2003 +Fixed new message dissapearing in resetnew command. + +23.02.2003 +Added history to personal messages. +Link in messages will now be underlined. + +24.02.2003 +Fixed appearing url in message containing only pictures. + +25.02.2003 +Some bugs fixed in personal messages (viewing). + +26.02.2003 +Fixed some little bugs in personal messages. + +01.03.2003 +Added private message manager to the project (prvman). + +02.03.2003 +Added announce support. +In personal message added new error message "too long message". +Added refresh count (incrementing every refresh) to the user profiles. + +03.03.2003 +Added sorting by refresh count to "all users". +Added banner picture and 2-d link bar disable to configuration form. + +05.03.2003 +user right caching no longer supported. +Added new smiles (from -=MC=-). + +06.03.2003 +Added announce hiding/showing trought cookies. + +07.03.2003 +Some interfaces and translation fixes. +Removed prvman from project, all functionality moved to profman. +Fixed little bug in header of brower (cutting tags was incorrect). + +08.03.2003 +A lot of interface fixes in profiles. +Fixed bug with applying new password during profile edit. +Added ERROR_ON_SCREEN define to allow printing exact line/file of error to user browser. +Serious code cleanup in main.cpp. + +09.03.2003 +Added announce update. + +12.03.2003 +Fixed compilation problem under Win32, some small interface fixes in profman, indexbuilder. + +14.03.2003 +Fixed important bugs in hashindex.cpp. + +16.03.2003 +Fixed HTML filtering in signature. +Some changes in profile creation/modification in main.cpp. + +17.03.2003 +Fixed problem with profile creation with null password (core dump acquired sometimes). + +18.03.2003 +Fixed bug with url preparsing when tags was disabled. + +20.03.2003 +Fixed bug in hashindex.cpp (delete). +Added last indexed message information to the search page. +New version 2.0 pre beta1. + +23.03.2003 +Fixed some bugs with session management in logins.cpp, increased default session read buffer size. +Added USER_SESSION_LIVE_TIME to basetypes.h. + +30.03.2003 +Changed design of conference (different thread dividers). +Added main thread counter. + +04.04.2003 +Added own name colouring in message index. + +05.04.2003 +Some source code cleanup, more detailed comments (basetypes.h). + +26.04.2003 +Code cleanup, added decrementation of main thread counter during delete. +Fixed new messages cookie refresh to "index only" refresh. + +27.04.2003 +Fixed workaround across announces (disabling it by cookie). + +28.04.2003 +Removed call to printing if topic mask is NULL. + +29.04.2003, alec (back from nowhere :)) +* replaced threads colors alternating from table to div && css + added DESIGN_open_dl_grey, css class "g", alternating grey color is DESIGN_THREADS_DIVIDER_grey +* added cookie config option: if "+" acts as a link to the next new message +* css classes names shortening: emplus->e + +05.05.2003, www +Fixed bug with post time check if password is invalid. + +07.05.2003, www +Added javascript to prevent duplicate post. +Fixed some bugs in HTML. +Fixed bug with maximum subject size in message. + +08.05.2003, www +Added some parsing features (like ftp://) to boardtags.cpp. +Returned email ackn checkbox to not logged in users. + +19.05.2003, alec, 20030519-autoparse-uinfo.diff +* added https autoparsing, changed parsing code a bit +* changes to CodeHttpString, uinfo link is now http-coded +www: Added own function for time/data translation to human readable format. + +23.05.2003, alec, 20030523-whitespace-title.diff +* added FilterWhitespaces and filtering of ui->username when registering and + mes.MessageHeader when posting a new message + TODO: add filter to username if unregister posting +* added filling database files with first 4 bytes in case if files are empty, + to avoid msg_id=0 in new boards +* added printing of current topic to title (if any) + +28.05.2003, www +Added greetings to login message. +Added chexbox for disabling host name displaying in index. +Added selected nick names coloring. + +29.05.2003, www +Fixed some bugs with previous modification. +Added private messages email ackn. +Added checkbox to disable using private messages. + +31.05.2003, www +Added preview for private messages and announces. +Some code simplifying and modification in private messages printing. +Added new feature "always send email ackn. for every post" to user profile. +Fixed bug with invalid http encoding some urls. +CodeHttpString() and FilterHTMLTags() in speller.cpp now can allocate storage from internal buffer, but default behaviour didn't change. +Removed ICQ info in user profile if ICQ didn't specified. +New version to 2.0 pre beta2. + +07.06.2003, www +Added alternative displaying name (different from username) and right for use it. + +12.06.2003, www +Fixed 2 vulnerabilities for Microsoft IE in tag parsing (allowed to use HTML). +Changed color of empty message sign to BLACK. +Changed encoding/title order in the HTML header, added encoding macro to messages.h. + +13.06.2003, www +Changed the way of quick topic navigation, now cookies are used. + +14.06.2003, www +Added checkbox for disabling alternative nick displaying. + +16.06.2003, www +Some bugs with parsing names and html tags was fixed. + +20.06.2003, www +Added disable signature checkbox to user settings. + +21.06.2003, www +Session cookie is now attached to IP address. + +27.06.2003, www +Added new sort mode to userlist (by right). +Some design changes in post message form. + +01.07.2003, merge with hlt +Fixed post problem under IIS (use CONTENT_LENGTH env. variable). +Minor memory fixes. +Fixed problem under Win32 with Fsize() bug check if file was already opened. +www: Optionalize HTTP_REFERER check. + +02.07.2003, www +Fixed bug with displaying several rolled threads coming one after another. +Added signature printing to profman. + +30.09.2003, www +Some interface fixes in search. +Added checkbox about updating announce id to update announce form. +Merge with demon: + * Allow admin post to closed threads + * Some source code fixes + * Favourites thread support + +01.10.2003, www +Added checkbox to login form about session ip check. +Enlarged session sequence to 8 bytes. + +07.10.2003, www +Added activity log for last 10 min (hits/hosts). +Added last posted message printing in collapsed threads. +Changed version to 2.0 pre beta3. + +09.10.2003, www +A lot of design changes (removed bottom link bar, etc.) +Added checkbox to disable reply form in message view page. + +14.10.2003, www +Little fix in profiles.cpp (sort user fix) - USERRIGHT_SUPERUSER will only be placed to right if other right exists in all profiles list. Allows viewing all moderators in one group. +Some code cleanup, added define for disabling activity log support. + +11.05.2004, www +New distributive creation was started. +Profman and reindex was merged to wcmanager tool. + +18.07.2004, www +Added change message feature. + +18.08.2004, demon +Fixed bug with default settings while opening configure=action +Added saving view configuration to profile +Added simple banned list editor +Added mail subject encoding (base64), going to rfc in mail +Added new board tags ( SUP, SUB and STRIKE) +Removed p.gif between threads, added border style for threads div's +Style changes ( body, table, padding, margin and others) +Changed version to 2.0 pre beta4. + +22.08.2004, www +Some code simplifications for main.cpp. + +?, www +Timezone support added. + +25.10.2004, demon +Timezone setting added to profile. +Removing SCookies[] massive, cookies parsing reforming. +Changing new session behavior - all messages are in read state. + +27.10.2004, demon +Fixed security check (flag to allow creating new message and thread) +Design bug - unclosed tag. + +21.01.2005, hlt (demon - it's rolled back due to bug?!) +Fixed persmsg to users with html chars in their names - now names are stored in db as raw, not escaped html +Fixed issue with ?persmsgform not filtering html tags (html javascript script injection exploit) blob - /dev/null blob + a9d7f05cf1373a972625cf289d82bb91fc219259 (mode 644) --- /dev/null +++ src/Makefile @@ -0,0 +1,71 @@ +# +# Makefile for wwwconf, version by alec@3ka.mipt.ru +# Created 24.01.2003 +# + +CC=g++ +# -pg -g +CXX=$(CC) + +FILES_INDEX= sha1.cpp statfs.cpp dbase.cpp main.cpp announces.cpp boardtags.cpp speller.cpp security.cpp freedb.cpp indexer.cpp profiles.cpp logins.cpp hashindex.cpp searcher.cpp error.cpp sendmail.cpp colornick.cpp activitylog.cpp +FILES_DBTOOL= freedb.cpp profiles.cpp hashindex.cpp profman.cpp indexer.cpp searcher.cpp +SOURCES=$(FILES_INDEX) $(FILES_DBTOOL) + +OBJECTS_INDEX= $(FILES_INDEX:.cpp=.o) +OBJECTS_DBTOOL= $(FILES_DBTOOL:.cpp=.o) + +prefix=/home/estet/wwwconf10 +inst = /usr/bin/install -c + +CFLAGS:= -O2 -fno-exceptions + + +#.if (.depend,$(wildcard .depend)) +#include .depend +#.else +#@echo "You do not have dep file, run make dep" +#.endif + +all: index dbtool + @echo Compiling Done + +index: $(OBJECTS_INDEX) + $(CC) $(CFLAGS) -o index.cgi $(OBJECTS_INDEX) +dbtool: $(OBJECTS_DBTOOL) + $(CC) $(CFLAGS) -o dbtool $(OBJECTS_DBTOOL) + +# +# include dependency files if they exist +# +#ifneq ($(wildcard .depend),) +#include .depend +#endif + +#creating dependencies +dep: + @echo "Creating .depend" + @rm -f .depend + $(CC) -MM -MG $(SOURCES) >> .depend + + +clean: + @rm -f *.o + @rm -f index.cgi dbtool + @echo Clean complete + +install: all + @echo Installing binaries and tools to ${prefix} + cp ${prefix}/dbtool ${prefix}/dbtool_prev + cp ${prefix}/index.cgi ${prefix}/index.cgi_prev + ${inst} -m 751 index.cgi ${prefix}/index.cgi + ${inst} -m 750 dbtool ${prefix} + +uninstall: ${prefix}/index.cgi_prev ${prefix}/dbtool_prev + @echo UnInstalling backed up binaries and tools + cp ${prefix}/index.cgi_prev ${prefix}/index.cgi + cp ${prefix}/dbtool_prev ${prefix}/dbtool + +fake: index + @echo Installing binaries and tools to ${prefix} + ${inst} -m 751 index.cgi ${prefix}/index-dev.cgi + ${inst} -m 750 dbtool ${prefix}/dbtool-dev blob - /dev/null blob + 48853d6df89f37f04996ab170b75b772c0d4e350 (mode 644) --- /dev/null +++ src/activitylog.cpp @@ -0,0 +1,247 @@ +/*************************************************************************** + activitylog.cpp - board activity logger + ------------------- + begin : Mon Oct 6 2003 + copyright : (C) 2003 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "activitylog.h" + +#define ACTIVITY_CONTROL_TIME 10*60 // 10min +#define BLOCKREADCOUNT 1000 + +void inline swap(DWORD *a, DWORD *b) +{ + register DWORD t=*a; + *a=*b; + *b = t; +} + +int RegisterActivityFrom(DWORD IP, DWORD &hostcnt, DWORD &hitcnt) +{ + WCFILE *f = NULL, *f1 = NULL; + DWORD tm, tm1, fin, fin1; + int disfileok = 0, addfileok = 0, finalizedone = 0, swapdone = 0; + hostcnt = hitcnt = 0; + DWORD crtime = time(NULL); + + if((f = wcfopen(F_ACTIVITYLOG1, FILE_ACCESS_MODES_RW)) == NULL) { + // create file + if((f = wcfopen(F_ACTIVITYLOG1, FILE_ACCESS_MODES_CW)) != NULL) + { + DWORD x[2]; + memset(x,0,8); + fCheckedWrite(&x, 8, f); + wcfclose(f); + f = wcfopen(F_ACTIVITYLOG1, FILE_ACCESS_MODES_RW); + if(f) lock_file(f); + } + else goto failed; + } + else lock_file(f); + if((f1 = wcfopen(F_ACTIVITYLOG2, FILE_ACCESS_MODES_RW)) == NULL) { + // create file + if((f1 = wcfopen(F_ACTIVITYLOG2, FILE_ACCESS_MODES_CW)) != NULL) + { + DWORD x[2]; + memset(x,0,8); + fCheckedWrite(&x, 8, f1); + wcfclose(f1); + f1 = wcfopen(F_ACTIVITYLOG2, FILE_ACCESS_MODES_RW); + if(f1) lock_file(f1); + } + else goto failed; + } + else lock_file(f1); + + if(!fCheckedRead(&tm, 4, f)) + goto failed; + if(!fCheckedRead(&tm1, 4, f1)) + goto failed; + if(!fCheckedRead(&fin, 4, f)) + goto failed; + if(!fCheckedRead(&fin1, 4, f1)) + goto failed; + + // find file for displaying (it will be f1) + if(crtime - 2*ACTIVITY_CONTROL_TIME <= tm && tm < crtime - ACTIVITY_CONTROL_TIME ) + { + swap((DWORD*)(&f), (DWORD*)(&f1)); + swap(&tm, &tm1); + swap(&fin, &fin1); + + // to know path to the file + swapdone = !swapdone; + + disfileok = 1; + } + if(crtime - 2*ACTIVITY_CONTROL_TIME <= tm1 && tm1 < crtime - ACTIVITY_CONTROL_TIME ) + { + disfileok = 1; + } + + // find file for saving (will be f) + if(crtime - ACTIVITY_CONTROL_TIME <= tm && tm < crtime) + { + addfileok = 1; + } + if(crtime - ACTIVITY_CONTROL_TIME <= tm1 && tm1 < crtime) + { + swap((DWORD*)(&f), (DWORD*)(&f1)); + swap(&tm, &tm1); + swap(&fin, &fin1); + + // to know path to the file + swapdone = !swapdone; + + addfileok = 1; + } + + // parse file with display information + if(disfileok) { + if(!fin1) { + DWORD rr, cn, i; + SActivityLogRecord* buf; + + // finalize file + buf = (SActivityLogRecord*)malloc(sizeof(SActivityLogRecord)*BLOCKREADCOUNT); + while(!wcfeof(f1)) { + rr = wcfread(buf, 1, sizeof(SActivityLogRecord)*BLOCKREADCOUNT, f1); + + if((rr%sizeof(SActivityLogRecord)) != 0) { + /* read error */ + break; + } + cn = rr/sizeof(SActivityLogRecord); + hostcnt += cn; + for(i = 0; i < cn; i++) { + hitcnt += buf[i].Count; + } + } + free(buf); + wcfflush(f1); + // truncate end of file +#ifdef WIN32 + wctruncate(f1, 4); +#else + truncate(swapdone ? F_ACTIVITYLOG1 : F_ACTIVITYLOG2, 4); +#endif + wcfseek(f1, 0, SEEK_END); + rr = 1; + fCheckedWrite(&rr, 4, f1); + fCheckedWrite(&hitcnt, 4, f1); + fCheckedWrite(&hostcnt, 4, f1); + finalizedone = 1; + } + else { + // just read info from file + fCheckedRead(&hitcnt, 4, f1); + fCheckedRead(&hostcnt, 4, f1); + } + // release file lock as soon as possible (won't wait for the end of this fuction) + wcfflush(f1); + unlock_file(f1); + wcfclose(f1); + f1 = NULL; + } + + if(addfileok) { + DWORD rr, cn, pos, done = 0, i; + SActivityLogRecord* buf; + + // add ip to file + buf = (SActivityLogRecord*)malloc(sizeof(SActivityLogRecord)*BLOCKREADCOUNT); + while(!wcfeof(f)) { + pos = wcftell(f); + rr = wcfread(buf, 1, sizeof(SActivityLogRecord)*BLOCKREADCOUNT, f); + + if((rr%sizeof(SActivityLogRecord)) != 0) { + /* read error */ + done = 1; + break; + } + cn = rr/sizeof(SActivityLogRecord); + for(i = 0; i < cn; i++) { + if(buf[i].IP == IP) { + buf[i].Count++; + buf[i].Time = time(NULL); + done = 1; + wcfseek(f, pos, SEEK_SET); + fCheckedWrite(buf, sizeof(SActivityLogRecord)*(i+1), f); + break; + } + } + if(done) break; + } + free(buf); + if(!done) { + SActivityLogRecord ss; + ss.Count = 1; + ss.IP = IP; + ss.Time = crtime; + wcfseek(f, 0, SEEK_END); + fCheckedWrite(&ss, sizeof(SActivityLogRecord), f); + } + } + else { + DWORD rr; + SActivityLogRecord ss; + + // if it's filalized file, let's add activity to the history + if(fin) { + WCFILE *f2; + DWORD buf[3]; + // add to achive + fCheckedRead(&hitcnt, 4, f); + fCheckedRead(&hostcnt, 4, f); + + if((f2 = wcfopen(F_ACTIVITYARCH, FILE_ACCESS_MODES_RW)) == NULL) { + // create file + f2 = wcfopen(F_ACTIVITYARCH, FILE_ACCESS_MODES_CW); + } + + if(f2 != NULL) { + lock_file(f2); + wcfseek(f2, 0, SEEK_END); + buf[0] = tm; buf[1] = hitcnt; buf[2] = hostcnt; + fCheckedWrite(&buf, 12, f2); + wcfflush(f2); + unlock_file(f2); + wcfclose(f2); + } + } + + ss.Count = 1; + ss.IP = IP; + ss.Time = crtime; + + wcfflush(f); +#ifdef WIN32 + wctruncate(f, 8); +#else + truncate(swapdone ? F_ACTIVITYLOG2 : F_ACTIVITYLOG1, 4); +#endif + wcfseek(f, 4, SEEK_SET); + rr = 0; + fCheckedWrite(&rr, 4, f); + fCheckedWrite(&ss, sizeof(SActivityLogRecord), f); + // make header + wcfseek(f, 0, SEEK_SET); + if(!finalizedone) rr = crtime; + else rr = tm1 + ACTIVITY_CONTROL_TIME; + fCheckedWrite(&rr, 4, f); + } +failed: + if(f) { + wcfflush(f); + unlock_file(f); + wcfclose(f); + } + if(f1) { + wcfflush(f1); + unlock_file(f1); + wcfclose(f1); + } + return 0; +} blob - /dev/null blob + e48669e376b52b1e908fcc19b4112d1f0a370425 (mode 644) --- /dev/null +++ src/activitylog.h @@ -0,0 +1,23 @@ +/*************************************************************************** + activitylog.h - board activity logger header + ------------------- + begin : Mon Oct 6 2003 + copyright : (C) 2003 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef ACTYVITYLOG_H_INCLUDED +#define ACTYVITYLOG_H_INCLUDED + +#include "basetypes.h" + +struct SActivityLogRecord +{ + DWORD IP; + DWORD Count; + DWORD Time; +}; + +int RegisterActivityFrom(DWORD IP, DWORD &hostcnt, DWORD &hitcnt); + +#endif blob - /dev/null blob + 861a225fb0afbe4b99565df6eb1e979fb951f040 (mode 644) --- /dev/null +++ src/announces.cpp @@ -0,0 +1,323 @@ +/*************************************************************************** + announces.cpp - board announces support + ------------------- + begin : Mon Feb 24 2003 + copyright : (C) 2001 - 2003 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "announces.h" +#include "error.h" + +static void* CreateAnnounceFile() +{ + FILE *f; + f = fopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_CW); + if(f) { + // announces number starting from 1 + DWORD x = 1; + // write starting unique id + if(fwrite(&x, 1, sizeof(x), f) != sizeof(x)) { + fclose(f); + f = NULL; + } + else { + fclose(f); + f = fopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_RW); + } + } + return f; +} + +static void* CreateAnnounceWCFile() +{ + WCFILE *f; + f = wcfopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_CW); + if(f) { + // announces number starting from 1 + DWORD x = 1; + // write starting unique id + if(wcfwrite(&x, 1, sizeof(x), f) != sizeof(x)) { + wcfclose(f); + f = NULL; + } + else { + wcfclose(f); + f = wcfopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_RW); + } + } + return f; +} + +int ReadLastAnnounceNumber(DWORD *an) +{ + FILE *f; + int ret = 0; + + f = fopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_RW); + if(!f) return 0; + if(fread(an, 1, sizeof(DWORD), f) == sizeof(DWORD)) + ret = 1; + fclose(f); + return ret; +} + +int PostGlobalAnnounce(char *username, DWORD uniqid, char *announce, DWORD ttl, DWORD flags) +{ + WCFILE *f; + DWORD siz; + SGlobalAnnounce an; + DWORD id; + + if((f = wcfopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_RW)) == NULL) { + if((f = (WCFILE*)CreateAnnounceWCFile()) == NULL) { + return ANNOUNCES_RETURN_IO_ERROR; + } + } + // prepare announce structure + strcpy(an.Announce, announce); + strcpy(an.From, username); + an.UIdFrom = uniqid; + an.TTL = ttl; + an.Date = time(NULL); + an.Flags = flags; + memset(an.Reserved, 0, sizeof(an.Reserved)); + // write announce + lock_file(f); + if(!fCheckedRead(&id, sizeof(id), f)) { + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + // save number + an.Number = id; + // increment number + id++; + if(wcfseek(f, 0, SEEK_SET) != 0) { + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_IO_ERROR; + } + if(!fCheckedWrite(&id, sizeof(id), f)) { + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_IO_ERROR; + } + if(wcfseek(f, 0, SEEK_END) != 0) { + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_IO_ERROR; + } + // start transcation + siz = wcftell(f); + if(!fCheckedWrite(&an, sizeof(SGlobalAnnounce), f)) { + // rolling back +#ifdef WIN32 + wctruncate(f, siz); +#else + truncate(F_GLOBAL_ANN, siz); +#endif + id--; + if(wcfseek(f, 0, SEEK_END) == 0) { + fCheckedWrite(&id, sizeof(id), f); + } + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_IO_ERROR; + } + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_OK; +} + +int ReadGlobalAnnounces(time_t ct, SGlobalAnnounce **ga, DWORD *cnt) +{ + FILE *f; + DWORD i = 0, rd; + SGlobalAnnounce *an; + + *ga = NULL; + *cnt = 0; + + an = (SGlobalAnnounce*)malloc(sizeof(SGlobalAnnounce)); + if(!an) return ANNOUNCES_RETURN_LOW_RES; + + if((f = fopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_R)) == NULL) { + if((f = (FILE*)CreateAnnounceFile()) == NULL) { + free(an); + return ANNOUNCES_RETURN_IO_ERROR; + } + } + if(fseek(f, sizeof(DWORD), SEEK_SET) != 0) { + free(an); + return ANNOUNCES_RETURN_IO_ERROR; + } + while(!feof(f)) + { + if((rd = fread(&(an[i]), 1, sizeof(SGlobalAnnounce), f)) != sizeof(SGlobalAnnounce)) { + if(rd != 0) { + free(an); + fclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + else break; + } + i++; + an = (SGlobalAnnounce*)realloc(an, (i+1)*sizeof(SGlobalAnnounce)); + } + fclose(f); + *cnt = i; + *ga = an; + return ANNOUNCES_RETURN_OK; +} + +int DeleteGlobalAnnounce(DWORD id, DWORD uniqid) +{ + WCFILE *f; + DWORD pos, fsize, rd; + SGlobalAnnounce *an; + + an = (SGlobalAnnounce*)malloc(sizeof(SGlobalAnnounce)); + if(!an) return ANNOUNCES_RETURN_LOW_RES; + + if((f = wcfopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_RW)) == NULL) { + free(an); + return ANNOUNCES_RETURN_IO_ERROR; + } + lock_file(f); + if(wcfseek(f, sizeof(DWORD), SEEK_SET) != 0) { + free(an); + return ANNOUNCES_RETURN_IO_ERROR; + } + an->Number = 0xffffffff; + while(!wcfeof(f)) + { + pos = wcftell(f); + if((rd = wcfread(an, 1, sizeof(SGlobalAnnounce), f)) != sizeof(SGlobalAnnounce)) { + if(rd != 0) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + else break; + } + if(an->Number == id && (uniqid == 0 || an->UIdFrom == uniqid)) break; + } + if(an->Number == id) { + // let's delete it + int i = 0; + while(!wcfeof(f)) + { + if((rd = wcfread(&(an[i]), 1, sizeof(SGlobalAnnounce), f)) != sizeof(SGlobalAnnounce)) { + if(rd != 0) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + else break; + } + i++; + an = (SGlobalAnnounce*)realloc(an, (i+1)*sizeof(SGlobalAnnounce)); + } + fsize = wcftell(f); + fsize -= sizeof(SGlobalAnnounce); + if(wcfseek(f, pos, SEEK_SET) != 0) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + if(wcfwrite(an, 1, sizeof(SGlobalAnnounce)*i, f) != sizeof(SGlobalAnnounce)*i) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + free(an); + // !!!!!!!!!!!! + wcfflush(f); + // truncate end of file +#ifdef WIN32 + wctruncate(f, fsize); +#else + truncate(F_GLOBAL_ANN, fsize); +#endif + unlock_file(f); + wcfclose(f); + } + else { + // announce not found + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_NOT_FOUND; + } + + return ANNOUNCES_RETURN_OK; +} + +int UpdateGlobalAnnounce(DWORD id, char *username, DWORD uniqid, char *announce, + DWORD ttl, DWORD flags, DWORD updateopt) +{ + WCFILE *f; + DWORD pos, rd; + SGlobalAnnounce *an; + + an = (SGlobalAnnounce*)malloc(sizeof(SGlobalAnnounce)); + if(!an) return ANNOUNCES_RETURN_LOW_RES; + + if((f = wcfopen(F_GLOBAL_ANN, FILE_ACCESS_MODES_RW)) == NULL) { + free(an); + return ANNOUNCES_RETURN_IO_ERROR; + } + lock_file(f); + if(wcfseek(f, sizeof(DWORD), SEEK_SET) != 0) { + free(an); + return ANNOUNCES_RETURN_IO_ERROR; + } + an->Number = 0xffffffff; + while(!wcfeof(f)) + { + pos = wcftell(f); + if((rd = wcfread(an, 1, sizeof(SGlobalAnnounce), f)) != sizeof(SGlobalAnnounce)) { + if(rd != 0) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + else break; + } + if(an->Number == id) break; + } + if(an->Number == id) { + // let's update it + strcpy(an->Announce, announce); + if((updateopt & ANNOUNCES_UPDATE_OPT_USER)) { + strcpy(an->From, username); + an->UIdFrom = uniqid; + } + if((updateopt & ANNOUNCES_UPDATE_OPT_TTL)) an->TTL = ttl; + if((updateopt & ANNOUNCES_UPDATE_OPT_TIME)) an->Date = time(NULL); + if((updateopt & ANNOUNCES_UPDATE_OPT_FLAGS)) an->Flags = flags; + memset(an->Reserved, 0, sizeof(an->Reserved)); + if(wcfseek(f, pos, SEEK_SET) != 0) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + if(wcfwrite(an, 1, sizeof(SGlobalAnnounce), f) != sizeof(SGlobalAnnounce)) { + free(an); + wcfclose(f); + return ANNOUNCES_RETURN_DB_ERROR; + } + free(an); + unlock_file(f); + wcfclose(f); + } + else { + // announce not found + unlock_file(f); + wcfclose(f); + return ANNOUNCES_RETURN_NOT_FOUND; + } + + return ANNOUNCES_RETURN_OK; + +} blob - /dev/null blob + 81ecc93e81e05ec8ed4365861a86ead3b7717e1a (mode 644) --- /dev/null +++ src/announces.h @@ -0,0 +1,68 @@ +/*************************************************************************** + announces.h - board announces support header + ------------------- + begin : Mon Feb 24 2003 + copyright : (C) 2001 - 2003 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef ANNOUNCES_H_INCLUDED +#define ANNOUNCES_H_INCLUDED + +#include "basetypes.h" +#include "profiles.h" + +#define GLOBAL_ANNOUNCE_MAXSIZE 513 + +#define ANNOUNCES_RETURN_OK 0 +#define ANNOUNCES_RETURN_IO_ERROR 1 +#define ANNOUNCES_RETURN_DB_ERROR 2 +#define ANNOUNCES_RETURN_LOW_RES 3 +#define ANNOUNCES_RETURN_NOT_FOUND 4 + +#define ANNOUNCES_UPDATE_OPT_USER 0x01 +#define ANNOUNCES_UPDATE_OPT_TIME 0x02 +#define ANNOUNCES_UPDATE_OPT_FLAGS 0x04 +#define ANNOUNCES_UPDATE_OPT_TTL 0x08 + +#pragma pack(1) +struct SGlobalAnnounce { + char Announce[GLOBAL_ANNOUNCE_MAXSIZE]; + + char From[PROFILES_MAX_USERNAME_LENGTH]; + DWORD UIdFrom; // UniqID of poster + + time_t Date; // post date + DWORD TTL; // Time To Live of this announce + + DWORD Flags; // flags of the post + + DWORD Number; // unique announce number (for identification) + + DWORD Reserved[2]; // reserved for the future use +}; +#pragma pack(4) + +/* Post announce as selected user. + * It don't check security permitions of poster ! + */ +int PostGlobalAnnounce(char *username, DWORD uniqid, char *announce, DWORD ttl, DWORD flags); + +/* Read annonces that implies to 'ct' date. (!!! ignored for now !!!) + */ +int ReadGlobalAnnounces(time_t ct, SGlobalAnnounce **ga, DWORD *cnt); + +/* Delete global announce by id + */ +int DeleteGlobalAnnounce(DWORD id, DWORD uniqid); + +/* Read last used announce number + */ +int ReadLastAnnounceNumber(DWORD *an); + +/* Update announce (using updateopt flags) by id + */ +int UpdateGlobalAnnounce(DWORD id, char *username, DWORD uniqid, char *announce, + DWORD ttl, DWORD flags, DWORD updateopt); + +#endif // of ANNOUNCES_H_INCLUDED blob - /dev/null blob + 7be775ecde49bc54c007ad713bc64745b14ffe86 (mode 644) --- /dev/null +++ src/basetypes.h @@ -0,0 +1,547 @@ +/*************************************************************************** + basetypes.h - base types and definitions + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef BASETYPES_H_INCLUDED +#define BASETYPES_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +/****************** Log&Debug ******************/ +// can be 0 or 1 +// 0 - disabled [Recomended] +// 1 - enabled +#define _DEBUG_ 1 +// +// can be 0, 1, 2 +// 0 - fully disable, even critical errors +// 1 - disable, but critical error [Recommended] +// 2 - fully enable (information, critical errors, etc.) +#define ENABLE_LOG 2 +// +// should file and string of each global error be showed to the user (useful for debug) +#define ERROR_ON_SCREEN 1 +/***********************************************/ + +/*************************** language and locale ***************************/ +#ifdef WIN32 +#define LANGUAGE_LOCALE "Russian" // Windows +#else +#define LANGUAGE_LOCALE "ru_RU.CP1251" // Unix +#endif + +// should we set up locale during initialization +#define USE_LOCALE 0 + +#define RT_REDIRECT 1 + +// spelling check before post message +#define SPELLING_CHECK 1 + +// banned ip check before post message +#define BANNED_CHECK 1 + +// if message body not have be empty +#define MSG_REQURED_BODY 0 + +// enable IP to DNS name reslove Host Addresses +#define IP_TO_HOSTNAME_RESOLVE 1 + +/* date&time output style + Possible values: + 1 - standart ctime output + 2 - MM/DD/YY + 3 - DD/MM/YY */ +#define DATETIME_STYLE 3 + +#define DATETIME_DEFAULT_TIMEZONE 3 + +// show or not host names in messages +#define SHOW_HOST_NAME 1 + +// allow remark new messages +// 1 = mark with + +// 2 = mark will be linked to the next new message +#define ALLOW_MARK_NEW_MESSAGES 2 + +// should wwwconf change header of page on different pages +#define STABLE_TITLE 0 + +// antispam function control +#define ALLOW_ANTISPAM 1 +// post time limit (in seconds), reason to decide that it's flood +// *** processed ONLY if antispam function active *** +#define POST_TIME_LIMIT 10 + +// refresh to posted message time +#define AUTO_REFRESH_TIME 3 + +/*****************************************************************************/ +// topic support +#define TOPICS_SYSTEM_SUPPORT 1 + +// should we allow posting messages as unregistred when the same registred user exists +#define POST_ALLOW_UNDER_SAME_NICK 0 + +//************************************** +// support for user profiles +// *** if this feature is turned off NOBODY security byte and rigth will be applied to all users *** +#define USER_PROFILES_SUPPORT 1 + +#define USER_ALT_NICK_SPELLING_SUPPORT 1 + +// default session live time (for logged in user) +#define USER_SESSION_LIVE_TIME 360000 + +// user personal message support, allows to use conference as private messenger +#define USER_PERSONAL_MESSAGE_SUPPORT 1 +//************************************** + +// user favourites support, allow save messages in profile +// 1 = allow save any message to favourites +// 2 = allow save only parent message in thread +#define USER_FAVOURITES_SUPPORT 2 + +// support for global announces +#define GLOBAL_ANNOUNCES_SUPPORT 1 + +// support for user activity internal counters +#define ACTIVITY_LOGGING_SUPPORT 1 + +// top and bottom banner located in file or defined statically +#define USE_TEXT_BOTTOMBANNER 1 +#define USE_TEXT_TOPBANNER 1 + +//delete unused accounts +#define CLEANUP_IDLE_USERS 1 + +// count of messages on one page of search +#define SEARCH_MES_PER_PAGE_COUNT 100 + +/********************* DEFAULT USER AND MESSAGE PARAMETERS *******************/ + +/******** message database structures length *********/ +#define MESSAGE_HEADER_LENGTH 100 +#define AUTHOR_NAME_LENGTH 30 +#define HOST_NAME_LENGTH 60 + +/************* default not logged users parameters ***************/ +#define DEFAULT_NOBODY_SECURITY_BYTE 10 +#define DEFAULT_NOBODY_HDR_SEC_BYTE 255 +#define DEFAULT_NOBODY_RIGHT USERRIGHT_CREATE_MESSAGE | USERRIGHT_VIEW_MESSAGE | USERRIGHT_CREATE_MESSAGE_THREAD | USERRIGTH_PROFILE_CREATE + +/******** default user creation parameters (logged users) ********/ +#define DEFAULT_USER_SECURITY_BYTE 2 +#define DEFAULT_USER_HDR_SEC_BYTE 11 +#define DEFAULT_USER_RIGHT USERRIGHT_CREATE_MESSAGE | USERRIGHT_VIEW_MESSAGE | USERRIGHT_CREATE_MESSAGE_THREAD | USERRIGTH_PROFILE_MODIFY | USERRIGTH_PROFILE_CREATE +#define USER_DEFAULT_PROFILE_CREATION_FLAGS PROFILES_FLAG_VISIBLE_EMAIL | PROFILES_FLAG_VIEW_SETTINGS + +/******** default admin creation parameters (moderators) *********/ +#define DEFAULT_ADMIN_SECURITY_BYTE 0 +#define DEFAULT_ADMIN_HDR_SEC_BYTE 0 +#define DEFAULT_ADMIN_RIGHT USERRIGHT_SUPERUSER + +/******************** default "own settings" *********************/ +// which will be used too if browser does not support cookie +#define CONFIGURE_SETTING_DEFAULT_lsel 2 // 1 - by time +#define CONFIGURE_SETTING_DEFAULT_tv 8 // 12 hours +#define CONFIGURE_SETTING_DEFAULT_tt 1 // hours +#define CONFIGURE_SETTING_DEFAULT_tc 100 +#define CONFIGURE_SETTING_DEFAULT_ss SHOW_MESSAGE_STYLE_HRON_FORWARD +#define CONFIGURE_SETTING_DEFAULT_dsm 0 +#define CONFIGURE_SETTING_DEFAULT_topics 0xFFFFFFFF +#define CONFIGURE_SETTING_DEFAULT_toverride 0 // own settings + +/********************** common params **********************/ +#define MY_CGI_URL "" +#define MY_HOST_URL "" + +#define BOARD_PIC_URL "pic/" // smile dir (HTTP path to pic with smiles) + // + // NOTE: it's not absolute path on server + // it's only HTTP path + +#define HTTP_REFERER_CHECK 0 +// this string should be in HTTP_REFERER to pass trough the test +#define ALLOWED_HTTP_REFERER "rt.mipt.ru" + +// MAIL + +// WC_TYPE +// 1 - via smtp ( localhost or remote server) +// 2 - via command line (sendmail in unix like system) + +#define MA_TYPE 1 + +#define MA_READURL "http://192.168.1.7/" +#define MA_FROM "automailer-noreply@rt.mipt.ru" +// there should be smtp server ip or path to sendmail-like program +#define MA_SENDER "localhost" +#define ADMIN_MAIL "sergeyb@parallels.ru" + +#define COOKIE_NAME_STRING "RTBB=" +#define COOKIE_SESSION_NAME "SessionRT=" +#define COOKIE_EXPIRATION_DATE "Fri, 31-Dec-2009 00:00:00 GMT;" +#define COOKIE_SERVER_PATH "/;" + +// the maximum size for top and bottom files +#define MAX_HTML_FILE_SIZE 65535 + +/******************* perfomace parameters *******************/ + +// optimize index building for short index (about 300-500 messages in index) +// it will sligtly improove perfomance on HDD with high seek time +#define SHORT_INDEX_OPTIMIZATION 1 + +// count of message table entries for caching working with it +// this value is limited to 32000 +#define READ_MESSAGE_TABLE 2000 + +// count of message index entries to cache working with it +// this value limited to 32000 +#define READ_MESSAGE_HEADER 2*65535/sizeof(SMessage) + + +/////////////////////////////////////////////////////////////////////////////// +//////////////////// Platform dependent parameters +/////////////////////////////////////////////////////////////////////////////// + +#ifdef WIN32 +/*********WIN32*********/ +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +typedef struct _WCFILE { + HANDLE MutexHandle; // mutex for file locking + FILE *f; // file hanlde +} WCFILE; + +inline WCFILE* wcfopen(char *fname, char *mode) +{ + WCFILE *f = (WCFILE*)malloc(sizeof(WCFILE)); + char *mn = (char*)malloc(strlen(fname) + 20); + if(!f || !mn) + goto FAILED; + + f->f = fopen(fname, mode); + if(f->f == NULL) + goto FAILED; + + strcpy(mn, "Global\\"); // we use global namespace + strcat(mn, fname); + f->MutexHandle = ::CreateMutex(NULL, FALSE, mn); + if(!f->MutexHandle) { + fclose(f->f); + goto FAILED; + } + free(mn); + return f; + +FAILED: + if(f) free(f); + if(mn) free(mn); + return NULL; +} + +inline void wcfclose(WCFILE *f) +{ + fclose(f->f); + ::ReleaseMutex(f->MutexHandle); + ::CloseHandle(f->MutexHandle); + free(f); +} + +inline void flock(WCFILE *a, int b) +{ + if(b == 1) { + ::WaitForSingleObject(a->MutexHandle, INFINITE); + } + else { + ::ReleaseMutex(a->MutexHandle); + } +} + +#define wcfseek(a,b,c) fseek(a->f,b,c) +#define wcfeof(a) feof(a->f) +#define wcfread(a,b,c,d) fread(a,b,c,d->f) +#define wcfwrite(a,b,c,d) fwrite(a,b,c,d->f) +#define wcftell(a) ftell(a->f) +#define wcfflush(a) fflush(a->f) + +inline int truncate(FILE *f, unsigned long b) +{ + return chsize(fileno(f), b); +} + +inline int wctruncate(WCFILE *f, unsigned long b) +{ + return chsize(fileno(f->f), b); +} + +#define lock_file(a) {fflush(a->f);flock(a, 1);} +#define unlock_file(a) {fflush(a->f);flock(a, 0);} + +#if _DEBUG_ == 1 + +#include + +/* memory leaks detection */ +#define _CRTDBG_MAP_ALLOC +#include +#include + +#endif // _DEBUG_ + +/**********Unix*********/ +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef unsigned short WORD; +typedef unsigned long DWORD; + +#define WCFILE FILE + +#define wcfopen fopen +#define wcfclose fclose +#define wcfseek fseek +#define wcfeof feof +#define wcfread fread +#define wcfwrite fwrite +#define wcftell ftell +#define wcfflush fflush + +#define lock_file(a) {fflush(a);flock(fileno(a), LOCK_EX);} +#define unlock_file(a) {fflush(a);flock(fileno(a), LOCK_UN);} + +//string case-insensitive compare +#define strcmpi strcasecmp + +#endif + + +/////////////////////////////////////////////////////////////////////////////// +///////////////////// Platform independent MACRO definitions +/////////////////////////////////////////////////////////////////////////////// + +#define FILE_ACCESS_MODES_RW "rb+" // read-write mode +#define FILE_ACCESS_MODES_R "rb" // read mode +#define FILE_ACCESS_MODES_CW "wb+" // create new (overwrite) + +// Environment params name +#define QUERY_STRING "QUERY_STRING" +#define REQUEST_URI "REQUEST_URI" +#define REMOTE_ADDR "REMOTE_ADDR" + +// HTML checked or/and selected +#define RADIO_CHECKED " CHECKED" +#define LISTBOX_SELECTED " SELECTED" + +#define fCheckedRead(buffer, size, f) (wcfread(buffer, 1, size, f) == size) +#define fCheckedWrite(buffer, size, f) (wcfwrite(buffer, 1, size, f) == size) +typedef unsigned char BYTE; +#define M_IN(x,a,b) (((x)>=(a))&&((x)<=(b))) + + +/////////////////////////////////////////////////////////////////////////////// +///////////////////// Internal parameters +/////////////////////////////////////////////////////////////////////////////// + +/*---------------------- DIRECTORIES ----------------------*/ +#define DIR_MAINDATA "data/" +#define DIR_MESSAGES DIR_MAINDATA "messages/" // messages dir, for message database only +#define DIR_SEARCHER DIR_MAINDATA "searcher/" // searcher dir, for search index only +#define DIR_PROFILES DIR_MAINDATA "profiles/" // profiles dir, profile database only +#define DIR_SETTINGS DIR_MAINDATA "settings/" // settings dir, for forum settings +#define DIR_INTERNALS DIR_MAINDATA "internals/" // internal settings that will be autocreated +#define DIR_PROF_PIC DIR_PROFILES "pic/" // profile pictures dir + +/*-------------------- PROFILES DATABASE ------------------*/ +#define F_PROF_INDEX DIR_PROFILES "profindex.idx" // profile login indexes +#define F_PROF_NINDEX DIR_PROFILES "profindex.db" // profile indexes +#define F_PROF_FREENIDX DIR_PROFILES "profifree.db" // profile free nindex indexes +#define F_PROF_BODY DIR_PROFILES "profbody.db" // profile bodies (full user info) +#define F_PROF_FREEBODY DIR_PROFILES "profbfree.db" // profile free body indexes +#define F_PROF_PERSMSG DIR_PROFILES "profpers.db" // profile personal messages index +#define F_PROF_ALTNICK DIR_PROFILES "profcnicks.db" // profile alternative nick spelling + +/*------------------- CONFIGURATION FILES -----------------*/ +#define F_CONFIG "wwwconf.conf" // config file -- NOT YET SUPPORTED + +/*------------------ MESSAGE DATABASE FILES ---------------*/ +#define F_MSGINDEX DIR_MESSAGES "index.msg" // message headers +#define F_MSGBODY DIR_MESSAGES "messages.msg" // message bodies +#define F_INDEX DIR_MESSAGES "ra_index.msg" // random access index file (hronological indexes) +#define F_VINDEX DIR_MESSAGES "vra_index.msg" // virtual index file +#define F_FREEMBODY DIR_MESSAGES "freemess.msg" // free spaces in message bodies +#define F_FREEINDEX DIR_MESSAGES "freeindex.msg" // free spaces in message headers +#define F_GLOBAL_ANN DIR_MESSAGES "globalann.msg" // global announces + +/*------------------ SEARCH INDEX FILES -------------------*/ +#define F_SEARCH_INDEX DIR_SEARCHER "messearch.idx" // searcher message index file +#define F_SEARCH_DB DIR_SEARCHER "messearch.db" // searcher message index file +#define F_SEARCH_LASTINDEX DIR_SEARCHER "lastindex" // database id and last indexed message + +/*---------------- SETTINGS FILES --------------*/ +#define F_BANNEDIP DIR_SETTINGS "banned.txt" // list of banned IP +#define F_BADWORDS DIR_SETTINGS "badwords.txt" // list of words, witch is resstricted message headers and bodies + +/*---------------- INTERNAL SUPPORT FILES --------------*/ +#define F_ANTISPAM DIR_INTERNALS "antispam.dat" // antispam system file +#define F_AUTHSEQ DIR_INTERNALS "authuser.dat" // currently authorized users (sessions) +#define F_ACTIVITYLOG1 DIR_INTERNALS "activitylog1.dat" // user activity log file 1 +#define F_ACTIVITYLOG2 DIR_INTERNALS "activitylog2.dat" // user activity log file 2 +#define F_ACTIVITYARCH DIR_INTERNALS "activityarch.dat" // user activity archive + +/*---------------------- LOG FILE -------------------------*/ +#define LOG_FILE DIR_MAINDATA "wwwconf.log" // log file + +/*------------- BANNERS&HELP (should be placed with index of forum) -------------*/ +#define F_TOPBANNER "topbanner.html" // top banner of wwwconf +#define F_BOTTOMBANNER "bottombanner.html" // bottom banner of wwwconf +#define F_FAQ_HELP "help.html" // information about using tags and smiles of wwwconf +#define F_RULES_HELP "rules.html" // infromation about rules of board + +#define COOKIE_MAX_LENGTH 400 + +#define MAX_STRING 255 +/* maximal parameters string and message length */ +#define MAX_PARAMETERS_STRING 65535 + +#define DATE_PRINT_STYLE 1 +#define THREAD_PRINT_STYLE 2 +#define SHOW_MESSAGE_STYLE_HRON_FORWARD 1 +#define SHOW_MESSAGE_STYLE_HRON_BACKWARD 2 + +#define PRINT_FORWARD 1 +#define PRINT_BACKWARD 0 +#define GO_FORWARD 1 +#define GO_BACKWARD 0 + +/********** bit masks **********/ +/********** Message flags ****************/ +#define MESSAGE_HAVE_PICTURE 0x0001 +#define MESSAGE_HAVE_URL 0x0002 +#define MESSAGE_HAVE_BODY 0x0004 +#define MESSAGE_IS_CLOSED 0x0008 +#define MESSAGE_IS_INVISIBLE 0x0010 +#define MESSAGE_ENABLED_TAGS 0x0020 +#define MESSAGE_ENABLED_SMILES 0x0040 // affects only to HEADER of msg +#define MESSAGE_MAIL_NOTIFIATION 0x0080 +#define MESSAGE_COLLAPSED_THREAD 0x0100 // collapsed thread +#define MESSAGE_WAS_SIGNED 0x0200 // message have signature +#define MESSAGE_ENABLED_HTML 0x0400 // message in html format + +/* for printhtmlmessage_in_index proc */ +#define MESSAGE_INDEX_PRINT_ITS_URL 0x0001 +#define MESSAGE_INDEX_DISABLE_ROLLED 0x0002 +#define MESSAGE_INDEX_PRINT_BLANK_URL 0x0004 + +/* for user right - all modify/close/roll/delete modes affect ONLY on own posts! */ + +#define USERRIGHT_COUNT 14 + +#define USERRIGHT_SUPERUSER 0x0001 // allow ALL rigth (skip all right test) +#define USERRIGHT_VIEW_MESSAGE 0x0002 // allow view messages in conference +#define USERRIGHT_MODIFY_MESSAGE 0x0004 // modify (change) own messages +#define USERRIGHT_CLOSE_MESSAGE 0x0008 // close thread right +#define USERRIGHT_OPEN_MESSAGE 0x0010 // open thread right (form closed) +#define USERRIGHT_CREATE_MESSAGE 0x0020 // create message (reply) +#define USERRIGHT_CREATE_MESSAGE_THREAD 0x0040 // create message (new thread) +#define USERRIGTH_ALLOW_HTML 0x0080 // allow HTML right +#define USERRIGTH_PROFILE_MODIFY 0x0100 // allow modify, delete own profile +#define USERRIGTH_PROFILE_CREATE 0x0200 // allow create new profiles +#define USERRIGHT_ROLL_MESSAGE 0x0400 // roll thread right +#define USERRIGHT_UNROLL_MESSAGE 0x0800 // unroll thread right +#define USERRIGHT_POST_GLOBAL_ANNOUNCE 0x1000 // post global conference announce +#define USERRIGHT_ALT_DISPLAY_NAME 0x2000 // alternative display name + +/* for virtual indexes */ +#define NO_MESSAGE_CODE 0xFFFFFFFF + +/* Common message structure */ +struct SMessage +{ + /* common parameters */ + char MessageHeader[MESSAGE_HEADER_LENGTH]; + char AuthorName[AUTHOR_NAME_LENGTH]; + char HostName[HOST_NAME_LENGTH]; + + /* IP Address of poster */ + DWORD IPAddr; + + /* unique user ID or 0, if anonymous posts */ + DWORD UniqUserID; + + /* security level of message (for tags, etc.) */ + /* body security */ + BYTE Security; + /* header security */ + BYTE SecHeader; + + /* flag of message : HAVE_PIC, CLOSED, etc. */ + DWORD Flag; + + /* creation time */ + time_t Date; + /* modifying date */ + time_t MDate; + + /* message level in tree */ + WORD Level; + + /* topic flags */ + DWORD Topics; + + /* request counter of this message */ + WORD Readed; + + /* index of main thread message */ + DWORD ParentThread; + + // ???????????????????????????????????????? + /* index of parent message + DWORD ParentMsg; + */ + + /* virtual index of message */ + DWORD ViIndex; + + /* index of message body */ + DWORD MIndex; + /* size of message body */ + DWORD msize; +}; + + +/////////////////////////////////////////////////////////////////////////////// +///////////////////// Subroutine definitions +/////////////////////////////////////////////////////////////////////////////// + +char* toupperstr(char *s); + +#endif // of BASETYPES_H_INCLUDED blob - /dev/null blob + fc51e9f1cf037c23b68ce6e6c4f55231e6e3680b (mode 644) --- /dev/null +++ src/boardtags.cpp @@ -0,0 +1,747 @@ +/*************************************************************************** + boardtags.cpp - board tags support + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "boardtags.h" +#include "error.h" + +/* following define WWWConf Board Tags, and + * it's translation into standart HTML tags, + * and security level of each tag + */ +STagConvert TagConvTable[BoardTagCount] = { + /* text output tags */ + {"B", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2}, + {"E", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2}, + {"I", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2}, + {"U", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2}, + {"H", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 0}, + {"S", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2}, + /* Colour tags */ + {"GREEN", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2}, + {"RED", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 0}, + {"COLOR", "", WC_TAG_TYPE_2, "", WC_TAG_TYPE_1, 0}, + {"C", "", WC_TAG_TYPE_2, "", WC_TAG_TYPE_1, 0}, + /* URL, Picture, Mail */ + {"URL", "", WC_TAG_TYPE_2, "", WC_TAG_TYPE_1, 10}, + {"PIC", "", WC_TAG_TYPE_1, 10}, + {"MAIL", "", WC_TAG_TYPE_2, "", WC_TAG_TYPE_1, 10}, + /* HR SIZE=1 */ + {"HR", "
", WC_TAG_TYPE_ONLYOPEN, "", WC_TAG_TYPE_DISABLED, 2}, + /* quotation */ + {"Q", "

Quotation:

", + WC_TAG_TYPE_1, "

", WC_TAG_TYPE_1, 2}, + /* Center */ + {"CENTER", "
", WC_TAG_TYPE_1, "
", WC_TAG_TYPE_1, 10}, + /* Pre */ + {"PRE", "
", WC_TAG_TYPE_1, "
", WC_TAG_TYPE_1, 10}, + {"STRIKE", "", WC_TAG_TYPE_1, "", WC_TAG_TYPE_1, 2} +}; + +/* define there smile-like codes + * and it's translation to HTML + * first character in tag must be ':' or ';' + */ +SPicConvert PicConvTable[BoardPicCount] = { + {":))", "bigsmile.gif", 9}, + {":-))", "bigsmile.gif", 9}, + {":-)", "smile.gif", 9}, + {":)", "smile.gif", 9}, + {":(", "frown.gif", 9}, + {":-(", "frown.gif", 9}, + {";)", "wink.gif", 9}, + {";-)", "wink.gif", 9}, + {":LOL", "lol.gif", 9}, + {":!!", "lol.gif", 9}, + {":-\\", "smirk.gif", 9}, + {":\\", "smirk.gif", 9}, + {":o", "redface.gif", 9}, + {":MAD", "mad.gif", 9}, + {":STOP", "stop.gif", 0}, // admin only + {":APPL", "appl.gif", 9}, + {":BAN", "ban.gif", 9}, + {":BEE", "bee.gif", 9}, + {":BIS", "bis.gif", 9}, + {":ZLOBA", "blya.gif", 9}, + {":BORED", "bored.gif", 9}, + {":BOTAT", "botat.gif", 9}, + {":COMP", "comp.gif", 9}, + {":CRAZY", "crazy.gif", 9}, + {":DEVIL", "devil.gif", 9}, + {":DOWN", "down.gif", 9}, + {":FIGA", "figa.gif", 9}, + {":GIT", "git.gif", 9}, + {":GYGY", "gy.gif", 9}, + {":HEH", "heh.gif", 9}, + {":CIQ", "iq.gif", 9}, + {":KURIT", "kos.gif", 9}, + {":LAM", "lam.gif", 9}, + {":MNC", "mnc.gif", 9}, + {":NO", "no.gif", 9}, + {":SMOKE", "smoke.gif", 9}, + {":SORRY", "sorry.gif", 9}, + {":SUPER", "super.gif", 9}, + {":UP", "up.gif", 9}, + {":YES2", "yes2.gif", 9}, + {":YES", "yes.gif", 9}, + {":BASH", "bash.gif", 9}, + {":CLAPPY", "clappy.gif", 9}, + {":EWW", "eww.gif", 9}, + {":ROTFL", "roflol.gif", 9}, + {":SPOTMAN","spotman.gif", 9}, + {":WAVE", "wave.gif", 9}, + {":COWARD", "coward.gif", 9}, + {":DRAZNIT","draznit.gif", 9}, + {":ROLLEYES","pizdets.gif", 9}, + {":PLOHO", "blevalyanaeto.gif",9}, + {":}", "icqbig.gif", 9}, +}; + +/* parse string to nearest ';' or ':' */ +int inline ParseToOpenSmileTagorHttp(char *s) +{ + register unsigned int i = 0; +#if TRY_AUTO_URL_PREPARSE + // find smile, ftp or http start + while(s[i] != 0 && s[i] != ':' && s[i] != ';' && s[i] != 'h' && s[i] != 'f') i++; +#else + while(s[i] != 0 && s[i] != ':' && s[i] != ';') i++; +#endif + return i; +} + +#if TRY_AUTO_URL_PREPARSE +/* return 1 if url was parsed, 0 otherwise */ +static int ReparseUrl(char **ss, char **dd, DWORD status) +{ + int rf = 0; + char *d = *dd, *s = *ss; + int slen = strlen(s); + if( ( (slen > 7) && (strncmp(s, "http://", 7) == 0) ) || + ( (slen > 8) && (strncmp(s, "https://", 8) == 0) ) || + ( (slen > 6) && (strncmp(s, "ftp://", 6) == 0) ) ) + { + if((status & 4)) { + // we have found http:// | https:// | ftp:// reference, so try to parse it + char *olds = s; + char oldcs; + char *dtmp; + + if(*s == 'h') s++; + s+=6; + + while(*s != 0 && *s != 13 && *s != 10 && *s != ' ' && *s != ')' && *s != '(' + && *s != '>' && *s != '<' && *s != ']' && *s != '[' && *s != ',' + && strncmp(s, """, 6) !=0 ) s++; + oldcs = *s; + *s = 0; + dtmp = (char*)malloc(strlen(olds)*2+strlen(PARSED_URL_TMPL)); + sprintf(dtmp, PARSED_URL_TMPL, olds, olds); + strcpy(d, dtmp); + d+=strlen(dtmp); + free(dtmp); + *s = oldcs; + } + rf = 1; + } + + *dd = d; + *ss = s; + return rf; +} +#endif + +/* Smart strcat() function. It removes all duplicated spaces, char #10 and all tabs. + * The behavior depends of status. If status nonzero it works as usual strcat except + * #10 char removing. + * status meaning: + * 0x01 - spaces and tabs elimination (DISABLING) + * 0x02 - 13 -> BR parsing + * 0x04 - url parsing + */ +int inline smartstrcat(char *d, char *s, DWORD status, DWORD *flg) +{ + char *od = d; + int fstat; + d += strlen(d); + *flg = 0; + if(status & 1) { + while(*s != 0) { +#if TRY_AUTO_URL_PREPARSE + fstat = ReparseUrl(&s, &d, status); + if(fstat) *flg = 1; +#endif + + if(*s != 10) { + if(*s == 13 && (status & 2)) { + // convert to
+ memcpy(d, "
", 4); + d+=4; + } + else { + *d = *s; + d++; + } + } + s++; + } + *d = *s; + } + else { + register int ws = 0; // was space or tab + while(*s != 0) { +#if TRY_AUTO_URL_PREPARSE + fstat = ReparseUrl(&s, &d, status); + if(fstat) *flg = 1; +#endif + + if( *s != 10 && (!(ws && (*s == 0x20 || *s == 0x09))) ) { + if(*s == 0x20 || *s == 0x09) { + ws = 1; + *d = 0x20; // space + } + else { + ws = 0; + if(*s == 13 && (status & 2)) { + // convert to
+ memcpy(d, "
", 4); + d+=3; + } + else *d = *s; + } + d++; + } + s++; + } + *d = *s; + } + return d - od; +} + +/* function for concatenation string s to d + * with converting smile-codes to images + */ +int inline ParseSmiles_smartstrcat(char *d, char *s, BYTE sec, DWORD status, DWORD *flg) +{ + register char *dd = d + strlen(d); + register char *ss = s; + unsigned int i = 0, fstat; + int wassmile = 0; + *flg = 0; + while(*ss != 0) { + i = ParseToOpenSmileTagorHttp(ss); + if(i) { + char si = ss[i]; + ss[i] = 0; + dd += smartstrcat(dd, ss, status, flg); + ss[i] = si; + ss += i; + } + if(*ss == 0) break; + +#if TRY_AUTO_URL_PREPARSE + fstat = ReparseUrl(&ss, &dd, status); + if(fstat) *flg = 1; +#endif + + for(register unsigned int j = 0; j < BoardPicCount; j++) { + if(strlen(PicConvTable[j].tag) <= strlen(ss) && PicConvTable[j].security >= sec && + strncmp(ss, PicConvTable[j].tag, strlen(PicConvTable[j].tag)) == 0 && ((status & 1) == 0) ) { + wassmile = 1; + strcat(dd, "\"");"); + dd += strlen(dd); + ss += strlen(PicConvTable[j].tag); + goto next_sym; + } + } + + if(*dd == 0) *(dd+1) = 0; + + if(*ss == 13 && (status & 2)) { + // convert to
+ memcpy(dd, "
", 4); + dd+=3; + } + else { + *dd = *ss; + } + dd++; + ss++; +next_sym: ; + } + *dd = 0; + return wassmile; +} + +/* insert string s to string d at position index + * return d, DOES NOT CONTROL ANY ERRORS + */ +char* strins(char *d, char *s, int index) +{ + register char *p = d + index; // from + register char *t = d + index + strlen(s); // to + register unsigned int x = strlen(d) - index; // count + for(register int j = x; j >= 0; j--) t[j] = p[j]; + t[x+1] = 0; + strncpy(p, s, strlen(s)); + return d; + +} + +/* parse string up to nearest =, WC_TAG_OPEN/CLOSE */ +int inline ParseRegExp(char *s) +{ + register int i = 0; + while(s[i] != 0 && s[i] != '=' && s[i] != WC_TAG_CLOSE && s[i] != WC_TAG_OPEN) i++; + return i; +} + +/* parse to nearest WC_TAG_OPEN */ +int inline ParseToOpenWC_TAG(char *s) +{ + register int i = 0; + while(s[i] != 0 && s[i] != WC_TAG_OPEN) i++; + return i; +} + +/* parse to nearest WC_TAG_CLOSE */ +int inline ParseToCloseWC_TAG(char *s) +{ + register int i = 0; + while(s[i] != 0 && s[i] != WC_TAG_CLOSE) i++; + return i; +} + +/* input: s - parsing string with begining of tag (first symbol = WC_TAG_OPEN) + * oputput: function return length of parsed board tag or 0 if tag is not valid + * par1 - tag name, par2 - parameter after = in tag (NULL if not present) + */ +int inline ParseBoardTag(char *s, char **par1, char **par2) +{ + char *ss; + int i, j; + ss = s; + *par1 = NULL; + *par2 = NULL; + // ignore WC_TAG_OPEN + if(*s != WC_TAG_OPEN) { + return 0; + } + s++; + // parse first arg + i = ParseRegExp(s); + if(i == 0) { + return 0; + } + *par1=(char*)malloc(i + 1); + char ts = s[i]; + s[i] = 0; + strcpy(*par1, s); + toupperstr(*par1); + s[i] = ts; + s += i; + if(*s == WC_TAG_CLOSE) { + return s - ss + 1; + } + if(*s == '=') { + // parse second arg + s++; + j = ParseToCloseWC_TAG(s); + if(j == 0) { + goto ParseBoardTag_Faild; + } + if(s[j] == WC_TAG_CLOSE) { + *par2=(char*)malloc(j + 1); + char ts = s[j]; + s[j] = 0; + strcpy(*par2, s); + s[j] = ts; + return s - ss + j + 1; + } + } +ParseBoardTag_Faild: + free(*par1); + *par1 = NULL; + *par2 = NULL; + return 0; +} + +/* check and expand board tags -> HTML tags + * return value: function return 1 if successfull, overwise 0 + * tagtype - tag type (index in TagConvTable) and taglen = 1, 2 + */ +int inline ExpandTag(char *tag1, char *tag2, char **restag, int *tagnumber, int *tagtype, BYTE security) +{ + int tagdirection = 0; /* open by default */ + + if(tag1[0] == '/') { + tagdirection = 1; + tag1++; + } + + *restag = NULL; + + for(int i=0; i < BoardTagCount; i++) { + if(strcmp(tag1, TagConvTable[i].tag) == 0) { + if(TagConvTable[i].security < security) { + return 0; + } + *tagnumber = i; + int tagt; + if(tagdirection) tagt = TagConvTable[i].typeclose; + else tagt = TagConvTable[i].typeopen; + switch(tagt) { + case WC_TAG_TYPE_1: + *tagtype = WC_TAG_TYPE_1; + /* check for valid param count */ + if(tag2 != NULL) return 0; + if(tagdirection) { + /* closing */ + *restag = (char*)malloc(strlen(TagConvTable[i].tclosetag) + 1); + strcpy(*restag, TagConvTable[i].tclosetag); + } + else { + /* opening */ + *restag = (char*)malloc(strlen(TagConvTable[i].topentag) + 1); + strcpy(*restag, TagConvTable[i].topentag); + } + return 1; + + case WC_TAG_TYPE_2: + *tagtype = WC_TAG_TYPE_2; + /* check for valid param count + */ + if(tag2 == NULL) return 0; + if(!tagdirection) { + /* opening */ + char *parsedtag2; + + if(i == URL_TAG_TYPE) { + if(strncmp(tag2, "http:", 5) != 0 && strncmp(tag2, "ftp:", 4) != 0 && + strncmp(tag2, "file:", 5) != 0 && strncmp(tag2, "https:", 6) != 0 && + strncmp(tag2, "smb:", 6) != 0) + { + parsedtag2 = (char*)malloc(strlen(tag2) + 10); + strcpy(parsedtag2, "http://"); + strcat(parsedtag2, tag2); + } + else parsedtag2 = tag2; + } + else parsedtag2 = tag2; + + *restag = (char*)malloc(strlen(TagConvTable[i].topentag) + 1 + strlen(parsedtag2)); + + /* use sprintf() to insert tag2 into result + * (format of topentag as %s instead of tag2) + */ + sprintf(*restag, TagConvTable[i].topentag, parsedtag2); + *restag = (char*)realloc(*restag, strlen(*restag) + 1); + if(parsedtag2 != tag2) free(parsedtag2); + } + else { + /* closing - not currently supported */ + return 0; + } + return 1; + + case WC_TAG_TYPE_12: + /* temporary not used */ + + return 0; + + case WC_TAG_TYPE_ONLYOPEN: + *tagtype = WC_TAG_TYPE_ONLYOPEN; + /* check for valid param count + */ + if(tag2 != NULL) return 0; + if(!tagdirection) { + /* opening */ + *restag = (char*)malloc(strlen(TagConvTable[i].topentag) + 1); + strcpy(*restag, TagConvTable[i].topentag); + } + else { + /* closing - not valid (only opening) */ + return 0; + } + return 1; + } + } + } + /* tag not found */ + return 0; +} + +/* filtering smile codes and board tags using current security level = security + * and message flags MESSAGE_ENABLED_SMILES MESSAGE_ENABLED_TAGS + * return value 1 if all successfull, or 0 if string was cutted, + * because of ml limitation + * **** input : s - string, ml - max result string length, Flags - flags of message, security - sec. + * level of msg (for tags conversion) + * **** output : r - resulting string + + * Meaning of some flags + * 0x80 - set up flag HAVE_URL + * 0x04 - url autopreparse + + */ +int FilterBoardTags(char *s, char **r, BYTE security, DWORD ml, DWORD Flags, DWORD *RF) +{ + // + int beforePreStatus; + // + char *tag1 = NULL, *tag2 = NULL, *res = NULL, *st; + DWORD opentag, reff, status = 0x04, urldisable = 0; // http preparse + int i, StringTooLong = 0; + SSavedTag OldTag[MAX_NESTED_TAGS]; + + // ignore starting newline + while(*s == 10 || *s == 13) s++; + + // ignore ending newline + { + int sl = strlen(s); + register int k; + for(k = sl; k>0; k--) { + if(!(s[k - 1] == 10 || s[k - 1] == 13)) + break; + } + s[k] = 0; + } + + *RF = 0; + *r = NULL; + + if(Flags & BOARDTAGS_EXPAND_ENTER) + status |= 0x02; // 13 ->
conversion + + if((Flags & BOARDTAGS_CUT_TAGS) || (Flags & BOARDTAGS_TAG_PREPARSE) || ((Flags & BOARDTAGS_PURL_ENABLE) == 0)) { + status &= (~0x04); // disable url parsing + urldisable = 1; + } + + /* alloc memory for resulting string */ + beforePreStatus = status; + if(ml < 32000) st = (char *)malloc(32000); + else st = (char *)malloc(3*ml); + + st[0] = 0; + opentag = 0; + for(;;) { + if(strlen(st) >= ml) { + StringTooLong = 1; + break; + } + if(*s == 0) break; + i = ParseToOpenWC_TAG(s); + if(i) { + char si = s[i]; + s[i] = 0; + if((Flags & MESSAGE_ENABLED_SMILES) && ((Flags & BOARDTAGS_TAG_PREPARSE) == 0)) { + if(ParseSmiles_smartstrcat(st, s, security, status, &reff)) { + *RF = *RF | MESSAGE_ENABLED_SMILES; + } + if(reff && ((status & 0x80) == 0)) (*RF) |= MESSAGE_HAVE_URL; + } + else { + smartstrcat(st, s, status, &reff); + if(reff && ((status & 0x80) == 0)) (*RF) |= MESSAGE_HAVE_URL; + } + s[i] = si; + s += i; + } + i = ParseBoardTag(s, &tag1, &tag2); + + if((Flags & MESSAGE_ENABLED_TAGS) == 0) + goto ignore_tag; + + if(i) { + int tt = 0, tl = 0; + + /* we have tag, parse it! */ + if(!ExpandTag(tag1, tag2, &res, &tt, &tl, security)) { + /* invalid tag */ + goto ignore_tag; + } + + if(tl == WC_TAG_TYPE_ONLYOPEN) { + *RF = *RF | MESSAGE_ENABLED_TAGS; + if((status & 1) == 0 && ((Flags & BOARDTAGS_TAG_PREPARSE) == 0)) { + // only opened tag - so parse it at once + strcat(st, res); + s += i; + } + else goto ignore_tag; + } + else { + // if successfully expanded (exists) + // already have open tag - so try to interpret it as closing tag + if(tag1[0] == '/') { + if(opentag) { + /* closing tag - check for conformity */ + if( tl != 1 || OldTag[opentag - 1].tt != tt) { + /* incompartable tags - ignore it */ + goto ignore_tag; + } + + if(tt == PRE_TAG_TYPE || tt == PIC_TAG_TYPE) // allow tag and space parsing again + status &= 0xFFFFFFFE; + if(tt == PRE_TAG_TYPE) + status = beforePreStatus; + /* set flags of message type */ + if(tt == PIC_TAG_TYPE) { /* there was a picture tag */ + if(!urldisable) { + status |= 0x04; // allow http parsing + } + status &= (~0x80); + *RF = *RF | MESSAGE_HAVE_PICTURE; + } + if(tt == URL_TAG_TYPE) { /* there was a url tag */ + if(!urldisable) { + status |= 0x04; // allow http parsing + } + *RF = *RF | MESSAGE_HAVE_URL; + } + /* have at least one tag */ + *RF = *RF | MESSAGE_ENABLED_TAGS; + + // what we will do with tags + if((Flags & BOARDTAGS_TAG_PREPARSE)) { + // do not change tags, just preparse spaces, etc. + strins(st, OldTag[opentag - 1].oldexp, OldTag[opentag - 1].index); + char os = s[i]; + s[i] = 0; + strcat(st, s); + s[i] = os; + } + else { + // expand tags or ignore(cut) them + if((Flags & BOARDTAGS_CUT_TAGS) == 0) { + // + // PATCH for PIC tag + // + if(tt == PIC_TAG_TYPE) { /* there was a picture tag */ + char *ts = st + OldTag[opentag - 1].index; + if(strncmp(ts, "http:", 5) != 0 && strncmp(ts, "ftp:", 4) != 0 && + strncmp(ts, "file:", 5) != 0 && strncmp(ts, "https:", 6) != 0 && + strncmp(ts, "smb:", 6) != 0) + { + // add http + strins(ts, "http://", 0); + } + } + strins(st, OldTag[opentag - 1].tagexp, OldTag[opentag - 1].index); + strins(st, res, strlen(st)); + } + else {} // tag will be cutted + } + free(OldTag[opentag - 1].tagexp); + free(OldTag[opentag - 1].oldexp); + opentag--; // dec tag count + s += i; + } + else { + /* ignore tags first elem of tag */ + goto ignore_tag; + } + } + else { + if((status & 1) == 0) { + // opening tag + /* tag expanded successfully - set current tag struct */ + if(opentag > MAX_NESTED_TAGS - 1) goto ignore_tag; + OldTag[opentag].tt = tt; + OldTag[opentag].tl = tl; + OldTag[opentag].tagexp = res; + res = NULL; + OldTag[opentag].index = strlen(st); + char os = s[i]; + s[i] = 0; + OldTag[opentag].oldexp = (char*)malloc(strlen(s) + 1); + strcpy(OldTag[opentag].oldexp, s); + s[i] = os; + s += i; + opentag++; // inc tag count + // check if it was PRE or PIC tag + if(tt == PRE_TAG_TYPE) { + beforePreStatus = status; + status &= ~2;//disable "\n" -> "
" conv + } + if(tt == PRE_TAG_TYPE || tt == PIC_TAG_TYPE) // disable tag parsing + status |= 0x01; + // check if it was PIC tag + if(tt == PIC_TAG_TYPE) {// disable http parsing + if(!urldisable) + status &= (~0x04); + status |= 0x80; + } + // check if it was URL tag + if(tt == URL_TAG_TYPE) {// disable http parsing + if(!urldisable) + status &= (~0x04); + } + } + else goto ignore_tag; + } + } + } + else { + /* ignore tags first elem of tag */ + goto ignore_tag; + } + goto parse_next; +ignore_tag: + if((*s) != 0) { + register char si; + si = *(s + 1); + *(s +1 ) = 0; + strcat(st, s); + *(s + 1) = si; + s++; + } +parse_next: + if(tag1) { + free(tag1); + tag1 = NULL; + } + if(tag2) { + free(tag2); + tag2 = NULL; + } + if(res) { + free(res); + res = NULL; + } + } + + if(StringTooLong) { + /* too long string */ + free(st); + for(register DWORD i = 0; i 0; k--) + strins(st, OldTag[k - 1].oldexp, OldTag[k - 1].index); + + for(k = 0; k < opentag; k++) { + free(OldTag[k].oldexp); + free(OldTag[k].tagexp); + } + } + st = (char*)realloc(st, strlen(st) + 5); + *r = st; + return 1; +} blob - /dev/null blob + 6f47900bdf178b0cbf65b799fa8c4f486434e241 (mode 644) --- /dev/null +++ src/boardtags.h @@ -0,0 +1,80 @@ +/*************************************************************************** + boardtags.h - board tags support include + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef BOARDTAGS_H_INCLUDED +#define BOARDTAGS_H_INCLUDED + +#include "basetypes.h" + +#define WC_TAG_OPEN '[' +#define WC_TAG_CLOSE ']' + +#define TRY_AUTO_URL_PREPARSE 1 +#define PARSED_URL_TMPL "%s" + +#define MAX_NESTED_TAGS 8 + +#define BOARDTAGS_CUT_TAGS 0x08000000 +#define BOARDTAGS_TAG_PREPARSE 0x10000000 +#define BOARDTAGS_EXPAND_ENTER 0x20000000 +#define BOARDTAGS_PURL_ENABLE 0x40000000 + +#define BoardTagCount 18 +#define BoardPicCount 52 + +#define URL_TAG_TYPE 10 +#define PIC_TAG_TYPE 11 +#define PRE_TAG_TYPE 16 + +#define WC_TAG_TYPE_DISABLED 0 +#define WC_TAG_TYPE_1 1 +#define WC_TAG_TYPE_2 2 +#define WC_TAG_TYPE_12 3 +#define WC_TAG_TYPE_ONLYOPEN 4 + +/* element of table for converting WWWConf Tags to HTML */ +struct STagConvert { + /* board tag */ + char *tag; + /* corresponding opening and closing HTML tags */ + char *topentag; + char typeopen; + char *tclosetag; + char typeclose; + /* security level of tag + * zero - is highest level + */ + BYTE security; +}; + +struct SPicConvert { + /* board code */ + char *tag; + /* Pic URL */ + char *url; + /* security level of smile + * zero - is highest level + */ + BYTE security; +}; + +/* Struct for saving last opened tag */ +struct SSavedTag { + /* tag type and tag length */ + int tt, tl; + + /* tag old and expanded expression */ + char *tagexp; + char *oldexp; + /* insert expanded expression index */ + int index; +}; + +int FilterBoardTags(char *s, char **r, BYTE security, DWORD ml, DWORD Flags, DWORD *RF); + +#endif blob - /dev/null blob + 376771684820314e4e36fee9d2bcac7fa2fc1a71 (mode 644) --- /dev/null +++ src/colornick.cpp @@ -0,0 +1,179 @@ +/*************************************************************************** + colornick.cpp - alternative nick spelling support + ------------------- + begin : Sat Jun 07 2003 + copyright : (C) 2001-2003 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "colornick.h" + +CAltNamesParser::CAltNamesParser(char *fname, bool &init) +{ + init = 0; + classinit = 0; + AltNamesStruct ns; + char *ts; + DWORD rd; + + // try to open existing file + if((f = wcfopen(fname, FILE_ACCESS_MODES_RW)) == NULL) { + // not exist - try to create file + if((f = wcfopen(fname, FILE_ACCESS_MODES_CW)) == NULL) { + return; + } + else { + wcfclose(f); + if((f = wcfopen(fname, FILE_ACCESS_MODES_RW)) == NULL) { + return; + } + } + } + + // file successfully opened - read values + while(!wcfeof(f)) { + if(((rd = (DWORD)wcfread(&ns, 1, sizeof(ns), f)) % sizeof(ns)) != 0) { + wcfclose(f); + return; + } + if(!rd) break; + ts = (char*)malloc(MAX_ALT_NICK_SIZE); + strcpy(ts, ns.aname); + nmap[ns.uid] = ts; + } + wcfclose(f); + + strcpy(ifname, fname); + + init = 1; + classinit = 1; +} + +CAltNamesParser::~CAltNamesParser() +{ + std::hash_map::iterator it; + for(it = nmap.begin(); it != nmap.end(); it++) { + free(it->second); + } + nmap.clear(); +} + +int CAltNamesParser::AddAltName(DWORD uid, char *name, char *altname) +{ + if(classinit) { + if(nmap.find(uid) == nmap.end()) { + AltNamesStruct ns; + memset(&ns, 0, sizeof(ns)); + char *s2 = (char*)malloc(MAX_ALT_NICK_SIZE); + strcpy(s2, altname); + nmap[uid] = s2; + // save to file + ns.uid = uid; + strcpy(ns.rname, name); + strcpy(ns.aname, s2); + if((f = wcfopen(ifname, FILE_ACCESS_MODES_RW)) == NULL) + return 0; // file MUST exist + lock_file(f); + wcfseek(f, 0, SEEK_END); + fCheckedWrite(&ns, sizeof(ns), f); + unlock_file(f); + wcfclose(f); + return 1; + } + else { + // update + AltNamesStruct ns; + memset(&ns, 0, sizeof(ns)); + DWORD pos, fn = 0; + char *s1, *s2 = (char*)malloc(MAX_ALT_NICK_SIZE); + strcpy(s2, altname); + s1 = nmap[uid]; + free(s1); + nmap[uid] = s2; + // save to file (first of all - let's find) + if((f = wcfopen(ifname, FILE_ACCESS_MODES_RW)) == NULL) + return 0; // file MUST exist + lock_file(f); + while(!wcfeof(f)) { + pos = wcftell(f); + if(!fCheckedRead(&ns, sizeof(ns), f)) { + wcfclose(f); + return 0; + } + if(ns.uid == uid) { + strcpy(ns.rname, name); + strcpy(ns.aname, altname); + wcfseek(f, pos, SEEK_SET); + fn = 1; + break; + } + } + if(fn) fCheckedWrite(&ns, sizeof(ns), f); + unlock_file(f); + wcfclose(f); + return 1; + } + } + return 0; // Already exist +} + +int CAltNamesParser::DeleteAltName(DWORD uid) +{ + if(classinit) { + std::hash_map::iterator it; + if(nmap.find(uid) != nmap.end()) { + AltNamesStruct ns; + DWORD pos, rd, fn = 0; + char cb[100000]; + // delete from file (first of all - let's find) + if((f = wcfopen(ifname, FILE_ACCESS_MODES_RW)) == NULL) + return 0; // file MUST exist + lock_file(f); + while(!wcfeof(f)) { + pos = wcftell(f); + if(!fCheckedRead(&ns, sizeof(ns), f)) { + wcfclose(f); + return 0; + } + if(ns.uid == uid) { + rd = (DWORD)wcfread(cb, 1, 100000, f); + if(rd == 100000) { + wcfclose(f); + return 0; + } + wcfseek(f, pos, SEEK_SET); + fn = 1; + break; + } + } + if(fn) fCheckedWrite(cb, rd, f); + pos = wcftell(f); +#ifdef WIN32 + wctruncate(f, pos); +#else + truncate(ifname, pos); +#endif + unlock_file(f); + wcfclose(f); + + it = nmap.find(uid); + free(it->second); + nmap.erase(it); + + return 1; + } + } + return 0; +} + +int CAltNamesParser::NameToAltName(DWORD uid, char *altname) +{ + if(classinit) { + if(nmap.find(uid) != nmap.end()) { + strcpy(altname, nmap[uid]); + return 1; + } + } + return 0; +} blob - /dev/null blob + cefae2d1a431b4824fedd926b78ab92c4ed7bae3 (mode 644) --- /dev/null +++ src/colornick.h @@ -0,0 +1,62 @@ +/*************************************************************************** + colornick.h - alternative nick spelling support include + ------------------- + begin : Sat Jun 07 2003 + copyright : (C) 2001-2003 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef COLORNICK_H_INCLUDED +#define COLORNICK_H_INCLUDED + +#include "basetypes.h" + +#if defined(__GNUC__) +# if __GNUC__ < 3 && __GNUC__ >= 2 && __GNUC_MINOR__ >= 95 +# include +# elif __GNUC__ >= 3 +# include +namespace std{ + using namespace __gnu_cxx; +} +# else +# include +# endif +#elif defined(_MSC_VER) +# if _MSC_VER >= 1100 +# include +# else +# error "std::hash_map is not available with this compiler, compile using MSVC7 and later" +# endif +#elif defined(__sgi__) +# include +#else +# error "std::hash_map is not available with this compiler" +#endif + +#define MAX_REAL_NICK_SIZE 30 +#define MAX_ALT_NICK_SIZE 300 + +class CAltNamesParser { +private: + int classinit; + WCFILE *f; + char ifname[1000]; + std::hash_map nmap; +#pragma pack(1) + typedef struct _AltNamesStruct { + DWORD uid; + char rname[MAX_REAL_NICK_SIZE]; + char aname[MAX_ALT_NICK_SIZE]; + } AltNamesStruct, *PAltNamesStruct; +#pragma pack(4) +public: + CAltNamesParser(char *fname, bool &init); + ~CAltNamesParser(); + + int AddAltName(DWORD uid, char *name, char *altname); + int DeleteAltName(DWORD uid); + int NameToAltName(DWORD uid, char *altname); +}; + +#endif blob - /dev/null blob + b8c217849812caef063248628fa2d32b094dad58 (mode 644) --- /dev/null +++ src/dbase.cpp @@ -0,0 +1,3244 @@ +/*************************************************************************** + dbase.cpp - database message engine + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "dbase.h" +#include "error.h" +#include "security.h" +#include "speller.h" +#include "messages.h" +#include "boardtags.h" +#include "profiles.h" +#include "freedb.h" +#include "sendmail.h" +#include "main.h" +#include "messages.h" + +static int curcolor = 1; + + +// current message displaying parameters +time_t RefreshDate; +int currentlsel; +int currenttc; +int currenttt; +int currenttv; +int currentss; +int currentdsm; +DWORD currenttopics; +int currentlm; +int currentfm; +int currentlt; +int currentft; +int currentlann; +int topicsoverride; +int currenttz; + +int cookie_lsel; +int cookie_tc; +int cookie_tt; +int cookie_tv; +int cookie_ss; +int cookie_dsm; +DWORD cookie_topics; +int cookie_tz; + +DWORD cookie_lastenter; +char *cookie_seq; +char *cookie_name; + +time_t current_minprntime; + +CUserLogin ULogin; + +#if USER_ALT_NICK_SPELLING_SUPPORT +static bool cninit; +CAltNamesParser AltNames(F_PROF_ALTNICK, cninit); +#endif + +int HPrinted = 0; + +char *Cip; +DWORD Nip = 0; +#if ALLOW_MARK_NEW_MESSAGES == 2 +DWORD newhref = 0; +#endif + +char DESIGN_open_dl[10]; +char DESIGN_open_dl_grey[20]; +char DESIGN_open_dl_white[20]; +char DESIGN_close_dl[10]; +char DESIGN_threads_divider[500]; +char DESIGN_break[10]; + +int ReadDBMessage(DWORD midx, SMessage *mes) +{ + WCFILE *f; + + if(midx == NO_MESSAGE_CODE) return 0; + if((f = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) return 0; + if(wcfseek(f, midx, SEEK_SET) != 0) + { + wcfclose(f); + return 0; + } + if(!fCheckedRead(mes, sizeof(SMessage), f)) + { + wcfclose(f); + return 0; + } + wcfclose(f); + return 1; +} + +int ReadDBMessageBody(char *buf, DWORD index, int size) +{ + FILE *f; + if((f = fopen(F_MSGBODY, FILE_ACCESS_MODES_R)) == NULL)return 0; + if(fseek(f, index, SEEK_SET) != 0) return 0; + if(fread(buf, 1, size, f) != size) return 0; + fclose(f); + return 1; +} + +int WriteDBMessage(DWORD midx, SMessage *mes) +{ + WCFILE *f; + + if((f = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) return 0; + lock_file(f); + if(wcfseek(f, midx, SEEK_SET) != 0) + { + unlock_file(f); + wcfclose(f); + return 0; + } + if(!fCheckedWrite(mes, sizeof(SMessage), f)) + { + unlock_file(f); + wcfclose(f); + return 0; + } + unlock_file(f); + wcfclose(f); + return 1; +} + +int IP2HostName(DWORD IP, char *hostname, int maxlen) +{ + struct hostent *he; +#if IP_TO_HOSTNAME_RESOLVE + // + // Resolve IP to DNS names + // + if((he = gethostbyaddr((char*)(&IP), 4, AF_INET)) != NULL) { + // prevent saving bad hostname + if(strlen(he->h_name) > 0) { + strncpy(hostname, he->h_name, maxlen); + + if(!strcmp(he->h_name, "veles-1.dipcompany.mipt.ru")) + strcpy(hostname, "work.box"); + + if(!strcmp(he->h_name, "sipa.4ka.mipt.ru")) + strcpy(hostname, "áåãåìîòèê.4ka.mipt.ru"); + + if(!strcmp(he->h_name, "mc.3ka.mipt.ru")) + strcpy(hostname, "votalka.mc"); + + if(!strcmp(he->h_name, "flower.4ka.private.mipt.ru")) + strcpy(hostname, "viento.4ka.private.mipt.ru"); + + if(!strcmp(he->h_name, "windmill.dgap.mipt.ru")) + strcpy(hostname, "rew24dollar.dgap.mipt.ru"); + + + if(!strcmp(he->h_name, "172.16.2.124")) + strcpy(hostname, "elmariachi.private.rt.mipt.ru"); + + if(!strcmp(he->h_name, "energy.3ka.mipt.ru")) + strcpy(hostname, "bahus.org"); + + } + else return 0; + } + else return 0; +#else + strcpy(hostname, inet_ntoa(IP), maxlen); +#endif + hostname[maxlen - 1] = 0; + return 1; +} + +int ConvertTime(time_t tt, char *s) +{ + tt = tt + 3600*(currenttz - DATETIME_DEFAULT_TIMEZONE); + +#if DATETIME_STYLE == 1 + char *c = ctime(&tt); + strcpy(s,c); + s[strlen(s)-1] = 0; +#endif +#if DATETIME_STYLE == 2 + tm *x; + x = localtime(&tt); + if(x->tm_min < 10) + sprintf(s, "%d/%d/%d %d:0%d", x->tm_mon + 1, x->tm_mday, x->tm_year + 1900, + x->tm_hour, x->tm_min); + else + sprintf(s, "%d/%d/%d %d:%d", x->tm_mon + 1, x->tm_mday, x->tm_year + 1900, + x->tm_hour, x->tm_min); +#endif +#if DATETIME_STYLE == 3 + tm *x; + x = localtime(&tt); + if(x) { + if(x->tm_min < 10) + sprintf(s, "%d/%d/%d %d:0%d",x->tm_mday, x->tm_mon + 1, x->tm_year + 1900, + x->tm_hour, x->tm_min); + else + sprintf(s, "%d/%d/%d %d:%d",x->tm_mday, x->tm_mon + 1, x->tm_year + 1900, + x->tm_hour, x->tm_min); + } +#endif + return 1; +} + +char* ConvertFullTime(time_t tt) +{ + char *days[7] = { + MESSAGEMAIN_DATETIME_DAY_SUN, + MESSAGEMAIN_DATETIME_DAY_MON, + MESSAGEMAIN_DATETIME_DAY_TEU, + MESSAGEMAIN_DATETIME_DAY_WED, + MESSAGEMAIN_DATETIME_DAY_THU, + MESSAGEMAIN_DATETIME_DAY_FRI, + MESSAGEMAIN_DATETIME_DAY_SAT + }; + char *months[12] = { + MESSAGEMAIN_DATETIME_JAN, + MESSAGEMAIN_DATETIME_FEB, + MESSAGEMAIN_DATETIME_MAR, + MESSAGEMAIN_DATETIME_APR, + MESSAGEMAIN_DATETIME_MAY, + MESSAGEMAIN_DATETIME_JUN, + MESSAGEMAIN_DATETIME_JUL, + MESSAGEMAIN_DATETIME_AUG, + MESSAGEMAIN_DATETIME_SEP, + MESSAGEMAIN_DATETIME_OCT, + MESSAGEMAIN_DATETIME_NOV, + MESSAGEMAIN_DATETIME_DEC + }; + static char s[1000]; + tm *x; + + x = localtime(&tt); + sprintf(s, "%s, %s %d %d:%02d:%02d %d", days[x->tm_wday], months[x->tm_mon], x->tm_mday, x->tm_hour, x->tm_min, x->tm_sec, x->tm_year + 1900); + + return s; +} + +void DB_Base::Profile_UserName(char *name, char *tostr, int reg, int doparsehtml) +{ + char *str, *str1; + if(reg) { + if(doparsehtml) str = FilterHTMLTags(name, AUTHOR_NAME_LENGTH*3+1, 0); + else str = name; + str1 = CodeHttpString(name, 0); // do not allocate memory, use internal buffer + sprintf(tostr, "%s", MY_CGI_URL, str1, str); + } + else + sprintf(tostr, DESIGN_MESSAGE_UNREG, name); +} + +/* this function could not print more than 32000 messages at once */ +int DB_Base::printThreadbuffer(SMessage *buf, DWORD size, int p, DWORD fmpos, int ll, + int *czero, DWORD selected, DWORD root, int *bp) +{ + if(p) { + DWORD count = size/sizeof(SMessage); + for(DWORD i = 0; i < count; i++) { + + if(fmpos + i*sizeof(SMessage) == root) (*bp) = 1; + if((*bp)){ + if(invflag != -1 || ((buf[i].Flag & MESSAGE_IS_INVISIBLE) != 0)) + { + if(((buf[i].Flag & MESSAGE_IS_INVISIBLE) != 0) && (invflag == -1)) + { + invflag = buf[i].Level; + } + else + { // (buf[i].Flag & MESSAGE_IS_INVISIBLE) == TRUE, invflag != -1 + // seems that invisibility was already started + if(invflag >= buf[i].Level) + { + if((buf[i].Flag & MESSAGE_IS_INVISIBLE) == 0) + { + // invisible message ended + invflag = -1; + goto L_BVisible1; + } + else + { + // next message invisible too + invflag = buf[i].Level; + } + } + } + // if admin, show all + if((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) goto L_BVisible1; + } + else { +L_BVisible1: + // we are printing content of a thread, READING THREAD + if(buf[i].Level != ll) + { + if(ll > buf[i].Level) + { + int x = ll - buf[i].Level; + for(int j = 0; j < x ; j++) printf(DESIGN_close_dl); + ll = buf[i].Level; + } + else + { + // only 1 level increase allowed + printf(DESIGN_open_dl); + ll = buf[i].Level; + } + } + else if (buf[i].Level > 0) { + // br before messages on one level, READING, 111!! + printf(DESIGN_break); + } + + if(buf[i].Level == 0) + { + (*czero)++; + if(*czero == 2) + { + return ll; + } + } + + if(selected != buf[i].ViIndex) + { + printhtmlmessage_in_index(&buf[i], MESSAGE_INDEX_PRINT_ITS_URL | MESSAGE_INDEX_DISABLE_ROLLED); + } + else + { + printhtmlmessage_in_index(&buf[i], MESSAGE_INDEX_DISABLE_ROLLED); + } + } + } + } + } + else { + DWORD count = size/sizeof(SMessage) - 1; + for(signed long i = count; i >= 0; i--) + { + + if(fmpos + i*sizeof(SMessage) == root) (*bp) = 1; + if(*bp) + { + if(invflag != -1 || ((buf[i].Flag & MESSAGE_IS_INVISIBLE) != 0)) + { + if(((buf[i].Flag & MESSAGE_IS_INVISIBLE) != 0) && (invflag == -1)) + { + invflag = buf[i].Level; + } + else + { + if(invflag >= buf[i].Level) + { + if((buf[i].Flag & MESSAGE_IS_INVISIBLE) == 0) + { + // invisible message ended + invflag = -1; + goto L_BVisible2; + } + else + { + // next message invisible too + invflag = buf[i].Level; + } + } + } + // if superuser, show all + if(ULogin.LU.right & USERRIGHT_SUPERUSER) goto L_BVisible2; + } + else + { +L_BVisible2: + if(buf[i].Level != ll) + { + if(ll > buf[i].Level) + { + int x = ll - buf[i].Level; + for(int j = 0; j < x ; j++) printf(DESIGN_close_dl); + ll = buf[i].Level; + } + else + { + // only 1 level increase allowed + printf(DESIGN_open_dl); + ll = buf[i].Level; + } + } + else if (buf[i].Level > 0) { + // br before messages on one level, READING, 111!! + printf(DESIGN_break); + } + + if(buf[i].Level == 0) + { + (*czero)++; + if(*czero == 2) + { + return ll; + } + } + if(selected != buf[i].ViIndex) + { + printhtmlmessage_in_index(&buf[i], MESSAGE_INDEX_PRINT_ITS_URL | MESSAGE_INDEX_DISABLE_ROLLED); + } + else + { + printhtmlmessage_in_index(&buf[i], MESSAGE_INDEX_DISABLE_ROLLED); + } + } + } + } + } + return ll; +} + +/* this function could not print more than 32000 messages at once */ +int DB_Base::printhtmlbuffer(SMessage *buf, DWORD size, int p/*direction*/, int *ll, int *pr, DWORD mode, DWORD &shouldprint, DWORD &skipped) +{ + + if(p) + { + DWORD count = size/sizeof(SMessage); + for(DWORD i = 0; i < count; i++) + { +#if TOPICS_SYSTEM_SUPPORT + // check for topic match our topic mask + if(buf[i].Level == 0) { + // check should we stop printing because of data limitation + if(buf[i].Date < current_minprntime && currentlsel == 1) { + return 0; + } + if( !((1 << buf[i].Topics) & currenttopics) ) + { + invflag = 0; + collapsed = 1; + skipped |= 0xf0000000; + continue; + } + } +#endif + // check for view mode == all rolled + if((mode & PRINTMODE_ALL_ROLLED) && buf[i].Level == 0) { + invflag = buf[i].Level; + collapsed = 1; + /* show first message of the thread */ + goto L_BVisible1; + } + + if(invflag != -1 || (buf[i].Flag & MESSAGE_IS_INVISIBLE) || + (buf[i].Flag & MESSAGE_COLLAPSED_THREAD)) + { + + if((invflag == -1) && ((buf[i].Flag & MESSAGE_IS_INVISIBLE) || + (buf[i].Flag & MESSAGE_COLLAPSED_THREAD))) + { + // + // Starting invsible/rolled message check + // + invflag = buf[i].Level; + if(buf[i].Flag & MESSAGE_COLLAPSED_THREAD) + { + collapsed = 1; + // can we show it ? + if((buf[i].Flag & MESSAGE_IS_INVISIBLE) != 0) { + if((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) { + /* show first message of the rolled thread */ + goto L_BVisible1; + } + } + else goto L_BVisible1; + } + } + else + { + // + // Check for stopping rolled/invisible thread + // + if(invflag >= buf[i].Level) + { + if(buf[i].Flag & MESSAGE_IS_INVISIBLE) + { + /* next message invisible too */ + invflag = buf[i].Level; + + if((ULogin.LU.right & USERRIGHT_SUPERUSER)) { + if((buf[i].Flag & MESSAGE_COLLAPSED_THREAD) != 0) { + collapsed = 1; + goto L_BVisible1; + } + else collapsed = 0; + } + } + else + { + /* invisible or collapsed message ended or not ?*/ + if((buf[i].Flag & MESSAGE_COLLAPSED_THREAD) == 0 && collapsed) { + /* next message collapsed too */ + invflag = -1; + collapsed = 0; + } + else if(collapsed == 0 && (buf[i].Flag & MESSAGE_COLLAPSED_THREAD) != 0) { + collapsed = 1; + } + else if(collapsed == 1 && (buf[i].Flag & MESSAGE_COLLAPSED_THREAD) != 0) { + } + else { + invflag = -1; + } + goto L_BVisible1; + } + } + } + + /* if admin, show all invisible messages */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) && (!collapsed)) + goto L_BVisible1; +#if ALLOW_MARK_NEW_MESSAGES + /* check for new message mark */ + if((collapsed) && currentlm < buf[i].ViIndex && (skipped & 0xf0000000) == 0) { + if(newmessflag) { + if(lastmes.Date < buf[i].Date) + memcpy(&lastmes, &(buf[i]), sizeof(SMessage)); + } + else memcpy(&lastmes, &(buf[i]), sizeof(SMessage)); + newmessflag++; + } +#endif + if(buf[i].Level == 0) skipped |= 0xf0000000; + if((skipped & 0xf0000000) == 0) skipped++; + } + else { +L_BVisible1: + /* check if it's end of thread and if it is increase already printed count + * also check should we stop printing + */ + + if(currentlm < buf[i].ViIndex){ + nm_counter ++; + if(buf[i].Level == 0) + nt_counter ++; + } + + if(buf[i].Level == 0) + { + alrprn++; + // check should we stop printing + if( (currentlsel == 1 && buf[i].Date < current_minprntime) || + (currentlsel == 2 && alrprn == currenttc + 1) ) + { + return 0; + } + } + + int delayprint = 0; + if(shouldprint != 0xFFFFFFFF) { + // full collapsed thread, INDEX + //printf("
33"); + + skipped &= (~0xf0000000); + // delayed print done + if(skipped) delayprint = 1; + printhtmlmessage_in_index(&pmes, MESSAGE_INDEX_PRINT_ITS_URL, skipped, newmessflag); + newmessflag = 0; + shouldprint = 0xFFFFFFFF; + skipped = 0; + } + + // there more than 1 message in thread, MAIN INDEX! + if(buf[i].Level != (*ll)) { + if((*ll) > buf[i].Level) { + int x = (*ll) - buf[i].Level; + for(int j = 0; j < x ; j++) printf(DESIGN_close_dl); + (*ll) = buf[i].Level; + } + else { + // only 1 level of message increase allowed + printf(DESIGN_open_dl); + (*ll) = buf[i].Level; + } + } + else if (buf[i].Level > 0){ + // br before messages on one level, INDEX, 44!! + if(!delayprint) printf(DESIGN_break); + } + + if(buf[i].Level == 0 && (*pr)) { + // div's alternating color + printf("%s%s",DESIGN_close_dl, DESIGN_threads_divider); + if(curcolor) printf(DESIGN_open_dl_white); + else printf(DESIGN_open_dl_grey); + curcolor = !curcolor; + } + else (*pr) = 1; + + if(!collapsed) { + //printf("
44"); + + printhtmlmessage_in_index(&buf[i], MESSAGE_INDEX_PRINT_ITS_URL); + } + else { + shouldprint = i; + skipped = 0; + newmessflag = 0; + memcpy(&pmes, &buf[i], sizeof(SMessage)); + } + } + } + } + else { + DWORD count = size/sizeof(SMessage) - 1; + for(signed long i = count; i >= 0; i--) + { +#if TOPICS_SYSTEM_SUPPORT + // check for topic match our topic mask + if(buf[i].Level == 0) { + // check should we stop printing because of data limitation + if(buf[i].Date < current_minprntime && currentlsel == 1) { + return 0; + } + if( !((1 << buf[i].Topics) & currenttopics) ) + { + invflag = 0; + collapsed = 1; + skipped |= 0xf0000000; + continue; + } + } +#endif + + // check for view mode == all rolled + if((mode & PRINTMODE_ALL_ROLLED) && buf[i].Level == 0) { + invflag = buf[i].Level; + collapsed = 1; + /* show first message of the thread */ + goto L_BVisible2; + } + + if(invflag != -1 || (buf[i].Flag & MESSAGE_IS_INVISIBLE) || + (buf[i].Flag & MESSAGE_COLLAPSED_THREAD)) + { + + if((invflag == -1) && ((buf[i].Flag & MESSAGE_IS_INVISIBLE) || + (buf[i].Flag & MESSAGE_COLLAPSED_THREAD))) + { + // + // Starting invsible/rolled message check + // + invflag = buf[i].Level; + if(buf[i].Flag & MESSAGE_COLLAPSED_THREAD) + { + collapsed = 1; + // can we show it ? + if((buf[i].Flag & MESSAGE_IS_INVISIBLE) != 0) { + if((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) { + /* show first message of the rolled thread */ + goto L_BVisible2; + } + } + else goto L_BVisible2; + } + } + else + { + // + // Check for stopping rolled/invsible thread + // + if(invflag >= buf[i].Level) + { + if(buf[i].Flag & MESSAGE_IS_INVISIBLE) + { + /* next message invisible too */ + invflag = buf[i].Level; + + if((ULogin.LU.right & USERRIGHT_SUPERUSER)) { + if((buf[i].Flag & MESSAGE_COLLAPSED_THREAD) != 0) { + collapsed = 1; + goto L_BVisible2; + } + else collapsed = 0; + } + } + else + { + /* invisible or collapsed message ended or not ?*/ + if((buf[i].Flag & MESSAGE_COLLAPSED_THREAD) == 0 && collapsed) { + /* next message collapsed too */ + invflag = -1; + collapsed = 0; + } + else if(collapsed == 0 && (buf[i].Flag & MESSAGE_COLLAPSED_THREAD) != 0) { + collapsed = 1; + } + else if(collapsed == 1 && (buf[i].Flag & MESSAGE_COLLAPSED_THREAD) != 0) { + } + else { + invflag = -1; + } + goto L_BVisible2; + } + } + } + /* if admin, show all invisible messages */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) && (!collapsed)) + goto L_BVisible2; +#if ALLOW_MARK_NEW_MESSAGES + /* check for new message mark */ + if((collapsed) && currentlm < buf[i].ViIndex && (skipped & 0xf0000000) == 0) { + if(newmessflag) { + if(lastmes.Date < buf[i].Date) + memcpy(&lastmes, &(buf[i]), sizeof(SMessage)); + } + else memcpy(&lastmes, &(buf[i]), sizeof(SMessage)); + newmessflag++; + } +#endif + if(buf[i].Level == 0) skipped |= 0xf0000000; + if((skipped & 0xf0000000) == 0) skipped++; + } + else + { +L_BVisible2: + /* check if it's end of thread and if it is increase already printed count + * also check should we stop printing + */ + + if(currentlm < buf[i].ViIndex){ + nm_counter ++; + if(buf[i].Level == 0) + nt_counter ++; + } + + if(buf[i].Level == 0) + { + alrprn++; + // check should we stop printing + if( (currentlsel == 1 && buf[i].Date < current_minprntime) || + (currentlsel == 2 && alrprn == currenttc + 1) ) + { + return 0; + } + } + + int delayprint = 0; + if(shouldprint != 0xFFFFFFFF) { + // before collapsed sub thread in main INDEX + + skipped &= (~0xf0000000); + // delayed print done + if(skipped) delayprint = 1; + printhtmlmessage_in_index(&pmes, MESSAGE_INDEX_PRINT_ITS_URL, skipped, newmessflag); + newmessflag = 0; + shouldprint = 0xFFFFFFFF; + skipped = 0; + } + + // only one message in (sub) thread, could be collapsed, MAIN INDEX + if(buf[i].Level != (*ll)) + { + if((*ll) > buf[i].Level) + { + int x = (*ll) - buf[i].Level; + for(int j = 0; j < x ; j++) printf(DESIGN_close_dl); + (*ll) = buf[i].Level; + } + else + { + /* only 1 level increase allowed */ + printf(DESIGN_open_dl); + (*ll) = buf[i].Level; + } + } + else if (buf[i].Level > 0){ + // br before messages on one level, INDEX, 44!! + if(!delayprint) printf(DESIGN_break); + } + + if(buf[i].Level == 0 && (*pr)) { + // div's alternating color + printf("%s%s", DESIGN_close_dl, DESIGN_threads_divider); + if(curcolor) printf(DESIGN_open_dl_white); + else printf(DESIGN_open_dl_grey); + curcolor = !curcolor; + } + else (*pr) = 1; + + if(!collapsed) { + //printf("
66"); + + printhtmlmessage_in_index(&buf[i], MESSAGE_INDEX_PRINT_ITS_URL); + } + else { + shouldprint = i; + skipped = 0; + newmessflag = 0; + memcpy(&pmes, &buf[i], sizeof(SMessage)); + } + } + } + } + return 1; +} + +int DB_Base::DB_PrintHtmlIndex(time_t time1, time_t time2, DWORD mtc) +{ + curcolor = (mtc % 2); + + // if we have NULL topics - stop printing + if(currenttopics == 0) return 0; + + switch(currentss) { + case 1: + return printhtmlindexhron_bythreads(PRINTMODE_NULL); + case 2: + return printhtmlindexhron_bythreads(PRINTMODE_NULL); + case 3: + return printhtmlindexhron_wothreads(); + case 4: + return printhtmlindexhron_bythreads(PRINTMODE_ALL_ROLLED); + } + return 1; +} + +int DB_Base::printhtmlmessage_in_index(SMessage *mes, int style, DWORD skipped, int newmessmark) +{ + // define common used code printing afrer message header ([url],[pic], etc.) +#define PRINT_COMMON_POST_MESSAGE_INFO() {\ + if((mes->Flag & MESSAGE_HAVE_URL) == MESSAGE_HAVE_URL)\ + printf(TAG_MSG_HAVE_URL);\ + if((mes->Flag & MESSAGE_HAVE_BODY) != MESSAGE_HAVE_BODY)\ + printf(TAG_MSG_HAVE_NO_BODY);\ + if((mes->Flag & MESSAGE_HAVE_PICTURE) == MESSAGE_HAVE_PICTURE)\ + printf(TAG_MSG_HAVE_PIC);\ +} + + // define common used code printing before message header (topic) +#define PRINT_COMMON_PREV_MESSAGE_INFO() {\ + if(mes->Topics <= TOPICS_COUNT - 1 && mes->Level == 0 && mes->Topics != 0) {\ + printf(DESIGN_TOPIC_TAG_OPEN "%s" DESIGN_TOPIC_TAG_CLOSE DESIGN_TOPIC_DIVIDER,Topics_List[mes->Topics]);\ + }\ +} + // ******************************* + // BUG BUG with aname + ////////////////////////////////// + char *mp = NULL, aname[1000], tm[200]; + DWORD ff; + DWORD flg; + + /*if(strcmp(mes->HostName, "172.16.1.130") == 0) + return 0;*/ + +#if ALLOW_MARK_NEW_MESSAGES == 2 + if((currentdsm & 16) != 0) { + if(currentlm < mes->ViIndex || newmessmark) printf(TAG_NEW_MSG_MARK_HREF,newhref,++newhref+1); + } + else { + if(currentlm < mes->ViIndex || newmessmark) printf(TAG_NEW_MSG_MARK); + } +#endif +#if ALLOW_MARK_NEW_MESSAGES == 1 + if(currentlm < mes->ViIndex || newmessmark) printf(TAG_NEW_MSG_MARK); +#endif + + ConvertTime(mes->Date, tm); + + // check whether smiles have been disabled globally + if((currentdsm & 1) == 0) flg = MESSAGE_ENABLED_TAGS | MESSAGE_ENABLED_SMILES; + else flg = MESSAGE_ENABLED_TAGS; + if(FilterBoardTags(mes->MessageHeader, &mp, mes->SecHeader, MAX_PARAMETERS_STRING, + flg, &ff) != 0) { + } + else mp = (char*)(&mes->MessageHeader); + + // does this message posted by registred user ? + if(mes->UniqUserID == 0) sprintf(aname, DESIGN_UNREGISTRED_NICK, mes->AuthorName); + else { + char altnick[1000]; + + if((currentdsm & 0x40) == 0) { + // + // first of all translate to to alt nick if requred + // + if(!AltNames.NameToAltName(mes->UniqUserID, altnick)) { + strcpy(altnick, mes->AuthorName); + } + } + else strcpy(altnick, mes->AuthorName); + + // if this, is does this user view this message ;-) ? + if( ((currentdsm & 0x08) == 0) && ULogin.LU.ID[0] !=0 && mes->UniqUserID == ULogin.LU.UniqID ) { + sprintf(aname, DESIGN_REGISTRED_OWN_NICK, altnick); + } + else { + char *ts; + // maybe user has selected some nicks to be displayed as detailed nicks? + if(ULogin.LU.ID[0] != 0 && ((ts = strstr(ULogin.pfui->SelectedUsers, mes->AuthorName)) != NULL)) { + sprintf(aname, DESIGN_SELECTEDUSER_NICK, altnick); + } + else { + sprintf(aname, DESIGN_REGISTRED_NICK, altnick); + } + } + } + + if(mes->Flag & MESSAGE_IS_CLOSED) printf(TAG_MSG_CLOSED_THREAD); +/* if((mes->Flag & MESSAGE_COLLAPSED_THREAD) && ((style & MESSAGE_INDEX_DISABLE_ROLLED) == 0)) + printf(TAG_MSG_ROLLED_THREAD);*/ + + if((mes->Flag & MESSAGE_IS_INVISIBLE) != 0) + printf(""); + + printf("ViIndex); + if(MESSAGE_INDEX_PRINT_ITS_URL & style) + printf(" HREF=\"%s?read=%ld\"",MY_CGI_URL, mes->ViIndex); + if(MESSAGE_INDEX_PRINT_BLANK_URL & style) + printf(" TARGET=\"_blank\""); + if((MESSAGE_INDEX_PRINT_ITS_URL & style) == 0) printf(">"); + else printf(">"); +#if TOPICS_SYSTEM_SUPPORT + PRINT_COMMON_PREV_MESSAGE_INFO(); +#endif + // subject + printf("%s", mp); + if((MESSAGE_INDEX_PRINT_ITS_URL & style) == 0) printf(""); + + PRINT_COMMON_POST_MESSAGE_INFO(); + + if(mes->Readed) printf(" (%d)", mes->Readed); + else printf(""); + + printf(" -- %s", aname); + if((currentdsm & 32) == 0)printf(" (%s)", mes->HostName); + printf(" -- %s", tm); + + if((mes->Flag & MESSAGE_IS_INVISIBLE) != 0) + printf(""); + + if(skipped != 0xffffffff && skipped != 0) { + if(newmessmark) { + // does this message posted by registred user ? + if(lastmes.UniqUserID == 0) sprintf(aname, DESIGN_UNREGISTRED_NICK, lastmes.AuthorName); + else { + char altnick[1000]; + + if((currentdsm & 0x40) == 0) { + // + // first of all translate to to alt nick if requred + // + if(!AltNames.NameToAltName(lastmes.UniqUserID, altnick)) { + strcpy(altnick, lastmes.AuthorName); + } + } + else strcpy(altnick, lastmes.AuthorName); + + // if this, is does this user view this message ;-) ? + if( ((currentdsm & 0x08) == 0) && ULogin.LU.ID[0] !=0 && lastmes.UniqUserID == ULogin.LU.UniqID ) { + sprintf(aname, DESIGN_REGISTRED_OWN_NICK, altnick); + } + else { + char *ts; + // maybe user has selected some nicks to be displayed as detailed nicks? + if(ULogin.LU.ID[0] != 0 && ((ts = strstr(ULogin.pfui->SelectedUsers, lastmes.AuthorName)) != NULL)) { + sprintf(aname, DESIGN_SELECTEDUSER_NICK, altnick); + } + else { + sprintf(aname, DESIGN_REGISTRED_NICK, altnick); + } + } + } + ConvertTime(lastmes.Date, tm); + printf(TAG_ONLYHEADERS_POSTCNT_MARKNEW, DESIGN_open_dl, TAG_MSG_ROLLED_THREAD, + skipped, newmessmark, MY_CGI_URL, lastmes.ViIndex, aname, + tm, DESIGN_close_dl); + } + else + printf(TAG_ONLYHEADERS_POSTCNT, DESIGN_open_dl, TAG_MSG_ROLLED_THREAD, + skipped, DESIGN_close_dl); + } + + if(mp != (char*)&mes->MessageHeader) free(mp); + return 1; +} + +int DB_Base::PrintHtmlMessageBufferByVI(DWORD *VI, DWORD cnt) +{ + SMessage msgs; + DWORD fmpos, i; + WCFILE *m; + + /* initializing */ + alrprn = 0; + + invflag = -1; + collapsed = 0; + newmessflag = 0; + + if((m = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + + // search result entry + printf(DESIGN_open_dl); + + for(i = 0; i < cnt; i++) { + + fmpos = TranslateMsgIndex(VI[i]); + + if(fmpos == NO_MESSAGE_CODE) + continue; + + if(wcfseek(m, fmpos, SEEK_SET) < 0) { + wcfclose(m); + return 0; + } + + if(!fCheckedRead(&msgs, sizeof(SMessage), m)) + printhtmlerror(); + + // check if user have superuser permissions if message is invisible + if( ((msgs.Flag & MESSAGE_IS_INVISIBLE) == 0) || + ((msgs.Flag & MESSAGE_IS_INVISIBLE) != 0 && (ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) ) { + printf(DESIGN_break); + printhtmlmessage_in_index(&msgs, MESSAGE_INDEX_PRINT_ITS_URL | MESSAGE_INDEX_PRINT_BLANK_URL | MESSAGE_INDEX_DISABLE_ROLLED); + } + } + printf(DESIGN_close_dl); + wcfclose(m); + return 1; +} + +int DB_Base::PrintandCheckMessageFavsExistandInv(SProfile_UserInfo *ui, DWORD viewinv, int *updated) +{ + + SMessage msgs; + DWORD fmpos, cnt = 0; + int i; + WCFILE *m; + *updated = 0; + + printf(DESIGN_open_dl); + printf("

"); + /* initializing */ + if((m = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + // search result entry + for(i = PROFILES_FAV_THREADS_COUNT - 1; i + 1 > 0; i--) { + + if((fmpos = TranslateMsgIndex(ui->favs[i])) == NO_MESSAGE_CODE){ + ui->favs[i] = 0; + *updated = 1; + continue; + } + if(wcfseek(m, fmpos, SEEK_SET) < 0) { + wcfclose(m); + return 0; + } + + if(!fCheckedRead(&msgs, sizeof(SMessage), m)) printhtmlerror(); + if((msgs.Flag & MESSAGE_IS_INVISIBLE) && viewinv == 0) { + ui->favs[i] = 0; + *updated = 1; + continue; + } + printf(DESIGN_break); + cnt++; + printf("%ld." "" DESIGN_FAVORITES_DEL_THREAD " ", + cnt, ui->favs[i]); + printhtmlmessage_in_index(&msgs, MESSAGE_INDEX_PRINT_ITS_URL | MESSAGE_INDEX_PRINT_BLANK_URL | MESSAGE_INDEX_DISABLE_ROLLED); + } + wcfclose(m); + printf(DESIGN_close_dl); + printf("

"); + return cnt; +} + +int DB_Base::printhtmlindexhron_wothreads() +{ + SMessage msgs; + DWORD fpos, fmpos; + WCFILE *f, *m; + + // initializing + alrprn = 0; + invflag = -1; + collapsed = 0; + newmessflag = 0; + + if((f = wcfopen(F_VINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if((m = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + + printf(DESIGN_open_dl); + + if(wcfseek(f, 0, SEEK_END) != 0) printhtmlerror(); + fpos = wcftell(f); + + do { + if(fpos == 4) break; + + fpos-=sizeof(DWORD); + + if(wcfseek(f, fpos, SEEK_SET) < 0) printhtmlerror(); + if(!fCheckedRead(&fmpos, sizeof(DWORD), f)) + printhtmlerror(); + + if(fmpos == NO_MESSAGE_CODE) continue; + + printf(DESIGN_break); + + if(wcfseek(m, fmpos, SEEK_SET) != 0) + printhtmlerror(); + if(!fCheckedRead(&msgs, sizeof(SMessage), m)) + printhtmlerror(); + + printhtmlmessage_in_index(&msgs, MESSAGE_INDEX_PRINT_ITS_URL | MESSAGE_INDEX_DISABLE_ROLLED); + + alrprn++; + + } while((currentlsel == 1 && msgs.Date > current_minprntime) || + (currentlsel == 2 && alrprn != currenttc + 1)); + + printf(DESIGN_close_dl); + + wcfclose(f); + wcfclose(m); + + return 1; +} + +int DB_Base::printhtmlindexhron_bythreads(DWORD mode) +{ + SMessageTable *buf; + SMessage *msgs; + DWORD rr, fmpos, shouldprint = 0xFFFFFFFF, skipped = 0; + DWORD fipos; + int LastLevel = 0; + int firprn = 0; + + // initializing + alrprn = 0; + invflag = -1; + collapsed = 0; + newmessflag = 0; + nt_counter = 0; + nm_counter = 0; + + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_MSGINDEX); + if((fi = wcfopen(F_INDEX, FILE_ACCESS_MODES_R)) == NULL) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_INDEX); + + if(wcfseek(fi, 0, SEEK_END) != 0) printhtmlerror(); + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)*READ_MESSAGE_TABLE + 1); + msgs = (SMessage *)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER + 1); + + fipos = wcftell(fi); + + // beginning thread envelope - div + if (curcolor) printf(DESIGN_open_dl_white); + else printf(DESIGN_open_dl_grey); + curcolor=!curcolor; + + for(;;) { + DWORD tord; + if(fipos == 0) break; + else { + if(fipos >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + fipos = fipos - READ_MESSAGE_TABLE*sizeof(SMessageTable); + tord = READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + tord = fipos; + fipos = 0; + } + } + + if(wcfseek(fi, fipos, SEEK_SET) != 0) printhtmlerror(); + if((rr = wcfread(buf, 1, tord, fi)) != tord) printhtmlerror(); + + signed long i = rr / sizeof(SMessageTable) - 1; + + while(i >= 0) { + if(buf[i].begin < buf[i].end ) { + // forward direction + fmpos = buf[i].begin; + if(wcfseek(fm, fmpos, SEEK_SET) == -1) printhtmlerror(); + while(fmpos != (buf[i].end + 1)) { + DWORD toread; + if(buf[i].end - fmpos < READ_MESSAGE_HEADER*sizeof(SMessage)) { + toread = buf[i].end - fmpos + 1; + fmpos = fmpos + toread; + } + else { + toread = READ_MESSAGE_HEADER*sizeof(SMessage); + fmpos = fmpos + toread; + } + if(!fCheckedRead(msgs, toread, fm)) printhtmlerror(); + + if(printhtmlbuffer(msgs, toread, PRINT_FORWARD, &LastLevel, &firprn, mode, shouldprint, skipped) == 0) { + goto End_of_Prn; + } + + } + } + else { + // backward direction + DWORD toread; + fmpos = buf[i].begin + 1; + while(fmpos != buf[i].end) { + if( fmpos - buf[i].end > READ_MESSAGE_HEADER*sizeof(SMessage)) { + fmpos = fmpos - READ_MESSAGE_HEADER*sizeof(SMessage); + toread = READ_MESSAGE_HEADER*sizeof(SMessage); + } + else { + toread = fmpos - buf[i].end; + fmpos = buf[i].end; + } + + if(wcfseek(fm, fmpos, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msgs, toread, fm)) printhtmlerror(); + + if(printhtmlbuffer(msgs, toread, PRINT_BACKWARD, &LastLevel, &firprn, mode, shouldprint, skipped) == 0) { + goto End_of_Prn; + } + } + } + i--; + } + } +End_of_Prn: + + for(int i = -1; i < LastLevel; i++) printf(DESIGN_close_dl); + + DWORD totalcount = MessageCountInDB(); + printf(MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT); + if(nm_counter) + printf(MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT_NEW, nt_counter, nm_counter, totalcount); + else printf(MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT_NO_NEW, totalcount); + + free(buf); + free(msgs); + wcfclose(fi); + wcfclose(fm); + return 1; +} + +DB_Base::DB_Base() +{ + fi = NULL; + fb = NULL; + fm = NULL; + fv = NULL; +} + +DB_Base::~DB_Base() +{ + +} + +/* insert message "mes" with body "body" acording CFlags to board + * REMARKS: mes->Host should be IP address, not a DNS name, + * this function DOESN'T SET CURRENT DATE AND TIME + * returns 0 if successfull, otherwise error code returned + */ +int DB_Base::DB_InsertMessage(struct SMessage *mes, DWORD root, WORD msize, char** body, + DWORD CFlags, char *passw, char **banreason) +{ + DWORD fp,fl; + DWORD ri,fisize, rd; + SMessageTable *buf; + SMessage *msg; + unsigned char haddr[4]; + void *tmp; + signed long i; + int code; + int re; // reply flag + hostent *he; + DWORD MFlags, msigned = 0; + + CProfiles *uprof = NULL; + /* posting user SProfile_UserInfo absoulte index in profile database */ + DWORD Uind = 0xFFFFFFFF; + + /****** check User ******/ + SProfile_UserInfo UI; + SProfile_FullUserInfo FUI; + + if(passw != NULL && *passw != 0) { + uprof = new CProfiles(); + if(uprof->errnum != PROFILE_RETURN_ALLOK) { +#if ENABLE_LOG >= 1 + print2log("Error working with profiles database (init)"); +#endif + printhtmlerror(); + } + int opres = uprof->GetUserByName(mes->AuthorName, &UI, NULL, &Uind); + if((opres != PROFILE_RETURN_ALLOK) || (strcmp(UI.password, passw) != 0)) { + delete uprof; + return MSG_CHK_ERROR_INVALID_PASSW; + } + } + else { + if(ULogin.LU.ID[0] != 0) { + // + // User was already logged in + // + memcpy(&UI, ULogin.pui, sizeof(UI)); + strcpy(mes->AuthorName, UI.username); + Uind = ULogin.LU.SIndex; + } + else { + char *st; + + /* default user */ + UI.secur = DEFAULT_NOBODY_SECURITY_BYTE; + UI.secheader = DEFAULT_NOBODY_HDR_SEC_BYTE; + UI.right = DEFAULT_NOBODY_RIGHT; + UI.UniqID = 0; + + // check user name length ;-) + if(FilterBoardTags(mes->AuthorName, &st, 255, AUTHOR_NAME_LENGTH - 1, BOARDTAGS_TAG_PREPARSE, &fp) == 0) { + return MSG_CHK_ERROR_NONAME; + } + else { + strcpy(mes->AuthorName, st); + free(st); + } + if(strlen(mes->AuthorName) == 0 || strcmp(mes->AuthorName, " ") == 0) return MSG_CHK_ERROR_NONAME; +#if POST_ALLOW_UNDER_SAME_NICK == 0 + uprof = new CProfiles(); + if(uprof->GetUserByName(mes->AuthorName, NULL, NULL, NULL) == PROFILE_RETURN_ALLOK) { + delete uprof; + return MSG_CHK_ERROR_INVALID_PASSW; + } +#endif + } + } + + + +// Check security rights for logged users + if( + !(UI.right & USERRIGHT_SUPERUSER) && + !((UI.right & USERRIGHT_CREATE_MESSAGE) && root) && + !((UI.right & USERRIGHT_CREATE_MESSAGE_THREAD) && root == 0)) { + return MSG_CHK_ERROR_BANNED; + } + + if(UI.Flags & PROFILES_FLAG_HAVE_SIGNATURE) { + // set "signed" flag in message + msigned = 1; + } + + + // + // Message security == user security !!! + // + if(UI.right & USERRIGTH_ALLOW_HTML) CFlags = CFlags | MSG_CHK_ALLOW_HTML; + mes->Security = UI.secur; + mes->SecHeader = UI.secheader; + // set poster ID of message + mes->UniqUserID = UI.UniqID; + + // message header, banned address and spelling message check + switch (code = CheckSpellingBan(mes, body, banreason, CFlags, &MFlags, UI.UniqID)) { + case MSG_CHK_ERROR_PASSED: + break; + default: + return code; + } + + /* increase postcount if posting as registred user */ + if(Uind != 0xFFFFFFFF) { + if(!uprof) uprof = new CProfiles(); // if it's logged in user + + UI.postcount++; + UI.lastIP = mes->IPAddr; + UI.LoginDate = time(NULL); + + if(uprof->SetUInfo(Uind, &UI) == 0) { + delete uprof; +#if ENABLE_LOG >= 1 + print2log("Call to CProfiles::SetUInfo failed at DB_Base::DB_InsertMessage(), line %d (Update user information for %s)", + __LINE__, UI.username); +#endif + printhtmlerror(); + } + } + if(uprof != NULL) delete uprof; + + + if(*body != NULL && **body != 0) msize = (WORD)(strlen(*body) + 1); + else { + msize = 0; + } + + // tuning some columns of the message stucture + mes->Readed = 0; + mes->msize = msize; + mes->Level = 0; + mes->Flag = 0; + mes->ParentThread = 0; + + /************ set flags of message ************/ + /* tune [pic] [url] message flags and other message flags */ + mes->Flag = mes->Flag | MFlags; + + // set "signed" flag + if(msigned && (CFlags & MSG_CHK_DISABLE_SIGNATURE) == 0) + mes->Flag |= MESSAGE_WAS_SIGNED; + + if(msize > 0) mes->Flag |= MESSAGE_HAVE_BODY; + + if((CFlags & MSG_CHK_ENABLE_EMAIL_ACKNL) && Uind != 0xFFFFFFFF) + mes->Flag |= MESSAGE_MAIL_NOTIFIATION; + /**********************************************/ + + // tune message level and parent thread, if it's reply + // *** NEW *** : also tune Topic (if only one topic per thread supported) + if(root != 0) { + DWORD viroot = root; + re = 1; // set "reply" flag + + // get real index + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return MSG_CHK_ERROR_INVALID_REPLY; + + // read parent message + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + msg = (SMessage *)malloc(sizeof(SMessage)); + if(wcfseek(fm, root, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msg, sizeof(SMessage), fm)) printhtmlerror(); + wcfclose(fm); + + // check whether post is allowed + if((UI.right & USERRIGHT_SUPERUSER) == 0 && (msg->Flag & MESSAGE_IS_CLOSED)) { + free(msg); + return MSG_CHK_ERROR_CLOSED; + } + + // tune level of message + mes->Level = (WORD)(msg->Level + 1); + + // tune parent thread + if(msg->Level > 0) + mes->ParentThread = msg->ParentThread; + else + mes->ParentThread = root; + + // tune topic + mes->Topics = msg->Topics; + + // tune flags (inheritance) + mes->Flag |= ((msg->Flag & (MESSAGE_IS_INVISIBLE | MESSAGE_COLLAPSED_THREAD | MESSAGE_IS_CLOSED))); + + // send mail ackn if required + { + // 1. Get user and email + CProfiles prof; + SProfile_UserInfo ui; + SProfile_FullUserInfo fui; + char subj[1000]; + char bdy[100000]; + + fui.AboutUser = NULL; + + if(msg->UniqUserID != 0 && prof.GetUserByName(msg->AuthorName, &ui, &fui, NULL) == PROFILE_RETURN_ALLOK && + ((msg->Flag & MESSAGE_MAIL_NOTIFIATION) || (ui.Flags & PROFILES_FLAG_ALWAYS_EMAIL_ACKN)) ) { + char *pb, *pb1, *pb2; + DWORD tmp; + + DWORD flags = MESSAGE_ENABLED_TAGS; + + if(!PrepareTextForPrint(mes->MessageHeader, &pb, mes->SecHeader, flags | BOARDTAGS_CUT_TAGS)) { + pb = (char*)malloc(strlen(mes->MessageHeader) + 1); + strcpy(pb, mes->MessageHeader); + } + + sprintf(subj, MAILACKN_REPLY_SUBJECT, pb); + free(pb); + + if(!PrepareTextForPrint(mes->MessageHeader, &pb, mes->SecHeader, flags | mes->Flag | BOARDTAGS_EXPAND_ENTER)) { + pb = (char*)malloc(strlen(mes->MessageHeader) + 1); + strcpy(pb, mes->MessageHeader); + } + if(!PrepareTextForPrint(msg->MessageHeader, &pb1, mes->SecHeader, flags | mes->Flag | BOARDTAGS_EXPAND_ENTER)) { + pb1 = (char*)malloc(strlen(msg->MessageHeader) + 1); + strcpy(pb1, msg->MessageHeader); + } + if(!PrepareTextForPrint(*body, &pb2, mes->Security, flags | mes->Flag | BOARDTAGS_EXPAND_ENTER | BOARDTAGS_PURL_ENABLE)) { + pb2 = (char*)malloc(strlen(*body) + 1); + strcpy(pb2, *body); + } + + sprintf(bdy, MAILACKN_REPLY_BODY, msg->AuthorName, mes->AuthorName, pb1, pb, pb2, viroot); + + wcSendMail(fui.Email, subj, bdy); + + print2log("Mailackn was sent to %s", fui.Email); + + free(pb); + free(pb1); + free(pb2); + } + if(fui.AboutUser) free(fui.AboutUser); + } + free(msg); + } + else { + re = 0; + } + + if((fb = wcfopen(F_MSGBODY, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerrorat(LOG_UNABLETOLOCATEFILERW, F_MSGBODY); + // ******* lock fb ******* + lock_file(fb); + + // get free space and set file pointer + CFreeDBFile fdb(F_FREEMBODY, 0); + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fb); + printhtmlerrorat(LOG_UNABLETOCREATEFILE, F_FREEMBODY); + } + if((rd = fdb.AllocFreeSpace(msize)) == 0xFFFFFFFF) { + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fb); + printhtmlerrorat(LOG_UNABLETOCREATEFILE, F_FREEMBODY); + } + + if(wcfseek(fb, 0, SEEK_END) != 0) { + unlock_file(fb); + printhtmlerror(); + } + rd = wcftell(fb); + // in case if file is empty, to avoid msg_id=0 + if (rd == 0){ + if(!fCheckedWrite(&rd, sizeof(DWORD), fb)) { + unlock_file(fb); + printhtmlerror(); + } + rd = wcftell(fb); + } + } + else { + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fb); + printhtmlerror(); + } + if(wcfseek(fb, rd, SEEK_SET) != 0) { + unlock_file(fm); + printhtmlerror(); + } + } + + // set index of body + mes->MIndex = rd; + if(!fCheckedWrite(*body, msize, fb)) { + unlock_file(fb); + printhtmlerror(); + } + + unlock_file(fb); + // ******* unlock fb ******* + + wcfclose(fb); + + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + // ****** lock fm ****** + lock_file(fm); + + // Allocate space for message header and save message index + CFreeDBFile fdb1(F_FREEINDEX, sizeof(SMessage)); // Wasted block = sizeof(SMessage) + if(fdb1.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fm); + printhtmlerrorat(LOG_UNABLETOCREATEFILE, F_FREEINDEX); + } + if((fp = fdb1.AllocFreeSpace(sizeof(SMessage))) == 0xFFFFFFFF) { + if(fdb1.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fm); + printhtmlerrorat(LOG_UNABLETOCREATEFILE, F_FREEINDEX); + } + + if(wcfseek(fm, 0, SEEK_END) != 0) { + unlock_file(fm); + printhtmlerror(); + } + fp = wcftell(fm); + // in case if file is empty, to avoid msg_id=0 + if (fp == 0){ + if(!fCheckedWrite(&fp, sizeof(DWORD), fm)) { + unlock_file(fm); + printhtmlerror(); + } + fp = wcftell(fm); + } + + } + else { + if(fdb1.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fb); + printhtmlerror(); + } + if(wcfseek(fm, fp, SEEK_SET) != 0) { + unlock_file(fm); + printhtmlerror(); + } + } + + // get msg index for new entry + ri = AddMsgIndex(fp); + // tune ViIndex in msg + mes->ViIndex = ri; + // write mes + if(!fCheckedWrite(mes, sizeof(SMessage), fm)) { + unlock_file(fm); + printhtmlerror(); + } + + unlock_file(fm); + // ****** unlock fm ****** + wcfclose(fm); + + if((fi = wcfopen(F_INDEX, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + // ****** lock fi ****** + lock_file(fi); + + // find index of root message + if(re) { + // temporary !!! should be added index support + if(wcfseek(fi, 0, SEEK_END) != 0) { + unlock_file(fi); + printhtmlerror(); + } + + fisize = fl = wcftell(fi); + buf = (SMessageTable *)malloc((sizeof(SMessageTable)*READ_MESSAGE_TABLE) + 1); + + while(fl > 0) { + DWORD toread; + if(fl >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + fl = fl - READ_MESSAGE_TABLE*sizeof(SMessageTable); + toread = READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + toread = fl; + fl = 0; + } + + if(wcfseek(fi, fl, SEEK_SET) != 0) { + unlock_file(fi); + printhtmlerror(); + } + + if(!fCheckedRead(buf, toread, fi)) { + unlock_file(fi); + printhtmlerror(); + } + + rd = i = (toread + 1) / sizeof(SMessageTable) - 1; + while(i>=0) { + if(M_IN(root, buf[i].begin, buf[i].end) || M_IN(root, buf[i].end, buf[i].begin)) { + goto LB_end; + } + i--; + } + } + // NO MESSAGE +#if _DEBUG_ == 1 + print2log("Incorrect message DB - message not found"); +#endif + unlock_file(fi); + wcfclose(fi); + printhtmlerror(); + // -------------------------------------------- + +LB_end: + tmp = malloc(fisize - fl + 10); + if(wcfseek(fi, fl + ((i+1)*sizeof(SMessageTable)), SEEK_SET) == -1) { + unlock_file(fi); + printhtmlerror(); + } + // read end part of WCFILE + DWORD readed; + readed = wcfread(tmp, 1, fisize - fl + 10, fi); + if(!wcfeof(fi)) { + unlock_file(fi); + printhtmlerror(); + } + if(wcfseek(fi, fl + (i*sizeof(SMessageTable)), SEEK_SET) == -1) { + unlock_file(fi); + printhtmlerror(); + } + if(buf[i].end < buf[i].begin) { + // write indexes up to message before root + fl = buf[i].begin; + if(buf[i].end < root) { + buf[i].begin = root - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + if(root + sizeof(SMessage) == fp) { + // can join two messages with backward style + buf[i].begin = root; + buf[i].end = fp + sizeof(SMessage) - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + else { + // write new message index + buf[i].begin = fp; + buf[i].end = fp + sizeof(SMessage) - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + // write last messages + buf[i].begin = fl; + buf[i].end = root; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + } + else { + if((buf[i].end + 1 == fp) && (root + sizeof(SMessage) == fp)) { + buf[i].end = fp + sizeof(SMessage) - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + else { + fl = buf[i].begin; + if(buf[i].end + 1 != root + sizeof(SMessage)) { + // write indexes up to root + buf[i].begin = root + sizeof(SMessage); + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + // write new message index + buf[i].begin = fp; + buf[i].end = fp + sizeof(SMessage) - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + // write last messages + buf[i].begin = fl; + buf[i].end = root + sizeof(SMessage) - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + } + // write end part of WCFILE + if(!fCheckedWrite(tmp, readed, fi)) { + unlock_file(fi); + printhtmlerror(); + } + free(tmp); + } + else { + + // Increment main thread count + IncrementMainThreadCount(); + + DWORD fpos; + if(wcfseek(fi, 0, SEEK_END) != 0) { + unlock_file(fi); + printhtmlerror(); + } + fpos = wcftell(fi); + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)); + + if(fpos > 0) { + // try to join message + fpos -= sizeof(SMessageTable); + if(wcfseek(fi, fpos, SEEK_SET) != 0) { + unlock_file(fi); + printhtmlerror(); + } + if(!fCheckedRead(buf, sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + if((buf->begin > buf->end) && (buf->begin + 1 == fp)) { + buf->begin += sizeof(SMessage); + } + else { + if(((buf->end - buf->begin + 1)/sizeof(SMessage) == 1) && (buf->end + 1 == fp)) { + buf->end = buf->begin; + buf->begin = fp - 1 + sizeof(SMessage); + } + else { + buf->begin = fp; + buf->end = fp + sizeof(SMessage) - 1; + fpos += sizeof(SMessageTable); + } + } + } + else { + // no join - just put it at the end of WCFILE + buf->begin = fp; + buf->end = fp + sizeof(SMessage) - 1; + //fpos += sizeof(SMessageTable); + } + + if(wcfseek(fi, fpos, SEEK_SET) != 0) printhtmlerror(); + + if(!fCheckedWrite(buf, sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + + // close all files and clean garbage database + unlock_file(fi); + // ****** unlock fi ****** + + wcfclose(fi); + free(buf); + return MSG_CHK_ERROR_PASSED; +} + +// delete messages with Level >= root.Level +// return 1 if successful, otherwise 0 +int DB_Base::DB_DeleteMessages(DWORD root) +{ + DWORD rr; + DWORD *msgsel; + DWORD count; + // select messages in root thread + if(!SelectMessageThreadtoBuf(root, &msgsel, &count)) return 0; + // delete selected messages + for(rr = 0; rr < count; rr++) { + DB_DeleteMessage(msgsel[rr]); + } + free(msgsel); + return 1; +} + +// return 1 if successfull, 0 otherwise +int DB_Base::DB_DeleteMessage(DWORD root) +{ + SMessage msg; + SMessageTable *buf; + DWORD fbsize, fbindex, oldroot; + DWORD fl, fisize, rd; + int i; + void *tmp; + oldroot = root; + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return 0; + + //******************************************* + // Transaction should be started here + //******************************************* + + // Delete message reference + if(DeleteMsgIndex(oldroot) == 0) return 0; + // Read message and save index of body and body size + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) printhtmlerror(); + if(wcfseek(fm, root, SEEK_SET) < 0) printhtmlerror(); + if(!fCheckedRead(&msg, sizeof(SMessage), fm)) printhtmlerror(); + wcfclose(fm); + fbsize = msg.msize; + fbindex = msg.MIndex; + // Decrement thread count if it's main thread message + if(msg.Level == 0) DecrementMainThreadCount(); + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)*READ_MESSAGE_TABLE + 1); + + // drop index in FI_INDEX + + if((fi = wcfopen(F_INDEX, FILE_ACCESS_MODES_RW)) == NULL) { + printhtmlerror(); + } + // ****** lock fi ****** + lock_file(fi); + + // find index of root message + // temporary !!! should be added index support + if(wcfseek(fi, 0, SEEK_END) != 0) { + unlock_file(fi); + printhtmlerror(); + } + fisize = fl = wcftell(fi); + while(fl > 0) { + DWORD toread; + if(fl >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + fl = fl - READ_MESSAGE_TABLE*sizeof(SMessageTable); + toread = READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + toread = fl; + fl = 0; + } + if(wcfseek(fi, fl, SEEK_SET) != 0) { + unlock_file(fi); + printhtmlerror(); + } + if(!fCheckedRead(buf, toread, fi)) { + unlock_file(fi); + printhtmlerror(); + } + rd = i = (toread + 1) / sizeof(SMessageTable) - 1; + while(i>=0) { + if(M_IN(root, buf[i].begin, buf[i].end) || M_IN(root, buf[i].end, buf[i].begin)) { + goto LB_MsgFound; + } + i--; + } + } + // not found message + unlock_file(fi); + printhtmlerror(); + +LB_MsgFound: + + tmp = malloc(fisize - fl + 10); + if(wcfseek(fi, fl + ((i+1)*sizeof(SMessageTable)), SEEK_SET) != 0) { + unlock_file(fi); + printhtmlerror(); + } + // read end part of WCFILE + DWORD readed; + readed = wcfread(tmp, 1, fisize - fl + 10, fi); + if(!wcfeof(fi)) { + unlock_file(fi); + printhtmlerror(); + } + if(wcfseek(fi, fl + (i*sizeof(SMessageTable)), SEEK_SET) != 0) { + unlock_file(fi); + printhtmlerror(); + } + + oldroot = 0; + if(buf[i].end < buf[i].begin) { + // write indexes up to message before root + fl = buf[i].begin; + if(buf[i].end < root) { + oldroot = 1; + buf[i].begin = root - 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + oldroot = 1; + unlock_file(fi); + printhtmlerror(); + } + } + // write last messages + buf[i].begin = fl; + buf[i].end = root + sizeof(SMessage); + if(buf[i].begin + 1 != buf[i].end) { + oldroot = 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + } + else { + fl = buf[i].begin; + if(buf[i].end + 1 != root + sizeof(SMessage)) { + oldroot = 1; + // write indexes up to root + buf[i].begin = root + sizeof(SMessage); + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + // write last messages + buf[i].begin = fl; + buf[i].end = root - 1; + if(buf[i].begin < buf[i].end) { + oldroot = 1; + if(!fCheckedWrite(&buf[i], sizeof(SMessageTable), fi)) { + unlock_file(fi); + printhtmlerror(); + } + } + } + + if(!fCheckedWrite(tmp, readed, fi)) { + unlock_file(fi); + printhtmlerror(); + } + + free(tmp); + + if(!oldroot) fisize-=sizeof(SMessageTable); + +#ifdef WIN32 + if(!oldroot) if(wctruncate(fi, fisize) != 0) { +#else + if(!oldroot) if(truncate(F_INDEX, fisize) != 0) { +#endif + unlock_file(fi); + printhtmlerror(); + } + + unlock_file(fi); + // ****** unlock fi ******* + wcfclose(fi); + + free(buf); + + // mark messages as free space + CFreeDBFile fdb(F_FREEINDEX, 0); // there is no wasted block ! + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) + printhtmlerror(); + if(fdb.MarkFreeSpace(root, sizeof(SMessage)) != FREEDBFILE_ERROR_ALLOK) + printhtmlerror(); + + // free fb space + CFreeDBFile fdb1(F_FREEMBODY, 0); + if(fdb1.errnum != FREEDBFILE_ERROR_ALLOK) + printhtmlerror(); + if(fdb1.MarkFreeSpace(fbindex, fbsize) != FREEDBFILE_ERROR_ALLOK) + printhtmlerror(); + + return 1; +} + +int DB_Base::DB_ChangeMessage(DWORD root, SMessage *nmsg, char **body, WORD msize, + DWORD CFlags, char **banreason) +{ + int i; + DWORD RFlags; + DWORD omsize; + WCFILE *fm; + + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return 0; + + // message header, banned address and spelling message check + switch (i = CheckSpellingBan(nmsg, body, banreason, CFlags, &RFlags)) { + case MSG_CHK_ERROR_PASSED: break; + default: return i; + } + + // tuning some columns of message stucture (first stage) + omsize = nmsg->msize; + + // save new message size + if(*body != NULL && **body != 0) nmsg->msize = (WORD)(strlen(*body) + 1); + else { + nmsg->msize = 0; + } + + /************ set flags of message ************/ + /* tune [pic] [url] message flags and other message flags */ + nmsg->Flag = nmsg->Flag | RFlags; + + // set "signed" flag +// if(msigned && (CFlags & MSG_CHK_DISABLE_SIGNATURE) == 0) +// nmsg->Flag |= MESSAGE_WAS_SIGNED; + + if(msize > 0) nmsg->Flag |= MESSAGE_HAVE_BODY; + else nmsg->Flag &= (~MESSAGE_HAVE_BODY); + + if((CFlags & MSG_CHK_ENABLE_EMAIL_ACKNL) && ULogin.LU.ID[0] != 0xFFFFFFFF) + nmsg->Flag |= MESSAGE_MAIL_NOTIFIATION; + + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + + // ********* lock FM ********* + lock_file(fm); + + if(wcfseek(fm, root, SEEK_SET) != 0) { + unlock_file(fm); + printhtmlerror(); + } + + // enought size for write new body ? + if(nmsg->msize > omsize) { + // No, it's a pity we need to reallocate free space + + // mark body of message as free space + CFreeDBFile fdb(F_FREEMBODY, 0); + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fm); + printhtmlerror(); + } + if(fdb.MarkFreeSpace(nmsg->MIndex, omsize) != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fm); + printhtmlerror(); + } + + // write new body + if((fb = wcfopen(F_MSGBODY, FILE_ACCESS_MODES_RW)) == NULL) { + unlock_file(fm); + printhtmlerror(); + } + // ********* lock fb ********* + lock_file(fb); + + // get free space and set WCFILE pointer + if((nmsg->MIndex = fdb.AllocFreeSpace(msize)) == 0xFFFFFFFF) { + // no free space - allocate it at the end of WCFILE + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fm); + unlock_file(fb); + printhtmlerror(); + } + + if(wcfseek(fb, 0, SEEK_END) != 0) { + unlock_file(fm); + unlock_file(fb); + printhtmlerror(); + } + nmsg->MIndex = wcftell(fb); + } + else { + // free space found + if(wcfseek(fb, nmsg->MIndex, SEEK_SET) != 0) { + unlock_file(fm); + unlock_file(fb); + printhtmlerror(); + } + } + + if(!fCheckedWrite(*body, nmsg->msize, fb)) { + unlock_file(fb); + unlock_file(fm); + printhtmlerror(); + } + unlock_file(fb); + // ******* unlock fb ******* + wcfclose(fb); + + } + else { + // if the body present write it + if(nmsg->msize) { + if((fb = wcfopen(F_MSGBODY, FILE_ACCESS_MODES_RW)) == NULL) { + unlock_file(fm); + printhtmlerror(); + } + // ********* lock fb ********* + lock_file(fb); + + if(wcfseek(fb, nmsg->MIndex, SEEK_SET) != 0) { + unlock_file(fb); + unlock_file(fm); + printhtmlerror(); + } + if(!fCheckedWrite(*body, nmsg->msize, fb)) { + unlock_file(fb); + unlock_file(fm); + printhtmlerror(); + } + unlock_file(fb); + // ******** unlock fb ******** + wcfclose(fb); + } + + // more or equal to sizeof(SMessageBody) will left free? + if(nmsg->msize < omsize) { + // mark it as free space + CFreeDBFile fdb(F_FREEMBODY, 0); + if(fdb.errnum != FREEDBFILE_ERROR_ALLOK) { + unlock_file(fm); + printhtmlerror(); + } + if(fdb.MarkFreeSpace(nmsg->MIndex + nmsg->msize, + omsize - nmsg->msize) != FREEDBFILE_ERROR_ALLOK) + { + unlock_file(fm); + printhtmlerror(); + } + } + } + + // write message header + if(!fCheckedWrite(nmsg, sizeof(SMessage), fm)) { + unlock_file(fm); + printhtmlerror(); + } + + unlock_file(fm); + // unlock FM semaphore + + wcfclose(fm); + + return 1; +} + +/* Print message with body + */ +int DB_Base::PrintHtmlMessageBody(SMessage *msg, char *body) +{ + char *an, *pb, *ps = NULL; + DWORD tmp; + DWORD flg; + CProfiles prof; +#if SHOW_HOST_NAME + int showhost = 1; +#else + int showhost = 0; +#endif + + if((currentdsm & 1) == 0) flg = MESSAGE_ENABLED_TAGS | MESSAGE_ENABLED_SMILES; + else flg = MESSAGE_ENABLED_TAGS; + + if(FilterBoardTags(msg->MessageHeader, &an, msg->SecHeader, + MAX_PARAMETERS_STRING, flg, &tmp) == 1) { + + } + else an = (char*)&(msg->MessageHeader); + + if(msg->msize > 0) { + DWORD flg = msg->Flag | MESSAGE_ENABLED_SMILES | BOARDTAGS_PURL_ENABLE; + if((currentdsm & 1) != 0) flg = flg & (~MESSAGE_ENABLED_SMILES); + + if(FilterBoardTags(body, &pb, msg->Security, MAX_PARAMETERS_STRING, flg | BOARDTAGS_EXPAND_ENTER, &tmp) == 0) + pb = body; + } + if(msg->Flag & MESSAGE_WAS_SIGNED) { + SProfile_UserInfo ui; + SProfile_FullUserInfo fui; + if(prof.GetUserByName(msg->AuthorName, &ui, &fui, NULL) == PROFILE_RETURN_ALLOK && + msg->UniqUserID == ui.UniqID) + { + if(strlen(fui.Signature) > 0) { + // first of all - let's filter HTML ! + char *st = FilterHTMLTags(fui.Signature, MAX_PARAMETERS_STRING); + if(st) { + if(FilterBoardTags(st, &ps, msg->Security, MAX_PARAMETERS_STRING, + flg | BOARDTAGS_EXPAND_ENTER, &tmp) == 0) + { + ps = (char*)malloc(strlen(st) + 1); + strcpy(ps, st); + } + free(st); + } + } + } + } + + printf(DESIGN_VIEW_THREAD_MSG_HEADER); + +#if TOPICS_SYSTEM_SUPPORT + // print topic info + SMessage parmes; + if(msg->ParentThread != 0 && msg->ParentThread != NO_MESSAGE_CODE) { + if(!ReadDBMessage(msg->ParentThread, &parmes)) { + // database error - invalid parent thread + printhtmlerror(); + } + } + else { + memcpy(&parmes, msg, sizeof(SMessage)); + } + + if( parmes.Topics >= 0 && parmes.Topics < TOPICS_COUNT) + printf(DESIGN_VIEW_THREAD_TOPIC, Topics_List[parmes.Topics]); + else printf(DESIGN_VIEW_THREAD_TOPIC, Topics_List[0]); + +#endif + + printf("%s", an); + +#ifdef USER_FAVOURITES_SUPPORT + { + + DWORD favtemp; +#if USER_FAVOURITES_SUPPORT == 2 + favtemp = parmes.ViIndex; +#else + favtemp = msg->ViIndex; +#endif + if (ULogin.LU.ID[0] != 0){ + DWORD result = prof.CheckandAddFavsList(ULogin.LU.SIndex, favtemp, 0); + switch(result) { + case PROFILE_RETURN_ALLOK: + printf("   " + DESIGN_FAVORITES_ADD_THREAD "", favtemp); + break; + case PROFILE_RETURN_ALREADY_EXIST: + printf("   " + DESIGN_FAVORITES_DEL_THREAD "", favtemp); + break; + case PROFILE_RETURN_UNKNOWN_ERROR: + //printf(DESIGN_VIEW_THREAD_MSG_FAVNO); + break; + } + } + } +#endif + +#if TOPICS_SYSTEM_SUPPORT + // if we are not in preview mode and have admin right - let's print topic change form + if( ((ULogin.LU.right & USERRIGHT_SUPERUSER) || // modification by admin + (ULogin.LU.ID[0] != 0 && msg->UniqUserID == ULogin.LU.UniqID && + (ULogin.LU.right & USERRIGHT_MODIFY_MESSAGE))) && // own message by user + (msg->ParentThread != NO_MESSAGE_CODE) + ) + { + // print change topic form + printf("\n

" + "  
\n"); + } +#endif + + /* potential BUG here */ + char *aname = (char*)malloc(1000); + Profile_UserName(msg->AuthorName, aname, msg->UniqUserID, 0); + + printf(DESIGN_VIEW_THREAD_MSG_SENT, MESSAGEMAIN_viewthread_sent, aname); + + free(aname); + + // print host name if requred + if(showhost || (ULogin.LU.right & USERRIGHT_SUPERUSER)) { + char tmp[10000], tmp2[100]; + unsigned char *aa = (unsigned char *)(&msg->IPAddr); + strcpy(tmp, msg->HostName); + // print IP in numeric format for administrator + if((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) { + strcat(tmp, MESSAGEMAIN_viewthread_ipview); + sprintf(tmp2, "%u.%u.%u.%u", aa[0] & 0xff, aa[1] & 0xff, aa[2] & 0xff, aa[3] & 0xff); + strcat(tmp, tmp2); + } + printf(DESIGN_VIEW_THREAD_MSG_SENT2, tmp); + } + + char *dt = ConvertFullTime((time_t)msg->Date); + printf(DESIGN_VIEW_THREAD_DATE, MESSAGEMAIN_viewthread_date, dt); + if(msg->MDate) { + dt = ConvertFullTime((time_t)msg->MDate); + printf(DESIGN_VIEW_THREAD_MDATE, MESSAGEMAIN_viewthread_mdate, dt); + } + + printf(DESIGN_VIEW_THREAD_MSG_SENT3); + + // Print body + if(msg->msize > 0) { + printf(DESIGN_VIEW_THREAD_BODY, pb); + } + else printf(DESIGN_VIEW_THREAD_BODY, ""); + + // Print signature + if(ps) { + if((currentdsm & 0x80) == 0) { + printf(DESIGN_VIEW_THREAD_SIGN, ps); + } + else { + printf(DESIGN_VIEW_THREAD_SIGN, MESSAGEMAIN_viewthread_sigdisabled); + } + free(ps); + } + + printf("


"); + if(an != (char*)&(msg->MessageHeader)) free(an); + if(msg->msize > 0 && pb != body) free(pb); + return 0; +} + +// return 1 if valid, 0 otherwise +int DB_Base::DB_PrintMessageBody(DWORD root) +{ + SMessage msg; + char *body; + DWORD readed; + + // Superuser access will not increment read count + bool NeedReadedIncrement = ((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) && + (CheckReadValidity(Nip, root)); + + // Get real index + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return 0; + + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + + + // --- lock F_MSGINDEX file --- + if(NeedReadedIncrement) lock_file(fm); + + if(wcfseek(fm, root, SEEK_SET) != 0) + { + if(NeedReadedIncrement) unlock_file(fm); + printhtmlerror(); + } + + if(!fCheckedRead(&msg, sizeof(SMessage), fm)) + { + if(NeedReadedIncrement) unlock_file(fm); + printhtmlerror(); + } + + if(NeedReadedIncrement) + { + msg.Readed++; + if(wcfseek(fm, root, SEEK_SET) != 0) + { + unlock_file(fm); + printhtmlerror(); + } + if(!fCheckedWrite(&msg, sizeof(SMessage), fm)) + { + unlock_file(fm); + printhtmlerror(); + } + unlock_file(fm); + wcfclose(fm); + } + // end of lock F_MSGINDEX file --- + + if((fb = wcfopen(F_MSGBODY, FILE_ACCESS_MODES_R)) == NULL) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_MSGBODY); + if(wcfseek(fb, msg.MIndex, SEEK_SET) == -1) printhtmlerror(); + body = (char*)malloc(msg.msize + 10); + if((readed = wcfread(body, 1, msg.msize + 2, fb)) < msg.msize) printhtmlerror(); + body[readed] = 0; + if(msg.msize != 0 && *body == 0) { + char *ss = body; + ss++; + while(*ss) { + *(ss-1) = *(ss); + ss++; + } + *(ss-1) = *ss; + } + wcfclose(fb); + + PrintHtmlMessageBody(&msg, body); + return 1; +} + +/* print messages thread begining from message root, if root is not first message in the thread, + * functions search for first message of the thread, and print thread from there + * return 1 if valid, 0 otherwise + */ +int DB_Base::DB_PrintMessageThread(DWORD root) +{ + SMessageTable *buf; + SMessage *msgs; + DWORD rr, fipos, toread; + DWORD fmpos, fl, oldroot; + DWORD fisize, rd; + int LastLevel = 0; + int i; + // translate virtual to real index, and check it + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return 0; // invalid or nonexisting index + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)*READ_MESSAGE_TABLE+1); + msgs = (SMessage *)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER+1); + + // find where is main thread message + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(wcfseek(fm, root, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msgs, sizeof(SMessage), fm)) printhtmlerror(); + + oldroot = msgs->ViIndex; + + if(msgs->Level != 0) + rr = msgs->ParentThread; + else + rr = root; + + wcfclose(fm); + + /* set root index = index of main thread message */ + root = rr; + + if((fi = wcfopen(F_INDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(wcfseek(fi, 0, SEEK_END) == -1) printhtmlerror(); + + /* temporary !!! should be added index support */ + // find index in index file + fisize = fl = wcftell(fi); + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)*READ_MESSAGE_TABLE + 1); + + while(fl > 0) { + DWORD toread; + if(fl >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + fl = fl - READ_MESSAGE_TABLE*sizeof(SMessageTable); + toread = READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + toread = fl; + fl = 0; + } + if(wcfseek(fi, fl, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(buf, toread, fi)) printhtmlerror(); + rd = i = (toread + 1) / sizeof(SMessageTable) - 1; + while(i>=0) { + if(M_IN(root, buf[i].begin, buf[i].end) || M_IN(root, buf[i].end, buf[i].begin)) { + goto PT_Found; + } + i--; + } + } + + // not found in indexes - fatal error + printhtmlerror(); + +PT_Found: + fl = fl + (i + 1)*sizeof(SMessageTable); + + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(wcfseek(fi, fl, SEEK_SET) == -1) printhtmlerror(); + + fipos = wcftell(fi); + + int czero = 0; + int bp = 0; + invflag = -1; + collapsed = 0; + + printf(MESSAGEMAIN_in_this_thread); + printf(DESIGN_open_dl); + + for(;;) { + if(fipos == 0) break; + else { + if(fipos >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + toread = READ_MESSAGE_TABLE*sizeof(SMessageTable); + fipos = fipos - READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + toread = fipos; + fipos = 0; + } + } + if(wcfseek(fi, fipos, SEEK_SET) == -1) printhtmlerror(); + if((rr = wcfread(buf, 1, toread, fi)) % sizeof(SMessageTable) != 0) printhtmlerror(); + + signed long i = rr / sizeof(SMessageTable) - 1; + + while(i >= 0) { + if(buf[i].begin < buf[i].end ) { + // forward direction + fmpos = buf[i].begin; + if(!czero) fmpos = root; + if(wcfseek(fm, fmpos, SEEK_SET) == -1) printhtmlerror(); + while(fmpos != (buf[i].end + 1)) { + DWORD toread; + if(buf[i].end - fmpos < READ_MESSAGE_HEADER*sizeof(SMessage)) { + toread = buf[i].end - fmpos + 1; + fmpos = fmpos + toread; + } + else { + toread = READ_MESSAGE_HEADER*sizeof(SMessage); + fmpos = fmpos + toread; + } + //if(strcmp(getenv(QUERY_STRING), "read=1695642") == 0) + // print4log("suxxxx: toread:%d, root:%d, fmpos:%d, beg:%d, end:%d", toread, root, fmpos, buf[i].begin, buf[i].end); + if(!fCheckedRead(msgs, toread, fm)) printhtmlerror(); + + LastLevel = printThreadbuffer(msgs, toread, PRINT_FORWARD, fmpos - toread, LastLevel, + &czero, oldroot, root, &bp); + if(czero == 2) goto PT_Finish; + } + } + else { + // backward direction + DWORD toread; + fmpos = buf[i].begin + 1; + while(fmpos != buf[i].end) { + if( fmpos - buf[i].end > READ_MESSAGE_HEADER*sizeof(SMessage)) { + fmpos = fmpos - READ_MESSAGE_HEADER*sizeof(SMessage); + toread = READ_MESSAGE_HEADER*sizeof(SMessage); + } + else { + toread = fmpos - buf[i].end; + fmpos = buf[i].end; + } + + if(wcfseek(fm, fmpos, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msgs, toread, fm)) printhtmlerror(); + + LastLevel = printThreadbuffer(msgs, toread, PRINT_BACKWARD, fmpos , LastLevel, + &czero, oldroot, root, &bp); + if(czero == 2) goto PT_Finish; + } + } + i--; + } + } + +PT_Finish: + for(i = -1; i < LastLevel; i++) printf(DESIGN_close_dl); + + free(buf); + free(msgs); + wcfclose(fi); + wcfclose(fm); + return 1; +} + +/* close posting messages to message thread begining from root + * code = 1 - CLOSE, code = 0 - OPEN + * return 1 if valid, 0 otherwise + */ +int DB_Base::DB_ChangeInvisibilityFlag(DWORD root, int invf) +{ + SMessage *msgs; + // translate virtual to real index + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return 0; + msgs = (SMessage *)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER+1); + + // read message + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) printhtmlerror(); + if(wcfseek(fm, root, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msgs, sizeof(SMessage), fm)) printhtmlerror(); + + // update flag + if(invf == 1) + msgs->Flag = msgs->Flag | MESSAGE_IS_INVISIBLE; + else { + if(msgs->Flag & MESSAGE_IS_INVISIBLE) + msgs->Flag = msgs->Flag - MESSAGE_IS_INVISIBLE; // should be XOR + } + + // write message + if(wcfseek(fm, root, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedWrite(msgs, sizeof(SMessage), fm)) printhtmlerror(); + wcfclose(fm); + free(msgs); + return 1; +} + +/* set collapsed flag on message root + * behaviour depend of code: + * if code == 0 - invert current value of flag + * if code == 1 - set collapsed flag + * if code == 0 - clean collapsed flag + * return value : 1 if flag set, or 2 if flag not set + */ +int DB_Base::DB_ChangeRollMessage(DWORD root, int code) +{ + SMessage *msgs; + + /* translate virtual to real index */ + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) + return 0; + + /* read message */ + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) { + wcfclose(fm); + return 0; + } + + if(wcfseek(fm, root, SEEK_SET) != 0) { + wcfclose(fm); + return 0; + } + + msgs = (SMessage *)malloc(sizeof(SMessage) + 1); + + if(!fCheckedRead(msgs, sizeof(SMessage), fm)) { + wcfclose(fm); + free(msgs); + return 0; + } + + /* update flag */ + DWORD flg = msgs->Flag; + if(code == 0) { + if(msgs->Flag & MESSAGE_COLLAPSED_THREAD) + msgs->Flag = msgs->Flag & (~MESSAGE_COLLAPSED_THREAD); + else + msgs->Flag = msgs->Flag | MESSAGE_COLLAPSED_THREAD; + } + else + if(code == 1) { + msgs->Flag = msgs->Flag | MESSAGE_COLLAPSED_THREAD; + } + else + if(code == 2) { + msgs->Flag = msgs->Flag & (~MESSAGE_COLLAPSED_THREAD); + } + else { + /* invalid code value */ + wcfclose(fm); + free(msgs); + return 0; + } + if(flg == msgs->Flag) { + wcfclose(fm); + free(msgs); + return (!(msgs->Flag & MESSAGE_COLLAPSED_THREAD)) + 1; + } + + // write message + if(wcfseek(fm, root, SEEK_SET) != 0) printhtmlerror(); + if(!fCheckedWrite(msgs, sizeof(SMessage), fm)) { + wcfclose(fm); + free(msgs); + return 0; + } + wcfclose(fm); + int res = (!(msgs->Flag & MESSAGE_COLLAPSED_THREAD)) + 1; + free(msgs); + + return res; +} + +/* set "invisible" flag for messages with Level > root.Level in (thread) + * code = 1 - CLOSE, code = 0 - OPEN + * return 1 if valid, 0 otherwise + */ +int DB_Base::DB_ChangeCloseThread(DWORD root, int code) +{ + DWORD rr; + DWORD *msgsel; + DWORD count; + + /* select messages in root thread */ + if(!SelectMessageThreadtoBuf(root, &msgsel, &count)) return 0; + + /* change "invisible" flag on selected messages */ + for(rr = 0; rr < count; rr++) { + DB_ChangeCloseMessage(msgsel[rr], code); + } + free(msgsel); + + return 1; +} + +/* change collapsed thread bit on thread tmp */ +int DB_Base::DB_ChangeRollThreadFlag(DWORD tmp) +{ + DWORD rr; + DWORD *msgsel; + DWORD count; + + /* select messages in root thread */ + if(!SelectMessageThreadtoBuf(tmp, &msgsel, &count)) return 0; + + /* change COLLAPSED_THREAD flag on selected messages */ + int code = 0; + for(rr = 0; rr < count; rr++) { + code = DB_ChangeRollMessage(msgsel[rr], code); + } + free(msgsel); + + return 1; +} + +int DB_Base::SelectMessageThreadtoBuf(DWORD root, DWORD **msgsel, DWORD *mescnt) +{ + SMessageTable *buf; + SMessage *msgs; + DWORD rr, fipos, toread; + DWORD fmpos, fl, EndLevel, viroot; + DWORD fisize, rd; + int i, j; + + // array for storing selecting messages + *mescnt = 0; + *msgsel = (DWORD*)malloc(1); + + // save virtual index + viroot = root; + + // translate virtual to real index, and check it + root = TranslateMsgIndex(root); + if(root == NO_MESSAGE_CODE) return 0; // invalid or nonexisting index + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)*READ_MESSAGE_TABLE+1); + msgs = (SMessage *)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER+1); + + // get EndLevel (current Level of root) + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(wcfseek(fm, root, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msgs, sizeof(SMessage), fm)) printhtmlerror(); + EndLevel = msgs->Level; + wcfclose(fm); + + if((fi = wcfopen(F_INDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(wcfseek(fi, 0, SEEK_END) == -1) printhtmlerror(); + + // temporary !!! should be added index support + // find index in index file + fisize = fl = wcftell(fi); + + buf = (SMessageTable *)malloc(sizeof(SMessageTable)*READ_MESSAGE_TABLE + 1); + + while(fl > 0) { + DWORD toread; + if(fl >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + fl = fl - READ_MESSAGE_TABLE*sizeof(SMessageTable); + toread = READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + toread = fl; + fl = 0; + } + if(wcfseek(fi, fl, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(buf, toread, fi)) printhtmlerror(); + rd = i = (toread + 1) / sizeof(SMessageTable) - 1; + while(i>=0) { + if(M_IN(root, buf[i].begin, buf[i].end) || M_IN(root, buf[i].end, buf[i].begin)) { + goto PT_Found; + } + i--; + } + } + + // not found in indexes - fatal error + return 0; + +PT_Found: + + fl = fl + (i + 1)*sizeof(SMessageTable); + + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(wcfseek(fi, fl, SEEK_SET) == -1) printhtmlerror(); + + fipos = wcftell(fi); + + //int czero = 0; + // flag, showing if we reach ViIndex of root msg + int reachviroot = 0; + + for(;;) { + if(fipos == 0) break; + else { + if(fipos >= READ_MESSAGE_TABLE*sizeof(SMessageTable)) { + toread = READ_MESSAGE_TABLE*sizeof(SMessageTable); + fipos = fipos - READ_MESSAGE_TABLE*sizeof(SMessageTable); + } + else { + toread = fipos; + fipos = 0; + } + } + if(wcfseek(fi, fipos, SEEK_SET) == -1) printhtmlerror(); + if((rr = wcfread(buf, 1, toread, fi)) % sizeof(SMessageTable) != 0) printhtmlerror(); + signed long i = rr / sizeof(SMessageTable) - 1; + while(i >= 0) { + + if(buf[i].begin < buf[i].end ) { + // forward direction + fmpos = buf[i].begin; + /*if(!czero) { + czero = 1; + fmpos = root; + }*/ + if(wcfseek(fm, fmpos, SEEK_SET) == -1) printhtmlerror(); + while(fmpos != (buf[i].end + 1)) { + DWORD toread; + if(buf[i].end - fmpos < READ_MESSAGE_HEADER*sizeof(SMessage)) { + toread = buf[i].end - fmpos + 1; + fmpos = fmpos + toread; + } + else { + toread = READ_MESSAGE_HEADER*sizeof(SMessage); + fmpos = fmpos + toread; + } + if(!fCheckedRead(msgs, toread, fm)) printhtmlerror(); + rr = (toread + 1)/ sizeof(SMessage); + + for(j = 0; j < rr; j++) { + if(viroot == msgs[j].ViIndex) { + reachviroot = 1; + } + if(msgs[j].Level <= EndLevel && viroot != msgs[j].ViIndex && reachviroot) { + goto PT_Finish; + } + if(reachviroot) { + (*mescnt)++; + (*msgsel) = (DWORD*)realloc((*msgsel), (*mescnt)*sizeof(DWORD)); + (*msgsel)[(*mescnt) - 1] = msgs[j].ViIndex; + } + } + } + } + else { + // backward direction + DWORD toread; + fmpos = buf[i].begin + 1; + /*if(!czero) { + czero = 1; + fmpos = root; + }*/ + while(fmpos != buf[i].end) { + if( fmpos - buf[i].end > READ_MESSAGE_HEADER*sizeof(SMessage)) { + fmpos = fmpos - READ_MESSAGE_HEADER*sizeof(SMessage); + toread = READ_MESSAGE_HEADER*sizeof(SMessage); + } + else { + toread = fmpos - buf[i].end; + fmpos = buf[i].end; + } + + if(wcfseek(fm, fmpos, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedRead(msgs, toread, fm)) printhtmlerror(); + rr = (toread + 1)/ sizeof(SMessage) - 1; + + for(j=rr; j >= 0; j--) { + if(viroot == msgs[j].ViIndex) { + reachviroot = 1; + } + if(msgs[j].Level <= EndLevel && viroot != msgs[j].ViIndex && reachviroot) { + goto PT_Finish; + } + if(reachviroot) { + (*mescnt)++; + (*msgsel) = (DWORD*)realloc((*msgsel), (*mescnt)*sizeof(DWORD)); + (*msgsel)[(*mescnt) - 1] = msgs[j].ViIndex; + } + } + } + } + i--; + } + } +PT_Finish: + wcfclose(fi); + wcfclose(fm); + free(buf); + free(msgs); + return 1; +} + +// change "closed" flag on root message +// return 1 if successfull, otherwise 0 +int DB_Base::DB_ChangeCloseMessage(DWORD root, int code) +{ + SMessage *msgs; + // translate virtual to real index + root = TranslateMsgIndex(root); + + msgs = (SMessage *)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER+1); + + // read message + if((fm = wcfopen(F_MSGINDEX, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + // ******* lock FM ******* + lock_file(fm); + + if(wcfseek(fm, root, SEEK_SET) == -1) { + unlock_file(fm); + printhtmlerror(); + } + if(!fCheckedRead(msgs, sizeof(SMessage), fm)) { + unlock_file(fm); + printhtmlerror(); + } + // update flag + if(!code) { + if(msgs->Flag & MESSAGE_IS_CLOSED) + msgs->Flag = msgs->Flag - MESSAGE_IS_CLOSED; + } + else msgs->Flag = msgs->Flag | MESSAGE_IS_CLOSED; + // write message + if(wcfseek(fm, root, SEEK_SET) == -1) printhtmlerror(); + if(!fCheckedWrite(msgs, sizeof(SMessage), fm)) { + unlock_file(fm); + printhtmlerror(); + } + + unlock_file(fm); + // ******* unlock FM ******* + + wcfclose(fm); + free(msgs); + return 1; +} + +// change "invisible" flag on all messages with Level > root.Level +// return 1 if successfull, otherwise 0 +int DB_Base::DB_ChangeInvisibilityThreadFlag(DWORD root, int invf) +{ + DWORD rr; + DWORD *msgsel; + DWORD count; + // select messages in root thread + if(!SelectMessageThreadtoBuf(root, &msgsel, &count)) return 0; + //change "invisible" flag on selected messages + for(rr = 0; rr < count; rr++) { + DB_ChangeInvisibilityFlag(msgsel[rr], invf); + } + free(msgsel); + + return 1; +} + +// return translated code, or NO_MESSAGE_CODE +DWORD DB_Base::TranslateMsgIndex(DWORD root) +{ + DWORD r; + if(root !=0) { + if((fv = wcfopen(F_VINDEX, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if(!(wcfseek(fv, root*sizeof(DWORD), SEEK_SET) != 0)) { + if(!fCheckedRead(&r, sizeof(DWORD), fv)) { + // reach end of file ? + r = NO_MESSAGE_CODE; + } + } + else r = NO_MESSAGE_CODE; + wcfclose(fv); + } + else r = NO_MESSAGE_CODE; + return r; +} + +/* add message with real index root to virtual indexes and return + virtual index of this message */ +DWORD DB_Base::AddMsgIndex(DWORD root) +{ + DWORD r; + // test if it's valid value + //if(root == NO_MESSAGE_CODE) printhtmlerror(); + + if((fv = wcfopen(F_VINDEX, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + // ******* lock FV ******* + lock_file(fv); + + if(wcfseek(fv, 0, SEEK_END) < 0) { + unlock_file(fv); + printhtmlerror(); + } + r = wcftell(fv); + // in case if file is empty, to avoid msg_id=0 + if (r == 0){ + if(!fCheckedWrite(&r, sizeof(DWORD), fv)) { + unlock_file(fv); + printhtmlerror(); + } + r = wcftell(fv); + } + + if(!fCheckedWrite(&root, sizeof(DWORD), fv)) { + unlock_file(fv); + printhtmlerror(); + } + r = (r+1)/sizeof(DWORD); + + unlock_file(fv); + // ******* unlock FV ******* + + wcfclose(fv); + return r; +} + +// delete virtual message index +// return 1 if successfull, 0 otherwise +int DB_Base::DeleteMsgIndex(DWORD root) +{ + + if((fv = wcfopen(F_VINDEX, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + // ******* lock FV ******* + lock_file(fv); + + if(wcfseek(fv, root*sizeof(DWORD), SEEK_SET) < 0) { + unlock_file(fv); + return 0; + } + root = NO_MESSAGE_CODE; + if(!fCheckedWrite(&root, sizeof(DWORD), fv)) { + unlock_file(fv); + return 0; + } + unlock_file(fv); + // ******* unlock FV ******* + + wcfclose(fv); + return 1; +} + +DWORD DB_Base::VIndexCountInDB() +{ + DWORD fsize; + fsize = Fsize(F_VINDEX); + if (fsize > 0) + return ( (DWORD)(((DWORD)fsize) - 3) )/sizeof(DWORD); + else + return 0; + +} + +DWORD DB_Base::MessageCountInDB() +{ + return ( ( (DWORD)(((DWORD)Fsize(F_MSGINDEX))) )/sizeof(SMessage) ); +} + +int DB_Base::ReadMainThreadCount(DWORD *root) +{ + FILE *f; + int ret = 0; + if((f = fopen(F_VINDEX, FILE_ACCESS_MODES_R)) == NULL) + return ret; + if(fread(root, 1, sizeof(DWORD), f) == sizeof(DWORD)) { + ret = 1; + } + fclose(f); + + return ret; +} + +int DB_Base::IncrementMainThreadCount() +{ + DWORD root; + if((fv = wcfopen(F_VINDEX, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + // ******* lock FV ******* + lock_file(fv); + + if(!fCheckedRead(&root, sizeof(DWORD), fv)) { + unlock_file(fv); + return 0; + } + if(wcfseek(fv, 0, SEEK_SET) < 0) { + unlock_file(fv); + return 0; + } + root++; + if(!fCheckedWrite(&root, sizeof(DWORD), fv)) { + unlock_file(fv); + return 0; + } + unlock_file(fv); + // ******* unlock FV ******* + + wcfclose(fv); + + return 1; +} + +int DB_Base::DecrementMainThreadCount() +{ + DWORD root; + if((fv = wcfopen(F_VINDEX, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + // ******* lock FV ******* + lock_file(fv); + + if(!fCheckedRead(&root, sizeof(DWORD), fv)) { + unlock_file(fv); + return 0; + } + if(wcfseek(fv, 0, SEEK_SET) < 0) { + unlock_file(fv); + return 0; + } + if(root) root--; + if(!fCheckedWrite(&root, sizeof(DWORD), fv)) { + unlock_file(fv); + return 0; + } + unlock_file(fv); + // ******* unlock FV ******* + + wcfclose(fv); + + return 1; +} + +#ifdef WIN32 + +DWORD Fsize(char *s) +{ + HANDLE hFile = CreateFile(s, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + DWORD sizeHigh, sizeLow; + if(hFile == INVALID_HANDLE_VALUE) + { + if(GetLastError() == ERROR_SHARING_VIOLATION) + { + WIN32_FIND_DATA wfd; + HANDLE hSearch = FindFirstFile(s, &wfd); + if(hSearch != INVALID_HANDLE_VALUE) + { + FindClose(hSearch); + sizeLow = wfd.nFileSizeLow; + sizeHigh = wfd.nFileSizeHigh; + goto ret_size; + } + } + else { + char ss[10000]; + sprintf(ss, LOG_GETFILESIZEFAILED, s); + printhtmlerrormes(ss); + } + } + sizeLow = GetFileSize(hFile, &sizeHigh); + CloseHandle(hFile); +ret_size: + if(sizeHigh) { + char ss[10000]; + sprintf(ss, LOG_FILESIZETOOHIGH, s); + printhtmlerrormes(ss); + } + return sizeLow; +} + +#else //WIN32 + +DWORD Fsize(char *s) +{ + WCFILE *f; + register DWORD r; + if((f = wcfopen(s, FILE_ACCESS_MODES_R)) == NULL) { + char ss[10000]; + sprintf(ss, LOG_GETFILESIZEFAILED, s); + printhtmlerrormes(ss); + } + if(wcfseek(f, 0, SEEK_END) != 0) { + char ss[10000]; + sprintf(ss, LOG_GETFILESIZEFAILED, s); + printhtmlerrormes(ss); + } + r = wcftell(f); + wcfclose(f); + return r; +} + +#endif //WIN32 blob - /dev/null blob + 7f4a64dbb7ad065b78eb36e977bc1ee24372889e (mode 644) --- /dev/null +++ src/dbase.h @@ -0,0 +1,152 @@ +/*************************************************************************** + dbase.h - message database engine include + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef DBASE_H_INCLUDED +#define DBASE_H_INCLUDED + +#include "basetypes.h" +#include "speller.h" +#include "logins.h" +#include "colornick.h" + +struct SMessageTable +{ + /* index ordering table */ + DWORD begin; + DWORD end; +}; + +#define PRINTMODE_NULL 0x0000 +#define PRINTMODE_ALL_ROLLED 0x0001 + +// IP address of user +extern char *Cip; +extern DWORD Nip; + + +/* cookie data */ +extern time_t RefreshDate; +extern int currentlsel; +extern int currenttc; +extern int currenttt; +extern int currenttv; +extern int currentss; +extern int currentdsm; +extern DWORD currenttopics; +extern int currentlann; +extern int topicsoverride; +extern int currentlm; // last message +extern int currentfm; // first message +extern int currentlt; // last threads +extern int currentft; // first threads +extern int currenttz; + +extern int cookie_lsel; +extern int cookie_tc; +extern int cookie_tt; +extern int cookie_tv; +extern int cookie_ss; +extern int cookie_dsm; +extern DWORD cookie_topics; +extern int cookie_tz; + +extern DWORD cookie_lastenter; +extern char *cookie_seq; +extern char *cookie_name; + +extern time_t current_minprntime; + +/* shows if header of CGI script was printed */ +extern int HPrinted; + +extern CUserLogin ULogin; + +#if USER_ALT_NICK_SPELLING_SUPPORT +extern CAltNamesParser AltNames; +#endif + +/* ------------------------ + * functions + * ------------------------ + */ +DWORD Fsize(char *s); +int ConvertTime(time_t tt, char *s); +char *ConvertFullTime(time_t tt); +int ReadDBMessage(DWORD midx, SMessage *mes); +int ReadDBMessageBody(char *buf, DWORD index, int size); +int WriteDBMessage(DWORD midx, SMessage *mes); +int IP2HostName(DWORD IP, char *hostname, int maxlen); + +class DB_Base +{ +protected: + WCFILE *fi, // random access index file + *fm, // message headers + *fb, // message bodies + *fv, // virtual index file + *ffm, // free spaces in message headers + *ffb; // free spaces in message bodies + + int alrprn; // count of already printed threads + int nt_counter; // count of printed new threads + int nm_counter; // count of printed new msgs + /* fpr printhtmlindex */ + int invflag; // "invisible thread was printed" flag + int collapsed; // "rolled thread was printed" flags + int newmessflag;// "new message" mark preparing for collapsed threads + SMessage pmes; // for message preprinting + SMessage lastmes; // for last posted message in collapsed thread + + int SelectMessageThreadtoBuf(DWORD root, DWORD **msgsel, DWORD *msgcnt); + + int printhtmlbuffer(SMessage *buf, DWORD size, int p, int *ll, int *pr, DWORD mode, DWORD &shouldprint, DWORD &skipped); + int printThreadbuffer(SMessage *buf, DWORD size, int p, DWORD fmpos, int ll, int *czero, DWORD selected, DWORD root, int *bp); + int printhtmlindexhron_bythreads(DWORD mode); + int printhtmlindexhron_wothreads(); + int DB_Base::printhtmlmessage_in_index(SMessage *mes, int style, DWORD skipped = 0xffffffff, int newmessmark = 0); + + int DB_ChangeInvisibilityFlag(DWORD root, int invf); + int DB_ChangeCloseMessage(DWORD root, int code); + int DB_DeleteMessage(DWORD root); + int DB_ChangeRollMessage(DWORD root, int code); + +public: + DB_Base(); + ~DB_Base(); + + DWORD TranslateMsgIndex(DWORD root); + DWORD AddMsgIndex(DWORD root); + int DeleteMsgIndex(DWORD root); + DWORD VIndexCountInDB(); + + DWORD MessageCountInDB(); + + int IncrementMainThreadCount(); + int DecrementMainThreadCount(); + int ReadMainThreadCount(DWORD *root); + + int PrintHtmlMessageBody(SMessage *mes, char *body); + int PrintHtmlMessageBufferByVI(DWORD *VI, DWORD cnt); + + int DB_InsertMessage(struct SMessage *mes, DWORD root, WORD msize, char** body, DWORD CFlags, char *passw, char **banreason); + int DB_ChangeMessage(DWORD root, SMessage *msg, char **body, WORD msize, DWORD CFlags, char **banreason); + + int PrintandCheckMessageFavsExistandInv(SProfile_UserInfo *ui, DWORD viewinv, int *updated); + + int DB_DeleteMessages(DWORD root); + int DB_ChangeInvisibilityThreadFlag(DWORD root, int invf); + int DB_ChangeRollThreadFlag(DWORD tmp); + int DB_ChangeCloseThread(DWORD root, int code); + int DB_PrintMessageThread(DWORD root); + int DB_PrintHtmlIndex(time_t time1, time_t time2, DWORD mtc); + int DB_PrintMessageBody(DWORD root); + void Profile_UserName(char *name, char *tostr, int reg, int doparsehtml = 1); +}; + +#endif + blob - /dev/null blob + 5221175e0f0f078012744624f9b8869090ca6fa0 (mode 644) --- /dev/null +++ src/error.cpp @@ -0,0 +1,156 @@ +/*************************************************************************** + error.cpp - log&error handler + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "stdarg.h" +#include "dbase.h" +#include "error.h" +#include "messages.h" + +/* print message to logfile + * s - format string + * %s string + * %d[f] DWORD (if 'f' as hex) + * %b[f] BYTE (if 'f' as hex) + */ +void print2log(char *s, ...) +{ + DWORD i = 0, c = 0; + FILE *f; + // + // POTENTIAL BUG HERE + // + char xx[100]; + char *ss = (char*)malloc(100*strlen(s)); + ss[0] = 0; + va_list marker; + +/* if((f = fopen(LOG_FILE, "a")) != NULL) { + fprintf(f, "entering:"); + fclose(f); + }*/ + + // Initialize variable arguments + va_start(marker, s); + DWORD slen = strlen(s); + while(i < slen) + { + if(s[i] == '%') { + if(i + 1 < slen) { + i++; + switch(s[i]) { + case 'd': + { + bool fhex = false; + if(i + 1 < slen && s[i+1] == 'f') + { + fhex = true; + i++; + } + DWORD x = va_arg(marker, DWORD); + if(!fhex) sprintf(xx,"%lu", x); + else { + sprintf(xx,"%lx", x); + strcat(ss, "0x"); + } + strcat(ss, xx); + break; + } + case 's': + { + char *x = va_arg(marker, char*); + if(x) strcat(ss, x); + else strcat(ss, "null"); + break; + } + case 'b': + { + bool fhex = false; + if(i + 1 < slen && s[i+1] == 'f') + { + fhex = true; + i++; + } + BYTE x = (BYTE)va_arg(marker, int); + if(!fhex) sprintf(xx,"%hu", x); + else { + sprintf(xx,"%hx", x); + strcat(ss, "0x"); + } + strcat(ss, xx); + break; + } + default: + { + char tmp[3]; + tmp[0] = s[i-1]; + tmp[1] = s[i]; + tmp[2] = 0; + strcat(ss, tmp); + } + } + c = strlen(ss); + } + else { + ss[c] = s[i]; + c++; + ss[c] = 0; + } + + } + else { + ss[c] = s[i]; + c++; + ss[c] = 0; + } + i++; + } + // Reset variable arguments + va_end(marker); + + time_t t; + char *p; + if((f = fopen(LOG_FILE, "a")) != NULL) { + t = time(NULL); + p = ctime(&t); + p[strlen(p) - 1] = 0; + fprintf(f, "%s : %s\n", p, ss); + fclose(f); + } + free(ss); +} + + +/* print error to file [file] at line [line] and message then immediately exit */ +int printwidehtmlerror(char *file, DWORD line, char *s) +{ +#if ENABLE_LOG + print2log(LOG_UNHANDLED, file, line, getenv(REMOTE_ADDR), + (s && (*s != 0)) ? s : LOG_ERRORTYPEUNKN, getenv(QUERY_STRING)); +#endif + // for correct showing in browser + if(!HPrinted) printf("Content-type: text/html\n\n" \ + TITLE_WWWConfBegining TITLE_divider "Error during page refresh"); + + printf("

An error occured

Try to refresh this page, and if" + " this occure again please contact server " + " administrator for support", ADMIN_MAIL); +#if ERROR_ON_SCREEN == 0 +#if ENABLE_LOG + printf("

This error have been logged to the" + " server log"); +#endif +#else + printf("

Technical details
" \ + "" LOG_UNHANDLED_HTML, file, line, getenv(REMOTE_ADDR), + (s && (*s != 0)) ? s : LOG_ERRORTYPEUNKN, getenv(QUERY_STRING)); +#endif + printf(""); + fflush(stdout); + exit(0); +} blob - /dev/null blob + 4cdc6fb05cb47fdd1f028c6152dd448afcd8feda (mode 644) --- /dev/null +++ src/error.h @@ -0,0 +1,22 @@ +/*************************************************************************** + error.h - log&error handler header + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef ERROR_H_INCLUDED +#define ERROR_H_INCLUDED + +#define printhtmlerror() printwidehtmlerror(__FILE__, __LINE__, "") +#define printhtmlerrormes(s) printwidehtmlerror(__FILE__, __LINE__, s) +#define printhtmlerrorat(p, s) { \ + char ss[10000]; \ + sprintf(ss, p, s); \ + printwidehtmlerror(__FILE__, __LINE__, ss); } + +void print2log(char *s, ...); +int printwidehtmlerror(char *file, DWORD line, char *s); + +#endif blob - /dev/null blob + bc6c5813ed7f281c9b5e3d9b5906bc7a7c60b0a9 (mode 644) --- /dev/null +++ src/freedb.cpp @@ -0,0 +1,181 @@ +/*************************************************************************** + freedb.cpp - free spaces database support + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "freedb.h" + +#define unlock_and_freedb_io_error1() {unlock_file(ffb);errnum = FREEDBFILE_ERROR_IO_ERROR;return FREEDBFILE_ERROR_IO_ERROR;} +#define freedb_io_error1() {errnum = FREEDBFILE_ERROR_IO_ERROR; return FREEDBFILE_ERROR_IO_ERROR;} +#define freedb_lock_file() {lock_file(ffb);} +#define freedb_unlock_file() {unlock_file(ffb)} + + +/* mark free space block with size bsize and index bIndex + * if successfull return FREEDB_ERROR_ALLOK + */ +DWORD CFreeDBFile::MarkFreeSpace(DWORD bIndex, DWORD bsize) +{ + SFreeDBEntry fs; + DWORD rr; + WCFILE *ffb; + + if(!init) { + errnum = FREEDBFILE_ERROR_NOT_INITIALIZED; + return errnum; + } + + // ignore wasted blocks + if(bsize < wasted_block) bsize = 0; + + if((ffb = wcfopen(fname, FILE_ACCESS_MODES_RW)) == NULL) { + if((ffb = wcfopen(fname, FILE_ACCESS_MODES_CW)) == NULL) { + freedb_io_error1() + } + else { + wcfclose(ffb); + if((ffb = wcfopen(fname, FILE_ACCESS_MODES_RW)) == NULL) { + freedb_io_error1() + } + } + } + /* seek at begining of WCFILE */ + if(wcfseek(ffb, 0, SEEK_SET) != 0) { + freedb_io_error1(); + } + + /********* lock WCFILE *********/ + freedb_lock_file(); + + int alreadyfind = 0; + while(!wcfeof(ffb)) { + if((rr = (DWORD)wcfread(&fs, 1, sizeof(SFreeDBEntry), ffb)) != sizeof(SFreeDBEntry)) { + if(rr == 0) break; + unlock_and_freedb_io_error1(); + } + if(fs.size == 0) { + alreadyfind = 1; + rr = wcftell(ffb) - sizeof(SFreeDBEntry); + if(wcfseek(ffb, rr, SEEK_SET) != 0) { + unlock_and_freedb_io_error1(); + } + fs.size = bsize; + fs.index = bIndex; + if(!fCheckedWrite(&fs, sizeof(SFreeDBEntry), ffb)) { + unlock_and_freedb_io_error1(); + } + break; + } + } + if(!alreadyfind) { + if(wcfseek(ffb, 0, SEEK_END) != 0) { + unlock_and_freedb_io_error1() + } + fs.size = bsize; + fs.index = bIndex; + if(!fCheckedWrite(&fs, sizeof(SFreeDBEntry), ffb)) { + unlock_and_freedb_io_error1() + } + } + freedb_unlock_file(); + /******* unlock ffb WCFILE *******/ + wcfclose(ffb); + errnum = FREEDBFILE_ERROR_ALLOK; + return FREEDBFILE_ERROR_ALLOK; +} + +/* allocate size bytes of free space, and return index of it + * otherwise return 0xFFFFFFFF and set errnum with error code + */ +DWORD CFreeDBFile::AllocFreeSpace(DWORD size) +{ + SFreeDBEntry fs; + DWORD rr; + WCFILE *ffb; + + if(!init) { + errnum = FREEDBFILE_ERROR_NOT_INITIALIZED; + return 0xFFFFFFFF; + } + + if((ffb = wcfopen(fname, FILE_ACCESS_MODES_RW)) == NULL) { + if((ffb = wcfopen(fname, FILE_ACCESS_MODES_CW)) == NULL) { + freedb_io_error1() + } + else { + wcfclose(ffb); + if((ffb = wcfopen(fname, FILE_ACCESS_MODES_RW)) == NULL) { + freedb_io_error1() + } + } + } + /* seek at begining of WCFILE */ + if(wcfseek(ffb, 0, SEEK_SET) != 0) { + freedb_io_error1(); + } + + /******** lock ffb *********/ + freedb_lock_file(); + + while(!wcfeof(ffb)) { + if((rr = (DWORD)wcfread(&fs, 1, sizeof(SFreeDBEntry), ffb)) != sizeof(SFreeDBEntry)) { + if(rr == 0) { + break; + } + unlock_and_freedb_io_error1(); + } + if(fs.size >= size) { + rr = wcftell(ffb) - sizeof(SFreeDBEntry); + if(wcfseek(ffb, rr, SEEK_SET) != 0) { + unlock_and_freedb_io_error1() + } + + fs.size = fs.size - size; + fs.index = fs.index + size; + + // make wasted space, if block too small + if(fs.size < wasted_block) fs.size = 0; + + if(!fCheckedWrite(&fs, sizeof(SFreeDBEntry), ffb)) { + unlock_and_freedb_io_error1() + } + + freedb_unlock_file(); + wcfclose(ffb); + // unlock FFB semaphore + return fs.index - size; + } + } + + freedb_unlock_file(); + /********* unlock ffb *********/ + + wcfclose(ffb); + + return 0xFFFFFFFF; +} + +CFreeDBFile::CFreeDBFile(char *ifname, DWORD wasted_b) +{ + init = 0; + if(ifname == NULL || strlen(ifname) < 1) { + errnum = FREEDBFILE_ERROR_INVALID_FILE; + return; + } + fname = (char*)malloc(strlen(ifname) + 1); + strcpy(fname, ifname); + wasted_block = wasted_b; + errnum = FREEDBFILE_ERROR_ALLOK; + init = 1; +} + +CFreeDBFile::~CFreeDBFile() +{ + if(init) { + free(fname); + } +} blob - /dev/null blob + 23b6a1da4ab63dd0d60ef44e247ff4e6ab94322d (mode 644) --- /dev/null +++ src/freedb.h @@ -0,0 +1,42 @@ +/*************************************************************************** + freedb.h - free spaces database support include + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef FREEDBFILE_H_INCLUDED +#define FREEDBFILE_H_INCLUDED + +#include "basetypes.h" + +#define FREEDBFILE_ERROR_ALLOK 0 +#define FREEDBFILE_ERROR_NOT_INITIALIZED 1 +#define FREEDBFILE_ERROR_IO_ERROR 2 +#define FREEDBFILE_ERROR_INVALID_FILE 3 + +#define FREEDBFILE_NO_FREE_SPACE 0xFFFFFFFF + +#define FREEDBFILE_READBUF_COUNT 20 + +/* free spaces index table entry */ +struct SFreeDBEntry { + DWORD size; + DWORD index; +}; + +class CFreeDBFile { +protected: + char *fname; + int init; + DWORD wasted_block; +public: + CFreeDBFile(char *ifname, DWORD wasted_block); + ~CFreeDBFile(); + DWORD errnum; + DWORD MarkFreeSpace(DWORD bIndex, DWORD bsize); + DWORD AllocFreeSpace(DWORD size); +}; + +#endif blob - /dev/null blob + 70ab2c6a87617860d924be22f2160005b51014a7 (mode 644) --- /dev/null +++ src/hashindex.cpp @@ -0,0 +1,500 @@ +/*************************************************************************** + hashindex.cpp - hashed indexes for strings + ------------------- + begin : Sun Nov 5 2002 + copyright : (C) 2001-2002 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "hashindex.h" + +#define hi_lock_file() {lock_file(f);} +#define hi_unlock_file() {unlock_file(f);} + +#define OFILE_NAME F_PROF_INDEX + +/* Index WCFILE format + * db 10, [name], 13, [Index=DWORD 4 bytes] + * ........................................ + */ + +static char* mstrstr(char *s, char *f, DWORD size) +{ + char *ss, *ff = f; + DWORD i = 0; + while(i <= size) { + ss = s; + ff = f; + while(*s == *ff && *ff != 0) { + s++; + i++; + ff++; + } + if(*ff == 0) { + return ss; + } + if(s - ss == 0) { + s++; + i++; + } + } + return NULL; +} + +DWORD hashstr(char *s, DWORD m) +{ + DWORD sum = 0; + for(; *s != 0; s++) { + sum = sum + (*s); + } + return (sum % m); +} + +int GetIndexOfString(char *s, DWORD *Index) +{ + WCFILE *f; + DWORD hash; + char buf[HASHINDEX_BLOCK_SIZE]; + char ps[MAX_HASHINDEX_STRLEN + 10]; + HASHINDEX_BLOCKINFO bi; + char *fs; + + if(strlen(s) < 3 || strlen(s) > MAX_HASHINDEX_STRLEN) + return HASHINDEX_ER_FORMAT; + + hash = HASHINDEX_BLOCK_SIZE * hashstr(s, HASHTAB_LEN); + + if((f = wcfopen(OFILE_NAME, FILE_ACCESS_MODES_RW)) == NULL) + return HASHINDEX_ER_IO_READ; + + for(;;) { + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + if(!fCheckedRead(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + ps[0] = 10; + strcpy(&ps[1], s); + ps[strlen(s) + 1] = 13; + ps[strlen(s) + 2] = 0; + memcpy(&bi, buf, sizeof(bi)); + + // + // Search for string in loaded block + // + if((fs = mstrstr(buf + sizeof(HASHINDEX_BLOCKINFO), ps, bi.Used)) != NULL) { + memcpy(Index, fs + strlen(s) + 2, 4); + break; + } + + if(bi.Next == HASHINDEX_NULL) { + wcfclose(f); + return HASHINDEX_ER_NOT_FOUND; + } + else hash = bi.Next; + } + + wcfclose(f); + + return HASHINDEX_ER_OK; +} + +int AddStringToHashedIndex(char *s, DWORD Index) +{ + WCFILE *f; + DWORD oldhash, hash, neededsize, i; + HASHINDEX_BLOCKINFO bi; + char buf[HASHINDEX_BLOCK_SIZE]; + char prepbuf[MAX_HASHINDEX_STRLEN + 10]; + + if(strlen(s) < 3 || strlen(s) > MAX_HASHINDEX_STRLEN) + return HASHINDEX_ER_FORMAT; + + hash = HASHINDEX_BLOCK_SIZE * hashstr(s, HASHTAB_LEN); + + if((f = wcfopen(OFILE_NAME, FILE_ACCESS_MODES_RW)) == NULL) { + // + // try to create new index WCFILE + // + if((f = wcfopen(OFILE_NAME, FILE_ACCESS_MODES_CW)) == NULL) + return HASHINDEX_ER_IO_CREATE; + + hi_lock_file(); + + memset(buf, 0, HASHINDEX_BLOCK_SIZE); + bi.Used = sizeof(HASHINDEX_BLOCKINFO); + bi.Next = HASHINDEX_NULL; + memcpy(buf, &bi, sizeof(bi)); + + for(i = 0; i < HASHTAB_LEN; i++) { + if(!fCheckedWrite(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_WRITE; + } + } + + hi_unlock_file(); + } + // + // Lock index WCFILE + // + hi_lock_file(); + + neededsize = strlen(s) + 4 /* for Index*/ + 2 /* for 10 and 13 signatures*/; + prepbuf[0] = 10; + strcpy(&prepbuf[1], s); + prepbuf[neededsize - 5] = 13; + prepbuf[neededsize - 4] = 0; + prepbuf[neededsize] = 0; + + oldhash = 0xffffffff; + for(;;) { + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + + if(!fCheckedRead(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + memcpy(&bi, buf, sizeof(bi)); + + // + // Search for string in loaded block + // + if(mstrstr(buf+sizeof(bi), prepbuf, bi.Used) != NULL) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_ALREADY_EXIST; + } + + if((oldhash == 0xffffffff) && (HASHINDEX_BLOCK_SIZE >= neededsize + bi.Used + 1)) { + // acceptable block - so save it for future use (write data, if not exist) + oldhash = hash; + } + + if(bi.Next != HASHINDEX_NULL) { + // + // Go ahead and check next chained block + // + hash = bi.Next; + } + else { + // + // It was the last block - add new index now + // + + // but in what block ;-)? so we should keep first acceptable block for write to + + memcpy(&prepbuf[neededsize - 4], &Index, 4); + + // + // check for space in current block + // + if(oldhash == 0xffffffff) { + DWORD newhash; + HASHINDEX_BLOCKINFO nbi; + // + // Need to create new hash block and link it to the chain + // + if(wcfseek(f, 0, SEEK_END) != 0) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + newhash = wcftell(f); + memset(buf, 0, HASHINDEX_BLOCK_SIZE); + nbi.Next = HASHINDEX_NULL; + nbi.Used = (WORD)(neededsize + sizeof(HASHINDEX_BLOCKINFO)); + memcpy(buf, &nbi, sizeof(nbi)); + memcpy(&buf[sizeof(HASHINDEX_BLOCKINFO)], prepbuf, neededsize); + if(!fCheckedWrite(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_WRITE; + } + bi.Next = newhash; + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + if(!fCheckedWrite(&bi, sizeof(bi), f)) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_WRITE; + } + } + else { + // + // Save to first suitable block + // + if(hash != oldhash) { + hash = oldhash; + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + + if(!fCheckedRead(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + memcpy(&bi, buf, sizeof(bi)); + } + + memcpy(&buf[bi.Used], prepbuf, neededsize + 1); // including term zero + bi.Used = (WORD)(bi.Used + neededsize); + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_READ; + } + memcpy(buf, &bi, sizeof(bi)); + if(!fCheckedWrite(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_IO_WRITE; + } + } + + break; + } + } + + hi_unlock_file(); + wcfclose(f); + + return HASHINDEX_ER_OK; +} + +int DeleteStringFromHashedIndex(char *s) +{ + WCFILE *f; + DWORD hash; + HASHINDEX_BLOCKINFO bi; + char buf[HASHINDEX_BLOCK_SIZE]; + char ps[MAX_HASHINDEX_STRLEN + 10]; + char *fs; + + if(strlen(s) < 3 || strlen(s) > MAX_HASHINDEX_STRLEN) + return HASHINDEX_ER_FORMAT; + + hash = HASHINDEX_BLOCK_SIZE * hashstr(s, HASHTAB_LEN); + + if((f = wcfopen(OFILE_NAME, FILE_ACCESS_MODES_RW)) == NULL) + return HASHINDEX_ER_IO_READ; + hi_lock_file(); + + for(;;) { + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + if(!fCheckedRead(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + ps[0] = 10; + strcpy(&ps[1], s); + ps[strlen(s) + 1] = 13; + ps[strlen(s) + 2] = 0; + memcpy(&bi, buf, sizeof(bi)); + + // + // Search for string in loaded block + // + if((fs = mstrstr(buf + sizeof(HASHINDEX_BLOCKINFO), ps, bi.Used)) != NULL) { + DWORD len = strlen(s) + 2 + 4; + // + // remove from block + // + for(; (fs - buf) < bi.Used; *fs = *(fs + len), fs++); + memset(&(buf[bi.Used - len-1]), 0, len+1); + + if(wcfseek(f, hash, SEEK_SET) != 0) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + bi.Used = (WORD)(bi.Used - len); + memcpy(buf, &bi, sizeof(bi)); + + if(!fCheckedWrite(buf, HASHINDEX_BLOCK_SIZE, f)) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + break; + } + + if(bi.Next == HASHINDEX_NULL) { + hi_unlock_file(); + wcfclose(f); + return HASHINDEX_ER_NOT_FOUND; + } + else hash = bi.Next; + } + + hi_unlock_file(); + wcfclose(f); + + return HASHINDEX_ER_OK; +} + +int GenerateHashwordList(char **names) +{ + WCFILE *f; + DWORD hash, pos, curalloced, bb = 0; + char buf[HASHINDEX_BLOCK_SIZE]; + HASHINDEX_BLOCKINFO bi; + char *fs, *ss; + +#define GHL_REALLOC_BLOCK_SIZE 20000 + *names = ss = (char*)malloc(GHL_REALLOC_BLOCK_SIZE); + *ss = 0; + curalloced = GHL_REALLOC_BLOCK_SIZE; + + if((f = wcfopen(OFILE_NAME, FILE_ACCESS_MODES_R)) == NULL) + return HASHINDEX_ER_IO_CREATE; + + for(hash = 0; hash < HASHTAB_LEN; hash++) { + pos = hash*HASHINDEX_BLOCK_SIZE; + for(;;) { + if(wcfseek(f, pos, SEEK_SET) != 0) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + if(!fCheckedRead(buf, HASHINDEX_BLOCK_SIZE, f)) { + free(*names); + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + memcpy(&bi, buf, sizeof(bi)); + + // + // parse block + // + fs = buf + sizeof(bi); + while(*fs != 0) { + char *d; + fs++; + d = fs; + while(*d != 13) d++; + *d = 0; + + // save result + strcat(ss, fs); + ss += strlen(fs) + 1; + + // increment used memory + bb += strlen(fs) + 1; + + *(ss - 1) = 13; + *ss = 0; + if(bb >= curalloced - 40) { + curalloced += GHL_REALLOC_BLOCK_SIZE; + *names = (char*)realloc(*names, curalloced); + } + d += 5; + fs = d; + } + + if(bi.Next != HASHINDEX_NULL) + pos = bi.Next; + else break; + } + } + + wcfclose(f); + + return HASHINDEX_ER_OK; +} + +static int compare(const void *p1, const void *p2) +{ + return int(*((DWORD*)p1) - *((DWORD*)p2)); +} + +int GenerateIndexList(DWORD **index) +{ + WCFILE *f; + DWORD hash, pos, curalloced, si = 0 /* saving index */; + char buf[HASHINDEX_BLOCK_SIZE]; + HASHINDEX_BLOCKINFO bi; + char *fs; + +#define GIL_REALLOC_BLOCK_SIZE 2000*sizeof(DWORD) + *index = (DWORD*)malloc(GIL_REALLOC_BLOCK_SIZE); + curalloced = GIL_REALLOC_BLOCK_SIZE; + + if((f = wcfopen(OFILE_NAME, FILE_ACCESS_MODES_R)) == NULL) + return HASHINDEX_ER_IO_CREATE; + + for(hash = 0; hash < HASHTAB_LEN; hash++) { + pos = hash*HASHINDEX_BLOCK_SIZE; + for(;;) { + if(wcfseek(f, pos, SEEK_SET) != 0) { + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + if(!fCheckedRead(buf, HASHINDEX_BLOCK_SIZE, f)) { + free(*index); + hi_unlock_file(); + return HASHINDEX_ER_IO_READ; + } + + memcpy(&bi, buf, sizeof(bi)); + + // + // parse block + // + fs = buf + sizeof(bi); + while(*fs != 0) { + char *d; + fs++; + d = fs; + while(*d != 13 && *d != 0) d++; + + if(*d == 0) break; + + d++; + (*index)[si] = *((DWORD*)d); + si++; + + if(si*sizeof(DWORD) >= curalloced - 40) { + curalloced += GHL_REALLOC_BLOCK_SIZE; + *index = (DWORD*)realloc(*index, curalloced); + } + d += 4; + fs = d; + } + + if(bi.Next != HASHINDEX_NULL) + pos = bi.Next; + else break; + } + } + + wcfclose(f); + + qsort(((void*)(*index)), si, sizeof(DWORD), compare); + (*index)[si] = 0xffffffff; // end of array + + return HASHINDEX_ER_OK; +} blob - /dev/null blob + c36877d09d93c498fd155210f7b4b5864b451057 (mode 644) --- /dev/null +++ src/hashindex.h @@ -0,0 +1,45 @@ +/*************************************************************************** + hashindex.cpp - hashed indexes for string include + ------------------- + begin : Sun Nov 5 2002 + copyright : (C) 2001-2002 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef _HASHINDEX_H_INCLUDED_ +#define _HASHINDEX_H_INCLUDED_ + +#include "basetypes.h" + +#define HASHINDEX_ER_OK 0 +#define HASHINDEX_ER_ALREADY_EXIST 1 +#define HASHINDEX_ER_NOT_FOUND 2 +#define HASHINDEX_ER_IO_CREATE 3 +#define HASHINDEX_ER_IO_READ 4 +#define HASHINDEX_ER_IO_WRITE 5 +#define HASHINDEX_ER_FORMAT 6 + +#define HASHTAB_LEN 256 +#define HASHINDEX_BLOCK_SIZE 2000 +#define HASHINDEX_NULL 0xFFFFFFFF + +#define MAX_HASHINDEX_STRLEN 30 + +typedef struct _HASHINDEX_BLOCKINFO { + WORD Used; + DWORD Next; +} HASHINDEX_BLOCKINFO, *PHASHINDEX_BLOCKINFO; + +DWORD hashstr(char *s, DWORD m); + +int AddStringToHashedIndex(char *s, DWORD Index); + +int GetIndexOfString(char *s, DWORD *Index); + +int DeleteStringFromHashedIndex(char *s); + +int GenerateHashwordList(char **names); + +int GenerateIndexList(DWORD **index); + +#endif blob - /dev/null blob + baada3917ffece10802333a4fa9dc55a604059a1 (mode 644) --- /dev/null +++ src/indexer.cpp @@ -0,0 +1,905 @@ +/*************************************************************************** + indexer.cpp - indexing support + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "indexer.h" +#include "searcher.h" + +#define INDEXER_RUNTIME_CHECK 0 + +#define unlock_and_indexer_io_error0() {unlock_file(ifh);errnum = INDEXFILE_ERROR_IO_ERROR;return;} +#define unlock_and_indexer_io_error1() {unlock_file(ifh);errnum = INDEXFILE_ERROR_IO_ERROR;return INDEXFILE_ERROR_IO_ERROR;} +#define indexer_io_error0() {errnum = INDEXFILE_ERROR_IO_ERROR; return;} +#define indexer_io_error1() {errnum = INDEXFILE_ERROR_IO_ERROR; return INDEXFILE_ERROR_IO_ERROR;} +#define indexer_lock_file() {lock_file(ifh);} +#define indexer_unlock_file() {unlock_file(ifh);} + +/* Indexer class constructor: open or create + * chartable must be NULL if CREATE_NEW not set + */ +CIndexFile::CIndexFile(char *ifname, DWORD flags, WORD chartablelen, char *chartable, DWORD maxi) +{ + init = 0; + DWORD i; + + iblock = (SSymbolIndex *)malloc(sizeof(SSymbolIndex)*chartablelen); + + if((flags & INDEXFILE_CREATE_BOTH) != 0) + { + /* open existing index file */ + if((ifh = wcfopen(ifname, FILE_ACCESS_MODES_RW)) != NULL) + { + char *sign = (char*)malloc(strlen(INDEXFILE_FILE_SIGNATURE) + 1); + if(wcfread(sign, 1, strlen(INDEXFILE_FILE_SIGNATURE), ifh) != + strlen(INDEXFILE_FILE_SIGNATURE)) + { + free(sign); + flags = INDEXFILE_CREATE_NEW; + } + if(strncmp(sign, INDEXFILE_FILE_SIGNATURE, strlen(INDEXFILE_FILE_SIGNATURE)) != 0) + { + errnum = INDEXFILE_ERROR_INVALID_FILE; + free(sign); + flags = INDEXFILE_CREATE_NEW; + } + free(sign); + flags = INDEXFILE_CREATE_EXISTING; + } + else + { + flags = INDEXFILE_CREATE_NEW; + } + } + + if((flags & INDEXFILE_CREATE_NEW) != 0) + { + /* create new index file */ + if((ifh = wcfopen(ifname, FILE_ACCESS_MODES_CW)) != NULL) + { + indexer_lock_file(); + /* wrtie signature */ + if(wcfwrite(INDEXFILE_FILE_SIGNATURE, 1, strlen(INDEXFILE_FILE_SIGNATURE), ifh) != + strlen(INDEXFILE_FILE_SIGNATURE)) + { + free(iblock); + unlock_and_indexer_io_error0(); + } + /* write max indexing length (maxi) */ + if(wcfwrite(&maxi, 1, sizeof(maxi), ifh) != sizeof(maxi)) + { + free(iblock); + unlock_and_indexer_io_error0(); + } + /* write symbol count and table */ + if(wcfwrite(&chartablelen, 1, sizeof(chartablelen), ifh) != sizeof(chartablelen)) + { + free(iblock); + unlock_and_indexer_io_error0(); + } + if(wcfwrite(chartable, 1, chartablelen, ifh) != chartablelen) + { + free(iblock); + unlock_and_indexer_io_error0(); + } + + memset(iblock, 0xFF, chartablelen*sizeof(SSymbolIndex)); + if(wcfwrite(iblock, 1, chartablelen*sizeof(SSymbolIndex), ifh) != chartablelen*sizeof(SSymbolIndex)) + { + free(iblock); + unlock_and_indexer_io_error0(); + } + + indexer_unlock_file(); + wcfclose(ifh); + } + else indexer_io_error0(); + flags = INDEXFILE_CREATE_EXISTING; + } + + if((flags & INDEXFILE_CREATE_EXISTING) != 0) + { + /* open existing index file */ + if((ifh = wcfopen(ifname, FILE_ACCESS_MODES_RW)) != NULL) + { + char *sign = (char*)malloc(strlen(INDEXFILE_FILE_SIGNATURE) + 1); + if(wcfread(sign, 1, strlen(INDEXFILE_FILE_SIGNATURE), ifh) != + strlen(INDEXFILE_FILE_SIGNATURE)) + { + free(sign); + free(iblock); + indexer_io_error0(); + } + if(strncmp(sign, INDEXFILE_FILE_SIGNATURE, strlen(INDEXFILE_FILE_SIGNATURE)) != 0) + { + errnum = INDEXFILE_ERROR_INVALID_FILE; + free(sign); + free(iblock); + return; + } + free(sign); + + /* read maximum index length */ + if(wcfread(&maxindex, 1, sizeof(maxindex), ifh) != sizeof(maxindex)) + { + free(iblock); + indexer_io_error0(); + } + /* read symbolic count */ + if(wcfread(&symcount, 1, sizeof(symcount), ifh) != sizeof(symcount)) + { + free(iblock); + indexer_io_error0(); + } + // realloc iblock for new symcount + iblock = (SSymbolIndex *)realloc(iblock, sizeof(SSymbolIndex)*symcount); + + char *chartbl = (char*)malloc(symcount + 10); + if(wcfread(chartbl, 1, symcount, ifh) != symcount) + { + free(chartbl); + indexer_io_error0(); + } + /* prepare index of the begining */ + begin_pos = wcftell(ifh); + + if(wcfread(iblock, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) + { + free(iblock); + free(chartbl); + indexer_io_error0() + } + // prepare symtable indexes + for(i = 0; i < INDEXFILE_MAX_CHARTABLE; i++) symtable[i] = INDEXFILE_MAX_CHARTABLE; + for(i = 0; i < symcount; i++) + symtable[(unsigned char)chartbl[i]] = (unsigned char)i; + free(chartbl); + // Activate cache + CacheROOT = AllocCacheBlock(symcount); + memcpy(CacheROOT->II, iblock, sizeof(SSymbolIndex)*symcount); + } + else { + free(iblock); + indexer_io_error0(); + } + + init = 1; + errnum = INDEXFILE_ERROR_ALLOK; + // save file name + CIndexFile::ifname = (char*)malloc(strlen(ifname) + 1); + strcpy(CIndexFile::ifname, ifname); + // make empty block + iblockFF = (SSymbolIndex*)malloc(sizeof(SSymbolIndex)*symcount); + memset(iblockFF, 0xFF, sizeof(SSymbolIndex)*symcount); + return; + } +} + +CIndexFile::~CIndexFile() +{ + if(init) + { + DWORD lev = 0; + DWORD j[FIRST_LEVELS_CACHE_SIZE]; + int recursion = 0; + DWORD begfrom = 0; + SCacheElIndex *tcb[FIRST_LEVELS_CACHE_SIZE]; + tcb[0] = CacheROOT; + if(wcfseek(ifh, begin_pos, SEEK_SET) != 0) + { + indexer_io_error0(); + } + if(wcfwrite(tcb[lev]->II, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) + { + indexer_io_error0() + } + + for(;;) + { + + for(j[lev] = begfrom; j[lev] < symcount; j[lev]++) + { + if((DWORD)tcb[lev]->IM[j[lev]] != INDEXFILE_NO_INDEX) + { + if(wcfseek(ifh, tcb[lev]->II[j[lev]].Index, SEEK_SET) != 0) + { + indexer_io_error0(); + } + if(wcfwrite(tcb[lev]->IM[j[lev]]->II, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) + { + indexer_io_error0() + } + lev++; + tcb[lev] = tcb[lev-1]->IM[j[lev-1]]; + recursion = 1; + break; + } + } + if(!recursion) + { + FreeCacheBlock(tcb[lev]); + if(lev) lev--; + else break; // go out at all + j[lev]++; + begfrom = j[lev]; + } + else + { + begfrom = 0; + recursion = 0; + } + } + + free(ifname); + free(iblock); + free(iblockFF); + wcfclose(ifh); + } +} + + +/* Allocate cache block for defined symcount + * if successfull returns pointer to SCacheElIndex, otherwise returns NULL + */ +SCacheElIndex* CIndexFile::AllocCacheBlock(DWORD symcount) +{ + SCacheElIndex *p; + p = (SCacheElIndex*)malloc(sizeof(SCacheElIndex)); + if(!p) return p; + p->II = new SSymbolIndex[symcount]; + if(!p->II) + { + free(p); + return NULL; + } + memset(p->II, 0xFF, sizeof(SSymbolIndex)*symcount); + p->IM = (SCacheElIndex**)malloc(sizeof(SCacheElIndex*)*symcount); + if(!p->IM) + { + free(p->II); + free(p); + return NULL; + } + memset(p->IM, 0xFF, sizeof(SCacheElIndex*)*symcount); + return p; +} + + +/* Free cache block + */ +int CIndexFile::FreeCacheBlock(SCacheElIndex *cb) +{ + free(cb->II); + free(cb->IM); + free(cb); + return 1; +} + + +/* Test if word [iword] is compartible with current index file + * return 1 if compartible, otherwise 0 + */ +DWORD CIndexFile::TestIndexWord(char *iword) +{ + for(DWORD i = 0; i < strlen(iword); i++) + { + if(((unsigned char)iword[i]) > INDEXFILE_MAX_CHARTABLE || symtable[(unsigned char)iword[i]] == INDEXFILE_MAX_CHARTABLE) + { + return 0; + } + } + return 1; +} + +/* put new index entry for word iword to indexes, + * if index already exist it return INDEXFILE_ERROR_INDEX_ALREADY_EXIST + */ +//DWORD CIndexFile::PutIndexByWord(char *iword, DWORD LocIndex) +//{ +// DWORD indlength, curpos, cpos, i; +// SCacheElIndex *bcache; +// SSymbolIndex *iblk; +// +//#if INDEXER_RUNTIME_CHECK +// if(ifh == NULL) +// { +// errnum = INDEXFILE_ERROR_INVALID_FILE; +// return errnum; +// } +// if(TestIndexWord(iword) == 0) +// { +// errnum = INDEXFILE_ERROR_INVALID_WORD; +// return errnum; +// } +//#endif +// +// DWORD strlen_iword = (DWORD)strlen(iword); +// +// if(strlen_iword != 0 && strlen_iword <= INDEXFILE_MAX_INDEXING_WORD_LENGTH) +// { +// curpos = begin_pos; +// indexer_lock_file(); +// +// // prepare cache +// bcache = CacheROOT; +// +// if(strlen_iword > maxindex) indlength = maxindex; +// else indlength = strlen_iword; +// +// for(i = 0; i < indlength; i++) +// { +// if(i < FIRST_LEVELS_CACHE_SIZE) +// { +// if(i != 0) +// { +// bcache = bcache->IM[cpos]; +// } +// iblk = bcache->II; +// } +// else +// { +// iblk = iblock; +// if(wcfseek(ifh, curpos, SEEK_SET) != 0) +// { +// unlock_and_indexer_io_error1(); +// } +// if(wcfread(iblk, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) +// { +// unlock_and_indexer_io_error1(); +// } +// } +// +// cpos = symtable[(unsigned char)iword[i]]; +// +// if(iblk[cpos].Index == INDEXFILE_NO_INDEX && i != indlength - 1) +// { +// // create new block - we should write it to disk PERMANENTLY ! +// +// if(wcfseek(ifh, 0, SEEK_END) != 0) +// { +// unlock_and_indexer_io_error1(); +// } +// DWORD fpos = wcftell(ifh); +// if(wcfwrite(iblockFF, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) +// { +// unlock_and_indexer_io_error1(); +// } +// +// // now we decide what we should do: write new index to cache or to disk +// // and where we will allocate new block - in cache or on drive +// if(i < FIRST_LEVELS_CACHE_SIZE) +// { +// if(i < FIRST_LEVELS_CACHE_SIZE - 1) +// { +// // write to cache and allocate new in cache +// bcache->IM[cpos] = AllocCacheBlock(symcount); +// // write new index to cache +// bcache->II[cpos].Index = fpos; +// } +// else +// { +// // write to cache but allocate new on disk +// bcache->II[cpos].Index = fpos; +// } +// curpos = bcache->II[cpos].Index; +// } +// else +// { +// // write to disk and allocate new on disk +// iblk[cpos].Index = fpos; +// if(wcfseek(ifh, curpos, SEEK_SET) != 0) +// { +// unlock_and_indexer_io_error1(); +// } +// if(wcfwrite(iblk, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) +// { +// unlock_and_indexer_io_error1(); +// } +// curpos = iblk[cpos].Index; +// } +// } +// else +// { +// if(i != indlength - 1) +// { +// curpos = iblk[cpos].Index; +// if(i < FIRST_LEVELS_CACHE_SIZE - 1 && (DWORD)bcache->IM[cpos] == INDEXFILE_NO_INDEX) +// { +// // load to cache, if we need it +// +// // allocate block +// bcache->IM[cpos] = AllocCacheBlock(symcount); +// +// // and read index from disk +// if(wcfseek(ifh, iblk[cpos].Index, SEEK_SET) != 0) +// { +// unlock_and_indexer_io_error1(); +// } +// if(wcfread(bcache->IM[cpos]->II, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) +// { +// unlock_and_indexer_io_error1(); +// } +// } +// } +// }//of else +// } +// +// if(iblk[cpos].Location != INDEXFILE_NO_INDEX) +// { +// indexer_unlock_file(); +// errnum = INDEXFILE_ERROR_INDEX_ALREADY_EXIST; +// return errnum; +// } +// else { +// // save index +// iblk[cpos].Location = LocIndex; +// if(indlength > FIRST_LEVELS_CACHE_SIZE) +// { +// // write to drive +// if(wcfseek(ifh, curpos, SEEK_SET) != 0) +// { +// unlock_and_indexer_io_error1(); +// } +// DWORD rr = (DWORD)wcfwrite(iblk, 1, symcount*sizeof(SSymbolIndex), ifh); +// indexer_unlock_file(); +// if(rr != symcount*sizeof(SSymbolIndex)) +// { +// indexer_io_error1(); +// } +// } +// } +// } +// else +// { +// errnum = INDEXFILE_ERROR_INVALID_WORD; +// return errnum; +// } +// errnum = INDEXFILE_ERROR_ALLOK; +// return errnum; +//} + + +/* put new index entry for word iword to indexes, + * if index is not the same for subwords functions aborts and return + * INDEXFILE_ERROR_EXIST_DIFF_INDEX + * BEFORE CALLING THIS FUNCTION : Should be set AddingMId at CMessageSearcher because of + * this function using calls to CMessageSearcher::AddMessageToRefBlock() and AllocRefBlock() + *********************************************************************** + * THERE IS SOME ADMISSION : IF there is an index for word with lenght n + * => we should have also index for all words between MinLenght and default + * word length. If say other it means that if you are using this functions you can't + * in addition to use PutIndexByWord, because of database corruption will take place. + */ +DWORD CIndexFile::PutOrGetIndexByWordAssoc(char *iword, BYTE MinLength, void *vpms)// DWORD NewBlockMark, DWORD NewBlockDelta) +{ + CMessageSearcher *pMS = (CMessageSearcher*)vpms; + DWORD indlength, curpos, cpos, NewLocation; + DWORD i; + SCacheElIndex *bcache; + SSymbolIndex *iblk; + +#if INDEXER_RUNTIME_CHECK + if(ifh == NULL) + { + errnum = INDEXFILE_ERROR_INVALID_FILE; + return errnum; + } + if(TestIndexWord(iword) == 0) + { + errnum = INDEXFILE_ERROR_INVALID_WORD; + return errnum; + } +#endif + + DWORD strlen_iword = (DWORD)strlen(iword); + + if(strlen_iword != 0 && strlen_iword <= INDEXFILE_MAX_INDEXING_WORD_LENGTH) + { + curpos = begin_pos; + indexer_lock_file(); + + // prepare cache + bcache = CacheROOT; + + if(strlen_iword > maxindex) indlength = maxindex; + else indlength = strlen_iword; + + for(i = 0; i < indlength; i++) + { + if(i < FIRST_LEVELS_CACHE_SIZE) + { + if(i != 0) + { + bcache = bcache->IM[cpos]; + } + iblk = bcache->II; + } + else + { + iblk = iblock; + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfread(iblk, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) + { + unlock_and_indexer_io_error1(); + } + } + + cpos = symtable[(unsigned char)iword[i]]; + + // add new id to block, update location if new block is created + if(i >= MinLength) + { + NewLocation = pMS->AddMessageToRefBlock(iblk[cpos].Location); + if(NewLocation != iblk[cpos].Location && i >= FIRST_LEVELS_CACHE_SIZE) { + iblk[cpos].Location = NewLocation; + // update with new index only in case we are missing cache =) + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfwrite(iblk, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) + { + unlock_and_indexer_io_error1(); + } + } + else iblk[cpos].Location = NewLocation; + } + + // go else + if(iblk[cpos].Index == INDEXFILE_NO_INDEX && i != indlength - 1) + { + // create new block - we should write it to disk PERMANENTLY ! + + if(wcfseek(ifh, 0, SEEK_END) != 0) + { + unlock_and_indexer_io_error1(); + } + DWORD fpos = wcftell(ifh); + if(wcfwrite(iblockFF, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) + { + unlock_and_indexer_io_error1(); + } + + // now we decide what we should do: write new index to cache or to disk + // and where we will allocate new block - in cache or on drive + if(i < FIRST_LEVELS_CACHE_SIZE) + { + // write new index to cache + bcache->II[cpos].Index = fpos; + if(i < FIRST_LEVELS_CACHE_SIZE - 1) + { + // write to cache and allocate new in cache + bcache->IM[cpos] = AllocCacheBlock(symcount); + } + curpos = bcache->II[cpos].Index; + } + else + { + // write to disk and allocate new on disk + iblk[cpos].Index = fpos; + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfwrite(iblk, 1, symcount*sizeof(SSymbolIndex), ifh) != symcount*sizeof(SSymbolIndex)) + { + unlock_and_indexer_io_error1(); + } + curpos = iblk[cpos].Index; + } + } + else + { + if(i != indlength - 1) + { + curpos = iblk[cpos].Index; + if(i < FIRST_LEVELS_CACHE_SIZE - 1 && (DWORD)bcache->IM[cpos] == INDEXFILE_NO_INDEX) + { + // load to cache, if we need it + + // allocate block + bcache->IM[cpos] = AllocCacheBlock(symcount); + + // and read index from disk + if(wcfseek(ifh, iblk[cpos].Index, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfread(bcache->IM[cpos]->II, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) + { + unlock_and_indexer_io_error1(); + } + } + } + }//of else + } + // condition + // iblk[cpos].Location != INDEXFILE_NO_INDEX + // will be true always + + if(indlength > FIRST_LEVELS_CACHE_SIZE) + { + // save index + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + DWORD rr = (DWORD)wcfwrite(iblk, 1, symcount*sizeof(SSymbolIndex), ifh); + if(rr != symcount*sizeof(SSymbolIndex)) + { + unlock_and_indexer_io_error1(); + } + } + indexer_unlock_file(); + errnum = INDEXFILE_ERROR_ALLOK; + return errnum; + } + else + { + errnum = INDEXFILE_ERROR_INVALID_WORD; + return errnum; + } +} + + +/* get index entry for word [iword] + * return values: if index exist return INDEXFILE_ALLOK and if LocIndex not NULL + * store here returning index, and also if it is uniq index and exact not NULL + * set exact set it = 1, otherwise = 0, + * if index not exist return INDEXFILE_INDEX_NOT_EXIST + */ +DWORD CIndexFile::GetIndexByWord(char *iword, DWORD *LocIndex, int *exact) +{ + DWORD curpos, i, cpos; + DWORD indlength; + SCacheElIndex *bcache; + SSymbolIndex *iblk; + +#if INDEXER_RUNTIME_CHECK + if(ifh == NULL || iblock == NULL) + { + errnum = INDEXFILE_ERROR_INVALID_FILE; + return errnum; + } + if(TestIndexWord(iword) == 0) + { + errnum = INDEXFILE_ERROR_INVALID_WORD; + return errnum; + } +#endif + + DWORD strlen_iword = (DWORD)strlen(iword); // just for optimizing + + if(strlen_iword > 1) + { + curpos = begin_pos; + + // prepare cache + bcache = CacheROOT; + + if(strlen_iword > maxindex) indlength = maxindex; + else indlength = strlen_iword; + + for(i = 0; i < indlength; i++) + { + + if(i < FIRST_LEVELS_CACHE_SIZE) + { + if(i != 0) + { + if((DWORD)bcache->IM[cpos] == INDEXFILE_NO_INDEX) + { + // load to cache + + // allocate block + bcache->IM[cpos] = AllocCacheBlock(symcount); + + // and read index from disk + if(wcfseek(ifh, iblk[cpos].Index, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfread(bcache->IM[cpos]->II, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) + { + unlock_and_indexer_io_error1(); + } + + } + // get it from cache + bcache = bcache->IM[cpos]; + } + iblk = bcache->II; + } + else + { + iblk = iblock; + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfread(iblk, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) + { + unlock_and_indexer_io_error1(); + } + } + + cpos = symtable[(unsigned char)iword[i]]; + + if(i != indlength - 1) + { + if(iblk[cpos].Index == INDEXFILE_NO_INDEX) + { + errnum = INDEXFILE_ERROR_INDEX_NOT_EXIST; + return errnum; + } + else + { + curpos = iblk[cpos].Index; + } + } + } + + if(LocIndex != NULL) *LocIndex = iblk[cpos].Location; + if(exact != NULL) + { + if(strlen_iword <= maxindex) *exact = 1; + else *exact = 0; + } + errnum = INDEXFILE_ERROR_ALLOK; + return errnum; + } + else + { + errnum = INDEXFILE_ERROR_INVALID_WORD; + return errnum; + } +} + + +/* NEW VERSION DOESN'T TESTED AT ALL !!! */ + +/* modify index associated with word [iword] to NewLocIndex if oldLocIndex equal + * modifying index otherwise return error code (INDEXFILE_ERROR_INDEX_NOT_EXIST + * returned in that case if oldLocIndex != index of modifying word) + * (if it need to delete index - NewLocIndex should be set to INDEXFILE_NO_INDEX) + */ +DWORD CIndexFile::ModifyIndexByWord(char *iword, DWORD oldLocIndex, DWORD NewLocIndex) +{ + DWORD curpos, i, cpos; + DWORD indlength; + SCacheElIndex *bcache; + SSymbolIndex *iblk; + +#if INDEXER_RUNTIME_CHECK + if(ifh == NULL) + { + errnum = INDEXFILE_ERROR_INVALID_FILE; + return errnum; + } + if(TestIndexWord(iword) == 0) + { + errnum = INDEXFILE_ERROR_INVALID_WORD; + return errnum; + } +#endif + + DWORD strlen_iword = (DWORD)strlen(iword); // just for optimizing + + if(strlen_iword > 1) + { + curpos = begin_pos; + + // prepare cache + bcache = CacheROOT; + + if(strlen_iword > maxindex) indlength = maxindex; + else indlength = strlen_iword; + + for(i = 0; i < indlength; i++) + { + if(i < FIRST_LEVELS_CACHE_SIZE) + { + if(i != 0) + { + if((DWORD)bcache->IM[cpos] == INDEXFILE_NO_INDEX) + { + // load to cache + + // allocate block + bcache->IM[cpos] = AllocCacheBlock(symcount); + + // and read index from disk + if(wcfseek(ifh, iblk[cpos].Index, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfread(bcache->IM[cpos]->II, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) + { + unlock_and_indexer_io_error1(); + } + + } + // get it from cache + bcache = bcache->IM[cpos]; + } + iblk = bcache->II; + } + else + { + iblk = iblock; + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + if(wcfread(iblk, 1, sizeof(SSymbolIndex)*symcount, ifh) != sizeof(SSymbolIndex)*symcount) + { + unlock_and_indexer_io_error1(); + } + } + + cpos = symtable[(unsigned char)iword[i]]; + + if(iblk[cpos].Index == INDEXFILE_NO_INDEX) + { + errnum = INDEXFILE_ERROR_INDEX_NOT_EXIST; + return errnum; + } + else + { + if(i != indlength - 1) + { + curpos = iblk[cpos].Index; + } + } + } + + if(iblk[cpos].Location == INDEXFILE_NO_INDEX) + { + errnum = INDEXFILE_ERROR_INDEX_NOT_EXIST; + return errnum; + } + else + { + if(oldLocIndex != iblk[cpos].Location) + { + errnum = INDEXFILE_ERROR_INDEX_NOT_EXIST; + return errnum; + } + else + { + iblk[cpos].Location = NewLocIndex; + if(indlength > FIRST_LEVELS_CACHE_SIZE) + { + // save index + indexer_lock_file(); + if(wcfseek(ifh, curpos, SEEK_SET) != 0) + { + unlock_and_indexer_io_error1(); + } + DWORD rr = (DWORD)wcfwrite(iblk, 1, symcount*sizeof(SSymbolIndex), ifh); + indexer_unlock_file(); + + if(rr != symcount*sizeof(SSymbolIndex)) + { + indexer_io_error1(); + } + } + + errnum = INDEXFILE_ERROR_ALLOK; + return errnum; + } + } + } + else + { + errnum = INDEXFILE_ERROR_INVALID_WORD; + return errnum; + } +} blob - /dev/null blob + d7e3730f9f37a78de27988ad647ab8b6d94e2f03 (mode 644) --- /dev/null +++ src/indexer.h @@ -0,0 +1,78 @@ +/*************************************************************************** + indexer.h - indexing support include + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef INDEXER_H_INCLUDED +#define INDEXER_H_INCLUDED + +#include "basetypes.h" + +// Perfomance releative params +// Higher is better, but will take more memory +#define FIRST_LEVELS_CACHE_SIZE 5 + +// Common unmodif. params +#define INDEXFILE_MAX_CHARTABLE 256 +#define INDEXFILE_FILE_SIGNATURE "wc-idx" +#define INDEXFILE_MAX_INDEXING_WORD_LENGTH 255 + +/* indexer error codes */ +#define INDEXFILE_ERROR_ALLOK 0 +#define INDEXFILE_ERROR_NOT_INITIALIZED 1 +#define INDEXFILE_ERROR_IO_ERROR 2 +#define INDEXFILE_ERROR_INVALID_FILE 3 +#define INDEXFILE_ERROR_INVALID_WORD 4 +#define INDEXFILE_ERROR_INDEX_ALREADY_EXIST 5 +#define INDEXFILE_ERROR_INDEX_NOT_EXIST 6 +#define INDEXFILE_ERROR_EXIST_DIFF_INDEX 7 + +#define INDEXFILE_CREATE_NEW 0x0001 +#define INDEXFILE_CREATE_EXISTING 0x0002 +#define INDEXFILE_CREATE_BOTH 0x0004 + +#define INDEXFILE_NO_INDEX 0xFFFFFFFF + +/* Index element structure */ +struct SSymbolIndex { + DWORD Index; + DWORD Location; +}; + +/* Cache elements structure */ +struct SCacheElIndex; + +struct SCacheElIndex { + SSymbolIndex *II; // File info + SCacheElIndex **IM; // Memory references +}; + +class CIndexFile { +protected: + WCFILE *ifh; + WORD symcount; + WORD symtable[INDEXFILE_MAX_CHARTABLE]; + DWORD begin_pos, maxindex; + SSymbolIndex *iblock, *iblockFF; + char *ifname; + int init; + + SCacheElIndex *CacheROOT; // ROOT element of cache block structure + SCacheElIndex* AllocCacheBlock(DWORD symcount); + int FreeCacheBlock(SCacheElIndex *cb); +public: + CIndexFile(char *ifname, DWORD flags, WORD chartablelen, char *chartable, DWORD maxi); + ~CIndexFile(); + DWORD errnum; + + DWORD TestIndexWord(char *iword); +// DWORD PutIndexByWord(char *iword, DWORD LocIndex); + DWORD PutOrGetIndexByWordAssoc(char *iword, BYTE MinLength, void *vpms); + DWORD GetIndexByWord(char *iword, DWORD *LocIndex, int *exact); + DWORD ModifyIndexByWord(char *iword, DWORD oldLocIndex, DWORD NewLocIndex); +}; + +#endif blob - /dev/null blob + bd10691123d34b103b07ff7946b90474305fa5ce (mode 644) --- /dev/null +++ src/logins.cpp @@ -0,0 +1,595 @@ +/*************************************************************************** + login.cpp - log in/out support + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "security.h" +#include "logins.h" +#include "error.h" + +#define unlock_and_logins_io_error() {unlock_file(f); wcfclose(f); return 0;} +#define logins_lock_file() {lock_file(f);} +#define logins_unlock_file() {unlock_file(f);} + +/* create authorization sequence with ttl - Time To Live for user *ui + * and store it to ui.ID + * return 1 if successfull, otherwise zero returned + */ +DWORD OpenAuthSequence(int ttl, SSavedAuthSeq *ui) +{ + SSavedAuthSeq *buf; + WCFILE *f; + int el; + DWORD id, id1, rr, i, ii; + + /* set creation time */ + time_t tn = time(NULL); + + if((f = wcfopen(F_AUTHSEQ, FILE_ACCESS_MODES_RW)) == NULL) { + // if file doesn't exist - create it + if((f = wcfopen(F_AUTHSEQ, FILE_ACCESS_MODES_CW)) == NULL) { + return 0; + } + else { + wcfclose(f); + if((f = wcfopen(F_AUTHSEQ, FILE_ACCESS_MODES_RW)) == NULL) { + return 0; + } + } + } + buf = (SSavedAuthSeq*)malloc(sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT); + + /******** lock f ********/ + logins_lock_file(); + + ii = 0; + while(!wcfeof(f)) { + if((rr = wcfread(((char*)buf + ii*sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT), 1, sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT, f)) != + sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT) { + if((rr%sizeof(SSavedAuthSeq)) != 0) { + free(buf); + unlock_and_logins_io_error(); + } + } + ii++; + buf = (SSavedAuthSeq*)realloc(buf, (ii+1)*sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT); + } + + // Generate random sequence for user session + // if generated sequence exist regenerate it again +L_Try: +// print2log("->>> %d", ((ii-1)*SEQUENCE_READ_COUNT + (rr+1)/sizeof(SAuthUserSeq))); + id = rand32(); + id1 = rand32(); + el = -1; + for(i = 0; i < ((ii-1)*SEQUENCE_READ_COUNT + (rr+1)/sizeof(SSavedAuthSeq)); i++) { + if(buf[i].ID[0] == id && buf[i].ID[1] == id1) + goto L_Try; + if(buf[i].ExpireDate < tn) { + if(el < 0) el = i; + } + } + + free(buf); + + // Sequence was successfully generated, save it + ui->ID[0] = id; + ui->ID[1] = id1; + ui->ExpireDate = time(NULL) + ttl; + + if(el < 0) { + if(wcfseek(f, 0, SEEK_END) < 0) + unlock_and_logins_io_error(); + } + else { + if(wcfseek(f, el*sizeof(SSavedAuthSeq), SEEK_SET) < 0) + unlock_and_logins_io_error(); + } + + if(!fCheckedWrite(ui, sizeof(SSavedAuthSeq), f)) + unlock_and_logins_io_error(); + + logins_unlock_file(); + /********* unlock f *********/ + + wcfclose(f); + return 1; +} + +/* close authorization sequence by Session id (=id) or userId (=Uid) + * return 1 if successfull otherwise 0 returned + */ +int CloseAuthSequence(DWORD id[2], DWORD Uid) +{ + SSavedAuthSeq *buf = NULL; + WCFILE *f; + DWORD rr, i, ii = 0; + time_t tn = time(NULL); + + if(( (id[0] != 0 || id[1] != 0) && Uid != 0) || (id[0] == 0 && id[1] == 0 && Uid == 0)) + return 0; // incorrect params + + if((f = wcfopen(F_AUTHSEQ, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + + buf = (SSavedAuthSeq*)malloc(sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT); + + //******** lock f ******** + logins_lock_file(); + + while(!wcfeof(f)) { + if((rr = wcfread(((char*)buf + ii*sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT), 1, sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT, f)) != + sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT) + { + if((rr%sizeof(SSavedAuthSeq)) != 0) { + free(buf); + unlock_and_logins_io_error(); + } + } + ii++; + buf = (SSavedAuthSeq*)realloc(buf, (ii+1)*sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT); + } + + int changed = 0; + for(i = 0; i < ((ii-1)*SEQUENCE_READ_COUNT + (rr+1)/sizeof(SSavedAuthSeq)); i++) + { + if( buf[i].ExpireDate > tn && ((buf[i].ID[0] == id[0] && buf[i].ID[1] == id[1] && Uid == 0) || + (buf[i].UniqID == Uid && id[0] == 0 && id[1] == 0)) ) + { + if(wcfseek(f, i*sizeof(SSavedAuthSeq), SEEK_SET) < 0) { + free(buf); + unlock_and_logins_io_error(); + } + + // set time as sequence expired == free sequence + buf[i].ExpireDate = time(NULL) - 1; + + if(wcfwrite(&buf[i], 1, sizeof(SSavedAuthSeq), f) != sizeof(SSavedAuthSeq)) { + free(buf); + unlock_and_logins_io_error(); + } + changed = 1; + if(id != 0) break; + } + } + + free(buf); + + //******** unlock f ******** + logins_unlock_file(); + + wcfclose(f); + return changed; +} + + + +/* list authorization sequences by userId (=Uid) +* return 1 if successfull otherwise 0 returned +*/ +int GenerateListAuthSequence(char ***buflist, DWORD *sc, DWORD Uid) +{ + *buflist = NULL; + *sc = 0; + SSavedAuthSeq *buf; + WCFILE *f; + DWORD rr, i, cn=0, fpos; + + if((f = wcfopen(F_AUTHSEQ, FILE_ACCESS_MODES_R)) == NULL) return 0; + + buf = (SSavedAuthSeq*)malloc(SEQUENCE_READ_COUNT*sizeof(SSavedAuthSeq)); + if(!(*buflist = (char**)malloc(sizeof(char**)))) return 0; + + /******** lock f ********/ + logins_lock_file(); + + do { + fpos = wcftell(f); + rr = wcfread(buf, 1, sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT, f); + + if((rr%sizeof(SSavedAuthSeq)) != 0) { + /* read error */ + free(buf); + for(i = 0; i < cn; i++) free((*buflist)[i]); + free(buflist); + *buflist = NULL; + unlock_and_logins_io_error(); + } + + rr = rr/sizeof(SSavedAuthSeq); + for(i = 0; i < rr; i++) { + if( Uid==0 || (buf[i].UniqID & (~SEQUENCE_IP_CHECK_DISABLED)) == Uid ){ + *buflist = (char**)realloc(*buflist, (cn+1)*sizeof(char**)); + (*buflist)[cn] = (char*)malloc(5*sizeof(DWORD) + 1); + memcpy(((char*)((*buflist)[cn])), &buf[i].ExpireDate, sizeof(DWORD)); + memcpy(((char*)((*buflist)[cn]))+4, &buf[i].IP, sizeof(DWORD)); + memcpy(((char*)((*buflist)[cn]))+8, &buf[i].ID[0], sizeof(DWORD)); + memcpy(((char*)((*buflist)[cn]))+12, &buf[i].ID[1], sizeof(DWORD)); + memcpy(((char*)((*buflist)[cn]))+16, &buf[i].UniqID, sizeof(DWORD)); + cn++; + } + } + } while(rr == SEQUENCE_READ_COUNT); + + free(buf); + + logins_unlock_file(); + /********* unlock f *********/ + + wcfclose(f); + *sc = cn; + return 1; +} + + + +/* check and update sequence 'id' with ttl - Time To Live + * return 1 if successfull otherwise -1 if not found and 0 if i/o error + */ +int CheckAndUpdateAuthSequence(DWORD id[2], DWORD IP, int ttl, SSavedAuthSeq *ui) +{ + SSavedAuthSeq *buf; + WCFILE *f; + DWORD rr, i, cn, fpos; + + if((f = wcfopen(F_AUTHSEQ, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + buf = (SSavedAuthSeq*)malloc(sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT); + + /******** lock f ********/ + logins_lock_file(); + + + while(!wcfeof(f)) { + fpos = wcftell(f); + rr = wcfread(buf, 1, sizeof(SSavedAuthSeq)*SEQUENCE_READ_COUNT, f); + + if((rr%sizeof(SSavedAuthSeq)) != 0) { + /* read error */ + free(buf); + unlock_and_logins_io_error(); + } + cn = rr/sizeof(SSavedAuthSeq); + + time_t tn = time(NULL); + + for(i = 0; i < cn; i++) { + if( buf[i].ExpireDate > tn && buf[i].ID[0] == id[0] && buf[i].ID[1] == id[1] && + ( (buf[i].UniqID & SEQUENCE_IP_CHECK_DISABLED) != 0 || buf[i].IP == IP || ttl == 0 ) ) + { + memcpy((void*)ui, &buf[i], sizeof(SSavedAuthSeq)); + + if(ttl){ + + if(wcfseek(f, fpos + i*sizeof(SSavedAuthSeq), SEEK_SET) != 0) { + free(buf); + unlock_and_logins_io_error(); + } + + buf[i].ExpireDate = time(NULL) + ttl; + if(!fCheckedWrite(&buf[i], sizeof(SSavedAuthSeq), f)) { + free(buf); + unlock_and_logins_io_error(); + } + } + + free(buf); + + logins_unlock_file(); + /********* unlock f *********/ + + wcfclose(f); + return 1; + } + } + } + + logins_unlock_file(); + /********* unlock f *********/ + + return -1; +} + +/********************** CUserLogin **********************/ +CUserLogin::CUserLogin() +{ + uprof = NULL; + pui = NULL; + pfui = NULL; + LU.SIndex = 0xFFFFFFFF; + LU.right = DEFAULT_NOBODY_RIGHT; + LU.sec = DEFAULT_NOBODY_SECURITY_BYTE; + LU.sechdr = DEFAULT_NOBODY_HDR_SEC_BYTE; + LU.UniqID = 0; + LU.ID[0] = 0; + LU.ID[1] = 0; +} + +CUserLogin::~CUserLogin() +{ + if(uprof != NULL) delete uprof; + if(pui != NULL) free(pui); + if(pfui != NULL) free(pfui); +} + +/* open user session and return 1 if successfull (all information will be stored + * to LU, otherwise return 0 + */ +DWORD CUserLogin::OpenSession(char *uname, char *passw, SProfile_FullUserInfo *Fui, DWORD lIP, DWORD IPCheckD) +{ + int cr; + if(uprof == NULL) { + uprof = new CProfiles(); + if(uprof->errnum != PROFILE_RETURN_ALLOK) { +#if ENABLE_LOG >= 1 + print2log("call to CProfiles::CProfiles failed at CUserLogin::OpenSession(), line %d", __LINE__); +#endif + return 0; + } + } + + if(pui == NULL) pui = (SProfile_UserInfo*)malloc(sizeof(SProfile_UserInfo)); + if(pfui == NULL) pfui = (SProfile_FullUserInfo*)malloc(sizeof(SProfile_FullUserInfo)); + + if((cr = uprof->GetUserByName(uname, pui, pfui, &LU.SIndex)) == PROFILE_RETURN_ALLOK && + strcmp(passw, pui->password) == 0) + { + /* prepare SUserInfo structure */ + LU.right = pui->right; + LU.sec = pui->secur; + LU.sechdr = pui->secheader; + LU.UniqID = pui->UniqID; + + /* modify SUPERUSER right */ + if(LU.right & USERRIGHT_SUPERUSER) { + LU.right = LU.right | USERRIGHT_VIEW_MESSAGE | USERRIGHT_CLOSE_MESSAGE | + USERRIGHT_MODIFY_MESSAGE | USERRIGHT_CREATE_MESSAGE | USERRIGHT_CREATE_MESSAGE_THREAD | + USERRIGHT_OPEN_MESSAGE | USERRIGTH_ALLOW_HTML | USERRIGTH_PROFILE_MODIFY | + USERRIGTH_PROFILE_CREATE | USERRIGHT_POST_GLOBAL_ANNOUNCE | USERRIGHT_ALT_DISPLAY_NAME; + } + + // fill sequence info + //SEQ.ID; // ID of session + //SEQ.Reserved; // Reserved place + //SEQ.ExpireDate; // Expiration date of the session + SEQ.UniqID = pui->UniqID; // UniqID of user + if(IPCheckD) SEQ.UniqID |= SEQUENCE_IP_CHECK_DISABLED; + SEQ.IP = lIP; // IP address of session + SEQ.SIndex = LU.SIndex; // Index in profindex file + + /* open sequence for user */ + if(OpenAuthSequence(SEQUENCE_LIVE_TIME, &SEQ) != 1) { + LU.SIndex = 0xFFFFFFFF; + LU.right = DEFAULT_NOBODY_RIGHT; + LU.sec = DEFAULT_NOBODY_SECURITY_BYTE; + LU.sechdr = DEFAULT_NOBODY_HDR_SEC_BYTE; + LU.UniqID = 0; + LU.ID[0] = 0; + LU.ID[1] = 0; + free(pui); + free(pfui); + pui = NULL; + pfui = NULL; +#if ENABLE_LOG >= 1 + print2log("Call to OpenAuthSequence failed at CUserLogin::OpenSession(), line %d", __LINE__); +#endif + return 0; + } + else { + // save to LU + LU.ID[0] = SEQ.ID[0]; + LU.ID[1] = SEQ.ID[1]; + LU.ExpireDate = SEQ.ExpireDate; + } + + // update IP and last login date + pui->lastIP = lIP; + pui->LoginDate = time(NULL); + if(uprof->SetUInfo(LU.SIndex, pui) != 1) { +#if ENABLE_LOG >= 1 + print2log("Call to CProfiles::SetUInfo failed at CUserLogin::OpenSession(), lined %d", __LINE__); +#endif + } + + // copy Full user info if requred + if(Fui != NULL) memcpy(Fui, pfui, sizeof(SProfile_FullUserInfo)); + return 1; + } + else { +#if ENABLE_LOG >= 1 + if(cr == PROFILE_RETURN_DB_ERROR) + print2log("Call to CProfiles::GetUserByName failed at CUserLogin::OpenSession(), line %d", __LINE__); +#endif + free(pui); + free(pfui); + pui = NULL; + pfui = NULL; + /* invalid username/password */ + return 0; + } +} + +/* check sequence seq for activity, set LU to this sequence and + * return 1 if successfull, otherwise return 0 + + lIP == 0 - checking existing seq and Uid == seq.UniqID without updating (!!!) + Uid ==0 full checking with updating + + */ +DWORD CUserLogin::CheckSession(DWORD seq[2], DWORD lIP, DWORD Uid) +{ + int seqttl=0; + if(lIP) seqttl = SEQUENCE_LIVE_TIME; + + + if( Uid != 0 && lIP != 0) goto SessionErrorEnd; //invalid calls + + + if(CheckAndUpdateAuthSequence(seq, lIP, seqttl, &SEQ) == 1) { + if(seqttl){ + + if(uprof == NULL) { + uprof = new CProfiles(); + if(uprof->errnum != PROFILE_RETURN_ALLOK) { +#if ENABLE_LOG >= 1 + print2log("call to CProfiles::CProfiles failed at CUserLogin::CheckSession(), line %d", __LINE__); +#endif + goto SessionError1; + } + } + + if(pui == NULL) pui = (SProfile_UserInfo*)malloc(sizeof(SProfile_UserInfo)); + if(pfui == NULL) pfui = (SProfile_FullUserInfo*)malloc(sizeof(SProfile_FullUserInfo)); + + if(uprof->GetUInfo(SEQ.SIndex, pui) != 1) { +#if ENABLE_LOG >= 1 + print2log("call to CProfiles::GetUInfo failed at CUserLogin::CheckSession(), line %d" \ + " (maybe user has been deleted)", __LINE__); +#endif + goto SessionError2; + } + + // Update IP and last login date + pui->lastIP = lIP; + pui->LoginDate = time(NULL); + pui->RefreshCount++; + + if(uprof->SetUInfo(SEQ.SIndex, pui) != 1) { +#if ENABLE_LOG >= 1 + print2log("Call to CProfiles::SetUInfo failed at CUserLogin::CheckSession(), lined %d", __LINE__); +#endif + goto SessionError2; + } + + + if(uprof->GetFullInfo(pui->FullInfo_ID, pfui) != 1) { +#if ENABLE_LOG >= 1 + print2log("call to CProfiles::GetFullInfo() failed at CUserLogin::CheckSession(), line %d" + " (maybe user have been deleted)", __LINE__); +#endif + goto SessionError2; + } + + + // Pui + Pfui is ok + // profile updated + // Load to LU + + LU.ID[0] = SEQ.ID[0]; + LU.ID[1] = SEQ.ID[1]; + LU.SIndex = SEQ.SIndex; + + LU.UniqID = (SEQ.UniqID & (~SEQUENCE_IP_CHECK_DISABLED)); + LU.ExpireDate = SEQ.ExpireDate; + + // LOAD REAL RIGHTS !!! + LU.right = pui->right; + + // LOAD REAL SECURITY BYTES + LU.sechdr = pui->secheader; + LU.sec = pui->secur; + + /* modify SUPERUSER right */ + if(LU.right & USERRIGHT_SUPERUSER) { + LU.right = LU.right | USERRIGHT_VIEW_MESSAGE | USERRIGHT_CLOSE_MESSAGE | + USERRIGHT_MODIFY_MESSAGE | USERRIGHT_CREATE_MESSAGE | USERRIGHT_CREATE_MESSAGE_THREAD | + USERRIGHT_OPEN_MESSAGE | USERRIGTH_ALLOW_HTML | USERRIGTH_PROFILE_MODIFY | + USERRIGTH_PROFILE_CREATE | USERRIGHT_POST_GLOBAL_ANNOUNCE | USERRIGHT_ALT_DISPLAY_NAME; + } + } + else { + //smb wants check own Uid's session + if( Uid !=0 && (SEQ.UniqID & (~SEQUENCE_IP_CHECK_DISABLED)) != Uid ) return 0; + } + + return 1; + } + // seqence cannot be found + + goto SessionErrorEnd; + +SessionError2: + + if(CloseAuthSequence(seq, 0) == 0) {} + + free(pui); + free(pfui); + pui = NULL; + pfui = NULL; + +SessionError1: + + delete uprof; + uprof = NULL; + +SessionErrorEnd: + + // init as no session + LU.SIndex = 0xFFFFFFFF; + LU.right = DEFAULT_NOBODY_RIGHT; + LU.sec = DEFAULT_NOBODY_SECURITY_BYTE; + LU.sechdr = DEFAULT_NOBODY_HDR_SEC_BYTE; + LU.UniqID = 0; + LU.ID[0] = 0; + LU.ID[1] = 0; + + return 0; +} + +/* close sequence seq + * return 1 if successfull, 0 otherwise + */ +DWORD CUserLogin::CloseSession(DWORD seq[2]) +{ + if(CloseAuthSequence(seq, 0) == 1) { + LU.SIndex = 0xFFFFFFFF; + LU.right = DEFAULT_NOBODY_RIGHT; + LU.sec = DEFAULT_NOBODY_SECURITY_BYTE; + LU.sechdr = DEFAULT_NOBODY_HDR_SEC_BYTE; + LU.UniqID = 0; + LU.ID[0] = 0; + LU.ID[1] = 0; + if(pui != NULL) { + free(pui); + pui = NULL; + } + if(pfui != NULL) { + free(pfui); + pfui = NULL; + } + return 1; + } + return 0; +} + +/* force closing session if user such user logged in. + * return 1 if successfull, 0 otherwise + */ +DWORD CUserLogin::ForceCloseSessionForUser(DWORD UniqID) +{ + DWORD x[2]; + memset(&x, 0, 8); + if(CloseAuthSequence(x, UniqID) == 1) { + return 1; + } + return 0; +} + +DWORD CUserLogin::ForceCloseSessionBySeq(DWORD seq[2]) +{ + + if(CloseAuthSequence(seq, 0) == 1) { + return 1; + } + return 0; +} + +DWORD CUserLogin::GenerateListSessionForUser(char ***list, DWORD *scounter, DWORD Uniqid) +{ + if( GenerateListAuthSequence(list, scounter, Uniqid) == 1) return 1; + return 0; +} blob - /dev/null blob + 44b5c071bdeca3e57ca7e3a3c1a0859aca2095ac (mode 644) --- /dev/null +++ src/logins.h @@ -0,0 +1,70 @@ +/*************************************************************************** + login.cpp - log in/out support + ------------------- + begin : Sun Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef LOGINS_H_INCLUDED +#define LOGINS_H_INCLUDED + +#include "basetypes.h" +#include "profiles.h" + +#define SEQUENCE_READ_COUNT 1000 +#define SEQUENCE_LIVE_TIME USER_SESSION_LIVE_TIME + +struct SSavedAuthSeq { + DWORD ID[2]; // ID of session (8 bytes) + DWORD UniqID; // UniqID of user + // and also high bit of it is flag +#define SEQUENCE_IP_CHECK_DISABLED 0xf0000000 + DWORD IP; // IP address of session + DWORD SIndex; // Index in profindex file + time_t ExpireDate; // Expiration date of the session +}; + +struct SAuthUserSeq { + /* sequence number */ + DWORD ID[2]; + /* index of SProfile_UserInfo structure */ + DWORD SIndex; + /* User specific parameters */ + DWORD right; + /* uniq user ID */ + DWORD UniqID; + // security level of message and header + BYTE sec; + BYTE sechdr; + // Expiration date of the session + time_t ExpireDate; +}; + +/* contain information about logged in user or + * about default user + */ +class CUserLogin { +public: + CProfiles *uprof; + DWORD errnum; + SProfile_UserInfo *pui; + SProfile_FullUserInfo *pfui; + SAuthUserSeq LU; + + SSavedAuthSeq SEQ; + + /* constructor opens default session */ + CUserLogin(); + ~CUserLogin(); + DWORD OpenSession(char *uname, char *passw, SProfile_FullUserInfo *Fui, DWORD lIP, DWORD IPCheckD); + DWORD CheckSession(DWORD seq[2], DWORD lIP, DWORD Uid); + DWORD GetUserInfoStruct(DWORD seq[2]); + DWORD ForceCloseSessionForUser(DWORD UniqID); + DWORD ForceCloseSessionBySeq(DWORD seq[2]); + DWORD CloseSession(DWORD seq[2]); + DWORD GenerateListSessionForUser(char ***buflist, DWORD *sc, DWORD Uid); +}; + +#endif + blob - /dev/null blob + 3027c063710293931d4b4ac55936a270606526da (mode 644) --- /dev/null +++ src/main.cpp @@ -0,0 +1,5785 @@ +/*************************************************************************** + main.cpp - main module + ------------------- + begin : Thu Mar 14 21:54:15 MSK 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + +:set encoding=8bit-windows-1251 +:set termencoding=8bit-windows-1251 +:set termencoding=8bit-koi8-r + ***************************************************************************/ + +//#ifdef HAVE_CONFIG_H +//#include +//#endif + +#include "basetypes.h" +#include "dbase.h" +#include "error.h" +#include "main.h" +#include "messages.h" +#include "speller.h" +//#include "design.h" +#include "security.h" +#include "boardtags.h" +#include "profiles.h" +#include "logins.h" +#include "searcher.h" +#include "sendmail.h" +#include "announces.h" +#include "colornick.h" +#include "activitylog.h" +#include "statfs.h" + + +char *ConfTitle; + +char *MESSAGEHEAD_timetypes[4] = { + "÷àñ(à)", // coded as "1" + "äíÿ/äíåé", // coded as "2" + "íåäåëè(þ)", // coded as "3" + "ìåñÿö(åâ)" // coded as "4" +}; + +#if TOPICS_SYSTEM_SUPPORT +char *Topics_List[TOPICS_COUNT] = { + "áåç òåìû", + "Ìóðçèëêà", + "Ïðîãðàììèðîâàíèå", + "Ðàáîòà", + "Ó÷åáà", + "Îáñóæäåíèå", + "Êóïëþ", + "Äâèæîê áîðäû", + "Ðàçâëå÷åíèÿ", + "Ïðîäàì", + "Temp", + "Óñëóãè", + "Unix/Linux", + "Windows", + "Ïðîáëåìû ñåòè", + "Íîâîñòè", + "Ãîëîñîâàíèå", + "Ïîòåðÿíî/Íàéäåíî" +}; +int Topics_List_map[TOPICS_COUNT] = { + 0, //"áåç òåìû", + 4, //"Ó÷åáà", + 3, //"Ðàáîòà", + 1, //"Ìóðçèëêà", + 5, //"Îáñóæäåíèå", + 15,//"Íîâîñòè" + 8, //"Ðàçâëå÷åíèÿ", + 7, //"Äâèæîê áîðäû", + 2, //"Ïðîãðàììèðîâàíèå", + 6, //"Êóïëþ", + 9, //"Ïðîäàì", + 11,//"Óñëóãè", + 13,//"Windows", + 12,//"Unix/Linux", + 14,//"Ïðîáëåìû ñåòè", + 16,//"Ãîëîñîâàíèå", + 17,//"lost/found", + 10,//"Temp", +}; +#endif + +char *UserStatus_List[USER_STATUS_COUNT] = { + "Íîâè÷îê", + "Äóðà÷îê", + "Ýêñïåðò", + "Ãóðó", + "Ôëóäåð" +}; + +char *UserRight_List[USERRIGHT_COUNT] = { + "SUPERUSER", + "VIEW_MESSAGE", + "MODIFY_MESSAGE", + "CLOSE_MESSAGE", + "OPEN_MESSAGE", + "CREATE_MESSAGE", + "CREATE_MESSAGE_THREAD", + "ALLOW_HTML", + "PROFILE_MODIFY", + "PROFILE_CREATE", + "ROLL_MESSAGE", + "UNROLL_MESSAGE", + "POST_GLOBAL_ANNOUNCE", + "ALT_DISPLAY_NAME" +}; + +int GlobalNewSession = 1; + +enum { + ACTION_POST, + ACTION_PREVIEW, + ACTION_EDIT +}; + +char* strget(char *par,const char *find, WORD maxl, char end, bool argparsing = true); + +int getAction(char* par) +{ +#define JS_POST_FIELD "jpost" + int i = -1; + char* szActions[] = { + "post", + "preview", + "edit" + }; + int cActions = sizeof(szActions) / sizeof(char*); + char* st = strget(par, JS_POST_FIELD"=", MAX_STRING, '&'); + if(st && *st) { + for(i = 0; i < cActions; i++) + if(!strcmp(st, szActions[i])) + break; + } else { + char buf[MAX_STRING]; + for(i = 0; i < cActions; i++) + { + sprintf(buf, "%s=", szActions[i]); + st = strget(par, buf, MAX_STRING, '&'); + if(st) + break; + } + } + if(st) + free(st); + if(i < cActions) + return i; + return -1; +} + +static void HttpRedirect(char *url) +{ + printf("Status: 302 Moved\n"); + printf("Pragma: no-cache\n"); + printf("Location: %s\n\n",url); +} + +static void PrintBoardError(char *s1, char *s2, int code, DWORD msgid = 0) +{ + printf(DESIGN_GLOBAL_BOARD_MESSAGE, s1, s2); + if(code & HEADERSTRING_REFRESH_TO_MAIN_PAGE) + printf("%s", MESSAGEMAIN_browser_return); + if(code & HEADERSTRING_REFRESH_TO_THREAD && msgid != 0) + printf(MESSAGEMAIN_browser_to_thread, msgid); +} + +static void PrintBanList () +{ + FILE *f; + int readed; + void *buf = malloc(MAX_HTML_FILE_SIZE); + if((f = fopen(F_BANNEDIP, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + if((readed = fread(buf, 1, MAX_HTML_FILE_SIZE, f)) == 0) printhtmlerror(); + printf(DESIGN_BAN_FORM); + if(fwrite(buf, 1, readed, stdout) != readed) printhtmlerror(); + printf(DESIGN_BAN_FORM2); + free(buf); + fclose(f); + +} + +/* Prints post message form + */ +static void PrintMessageForm(SMessage *msg, char *body, DWORD s, int code, DWORD flags = 0) +{ + char tstr[2][100]; + + printf("

", + MY_CGI_URL, s); + + printf(DESIGN_POST_NEW_MESSAGE_TABLE ""); + if(code & ACTION_BUTTON_EDIT) printf(MESSAGEMAIN_post_editmessage); + else if(code & ACTION_BUTTON_FAKEREPLY) printf("" MESSAGEMAIN_post_replymessage ""); + else printf(MESSAGEMAIN_post_newmessage); + + printf(""); + printf("
"); + + if(!(code & ACTION_BUTTON_EDIT)) { + if(ULogin.LU.ID[0] == 0) { + // print name/password form + printf("%s  " + "\n", + MESSAGEMAIN_post_you_name, AUTHOR_NAME_LENGTH - 1, msg->AuthorName); + // print password + printf("%s    %s\n", + MESSAGEMAIN_post_your_password, PROFILES_MAX_PASSWORD_LENGTH - 1, MESSAGEMAIN_post_login_me); + } + else { + // print name + printf("%s %s   [%s] \n", + MESSAGEMAIN_post_you_name, msg->AuthorName, MY_CGI_URL, MESSAGEHEAD_logoff); + } + } + else { + // print edit name and ip + if(ULogin.LU.ID[0] != 0 && (ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) { + printf("%s  " \ + "" \ + "%s  ", MESSAGEMAIN_post_you_name, AUTHOR_NAME_LENGTH - 1, + msg->AuthorName, MESSAGEMAIN_post_hostname, HOST_NAME_LENGTH - 1, msg->HostName); + } + + } + +#if TOPICS_SYSTEM_SUPPORT + // subject and topic + if(s == 0) { + printf("%s ", MESSAGEMAIN_post_message_subject); + // Only for ROOT messages + printf(""); + } + else { + printf("%s ", MESSAGEMAIN_post_message_subject); + } + + printf("\n", + s? 88: 62, MESSAGE_HEADER_LENGTH - 1, msg->MessageHeader); + +#else + printf("%s ", MESSAGEMAIN_post_message_subject); + printf("\n", + MESSAGE_HEADER_LENGTH - 1, msg->MessageHeader); +#endif + + printf("%s\n", + MESSAGEMAIN_post_message_body); + + + printf("", + body); + + tstr[0][0] = tstr[1][0] = 0; + if(flags & MSG_CHK_DISABLE_SMILE_CODES) strcpy(tstr[0], RADIO_CHECKED); + if(flags & MSG_CHK_DISABLE_WWWCONF_TAGS) strcpy(tstr[1], RADIO_CHECKED); + printf("%s " + "%s ", + MESSAGEMAIN_post_disable_wwwconf_tags, tstr[1], MESSAGEMAIN_post_disable_smile_tags, tstr[0]); + +// if(ULogin.LU.ID != 0) { + tstr[0][0] = 0; + if(flags & MSG_CHK_ENABLE_EMAIL_ACKNL) strcpy(tstr[0], RADIO_CHECKED); + printf("%s", + MESSAGEMAIN_post_reply_acknl, tstr[0]); +// } + + printf("

"); + + printf(""); + + char onSubmitScript[] = + "\n"; + printf("%s", onSubmitScript); + + if(code & ACTION_BUTTON_EDIT) { + printf("\n", MESSAGEMAIN_post_edit_message); + } + else { + if(code & ACTION_BUTTON_PREVIEW) { + printf("\n ",MESSAGEMAIN_post_preview_message); + } + if(code & ACTION_BUTTON_POST) { + printf("", MESSAGEMAIN_post_post_message); + } + } + printf("", ""); + + printf("

 "); +} + +static void PrintLoginForm() +{ + printf("

", MY_CGI_URL); + + printf(DESIGN_BEGIN_LOGIN_OPEN); + + printf("%s%s" \ + "", + MESSAGEMAIN_login_loginname, AUTHOR_NAME_LENGTH - 1, + FilterHTMLTags(cookie_name, 1000, 0), MESSAGEMAIN_login_password); + + printf("
" \ + MESSAGEMAIN_login_ipcheck "
"); + + printf("

" DESIGN_END_LOGIN_CLOSE "

"); + + printf(MESSAGEMAIN_login_lostpassw); +} + +static void PrintPrivateMessageForm(char *name, char *body) +{ + printf("

 

", MY_CGI_URL); + + printf(DESIGN_POST_NEW_MESSAGE_TABLE "" MESSAGEMAIN_privatemsg_send_msg_hdr + "


"); + printf("%s " + "" + "%s", + MESSAGEMAIN_privatemsg_send_msg_usr, PROFILES_MAX_USERNAME_LENGTH - 1, + name, MESSAGEMAIN_privatemsg_send_msg_bdy); + + printf("
", body); + + printf("

" + " 
", + MESSAGEMAIN_privatemsg_prev_msg_btn, MESSAGEMAIN_privatemsg_send_msg_btn); +} + +static void PrintAnnounceForm(char *body, int ChangeAnn = 0) +{ + printf("

 

", MY_CGI_URL); + + printf(DESIGN_POST_NEW_MESSAGE_TABLE "%s


", + ChangeAnn ? MESSAGEMAIN_globann_upd_ann_hdr : MESSAGEMAIN_globann_send_ann_hdr); + + printf("%s
" + "", + MESSAGEMAIN_globann_send_ann_body, body); + + if(ChangeAnn) printf("
" \ + MESSAGEMAIN_globann_upd_ann_id "
"); + printf("

"); + if(ChangeAnn) printf("", ChangeAnn); + printf("
", + MESSAGEMAIN_globann_prev_ann_btn, MESSAGEMAIN_globann_send_ann_btn); +} + +static void PrintLostPasswordForm() +{ + printf("

", MY_CGI_URL); + + printf(DESIGN_BEGIN_LOSTPASSW_OPEN); + + printf("%s%s", MESSAGEMAIN_lostpassw_loginname, AUTHOR_NAME_LENGTH - 1, + FilterHTMLTags(cookie_name, 1000, 0), MESSAGEMAIN_lostpassw_email, PROFILES_FULL_USERINFO_MAX_EMAIL - 1); + + printf("

" DESIGN_END_LOSTPASSW_CLOSE ""); +} + +/* print configuration form */ +static void PrintConfig() +{ + char str1[20], str2[20], str3[20], str4[20], str5[20], str6[20], str7[20], str8[20], str9[20]; + char strm[10][20]; + int i; + + printf("
", + MY_CGI_URL); + + printf("

%s

", MESSAGEHEAD_configure); + + printf("

%s

", MESSAGEHEAD_configure_showmsgs); + + str1[0] = str2[0] = str3[0] = str4[0] = str5[0] = 0; + if(currentlsel == 1) strcpy(str1, RADIO_CHECKED); + + switch(currenttt) { + case 1: + strcpy(str2, LISTBOX_SELECTED); + break; + case 2: + strcpy(str3, LISTBOX_SELECTED); + break; + case 3: + strcpy(str4, LISTBOX_SELECTED); + break; + case 4: + strcpy(str5, LISTBOX_SELECTED); + break; + } + printf("%s" \ + "
", + str1, MESSAGEHEAD_configure_msgslast, currenttv, + str2, MESSAGEHEAD_timetypes[0], str3, MESSAGEHEAD_timetypes[1], str4, + MESSAGEHEAD_timetypes[2], str5, MESSAGEHEAD_timetypes[3] + ); + + str1[0] = str2[0] = str3[0] = str4[0] = str5[0] = 0; + if(currentlsel == 2) strcpy(str1, RADIO_CHECKED); + + switch(currentss) { + case 1: + strcpy(str2, LISTBOX_SELECTED); + break; + case 2: + strcpy(str3, LISTBOX_SELECTED); + break; + case 3: + strcpy(str4, LISTBOX_SELECTED); + break; + case 4: + strcpy(str5, LISTBOX_SELECTED); + break; + } + + printf("%s" + "%s

%s", + str1, MESSAGEHEAD_configure_lastnum, currenttc, MESSAGEHEAD_configure_lastnum2, + MESSAGEHEAD_configure_showstyle, str3, + MESSAGEHEAD_configure_showhronbackward, str4, + MESSAGEHEAD_configure_showhronwothreads, str5, + MESSAGEHEAD_configure_showhrononlyheaders); + + printf("

Âðåìåííîé ïîÿñ:
"); + + +#if TOPICS_SYSTEM_SUPPORT + // use str4 for temporaty buffer + printf("

\ +
" DESIGN_CONFIGURE_CHECKALL "
"); + for(DWORD i = 0; i < TOPICS_COUNT; i++) + { + if(currenttopics & (1<
\n", + Topics_List[Topics_List_map[i]], Topics_List_map[i], str4); + } + printf("
"); +#endif + + if((currentdsm & 0x01) != 0) strcpy(str3, RADIO_CHECKED); + else str3[0] = 0; + if((currentdsm & 0x02) != 0) strcpy(str4, RADIO_CHECKED); + else str4[0] = 0; + if((currentdsm & 0x04) != 0) strcpy(str5, RADIO_CHECKED); + else str5[0] = 0; + if((currentdsm & 0x08) != 0) strcpy(str2, RADIO_CHECKED); + else str2[0] = 0; + if((currentdsm & 0x10) != 0) strcpy(str1, RADIO_CHECKED); + else str1[0] = 0; + if((currentdsm & 0x20) != 0) strcpy(str6, RADIO_CHECKED); + else str6[0] = 0; + if((currentdsm & 0x40) != 0) strcpy(str7, RADIO_CHECKED); + else str7[0] = 0; + if((currentdsm & 0x80) != 0) strcpy(str8, RADIO_CHECKED); + else str8[0] = 0; + if((currentdsm & 0x100) != 0) strcpy(str9, RADIO_CHECKED); + else str9[0] = 0; + + printf("
%s", + MESSAGEHEAD_configure_disablesmiles, str3); + printf("
%s", + MESSAGEHEAD_configure_disableuppic, str4); + printf("
%s", + MESSAGEHEAD_configure_disable2links, str5); + printf("
%s", + MESSAGEHEAD_configure_ownpostshighlight, str2); + printf("
%s", + MESSAGEHEAD_configure_showhostnames, str6); + printf("
%s", + MESSAGEHEAD_configure_showaltnames, str7); + printf("
%s", + MESSAGEHEAD_configure_showsign, str8); + printf("
%s", + MESSAGEHEAD_configure_showreplyform, str9); +#if ALLOW_MARK_NEW_MESSAGES == 2 + printf("
%s", + MESSAGEHEAD_configure_plus_is_href, str1); +#endif + printf("
"); + + if(ULogin.LU.ID[0] && (ULogin.pui->Flags & PROFILES_FLAG_VIEW_SETTINGS) ) + printf("

" MESSAGEHEAD_configure_saving_to_profile "
"); + else printf("

" MESSAGEHEAD_configure_saving_to_browser "
"); + if(ULogin.LU.ID[0]) printf(MESSAGEHEAD_configure_view_saving "
"); + + printf("

", + MESSAGEHEAD_configure_applysettings); + +} + +void PrintTopString(DWORD c, DWORD ind, DWORD ret) +{ + /* print init code */ + printf(DESIGN_COMMAND_TABLE_BEGIN); + + /* print messages */ + int g = 0; + + if(c & HEADERSTRING_ENABLE_TO_MESSAGE) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", ret, MESSAGEHEAD_to_message); + g = 1; + } + + if((c & HEADERSTRING_ENABLE_TO_MESSAGE) || (c & HEADERSTRING_ENABLE_REPLY_LINK)) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + if((c & HEADERSTRING_ENABLE_REPLY_LINK)) + printf("%s", + MY_CGI_URL, ret, MESSAGEMAIN_post_replymessage); + else printf("%s", + MESSAGEMAIN_post_replymessage); + g = 1; + } + + if(c & HEADERSTRING_RETURN_TO_MAIN_PAGE) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + if(ind == MAINPAGE_INDEX || ind == 0) printf("%s", + MY_CGI_URL, MESSAGEHEAD_return_to_main_page); + else printf("%s", + MY_CGI_URL, ind, MESSAGEHEAD_return_to_main_page); + g = 1; + } + + if(c & HEADERSTRING_POST_NEW_MESSAGE) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_post_new_message); + g = 1; + } + + if((c & HEADERSTRING_DISABLE_SEARCH) == 0) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_search); + g = 1; + } + + if(c & HEADERSTRING_CONFIGURE) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_configure); + g = 1; + } + + if(c & HEADERSTRING_ENABLE_RESETNEW) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_resetnew); + g = 1; + } + + if((c & HEADERSTRING_DISABLE_REGISTER) == 0) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + if(ULogin.LU.ID[0] != 0) + printf("%s", MY_CGI_URL, MESSAGEHEAD_registerprf); + else + printf("%s", MY_CGI_URL, MESSAGEHEAD_register); + g = 1; + } + + if(c & HEADERSTRING_REG_USER_LIST) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_userlist); + g = 1; + } + + if( (ULogin.LU.right & USERRIGHT_SUPERUSER) != 0 && HEADERSTRING_REG_USER_LIST) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_banlist); + } + + if((ULogin.LU.ID[0] == 0) && ((c & HEADERSTRING_DISABLE_LOGIN) == 0)) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_login); + g = 1; + } + + if((c & HEADERSTRING_DISABLE_FAQHELP) == 0) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("" MESSAGEHEAD_help_showhelp ""); + g = 1; + } + +#if USER_FAVOURITES_SUPPORT + if(ULogin.LU.ID[0] != 0 && (c & HEADERSTRING_DISABLE_FAVOURITES) == 0) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, MESSAGEHEAD_favourites); + g = 1; + } +#endif + + if(ULogin.LU.ID[0] != 0 && (c & HEADERSTRING_DISABLE_PRIVATEMSG) == 0) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + if(ULogin.pui->persmescnt - ULogin.pui->readpersmescnt > 0) + printf("%s(%d)", + MY_CGI_URL, MESSAGEHEAD_personalmsg, ULogin.pui->persmescnt - ULogin.pui->readpersmescnt); + else + printf("%s", MY_CGI_URL, MESSAGEHEAD_personalmsg); + g = 1; + } + + if((ULogin.LU.right & USERRIGHT_POST_GLOBAL_ANNOUNCE) != 0 && (c & HEADERSTRING_POST_NEW_MESSAGE) != 0) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_makeannounce); + g = 1; + } + + if((ULogin.LU.ID[0] != 0) && ((c & HEADERSTRING_DISABLE_LOGOFF) == 0)) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", MY_CGI_URL, MESSAGEHEAD_logoff); + g = 1; + } + + printf(""); +} + +void PrintTopStaticLinks(DWORD c) +{ + //print stable links on index page + if ((c & HEADERSTRING_REG_USER_LIST) != 0 && (currentdsm & 4) == 0) { + //printf(""); + printf(DESIGN_COMMAND_TABLE_BEGIN); + printf(""); + //gray space after top links + printf(" "); + printf(""); + } + +} + +/* print HTML header of file, header placed in topbanner.html */ +void PrintHTMLHeader(DWORD code, DWORD curind, DWORD retind = 0) +{ + if(!HPrinted) { + printf("Content-type: text/html\n"); + HPrinted = 1; // header have been printed + } + + + if((code & HEADERSTRING_NO_CACHE_THIS) != 0) printf("Pragma: no-cache\n"); + + printf("Set-Cookie: " COOKIE_NAME_STRING "name=%s|ed=%d|lsel=%d|tc=%d|tt=%d|tv=%d|ss=%d|" \ + "lm=%ld|fm=%ld|lt=%ld|ft=%ld|dsm=%d|seq=%08x%08x|topics=%d|lann=%d|tovr=%d|tz=%d&;" \ + " expires=" COOKIE_EXPIRATION_DATE "path=" COOKIE_SERVER_PATH + "\nSet-Cookie: " COOKIE_SESSION_NAME "on&; path=" COOKIE_SERVER_PATH "\n\n", + CodeHttpString(cookie_name, 0), cookie_lastenter, cookie_lsel, cookie_tc, cookie_tt, cookie_tv, + cookie_ss, currentlm, currentfm, currentlt, currentft, cookie_dsm, ULogin.LU.ID[0], ULogin.LU.ID[1], + cookie_topics, currentlann, topicsoverride,cookie_tz); + + printf(HTML_START); + + if((code & HEADERSTRING_REDIRECT_NOW)) { + printf("", MY_CGI_URL); + return; + } + + if(code & HEADERSTRING_REFRESH_TO_MAIN_PAGE) { + if(curind == MAINPAGE_INDEX || curind == 0) + printf("", + AUTO_REFRESH_TIME, MY_CGI_URL); + else + printf("", + AUTO_REFRESH_TIME, MY_CGI_URL, curind); + } + + // print output encoding (charset) + printf(TEXT_ENCODING_HEADER); + + // print title +#if STABLE_TITLE == 0 + printf("%s", ConfTitle); +#else + printf("%s", TITLE_StaticTitle); +#endif + + + printf(TEXT_STYLE_HEADER); + + // print header of board +#if USE_TEXT_TOPBANNER + // print constant expressions + printf(TEXT_TOPBANNER_HEADER); + + if(curind == MAINPAGE_INDEX && (currentdsm & 2) == 0) printf(TEXT_TOPBANNER_MAP); +#else + // print from TOPBANNER file + { + FILE *f; + DWORD readed; + void *buf = malloc(MAX_HTML_FILE_SIZE); + if((f = fopen(F_TOPBANNER,FILE_ACCESS_MODES_R)) == NULL) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_TOPBANNER); + if((readed = fread(buf, 1, MAX_HTML_FILE_SIZE, f)) == 0) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_TOPBANNER); + if(fwrite(buf, 1, readed, stdout) != readed) printhtmlerror(); + free(buf); + fclose(f); + } +#endif + + if((HEADERSTRING_DISABLE_ALL & code) == 0) { + /* print top string (navigation) */ + PrintTopString(code, curind, retind); + PrintTopStaticLinks (code); + } +} + +/* print bottom lines from file (banners, etc.) */ +void PrintBottomLines(DWORD code, DWORD curind, DWORD retind = 0) +{ + // gap between end of board and bottom header + printf(DESIGN_INDEX_WELCOME_CLOSE); + +/* if(((HEADERSTRING_DISABLE_ALL & code) == 0) ) { + PrintTopString(code, curind, retind); + }*/ + + +#if USE_TEXT_BOTTOMBANNER + if(curind == MAINPAGE_INDEX && (currentdsm & 2) == 0) + printf(TEXT_BOTTOMBANNER); + else + printf(TEXT_BOTTOMBANNER_SHORT); +#else + { + FILE *f; + void *buf; + DWORD readed; + if((buf = malloc(MAX_HTML_FILE_SIZE)) == NULL) + printhtmlerrorat(LOG_FATAL_NOMEMORY, MAX_HTML_FILE_SIZE); + if((f = fopen(F_BOTTOMBANNER,FILE_ACCESS_MODES_R)) == NULL) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_BOTTOMBANNER); + if((readed = fread(buf, 1, MAX_HTML_FILE_SIZE, f)) == 0) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_BOTTOMBANNER); + if(fwrite(buf, 1, readed, stdout) != readed) printhtmlerror(); + fclose(f); + free(buf); + } +#endif +} + +/* print moderation toolbar and keys + * + */ +int PrintAdminToolbar(DWORD root, int mflag, DWORD UID) +{ + DWORD fl = 0; // store bit mask for keys + + /* allow to superuser or author */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) || (ULogin.LU.ID[0] != 0 && + ULogin.LU.UniqID == UID)) { + + if(((mflag & MESSAGE_IS_CLOSED) == 0) && (ULogin.LU.right & USERRIGHT_CLOSE_MESSAGE)) + fl = fl | 0x0001; + + if((mflag & MESSAGE_IS_CLOSED) && (ULogin.LU.right & USERRIGHT_OPEN_MESSAGE)) + fl = fl | 0x0002; + + if(ULogin.LU.right & USERRIGHT_MODIFY_MESSAGE) + fl = fl | 0x0004; + } + + /* allow only to superuser */ + if(ULogin.LU.right & USERRIGHT_SUPERUSER) { + + fl = fl | 0x0080; /* delete */ + + if((mflag & MESSAGE_IS_INVISIBLE) == 0) + fl = fl | 0x0008; + + if(mflag & MESSAGE_IS_INVISIBLE) + fl = fl | 0x0010; + + if((mflag & MESSAGE_COLLAPSED_THREAD) == 0) + fl = fl | 0x0020; + + if(mflag & MESSAGE_COLLAPSED_THREAD) + fl = fl | 0x0040; + } + + int g = 0; + if(fl) { + /* print administration table */ + printf("
[ "); + + /* close thread */ + if(fl & 0x0001) { + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_close_thread); + g = 1; + } + + /* open thread */ + if(fl & 0x0002) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_unclose_thread); + g = 1; + } + + // change message + if(fl & 0x0004) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_change_message); + } + + /* collapse thread */ + if(fl & 0x0020) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_roll); + } + + /* uncollapse thread */ + if(fl & 0x0040) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_unroll); + } + + /* hide thread */ + if(fl & 0x0008) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_hide_thread); + g = 1; + } + + /* unhide thread */ + if(fl & 0x0010) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_unhide_thread); + g =1; + } + + /* delete thread */ + if(fl & 0x0080) { + if(g) printf(DESIGN_BUTTONS_DIVIDER); + printf("%s", + MY_CGI_URL, root, MESSAGEMAIN_moderate_delete_thread); + } + + printf(" ]
"); + } + return 0; +} + +/* print FAQ-Help page */ +void PrintFAQForm() +{ + size_t readed; + char *buf; + FILE *f; + + /* print faq file */ + if((buf = (char*)malloc(MAX_HTML_FILE_SIZE)) == NULL) printhtmlerror(); + + if((f = fopen(F_FAQ_HELP, FILE_ACCESS_MODES_R)) == NULL) printhtmlerror(); + //printhtmlerror(); + if((readed = fread(buf, 1, MAX_HTML_FILE_SIZE, f)) == 0) printhtmlerror(); + if(fwrite(buf, 1, readed, stdout) != readed) printhtmlerror(); + fclose(f); + + free(buf); +} + +void PrintSearchForm(char *s, DB_Base *db, int start = 0) +{ + printf("
", + MY_CGI_URL); + + printf("

%s

", MESSAGEHEAD_search); + + if(start) { + FILE *f; + char LastMsgStr[500]; + DWORD LastMsg = 0, LastDate = 0; + f = fopen(F_SEARCH_LASTINDEX, FILE_ACCESS_MODES_R); + if(f != NULL) { + fscanf(f, "%d %d", &LastMsg, &LastDate); + fclose(f); + } + if(LastMsg != 0) { + SMessage mes; + if(ReadDBMessage(db->TranslateMsgIndex(LastMsg), &mes)) { + char s[200]; + ConvertTime(mes.Date, s); + sprintf(LastMsgStr, "%d (%s)", LastMsg, s); + } + else strcpy(LastMsgStr, MESSAGEMAIN_search_indexerror); + } + else { + strcpy(LastMsgStr, MESSAGEMAIN_search_notindexed); + } + printf("

%s

%s : %s

", MESSAGEMAIN_search_howtouse, MESSAGEMAIN_search_lastindexed, LastMsgStr); + } + + printf("

%s
", MESSAGEMAIN_search_searchmsg); + printf("%s " + "", + MESSAGEMAIN_search_containing, s); + + + printf("

", + MESSAGEHEAD_search); +} + +#if STABLE_TITLE == 0 +void Tittle_cat(char *s) +{ + // set title + ConfTitle = (char*)realloc(ConfTitle, strlen(ConfTitle) + strlen(TITLE_divider) + strlen(s) + 1); + strcat(ConfTitle, TITLE_divider); + strcat(ConfTitle, s); +} +#else +#define Tittle_cat(x) {} +#endif + +/* print create or edit(delete) profile form (depend of flags) + * if flags == 1 - Edit profile, otherwise create profile + */ +void PrintEditProfileForm(SProfile_UserInfo *ui, SProfile_FullUserInfo *fui, DWORD flags) +{ + char str1[20], str2[20], str3[20], str4[20], str5[20]; + printf("
", + MY_CGI_URL); + + if(ULogin.LU.ID[0] == 0) { + printf(DESIGN_BEGIN_REGISTER_OPEN "" + "%s", MESSAGEMAIN_register_intro); + } + else + printf(DESIGN_BEGIN_REGISTER_OPEN "" + "%s", MESSAGEMAIN_register_chg_prof_intro); + + printf("
%s ", + MESSAGEMAIN_register_login); + + if( (ULogin.LU.ID[0] == 0) || (ULogin.LU.ID[0] != 0 && ((ULogin.pui->right & USERRIGHT_SUPERUSER) != 0)) ) { + printf("", + AUTHOR_NAME_LENGTH - 1, ui->username); + } + else { + printf("%s", ui->username); + } + + if( ULogin.LU.ID[0] != 0 && ((ULogin.LU.right & USERRIGHT_ALT_DISPLAY_NAME) != 0) ) { + printf("%s ", + MESSAGEMAIN_register_displayname, PROFILES_MAX_ALT_DISPLAY_NAME - 1, ui->altdisplayname); + } + + if((flags & 0x01) == 0) { + printf("" MESSAGEMAIN_register_oldpass_req "" \ + "%s ", + MESSAGEMAIN_register_oldpassword, PROFILES_MAX_PASSWORD_LENGTH - 1); + } + + if(ui->Flags & PROFILES_FLAG_VISIBLE_EMAIL) + strcpy(str1, RADIO_CHECKED); + else *str1 = 0; + + printf("" MESSAGEMAIN_register_if_want_change "" \ +"%s " \ +"%s " \ +"%s " \ +"" MESSAGEMAIN_register_validemail_req "" \ +"%s " \ +"%s" \ +"%s " \ +"%s ", + MESSAGEMAIN_register_password1, PROFILES_MAX_PASSWORD_LENGTH - 1, "", + MESSAGEMAIN_register_password2, PROFILES_MAX_PASSWORD_LENGTH - 1, "", + MESSAGEMAIN_register_full_name, PROFILES_FULL_USERINFO_MAX_NAME - 1, fui->FullName, + MESSAGEMAIN_register_email, PROFILES_FULL_USERINFO_MAX_EMAIL - 1, fui->Email, + MESSAGEMAIN_register_email_pub, str1, MESSAGEMAIN_register_homepage, + PROFILES_FULL_USERINFO_MAX_HOMEPAGE - 1, fui->HomePage, + MESSAGEMAIN_register_icq, PROFILES_MAX_ICQ_LEN - 1, ui->icqnumber + ); + + if((ui->Flags & PROFILES_FLAG_INVISIBLE) == 0) + strcpy(str1, RADIO_CHECKED); + else *str1 = 0; + + if((ui->Flags & PROFILES_FLAG_PERSMSGDISABLED) != 0) + strcpy(str2, RADIO_CHECKED); + else *str2 = 0; + + if((ui->Flags & PROFILES_FLAG_PERSMSGTOEMAIL) != 0) + strcpy(str3, RADIO_CHECKED); + else *str3 = 0; + + if((ui->Flags & PROFILES_FLAG_ALWAYS_EMAIL_ACKN) != 0) + strcpy(str4, RADIO_CHECKED); + else *str4 = 0; + + if((ui->Flags & PROFILES_FLAG_VIEW_SETTINGS) != 0) + strcpy(str5, RADIO_CHECKED); + else *str5 = 0; + + fui->SelectedUsers[PROFILES_FULL_USERINFO_MAX_SELECTEDUSR - 1] = 0; // FIX + + printf( +"%s
" \ +"%s
" \ +"%s
" \ +"%s" \ +"%s" \ +"%s" \ +"%s" \ +"%s", + MESSAGEMAIN_register_about, fui->AboutUser, + MESSAGEMAIN_register_signature, fui->Signature, + MESSAGEMAIN_register_selectedusers, fui->SelectedUsers, + MESSAGEMAIN_register_private_prof, str1, + MESSAGEMAIN_register_always_emlackn, str4, + MESSAGEMAIN_register_pmsg_disable, str2, + MESSAGEMAIN_register_pmsg_email, str3, + MESSAGEMAIN_register_view_saving, str5 + ); + + printf("" \ + MESSAGEMAIN_register_req_fields "" \ + "
"); + + /* print buttons */ + if(flags & 0x01) + printf(" ", MESSAGEMAIN_register_register); + + if(flags & 0x02) + printf(" ", MESSAGEMAIN_register_edit); + + if(flags & 0x04) + printf( + "" + "" + MESSAGEMAIN_register_confirm_delete); + + printf("" DESIGN_END_REGISTER_CLOSE ""); +} + + +void PrintSessionsList(DWORD Uid) +{ + char **buf = NULL; + char name[1000]; + DWORD sc = 0, i; + DWORD seqid[2], userid; + if(ULogin.GenerateListSessionForUser(&buf, &sc, Uid)){ + + if(sc){ + printf(DESIGN_BEGIN_USERINFO_INTRO_OPEN); + for(i = 0; i < sc; i++) { + unsigned char *seqip = (unsigned char*)(buf[i]+4); + seqid[0] = *((DWORD*)(buf[i]+8)); + seqid[1] = *((DWORD*)(buf[i]+12)); + userid = *((DWORD*)(buf[i]+16)); + time_t seqtime = *((DWORD*)(buf[i])); + char *seqdate; + if( seqtime > time(NULL)) seqdate = (char*)ConvertFullTime(seqtime-USER_SESSION_LIVE_TIME); + else seqdate = (char*)ConvertFullTime(seqtime); + + printf("%ld. "MESSAGEMAIN_session_ip"%u.%u.%u.%u %s", + i+1, seqip[0] & 0xff, seqip[1] & 0xff, seqip[2] & 0xff, seqip[3] & 0xff, + userid & SEQUENCE_IP_CHECK_DISABLED ? MESSAGEMAIN_session_ip_nocheck : MESSAGEMAIN_session_ip_check ); + + printf(""MESSAGEMAIN_session_date"" + " %s", seqdate); + printf(""MESSAGEMAIN_session_state""); + + if( seqtime > time(NULL) ) { + printf(MESSAGEMAIN_session_state_active); + + if( (ULogin.LU.right & USERRIGHT_SUPERUSER) != 0 || ( ULogin.LU.UniqID == Uid && ( ULogin.LU.right & USERRIGTH_PROFILE_MODIFY) != 0 ) ) + printf(" ["MESSAGEMAIN_session_state_toclose"]", MY_CGI_URL, seqid[0], seqid[1]); + } + else printf(MESSAGEMAIN_session_state_closed); + printf("
"); + free(buf[i]); + } + printf(DESIGN_END_USERINFO_INTRO_CLOSE); + } + else printf(DESIGN_BEGIN_USERINFO_INTRO_OPEN "" + MESSAGEMAIN_session_no "" DESIGN_END_USERINFO_INTRO_CLOSE); + } + else printhtmlerror(); + if(buf) free(buf); +} + +int PrintAboutUserInfo(char *name) +{ + char *nickname; + CProfiles *mprf = new CProfiles(); + if(mprf->errnum != PROFILE_RETURN_ALLOK) { +#if ENABLE_LOG >= 1 + print2log("error working with profiles database (init)"); +#endif + return 0; + } + SProfile_FullUserInfo fui; + SProfile_UserInfo ui; + + nickname = FilterHTMLTags(name, 1000); + + if(mprf->GetUserByName(name, &ui, &fui, NULL) != PROFILE_RETURN_ALLOK) + { + delete mprf; + printf(MESSAGEMAIN_profview_no_user, nickname); + + return 1; + } + +/**********/ + if(strcmp(name, "www") == 0) print2log("Profile www was accessed by %s", getenv("REMOTE_ADDR")); +/**********/ + + printf("

" DESIGN_BEGIN_USERINFO_INTRO_OPEN + "%s %s", MESSAGEMAIN_profview_intro, nickname); + + printf("
"); + + printf("%s%s", MESSAGEMAIN_profview_login, nickname ); + + + if(ULogin.LU.UniqID == ui.UniqID){ + printf(" (%s)", MESSAGEMAIN_profview_editinfo); + } + + if(ULogin.LU.ID[0] && ULogin.LU.UniqID != ui.UniqID){ + printf(" (%s)", CodeHttpString(name), MESSAGEMAIN_profview_postpersmsg); + } + + printf(""); + + if((ui.Flags & PROFILES_FLAG_ALT_DISPLAY_NAME) != 0) { + char *st; + if(!PrepareTextForPrint(ui.altdisplayname, &st, ui.secheader/*security*/, + MESSAGE_ENABLED_TAGS | BOARDTAGS_PURL_ENABLE)) + { + st = (char*)malloc(1000); + strcpy(st, ui.altdisplayname); + } + printf("%s%s", + MESSAGEMAIN_profview_altname, st); + free(st); + } + + if(((ui.Flags & PROFILES_FLAG_INVISIBLE) == 0) || (ULogin.LU.right & USERRIGHT_SUPERUSER) || + (ULogin.LU.UniqID == ui.UniqID) ) + { + printf("%s%s" \ + "%s%s", + MESSAGEMAIN_profview_fullname, fui.FullName, + MESSAGEMAIN_profview_homepage, fui.HomePage, fui.HomePage); + + /* if invisible mail - allow view only for same user or superuser */ + if((ui.Flags & PROFILES_FLAG_VISIBLE_EMAIL) || (ULogin.LU.right & USERRIGHT_SUPERUSER) || + (ULogin.LU.UniqID == ui.UniqID)) { + printf("%s%s", + MESSAGEMAIN_profview_email, fui.Email, fui.Email); + } + else printf("%s%s", + MESSAGEMAIN_profview_email, MESSAGEMAIN_profview_privacy_inf); + + /* possible error (with malloc) here */ + char *regdate, *logdate = (char*)malloc(255), *ustatus = (char*)malloc(255); + /*************************************/ + if(!ui.LoginDate) strcpy(logdate, "Never logged in"); + else strcpy(logdate, (char*)ConvertFullTime(ui.LoginDate)); + regdate = (char*)ConvertFullTime(fui.CreateDate); + + // set up ustatus + if((ui.right & USERRIGHT_SUPERUSER) && ((ULogin.LU.right & USERRIGHT_SUPERUSER) || (strcmp(name, "www") /*&& strcmp(name, "Jul'etka") */))) { + strcpy(ustatus, MESSAGEMAIN_profview_u_moderator); + } + else { + strcpy(ustatus, MESSAGEMAIN_profview_u_user); + } + + // check for too high value in status + if(ui.Status >= USER_STATUS_COUNT) ui.Status = USER_STATUS_COUNT - 1; // maximum status + + //strcat(ustatus, " ( "); + //strcat(ustatus, UserStatus_List[ui.Status]); + //strcat(ustatus, " )"); + + ui.icqnumber[15] = 0; // FIX + + char icqpic[1000]; + icqpic[0] = 0; + + if(strlen(ui.icqnumber) > 0) { + sprintf(icqpic, "%s" \ + "%s
", + MESSAGEMAIN_profview_user_icq, ui.icqnumber, ui.icqnumber); + } + + printf("%s%s%s" \ +"%s%ld" \ +"%s%s" \ +"%s%s" \ +"%s%s", + icqpic, + MESSAGEMAIN_profview_user_status, ustatus, + MESSAGEMAIN_profview_postcount, ui.postcount, + MESSAGEMAIN_profview_reg_date, regdate, + MESSAGEMAIN_profview_login_date, logdate, + MESSAGEMAIN_profview_about_user, fui.AboutUser); + + if((ULogin.LU.right & USERRIGHT_SUPERUSER) || (ULogin.LU.UniqID == ui.UniqID) ) { + char hname[10000]; + hostent *he; + unsigned char *aa = (unsigned char *)(&ui.lastIP); + sprintf(hname, "%u.%u.%u.%u", aa[0] & 0xff, aa[1] & 0xff, aa[2] & 0xff, aa[3] & 0xff); + if((he = gethostbyaddr((char*)(&ui.lastIP), 4, AF_INET)) != NULL) { + // prevent saving bad hostname + if(strlen(he->h_name) > 0) { + char tmp[1000]; + + strcpy(tmp, hname); + strncpy(hname, he->h_name, 9999); + strcat(hname, " ("); + strcat(hname, tmp); + strcat(hname, ")"); + } + } + // only for admin :) + if((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) + printf("%s%d", + MESSAGEMAIN_profview_refreshcnt, ui.RefreshCount); + printf("%s%s", + MESSAGEMAIN_profview_lastip, hname); + printf("%s%d(%d)", + MESSAGEMAIN_profview_persmsgcnt, ui.persmescnt, ui.readpersmescnt); + } + + free(logdate); + free(ustatus); + } + else { + printf("%s
", MESSAGEMAIN_profview_privacy_prof); + } + printf(DESIGN_END_USERINFO_INTRO_CLOSE); + + + printf("
"); + + if((ULogin.LU.right & USERRIGHT_SUPERUSER) || (ULogin.LU.UniqID == ui.UniqID) ) { + PrintSessionsList(ui.UniqID); + + } + + // + // if admin print profile modification form + // + if((ULogin.LU.right & USERRIGHT_SUPERUSER)) { + char sel[100]; + BYTE i; + printf("
User Status: ", MY_CGI_URL); + + printf(""); + + printf("
" MESSAGEMAIN_profview_sechdr "", (DWORD)ui.secheader); + printf("
" MESSAGEMAIN_profview_secbdy "", (DWORD)ui.secur); + printf("", nickname); + + // user rights here + puts("

"); + for(i = 0; i < USERRIGHT_COUNT; i++) + { + if( (ui.right & (1<
", + UserRight_List[i], i, sel); + } + puts("
"); + + printf("

", MESSAGEMAIN_register_edit); + + printf("

"); + } + + free(nickname); + delete mprf; + + return 1; +} + +// string compare +static int cmp_name(const void *p1, const void *p2) +{ + char upper[2][AUTHOR_NAME_LENGTH]; + strcpy(upper[0], (*(char **)p1) + 20); + strcpy(upper[1], (*(char **)p2) + 20); + for(int i = 0; i < 2; i++) + toupperstr(upper[i]); + + return strcmp(upper[0], upper[1]); +} + +// by last ip +static int cmp_ip(const void *p1, const void *p2) +{ + return int( ntohl((*((DWORD**)p1))[0]) - ntohl((*((DWORD**)p2))[0]) ); +} + +// by postcount +static int cmp_postcount(const void *p1, const void *p2) +{ + return int( (*((DWORD**)p2))[1] - (*((DWORD**)p1))[1] ); +} + +// by refresh count +static int cmp_refreshcount(const void *p1, const void *p2) +{ + return int( (*((DWORD**)p2))[3] - (*((DWORD**)p1))[3] ); +} + +// by last login date +static int cmp_date(const void *p1, const void *p2) +{ + return int( (*((DWORD**)p2))[2] - (*((DWORD**)p1))[2] ); +} + +// by security right +static int cmp_right(const void *p1, const void *p2) +{ + return int( (*((DWORD**)p1))[4] - (*((DWORD**)p2))[4] ); +} + +void PrintUserList(DB_Base *dbb, int code) +{ + char **buf = NULL; + char name[1000]; + DWORD uc = 0, i; + CProfiles uprof; + + if(!uprof.GenerateUserList(&buf, &uc)) + printhtmlerror(); + + // Print header of user list + printf("

%s
%s%d

", MESSAGEHEAD_userlist, MESSAGEMAIN_total_user_count, uc); + + switch(code) { + case 1: + qsort((void *)buf, uc, sizeof(char*), cmp_name); + break; + case 2: + qsort((void *)buf, uc, sizeof(char*), cmp_postcount); + break; + case 3: + qsort((void *)buf, uc, sizeof(char*), cmp_ip); + break; + case 4: + qsort((void *)buf, uc, sizeof(char*), cmp_date); + break; + case 5: + qsort((void *)buf, uc, sizeof(char*), cmp_refreshcount); + break; + case 6: + qsort((void *)buf, uc, sizeof(char*), cmp_right); + break; + } + + // print sort link bar + if((ULogin.LU.right & USERRIGHT_SUPERUSER)) { + printf("%s", MESSAGEMAIN_userlist_sortby); + if(code != 1) printf("%s | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyname); + else printf("%s | ", MESSAGEMAIN_userlist_sortbyname); + if(code != 2) printf("%s | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbypcnt); + else printf("%s | ", MESSAGEMAIN_userlist_sortbypcnt); + if(code != 3) printf("%s | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyhost); + else printf("%s | ", MESSAGEMAIN_userlist_sortbyhost); + if(code != 4) printf("%s | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbydate); + else printf("%s | ", MESSAGEMAIN_userlist_sortbydate); + if(code != 5) printf("%s | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyrefresh); + else printf("%s | ", MESSAGEMAIN_userlist_sortbyrefresh); + if(code != 6) printf("%s

", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyright); + else printf("%s

", MESSAGEMAIN_userlist_sortbyright); + } + + DWORD oldval; + if(uc) { + unsigned char *aa = (unsigned char*)buf[0]; + switch(code) { + case 2: + oldval = *((DWORD*)(buf[0] + 4)); + printf("(%lu)
", *((DWORD*)(buf[0] + 4))); + break; + case 3: + oldval = *((DWORD*)(buf[0])); + printf("(%u.%u.%u.%u)
", aa[0] & 0xff, aa[1] & 0xff, aa[2] & 0xff, aa[3] & 0xff); + break; + case 4: + // not used yet + break; + case 5: + oldval = *((DWORD*)(buf[0] + 12)); + printf("(%lu)
", *((DWORD*)(buf[0] + 12))); + break; + case 6: + oldval = *((DWORD*)(buf[0] + 16)); + printf("(%08x)
", *((DWORD*)(buf[0] + 16))); + break; + } + } + int cc = 0; + // print begin + for(i = 0; i < uc; i++) { + switch(code) { + case 2: + if(oldval != *((DWORD*)(buf[i] + 4))) { + printf("

(%lu)
", *((DWORD*)(buf[i] + 4))); + oldval = *((DWORD*)(buf[i] + 4)); + cc = 0; + } + break; + case 3: + if(oldval != *((DWORD*)(buf[i]))) { + unsigned char *aa = (unsigned char*)buf[i]; + printf("

(%u.%u.%u.%u)
", aa[0] & 0xff, aa[1] & 0xff, aa[2] & 0xff, aa[3] & 0xff); + oldval = *((DWORD*)(buf[i])); + cc = 0; + } + break; + case 4: + break; + case 5: + if(oldval != *((DWORD*)(buf[i] + 12))) { + printf("

(%lu)
", *((DWORD*)(buf[i] + 12))); + oldval = *((DWORD*)(buf[i] + 12)); + cc = 0; + } + break; + case 6: + if(oldval != *((DWORD*)(buf[i] + 16))) { + printf("

(%08x)
", *((DWORD*)(buf[i] + 16))); + oldval = *((DWORD*)(buf[i] + 16)); + cc = 0; + } + break; + } + if((cc % 10) != 0) printf(" | "); + if(((cc % 10) == 0) && cc != 0) { + // print end and begin + printf("


"); + } + cc++; + + dbb->Profile_UserName(buf[i] + 20, name, 1); + printf("%s", name); + free(buf[i]); + } + if(buf) free(buf); + printf("
"); +} + +/* create or update user profile + * if op == 1 - create + * if op == 2 - update + * if op == 3 - delete + */ +int CheckAndCreateProfile(SProfile_UserInfo *ui, SProfile_FullUserInfo *fui, char *p2, char *oldp, int op, char *deal) +{ + CProfiles *uprof; + DWORD err = 0, needregisteraltnick = 0; + + /* password check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + /* old password */ + if(op != 1 && (ULogin.LU.ID[0] == 0 || (strcmp(oldp, ULogin.pui->password) != 0) || + (strcmp(ULogin.pui->username, ui->username) != 0))) + return PROFILE_CHK_ERROR_INVALID_PASSWORD; + } + /* password and confirm password */ + if(op != 3 && (strcmp(ui->password, p2) != 0 || (strlen(p2) < PROFILES_MIN_PASSWORD_LENGTH) && strlen(p2) != 0)) + return PROFILE_CHK_ERROR_INVALID_PASSWORD_REP; + + if(strlen(p2) == 0) { + if(ULogin.LU.ID[0] != 0) strcpy(ui->password, ULogin.pui->password); + else return PROFILE_CHK_ERROR_INVALID_PASSWORD_REP; + } + + // ************ delete ************ + if(op == 3) { + if((ULogin.LU.ID[0] == 0 || strcmp(ULogin.pui->username, ui->username) != 0 || + (ULogin.LU.right & USERRIGTH_PROFILE_MODIFY) == 0) && (!(ULogin.LU.right & USERRIGHT_SUPERUSER))) + return PROFILE_CHK_ERROR_CANNOT_DELETE_USR; + + uprof = new CProfiles(); + + SProfile_UserInfo nui; + err = uprof->GetUserByName(ui->username, &nui, fui, NULL); + if(err == PROFILE_RETURN_ALLOK) { + // check for special admitions + if(nui.altdisplayname[0] != 0 && (nui.Flags & PROFILES_FLAG_ALT_DISPLAY_NAME) ) { + // need to delete alternative spelling too + ui->UniqID = nui.UniqID; + needregisteraltnick = 1; + } + + // deleting user + err = uprof->DeleteUser(ui->username); + // check result of operation + if(err == PROFILE_RETURN_ALLOK) { + if(ULogin.LU.UniqID == nui.UniqID) + ULogin.CloseSession(ULogin.LU.ID); // user deleted itself + else ULogin.ForceCloseSessionForUser(nui.UniqID); // superuser delete smb. + } + } + goto cleanup_and_parseerror; + } + + /* Now we know that it can't be user deletion, so check common parameters */ + + if(fui->Signature[0] != 0) { + ui->Flags = ui->Flags | PROFILES_FLAG_HAVE_SIGNATURE; + } + + if(ui->altdisplayname[0] != 0 && /*security check*/ (ULogin.LU.ID[0] != 0 && (ULogin.LU.right & USERRIGHT_ALT_DISPLAY_NAME) != 0 ) ) { + ui->Flags |= PROFILES_FLAG_ALT_DISPLAY_NAME; + needregisteraltnick = 1; + } + else { + ui->Flags &= (~PROFILES_FLAG_ALT_DISPLAY_NAME); + if( (ULogin.LU.ID[0] != 0 && (ULogin.LU.right & USERRIGHT_ALT_DISPLAY_NAME) != 0 ) ) needregisteraltnick = 1; + } + + /* common email check (if requred vaild email) */ + if(IsMailCorrect(fui->Email) == 0) + return PROFILE_CHK_ERROR_INVALID_EMAIL; + + uprof = new CProfiles(); + + // ********** update ********** + if(op == 2) { + err = uprof->ModifyUser(ui, fui, NULL); + goto cleanup_and_parseerror; + } + + // ********** create ********** + if(op == 1) { + ui->lastIP = Nip; + err = uprof->AddNewUser(ui, fui, NULL); + goto cleanup_and_parseerror; + } + + delete uprof; + + printhtmlerror(); + +cleanup_and_parseerror: + + delete uprof; + + switch(err) { + case PROFILE_RETURN_ALLOK: + { + // Do post user creation/modificaton job +#if USER_ALT_NICK_SPELLING_SUPPORT + if(op == 1 || op == 2 && needregisteraltnick) { + if(ui->altdisplayname[0] != 0) { + char *st; + + // parse tags + if(!PrepareTextForPrint(ui->altdisplayname, &st, ui->secheader/*security*/, + MESSAGE_ENABLED_TAGS | BOARDTAGS_PURL_ENABLE)) { + st = (char*)malloc(1000); + strcpy(st, ui->altdisplayname); + } + + AltNames.AddAltName(ui->UniqID, ui->username, st); + free(st); + } + else AltNames.DeleteAltName(ui->UniqID); + } + else if(op == 3 && needregisteraltnick) { + AltNames.DeleteAltName(ui->UniqID); + } +#endif + } + return PROFILE_CHK_ERROR_ALLOK; + + case PROFILE_RETURN_ALREADY_EXIST: + return PROFILE_CHK_ERROR_ALREADY_EXIST; + + case PROFILE_RETURN_DB_ERROR: +#if ENABLE_LOG >= 1 + print2log("Profiles database error: DB ERROR, deal=%s", deal); +#endif + printhtmlerror(); + + case PROFILE_RETURN_INVALID_FORMAT: +#if ENABLE_LOG >= 1 + print2log("Profiles database error: INVALID FORMAT, deal=%s", deal); +#endif + printhtmlerror(); + + case PROFILE_RETURN_INVALID_LOGIN: + if(op == 1 || op == 2) + return PROFILE_CHK_ERROR_INVALID_LOGIN_SPELL; + return PROFILE_CHK_ERROR_CANNOT_DELETE_USR; + + case PROFILE_RETURN_INVALID_PASSWORD: + return PROFILE_CHK_ERROR_INVALID_PASSWORD; + + case PROFILE_RETURN_PASSWORD_SHORT: + return PROFILE_CHK_ERROR_SHORT_PASSWORD; + + case PROFILE_RETURN_UNKNOWN_ERROR: + default: +#if ENABLE_LOG >= 1 + print2log("profiles database error : UNKNOWN, deal=%s", deal); +#endif + printhtmlerror(); + } +} + +void PrintFavouritesList() +{ + + printf("

%s
", MESSAGEHEAD_favourites); + //for( int i=0; i<20; i++){ + // printf("ULogin.pui->favs[%ld]=%ld
",i, ULogin.pui->favs[i]); + //} + //DB.PrintHtmlMessageBufferByVI(ULogin.pui->favs, PROFILES_FAV_THREADS_COUNT); + printf("

"); +} + + +/* complete operation with user profile and print + * result of execution + * op == 1 create + * op == 2 update + * op == 3 delete + */ +void DoCheckAndCreateProfile(SProfile_UserInfo *ui, SProfile_FullUserInfo *fui, char *passwdconfirm, char *oldpasswd, int op, char *deal) +{ + int err; + DWORD delme = 0; + + if(ULogin.LU.ID[0] != 0 && strcmp(ui->username, ULogin.pui->username) == 0 && op == 3) { + delme = 1; + } + + if(op == 1 ) { + char *f = FilterWhitespaces(ui->username); + memmove(ui->username, f, strlen(f) + 1); + } + + print2log("DoCheckAndCreateProfile: user '%s', op=%d, (by %s)", ui->username, op, ULogin.LU.ID[0] != 0 ? ULogin.pui->username : "anonymous"); + err = CheckAndCreateProfile(ui, fui, passwdconfirm, oldpasswd, op, deal); + + if(err != PROFILE_CHK_ERROR_ALLOK) + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + char *tmp; + + switch(err) { + case PROFILE_CHK_ERROR_ALLOK: + if(op == 3) { + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + MAINPAGE_INDEX); + if(!delme) + PrintBoardError(MESSAGEMAIN_register_delete_ex, MESSAGEMAIN_register_delete_ex2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + else + PrintBoardError(MESSAGEMAIN_register_delete_logoff, MESSAGEMAIN_register_delete_logoff2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + } + else { + if(op == 1) { + /* if session already opened - close it */ + if(ULogin.LU.ID[0] != 0) + ULogin.CloseSession(ULogin.LU.ID); + + if(ULogin.OpenSession(ui->username, ui->password, NULL, Nip, 0) == 1) { + // entered, set new cookie + cookie_name = (char*)realloc(cookie_name, AUTHOR_NAME_LENGTH); + strcpy(cookie_name, ui->username); + } + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_register_create_ex, MESSAGEMAIN_register_create_ex2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + } + else { + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_register_edit_ex, MESSAGEMAIN_register_edit_ex2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + } + } + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + MAINPAGE_INDEX); + break; + case PROFILE_CHK_ERROR_ALREADY_EXIST: + PrintBoardError(MESSAGEMAIN_register_already_exit, MESSAGEMAIN_register_already_exit2, 0); + break; + case PROFILE_CHK_ERROR_NOT_EXIST: + PrintBoardError(MESSAGEMAIN_register_invalid_psw, MESSAGEMAIN_register_invalid_psw2, 0); + break; + case PROFILE_CHK_ERROR_INVALID_LOGIN_SPELL: + PrintBoardError(MESSAGEMAIN_register_invalid_lg_spell, MESSAGEMAIN_register_invalid_lg_spell2, 0); + break; + case PROFILE_CHK_ERROR_INVALID_PASSWORD: + PrintBoardError(MESSAGEMAIN_register_invalid_psw, MESSAGEMAIN_register_invalid_psw2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + break; + case PROFILE_CHK_ERROR_INVALID_PASSWORD_REP: + PrintBoardError(MESSAGEMAIN_register_invalid_n_psw, MESSAGEMAIN_register_invalid_n_psw2, 0); + break; + case PROFILE_CHK_ERROR_SHORT_PASSWORD: + PrintBoardError(MESSAGEMAIN_register_invalid_n_psw, MESSAGEMAIN_register_invalid_n_psw2, 0); + break; + case PROFILE_CHK_ERROR_INVALID_EMAIL: + PrintBoardError(MESSAGEMAIN_register_invalid_email, MESSAGEMAIN_register_invalid_email2, 0); + break; + case PROFILE_CHK_ERROR_CANNOT_DELETE_USR: + /* possible BUG here */ + tmp = (char*)malloc(1000); + /*********************/ + sprintf(tmp, MESSAGEMAIN_register_cannot_delete, ui->username); + PrintBoardError(tmp, MESSAGEMAIN_register_cannot_delete2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + free(tmp); + break; + default: + printhtmlerror(); + } + + if(err != PROFILE_CHK_ERROR_ALLOK) + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); +} + +void printaccessdenied(char *deal) +{ + Tittle_cat(TITLE_Error); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); +#if ENABLE_LOG > 2 + print2log(LOG_UNKNOWN_URL, Cip, deal); +#endif + PrintBoardError(MESSAGEMAIN_access_denied, MESSAGEMAIN_access_denied2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); +} + +void printpassworderror(char *deal) +{ + /* incorrect username or password */ +#if ENABLE_LOG > 1 + print2log(LOG_PSWDERROR, Cip, deal); +#endif + + Tittle_cat(TITLE_IncorrectPassword); + + /* incorrect login and/or password */ + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_incorrectpwd, MESSAGEMAIN_incorrectpwd2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); +} + +void printnomessage(char *deal) +{ + Tittle_cat(TITLE_Error); +#if ENABLE_LOG > 2 + print2log(LOG_UNKNOWN_URL, Cip, deal); +#endif + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_nonexistingmsg, MESSAGEMAIN_nonexistingmsg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); +} + +void printbadurl(char *deal) +{ + Tittle_cat(TITLE_Error); + +#if ENABLE_LOG > 2 + print2log(LOG_UNKNOWN_URL, Cip, deal); +#endif + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_requesterror, MESSAGEMAIN_requesterror2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); +} + +/* print message thread */ +int PrintMessageThread(DB_Base *bd, DWORD root, DWORD Flag, DWORD Puser) +{ + // print admin toolbar + PrintAdminToolbar(root, Flag, Puser); + + bd->DB_PrintMessageBody(root); + bd->DB_PrintMessageThread(root); + return 0; +} + +//rewritten for IIS compatibility +// Return not more than maxlen bytes (including '\0') +char* GetParams(DWORD maxlen) +{ + char* pCL = getenv("CONTENT_LENGTH"); + if(pCL != NULL) + { + int nCL = atoi(pCL); + if(nCL > maxlen) nCL = maxlen; + if(nCL > 0) + { + DWORD ret; + char* szBuf = (char*)malloc(nCL + 3); + if(szBuf == NULL) { +#if _DEBUG_ == 1 + print2log("GetParams::malloc - out of memory"); +#endif + return NULL; + } + if((ret = (DWORD)fread(szBuf, sizeof(char), nCL, stdin)) == 0) { +#if _DEBUG_ == 1 + print2log("GetParams::fread - failed"); +#endif + goto cleanup; + } + szBuf[ret] = '&'; // patch string for our parser + szBuf[ret+1] = '\0'; +// print2log("POST params = %s, readed = %d", szBuf, ret); + return szBuf; +cleanup: + free(szBuf); + } + } + else { +#if _DEBUG_ == 1 + print2log("No CONTENT_LENGTH env. value"); +#endif + } + return NULL; +} + +/* parse hex symbol to value */ +char inline parsesym(char s) +{ + s = (char)toupper(s); + if(s >= '0' && s <= '9') return (char)(s - '0'); + if(s >= 'A' && s <= 'F') return (char)(s - 'A' + 10); + return 20; +} + +/* find and return key [find] in string [par] between [find] and "&" +* par is limited to MAX_PARAMETERS_LENGTH - 1 +*/ +char* strget(char *par,const char *find, WORD maxl, char end, bool argparsing) +{ + bool bZend = false; + char *res, *rres; + char *s, *x; + char a, b; + if(par == NULL) return NULL; + if(find == NULL) return NULL; + if((s = strstr(par, find)) == NULL) return NULL; + if(bZend = ((x = strchr(s, end)) == NULL)) + x = strchr(s, 0); + else + *x = 0; // temporary change '&' to '\0' + rres = res = (char *)malloc(maxl + 1); + s = s + strlen(find); + if(argparsing) { + while(*s != '\0' && res - rres < maxl) { + if(*s == '%' && x > s + 2) { + if((a = parsesym(*(s + 1))) == 20) { + s++; continue; // ignore invalid % + } + if((b = parsesym(*(s + 2))) == 20) { + s++; continue; // ignore invalid % + } + *res = (char)(a*16 + b); + s+=2; + } + else if(*s == '+') *res = ' '; + else *res = *s; + res++; + s++; + } + *res = 0; + rres = (char*)realloc(rres, strlen(rres) + 1); + } + else { + strncpy(rres, s, maxl); + rres[maxl] = 0; // fix for any string + } + if(!bZend) + *x = end; + return rres; +} + +// get cookie information, if avaliable +void ParseCookie() +{ + char *c, *s, *ss, *t, *st; + DWORD tmp; + int tmp_int; + + GlobalNewSession = 1; + currentft = 1; + currentlt = 1; + currentfm = 1; + currentlm = 1; + currentlann = 0; + + cookie_ss = CONFIGURE_SETTING_DEFAULT_ss; + cookie_tt = CONFIGURE_SETTING_DEFAULT_tt; + cookie_tv = CONFIGURE_SETTING_DEFAULT_tv; + cookie_tc = CONFIGURE_SETTING_DEFAULT_tc; + cookie_lsel = CONFIGURE_SETTING_DEFAULT_lsel; + cookie_dsm = CONFIGURE_SETTING_DEFAULT_dsm; + cookie_tz = DATETIME_DEFAULT_TIMEZONE; + +#if TOPICS_SYSTEM_SUPPORT + cookie_topics = CONFIGURE_SETTING_DEFAULT_topics; + topicsoverride = CONFIGURE_SETTING_DEFAULT_toverride; +#endif + + s = getenv("HTTP_COOKIE"); + //if(s) print2log(s); + + if(s != NULL) { + c = (char*)malloc(strlen(s) + 1); + strcpy(c, s); + + // After this strget() we will have all %XX parsed ! So we should + // disable %XX parsing + if((ss = strget(c, COOKIE_NAME_STRING, COOKIE_MAX_LENGTH, '&')) != NULL) { + ss = (char*)realloc(ss, strlen(ss)+2); + strcat(ss,"|"); + + + if(t = strget(ss, "name=", AUTHOR_NAME_LENGTH - 1, '|', 0)){ + cookie_name = t; + } + + + if(t = strget(ss, "seq=", 30, '|', 0)){ + cookie_seq = t; + } + + + + if(t = strget(ss, "ed=", 20, '|', 0)) { + RefreshDate = strtol(t, &st, 10); + if((!((*t) != '\0' && *st == '\0')) || errno == ERANGE) + { + RefreshDate = 0; + } + free(t); + } + + + // read lsel (show type selection) + if(t = strget(ss, "lsel=", 3, '|', 0)) { + tmp = strtol(t, &st, 10); + if(( (*t) != '\0' && *st == '\0') && errno != ERANGE && tmp <= 2 && tmp >= 1) + { + cookie_lsel = tmp; + } + free(t); + } + + // read tc (thread count) + if(t = strget(ss, "tc=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + cookie_tc = tmp; + } + free(t); + } + + // read tt (time type) + if(t = strget(ss, "tt=", 3, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp <= 4 && tmp > 0) + { + cookie_tt = tmp; + } + free(t); + } + + // read ss (style string) + if(t = strget(ss, "ss=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0 && tmp <= 4) + { + cookie_ss = tmp; + } + free(t); + } + + // read tv (time value) + if(t = strget(ss, "tv=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + cookie_tv = tmp; + } + free(t); + } + + // read lt (last thread) + if(t = strget(ss, "lt=", 12, '|', 0)){ + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + currentlt = tmp; + } + free(t); + } + + // read fm (first message) + if(t = strget(ss, "ft=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + currentft = tmp; + } + free(t); + } + + // read lm (last message) + if(t = strget(ss, "lm=", 12, '|', 0)){ + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + currentlm = tmp; + } + free(t); + } + + // read fm (first message) + if(t = strget(ss, "fm=", 12, '|', 0)){ + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + currentfm = tmp; + } + free(t); + } + + // read dsm (globally disable smiles, picture, and 2-d link bar) + if(t = strget(ss, "dsm=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp > 0) + { + cookie_dsm = tmp; + } + free(t); + } + +#if TOPICS_SYSTEM_SUPPORT + // read topics + if(t = strget(ss, "topics=", 20, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE) + { + cookie_topics = tmp; + } + free(t); + } + + // read topics override + if(t = strget(ss, "tovr=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE) + { + topicsoverride = tmp; + } + free(t); + } +#endif + + // read lann (last hided announce) + if(t = strget(ss, "lann=", 12, '|', 0)) { + tmp = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp >= 0) + { + currentlann = tmp; + ReadLastAnnounceNumber(&tmp); + if(currentlann > tmp) currentlann = tmp; + } + free(t); + } + + // read timezone + if(t = strget(ss, "tz=", 12, '|', 0) ) { + tmp_int = strtol(t, &st, 10); + if(((*t) != '\0' && *st == '\0') && errno != ERANGE && tmp_int >= -12 && tmp_int <= 12) + { + cookie_tz = tmp_int; + } + free(t); + } + + free(ss); + + } + + + if((ss = strget(c, COOKIE_SESSION_NAME, 12, '&')) && strcmp(ss, "on") == 0) { + GlobalNewSession = 0; + free(ss); + } + + free(c); + } + + if(!cookie_name){ + cookie_name = (char*)malloc(1); + cookie_name[0] = 0; + } + + if(!cookie_seq) { + cookie_seq = (char*)malloc(1); + cookie_seq[0] = 0; + } +} + +// calculate time limit for printing messages +void calc_print_time() +{ + if(currentlsel == 1) { + // calculate time limit + current_minprntime = time(NULL); + switch(currenttt) { + case 1: + // hours + current_minprntime = current_minprntime - 3600*currenttv; + break; + case 2: + // days + current_minprntime = current_minprntime - 3600*24*currenttv; + break; + case 3: + // weeks + current_minprntime = current_minprntime - 3600*24*7*currenttv; + break; + case 4: + // months + current_minprntime = current_minprntime - 3600*24*31*currenttv; + break; + } + } +} + +static void PrepareActionResult(int action, char **c_par1, char **c_par2) +{ + switch(action) { + case MSG_CHK_ERROR_NONAME : + *c_par1 = MESSAGEMAIN_add_no_name; + *c_par2 = MESSAGEMAIN_add_no_name2; + break; + case MSG_CHK_ERROR_NOMSGHEADER: + *c_par1 = MESSAGEMAIN_add_no_subject; + *c_par2 = MESSAGEMAIN_add_no_subject2; + break; + case MSG_CHK_ERROR_NOMSGBODY: + *c_par1 = MESSAGEMAIN_add_no_body; + *c_par2 = MESSAGEMAIN_add_no_body2; + break; + case MSG_CHK_ERROR_BADSPELLING: + *c_par1 = MESSAGEMAIN_add_spelling; + *c_par2 = MESSAGEMAIN_add_spelling2; + break; +#if BANNED_CHECK + case MSG_CHK_ERROR_BANNED: + *c_par1 = MESSAGEMAIN_add_banned; + *c_par2 = MESSAGEMAIN_add_banned2; + break; +#endif + case MSG_CHK_ERROR_CLOSED: + *c_par1 = MESSAGEMAIN_add_closed; + *c_par2 = MESSAGEMAIN_add_closed2; + break; + case MSG_CHK_ERROR_INVALID_REPLY: + *c_par1 = MESSAGEMAIN_add_invalid_reply; + *c_par2 = MESSAGEMAIN_add_invalid_reply; + break; + case MSG_CHK_ERROR_INVALID_PASSW: + *c_par1 = MESSAGEMAIN_incorrectpwd; + *c_par2 = MESSAGEMAIN_incorrectpwd2; + break; + default: + *c_par1 = MESSAGEMAIN_unknownerr; + *c_par2 = MESSAGEMAIN_unknownerr2; + break; + } +} + +int ConvertHex(char *s, char *res) +{ + int i = 0; + if(!s) return 0; + while(*s != 0 && *(s+1) != 0) { +#define FROM_HEX(x) ((x >= 'A' && x <= 'F') ? (x-'A' + 10) : \ + (x >= 'a' && x <= 'f') ? (x-'a' + 10) : (x - '0')) + res[i] = FROM_HEX(*s)*16 + FROM_HEX(*(s+1)); + i++; + s+=2; + } + return i; +} + +int main() +{ + char *deal, *st, *mesb; + char *par; // parameters string + char *tmp; + int initok = 0; + DB_Base DB; + SMessage mes; + +#ifndef WIN32 + + if(!isEnoughSpace()) { + printf("Content-type: text/html\n\n" + "Sorry guys, no space left for DB - wwwconf shutting down."); + exit(1); + } + +#endif + +#ifdef RT_REDIRECT +#define BADURL "/board/" +#define GOODURL "http://board.rt.mipt.ru/" + if((st = getenv(REQUEST_URI)) != NULL) + { + deal = (char*)malloc(strlen(st) + 2); + strcpy(deal, st); + //fprintf(stderr,"req uri: %s\n",deal); + if (strncmp(deal, BADURL, strlen(BADURL)) == 0 ) { + tmp = (char*)malloc(strlen(deal) + strlen(GOODURL) + 10); + sprintf(tmp,"%s%s",GOODURL,deal + strlen(BADURL)); + //fprintf(stderr,"redir: %s\n",tmp); + HttpRedirect(tmp); + free(tmp); + goto End_part; + } + free(deal); + } +#endif + +#define UA_LINKS "Links" +#define UA_LYNX "Lynx" +#define UA_NN202 "Mozilla/2.02" + // will we use
or
? + if( ((st = getenv("HTTP_USER_AGENT")) != NULL) && (*st != '\0') ) + { + deal = (char*)malloc(strlen(st) + 2); + strcpy(deal, st); + if ( (strncmp(deal, UA_LINKS, strlen(UA_LINKS)) == 0) || + (strncmp(deal, UA_LYNX, strlen(UA_LYNX)) == 0) || + (strncmp(deal, UA_NN202, strlen(UA_NN202)) == 0) ) { + strcpy(DESIGN_open_dl, DESIGN_OP_DL); + strcpy(DESIGN_open_dl_grey, DESIGN_OP_DL); + strcpy(DESIGN_open_dl_white, DESIGN_OP_DL); + strcpy(DESIGN_close_dl, DESIGN_CL_DL); + strcpy(DESIGN_break, DESIGN_DD); + strcpy(DESIGN_threads_divider, DESIGN_THREADS_DIVIDER_HR); + initok = 1; + } + free(deal); + } + if (!initok) { + strcpy(DESIGN_open_dl, DESIGN_OP_DIV); + strcpy(DESIGN_open_dl_grey, DESIGN_OP_DIV_grey); + strcpy(DESIGN_open_dl_white, DESIGN_OP_DIV_white); + strcpy(DESIGN_close_dl, DESIGN_CL_DIV); + strcpy(DESIGN_break, DESIGN_BR); + strcpy(DESIGN_threads_divider, DESIGN_THREADS_DIVIDER_IMG); + } + +#if defined(WIN32) && defined(IP_TO_HOSTNAME_RESOLVE) + + WSADATA wsaData; + if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0 ) { + // Tell the user that we could not find a usable + // WinSock DLL, but here just do nothing and bailing out + return -1; + } + +#endif + + /* + // ----------------------------- + char *s = (char *)&mes; + for(int i=0;iusername); + } + } + } + + // + // checking settings were saved in profile or cookies and restoring them. + // + + if(ULogin.LU.ID[0] && (ULogin.pui->Flags & PROFILES_FLAG_VIEW_SETTINGS) ) { + + currentdsm = ULogin.pui->vs.dsm; + currenttopics = ULogin.pui->vs.topics; + currenttv = ULogin.pui->vs.tv; + currenttc = ULogin.pui->vs.tc; + currentss = ULogin.pui->vs.ss; + currentlsel = ULogin.pui->vs.lsel; + currenttt = ULogin.pui->vs.tt; + currenttz = ULogin.pui->vs.tz; + } + else{ + currentlsel = cookie_lsel; + currenttc = cookie_tc; + currenttt = cookie_tt; + currenttv = cookie_tv; + currentss = cookie_ss; + currentdsm = cookie_dsm; + currenttopics = cookie_topics; + currenttz = cookie_tz; + } + + // caluclate minimal message print time + calc_print_time(); + + + //security check + if(ULogin.LU.ID[0] && (ULogin.LU.right & USERRIGHT_SUPERUSER) ) + print2log("Superuser: %s from %s - %s", ULogin.pui->username, Cip, deal); + + + //========================== + // detecting user wishes %) + //========================== + + + + if(strncmp(deal, "resetnew", 8) == 0) { + // apply old last message value + currentlm = currentfm; + currentlt = currentft; + cookie_lastenter = time(NULL); + // set new read time value + PrintHTMLHeader(HEADERSTRING_REDIRECT_NOW | HEADERSTRING_NO_CACHE_THIS, MAINPAGE_INDEX); + + goto End_part; + } + + if(strncmp(deal, "index", 5) == 0) + { + /* security check */ + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) + { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"index=", 16, '&')) != NULL) + { + int entok = 0; + if(strcmp(st, "all") == 0) { + topicsoverride = TOPICS_COUNT + 50; + entok = 1; + } + else { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || tmp > TOPICS_COUNT) + { + // just print common index + } + else { + topicsoverride = tmp; + entok = 1; + } + } + if(entok) { + PrintHTMLHeader(HEADERSTRING_REDIRECT_NOW | HEADERSTRING_NO_CACHE_THIS, MAINPAGE_INDEX); + goto End_part; + } + } + +#if TOPIC_SYSTEM_SUPPORT +#if STABLE_TITLE == 0 + // add current topic to index title + if (topicsoverride > 0 && topicsoverride <= TOPICS_COUNT) { + Tittle_cat(Topics_List[topicsoverride-1]); + } else if (topicsoverride > (TOPICS_COUNT + 1)) { + Tittle_cat(MESSAGEMAIN_WELCOME_ALLTOPICS); + } +#endif +#endif + + + // Apply new last message and thread value + DWORD readed = DB.VIndexCountInDB(); + DWORD mtc; + // Read main threads count + if(!DB.ReadMainThreadCount(&mtc)) mtc=0; + + currentfm = readed; + currentft = mtc; + // + // Here we make a decision about new session of "+" + // + if(GlobalNewSession) + { + // apply old last message value + currentlm = currentfm; + currentlt = currentft; + // set new read time value + cookie_lastenter = time(NULL); + } + + + PrintHTMLHeader(HEADERSTRING_REG_USER_LIST | HEADERSTRING_POST_NEW_MESSAGE | + HEADERSTRING_CONFIGURE | HEADERSTRING_WELCOME_INFO | + HEADERSTRING_ENABLE_RESETNEW | HEADERSTRING_DISABLE_END_TABLE, MAINPAGE_INDEX); + + // Prepare information about new message count and dispaly mode */ + char displaymode[500]; // display message mode + char displaynewmsg[500]; // new message info + char topicselect[2000]; // topic select: MAYBE BUG HERE IF TOO MANY TOPICS + char privmesinfo[500]; // private message info + char activityloginfo[500]; // user activity info + topicselect[0] = 0; + privmesinfo[0] = 0; + activityloginfo[0] = 0; + + DWORD a = currentfm - currentlm; + DWORD t = ((currentft - currentlt) >= 0) ? (currentft - currentlt) : 0; + DWORD totalcount = DB.MessageCountInDB(); + if(a) sprintf(displaynewmsg, MESSAGEMAIN_WELCOME_NEWTHREADS, t, a, totalcount); + else sprintf(displaynewmsg, MESSAGEMAIN_WELCOME_NONEWTHREADS, totalcount); + + // current settings in welcome message + if(currentlsel == 1) + { + // hours + sprintf(displaymode, MESSAGEMAIN_WELCOME_DISPLAYTIME, currenttv, MESSAGEHEAD_timetypes[currenttt-1]); + } + else + { + // threads + sprintf(displaymode, MESSAGEMAIN_WELCOME_DISPLAYTHREADS, currenttc); + } + +#if TOPICS_SYSTEM_SUPPORT + { + char tmp[500], sel[50], sel2[50]; + sel[0] = sel2[0] = 0; + // Prepare topic list + if(topicsoverride == 0) strcpy(sel, LISTBOX_SELECTED); + if(topicsoverride > TOPICS_COUNT) strcpy(sel2, LISTBOX_SELECTED); + sprintf(topicselect, DESIGN_WELCOME_QUICKNAV, sel, MESSAGEMAIN_WELCOME_YOURSETTINGS, sel2, MESSAGEMAIN_WELCOME_ALLTOPICS); + for(DWORD i = 0; i < TOPICS_COUNT; i++) { + if(Topics_List_map[i] == (topicsoverride - 1)) strcpy(sel, LISTBOX_SELECTED); + else sel[0] = 0; // "" + sprintf(tmp, "\n", Topics_List_map[i]+1, sel, Topics_List[Topics_List_map[i]]); + strcat(topicselect, tmp); + } + strcat(topicselect, ""); + } +#endif + + // moved to PrintTopStaticLinks //printf(" "); + + // print info about personal messages + if(ULogin.LU.ID[0] != 0 && ULogin.pui->persmescnt - ULogin.pui->readpersmescnt > 0) { + sprintf( privmesinfo, ", " MESSAGEMAIN_privatemsg_newmsgann " %ld " \ + MESSAGEMAIN_privatemsg_newmsgann1 "", (ULogin.pui->persmescnt - ULogin.pui->readpersmescnt) ); + } + +#if ACTIVITY_LOGGING_SUPPORT + sprintf(activityloginfo, MESSAGEMAIN_ACTIVITY_STATVIEW, hitcnt, hostcnt); +#endif + + int formstarted = 0; + if(ULogin.LU.ID[0] == 0) { + printf(MESSAGEMAIN_WELCOME_START, PROFILES_MAX_USERNAME_LENGTH, + FilterHTMLTags(cookie_name, 1000, 0), + PROFILES_MAX_PASSWORD_LENGTH, displaynewmsg, displaymode, + activityloginfo, topicselect); + formstarted = 1; + } + else { + char uname[1000]; + DB.Profile_UserName(ULogin.pui->username, uname, 1); + printf(MESSAGEMAIN_WELCOME_LOGGEDSTART, uname, privmesinfo, displaynewmsg, + displaymode, activityloginfo, topicselect); + } + + + + // Announce going here + { + SGlobalAnnounce *ga; + DWORD cnt, i; + if(ReadGlobalAnnounces(0, &ga, &cnt) != ANNOUNCES_RETURN_OK) printhtmlerror(); + if(cnt) { + char uname[1000], del[1000], date[100]; + int something_printed = 0; + for(i = 0; i < cnt; i++) { + if(ga[i].Number > currentlann) { + DB.Profile_UserName(ga[i].From, uname, 1); + + char *st = FilterHTMLTags(ga[i].Announce, MAX_PARAMETERS_STRING - 1); + char *st1 = NULL; + DWORD retflg; + if(FilterBoardTags(st, &st1, 0, MAX_PARAMETERS_STRING - 1, + MESSAGE_ENABLED_SMILES | MESSAGE_ENABLED_TAGS | BOARDTAGS_PURL_ENABLE | + BOARDTAGS_EXPAND_ENTER, &retflg) == 0) + { + st1 = st; + st = NULL; + } + + if(((ULogin.LU.right & USERRIGHT_POST_GLOBAL_ANNOUNCE) != 0 && ga[i].UIdFrom == + ULogin.LU.UniqID) || (ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) + { + sprintf(del, "" MESSAGEMAIN_globann_delannounce + " " MESSAGEMAIN_globann_updannounce + "", ga[i].Number, ga[i].Number); + } + else del[0] = 0; + + ConvertTime(ga[i].Date, date); + + if(!something_printed) { + if(!formstarted) printf("
"); + else printf(""); + } + + printf(DESIGN_GLOBALANN_FRAME, DESIGN_open_dl, st1, MESSAGEMAIN_globann_postedby, + uname, date, del, DESIGN_close_dl); + + if(st) free(st); + if(st1) free(st1); + something_printed = 1; + } + } + if(something_printed) { + printf("
" MESSAGEMAIN_globann_hidenewann "

", ga[cnt-1].Number); + } + else { + // show all announces + printf("
" MESSAGEMAIN_globann_showall "(%d)

", cnt); + // gap between welcome header and messages + if(formstarted) printf(""); + else printf(DESIGN_INDEX_WELCOME_CLOSE); + } + } + else { + // gap between welcome header and messages + if(formstarted) printf(""); + else printf(DESIGN_INDEX_WELCOME_CLOSE); + } + if(ga) free(ga); + } // of announces + + DWORD oldct = currenttopics; + + if(topicsoverride) { + if(topicsoverride > TOPICS_COUNT) currenttopics = 0xffffffff; // all + else currenttopics = (1<<(topicsoverride-1)); + } + DB.DB_PrintHtmlIndex(time(NULL), time(NULL), mtc); + currenttopics = oldct; + PrintBottomLines(HEADERSTRING_REG_USER_LIST | HEADERSTRING_POST_NEW_MESSAGE | HEADERSTRING_CONFIGURE | HEADERSTRING_ENABLE_RESETNEW, MAINPAGE_INDEX); + goto End_part; + } + + if(strncmp(deal, "read", 4) == 0) + { + /* security check */ + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) + { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"read=", 16, '&')) != NULL) + { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + DWORD x; + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || (x = DB.TranslateMsgIndex(tmp)) == NO_MESSAGE_CODE) + { + printnomessage(deal); + } + else + { + // read message + if(!ReadDBMessage(x, &mes)) printhtmlerror(); + + /* allow read invisible message only to SUPERUSER */ + if((mes.Flag & MESSAGE_IS_INVISIBLE) && ((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0)) { + printnomessage(deal); + } + else + { +#if STABLE_TITLE == 0 + // change title + char *an; + DWORD xtmp; + if(FilterBoardTags(mes.MessageHeader, &an, mes.SecHeader, + MAX_PARAMETERS_STRING, MESSAGE_ENABLED_TAGS | BOARDTAGS_CUT_TAGS, &xtmp) != 1) + { + an = (char*)&(mes.MessageHeader); + } + if (mes.Topics < TOPICS_COUNT && mes.Topics != 0 ){ + char *t; + t = (char*)malloc(strlen(an) + strlen(TITLE_divider) + strlen(Topics_List[mes.Topics]) + 4); + *t = 0; + strcat(t, Topics_List[mes.Topics]); + strcat(t, TITLE_divider); + strcat(t, an); + Tittle_cat(t); + free(t); + } else + Tittle_cat(an); + + if(an != (char*)&(mes.MessageHeader)) free(an); +#endif + // tmpxx contains vindex of parent message if thread is rolled. + // if some sub-thread is rolled, tmpxx contains vindex of MAIN parent of thread + + DWORD tmpxx; + if (mes.Flag & MESSAGE_COLLAPSED_THREAD && mes.Level > 0){ + SMessage parmes; + if(!ReadDBMessage(mes.ParentThread, &parmes)) printhtmlerror(); + tmpxx = parmes.ViIndex; + } + else tmpxx = tmp; + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_ENABLE_TO_MESSAGE | + ((currentdsm & 0x100) ? HEADERSTRING_ENABLE_REPLY_LINK : 0), tmpxx, tmp); + + PrintMessageThread(&DB, tmp, mes.Flag, mes.UniqUserID); + + /* allow post to closed message only to SUPERUSER and USER */ + if( (((mes.Flag & MESSAGE_IS_CLOSED) == 0 && + (ULogin.LU.right & USERRIGHT_CREATE_MESSAGE) ) || + (ULogin.LU.right & USERRIGHT_SUPERUSER) != 0 ) && + ((currentfm < MAX_DELTA_POST_MESSAGE) || + (tmp > (currentfm - MAX_DELTA_POST_MESSAGE)) || + (tmp == 0)) && ((currentdsm & 0x100) == 0)) + { + strcpy(mes.AuthorName, cookie_name); + mes.MessageHeader[0] = 0; + mesb = (char*)malloc(1); + *mesb = 0; + PrintMessageForm(&mes, mesb, tmp, ACTION_BUTTON_POST | ACTION_BUTTON_PREVIEW | ACTION_BUTTON_FAKEREPLY); + free(mesb); + } + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_ENABLE_TO_MESSAGE, tmpxx, tmp); + } + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "form", 4) == 0) + { + DWORD repnum = 0; + + // read form= parameter (if reply form is required) + if((st = strget(deal,"form=", 16, '&')) != NULL) + { + errno = 0; + char *ss; + repnum = strtol(st, &ss, 10); + DWORD x; + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + repnum < 1 || (x = DB.TranslateMsgIndex(repnum)) == NO_MESSAGE_CODE) + { + printnomessage(deal); + free(st); + goto End_part; + } + free(st); + } + + /* security check */ + if( (repnum && (ULogin.LU.right & USERRIGHT_CREATE_MESSAGE) == 0 ) || + ( !repnum && (ULogin.LU.right & USERRIGHT_CREATE_MESSAGE_THREAD) == 0) ){ + printaccessdenied(deal); + goto End_part; + } + + if(!repnum) Tittle_cat(TITLE_Form); + else Tittle_cat(TITLE_WriteReply); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + strcpy(mes.AuthorName, FilterHTMLTags(cookie_name, 1000, 0)); + mes.MessageHeader[0] = 0; + mesb = (char*)malloc(1); + *mesb = 0; + PrintMessageForm(&mes, mesb, repnum, + repnum ? ACTION_BUTTON_POST | ACTION_BUTTON_PREVIEW | ACTION_BUTTON_FAKEREPLY : + ACTION_BUTTON_POST | ACTION_BUTTON_PREVIEW); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } + + + if(strncmp(deal, "xpost", 5) == 0) { + char *ss = NULL; + char *passw, *mb, *c_host; + DWORD ROOT = 0; + DWORD CFlags = 0, LogMeIn = 0; + + // read method GET post params + if((ss = strget(deal, "xpost=", 16, '&')) != NULL ) { + errno = 0; + char *st; + ROOT = strtol(ss, &st, 10); + if((!(*ss != '\0' && *st == '\0')) || errno == ERANGE || + (ROOT != 0 && DB.TranslateMsgIndex(ROOT) == NO_MESSAGE_CODE)) { + printnomessage(deal); + goto End_part; + } + free(ss); + } + else { + printbadurl(deal); + goto End_part; + } + + // Check security rights + if(! ((ULogin.LU.right & USERRIGHT_CREATE_MESSAGE) && ROOT) && + !((ULogin.LU.right & USERRIGHT_CREATE_MESSAGE_THREAD) && ROOT == 0)) + { + printaccessdenied(deal); + goto End_part; + } + + + // make IP address + if ((tmp = getenv("HTTP_X_FORWARDED_FOR")) != NULL) print2log("proxy %s - %s", tmp, deal); + if(Nip != 1) { + /* // resolve + char*tmp; + // Exception! if forwareder for localhost or 127.0.0.1 - ignore forwarder + if((tmp = getenv("HTTP_X_FORWARDED_FOR")) != NULL && + strcmp(tmp, "127.0.0.1") != 0 && strcmp(tmp, "localhost") != 0 && + strncmp(tmp, "192.168", 7) != 0 && strncmp(tmp, "10.", 3) != 0) + { + // TODO: more detailed log here + print2log("proxy %s - %s", tmp, deal); + + // TODO: we need to resolve DNS here + strncpy(mes.HostName, tmp, HOST_NAME_LENGTH - 1); + mes.HostName[HOST_NAME_LENGTH - 1] = 0; + } else + */ + if(!IP2HostName(Nip, mes.HostName, HOST_NAME_LENGTH - 1)) + strcpy(mes.HostName, Cip); + } + else strcpy(mes.HostName, TAG_IP_NOT_DETECTED); + mes.IPAddr = Nip; + +#if HTTP_REFERER_CHECK == 1 + char *useragent = getenv("HTTP_USER_AGENT"); + if( + !useragent || + (strncmp(useragent, UA_LYNX, strlen(UA_LYNX)) && + strncmp(useragent, UA_LINKS, strlen(UA_LINKS))) + ) { + char *tts = getenv("HTTP_REFERER"); + if(tts == NULL || strstr(tts, ALLOWED_HTTP_REFERER) == NULL) { + // TODO: more detailed error here + print2log("bad referer, tts='%s'", tts); + printbadurl(deal); + goto End_part; + } + } +#endif + + // get parameters + par = GetParams(MAX_PARAMETERS_STRING); + + // read name + st = strget(par,"name=", AUTHOR_NAME_LENGTH - 1, '&'); + if(st == NULL) { + strcpy(mes.AuthorName, ""); + } + else { + strncpy(mes.AuthorName, st, AUTHOR_NAME_LENGTH - 1); + mes.AuthorName[AUTHOR_NAME_LENGTH - 1] = 0; + free(st); + } + + // read password + passw = strget(par,"pswd=", PROFILES_MAX_PASSWORD_LENGTH - 1, '&'); + + // read subject + st = strget(par,"subject=", MESSAGE_HEADER_LENGTH - 1, '&'); + if(st == NULL) { + strcpy(mes.MessageHeader, ""); + } + else { + strncpy(mes.MessageHeader, FilterWhitespaces(st), MESSAGE_HEADER_LENGTH - 1); + mes.MessageHeader[MESSAGE_HEADER_LENGTH - 1] = 0; + free(st); + } + + // read host (for edit) + c_host = strget(par,"host=", HOST_NAME_LENGTH - 1, '&'); + + // read msg body + mesb = strget(par,"body=", MAX_PARAMETERS_STRING, '&'); + // this is needed because of char #10 filtering. + // in WIN32 printf() works incorrectly with it +#if defined(WIN32) + FilterMessageForPreview(mesb, &mb); + free(mesb); + mesb = mb; +#endif + + // read dct (disable WWWConf Tags) + st = strget(par,"dct=", 10, '&'); + if(st != NULL) { + if(strcmp(st, "on") == 0) { + CFlags = CFlags | MSG_CHK_DISABLE_WWWCONF_TAGS; + } + free(st); + } + + // read dst (disable smile codes) + st = strget(par,"dst=", 10, '&'); + if(st != NULL) { + if(strcmp(st, "on") == 0) { + CFlags = CFlags | MSG_CHK_DISABLE_SMILE_CODES; + } + free(st); + } + + // read wen (acknol. by email) + st = strget(par,"wen=", 10, '&'); + if(st != NULL) { + // mail ackn. allowed ONLY for threads with ROOT == 0 + if(strcmp(st, "on") == 0 && ROOT == 0) { + CFlags = CFlags | MSG_CHK_ENABLE_EMAIL_ACKNL; + } + free(st); + } + + // read lmi (login me) + st = strget(par,"lmi=", 10, '&'); + if(st != NULL) { + if(strcmp(st, "on") == 0) { + LogMeIn = 1; + } + free(st); + } + + mes.Topics = 0; +#if TOPICS_SYSTEM_SUPPORT + { + char *ss; + DWORD topicID; + if((ss = strget(par, "topic=", 10, '&')) != NULL) { + errno = 0; + char *st; + topicID = strtol(ss, &st, 10); + if((!(*ss != '\0' && *st == '\0')) || errno == ERANGE || topicID > TOPICS_COUNT - 1) + { + // default topic + mes.Topics = TOPICS_DEFAULT_SELECTED; + } + mes.Topics = topicID; + free(ss); + } + } +#endif + + // get user action (post/edit/preview) + int action = getAction(par); + free(par); + + // init current error + int cr = 0; + switch(action) { + case ACTION_POST: + { + //************************************************* + // post message + //************************************************* + + // antispam + if(CheckPostfromIPValidity(Nip, POST_TIME_LIMIT) == 0) { +#if ENABLE_LOG + print2log(LOG_SPAM_TRY, Cip, deal); +#endif + Tittle_cat(TITLE_Spamtry); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_spamtry, MESSAGEMAIN_spamtry2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + if(passw) free(passw); + goto End_part; + } + + // do not allow posts to old threads + if ( ROOT > 0 && ((DB.VIndexCountInDB() - ROOT) > MAX_DELTA_POST_MESSAGE) ) { + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, ROOT); + PrintBoardError(MESSAGEMAIN_add_closed, MESSAGEMAIN_add_closed2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + if(passw) free(passw); + goto End_part; + + } + + mes.Date = time(NULL); // set current time + mes.MDate = (time_t)0; // haven't modified + char *banreason = NULL; + if((cr = DB.DB_InsertMessage(&mes, ROOT, strlen(mesb), &mesb, CFlags, passw, &banreason)) != MSG_CHK_ERROR_PASSED) + { + char *c_ActionResult1, *c_ActionResult2; + PrepareActionResult(cr, &c_ActionResult1, &c_ActionResult2); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, ROOT); + PrintBoardError(c_ActionResult1, c_ActionResult2, 0); + + if(cr == MSG_CHK_ERROR_BANNED && banreason) { + // print the reason if it exists + printf(DESIGN_BAN_REASON_STYLE, MESSAGEMAIN_BANNED_REASON, banreason); + } + if(banreason) free(banreason); + } + else { + // Mark that IP as already posted + CheckPostfromIPValidity(Nip, POST_TIME_LIMIT); + + // posted, set new cookie + cookie_name = (char*)realloc(cookie_name, AUTHOR_NAME_LENGTH); + strcpy(cookie_name, mes.AuthorName); + + + // + // Log in user if requested + // + if(LogMeIn && (passw != NULL && *passw != 0)) { + LogMeIn = 0; + /* if session already opened - close it */ + if(ULogin.LU.ID[0] != 0) + ULogin.CloseSession(ULogin.LU.ID); + + if(ULogin.OpenSession(mes.AuthorName, passw, NULL, Nip, 0) == 1) { + // entered, ok + LogMeIn = 1; + } + } + else LogMeIn = 0; + + // + // Check if message was posted to rolled thread than we should change ROOT to main root of thread + // + DWORD tmpxx; + if((mes.Flag & MESSAGE_COLLAPSED_THREAD)) { + SMessage parmes; + if(!ReadDBMessage(mes.ParentThread, &parmes)) printhtmlerror(); + tmpxx = parmes.ViIndex; + } + else tmpxx = mes.ViIndex; + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmpxx, ROOT); + if(LogMeIn) { + // if we have logged in also + PrintBoardError(MESSAGEMAIN_add_ok_login, MESSAGEMAIN_add_ok2, HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_THREAD, mes.ViIndex); + } + else PrintBoardError(MESSAGEMAIN_add_ok, MESSAGEMAIN_add_ok2, HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_THREAD, mes.ViIndex); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, tmpxx, ROOT); + + if(passw != NULL) free(passw); + + goto End_part; + } + } + break; + case ACTION_PREVIEW: + { + //********************************************** + // preview message + //********************************************** + DWORD rf; + SProfile_UserInfo UI; + + // + // set some fields of message + // + mes.ParentThread = NO_MESSAGE_CODE; + mes.Date = time(NULL); + mes.MDate = 0; + mes.ViIndex = 0; + + if(ULogin.LU.ID[0] != 0) { + memcpy(&UI, ULogin.pui, sizeof(UI)); + strcpy(mes.AuthorName, UI.username); + } + else { + /* default user */ + UI.secur = DEFAULT_NOBODY_SECURITY_BYTE; + UI.right = DEFAULT_NOBODY_RIGHT; + UI.secheader = DEFAULT_NOBODY_HDR_SEC_BYTE; + UI.UniqID = 0; + UI.username[0] = 0; + } + + if(UI.right & USERRIGTH_ALLOW_HTML) CFlags = CFlags | MSG_CHK_ALLOW_HTML; + mes.Security = UI.secur; + mes.SecHeader = UI.secheader; + mes.UniqUserID = UI.UniqID; + + char *banreason = NULL; + if((cr = CheckSpellingBan(&mes, &mesb, &banreason, CFlags, &rf)) != MSG_CHK_ERROR_PASSED) + { + char *c_ActionResult1, *c_ActionResult2; + PrepareActionResult(cr, &c_ActionResult1, &c_ActionResult2); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, ROOT); + PrintBoardError(c_ActionResult1, c_ActionResult2, 0); + + if(cr == MSG_CHK_ERROR_BANNED && banreason) { + // print the reason if it exists + printf(DESIGN_BAN_REASON_STYLE, MESSAGEMAIN_BANNED_REASON, banreason); + } + } + if(banreason) free(banreason); + + mes.Flag = rf; + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + printf(DESIGN_PREVIEW_PREVIEWMESSAGE, MESSAGEHEAD_preview_preview_message); + + // fix message body size for print preview + mes.msize = 1; // any constant greater than zero + + DB.PrintHtmlMessageBody(&mes, mesb); + + printf(DESIGN_PREVIEW_CHANGEMESSAGE, MESSAGEHEAD_preview_change_message); + + PrintMessageForm(&mes, mesb, ROOT, ACTION_BUTTON_POST | ACTION_BUTTON_PREVIEW, CFlags); + free(mesb); + } + break; + case ACTION_EDIT: + { + SMessage msg; + SProfile_UserInfo UI; + free(st); + + // + // Read the message cause we'll need some parts of it + // + if(!ReadDBMessage(DB.TranslateMsgIndex(ROOT), &msg)) printhtmlerror(); + + // we should leave current time intact and modify only modified + msg.MDate = time(NULL); // have been modified + + strcpy(msg.MessageHeader, mes.MessageHeader); + strcpy(msg.AuthorName, mes.AuthorName); + strcpy(msg.HostName, mes.HostName); + if((ULogin.pui->right & USERRIGHT_SUPERUSER) && c_host && c_host[0] != 0) { + strcpy(msg.HostName, c_host); + msg.HostName[HOST_NAME_LENGTH - 1] = 0; + } + msg.IPAddr = Nip; + + // Check security rights + if(ULogin.LU.ID[0] == 0 || ( + !(ULogin.pui->right & USERRIGHT_SUPERUSER) && + (ULogin.pui->UniqID != msg.UniqUserID) + ) + ) { + if(passw) free(passw); + printaccessdenied(deal); + goto End_part; + } + if((ULogin.pui->right & USERRIGHT_SUPERUSER)) + { + CProfiles *uprof = new CProfiles(); + if(uprof->errnum != PROFILE_RETURN_ALLOK) { +#if ENABLE_LOG >= 1 + print2log("Error working with profiles database (init)"); +#endif + printhtmlerror(); + } + // if user does not exist - it should be unreg + if(uprof->GetUserByName(mes.AuthorName, &UI, NULL, NULL) != PROFILE_RETURN_ALLOK) + msg.UniqUserID = 0; + delete uprof; + } + else { + strcpy(msg.AuthorName, ULogin.pui->username); + } + + char *banreason; + if((cr = DB.DB_ChangeMessage(ROOT, &msg, // what message + &mesb, strlen(mesb), CFlags, &banreason)) != MSG_CHK_ERROR_PASSED) + { + char *c_ActionResult1, *c_ActionResult2; + PrepareActionResult(cr, &c_ActionResult1, &c_ActionResult2); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, ROOT); + PrintBoardError(c_ActionResult1, c_ActionResult2, 0); + + if(cr == MSG_CHK_ERROR_BANNED && banreason) { + // print the reason if it exists + printf(DESIGN_BAN_REASON_STYLE, MESSAGEMAIN_BANNED_REASON, banreason); + } + } + else { + // posted, set new cookie + cookie_name = (char*)realloc(cookie_name, AUTHOR_NAME_LENGTH); + strcpy(cookie_name, mes.AuthorName); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + ROOT); + PrintBoardError(MESSAGEMAIN_add_ok, MESSAGEMAIN_add_ok2, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + } + } + break; + default: + { +#if ENABLE_LOG > 1 + print2log("Unknown parameter during message post, st = %s", st); +#endif + if(st) free(st); + if(passw) free(passw); + goto End_URLerror; + } + }// switch(action) + if(passw) free(passw); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, ROOT); + goto End_part; + } + + + if(strncmp(deal, "configure", 9) == 0) { + st = NULL; + if((st = strget(deal,"configure=", 16, '&')) != NULL) { + if(strcmp(st, "action") == 0) { + free(st); + // get parameters + par = GetParams(MAX_PARAMETERS_STRING); + + currentss = CONFIGURE_SETTING_DEFAULT_ss; + currenttt = CONFIGURE_SETTING_DEFAULT_tt; + currenttv = CONFIGURE_SETTING_DEFAULT_tv; + currenttc = CONFIGURE_SETTING_DEFAULT_tc; + currentlsel = CONFIGURE_SETTING_DEFAULT_lsel; + currentdsm = CONFIGURE_SETTING_DEFAULT_dsm; + currenttz = DATETIME_DEFAULT_TIMEZONE; + + if(par != NULL) { + char *st, *ss; + DWORD tmp; + +#define READ_PARAM_MASK(param, var, mask) { \ + char *ss = strget(par, param, 20, '&'); \ + if(ss != NULL) { \ + if(strcmp(ss, "1") == 0) { \ + var |= mask; \ + } \ + else { \ + var &= (~mask); \ + } \ + free(ss); \ + } \ + else var &= (~mask); \ +} + + // read disable smiles + READ_PARAM_MASK("dsm=", currentdsm, 0x01); + // read dup (disable upper picture) + READ_PARAM_MASK("dup=", currentdsm, 0x02); + // read dul (disable second link bar) + READ_PARAM_MASK("dul=", currentdsm, 0x04); + // read onh (disable own nick highlighing) + READ_PARAM_MASK("onh=", currentdsm, 0x08); + // read plu (enable + acting like an href) + READ_PARAM_MASK("plu=", currentdsm, 0x10); + // read host (disable host displaying) + READ_PARAM_MASK("host=", currentdsm, 0x20); + // read alt nick displaying + READ_PARAM_MASK("nalt=", currentdsm, 0x40); + // read signature disable + READ_PARAM_MASK("dsig=", currentdsm, 0x80); + // read show reply form + READ_PARAM_MASK("shrp=", currentdsm, 0x100); + +#define READ_PARAM_NUM(param, var, vardefault) {\ + char *ss = strget(par, param, 20, '&'); \ + if(ss != NULL) { \ + DWORD tmp = strtol(ss, &st, 10); \ + if(((!(*ss != '\0' && *st == '\0')) \ + || errno == ERANGE)) { \ + var = vardefault; \ + } \ + else { \ + var = tmp; \ + } \ + free(ss); \ + } \ + else var = vardefault; \ +} + + // read lsel (show type selection) + READ_PARAM_NUM("lsel=", currentlsel, CONFIGURE_SETTING_DEFAULT_lsel); + if(currentlsel != 1 && currentlsel != 2) + currentlsel = CONFIGURE_SETTING_DEFAULT_lsel; + // read tc (time count) + READ_PARAM_NUM("tc=", currenttc, CONFIGURE_SETTING_DEFAULT_tc); + if(currenttc <= 0) + currenttc = CONFIGURE_SETTING_DEFAULT_tc; + // read tv (thread value) + READ_PARAM_NUM("tv=", currenttv, CONFIGURE_SETTING_DEFAULT_tv); + if(currenttv <= 0) + currenttv = CONFIGURE_SETTING_DEFAULT_tv; + // read tt (read time type) + READ_PARAM_NUM("tt=", currenttt, CONFIGURE_SETTING_DEFAULT_tt); + if(currenttt < 1 || currenttt > 4) + currenttt = CONFIGURE_SETTING_DEFAULT_tt; + // read ss (read time type) + READ_PARAM_NUM("ss=", currentss, CONFIGURE_SETTING_DEFAULT_ss); + if(currentss < 1 || currentss > 4) + currentss = CONFIGURE_SETTING_DEFAULT_ss; + READ_PARAM_NUM("tz=", currenttz, DATETIME_DEFAULT_TIMEZONE); + if(currenttz < -12 || currenttz > 12) + currenttz = DATETIME_DEFAULT_TIMEZONE; + +#if TOPICS_SYSTEM_SUPPORT + // read topics that should be displayed + { + currenttopics = 0; + DWORD i; + for(i = 0; i < TOPICS_COUNT; i++) + { + char st[30]; + sprintf(st, "topic%d=", i); + if((ss = strget(par, st, 3, '&')) != NULL) + { + if(strcmp(ss, "on") == 0) + { + currenttopics |= (1<Flags & PROFILES_FLAG_VIEW_SETTINGS) ){ + + ULogin.pui->vs.dsm = currentdsm; + ULogin.pui->vs.topics = currenttopics; + ULogin.pui->vs.tv = currenttv; + ULogin.pui->vs.tc = currenttc; + ULogin.pui->vs.ss = currentss; + ULogin.pui->vs.lsel = currentlsel; + ULogin.pui->vs.tt = currenttt; + ULogin.pui->vs.tz = currenttz; + + CProfiles *uprof; + uprof = new CProfiles(); + uprof->ModifyUser(ULogin.pui, NULL, NULL); + delete uprof; + } + else{ + // settings are not in profile. so new values should be in cookies + cookie_lsel = currentlsel; + cookie_tc = currenttc; + cookie_tt = currenttt; + cookie_tv = currenttv; + cookie_ss = currentss; + cookie_dsm = currentdsm; + cookie_topics = currenttopics; + cookie_tz = currenttz; + } + + } + free(par); + + + // + // Redirect user to the index page + // + PrintHTMLHeader(HEADERSTRING_REDIRECT_NOW | HEADERSTRING_NO_CACHE_THIS, MAINPAGE_INDEX); + + goto End_part; + } + free(st); + + Tittle_cat(TITLE_Configure); + + /* print configuration form */ + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintConfig(); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + /****************************/ + } + goto End_part; + } + + if(strncmp(deal, "login", 5) == 0) { + st = NULL; + if((st = strget(deal,"login=", 16, '&')) != NULL) { + + if(strcmp(st, "action") == 0) { + free(st); + // check for User name and password + // get parameters + par = GetParams(MAX_PARAMETERS_STRING); + + /***************************************/ + int disableipcheck = 0; + char *ipchk; + if((ipchk = strget(par, "ipoff=", 10, '&')) != NULL) { + if(strcmp(ipchk, "1") == 0) { + disableipcheck = 1; + } + free(ipchk); + } + st = strget(par,"mname=", PROFILES_MAX_USERNAME_LENGTH - 1, '&'); + if(st != NULL) { + char *ss; + ss = strget(par,"mpswd=", PROFILES_MAX_PASSWORD_LENGTH - 1, '&'); + if(ss != NULL) { + /* if session already opened - close it */ + if(ULogin.LU.ID[0] != 0) + ULogin.CloseSession(ULogin.LU.ID); + + if(ULogin.OpenSession(st, ss, NULL, Nip, disableipcheck) == 1) { + print2log("User '%s' was logged in (%s)", ULogin.pui->username, getenv(REMOTE_ADDR)); + + // Prepare conference login greetings + char boardgreet[1000]; + char *greetnames[4] = { + MESSAGEMAIN_login_helloday, + MESSAGEMAIN_login_helloevn, + MESSAGEMAIN_login_hellonight, + MESSAGEMAIN_login_hellomor + }; + int cur = 2; + time_t tt = time(NULL); + tm *x = localtime(&tt); + if(x->tm_hour >= 6 && x->tm_hour < 10) cur = 3; + if(x->tm_hour >= 10 && x->tm_hour < 18) cur = 0; + if(x->tm_hour >= 18 && x->tm_hour < 22) cur = 1; + sprintf(boardgreet, MESSAGEMAIN_login_ok, greetnames[cur], ULogin.pui->username); + + + Tittle_cat(TITLE_Login); + + // entered, set new cookie + cookie_name = (char*)realloc(cookie_name, AUTHOR_NAME_LENGTH); + strcpy(cookie_name, st); + + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(boardgreet, MESSAGEMAIN_login_ok2, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + + free(ss); + free(st); + goto End_part; + } + free(ss); + } + free(st); + } + + printpassworderror(deal); + goto End_part; + } + + if(strcmp(st, "lostpasswform") == 0) { + free(st); + + Tittle_cat(TITLE_LostPassword); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN, MAINPAGE_INDEX); + printf(DESIGN_LOSTPASSW_HEADER, MESSAGEMAIN_lostpassw_header); + PrintLostPasswordForm(); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN, MAINPAGE_INDEX); + + goto End_part; + } + + if(strcmp(st, "lostpasswaction") == 0) { + free(st); + + // check for User name and email address + // get parameters + par = GetParams(MAX_PARAMETERS_STRING); + + /***************************************/ + st = strget(par,"mname=", PROFILES_MAX_USERNAME_LENGTH - 1, '&'); + if(st != NULL) { + char *ss; + ss = strget(par,"memail=", PROFILES_FULL_USERINFO_MAX_EMAIL - 1, '&'); + if(ss != NULL) { + CProfiles uprof; + SProfile_FullUserInfo Fui; + SProfile_UserInfo ui; + if(uprof.GetUserByName(st, &ui, &Fui, NULL) == PROFILE_RETURN_ALLOK) { + if(strcmp(Fui.Email, ss) == 0) { + // + // We should send password to the user + // + + Tittle_cat(TITLE_PasswordSent); + + // + // Send email + // + { + char subj[1000], bdy[10000]; + + sprintf(subj, MAILACKN_LOSTPASS_SUBJECT, st); + + sprintf(bdy, MAILACKN_LOSTPASS_BODY, st, ui.password); + //print2log("will send message now %s", bdy); + wcSendMail(Fui.Email, subj, bdy); + + print2log("Password was sent to %s", Fui.Email); + } + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_lostpassw_ok, MESSAGEMAIN_lostpassw_ok2, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + + free(ss); + free(st); + goto End_part; + } + } + } + } + + Tittle_cat(TITLE_LostPassword); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN, MAINPAGE_INDEX); + printf(DESIGN_LOSTPASSW_HEADER, MESSAGEMAIN_lostpassw_hretry); + PrintLostPasswordForm(); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN, MAINPAGE_INDEX); + + goto End_part; + } + + if(strcmp(st, "logoff") == 0) { + free(st); + + if(ULogin.LU.ID[0] == 0) { + /* not logged yet */ + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_logoff_not_logged_in, MESSAGEMAIN_logoff_not_logged_in2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } + + print2log("User '%s' was logged out (%s)", ULogin.pui->username, getenv(REMOTE_ADDR)); + + /* close sequence */ + ULogin.CloseSession(ULogin.LU.ID); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + + PrintBoardError(MESSAGEMAIN_logoff_ok, MESSAGEMAIN_logoff_ok, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } + free(st); + } + + Tittle_cat(TITLE_Login); + + /******* print login form *******/ + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN, MAINPAGE_INDEX); + printf(DESIGN_MODERATOR_ENTER_HEADER, MESSAGEMAIN_login_login_header); + PrintLoginForm(); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_LOGIN, MAINPAGE_INDEX); + /********************************/ + goto End_part; + } + + if(strncmp(deal, "close", 5) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_CLOSE_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"close=", 16, '&')) != NULL) { + char *ss; + DWORD midx; + errno = 0; + DWORD tmp = strtol(st, &ss, 10); + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || ((midx = DB.TranslateMsgIndex(tmp)) == NO_MESSAGE_CODE) ) { + printnomessage(deal); + } + else { + /* Security check for own message or USERRIGHT_SUPERUSER */ + + /******** read message ********/ + if(!ReadDBMessage(midx, &mes)) printhtmlerror(); + /* closing by author allowed in main thread only ! */ + if(ULogin.LU.ID[0] != 0 && ((mes.UniqUserID == ULogin.LU.UniqID && mes.Level == 0) || (ULogin.LU.right & USERRIGHT_SUPERUSER))) { + + Tittle_cat(TITLE_ClosingMessage); + + DB.DB_ChangeCloseThread(tmp, 1); + print2log("Message %d (%s (by %s)) was closed by %s", tmp, mes.MessageHeader, mes.AuthorName, ULogin.pui->username); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + PrintBoardError(MESSAGEMAIN_threadwasclosed, MESSAGEMAIN_threadwasclosed2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + } + else printaccessdenied(deal); + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + + if(strncmp(deal, "hide", 4) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"hide=", 16, '&')) != NULL) { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || DB.TranslateMsgIndex(tmp) == NO_MESSAGE_CODE) { + printnomessage(deal); + } + else { + DB.DB_ChangeInvisibilityThreadFlag(tmp, 1); + if(!ReadDBMessage(DB.TranslateMsgIndex(tmp), &mes)) printhtmlerror(); + print2log("Message %d (%s (by %s)) was hided by %s", tmp, mes.MessageHeader, mes.AuthorName, ULogin.pui->username); + + Tittle_cat(TITLE_HidingMessage); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + PrintBoardError(MESSAGEMAIN_threadchangehided, MESSAGEMAIN_threadchangehided2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + + if(strncmp(deal, "unhide", 6) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"unhide=", 16, '&')) != NULL) { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || DB.TranslateMsgIndex(tmp) == NO_MESSAGE_CODE) { + printnomessage(deal); + } + else { + Tittle_cat(TITLE_HidingMessage); + + DB.DB_ChangeInvisibilityThreadFlag(tmp, 0); + if(!ReadDBMessage(DB.TranslateMsgIndex(tmp), &mes)) printhtmlerror(); + print2log("Message %d (%s (by %s)) was unhided by %s", tmp, mes.MessageHeader, mes.AuthorName, ULogin.pui->username); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + PrintBoardError(MESSAGEMAIN_threadchangehided, MESSAGEMAIN_threadchangehided2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "unclose", 7) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_OPEN_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"unclose=", 16, '&')) != NULL) { + char *ss; + DWORD midx; + errno = 0; + DWORD tmp = strtol(st, &ss, 10); + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || ((midx = DB.TranslateMsgIndex(tmp)) == NO_MESSAGE_CODE) ) { + printnomessage(deal); + } + else { + /* Security check for own message or USERRIGHT_SUPERUSER */ + + /******** read message ********/ + if(!ReadDBMessage(midx, &mes)) printhtmlerror(); + if(ULogin.LU.ID[0] != 0 && (mes.UniqUserID == ULogin.LU.UniqID || (ULogin.LU.right & USERRIGHT_SUPERUSER))) { + + Tittle_cat(TITLE_ClosingMessage); + + DB.DB_ChangeCloseThread(tmp, 0); + if(!ReadDBMessage(DB.TranslateMsgIndex(tmp), &mes)) printhtmlerror(); + print2log("Message %d (%s (by %s)) was opened by %s", tmp, mes.MessageHeader, mes.AuthorName, ULogin.pui->username); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + PrintBoardError(MESSAGEMAIN_threadwasclosed, MESSAGEMAIN_threadwasclosed2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | + HEADERSTRING_DISABLE_FAQHELP, tmp); + } + else printaccessdenied(deal); + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "roll", 4) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"roll=", 16, '&')) != NULL) { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || DB.TranslateMsgIndex(tmp) == NO_MESSAGE_CODE) { + printnomessage(deal); + } + else { + + Tittle_cat(TITLE_RollMessage); + + DB.DB_ChangeRollThreadFlag(tmp); + if(!ReadDBMessage(DB.TranslateMsgIndex(tmp), &mes)) printhtmlerror(); + print2log("Message %d (%s (by %s)) was (un)rolled by %s", tmp, mes.MessageHeader, mes.AuthorName, ULogin.pui->username); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + tmp); + PrintBoardError(MESSAGEMAIN_threadrolled, MESSAGEMAIN_threadrolled2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + tmp); + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "delmsg", 6) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"delmsg=", 16, '&')) != NULL) { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + + if((!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || DB.TranslateMsgIndex(tmp) == NO_MESSAGE_CODE) { + printnomessage(deal); + } + else { + + Tittle_cat(TITLE_DeletingMessage); + + if(!ReadDBMessage(DB.TranslateMsgIndex(tmp), &mes)) printhtmlerror(); + print2log("Message %d (%s (by %s)) was deleted by %s", tmp, mes.MessageHeader, mes.AuthorName, ULogin.pui->username); + DB.DB_DeleteMessages(tmp); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, tmp); + PrintBoardError(MESSAGEMAIN_threaddeleted, MESSAGEMAIN_threaddeleted2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, + tmp); + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "changemsg", 9) == 0) { + // precheck security + if((ULogin.LU.right & USERRIGHT_MODIFY_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"changemsg=", 16, '&')) != NULL) { + errno = 0; + char *ss; + DWORD tmp = strtol(st, &ss, 10); + DWORD midx; + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || + tmp < 1 || ((midx = DB.TranslateMsgIndex(tmp)) == NO_MESSAGE_CODE)) { + printnomessage(deal); + } + else { + // + // read message + // + if(!ReadDBMessage(midx, &mes)) printhtmlerror(); + + // + // security check + // + if(!( (ULogin.LU.right & USERRIGHT_SUPERUSER) || ( // admin ? + ((mes.Flag & MESSAGE_IS_INVISIBLE) == 0) && // not hided + ((mes.Flag & MESSAGE_IS_CLOSED) == 0) && // and not closed + (ULogin.LU.right & USERRIGHT_MODIFY_MESSAGE) && // can modify? + (mes.UniqUserID == ULogin.LU.UniqID) ) // message posted by this user + )) + { + Tittle_cat(TITLE_Error); + printaccessdenied(deal); + } + else { +#if STABLE_TITLE == 0 + // set title - change title to change message + ConfTitle = (char*)realloc(ConfTitle, strlen(ConfTitle) + strlen(TITLE_divider) + strlen(TITLE_ChangingMessage) + strlen(mes.MessageHeader) + 6); + strcat(ConfTitle, TITLE_divider); + strcat(ConfTitle, TITLE_ChangingMessage); + strcat(ConfTitle, " - "); + strcat(ConfTitle, mes.MessageHeader); +#endif + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, tmp); + + PrintMessageThread(&DB, tmp, mes.Flag, mes.UniqUserID); + + char *mesb = (char*)malloc(mes.msize + 1); + mesb[0] = 0; + + // + // Read message body + // + if(!ReadDBMessageBody(mesb, mes.MIndex, mes.msize)) + printhtmlerrorat(LOG_UNABLETOLOCATEFILE, F_MSGBODY); + + PrintMessageForm(&mes, mesb, tmp, ACTION_BUTTON_EDIT); + + free(mesb); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, tmp); + } + } + free(st); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "help", 4) == 0) { + + Tittle_cat(TITLE_HelpPage); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, MAINPAGE_INDEX); + + PrintFAQForm(); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, MAINPAGE_INDEX); + goto End_part; + } + + if(strncmp(deal, "uinfo", 5) == 0) { + char *name; + if((name = strget(deal,"uinfo=", PROFILES_MAX_USERNAME_LENGTH, '&')) != NULL) { +#if STABLE_TITLE == 0 + ConfTitle = (char*)realloc(ConfTitle, strlen(ConfTitle) + 2*strlen(TITLE_divider) + strlen(TITLE_ProfileInfo) + strlen(name) + 1); + strcat(ConfTitle, TITLE_divider); + strcat(ConfTitle, TITLE_ProfileInfo); + strcat(ConfTitle, TITLE_divider); + strcat(ConfTitle, name); +#endif + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL, 0); + + PrintAboutUserInfo(name); + + PrintBottomLines(HEADERSTRING_DISABLE_ALL, 0); + free(name); + } + else goto End_URLerror; + goto End_part; + } + + if(strncmp(deal, "searchword", 10) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + + char *ss; + DWORD start = 0; + if((ss = strget(deal,"searchword=", 255 - 1, '&')) != NULL) { + if((st = strget(deal,"start=", 60, '&')) != NULL) { + errno = 0; + char *ss; + start = strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || tmp == 0) { + start = 1; + } + free(st); + } + else start = 1; + + if(strlen(ss) > 0) { + Tittle_cat(TITLE_Search); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX | HEADERSTRING_NO_CACHE_THIS); + PrintSearchForm(ss, &DB); + if(strlen(ss) >= SEARCHER_MIN_WORD) { + CMessageSearcher *ms = new CMessageSearcher(SEARCHER_INDEX_CREATE_EXISTING); + if(ms->errnum == SEARCHER_RETURN_ALLOK) { + DWORD c; + DWORD *vmsg = ms->SearchMessagesByPattern(ss, &c); + printf(DESIGN_SEARCH_SEARCH_STR_WAS, MESSAGEMAIN_search_search_str, ms->srch_str); + if(c != 0) { + // print count of found messages + printf(DESIGN_SEARCH_RESULT, MESSAGEMAIN_search_result1, c, MESSAGEMAIN_search_result2); + } + else { + // Nothing have been found + printf(DESIGN_SEARCH_NO_RESULT, MESSAGEMAIN_search_result1, MESSAGEMAIN_search_result_nothing); + } + + // Check and adjust start + if(c <= (start-1)*SEARCH_MES_PER_PAGE_COUNT) { + start = c/SEARCH_MES_PER_PAGE_COUNT + 1; + } + + DWORD oldc = c; + if(c > SEARCH_MES_PER_PAGE_COUNT) { + char *wrd = CodeHttpString(ss, 0); + if(wrd) { + printf("
" MESSAGEMAIN_search_result_pages); + int max = (c/SEARCH_MES_PER_PAGE_COUNT) + + (((c % SEARCH_MES_PER_PAGE_COUNT) == 0)? 0: 1); + for(int i = 0; i < max; i++) { + if(i > 0 && (i % 20) == 0) printf("
"); + if(i != start - 1) printf(" %d ", wrd, i+1, i+1); + else printf(" %d ", i+1); + } + printf("
"); + } + } + + if(c - (start-1)*SEARCH_MES_PER_PAGE_COUNT > SEARCH_MES_PER_PAGE_COUNT) c = SEARCH_MES_PER_PAGE_COUNT; + else c = c - (start-1)*SEARCH_MES_PER_PAGE_COUNT; + DB.PrintHtmlMessageBufferByVI(vmsg + (start-1)*SEARCH_MES_PER_PAGE_COUNT, c); + free(vmsg); + + c = oldc; + if(c > SEARCH_MES_PER_PAGE_COUNT) { + char *wrd = CodeHttpString(ss, 0); + if(wrd) { + printf("
" MESSAGEMAIN_search_result_pages); + int max = (c/SEARCH_MES_PER_PAGE_COUNT) + + (((c % SEARCH_MES_PER_PAGE_COUNT) == 0)? 0: 1); + for(int i = 0; i < max; i++) { + if(i > 0 && (i % 20 == 0)) printf("
"); + if(i != start - 1) printf(" %d ", wrd, i+1, i+1); + else printf(" %d ", i+1); + } + printf("
"); + } + } + } + else { + // Write that searcher have not been configured properly + } + delete ms; + } + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + free(ss); + goto End_part; + } + } + + Tittle_cat(TITLE_Search); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + + PrintSearchForm("", &DB, 1); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + + goto End_part; + } + + if(strncmp(deal, "search", 6) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + + if((st = strget(deal,"search=", 60, '&')) != NULL) { + if(strcmp(st, "action") == 0) { + free(st); + + /* get "method post" parameters */ + par = GetParams(MAX_PARAMETERS_STRING); + if(par != NULL) { + char *ss; + /* read search pattern */ + ss = strget(par, "find=", 255 - 1, '&'); + if(ss == NULL) { + ss = (char*)malloc(1); + ss[0] = 0; + } + + Tittle_cat(TITLE_Search); + +#if ENABLE_LOG == 2 + print2log("Search from %s, query=%s", getenv(REMOTE_ADDR), ss); +#endif + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + PrintSearchForm(ss, &DB); + if(strlen(ss) >= SEARCHER_MIN_WORD) { + CMessageSearcher *ms = new CMessageSearcher(SEARCHER_INDEX_CREATE_EXISTING); + if(ms->errnum == SEARCHER_RETURN_ALLOK) { + DWORD c; + DWORD *vmsg = ms->SearchMessagesByPattern(ss, &c); + printf(DESIGN_SEARCH_SEARCH_STR_WAS, MESSAGEMAIN_search_search_str, ms->srch_str); + if(c != 0) { + // print count of found messages + printf(DESIGN_SEARCH_RESULT, MESSAGEMAIN_search_result1, c, MESSAGEMAIN_search_result2); + } + else { + // Nothing have been found + printf(DESIGN_SEARCH_NO_RESULT, MESSAGEMAIN_search_result1, MESSAGEMAIN_search_result_nothing); + } + if(c > SEARCH_MES_PER_PAGE_COUNT) { + char *wrd = CodeHttpString(ss, 0); + if(wrd) { + printf("
" MESSAGEMAIN_search_result_pages); + int max = (c/SEARCH_MES_PER_PAGE_COUNT) + + (((c % SEARCH_MES_PER_PAGE_COUNT) == 0)? 0: 1); + for(int i = 0; i < max; i++) { + if(i > 0 && (i % 20 == 0)) printf("
"); + if(i != 0) printf(" %d ", wrd, i+1, i+1); + else printf(" %d ", i+1); + } + printf("
"); + } + } + DWORD oldc = c; + if(c > 0) { + if( c > SEARCH_MES_PER_PAGE_COUNT) c = SEARCH_MES_PER_PAGE_COUNT; + DB.PrintHtmlMessageBufferByVI(vmsg, c); + free(vmsg); + } + c = oldc; + if(c > SEARCH_MES_PER_PAGE_COUNT) { + char *wrd = CodeHttpString(ss, 0); + if(wrd) { + printf("
" MESSAGEMAIN_search_result_pages); + int max = (c/SEARCH_MES_PER_PAGE_COUNT) + + (((c % SEARCH_MES_PER_PAGE_COUNT) == 0)? 0: 1); + for(int i = 0; i < max; i++) { + if(i > 0 && (i % 20 == 0)) printf("
"); + if(i != 0) printf(" %d ", wrd, i+1, i+1); + else printf(" %d ", i+1); + } + printf("
"); + } + } + } + else { + // Write that searcher have not been configured properly + } + delete ms; + } + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + free(ss); + goto End_part; + } + else goto End_URLerror; + } + free(st); + } + + Tittle_cat(TITLE_Search); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + + PrintSearchForm("", &DB, 1); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_SEARCH, MAINPAGE_INDEX); + + goto End_part; + } + + if(strncmp(deal, "changeusr=", 8) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + if((st = strget(deal,"changeusr=", 30, '&')) != NULL) { + if(strcmp(st, "action") == 0) { + free(st); + + // here we do it :) + // get parameters + par = GetParams(MAX_PARAMETERS_STRING); + if(par !=NULL) { + BYTE sechdr, secbdy, ustat; + DWORD right = 0; + char *name; + + /* security byte header */ + if((st = strget(par, "sechdr=", 10, '&')) != NULL) { + errno = 0; + char *ss; + sechdr = (BYTE)strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE) { + sechdr = 255; + } + free(st); + } + else sechdr = 255; + + /* name */ + name = strget(par, "name=", PROFILES_MAX_USERNAME_LENGTH - 1, '&'); + + /* security byte body */ + if((st = strget(par, "secbdy=", 10, '&')) != NULL) { + errno = 0; + char *ss; + secbdy = (BYTE)strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE) { + secbdy = 255; + } + free(st); + } + else secbdy = 255; + + /* ustat */ + if((st = strget(par, "ustat=", 10, '&')) != NULL) { + errno = 0; + char *ss; + ustat = (BYTE)strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || ustat >= USER_STATUS_COUNT) { + ustat = 0; + } + free(st); + } + else ustat = 0; + + // read the right + { + DWORD i; + char *ss; + right = 0; + for(i = 0; i < USERRIGHT_COUNT; i++) + { + char st[30]; + sprintf(st, "right%d=", i); + if((ss = strget(par, st, 4, '&')) != NULL) + { + if(strcmp(ss, "on") == 0) + { + right |= (1<GetUserByName(name, &ui, &fui, &idx); + if(err == PROFILE_RETURN_ALLOK) { + int altnupd = 0; + // delete alt name if required + if(((ui.right & USERRIGHT_SUPERUSER) != 0 || + (ui.right & USERRIGHT_ALT_DISPLAY_NAME) != 0) && + ((right & USERRIGHT_ALT_DISPLAY_NAME) == 0 && + (right & USERRIGHT_SUPERUSER) == 0) + ) + { + ui.Flags &= (~PROFILES_FLAG_ALT_DISPLAY_NAME); + altnupd = 1; + } + + ui.secur = secbdy; + ui.secheader = sechdr; + ui.Status = ustat; + ui.right = right; + + if(uprof->SetUInfo(idx, &ui)) { + if(altnupd) AltNames.DeleteAltName(ui.UniqID); + updated = 1; + } + } + if(uprof) delete uprof; + } + + // + // Write complete message + // + if(updated) { + Tittle_cat(TITLE_Registration); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_register_edit_ex, MESSAGEMAIN_register_edit_ex2, + HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, + MAINPAGE_INDEX); + + // log this task + print2log("User %s was updated by %s", name, ULogin.pui->username); + } + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_register_edit_err, MESSAGEMAIN_register_edit_err2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + + free(par); + goto End_part; + } + else goto End_URLerror; + } + free(st); + } + + goto End_URLerror; + } + + if(strncmp(deal, "register", 8) == 0) { + /* security check */ + if((ULogin.LU.right & USERRIGTH_PROFILE_CREATE) == 0) { + printaccessdenied(deal); + goto End_part; + } + // We do not need to check security there, this action due to be done lately in DoCheckAndCreateProfile() + if((st = strget(deal,"register=", 30, '&')) != NULL) { + if(strcmp(st, "action") == 0) { + free(st); + SProfile_FullUserInfo fui; + SProfile_UserInfo ui; + + /****** set default user creation parameters ******/ + ui.Flags = 0; // don't have picture or signature + ui.right = DEFAULT_USER_RIGHT; + ui.secur = DEFAULT_USER_SECURITY_BYTE; + ui.secheader = DEFAULT_USER_HDR_SEC_BYTE; + /**************************************************/ + + /* get parameters */ + par = GetParams(MAX_PARAMETERS_STRING); + if(par !=NULL) { + char *ss, *passwdconfirm, *oldpasswd, *act, *mb; + + /* what we should do: edit, delete or create */ + act = strget(par, "register=", 255, '&'); + if(act == NULL) { + // default action - register + act = (char*)malloc(100); + strcpy(act, MESSAGEMAIN_register_register); + } + + /* read login name (username) and load user profile if update */ + ss = strget(par, "login=", PROFILES_MAX_USERNAME_LENGTH - 1, '&'); + if(ss != NULL) { + strcpy(ui.username, ss); + free(ss); + } + else { + if(ULogin.LU.ID[0] != 0) + strcpy(ui.username, ULogin.pui->username); + else ui.username[0] = 0; + } + /* if edit - load current settings */ + if(strcmp(act, MESSAGEMAIN_register_edit) == 0 && ui.username[0] != 0) { + CProfiles *cp = new CProfiles(); + cp->GetUserByName(ui.username, &ui, &fui, NULL); + delete cp; + } + + // Read alternative display name for user + ss = strget(par, "dispnm=", PROFILES_MAX_ALT_DISPLAY_NAME - 1, '&'); + if(ss != NULL) { + strcpy(ui.altdisplayname, ss); + free(ss); + } + else ui.altdisplayname[0] = 0; + + /* read password 1 */ + ss = strget(par, "pswd1=", PROFILES_MAX_PASSWORD_LENGTH - 1, '&'); + if(ss != NULL) { + strcpy(ui.password, ss); + free(ss); + } + else ui.password[0] = 0; + + /* read password 2 */ + passwdconfirm = strget(par, "pswd2=", PROFILES_MAX_PASSWORD_LENGTH - 1, '&'); + if(!passwdconfirm) + { + passwdconfirm = (char*)malloc(2); + passwdconfirm[0] = 0; + } + + /* read old password */ + oldpasswd = strget(par, "opswd=", PROFILES_MAX_PASSWORD_LENGTH - 1, '&'); + if(!oldpasswd) + { + oldpasswd = (char*)malloc(2); + oldpasswd[0] = 0; + } + + /* read full name */ + ss = strget(par, "name=", PROFILES_FULL_USERINFO_MAX_NAME - 1, '&'); + if(ss != NULL) { + strcpy(fui.FullName, ss); + free(ss); + } + else fui.FullName[0] = 0; + + /* read email */ + ss = strget(par, "email=", PROFILES_FULL_USERINFO_MAX_EMAIL - 1, '&'); + if(ss != NULL) { + strcpy(fui.Email, ss); + free(ss); + } + else fui.Email[0] = 0; + + /* read email */ + ss = strget(par, "icq=", PROFILES_MAX_ICQ_LEN - 1, '&'); + if(ss != NULL) { + strcpy(ui.icqnumber, ss); + free(ss); + } + else ui.icqnumber[0] = 0; + + /* read homepage address */ + ss = strget(par, "hpage=", PROFILES_FULL_USERINFO_MAX_HOMEPAGE - 1, '&'); + if(ss != NULL) { + strcpy(fui.HomePage, ss); + free(ss); + } + else fui.HomePage[0] = 0; + + /* read about */ + fui.AboutUser = strget(par, "about=", MAX_PARAMETERS_STRING - 1, '&'); + + // this is needed because of char #10 filtering. + // in WIN32 printf() works incorrectly with it +#if defined(WIN32) + FilterMessageForPreview(fui.AboutUser, &mb); + strcpy(fui.AboutUser, mb); + free(mb); +#endif + + /* read signature */ + ss = strget(par, "sign=", PROFILES_MAX_SIGNATURE_LENGTH - 1, '&'); + if(ss != NULL) { + // this is needed because of char #10 filtering. + // in WIN32 printf() works incorrectly with it +#if defined(WIN32) + FilterMessageForPreview(ss, &mb); + strcpy(fui.Signature, mb); + free(mb); +#else + strcpy(fui.Signature, ss); +#endif + free(ss); + } + else fui.Signature[0] = 0; + + // read selected users + ss = strget(par, "susr=", PROFILES_FULL_USERINFO_MAX_SELECTEDUSR - 1, '&'); + if(ss != NULL) { + // this is needed because of char #10 filtering. + // in WIN32 printf() works incorrectly with it +#if defined(WIN32) + FilterMessageForPreview(ss, &mb); + strcpy(fui.SelectedUsers, mb); + free(mb); +#else + strcpy(fui.SelectedUsers, ss); +#endif + free(ss); + } + else fui.SelectedUsers[0] = 0; + + /* invisible profile ? */ + ss = strget(par, "vprf=", 10, '&'); + if(ss != NULL && strcmp(ss, "1") == 0) { + ui.Flags = ui.Flags & (~PROFILES_FLAG_INVISIBLE); + } + else ui.Flags = ui.Flags | PROFILES_FLAG_INVISIBLE; + if(ss != NULL) free(ss); + + /* always email ackn. for every post ? */ + ss = strget(par, "apem=", 10, '&'); + if(ss != NULL && strcmp(ss, "1") == 0) { + ui.Flags = ui.Flags | PROFILES_FLAG_ALWAYS_EMAIL_ACKN; + } + else ui.Flags = ui.Flags & (~PROFILES_FLAG_ALWAYS_EMAIL_ACKN); + if(ss != NULL) free(ss); + + /* disabled private messages ? */ + ss = strget(par, "pdis=", 10, '&'); + if(ss != NULL && strcmp(ss, "1") == 0) { + ui.Flags = ui.Flags | PROFILES_FLAG_PERSMSGDISABLED; + } + else ui.Flags = ui.Flags & (~PROFILES_FLAG_PERSMSGDISABLED); + if(ss != NULL) free(ss); + + /* private message mail ackn ? */ + ss = strget(par, "peml=", 10, '&'); + if(ss != NULL && strcmp(ss, "1") == 0) { + ui.Flags = ui.Flags | PROFILES_FLAG_PERSMSGTOEMAIL; + } + else ui.Flags = ui.Flags & (~PROFILES_FLAG_PERSMSGTOEMAIL); + if(ss != NULL) free(ss); + + /* public email ? */ + ss = strget(par, "pem=", 10, '&'); + if(ss != NULL && strcmp(ss, "1") == 0) { + ui.Flags = ui.Flags | PROFILES_FLAG_VISIBLE_EMAIL; + } + else ui.Flags = ui.Flags & (~PROFILES_FLAG_VISIBLE_EMAIL); + if(ss != NULL) free(ss); + + /* save view settings to profile */ + ss = strget(par, "vprs=", 10, '&'); + if(ss != NULL && strcmp(ss, "1") == 0) { + ui.Flags = ui.Flags | PROFILES_FLAG_VIEW_SETTINGS; + } + else ui.Flags = ui.Flags & (~PROFILES_FLAG_VIEW_SETTINGS); + if(ss != NULL) free(ss); + + + + if(act != NULL && strcmp(act, MESSAGEMAIN_register_register) == 0) { + + Tittle_cat(TITLE_Registration); + + DoCheckAndCreateProfile(&ui, &fui, passwdconfirm, oldpasswd, 1, deal); + } + else if(act != NULL && strcmp(act, MESSAGEMAIN_register_edit) == 0) { + + Tittle_cat(TITLE_Registration); + + DoCheckAndCreateProfile(&ui, &fui, passwdconfirm, oldpasswd, 2, deal); + } + else + if(act != NULL && strcmp(act, MESSAGEMAIN_register_delete) == 0) { + + char* delete_confirmed = strget(par, CONFIRM_DELETE_CHECKBOX_TEXT "=", 255, '&'); + if(!delete_confirmed || !strlen(delete_confirmed)) + goto End_URLerror; + Tittle_cat(TITLE_Registration); + + DoCheckAndCreateProfile(&ui, &fui, passwdconfirm, oldpasswd, 3, deal); + } + else { + if(act != NULL) free(act); + goto End_URLerror; + } + if(act != NULL) free(act); + free(passwdconfirm); + free(oldpasswd); + goto End_part; + } + else goto End_URLerror; + } + free(st); + } + + SProfile_FullUserInfo fui; + SProfile_UserInfo ui; + memset(&fui, 0, sizeof(fui)); + fui.AboutUser = (char*)malloc(1); + fui.AboutUser[0] = 0; + memset(&ui, 0, sizeof(ui)); + ui.Flags = USER_DEFAULT_PROFILE_CREATION_FLAGS; + + DWORD x = 0; + if(ULogin.LU.ID[0] != 0 && (ULogin.LU.right & USERRIGHT_SUPERUSER)) x = 7; + else if(ULogin.LU.ID[0] == 0) x = 1; + else if(ULogin.LU.ID[0] != 0) x = 6; + + if(x & 0x02) { + ULogin.uprof->GetUserByName(ULogin.pui->username, &ui, &fui, NULL); + } + else { + strcpy(fui.HomePage, "http://"); + } + + Tittle_cat(TITLE_Registration); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + PrintEditProfileForm(&ui, &fui, x); + + free(fui.AboutUser); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } + +#if TOPICS_SYSTEM_SUPPORT + if(strncmp(deal, "ChangeTopic", 11) == 0) { + if((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) { + char *sn; + DWORD MsgNum = 0, Topic; + if((sn = strget(deal, "ChangeTopic=", 255 - 1, '&')) != NULL) { + errno = 0; + int errok; + char *ss; + MsgNum = strtol(sn, &ss, 10); + if( (!(*sn != '\0' && *ss == '\0')) || errno == ERANGE || MsgNum == 0 || + (MsgNum = DB.TranslateMsgIndex(MsgNum)) == NO_MESSAGE_CODE) { + errok = 0; + } + else errok = 1; + free(sn); + if(errok && (st = strget(deal,"topic=", 60, '&')) != NULL) { + errno = 0; + char *ss; + Topic = strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || Topic > TOPICS_COUNT) { + errok = 0; + } + else errok = 1; + free(st); + + // Do real job (change the topic) + SMessage mes; + if(ReadDBMessage(MsgNum, &mes)) { + DWORD oldTopic = mes.Topics; + mes.Topics = Topic; + if(WriteDBMessage(MsgNum, &mes)) { + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, mes.ViIndex, mes.ViIndex); + PrintBoardError(MESSAGEMAIN_messagechanged, MESSAGEMAIN_messagechanged2, HEADERSTRING_REFRESH_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_THREAD, mes.ViIndex); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAQHELP, mes.ViIndex); + print2log("Topic of message %d (%s (by %s)) was changed from [%s] to [%s] by %s", tmp, mes.MessageHeader, mes.AuthorName, + Topics_List[oldTopic], Topics_List[Topic], ULogin.pui->username); + goto End_part; + } + } + } + } + + // request error + else goto End_URLerror; + } + } +#endif + + if(strncmp(deal, "userlist", 8) == 0) { + char *sn; + DWORD code = 1; // by name + if((sn = strget(deal, "userlist=", 255 - 1, '&')) != NULL) { + errno = 0; + DWORD retval; + char *ss; + retval = strtol(sn, &ss, 10); + if( (!(*sn != '\0' && *ss == '\0')) || errno == ERANGE || retval == 0 || retval > 6) { + + } + else code = retval; + } + + // security check + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + if(code == 2 || code == 3 || code == 4 || code == 5 || code == 6) { + // security check + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + } + + Tittle_cat(TITLE_UserList); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + PrintUserList(&DB, code); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + goto End_part; + } + + if(strncmp(deal, "persmsgform", 11) == 0) { + if(ULogin.LU.UniqID != 0) { + // personal messages + char *sn = strget(deal, "persmsgform=", 255 - 1, '&'); + if(sn) { + char * f = FilterHTMLTags(sn, 255-1); + free(sn); + sn = f; + } + if(!sn) { + sn = (char*)malloc(1000); + strcpy(sn, ""); + } + + Tittle_cat(TITLE_AddPrivateMsg); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + PrintPrivateMessageForm(sn, ""); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + free(sn); + } + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_privatemsg_denyunreg, MESSAGEMAIN_privatemsg_denyunreg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + goto End_part; + } + + if(strncmp(deal, "persmsgpost", 11) == 0) { + if(ULogin.LU.UniqID != 0) { + // personal messages post or preview + int bodyok = 0, nameok = 0, tolong = 0, allowpmsg = 1; + + /* get parameters */ + par = GetParams(MAX_PARAMETERS_STRING); + if(par != NULL) { + char *name, *body, *fbody, *todo; + CProfiles prof; + SProfile_UserInfo ui; + SProfile_FullUserInfo fui; + int preview = 0; + + todo = strget(par, "Post=", MAX_PARAMETERS_STRING - 1, '&'); + + if(todo != NULL && strcmp(todo, MESSAGEMAIN_privatemsg_prev_msg_btn) == 0) { + preview = 1; + } + else if(todo != NULL && strcmp(todo, MESSAGEMAIN_privatemsg_send_msg_btn) == 0) { + preview = 0; + } + else { + free(par); + printbadurl(deal); + goto End_part; + } + + free(todo); + + name = strget(par, "name=", PROFILES_MAX_USERNAME_LENGTH - 1, '&'); + body = strget(par, "body=", MAX_PARAMETERS_STRING - 1, '&'); + + if(name && prof.GetUserByName(name, &ui, &fui, NULL) == PROFILE_RETURN_ALLOK) { + if((ui.Flags & PROFILES_FLAG_PERSMSGDISABLED)) allowpmsg = 0; + nameok = 1; + } + if(body && strlen(body) > 0) { + DWORD retflg; + if(FilterBoardTags(body, &fbody, 0, MAX_PARAMETERS_STRING - 1, + MESSAGE_ENABLED_SMILES | MESSAGE_ENABLED_TAGS | BOARDTAGS_TAG_PREPARSE, &retflg) == 0) { + /* if to long - ignore tags */ + + } + else { + free(body); + if(strcmp(fbody, " ") == 0) *fbody = 0; + body = fbody; + } + if(strcmp(body, "") != 0) bodyok = 1; + if(strlen(body) > PROFILE_PERSONAL_MESSAGE_LENGHT - 1) tolong = 1; + } + + if(bodyok && nameok && (!tolong) && allowpmsg) { + if(preview) { + char tostr[2000]; + char *ss; + + Tittle_cat(TITLE_AddPrivateMsg); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + printf(DESIGN_PREVIEW_PREVIEWMESSAGE "
", MESSAGEHEAD_preview_preview_message); + DB.Profile_UserName(name, tostr, 1); + ss = ConvertFullTime(time(NULL)); + // print header + printf("%s" MESSAGEMAIN_privatemsg_touser " %s, " MESSAGEMAIN_privatemsg_date " %s%s", + DESIGN_open_dl, tostr, ss, DESIGN_close_dl); + + char *st = FilterHTMLTags(body, MAX_PARAMETERS_STRING - 1); + char *st1 = NULL; + DWORD retflg; + if(FilterBoardTags(st, &st1, 0, MAX_PARAMETERS_STRING - 1, + MESSAGE_ENABLED_SMILES | MESSAGE_ENABLED_TAGS | BOARDTAGS_PURL_ENABLE | + BOARDTAGS_EXPAND_ENTER, &retflg) == 0) + { + st1 = st; + st = NULL; + } + + // print message text + printf(DESIGN_PRIVATEMSG_FRAME, DESIGN_open_dl, + DESIGN_PRIVATEMSG_FRAME_BGCL_OUT, st1, DESIGN_close_dl, DESIGN_break); + + PrintPrivateMessageForm(name, body); + + if(st) free(st); + if(st1) free(st1); + } + else { + if(prof.PostPersonalMessage(name, 0, body, ULogin.pui->username, ULogin.LU.UniqID) == PROFILE_RETURN_ALLOK) { + + Tittle_cat(TITLE_PrivateMsgWasPosted); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_privatemsg_msgwassent, MESSAGEMAIN_privatemsg_msgwassent2, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + + // Send ackn. to recipient + if((ui.Flags & PROFILES_FLAG_PERSMSGTOEMAIL)) { + char *pb2; + char subj[1000]; + char bdy[100000]; + + sprintf(subj, MAILACKN_PRIVATEMSG_SUBJECT, ULogin.pui->username); + + if(!PrepareTextForPrint(body, &pb2, 0/*security*/, MESSAGE_ENABLED_TAGS | BOARDTAGS_EXPAND_ENTER | BOARDTAGS_PURL_ENABLE)) { + pb2 = (char*)malloc(strlen(body) + 1); + strcpy(pb2, body); + } + + sprintf(bdy, MAILACKN_PRIVATEMSG_BODY, name, ULogin.pui->username, pb2, ULogin.pui->username); + + wcSendMail(fui.Email, subj, bdy); + print2log("Private message mailackn was sent to %s (%s->%s)", fui.Email, ULogin.pui->username, name); + + free(pb2); + } + } + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_privatemsg_msgcantsend, MESSAGEMAIN_privatemsg_msgcantsend2, 0); + } + } + + free(body); + free(name); + if(nameok) free(fui.AboutUser); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } + else { + Tittle_cat(TITLE_AddPrivateMsg); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + if(nameok) free(fui.AboutUser); + // print form and errors + if(!allowpmsg) { + printf("

  • " MESSAGEMAIN_privatemsg_disable_pmsg "
  • "); + } + else { + if(!nameok) + printf("

  • " MESSAGEMAIN_privatemsg_invalid_user "
  • "); + if(!bodyok) + printf("

  • " MESSAGEMAIN_privatemsg_invalid_body "
  • "); + if(tolong) + printf("

  • " MESSAGEMAIN_privatemsg_tolong_body "
  • "); + } + + if(!name) { + name = (char*)malloc(10); + *name = 0; + } + if(!name) { + body = (char*)malloc(10); + *body = 0; + } + PrintPrivateMessageForm(name, body); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + free(body); + free(name); + } + } + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_privatemsg_denyunreg, MESSAGEMAIN_privatemsg_denyunreg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + goto End_part; + } + + if(strncmp(deal, "persmsg", 7) == 0) { + if(ULogin.LU.UniqID != 0) { + // personal messages + char *sn; + DWORD type = 0; + if((sn = strget(deal, "persmsg=", 255 - 1, '&')) != NULL) { + if(strcmp(sn, "all") == 0) { + type = 1; + } + free(sn); + } + + CProfiles prof; + SPersonalMessage *msg, *frommsg; + DWORD *tt, *ft; + if(type) { + tt = NULL; + ft = NULL; + } + else { + tt = (DWORD*)malloc(sizeof(DWORD)); + *tt = 10; + ft = (DWORD*)malloc(sizeof(DWORD)); + *ft = 0; + } + // let's read to messages (maybe from too) + if(prof.ReadPersonalMessages(NULL, ULogin.LU.SIndex, &msg, tt, &frommsg, ft) != PROFILE_RETURN_ALLOK) + printhtmlerror(); + + // let's get received message count + DWORD cnt = 0, postedcnt = 0; + if(msg) { + while(msg[cnt].Prev != 0xffffffff) cnt++; + cnt++; + } + + if(ft) { + if(cnt) { + SPersonalMessage *msg1; + time_t ld = msg[cnt-1].Date; + + if(prof.ReadPersonalMessagesByDate(NULL, ULogin.LU.SIndex, &msg1, 0, &frommsg, ld) != PROFILE_RETURN_ALLOK) + printhtmlerror(); + + // let's get posted message count + if(frommsg) { + while(frommsg[postedcnt].Prev != 0xffffffff) postedcnt++; + postedcnt++; + } + } + else { + *ft = 10; + // let's read to messages (maybe from too) + if(prof.ReadPersonalMessages(NULL, ULogin.LU.SIndex, &msg, NULL, &frommsg, ft) != PROFILE_RETURN_ALLOK) + printhtmlerror(); + // let's get posted message count + if(frommsg) { + while(frommsg[postedcnt].Prev != 0xffffffff) postedcnt++; + postedcnt++; + } + } + } + else { + // let's get posted message count + if(frommsg) { + while(frommsg[postedcnt].Prev != 0xffffffff) postedcnt++; + postedcnt++; + } + } + + Tittle_cat(TITLE_PrivateMsg); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_PRIVATEMSG, MAINPAGE_INDEX); + + char uuname[1000]; + DB.Profile_UserName(ULogin.pui->username, uuname, 1); + + printf("

    " MESSAGEMAIN_privatemsg_header " %s
    ", uuname); + if((ULogin.pui->Flags & PROFILES_FLAG_PERSMSGDISABLED)) + printf("" MESSAGEMAIN_privatemsg_disabled "
    "); + + if(cnt) printf(MESSAGEMAIN_privatemsg_newmsgcnt " %d, ", + ULogin.pui->persmescnt - ULogin.pui->readpersmescnt); + else printf(MESSAGEMAIN_privatemsg_nonewmsg ", "); + printf(MESSAGEMAIN_privatemsg_allmsgcnt " %d, " MESSAGEMAIN_privatemsg_allmsgcnt1 " %d
    " + "" MESSAGEMAIN_privatemsg_writenewmsg + "

    ", ULogin.pui->persmescnt, ULogin.pui->postedmescnt); + + char tostr[1000], newm[100], *nickurl; + char *ss; + SPersonalMessage *pmsg; + int i = 0; + int j = 0; + int received = 0; // posted or received + for(;;) { + // check exit expression + if(i == cnt && j == postedcnt) break; + if(i == cnt) { + pmsg = &(frommsg[j]); + j++; + received = 0; + } else { + if(j == postedcnt) { + pmsg = &(msg[i]); + i++; + received = 1; + } + else { + if(frommsg[j].Date > msg[i].Date) { + pmsg = &(frommsg[j]); + j++; + received = 0; + } + else { + pmsg = &(msg[i]); + i++; + received = 1; + } + } + } + + if(!received) { + DB.Profile_UserName(pmsg->NameTo, tostr, 1); + } + else { + DB.Profile_UserName(pmsg->NameFrom, tostr, 1); + } + + ss = ConvertFullTime(pmsg->Date); + + if(received && i <= (ULogin.pui->persmescnt - ULogin.pui->readpersmescnt)) + strcpy(newm, MESSAGEMAIN_privatemsg_newmark); + else strcpy(newm, ""); + + if(!received) { + // posted message + printf("%s" MESSAGEMAIN_privatemsg_touser " %s, " MESSAGEMAIN_privatemsg_date " %s%s", + DESIGN_open_dl, tostr, ss, DESIGN_close_dl); + } + else { + nickurl = CodeHttpString(pmsg->NameFrom, 0); + // received message + if(nickurl) { + printf("%s" MESSAGEMAIN_privatemsg_fromuser " %s, " MESSAGEMAIN_privatemsg_date + " %s " MESSAGEMAIN_privatemsg_answer " %s%s", + DESIGN_open_dl, tostr, ss, nickurl, newm, DESIGN_close_dl); + } + } + + char *st = FilterHTMLTags(pmsg->Msg, MAX_PARAMETERS_STRING - 1); + char *st1 = NULL; + DWORD retflg; + if(FilterBoardTags(st, &st1, 0, MAX_PARAMETERS_STRING - 1, + MESSAGE_ENABLED_SMILES | MESSAGE_ENABLED_TAGS | BOARDTAGS_PURL_ENABLE | + BOARDTAGS_EXPAND_ENTER, &retflg) == 0) + { + st1 = st; + st = NULL; + } + + printf(DESIGN_PRIVATEMSG_FRAME, DESIGN_open_dl, + received ? DESIGN_PRIVATEMSG_FRAME_BGCL_IN : DESIGN_PRIVATEMSG_FRAME_BGCL_OUT, st1, DESIGN_close_dl, DESIGN_break); + + if(st) free(st); + if(st1) free(st1); + } + + ULogin.pui->readpersmescnt = ULogin.pui->persmescnt; + prof.SetUInfo(ULogin.LU.SIndex, ULogin.pui); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_PRIVATEMSG, MAINPAGE_INDEX); + if(msg) free(msg); + if(frommsg) free(frommsg); + } + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_privatemsg_denyunreg, MESSAGEMAIN_privatemsg_denyunreg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + goto End_part; + } + + if(strncmp(deal, "globann", 7) == 0) { + if((ULogin.LU.right & USERRIGHT_POST_GLOBAL_ANNOUNCE) != 0) { + // post global announce or global announce form + char *sn; + DWORD type = 0; + if((sn = strget(deal, "globann=", 255 - 1, '&')) != NULL) { + if(strcmp(sn, "post") == 0) { + type = 1; + free(sn); + } + } + if(!type) { + Tittle_cat(TITLE_PostGlobalAnnounce); + + char *ss, body[GLOBAL_ANNOUNCE_MAXSIZE]; + int cgann_num; + cgann_num = strtol(sn, &ss, 10); + if( (!(*sn != '\0' && *ss == '\0')) || errno == ERANGE) { + cgann_num = 0; + } + free(sn); + + body[0] = 0; + if(cgann_num != 0) { + SGlobalAnnounce *ga; + DWORD cnt, i; + if(ReadGlobalAnnounces(0, &ga, &cnt) != ANNOUNCES_RETURN_OK) printhtmlerror(); + for(i = 0; i < cnt; i++) { + if(ga[i].Number == cgann_num) { + strcpy(body, ga[i].Announce); + } + } + } + + // print form + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + PrintAnnounceForm(body, cgann_num); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } + else { + char *body = NULL; + int cgann_num = 0, preview = 0, refid = 0; + + // post + /* get parameters */ + par = GetParams(MAX_PARAMETERS_STRING); + if(par) { + char *todo = strget(par, "Post=", MAX_PARAMETERS_STRING - 1, '&'); + + // preview or post ? + if(todo != NULL && strcmp(todo, MESSAGEMAIN_globann_prev_ann_btn) == 0) { + preview = 1; + } + else if(todo != NULL && strcmp(todo, MESSAGEMAIN_globann_send_ann_btn) == 0) { + preview = 0; + } + else { + free(par); + printbadurl(deal); + goto End_part; + } + free(todo); + + char *sn = strget(par, "cgann=", 255 - 1, '&'); + char *refids = strget(par, "refid=", 100, '&'); + if(refids) { + if(strcmp(refids, "1") == 0) refid = 1; + free(refids); + } + body = strget(par, "body=", MAX_PARAMETERS_STRING - 1, '&'); + // translate to numeric format + char *ss; + if(sn) { + cgann_num = strtol(sn, &ss, 10); + if( (!(*sn != '\0' && *ss == '\0')) || errno == ERANGE) { + cgann_num = 0; + } + free(sn); + } + free(par); + } + if(body && strlen(body) > 5) { + if(strlen(body) >= GLOBAL_ANNOUNCE_MAXSIZE - 1) { + + Tittle_cat(TITLE_PostGlobalAnnounce); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + printf("

  • " MESSAGEMAIN_globann_tolong "
  • "); + + PrintAnnounceForm(body, cgann_num); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + else { + if(preview) { + char uname[1000]; + char *st; + char date[1000]; + + DB.Profile_UserName(ULogin.pui->username, uname, 1); + PrepareTextForPrint(body, &st, 0, MESSAGE_ENABLED_SMILES | MESSAGE_ENABLED_TAGS | + BOARDTAGS_PURL_ENABLE | BOARDTAGS_EXPAND_ENTER); + ConvertTime(time(NULL), date); + + Tittle_cat(TITLE_PostGlobalAnnounce); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + printf("

    %s
    ", MESSAGEMAIN_globann_preview_hdr); + + printf(DESIGN_GLOBALANN_FRAME, DESIGN_open_dl, st, MESSAGEMAIN_globann_postedby, + uname, date, "", DESIGN_close_dl); + + PrintAnnounceForm(body, cgann_num); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + if(st) free(st); + } + else { + if( (cgann_num && (!refid)) ? UpdateGlobalAnnounce(cgann_num, ULogin.pui->username, + ULogin.pui->UniqID, body, 0, 0, + ANNOUNCES_UPDATE_OPT_USER | ANNOUNCES_UPDATE_OPT_TIME | + ANNOUNCES_UPDATE_OPT_TTL | ANNOUNCES_UPDATE_OPT_FLAGS) != + ANNOUNCES_RETURN_OK + : PostGlobalAnnounce(ULogin.pui->username, ULogin.pui->UniqID, body, + 0, 0) != ANNOUNCES_RETURN_OK ) + { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_globann_anncantsend, MESSAGEMAIN_globann_anncantsend2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + else { + Tittle_cat(TITLE_GlobalAnnWasPosed); + + if(cgann_num && refid) { + DeleteGlobalAnnounce(cgann_num, 0); + print2log("Announce %d was deleted during update", cgann_num); + } + + if(!cgann_num) { + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_globann_annwassent, MESSAGEMAIN_globann_annwassent2, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + else { + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_globann_annwasupdated, MESSAGEMAIN_globann_annwasupdated2, HEADERSTRING_REFRESH_TO_MAIN_PAGE); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + + print2log("Global announce (%s) was posted by %s", body, ULogin.pui->username); + } + } + } + } + else if(body) { + Tittle_cat(TITLE_PostGlobalAnnounce); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + printf("

  • " MESSAGEMAIN_globann_toshort "
  • "); + + if(body) PrintAnnounceForm(body, cgann_num); + else PrintAnnounceForm("", cgann_num); + + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + else { + // invalid request + printbadurl(deal); + } + goto End_part; + } + } + else { + printaccessdenied(deal); + goto End_part; + } + } + + if(strncmp(deal, "ganndel", 7) == 0) { + char *sn; + if((ULogin.LU.right & USERRIGHT_POST_GLOBAL_ANNOUNCE) != 0) { + DWORD MsgNum = 0; + if((sn = strget(deal, "ganndel=", 255 - 1, '&')) != NULL) { + errno = 0; + int errok; + char *ss; + MsgNum = strtol(sn, &ss, 10); + if( (!(*sn != '\0' && *ss == '\0')) || errno == ERANGE) { + errok = 0; + } + else errok = 1; + free(sn); + + if(errok) { + if(DeleteGlobalAnnounce(MsgNum, ((ULogin.LU.right & USERRIGHT_SUPERUSER) != 0) ? 0 : ULogin.LU.UniqID) == ANNOUNCES_RETURN_OK) { + Tittle_cat(TITLE_GlobalAnnWasDeleted); + + print2log("Global Announce %d was deleted by user %s", MsgNum, ULogin.pui->username); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_globann_wasdeleted, MESSAGEMAIN_globann_wasdeleted2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + else { + Tittle_cat(TITLE_Error); + + print2log("Global Announce %d cannot be deleted by user %s", MsgNum, ULogin.pui->username); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_globann_cannotdel, MESSAGEMAIN_globann_cannotdel2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + } + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_globann_invalidnum, MESSAGEMAIN_globann_invalidnum2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + } + goto End_part; + } + } + + if(strncmp(deal, "rann", 4) == 0) { + char *sn; + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) != 0) { + DWORD MsgNum = 0; + if((sn = strget(deal, "rann=", 255 - 1, '&')) != NULL) { + errno = 0; + int errok; + char *ss; + MsgNum = strtol(sn, &ss, 10); + if( (!(*sn != '\0' && *ss == '\0')) || errno == ERANGE) { + errok = 0; + } + else errok = 1; + free(sn); + + if(!errok) goto End_URLerror; + + currentlann = MsgNum; + // to main page at once + PrintHTMLHeader(HEADERSTRING_REDIRECT_NOW | HEADERSTRING_NO_CACHE_THIS, MAINPAGE_INDEX); + goto End_part; + } + } + } + +#ifdef USER_FAVOURITES_SUPPORT + if(strncmp(deal, "favs", 4) == 0) { + int num; + if(ULogin.LU.UniqID != 0) { + CProfiles prof; + //favourites + // security check + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + Tittle_cat(TITLE_FavouritesPage); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAVOURITES, MAINPAGE_INDEX); + printf("

    %s

    ", MESSAGEHEAD_favourites); + + int updated; + if( (num = DB.PrintandCheckMessageFavsExistandInv(ULogin.pui, + ULogin.LU.right & USERRIGHT_SUPERUSER, &updated)) == 0) + printf("

    " MESSAGEMAIN_favourites_listclear "

    "); + if(updated) prof.SetUInfo(ULogin.LU.SIndex, ULogin.pui); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_FAVOURITES, MAINPAGE_INDEX); + goto End_part; + } + else { + Tittle_cat(TITLE_Error); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_favourites_denyunreg, MESSAGEMAIN_favourites_denyunreg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + goto End_part; + } + + if(strncmp(deal, "favadd", 6) == 0) { + if(ULogin.LU.UniqID != 0){ + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + if((st = strget(deal, "favadd=", 255 - 1, '&')) != NULL) { + errno = 0; + DWORD addmsg; + char *ss; + addmsg = strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || addmsg < 1){ + free (st); + goto End_URLerror; + } + free (st); + DWORD msg; + if( ( msg=DB.TranslateMsgIndex(addmsg)) == NO_MESSAGE_CODE){ + printnomessage(deal); + goto End_part; + } + if(!ReadDBMessage(msg, &mes)) printhtmlerror(); + /* allow read invisible message only to SUPERUSER */ + if((mes.Flag & MESSAGE_IS_INVISIBLE) && ((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0)) { + printnomessage(deal); + goto End_part; + } +#if USER_FAVOURITES_SUPPORT == 2 + if( mes.ParentThread != 0){ + Tittle_cat(TITLE_FavouritesPageAdd); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_favourites_addno, MESSAGEMAIN_favourites_addnoparent, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + } +#endif + CProfiles prof; + int result = prof.CheckandAddFavsList(ULogin.LU.SIndex, addmsg, 1); + switch(result) { + case PROFILE_RETURN_ALLOK: + Tittle_cat(TITLE_FavouritesPageAdd); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL, 0); + PrintBoardError(MESSAGEMAIN_favourites_added, MESSAGEMAIN_favourites_added2, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL, 0); + goto End_part; + case PROFILE_RETURN_ALREADY_EXIST: + Tittle_cat(TITLE_FavouritesPageAdd); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL, 0); + PrintBoardError(MESSAGEMAIN_favourites_addno, MESSAGEMAIN_favourites_addexist, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL, 0); + goto End_part; + case PROFILE_RETURN_UNKNOWN_ERROR: + Tittle_cat(TITLE_FavouritesPageAdd); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL, 0); + PrintBoardError(MESSAGEMAIN_favourites_addno, MESSAGEMAIN_favourites_addnoplace, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL, 0); + goto End_part; + default: + printhtmlerror(); + goto End_part; + + } + } + } + else { + Tittle_cat(TITLE_Error); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_favourites_denyunreg, MESSAGEMAIN_favourites_denyunreg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + goto End_part; + } + + if(strncmp(deal, "favdel", 6) == 0) { + if(ULogin.LU.UniqID != 0){ + if((ULogin.LU.right & USERRIGHT_VIEW_MESSAGE) == 0) { + printaccessdenied(deal); + goto End_part; + } + if((st = strget(deal, "favdel=", 255 - 1, '&')) != NULL) { + errno = 0; + DWORD delmsg; + char *ss; + delmsg = strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || delmsg == 0){ + free (st); + goto End_URLerror; + } + free (st); + DWORD msg; + if( (msg = DB.TranslateMsgIndex(delmsg)) == NO_MESSAGE_CODE){ + printnomessage(deal); + goto End_part; + } + if(!ReadDBMessage(msg, &mes)) printhtmlerror(); + /* allow read invisible message only to SUPERUSER */ + if((mes.Flag & MESSAGE_IS_INVISIBLE) && ((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0)) { + printnomessage(deal); + goto End_part; + } + CProfiles prof; + int result = prof.DelFavsList(ULogin.LU.SIndex, delmsg); + switch(result) { + case PROFILE_RETURN_ALLOK: + Tittle_cat(TITLE_FavouritesPageDel); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL, 0); + PrintBoardError(MESSAGEMAIN_favourites_deleted, MESSAGEMAIN_favourites_deleted2, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL, 0); + goto End_part; + case PROFILE_RETURN_UNKNOWN_ERROR: + Tittle_cat(TITLE_FavouritesPageDel); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_favourites_delno, MESSAGEMAIN_favourites_delnoexist, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + default: + printhtmlerror(); + goto End_part; + + } + } + } + else { + Tittle_cat(TITLE_Error); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_favourites_denyunreg, MESSAGEMAIN_favourites_denyunreg2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + } + goto End_part; + } +#endif + +#ifdef CLEANUP_IDLE_USERS + +#define DAY (60*60*24) +#define YEAR (DAY*365) + if(strncmp(deal, "cluserlist", 10) == 0) { + bool fDelete = false; + if(!(ULogin.LU.right & USERRIGHT_SUPERUSER)) { + printaccessdenied(deal); + goto End_part; + } + if((st = strget(deal,"cluserlist=", 14, '&')) != NULL) { + if(strcmp(st, "yes") == 0) { + free(st); + fDelete = true; + } + } + time_t tn = time(NULL); + DWORD i = 0, ii=0; + char **buf = NULL; + char name[1000]; + DWORD uc = 0; + CUserLogin ULogin; + CProfiles uprof; + Tittle_cat(TITLE_UserList); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + + printf("

    "); + printf( + "%s
    \n", + fDelete ? + "Ñëåäóþùèå ïîëüçîâàòåëè áûëè óñïåøíî óäàëåíû:" : + "Ñïèñîê ïîëüçîâàòåëåé ïîäëåæàùèõ óäàëåíèþ:" + ); + if(!uprof.GenerateUserList(&buf, &uc)) { + printf("error generating list"); + } else { + qsort((void*)buf, uc, sizeof(char*), cmp_name); + for(i = 0; i < uc; i++) { + DWORD + PostCount = *((DWORD*)(buf[i] + 4)), + RefreshCount = *((DWORD*)(buf[i] + 12)), + UserRight = *((DWORD*)(buf[i] + 16)), + LoginDate = *((DWORD*)(buf[i] + 8)), + activity = PostCount + RefreshCount; + char *username = buf[i] + 20; + int + idletime = tn - LoginDate; + bool + fSuperuser = UserRight & USERRIGHT_SUPERUSER, + fAged1 = idletime > YEAR, + fAged2 = idletime > YEAR / 2 && activity < 100, + fAged3 = idletime > YEAR / 4 && activity < 10; + if(!fSuperuser && (fAged1 || fAged2 || fAged3)) { + if((ii % 10) != 0) printf(" | "); + if(((ii % 10) == 0) && ii != 0) printf("
    "); + DB.Profile_UserName(buf[i] + 20, name, 1, 1); + printf("%s", name); + if(fDelete) { + DWORD err = uprof.DeleteUser(username); + if(err == PROFILE_RETURN_ALLOK) { + printf("!"); + } else { + printf("Íåâîçìîæíî óäàëèòü '%s' !!!", name); + goto End_part; + } + } + ii++; + }// if(!fSuperuser && (fAged1 || fAged2 || fAged3) + free(buf[i]); + } //for(;i óäàëåíî %d èç %d ïîëüçîâàòåëåé \n", + ii, + uc); + } else { + printf( + "
    Áóäåò óäàëåíî %d
    èç %d ïîëüçîâàòåëåé \n", + ii, + uc); + printf( + "
    " + "Ïðîäîëæèòü ?"); + } + }//if(generate_list(..)) + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + goto End_part; + }//if(strcmp(deal,"cluserlist")) +#endif //CLEANUP_IDLE_USERS + + + if(strncmp(deal, "banlist", 7) == 0) { + + /* security check */ + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0) { + printaccessdenied(deal); + goto End_part; + } + if((st = strget(deal,"banlist=", 30, '&')) != NULL) { + if(strcmp(st, "save") == 0) { + // read ban list + par = GetParams(MAX_PARAMETERS_STRING); + char *ban_list; + ban_list = strget(par,"ban_list=", MAX_PARAMETERS_STRING, '&'); + // this is needed because of char #10 filtering. + // in WIN32 printf() works incorrectly with it +#if defined(WIN32) + char *mb; + FilterMessageForPreview(ban_list, &mb); + free(ban_list); + ban_list = mb; +#endif + + // check ban_list is empty + if(ban_list == NULL || *ban_list == 0) { + Tittle_cat(TITLE_BanSave); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL, 0); + PrintBoardError(MESSAGEMAIN_ban_no_save, MESSAGEMAIN_ban_empty, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL, 0); + goto End_part; + + } + + WCFILE *BAN_FILE; + if ((BAN_FILE = wcfopen(F_BANNEDIP, FILE_ACCESS_MODES_RW)) == NULL) printhtmlerror(); + lock_file(BAN_FILE); + + if ( !fCheckedWrite(ban_list, strlen(ban_list), BAN_FILE) ) { + unlock_file(BAN_FILE); + printhtmlerror(); + } + + +#ifdef WIN32 + wctruncate(BAN_FILE, strlen(ban_list)); +#else + truncate(F_BANNEDIP, strlen(ban_list)); +#endif + + unlock_file(BAN_FILE); + wcfclose(BAN_FILE); + + Tittle_cat(TITLE_BanSave); + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + PrintBoardError(MESSAGEMAIN_ban_save, MESSAGEMAIN_ban_save2, 0); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + + print2log("Banlist update by %s from %s", ULogin.pui->username, Cip); + + } + } + else{ + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, 0); + PrintBanList(); + PrintBottomLines(HEADERSTRING_RETURN_TO_MAIN_PAGE, 0); + + print2log("Banlist view by %s from %s", ULogin.pui->username, Cip); + } + goto End_part; + } + + + + if(strncmp(deal, "clsession1", 9) == 0) { + if(ULogin.LU.UniqID != 0) { + DWORD closeseq[2]; + if((st= strget(deal, "clsession1=", 255 - 1, '&')) != NULL) { + errno = 0; + char *ss; + closeseq[0] = strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || closeseq[0] == 0 ) { + free(st); + goto End_URLerror; + } + } + free(st); + if((st= strget(deal, "clsession2=", 255 - 1, '&')) != NULL) { + errno = 0; + char *ss; + closeseq[1] = strtol(st, &ss, 10); + if( (!(*st != '\0' && *ss == '\0')) || errno == ERANGE || closeseq[1] == 0 ) { + free(st); + goto End_URLerror; + } + } + free(st); + + // checking session exists and user have suff. rights + // superuser knows if session does not exits + // user can receive only access deny message (session bf aware) + + if((ULogin.LU.right & USERRIGHT_SUPERUSER) == 0){ + if( (ULogin.LU.right & USERRIGTH_PROFILE_MODIFY) == 0 || ULogin.CheckSession(closeseq, 0, ULogin.LU.UniqID) != 1) { + printaccessdenied(deal); + goto End_part; + } + } + else { + if( ULogin.CheckSession(closeseq, 0, 0) != 1) { + Tittle_cat(TITLE_ClSession); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + PrintBoardError(MESSAGEMAIN_session_closed_no, MESSAGEMAIN_session_check_failed, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + goto End_part; + } + } + + // force closing session + if(ULogin.ForceCloseSessionBySeq(closeseq)){ + Tittle_cat(TITLE_ClSession); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + PrintBoardError(MESSAGEMAIN_session_closed_ok, MESSAGEMAIN_session_closed_ok2, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + goto End_part; + } + else { + Tittle_cat(TITLE_ClSession); + PrintHTMLHeader(HEADERSTRING_DISABLE_ALL | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + PrintBoardError(MESSAGEMAIN_session_closed_no, MESSAGEMAIN_session_close_failed, 0); + PrintBottomLines(HEADERSTRING_DISABLE_ALL | HEADERSTRING_REFRESH_TO_MAIN_PAGE, 0); + goto End_part; + } + } + goto End_URLerror; + + } + + +End_URLerror: + printbadurl(deal); + +End_part: + +#if _DEBUG_ == 1 + //print2log("Exit success"); +#ifdef WIN32 +#ifdef _DEBUG + free(Cip); + free(deal); + free(ConfTitle); + _CrtDumpMemoryLeaks(); +#endif +#endif // WIN32 +#endif // _DEBUG_ + + return EXIT_SUCCESS; +} blob - /dev/null blob + 4c1a0a7a04688bf32036cf68a5ec17d77ec03759 (mode 644) --- /dev/null +++ src/main.h @@ -0,0 +1,48 @@ +/*************************************************************************** + main.h - main module include + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef MAIN_H_INCLUDED +#define MAIN_H_INCLUDED + +// bit mask for proc making html header of board +#define HEADERSTRING_POST_NEW_MESSAGE 0x000001 +#define HEADERSTRING_CONFIGURE 0x000002 +#define HEADERSTRING_RETURN_TO_MAIN_PAGE 0x000004 +#define HEADERSTRING_REFRESH_TO_MAIN_PAGE 0x000008 +#define HEADERSTRING_WELCOME_INFO 0x000010 +#define HEADERSTRING_DISABLE_FAQHELP 0x000020 +#define HEADERSTRING_DISABLE_LOGOFF 0x000040 +#define HEADERSTRING_DISABLE_SEARCH 0x000080 +#define HEADERSTRING_DISABLE_REGISTER 0x000100 +#define HEADERSTRING_DISABLE_LOGIN 0x000200 +#define HEADERSTRING_DISABLE_ALL 0x000400 +#define HEADERSTRING_REG_USER_LIST 0x000800 +#define HEADERSTRING_REFRESH_TO_THREAD 0x001000 +#define HEADERSTRING_ENABLE_TO_MESSAGE 0x002000 +#define HEADERSTRING_ENABLE_RESETNEW 0x004000 +#define HEADERSTRING_REDIRECT_NOW 0x008000 +#define HEADERSTRING_NO_CACHE_THIS 0x010000 +#define HEADERSTRING_DISABLE_PRIVATEMSG 0x020000 +#define HEADERSTRING_DISABLE_FAVOURITES 0x040000 +#define HEADERSTRING_DISABLE_END_TABLE 0x080000 +#define HEADERSTRING_ENABLE_REPLY_LINK 0x100000 + +// button codes +#define ACTION_BUTTON_POST 0x0001 +#define ACTION_BUTTON_PREVIEW 0x0002 +#define ACTION_BUTTON_EDIT 0x0004 +#define ACTION_BUTTON_FAKEREPLY 0x0008 + +#define MAX_DELTA_POST_MESSAGE 15000 + +#define MAINPAGE_INDEX 0xFFFFFFFF + +#define VERSION "2.0 PRE BETA4" + + +#endif blob - /dev/null blob + 8e98e268117cfa3b98d4d189c39a4ddc03d1f0b0 (mode 644) --- /dev/null +++ src/messages.h @@ -0,0 +1,902 @@ + /*************************************************************************** + messages.h - Âñå ñîîáùåíèÿ êîíôåðåíöèè + ------------------- + begin : Fri Mar 23 2001 + ïåðåâîä : Àëåêñàíäð Ãëÿêîâ + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef MESSAGES_H_INCLUDED +#define MESSAGES_H_INCLUDED + +#include "basetypes.h" + +/* êîíñòàíòû ñâÿçàííûå ñî âðåìåíåì + * 0,1,2,3 -> ÷àñ äåíü íåäåëÿ ìåñÿö + */ +extern char *MESSAGEHEAD_timetypes[4]; + +#define MESSAGEHEAD_preview_preview_message "Ïðåäâàðèòåëüíûé ïðîñìîòð" +#define MESSAGEHEAD_preview_change_message "" + +#define MESSAGEHEAD_configure "Íàñòðîéêè" +#define MESSAGEHEAD_resetnew "Ñáðîñèòü +" +#define MESSAGEHEAD_post_new_message "Íîâîå ñîîáùåíèå" +#define MESSAGEHEAD_return_to_main_page "Íà ãëàâíóþ ñòðàíèöó" +#define MESSAGEHEAD_logoff "Âûõîä" +#define MESSAGEHEAD_help_showhelp "Ïðàâèëà" +#define MESSAGEHEAD_register "Ðåãèñòðàöèÿ" +#define MESSAGEHEAD_registerprf "Âàø ïðîôàéë" +#define MESSAGEHEAD_search "Ïîèñê" +#define MESSAGEHEAD_login "Âõîä" +#define MESSAGEHEAD_userlist "Ïîëüçîâàòåëè" +#define MESSAGEHEAD_personalmsg "Ïðèâàò" +#define MESSAGEHEAD_makeannounce "Äîáàâèòü àíîíñ" +#define MESSAGEHEAD_favourites "Èçáðàííîå" +#define MESSAGEHEAD_banlist "Áàíëèñò" + +#define MESSAGEMAIN_ban_save "Ñïàñèáî. Ñïèñîê ñîõðàíåí óñïåøíî." +#define MESSAGEMAIN_ban_save2 "×åðåç íåñêîëüêî ñåêóíä âû âåðíåòåñü ê ñïèñêó ñîîáùåíèé" + +#define MESSAGEMAIN_ban_no_save "Âíèìàíèå! Ñïèñîê íå ñîõðàíåí!" +#define MESSAGEMAIN_ban_empty "Îòïðàâëåííûé ñïèñîê ïóñò. " + + +#define MESSAGEMAIN_add_banned "Ñîîáùåíèå íå ìîæåò áûòü äîáàâëåíî" +#define MESSAGEMAIN_add_banned2 "Îòïðàâêà ñîîáùåíèé ñ âàøåãî êîìïüþòåðà áûëà çàïðåùåíà Àäìèíèñòðàòîðîì" +#define MESSAGEMAIN_add_closed "Ñîîáùåíèå íå ìîæåò áûòü äîáàâëåíî" +#define MESSAGEMAIN_add_closed2 "Ýòà âåòâü çàêðûòà Àäìèíèñòðàòîðîì, íîâûå ñîîáùåíèÿ íå ïðèíèìàþòñÿ" +#define MESSAGEMAIN_add_invalid_reply "Ñîîáùåíèå íå ìîæåò áûòü äîáàâëåíî" +#define MESSAGEMAIN_add_invalid_reply2 "Ñîîáùåíèå íà êîòîðîå Âû õîòèòå îòâåòèòü íå ñóùåñòâóåò!" + +#define MESSAGEMAIN_add_ok "Ñîîáùåíèå äîáàâëåíî" +#define MESSAGEMAIN_add_ok_login "Ñîîáùåíèå äîáàâëåíî, Âû âîøëè â êîíôåðåíöèþ " +#define MESSAGEMAIN_add_ok2 "Ñïàñèáî çà ó÷àñòèå. " + +#define MESSAGEMAIN_add_spelling "Ñîîáùåíèå íå ìîæåò áûòü äîáàâëåíî " +#define MESSAGEMAIN_add_spelling2 "Âàøå ñîîáùåíèå ñîäåðæèò çàïðåùåííûå ñëîâà, ïîïðîáóéòå íàïèñàòü åãî áåç íèõ" + +#define MESSAGEMAIN_add_no_name " âàøåì ñîîáùåíèè íåò èìåíè" +#define MESSAGEMAIN_add_no_name2 "×òîáû îòïðàâèòü ñîîáùåíèå, Âû äîëæíû óêàçàòü ïî êðàéíåé ìåðå Òåìó è âàøå Èìÿ" + +#define MESSAGEMAIN_add_no_subject " âàøåì ñîîáùåíèè íåò òåìû" +#define MESSAGEMAIN_add_no_subject2 "×òîáû îòïðàâèòü ñîîáùåíèå, Âû äîëæíû óêàçàòü ïî êðàéíåé ìåðå Òåìó è âàøå Èìÿ" + +// TODO :..... +#define MESSAGEMAIN_add_no_right_thrd "Ñîçäàíèå íîâîãî ïîòîêà áûëî çàïðåùåíî âàì ìîäåðàòîðàìè" +#define MESSAGEMAIN_add_no_right_thrd2 "Åñëè Âû ñ÷èòàåòå, ÷òî ýòî îøèáêà ñâÿæèòåñü ñ ìîäåðàòîðàìè ôîðóìà" + +#define MESSAGEMAIN_add_emptymsg_java "Íàïèøèòå, ïîæàëóéñòà, ÷òî-íèáóäü è óêàæèòå ïî âîçìîæíîñòè òîïèê Âàøåãî ñîîáùåíèÿ! Ñïàñèáî!" +#define MESSAGEMAIN_add_tolong_java "Ðàçìåð Âàøåãî ñîîáùåíèÿ ïðåâûøàåò ìàêñèìóì íà" +#define MESSAGEMAIN_add_tolong_java2 "ñèìâîëîâ! Ïîæàëóéñòà, óìåíüøèòå åãî, ðàçáèâ íà íåñêîëüêî ÷àñòåé! Ñïàñèáî!" + +#define MESSAGEMAIN_add_no_body " âàøåì ñîîáùåíèè íåò òåëà" +#define MESSAGEMAIN_add_no_body2 "×òîáû îòïðàâèòü ñîîáùåíèå, Âû äîëæíû íàïèñàòü òåëî ñîîáùåíèÿ" + +#define MESSAGEMAIN_add_flood "Âû ïûòàåòåñü ïîâòîðíî îòïðàâèòü ñîîáùåíèå èëè âðåìÿ ìåæäó âàøèìè ñîîáùåíèÿìè ñëèøêîì ìàëî" +#define MESSAGEMAIN_add_flood2 "Åñëè âû ïûòàåòåñü îòïðàâèòü íîâîå ñîîáùåíèå, ïîïðîáóéòå ñäåëàòü ýòî ÷åðåç íåêîòîðîå âðåìÿ" + +#define MESSAGEMAIN_unknownerr "Ïðîèçîøëà íåèçâåñòíàÿ îøèáêà" +#define MESSAGEMAIN_unknownerr2 "Ñîîáùèòå ïîæàëóéñòà Àäìèíèñòðàòîðó îá ýòîé îøèáêå" + +#define MESSAGEMAIN_requesterror "Îøèáî÷íûé çàïðîñ íà äåéñòâèå" +#define MESSAGEMAIN_requesterror2 "Âû èëè âàø áðîóçåð ïåðåäàëè íåïðàâèëüíóþ ññûëêó, è ñêðèïò íå ìîæåò åå îáðàáîòàòü." + +#define MESSAGEMAIN_nonexistingmsg "Ýòî ñîîáùåíèå íå ñóùåñòâóåò èëè ââåäåíî íåïðàâèëüíî" +#define MESSAGEMAIN_nonexistingmsg2 "Âû èëè âàø áðîóçåð ïåðåäàëè íåïðàâèëüíûé íîìåð ñîîáùåíèÿ, ïåðåçàãðóçèòå ïîæàëóéñòà ñòðàíèöó èëè ââåäèòå ïðàâèëüíûé íîìåð" + +#define MESSAGEMAIN_threadwasclosed "Ñîñòîÿíèå ýòîé âåòâè áûëî óñïåøíî èçìåíåíî" +#define MESSAGEMAIN_threadwasclosed2 "Âåòâü ìîãëà ñòàòü çàêðûòîé èëè îòêðûòîé" + +#define MESSAGEMAIN_threadchangehided "Âèäèìîñòü ýòîé âåòâè áûëà óñïåøíî èçìåíåíà" +#define MESSAGEMAIN_threadchangehided2 "Âåòâü ìîãëà ñòàòü âèäèìîé èëè íåâèäèìîé" + +#define MESSAGEMAIN_threaddeleted "Âåòâü áûëà óñïåøíî óäàëåíà" +#define MESSAGEMAIN_threaddeleted2 "" + +#define MESSAGEMAIN_threadrolled "Âåòâü áûëà óñïåøíî ñâåðíóòà èëè ðàçâåðíóòà" +#define MESSAGEMAIN_threadrolled2 "" + +#define MESSAGEMAIN_messagechanged "Ñîîáùåíèå áûëî èçìåíåíî" +#define MESSAGEMAIN_messagechanged2 "Ñïàñèáî çà ó÷àñòèå" + +#define MESSAGEMAIN_incorrectpwd "Óêàçàííîå èìÿ óæå ñóùåñòâóåò è ââåäåí íåâåðíûé ïàðîëü" +#define MESSAGEMAIN_incorrectpwd2 "Ïðîâåðüòå ïðàâèëüíîñòü íàïèñàíèÿ ïàðîëÿ è èìåíè
    Åñëè Âû õîòèòå îòïðàâèòü ñîîáùåíèå íå ðåãåñòðèðóÿñü â êîíôåðåíöèè ïîïðîáóéòå óêàçàòü äðóãîå íå çàíÿòîå èìÿ" + +#define MESSAGEMAIN_robotmessage "Èñïîëüçîâàíèå óêàçàííîãî èìåíè çàïðåùåíî" +#define MESSAGEMAIN_robotmessage2 "" + +#define MESSAGEMAIN_session_end "Âû ïûòàåòåñü ïîëó÷èòü äîñòóï èñïîëüçóÿ íåàâòîðèçèðîâàííîå ïîäêëþ÷åíèå" +#define MESSAGEMAIN_session_end2 "Ñêîðåå âñåãî âðåìÿ âàøåãî ïîäêëþ÷åíèÿ èñòåêëî è Âû äîëæíû ââåñòè èìÿ è ïàðîëü çàíîâî" + +#define MESSAGEMAIN_logoff_not_logged_in "Âû íå âîøëè íî ïûòàåòåñü âûéòè" +#define MESSAGEMAIN_logoff_not_logged_in2 "Âû óæå âûøëè, Âàì íå íóæíî äåëàòü ýòî åùå ðàç" + +#define MESSAGEMAIN_logoff_ok "Âû óñïåøíî âûøëè" +#define MESSAGEMAIN_logoff_ok2 "" + +#define MESSAGEMAIN_login_ok "%s, %s, Âû óñïåøíî âîøëè â êîíôåðåíöèþ" +#define MESSAGEMAIN_login_ok2 "" + +#define MESSAGEMAIN_login_helloday "Äîáðûé äåíü" +#define MESSAGEMAIN_login_helloevn "Äîáðûé âå÷åð" +#define MESSAGEMAIN_login_hellonight "Äîáðîé íî÷è" +#define MESSAGEMAIN_login_hellomor "Äîáðîå óòðî" + +#define MESSAGEMAIN_lostpassw_ok "Âàø ïàðîëü áûë îòïðàâëåí ïî email" +#define MESSAGEMAIN_lostpassw_ok2 "Ñïàñèáî çà ïîëüçîâàíèå ñèñòåìîé íàïîìèíàíèÿ ïàðîëÿ" + +#define MESSAGEMAIN_access_denied "Äîñòóï ê ýòîé ôóíêöèè äëÿ Âàñ çàïðåùåí" +#define MESSAGEMAIN_access_denied2 "Ïðîâåðüòå, âîøëè ëè âû â êîíôåðåíöèþ
    Åñëè Âû ñ÷èòàåòå, ÷òî ýòî îøèáêà - îáðàòèòåñü ê ìîäåðàòîðàì êîíôåðåíöèè" + +#define MESSAGEMAIN_spamtry "Áëîêèðîâêà ïîïûòêè ñïàìà èëè çàùèòà îò ïîâòîðíîé îòïðàâêè" +#define MESSAGEMAIN_spamtry2 "Åñëè Âû ïûòàåòåñü îòïðàâèòü ñîîáùåíèå, òî ýòî çíà÷èò, ÷òî îíî óæå îòïðàâëåíî è âàì íåçà÷åì äåëàòü ýòî åùå ðàç" + +#define MESSAGEMAIN_BANNED_REASON "Ïðè÷èíà çàïðåòà äîáàâëåíèÿ ñîîáùåíèé äëÿ Âàñ áûëà :" + +#define MESSAGEMAIN_browser_return "

    Âàø áðîóçåð äîëæåí âåðíóòü âàñ ê ñïèñêó ñîîáùåíèé ÷åðåç íåñêîëüêî ñåêóíä

    " + +#define MESSAGEMAIN_browser_to_thread "

    Âåðíóòüñÿ ê ñâîåìó ñîîáùåíèþ

    " + +#define MESSAGEMAIN_admin_contact "Åñëè Âû ñ÷èòàåòå ÷òî ýòî íåïðàâèëüíî, îáðàòèòåñü ê Àäìèíèñòðàòîðó êîíôåðåíöèè" + +/***************** Ôîðìà îòïðàâêè ñîîáùåíèé ******************/ +#define MESSAGEMAIN_post_newmessage "Íîâîå ñîîáùåíèå" +#define MESSAGEMAIN_post_replymessage "Îòâåòèòü" +#define MESSAGEMAIN_post_editmessage "Èçìåíèòü ñîîáùåíèå" + +#define MESSAGEMAIN_post_you_name "Èìÿ:" +#define MESSAGEMAIN_post_your_password "Ïàðîëü:" +#define MESSAGEMAIN_post_login_me "Àâòîëîãèí" +#define MESSAGEMAIN_post_hostname "Host:" +#define MESSAGEMAIN_post_message_subject "Òåìà:" +#define MESSAGEMAIN_post_message_body "Ñîîáùåíèå: (Êàê äîáàâèòü ôîðìàòèðîâàíèå, êàðòèíêè, è ò.ä. â âàøå ñîîáùåíèå)" + +#define MESSAGEMAIN_post_disable_wwwconf_tags "Îòêëþ÷èòü ðàñïîçíàâàíèå Òåãîâ êîíôåðåíöèè" +#define MESSAGEMAIN_post_disable_smile_tags "Îòêëþ÷èòü ðàñïîçíàâàíèå ñìàéë-êîäîâ" +#define MESSAGEMAIN_post_reply_acknl "Ïîëó÷àòü óâåäîìëåíèÿ îá îòâåòàõ ïî ïî÷òå" + +#define MESSAGEMAIN_post_preview_message "Ïðåäâàðèòåëüíûé ïðîñìîòð" +#define MESSAGEMAIN_post_post_message "Îòïðàâèòü" +#define MESSAGEMAIN_post_edit_message "Èçìåíèòü" + +/****************** Ðåãèñòðàöèîííàÿ ôîðìà ******************/ +#define MESSAGEMAIN_register_intro "Ðåãèñòðàöèÿ" +#define MESSAGEMAIN_register_chg_prof_intro "Èçìåíåíèå ïðîôàéëà" +#define MESSAGEMAIN_register_login "Èìÿ (*):" +#define MESSAGEMAIN_register_displayname "Îòîáðàæàåìîå èìÿ :" +#define MESSAGEMAIN_register_oldpass_req "Äëÿ èçìåíåíèÿ ïðîôàéëà Âû äîëæíû óêàçàòü Âàø ïàðîëü !" +#define MESSAGEMAIN_register_oldpassword "Ñòàðûé ïàðîëü (*):" +#define MESSAGEMAIN_register_if_want_change "Åñëè âû õîòèòå èçìåíèòü ïàðîëü ââåäèòå òóò íîâûé ïàðîëü, èíà÷å îñòàâüòå ýòè ïîëÿ ïóñòûìè" +#define MESSAGEMAIN_register_password1 "Íîâûé ïàðîëü (*):" +#define MESSAGEMAIN_register_password2 "Íîâûé ïàðîëü åùå ðàç (*):" +#define MESSAGEMAIN_register_full_name "Âàøå ïîëíîå èìÿ:" +#define MESSAGEMAIN_register_validemail_req "Âû äîëæíû óêàçàòü äåéñòâóþùèé E-Mail àäðåñ
    (îí áóäåò èñïîëüçîâàòüñÿ äëÿ ïîëó÷åíèÿ ïàðîëÿ è ñâîäîê ïî êîíôåðåíöèè)" +#define MESSAGEMAIN_register_email "E-Mail àäðåñ (*):" +#define MESSAGEMAIN_register_email_pub "Ïóáëè÷íûé äîñòóï ê Âàøåìó E-Mail" +#define MESSAGEMAIN_register_homepage "Àäðåñ Âàøåé äîìàøíåé ñòðàíèöû:" +#define MESSAGEMAIN_register_icq "ICQ :" +#define MESSAGEMAIN_register_signature "Åñëè Âû õîòèòå ñîáñòâåííóþ ïîäïèñü (áóäåò ïîÿâëÿòüñÿ â" \ + " íîâûõ ñîîáùåíèÿõ ïî óìîë÷àíèþ,
    è íå ìîæåò áûòü äëèííåå 255 ñèìâîëîâ), ââåäèòå åå çäåñü," \ + " èëè îñòàâüòå ïîëå ïóñòûì" +#define MESSAGEMAIN_register_selectedusers "Âûáðàíûå ïîëüçîâàòåëè, ñîîáùåíèÿ êîòîðûõ áóäóò ïîäñâå÷èâàòüñÿ
    " \ + "(êàæäîå èìÿ ïèøåòñÿ íà íîâîé ñòðîêå, ìàêñèìàëüíî ìîæíî ââåñòè 184 ñèìâîëà)" +#define MESSAGEMAIN_register_about "Ââåäèòå ÷òî-íèáóäü î Âàøèõ èíòåðåñàõ, õîááè è ò.ä." +#define MESSAGEMAIN_register_private_prof "Ïóáëè÷íûé äîñòóï ê Âàøåìó ïðîôàéëó" +#define MESSAGEMAIN_register_always_emlackn "Âñåãäà îòñûëàòü îòâåòû íà Âàøè ñîîáùåíèÿ íà E-mail" +#define MESSAGEMAIN_register_pmsg_disable "Çàïðåòèòü ñåðâèñ ïðèâàòíûõ ñîîáùåíèé" +#define MESSAGEMAIN_register_pmsg_email "Ïðèñûëàòü îïîâåùåíèå î ïðèõîäå íîâîãî ïðèâàòíîãî ñîîáùåíèÿ ïî ïî÷òå" +#define MESSAGEMAIN_register_req_fields "Âñå ïîëÿ îòìå÷åííûå * ÿâëÿþòñÿ îáÿçàòåëüíûìè !" +#define MESSAGEMAIN_register_register "Çàðåãèñòðèðîâàòü" +#define MESSAGEMAIN_register_edit "Èçìåíèòü" +#define MESSAGEMAIN_register_delete "Óäàëèòü" +#define MESSAGEMAIN_register_confirm_delete "ïîäòâåðäèòü óäàëåíèå" +#define MESSAGEMAIN_register_view_saving "Èñïîëüçîâàòü ïðîôàéë äëÿ õðàíåíèÿ íàñòðîåê âíåøíåãî âèäà" + +#define CONFIRM_DELETE_CHECKBOX_TEXT "confirm_delete" + +/**************** Ðåãèñòðàöèîííûå ñîîáùåíèÿ ***************/ +/**************** registration mnssages ***************/ +#define MESSAGEMAIN_register_create_ex "Ïðîôèëü ñîçäàí" +#define MESSAGEMAIN_register_create_ex2 "è Âû àâòîìàòè÷åñêè âîøëè" + +#define MESSAGEMAIN_register_edit_ex "Ïîëüçîâàòåëü áûë ñîçäàí / èçìåíåí" +#define MESSAGEMAIN_register_edit_ex2 "" + +#define MESSAGEMAIN_register_edit_err "Ïðîèçîøëà îøèáêà ïðè îáíîâëåíèè ïðîôàéëà" +#define MESSAGEMAIN_register_edit_err2 "Âîçìîæíî, ñòîèò ïîïðîáîâàòü åùå ðàç" + +#define MESSAGEMAIN_register_delete_ex "Ïîëüçîâàòåëü óäàëåí" +#define MESSAGEMAIN_register_delete_ex2 "" + +#define MESSAGEMAIN_register_delete_logoff "Âàø àêêàóíò áûë óäàëåí" +#define MESSAGEMAIN_register_delete_logoff2 "" + +#define MESSAGEMAIN_register_already_exit "Ýòî èìÿ óæå çàíÿòî" +#define MESSAGEMAIN_register_already_exit2 "Ïîïðîáóéòå ïðèäóìàòü äðóãîå èìÿ" + +#define MESSAGEMAIN_register_invalid_psw "Èìÿ èëè ïàðîëü ââåäåíû íåïðàâèëüíî" +#define MESSAGEMAIN_register_invalid_psw2 "Âû äîëæíû ââåñòè ïðàâèëüíîå èìÿ è ïàðîëü èëè åñëè âû èçìåíÿåòå" \ + " èíôîðìàöèþ î ñåáå âû äîëæíû ïåðåä ýòèì âîéòè â ñèñòåìó" + +#define MESSAGEMAIN_register_invalid_n_psw "Ïîäòâåðæäåíèå ïàðîëÿ íå ñîâïàäàåò èëè ïàðîëü ñëèøêîì êîðîòêèé" +#define MESSAGEMAIN_register_invalid_n_psw2 "Äëÿ ïîäòâåðæäåíèÿ ïàðîëÿ âàì íåîáõîäèìî ââåñòè åãî âåðíî" \ + " äâàæäû è äëèíà ïàðîëÿ äîëæíà áûòü íå ìåíåå 3 ñèìâîëîâ" + +#define MESSAGEMAIN_register_invalid_email "Ââåäåííûé E-Mail àäðåñ íåêîððåêòåí" +#define MESSAGEMAIN_register_invalid_email2 "×òîáû çàðåãèñòðèðîâàòüñÿ â êîíôåðåíöèè Âû äîëæíû ââåñòè äåéñòâóþùèé" \ + " E-Mail èíà÷å Âû íå ñìîæåòå ïîëüçîâàòüñÿ íåêîòîðûìè ôóíêöèÿìè êîíôåðåíöèè" + +#define MESSAGEMAIN_register_cannot_delete "Ïîëüçîâàòåëü %s íå ìîæåò áûòü óäàëåí" +#define MESSAGEMAIN_register_cannot_delete2 "Âû äîëæíû ââåñòè ïðàâèëüíîå èìÿ è ïàðîëü" + +#define MESSAGEMAIN_register_invalid_lg_spell "Íåò òàêîãî èìåíè ïîëüçîâàòåëÿ èëè îíî íåïðàâèëüíîå" +#define MESSAGEMAIN_register_invalid_lg_spell2 "Âû äîëæíû ââåñòè ïðàâèëüíîå èìÿ è ïàðîëü(äëèíà èìåíè äîëæíà áûòü íå ìåíüøå 3 ñèìâîëîâ)" + + +/***************** profile information *****************/ +#define MESSAGEMAIN_profview_intro "Èíôîðìàöèÿ î ïîëüçîâàòåëå: " +#define MESSAGEMAIN_profview_login "Èìÿ: " +#define MESSAGEMAIN_profview_postpersmsg "îòïðàâèòü ïðèâàòíîå ñîîáùåíèå" +#define MESSAGEMAIN_profview_editinfo "èçìåíèòü" +#define MESSAGEMAIN_profview_altname "Àëüòåðíàòèâíîå èìÿ: " +#define MESSAGEMAIN_profview_fullname "Ïîëíîå èìÿ: " +#define MESSAGEMAIN_profview_homepage "Äîìàøíÿÿ ñòðàíèöà: " +#define MESSAGEMAIN_profview_email "Email: " +#define MESSAGEMAIN_profview_dogsubstitute " at " +#define MESSAGEMAIN_profview_user_icq "ICQ: " +#define MESSAGEMAIN_profview_user_status "Ñòàòóñ: " +#define MESSAGEMAIN_profview_u_moderator "Ìîäåðàòîð" +#define MESSAGEMAIN_profview_u_user "Îáû÷íûé ïîëüçîâàòåëü" +#define MESSAGEMAIN_profview_postcount "×èñëî ñîîáùåíèé: " +#define MESSAGEMAIN_profview_reg_date "Äàòà ðåãèñòðàöèè: " +#define MESSAGEMAIN_profview_login_date "Âðåìÿ ïîñëåäíåãî äîñòóïà: " +#define MESSAGEMAIN_profview_about_user "Î ïîëüçîâàòåëå: " +#define MESSAGEMAIN_profview_refreshcnt "×èñëî îáíîâëåíèé: " +#define MESSAGEMAIN_profview_lastip "Ïîñëåäíèé âõîä ñ: " +#define MESSAGEMAIN_profview_persmsgcnt "Âñåãî ïåðñîíàëüíûõ ñîîáùåíèé(ïðî÷èòàíî): " + +#define MESSAGEMAIN_profview_no_user "

    Ïîëüçîâàòåëü %s íå çàðåãèñòðèðîâàí â ýòîé êîíôåðåíöèè
    " + +#define MESSAGEMAIN_profview_privacy_prof "Äàëüíåéøàÿ èíôîðìàöèÿ î ïîëüçîâàòåëå íåäîñòóïíà" +#define MESSAGEMAIN_profview_privacy_inf "Ëè÷íàÿ èíôîðìàöèÿ" + +#define MESSAGEMAIN_profview_sechdr "Êîä áåçîïàñòíîñòè äëÿ òåìû: " +#define MESSAGEMAIN_profview_secbdy "Êîä áåçîïàñòíîñòè äëÿ òåëà: " + +// user statuses +#define USER_STATUS_COUNT 5 +extern char *UserStatus_List[USER_STATUS_COUNT]; + +extern char *UserRight_List[USERRIGHT_COUNT]; + +/******************* session information *******************/ +#define MESSAGEMAIN_session_intro "Çàðåãèñòðèðîâàííûå ñåññèè " +#define MESSAGEMAIN_session_ip "IP àäðåñ âõîäà:" +#define MESSAGEMAIN_session_date "Âðåìÿ ïîñëåäíåãî äîñòóïà:" +#define MESSAGEMAIN_session_state "Ñîñòîÿíèå ñåññèè:" +#define MESSAGEMAIN_session_state_active "àêòèâíàÿ" +#define MESSAGEMAIN_session_state_toclose "çàêðûòü" +#define MESSAGEMAIN_session_state_closed "çàêðûòà" +#define MESSAGEMAIN_session_no "íåò ñåññèé" +#define MESSAGEMAIN_session_closed_ok "Ñåññèÿ çàêðûòà
    " +#define MESSAGEMAIN_session_closed_ok2 "Ñïàñèáî çà ó÷àñòèå!" +#define MESSAGEMAIN_session_closed_no "Ñåññèÿ íå çàêðûòà
    " +#define MESSAGEMAIN_session_check_failed "Ñåññèÿ íå íàéäåíà
    Âîçìîæíî, îíà áûëà òîëüêî ÷òî çàêðûòà" +#define MESSAGEMAIN_session_close_failed "Îøèáêà ïðè çàêðûòèè ñåññèè
    " +#define MESSAGEMAIN_session_ip_nocheck "(áåç ïðîâåðêè)" +#define MESSAGEMAIN_session_ip_check "" + +/************* private(personal) messages **************/ +#define MESSAGEMAIN_privatemsg_send_message "Îòïðàâèòü ñîîáùåíèå" +#define MESSAGEMAIN_privatemsg_send_msg_btn "Îòïðàâèòü" +#define MESSAGEMAIN_privatemsg_prev_msg_btn "Ïðåäïðîñìîòð" +#define MESSAGEMAIN_privatemsg_send_msg_hdr "Îòïðàâèòü ëè÷íîå ñîîáùåíèå" +#define MESSAGEMAIN_privatemsg_send_msg_usr "Ïîëüçîâàòåëþ: " +#define MESSAGEMAIN_privatemsg_send_msg_bdy "Ñîîáùåíèå (íå ìîæåò áûòü áîëüøå 384 ñèìâîëîâ)" + +#define MESSAGEMAIN_privatemsg_msgwassent "Ñîîáùåíèå áûëî îòïðàâëåíî ïîëüçîâàòåëþ" +#define MESSAGEMAIN_privatemsg_msgwassent2 "Ñïàñèáî çà ó÷àñòèå" + +#define MESSAGEMAIN_privatemsg_msgcantsend "Ñîîáùåíèå íå ìîæåò áûòü îòïðàâëåíî !" +#define MESSAGEMAIN_privatemsg_msgcantsend2 "Ïîïðîáóéòå ïîçæå !" + +#define MESSAGEMAIN_privatemsg_denyunreg "Äàííàÿ âîçìîæíîñòü íåäîñòóïíà íåçàðåãèñòðèðîâàííûì ïîëüçîâàòåëÿì !
    " +#define MESSAGEMAIN_privatemsg_denyunreg2 "Äëÿ òîãî ÷òîá èìåòü âîçìîæíîñòü îòïðàâëÿòü è ïîëó÷àòü ïåðñîíàëüíîå ñîîáùåíèå Âû äîëæíû çàðåãèñòðèðîâàòüñÿ â êîíôåðåíöèè !

    " + +#define MESSAGEMAIN_privatemsg_invalid_user "Âû äîëæíû óêàçàòü ñóùåñòâóþùèé íèê ïîëüçîâàòåëÿ" +#define MESSAGEMAIN_privatemsg_invalid_body "Ñîîáùåíèå íå ìîæåò áûòü ïóñòîå (èíà÷å êàêîé ñìûñë åãî ïîñûëàòü ?)" +#define MESSAGEMAIN_privatemsg_tolong_body "Ñîîáùåíèå ñëèøêîì äëèííîå, óìåíüøèòå åãî äëèíó" +#define MESSAGEMAIN_privatemsg_disable_pmsg "Ïîëüçîâàòåëü çàïðåòèë ïîëó÷åíèå ïåðñîíàëüíûõ ñîîáùåíèé,
    îòïðàâèòü åìó ïåðñîíàëüíîå ñîîáùåíèå íåâîçìîæíî" + +#define MESSAGEMAIN_privatemsg_header "Ïåðñîíàëüíûå ñîîáùåíèÿ äëÿ ïîëüçîâàòåëÿ" + +#define MESSAGEMAIN_privatemsg_disabled "Ïîëó÷åíèå ïåðñîíàëüíûõ ñîîîáùåíèé çàïðåùåíî!" + +#define MESSAGEMAIN_privatemsg_newmsgcnt "Êîëè÷åñòâî íîâûõ ñîîáùåíèé:" +#define MESSAGEMAIN_privatemsg_nonewmsg "Íîâûõ ñîîáùåíèé íåò" + +#define MESSAGEMAIN_privatemsg_allmsgcnt "Ñîîáùåíèé âñåãî, ïîëó÷åíî:" +#define MESSAGEMAIN_privatemsg_allmsgcnt1 "îòïðàâëåíî:" + +#define MESSAGEMAIN_privatemsg_writenewmsg "Íàïèñàòü íîâîå ïåðñîíàëüíîå ñîîáùåíèå" + +#define MESSAGEMAIN_privatemsg_newmsgann "Åñòü" +#define MESSAGEMAIN_privatemsg_newmsgann1 "íåïðî÷èòàííûõ ëè÷íûõ ñîîáùåíèé äëÿ Âàñ!" + +#define MESSAGEMAIN_privatemsg_newmark "[ Íîâîå !]" + +#define MESSAGEMAIN_privatemsg_answer "[Îòâåòèòü]" + +#define MESSAGEMAIN_privatemsg_fromuser "Îò ïîëüçîâàòåëÿ:" +#define MESSAGEMAIN_privatemsg_touser "Ïîëüçîâàòåëþ:" +#define MESSAGEMAIN_privatemsg_date "Îòïðàâëåíî:" + +/***************** favourites system *****************/ +#define MESSAGEMAIN_favourites_denyunreg "Äàííàÿ âîçìîæíîñòü íåäîñòóïíà íåçàðåãèñòðèðîâàííûì ïîëüçîâàòåëÿì !
    " +#define MESSAGEMAIN_favourites_denyunreg2 "Äëÿ òîãî, ÷òîáû èìåòü âîçìîæíîñòü õðàíèòü ññûëêè íà èçáðàííûå ñîîáùåíèÿ, Âû äîëæíû çàðåãèñòðèðîâàòüñÿ è âîéòè â êîíôåðåíöèþ !

    " + +#define MESSAGEMAIN_favourites_listclear "Âàø ñïèñîê èçáðàííîãî ïóñò" + +#if USER_FAVOURITES_SUPPORT == 1 +#define MESSAGEMAIN_favourites_added "Ñîîáùåíèå çàíåñåíî â Èçáðàííîå!
    " +#define MESSAGEMAIN_favourites_added2 "Ñïàñèáî çà ó÷àñòèå !
    Òåïåðü ññûëêó íà ýòî ñîîáùåíèå ìîæíî íàéòè â ñïèñêå
    " +#define MESSAGEMAIN_favourites_addno "Ñîîáùåíèå íå çàíåñåíî â Èçáðàííîå!
    " +#define MESSAGEMAIN_favourites_addexist "Ñîîáùåíèå óæå ïðèñóòñòâóåò â ñïèñêå!
    Âîçìîæíî, Âû òîëüêî ÷òî åãî äîáàâèëè è ïûòàåòåñü ñäåëàòü ýòî åùå ðàç
    " +#define MESSAGEMAIN_favourites_addnoplace "Ó Âàñ óæå ñîõðàíåíî 20 ñîîáùåíèé!
    Äëÿ òîãî, ÷òîáû äîáàâèòü ýòî ñîîáùåíèå, íåîáõîäèìî óäàëèòü õîòÿ áû îäíî èç óæå ñîõðàíåííûõ
    " +#define MESSAGEMAIN_favourites_deleted "Ñîîáùåíèå óäàëåíî èç Èçáðàííîãî!
    " +#define MESSAGEMAIN_favourites_deleted2 "Ñïàñèáî çà ó÷àñòèå !

    " +#define MESSAGEMAIN_favourites_delno "Ñîîáùåíèå íå óäàëåíî èç Èçáðàííîãî!
    " +#define MESSAGEMAIN_favourites_delnoexist "Ñîîáùåíèÿ íåò â ñïèñêå !
    Âîçìîæíî, Âû òîëüêî ÷òî åãî óäàëèëè
    " +#else +#define MESSAGEMAIN_favourites_added "Ïîòîê çàíåñåí â Èçáðàííîå!
    " +#define MESSAGEMAIN_favourites_added2 "Ñïàñèáî çà ó÷àñòèå !
    Òåïåðü ññûëêó íà ýòîò ïîòîê ìîæíî íàéòè â ñïèñêå
    " +#define MESSAGEMAIN_favourites_addno "Ïîòîê íå çàíåñåí â Èçáðàííîå!
    " +#define MESSAGEMAIN_favourites_addexist "Ïîòîê óæå ïðèñóòñòâóåò â ñïèñêå!
    Âîçìîæíî, Âû òîëüêî ÷òî åãî äîáàâèëè
    " +#define MESSAGEMAIN_favourites_addnoplace "Ó Âàñ óæå ñîõðàíåíî 20 ïîòîêîâ!
    Äëÿ òîãî, ÷òîáû äîáàâèòü ýòîò òðåä, íåîáõîäèìî óäàëèòü õîòÿ áû îäèí èç óæå ñîõðàíåííûõ
    " +#define MESSAGEMAIN_favourites_deleted "Ïîòîê óäàëåí èç Èçáðàííîãî!
    " +#define MESSAGEMAIN_favourites_deleted2 "Ñïàñèáî çà ó÷àñòèå !

    " +#define MESSAGEMAIN_favourites_delno "Ïîòîê íå óäàëåí èç Èçáðàííîãî!
    " +#define MESSAGEMAIN_favourites_delnoexist "Ïîòîêà íåò â ñïèñêå !
    Âîçìîæíî, Âû òîëüêî ÷òî åãî óäàëèëè
    " +#define MESSAGEMAIN_favourites_addnoparent "Ñîîáùåíèå íå ÿâëÿåòñÿ ïåðâûì äëÿ äàííîãî ïîòîêà!
    Äîáàâëÿòü ìîæíî òîëüêî ïåðâûå ñîîáùåíèÿ â òðåäå" +#endif + +/****************** global announces *****************/ +#define MESSAGEMAIN_globann_send_ann_hdr "Ðàçìåñòèòü íîâûé ãëîáàëüíûé àíîíñ" +#define MESSAGEMAIN_globann_upd_ann_hdr "Èçìåíèòü ãëîáàëüíûé àíîíñ" +#define MESSAGEMAIN_globann_send_ann_body "Òåêñò àíîíñà (íå ìîæåò áûòü áîëüøå 512 ñèìâîëîâ)" +#define MESSAGEMAIN_globann_upd_ann_id "Îáíîâèòü íîìåð àíîíñà (ñíîâà âñïëûâåò)" +#define MESSAGEMAIN_globann_send_ann_btn "Îòïðàâèòü" +#define MESSAGEMAIN_globann_prev_ann_btn "Ïðåäïðîñìîòð" + +#define MESSAGEMAIN_globann_preview_hdr "Ïðåäâàðèòåëüíûé ïðîñìîòð àíîíñà" + +#define MESSAGEMAIN_globann_anncantsend "Àíîíñ íå ìîæåò áûòü äîáàâëåí !" +#define MESSAGEMAIN_globann_anncantsend2 "Ìîæåò áûòü Âàì ñòîèò ïîïðîáîâàòü ïîçæå..." + +#define MESSAGEMAIN_globann_annwassent "Àíîíñ áûë äîáàâëåí" +#define MESSAGEMAIN_globann_annwassent2 "Ñïàñèáî çà ó÷àñòèå" + +#define MESSAGEMAIN_globann_annwasupdated "Àíîíñ áûë îáíîâëåí" +#define MESSAGEMAIN_globann_annwasupdated2 "Ñïàñèáî çà ó÷àñòèå" + +#define MESSAGEMAIN_globann_tolong "Àíîíñ ñëèøêîì äëèííûé, óìåíüøèòå åãî è ïîâòîðèòå ïîïûòêó" +#define MESSAGEMAIN_globann_toshort "Àíîíñ ñëèøêîì êîðîòêèé, çà÷åì åãî âîîáùå ïèñàòü ;) ?" + +#define MESSAGEMAIN_globann_wasdeleted "Àíîíñ áûë óñïåøíî óäàëåí" +#define MESSAGEMAIN_globann_wasdeleted2 "
    " + +#define MESSAGEMAIN_globann_cannotdel "Àíîíñ íå ìîæåò áûòü óäàëåí!" +#define MESSAGEMAIN_globann_cannotdel2 "Âîçìîæíî, ó Âàñ íåäîñòàòî÷íî ïðàâ äëÿ óäàëåíèÿ" + +#define MESSAGEMAIN_globann_invalidnum "Óêàçàí íå ñóùåñòâóþùèé èäåíòèôèêàòîð àíîíñà!" +#define MESSAGEMAIN_globann_invalidnum2 "Ïðîâåðüòå è îáíîâèòå ññûëêó ïî êîòîðîé Âû ïîïàëè ñþäà" + +#define MESSAGEMAIN_globann_delannounce "Óäàëèòü ýòîò àíîíñ" +#define MESSAGEMAIN_globann_updannounce "Îáíîâèòü ýòîò àíîíñ" +#define MESSAGEMAIN_globann_postedby "Îòïðàâëåí" + +#define MESSAGEMAIN_globann_showall "Ïîêàçàòü âñå àêòèâíûå àíîíñû" +#define MESSAGEMAIN_globann_hidenewann "Ñêðûòü òåêóùèå àíîíñû" + +/****************** moderation form ******************/ +#define MESSAGEMAIN_moderate_hide_thread "Ñêðûòü ýòó âåòâü" +#define MESSAGEMAIN_moderate_close_thread "Çàêðûòü ýòó âåòâü" +#define MESSAGEMAIN_moderate_unhide_thread "Ïîêàçàòü ýòó âåòâü" +#define MESSAGEMAIN_moderate_unclose_thread "Îòêðûòü ýòó âåòâü" +#define MESSAGEMAIN_moderate_delete_thread "Óäàëèòü ýòó âåòâü" +#define MESSAGEMAIN_moderate_change_message "Èçìåíèòü ýòî ñîîáùåíèå" +#define MESSAGEMAIN_moderate_roll "Ñâåðíóòü ýòó âåòâü" +#define MESSAGEMAIN_moderate_unroll "Ðàçâåðíóòü ýòó âåòâü" + +/********************* Ôîðìà âõîäà *********************/ +#define MESSAGEMAIN_login_login_header "Ââåäèòå Âàøå èìÿ è ïàðîëü" +#define MESSAGEMAIN_login_loginname " Èìÿ : " +#define MESSAGEMAIN_login_password " Ïàðîëü : " +#define MESSAGEMAIN_login_ipcheckshort "Íå ïðîâåðÿòü IP" +#define MESSAGEMAIN_login_ipcheck "Íå ïðîâåðÿòü IP àäðåñ äëÿ ñåññèè" + +#define MESSAGEMAIN_login_lostpassw "
    Åñëè Âû çàáûëè Âàø ïàðîëü êëèêíèòå òóò


    " + +/**************** Ôîðìà "çàáûëè ïàðîëü" ****************/ +#define MESSAGEMAIN_lostpassw_header "Ñèñòåìà íàïîìèíàíèÿ ïàðîëÿ

    Ââåäèòå Âàø íèê è àäðåñ ýëåêòðîííîé ïî÷òû
    " \ + "è Âû ïîëó÷èòå ïèñüìî ñ âàøèì ïàðîëåì" +#define MESSAGEMAIN_lostpassw_hretry "Âû óêàçàëè íåâåðíûé íèê è/èëè àäðåñ ýëåêòðîííîé ïî÷òû
    " \ + "Ïîæàëóéñòà, ïðîâåðüòå Âàø íèê è email è ïîâòîðèòå ïîïûòêó åùå ðàç" +#define MESSAGEMAIN_lostpassw_loginname " Íèê : " +#define MESSAGEMAIN_lostpassw_email " Email : " +#define MESSAGEMAIN_lostpassw_getpassw "Ïîëó÷èòü ïàðîëü" + +/****************** search form ******************/ +#define MESSAGEMAIN_search_searchmsg "Èñêàòü ñîîáùåíèÿ" + +#define MESSAGEMAIN_search_howtouse "Ââåäåíèå â ïðàâèëà èñïîëüçîâàíèÿ ïîèñêà.
    Ïîèñê âåäåòñÿ ïî ÷àñòè÷íûì êóñêàì ñëîâ (íå ìåíüøå òðåõ ñèìâîëîâ!) ñîäåðæàùèìñÿ â " \ + "òåëå èëè çàãîëîâêå ñîîáùåíèÿ.
    Ñëîâà â ñòðîêå ïîèñêà ìîæíî ðàçäåëÿòü ïðîáåëàìè, ÷òî çíà÷èò èñêàòü" \ + " ñîîáùåíèÿ ñîäåðæàùèå âñå òàêèå ïîäñòðîêè.
    Íà äàííîì ñåðâåðå ïîèñê ìîæåò çàíÿòü îò 1 äî 10 ñåêóíä " \ + "(â çàâèñèìîñòè îò çàãðóæåííîñòè), ïîýòîìó, ðåêîìåíäóåòñÿ äîæäàòüñÿ ðåçóëüòàòîâ ïîèñêà, à íå íàæèìàòü \"Ïîèñê\" " \ + "åùå ðàç." +#define MESSAGEMAIN_search_lastindexed "Ïîñëåäíåå ïðîèíäåêñèðîâàíîå ñîîáùåíèå" +#define MESSAGEMAIN_search_notindexed "Èíäåêñàöèÿ íå âûïîëíåíà" +#define MESSAGEMAIN_search_indexerror "Îøèáêà èíäåêñîâ" +#define MESSAGEMAIN_search_containing "ñîäåðæàùèå" +#define MESSAGEMAIN_search_sentby "ïîñëàííûå" +#define MESSAGEMAIN_search_search_str "Ñòðîêà çàïðîñà : " +#define MESSAGEMAIN_search_result1 "Ðåçóëüòàò ïîèñêà: " +#define MESSAGEMAIN_search_result2 "ñîâïàäåíèé íàéäåíî (Áóäåò ïîêàçàíî 100 íà ñòðàíèöó)" +#define MESSAGEMAIN_search_result_nothing "Íè÷åãî íå íàéäåíî, ïîïðîáóéòå èçìåíèòü êëþ÷åâûå ñëîâà ïîèñêà" +#define MESSAGEMAIN_search_result_pages "Ñòðàíèöû ðåçóëüòàòîâ:" + +/******************* message view form ******************/ +#define MESSAGEMAIN_viewthread_sent "Ñîîáùåíèå áûëî ïîñëàíî:" +#define MESSAGEMAIN_viewthread_ipview ", IP: " +#define MESSAGEMAIN_viewthread_date "Äàòà:" +#define MESSAGEMAIN_viewthread_mdate "Èçìåíåí:" +#define MESSAGEMAIN_viewthread_sigdisabled "Ïîëüçîâàòåëü èìååò ïîäïèñü, íî îòîáðàæåíèå ïîäïèñåé çàïðåùåíî â íàñòðîéêàõ." +#define MESSAGEMAIN_in_this_thread "
    Ñîîáùåíèÿ â ýòîì ïîòîêå
    " + +/********************** userlist ***********************/ +#define MESSAGEMAIN_total_user_count "Âñåãî ïîëüçîâàòåëåé: " +#define MESSAGEMAIN_userlist_sortby "Ñîðòèðîâàòü ïî: " +#define MESSAGEMAIN_userlist_sortbyname "íèêó" +#define MESSAGEMAIN_userlist_sortbydate "äàòå ïîñëåäíåãî äîñòóïà" +#define MESSAGEMAIN_userlist_sortbypcnt "êîë-âó ñîîáùåíèé" +#define MESSAGEMAIN_userlist_sortbyhost "õîñòó/IP àäðåñó" +#define MESSAGEMAIN_userlist_sortbyrefresh "ïî êîëè÷åñòâó îáíîâëåíèé" +#define MESSAGEMAIN_userlist_sortbyright "ïî ïðàâàì ïîëüçîâàòåëåé" + +/****************** configure form ******************/ +#define MESSAGEHEAD_to_message "Ïåðåéòè ê îòâåòàì" +#define MESSAGEHEAD_configure_showmsgs "Ïîêàçàòü âåòâè" +#define MESSAGEHEAD_configure_msgslast " ïîñëàííûå â òå÷åíèå ïîñëåäíèõ " +#define MESSAGEHEAD_configure_lastnum " ïîñëåäíèõ " +#define MESSAGEHEAD_configure_lastnum2 " âåòâåé " +#define MESSAGEHEAD_configure_showstyle "Ñòèëü îòîáðàæåíèÿ : " +#define MESSAGEHEAD_configure_disablesmiles "Ãëîáàëüíî îòìåíèòü ñìàéë-êîäû" +#define MESSAGEHEAD_configure_disableuppic "Îòêëþ÷èòü çàãîëîâîê êîíôåðåíöèè" +#define MESSAGEHEAD_configure_disable2links "Îòêëþ÷èòü âòîðóþ ñòðîêó ññûëîê" +#define MESSAGEHEAD_configure_ownpostshighlight "Îòêëþ÷èòü âûäåëåíèå ñîáñòâåííûõ ñîîáùåíèé" +#define MESSAGEHEAD_configure_showhostnames "Îòêëþ÷èòü îòîáðàæåíèå õîñòîâ â èíäåêñå" +#define MESSAGEHEAD_configure_showaltnames "Îòêëþ÷èòü îòîáðàæåíèå àëüòåðíàòèâíûõ èìåí" +#define MESSAGEHEAD_configure_showsign "Îòêëþ÷èòü îòîáðàæåíèå ïîäïèñåé ïîëüçîâàòåëåé" +#define MESSAGEHEAD_configure_plus_is_href "\" " TAG_NEW_MSG_MARK "\" ÿâëÿåòñÿ ññûëêîé íà ñëåäóþùåå íîâîå ñîîáùåíèå" +#define MESSAGEHEAD_configure_showreplyform "Íå îòîáðàæàòü ôîðìó îòâåòà" +#define MESSAGEHEAD_configure_applysettings "Ñîõðàíèòü íàñòðîéêè" + + +#define MESSAGEHEAD_configure_saving_to_profile "Íàñòðîéêè ñîõðàíÿþòñÿ â ïðîôàéëå è áóäóò äîñòóïíû ñ ëþáîãî áðàóçåðà" +#define MESSAGEHEAD_configure_saving_to_browser "Íàñòðîéêè ñîõðàíÿþòñÿ â áðàóçåðå è äîñòóïíû òîëüêî ñ äàííîãî êîìïüþòåðà" +#define MESSAGEHEAD_configure_view_saving "Èçìåíèòü ñïîñîá õðàíåíèÿ íàñòðîåê ìîæíî íà ñòðàíèöå ðåäàêòèðîâàíèÿ ïðîôàéëà" + +// coded as "1" +//#define MESSAGEHEAD_configure_showhronforward "Ïî ïîòîêàì â õðîíîëîãè÷åñêîì âèäå, ïî âîçðàñòàíèþ" +// coded as "2" +#define MESSAGEHEAD_configure_showhronbackward "Ïî ïîòîêàì â õðîíîëîãè÷åñêîì âèäå, ïî óáûâàíèþ" +// coded as "3" +#define MESSAGEHEAD_configure_showhronwothreads "Ïî ñîîáùåíèÿì â õðîíîëîãè÷åñêîì âèäå, ïî âîçðàñòàíèþ" +// coded as "4" +#define MESSAGEHEAD_configure_showhrononlyheaders "Ïî ñîîáùåíèÿì â õðîíîëîãè÷åñêîì âèäå, òîëüêî çàãîëîâêè" + + +#define WWWCONF_FULL_NAME "Ôîðóì" + +// for STABLE_TITLE = 1 +#if STABLE_TITLE == 1 +#define TITLE_StaticTitle "not used " VERSION +#endif + +/******************* topic support *********************/ +#if TOPICS_SYSTEM_SUPPORT +#define TOPICS_COUNT 18 +#define TOPICS_DEFAULT_SELECTED 0 +// this variable should be defined in main.cpp +extern char *Topics_List[TOPICS_COUNT]; +extern int Topics_List_map[TOPICS_COUNT]; +#endif + +/**************************** title messages *****************************/ +// for STABLE_TITLE = 0 +// board name prefix +#define TITLE_WWWConfBegining "Ôîðóì" +#define TITLE_divider " : " +// forms name +#define TITLE_WWWConfIndex " " +#define TITLE_Form "Íîâîå ñîîáùåíèå" +#define TITLE_WriteReply "Íàïèñàòü îòâåò" +#define TITLE_Configure "Íàñòðîéêà" +#define TITLE_Error "Îøèáêà !" +#define TITLE_Spamtry "Áëîêèðîâàíà ïîïûòêà ñïàìà!" +#define TITLE_Login "Âõîä â êîíôåðåíöèþ" +#define TITLE_Logoff "Âûõîä èç êîíôåðåíöèè" +#define TITLE_LostPassword "Çàáûëè ïàðîëü?" +#define TITLE_PasswordSent "Ïàðîëü îòïðàâëåí" +#define TITLE_IncorrectPassword "Íåïðàâèëüíûé ïàðîëü!" +#define TITLE_ClosingMessage "Çàêðûòü ñîîáùåíèÿ" +#define TITLE_HidingMessage "Ñêðûòü ñîîáùåíèÿ" +#define TITLE_DeletingMessage "Óäàëèòü ñîîáùåíèÿ" +#define TITLE_ChangingMessage "Èçìåíèòü ñîîáùåíèå - " +#define TITLE_RollMessage "Ðàçâåðíóòü ñîîáùåíèå" +#define TITLE_HelpPage "Ñïðàâêà" +#define TITLE_Registration "Ðåãèñòðàöèÿ / èçìåíèòü ïðîôèëü" +#define TITLE_Search "Ïîèñê ñîîáùåíèé" +#define TITLE_ProfileInfo "Èíôîðìàöèÿ î ïîëüçîâàòåëå" +#define TITLE_UserList "Ñïèñîê þçåðîâ" +#define TITLE_PrivateMsg "Ïðèâàòíûå ñîîáùåíèÿ" +#define TITLE_AddPrivateMsg "Íàïèñàòü ïðèâàòíîå ñîîáùåíèÿ" +#define TITLE_PrivateMsgWasPosted "Ïðèâàòíîå ñîîáùåíèå îòïðàâëåíî" +#define TITLE_PostGlobalAnnounce "Äîáàâèòü ãëîáàëüíûé àíîíñ" +#define TITLE_GlobalAnnWasPosed "Ãëîáàëüíûé àíîíñ äîáàâëåí" +#define TITLE_GlobalAnnWasDeleted "Ãëîáàëüíûé àíîíñ óäàëåí" +#define TITLE_FavouritesPage "Èçáðàííîå" +#define TITLE_FavouritesPageAdd "Äîáàâëåíèå òåìû â Èçáðàííîå" +#define TITLE_FavouritesPageDel "Óäàëåíèå òåìû èç Èçáðàííîãî" +#define TITLE_BanSave "Ñîõðàíåíèå ñïèñêà çàáàíåííûõ àéïè" +#define TITLE_ClSession "Çàêðûòèå ñåññèè" + +/***************************** welcome messages **************************/ +#define WELCOME_CONFERENCE_HEADER "Âõîä: "//"Âñåëåíñêîå ÇËÎ: " // :))) // namek ponyat :) +//#define ZLO "" + +#define MESSAGEMAIN_ACTIVITY_STATVIEW "Àêòèâíîñòü: %ld %ld" \ + " çà ïîñëåäíèå 10 ìèíóò" +#define MESSAGEMAIN_WELCOME_LOGGEDSTART "" \ + "
    " \ + WELCOME_CONFERENCE_HEADER MESSAGEMAIN_WELCOME_HELLOREG "%s%s
    %s%s
    %s
    " MESSAGEMAIN_WELCOME_SELECTTOPIC " %s
    " + +#define MESSAGEMAIN_WELCOME_START "" \ + "
    "\ + "
    "\ + " " WELCOME_CONFERENCE_HEADER MESSAGEMAIN_login_loginname \ + "   " MESSAGEMAIN_login_password \ + "   "\ + "" MESSAGEMAIN_login_ipcheckshort \ + "   
    %s%s
    %s
    " MESSAGEMAIN_WELCOME_SELECTTOPIC " %s
    " + +#define MESSAGEMAIN_WELCOME_HELLOREG "Âû âîøëè â êîíôåðåíöèþ êàê " +#define MESSAGEMAIN_WELCOME_SELECTTOPIC "Âûáåðèòå òåìó:" + +#define MESSAGEMAIN_WELCOME_NEWTHREADS_TEXT "íîâûõ ïîòîêîâ(ñîîáùåíèé): %ld(%ld) èç %ld" +#define MESSAGEMAIN_WELCOME_NEWTHREADS ""\ + MESSAGEMAIN_WELCOME_NEWTHREADS_TEXT"" + +#define MESSAGEMAIN_WELCOME_NONEWTHREADS_TEXT "íîâûõ ñîîáùåíèé íåò, âñåãî %ld" +#define MESSAGEMAIN_WELCOME_NONEWTHREADS ""\ + MESSAGEMAIN_WELCOME_NONEWTHREADS_TEXT"" + + +#define MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT_NEW "" +#define MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT_NO_NEW "" + +#define MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT "" + + + +#define MESSAGEMAIN_WELCOME_DISPLAYTIME ", ïîêàçàíû ñîîáùåíèÿ çà %d %s" +#define MESSAGEMAIN_WELCOME_DISPLAYTHREADS ", ïîêàçàíû ïîñëåäíèå %d ïîòîêîâ" + +#define MESSAGEMAIN_WELCOME_YOURSETTINGS "âàøè òåêóùèå òåìû" +#define MESSAGEMAIN_WELCOME_ALLTOPICS "âñå òåìû" + +/**************************** date/time messages *************************/ +#define MESSAGEMAIN_DATETIME_JAN "ßíâàðü" +#define MESSAGEMAIN_DATETIME_FEB "Ôåâðàëü" +#define MESSAGEMAIN_DATETIME_MAR "Ìàðò" +#define MESSAGEMAIN_DATETIME_APR "Àïðåëü" +#define MESSAGEMAIN_DATETIME_MAY "Ìàé" +#define MESSAGEMAIN_DATETIME_JUN "Èþíü" +#define MESSAGEMAIN_DATETIME_JUL "Èþëü" +#define MESSAGEMAIN_DATETIME_AUG "Àâãóñò" +#define MESSAGEMAIN_DATETIME_SEP "Ñåíòÿáðü" +#define MESSAGEMAIN_DATETIME_OCT "Îêòÿáðü" +#define MESSAGEMAIN_DATETIME_NOV "Íîÿáðü" +#define MESSAGEMAIN_DATETIME_DEC "Äåêàáðü" + +#define MESSAGEMAIN_DATETIME_DAY_SUN "Âîñêðåñåíüå" +#define MESSAGEMAIN_DATETIME_DAY_MON "Ïîíåäåëüíèê" +#define MESSAGEMAIN_DATETIME_DAY_TEU "Âòîðíèê" +#define MESSAGEMAIN_DATETIME_DAY_WED "Ñðåäà" +#define MESSAGEMAIN_DATETIME_DAY_THU "×åòâåðã" +#define MESSAGEMAIN_DATETIME_DAY_FRI "Ïÿòíèöà" +#define MESSAGEMAIN_DATETIME_DAY_SAT "Ñóááîòà" + +/**************************** mailing messeges ***************************/ + +#define MAILACKN_HEADER "Content-type: text/html; charset=\"windows-1251\"\r\n\r\n" + + +#define MAIL_SEND_GREETING "Çäðàâñòâóéòå, "\ + "%s.
    " + +#define MAIL_SEND_SIGNING "Ýòî ïèñüìî ïîñëàíî àâòîìàòè÷åñêè ôîðóìîì "WWWCONF_FULL_NAME \ + ".
    Âàì íå ñëåäóåò îòâå÷àòü íà íåãî.
    " + +// reply notification +#define MAILACKN_REPLY_SUBJECT WWWCONF_FULL_NAME ": %s" +#define MAILACKN_REPLY_BODY MAIL_SEND_GREETING \ +"%s îòâåòèë íà âàøå ñîîáùåíèå %s.

    "\ +"Òåìà îòâåòà: %s
    "\ +"----------- Ñîîáùåíèå ---------
    %s
    -------------------------------

    "\ +"Âåñü òðåä ìîæíî óâèäåòü çäåñü

    " + +// password recovery +#define MAILACKN_LOSTPASS_SUBJECT WWWCONF_FULL_NAME ": ïàðîëü äëÿ ïðîôèëÿ %s" +#define MAILACKN_LOSTPASS_BODY MAIL_SEND_GREETING \ +"Òåêóùèé ïàðîëü äëÿ âàøåãî ïðîôèëÿ: %s


    " + + +// private message +#define MAILACKN_PRIVATEMSG_SUBJECT WWWCONF_FULL_NAME ": íîâîå ëè÷íîå ñîîáùåíèå îò %s" +#define MAILACKN_PRIVATEMSG_BODY MAIL_SEND_GREETING \ +"Äëÿ Âàñ ïîëó÷åíî íîâîå ëè÷íîå ñîîáùåíèå îò %s.

    "\ +"----------- Ñîîáùåíèå ---------
    %s
    -------------------------------

    "\ +"Îòâåòèòü íà íåãî ìîæíî çäåñü
    " \ +"Ïîñìîòðåòü îñòàëüíûå ëè÷íûå ñîîáùåíèÿ Âû ìîæåòå çäåñü

    " + + + +/**************************** mailing messeges ***************************/ +/*#define MAILACKN_SUBJECT WWWCONF_FULL_NAME ": %s" +#define MAILACKN_MAINBODY_FORMAT "Content-type: text/html; charset=\"windows-1251\"\n" \ +"Çäðàâñòâóéòå, %s.
    %s îòâåòèë íà âàøå ñîîáùåíèå %s." \ +"

    Òåìà îòâåòà: %s\n
    ----------- Ñîîáùåíèå ---------
    %s
    -------------------------------" \ +"

    Âåñü òðåä ìîæíî óâèäåòü çäåñü" \ +"

    This mail was generated automatically by mailing engine" \ +" of " WWWCONF_FULL_NAME ".
    You SHOULD NOT REPLY to this message.
    " +*/ +// password recovery +/*#define MAILLOSTPASSW_SUBJECT WWWCONF_FULL_NAME ": ïàðîëü äëÿ ïðîôèëÿ %s" +#define MAILLOSTPASSW_MAINBODY_FORMAT "Content-type: text/html; charset=\"windows-1251\"\n" \ +"Çäðàâñòâóéòå, %s.
    Òåêóùèé ïàðîëü äëÿ âàøåãî ïðîôèëÿ: %s
    " \ +"

    This mail was generated automatically by mailing engine" \ +" of " WWWCONF_FULL_NAME ".
    You SHOULD NOT REPLY to this message.
    " + +#define MAILACKN_PRIVATEMSG_SUBJECT WWWCONF_FULL_NAME ": íîâîå ëè÷íîå ñîîáùåíèå îò %s" +#define MAILACKN_PRIVATEMSG_MAINBODY_FORMAT "Content-type: text/html; charset=\"windows-1251\"\n" \ +"Çäðàâñòâóéòå, %s.
    äëÿ Âàñ ïîëó÷åíî íîâîå ëè÷íîå ñîîáùåíèå îò %s." \ +"

    ----------- Ñîîáùåíèå ---------
    %s
    -------------------------------" \ +"

    Îòâåòèòü íà íåãî ìîæíî çäåñü
    " \ +"Ïîñìîòðåòü îñòàëüíûå ëè÷íûå ñîîáùåíèÿ Âû ìîæåòå çäåñü" \ +"

    This mail was generated automatically by mailing engine" \ +" of " WWWCONF_FULL_NAME ".
    You SHOULD NOT REPLY to this message.
    " +*/ + +/**************************** log messages *******************************/ +#define LOG_SPAM_TRY "Spam try from %s:, deal=%s" +#define LOG_UNKNOWN_URL "Unknown URL request from : %s, deal=%s" +#define LOG_UNHANDLED "UNHANDLED EXCEPTION at %s at line %d from : %s\n\tError: %s\t\tQUERY_STRING=%s" +#define LOG_UNHANDLED_HTML "UNHANDLED EXCEPTION at %s at line %d from : %s
    %sQUERY_STRING=%s
    " +#define LOG_ERRORTYPEUNKN "Unknown" +#define LOG_ACCESS_DENIED "Access denied from : %s, deal=%s" +#define LOG_PSWDERROR "Incorrect password from : %s, deal=%s" +#define LOG_FATAL_NOMEMORY "Unable to allocate memory block of size %d" +#define LOG_FILESIZETOOHIGH "Size of file %s is too high to be handled by this version" +#define LOG_GETFILESIZEFAILED "Filesize() failed for file %s" +#define LOG_UNABLETOLOCATEFILE "Unable to open/access file %s for R" +#define LOG_UNABLETOLOCATEFILERW "Unable to open/access file %s for RW" +#define LOG_UNABLETOCREATEFILE "Unable to open/create file %s" +#define LOG_WARN_UNABLETOOPENFILE "WARNING: Unable to open/access file %s, feature connected to this file will not be used" + +// from design.h +/*=====================================================================*/ +#define TAG_MSG_HAVE_NO_BODY " (-)" +#define TAG_MSG_HAVE_PIC " (pic)" +#define TAG_MSG_HAVE_URL " (url)" +#define TAG_MSG_CLOSED_THREAD "(çàêðûòî) " +#define TAG_MSG_ROLLED_THREAD "Câåðíóòî: " +#define TAG_ONLYHEADERS_POSTCNT "%s%s(îòâåòîâ: %d)%s" +#define TAG_ONLYHEADERS_POSTCNT_MARKNEW "%s%s(îòâåòîâ: %d, íîâûõ: %d," \ + " ïîñëåäíèé îòâåò: îò %s, %s)%s" +#define TAG_REPLY_PREFIX "Re: " +#define TAG_IP_NOT_DETECTED "X.X.X.X" +#define BAD_WORD_SYMBOL '#' +#define TAG_NEW_MSG_MARK_HREF "+ " +#define TAG_NEW_MSG_MARK "+ " + +/*********************** Topics **************************/ +#define DESIGN_TOPIC_TAG_OPEN "[" +#define DESIGN_TOPIC_TAG_CLOSE "]" +#define DESIGN_TOPIC_DIVIDER "  " + +/***************** nick name information *****************/ +#define DESIGN_REGISTRED_NICK "%s" +#define DESIGN_REGISTRED_OWN_NICK "%s" +#define DESIGN_SELECTEDUSER_NICK "%s" +#define DESIGN_UNREGISTRED_NICK "%s" + +/********************** favorites ************************/ +#define DESIGN_FAVORITES_DEL_THREAD "[X]" +#define DESIGN_FAVORITES_ADD_THREAD "[+]" + +#define DESIGN_THREADS_DIVIDER_IMG "" +#define DESIGN_THREADS_DIVIDER_HR "\n
    " +#define DESIGN_THREADS_DIVIDER_grey "#E9E9E9" +extern char DESIGN_threads_divider[500]; + +#define DESIGN_OP_DL "
    " +#define DESIGN_CL_DL "
    " +#define DESIGN_OP_DIV "
    " +#define DESIGN_OP_DIV_grey "
    " +#define DESIGN_OP_DIV_white "
    " +#define DESIGN_CL_DIV "
    " +extern char DESIGN_open_dl[10]; +extern char DESIGN_open_dl_grey[20]; +extern char DESIGN_open_dl_white[20]; +extern char DESIGN_close_dl[10]; + +#define DESIGN_BR "
    " +#define DESIGN_DD "
    " +extern char DESIGN_break[10]; + +#define DESIGN_BUTTONS_DIVIDER "  " + +#define DESIGN_GLOBAL_BOARD_MESSAGE "

    %s

    %s" + +#define DESIGN_VIEW_THREAD_BODY "

    %s
    " +#define DESIGN_VIEW_THREAD_SIGN "
    %s
    " +#define DESIGN_VIEW_THREAD_MSG_HEADER "
    " +// meesage was sent by NIK +#define DESIGN_VIEW_THREAD_MSG_SENT "
    %s %s " +#define DESIGN_VIEW_THREAD_MSG_SENT1 "<%s> " +#define DESIGN_VIEW_THREAD_MSG_SENT2 "(%s)" +#define DESIGN_VIEW_THREAD_MSG_SENT3 "

    " +// topic when reading +#define DESIGN_VIEW_THREAD_TOPIC "[%s]  " +//date +#define DESIGN_VIEW_THREAD_DATE "
    %s %s" +#define DESIGN_VIEW_THREAD_MDATE "(%s %s)" + +#define DESIGN_INDEX_WELCOME_STRING "

    %s %s!" +#define DESIGN_INDEX_WELCOME_STRING1 " %s %ld %s, âñåãî %d" +#define DESIGN_INDEX_WELCOME_CLOSE "

    " + +#define DESIGN_POST_NEW_MESSAGE_TABLE "" + +#define DESIGN_PREVIEW_PREVIEWMESSAGE "

    %s" +#define DESIGN_PREVIEW_CHANGEMESSAGE "

    %s" + +#define DESIGN_BAN_REASON_STYLE "

    %s %s" + +#define DESIGN_MODERATOR_ENTER_HEADER "

    %s" + +#define DESIGN_LOSTPASSW_HEADER "

    %s" + +#define DESIGN_SEARCH_SEARCH_STR_WAS "

    %s%s
    " +#define DESIGN_SEARCH_RESULT "
    %s%ld %s

    " +#define DESIGN_SEARCH_NO_RESULT "
    %s %s

    " + +#define DESIGN_COMMAND_TABLE_BEGIN "
    " +#define DESIGN_COMMAND_TABLE_END " ]
    \n" + +#define DESIGN_BEGIN_LOGIN_OPEN "
    " +#define DESIGN_END_LOGIN_CLOSE "
    " + +#define DESIGN_BEGIN_LOSTPASSW_OPEN "
    " +#define DESIGN_END_LOSTPASSW_CLOSE "
    " + +#define DESIGN_BEGIN_REGISTER_OPEN "
    " +#define DESIGN_END_REGISTER_CLOSE "
    " +// nick in read_message +#define DESIGN_MESSAGE_UNREG "%s (unreg)" + +#define DESIGN_BEGIN_USERINFO_INTRO_OPEN "
    " +#define DESIGN_END_USERINFO_INTRO_CLOSE "
    " + +#define DESIGN_SEARCH_RESULT "
    %s%ld %s

    " + +/******************* private messages *******************/ +#define DESIGN_PRIVATEMSG_FRAME "%s " \ + "
    %s
    %s%s" +#define DESIGN_PRIVATEMSG_FRAME_BGCL_IN "#FFBBBB" +#define DESIGN_PRIVATEMSG_FRAME_BGCL_OUT "#BBBBFF" + +/********************** announces ***********************/ +#define DESIGN_GLOBALANN_FRAME "%s " \ + "
    %s
    %s" \ + " %s (%s) %s
    %s" + +#define DESIGN_CONFIGURE_CHECKALL "Check/Uncheck All " \ +"\n\n" + +#define DESIGN_WELCOME_QUICKNAV "
    "\ + "
    " + +//****************************************************// +#define HTML_START "" + +#define TEXT_ENCODING_HEADER "" + +#define TEXT_TOPBANNER_HEADER "" + +#define TEXT_STYLE_HEADER "\n" \ +"" + +#define TEXT_TOPBANNER_MAP "" \ +"\"Íàâåðõ\"" \ +"\"Webmaster\"" \ +"" \ +"

    " \ +"" + +#define TEXT_BOTTOMBANNER "\n\n" \ +"

    " \ +"" \ +"" \ +"" \ +"
    " \ +"\n" \ +"\n" + +#define TEXT_BOTTOMBANNER_SHORT "" /* "

    Êîíôåðåíöèÿ îñíîâàíà íà äâèæêå " \ +"WWWConf " VERSION \ +", ïîääåðæèâàåòñÿ è ìîäåðèðóåòñÿ ãðóïïîé ýíòóçèàñòîâ.
    "*/ + +#endif blob - /dev/null blob + b29b801f46fe170fccd8959e37e4f994fd3a5be6 (mode 644) --- /dev/null +++ src/profiles.cpp @@ -0,0 +1,1114 @@ +/*************************************************************************** + profiles.h - profiles support + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "hashindex.h" +#include "profiles.h" +#include "freedb.h" +#include "error.h" + +/* return 1 if valid, 0 otherwise + */ +int isLoginStrValid(register char *s) +{ + while(*s != 0) { + if(((unsigned char)(*s)) < 32) { + return 0; + } + s++; + } + if(strlen(s) > PROFILES_MAX_USERNAME_LENGTH - 1) return 0; + return 1; +} + +/* constructor */ +CProfiles::CProfiles() +{ + errnum = PROFILE_RETURN_ALLOK; +} + + +/* constructor */ +CProfiles::~CProfiles() +{ +} + +/* write SProfile_FullUserInfo structure, allocating space for it automatically + * return 1 if successfull, otherwise zero + */ +int CProfiles::WriteFullInfo(DWORD *idx, SProfile_FullUserInfo *FI) +{ + /* prepare about string length */ + if(FI->AboutUser != NULL) + FI->size = (DWORD)strlen(FI->AboutUser); + else + FI->size = 0; + + /* alloc free space */ + CFreeDBFile fdf(F_PROF_FREEBODY, PROFILE_WASTED_FINFO_SIZE); + if(fdf.errnum != FREEDBFILE_ERROR_ALLOK) + return 0; + + if((*idx = fdf.AllocFreeSpace(sizeof(SProfile_FullUserInfo) - sizeof(char*) + + FI->size)) == 0xFFFFFFFF) { + if(fdf.errnum != FREEDBFILE_ERROR_ALLOK) + return 0; + + if(wcfseek(Fp_b, 0, SEEK_END) != 0) + return 0; + *idx = wcftell(Fp_b); + } + else { + if(wcfseek(Fp_b, *idx, SEEK_SET) != 0) + return 0; + } + + /* write SProfile_FullUserInfo */ + if(!fCheckedWrite(FI, sizeof(SProfile_FullUserInfo) - sizeof(char*), Fp_b)) + return 0; + if(!fCheckedWrite(FI->AboutUser, FI->size, Fp_b)) + return 0; + + return 1; +} +/* read SProfile_FullUserInfo structure + * return 1 if successfull, otherwise zero + */ +int CProfiles::ReadFullInfo(DWORD idx, SProfile_FullUserInfo *FI) +{ + // read SProfile_FullUserInfo + if(wcfseek(Fp_b, idx, SEEK_SET) != 0) + return 0; + if(!fCheckedRead(FI, sizeof(SProfile_FullUserInfo) - sizeof(char*), Fp_b)) + return 0; + + // prepare "about" string length + FI->AboutUser = (char*)malloc(FI->size + 1); + + if(!fCheckedRead(FI->AboutUser, FI->size, Fp_b)) { + free(FI->AboutUser); + return 0; + } + // set final zero at the end of string + FI->AboutUser[FI->size] = 0; + + return 1; +} +/* delete SProfile_FullUserInfo structure from profile body database + * by index [idx] and mark space as free + * return 1 if successfull, otherwise zero + */ +int CProfiles::DeleteFullInfo(DWORD idx) +{ + /* read old Full Info */ + SProfile_FullUserInfo *ofi = (SProfile_FullUserInfo*)malloc(sizeof(SProfile_FullUserInfo)); + + if(ReadFullInfo(idx, ofi) == 0) { + free(ofi); + return 0; + } + + /* mark free space */ + CFreeDBFile fdf(F_PROF_FREEBODY, PROFILE_WASTED_FINFO_SIZE); + if(fdf.errnum != FREEDBFILE_ERROR_ALLOK) { + free(ofi->AboutUser); + free(ofi); + return 0; + } + DWORD rr = sizeof(SProfile_FullUserInfo) - sizeof(char*) + ofi->size; + free(ofi->AboutUser); + free(ofi); + if(fdf.MarkFreeSpace(idx, rr) != FREEDBFILE_ERROR_ALLOK) + return 0; + + return 1; +} + + +/* read count structures SProfile_UserInfo at index idx */ +int CProfiles::ReadUInfo(DWORD idx, SProfile_UserInfo *FI) +{ + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) + return 0; + if(!fCheckedRead(FI, sizeof(SProfile_UserInfo), Fp_i)) + return 0; + + return 1; +} + +/* write new info structure SProfile_UserInfo and return it index in *idx + * and seek to the find place + * DESTROY curent position of Fp_i file !!! + * return 1 if successfull, otherwise zero returned + */ +int CProfiles::GetSpaceforUInfo(DWORD *idx) +{ + /* alloc free space */ + CFreeDBFile fdf(F_PROF_FREENIDX, 0); + if(fdf.errnum != FREEDBFILE_ERROR_ALLOK) + return 0; + + if((*idx = fdf.AllocFreeSpace(sizeof(SProfile_UserInfo))) == 0xFFFFFFFF) { + if(fdf.errnum != FREEDBFILE_ERROR_ALLOK) + return 0; + + if(wcfseek(Fp_i, 0, SEEK_END) != 0) + return 0; + *idx = wcftell(Fp_i); + } + else { + if(wcfseek(Fp_i, *idx, SEEK_SET) != 0) + return 0; + } + + return 1; +} + +/* write count structures SProfile_UserInfo at index idx */ +int CProfiles::WriteUInfo(DWORD idx, SProfile_UserInfo *FI) +{ + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) + return 0; + if(!fCheckedWrite(FI, sizeof(SProfile_UserInfo), Fp_i)) + return 0; + + return 1; +} + +int CProfiles::DeleteUInfo(DWORD idx) +{ + /* mark free space */ + CFreeDBFile fdf(F_PROF_FREENIDX, sizeof(SProfile_UserInfo)); + if(fdf.errnum != FREEDBFILE_ERROR_ALLOK) + return 0; + if(fdf.MarkFreeSpace(idx, sizeof(SProfile_UserInfo)) != FREEDBFILE_ERROR_ALLOK) + return 0; + + return 1; +} + + +/* add new user to profile database + * return PROFILE_RETURN_ALLOK if successfull, otherwise standart error codes + */ +int CProfiles::AddNewUser(SProfile_UserInfo *newprf, SProfile_FullUserInfo *FullUI, DWORD *ui_index) +{ + int ret, i; + DWORD idx; + DWORD rr; + DWORD ucount; + Fp_i = NULL; + Fp_b = NULL; + + if(!isLoginStrValid(newprf->username) || strlen(newprf->username) < 3) { + return PROFILE_RETURN_INVALID_LOGIN; + } + + if((ret = GetIndexOfString(newprf->username, &rr)) == HASHINDEX_ER_NOT_FOUND || + ret == HASHINDEX_ER_IO_READ) { + /* prepare SProfile_UserInfo and sb structures */ + newprf->postcount = 0; + FullUI->CreateDate = time(NULL); + newprf->LoginDate = 0; + newprf->persmsg = 0xffffffff; + newprf->persmescnt = 0; + newprf->readpersmescnt = 0; + newprf->postedmescnt = 0; + newprf->postedpersmsg = 0xffffffff; + newprf->RefreshCount = 0; + + + newprf->vs.dsm = CONFIGURE_SETTING_DEFAULT_dsm; + newprf->vs.topics = CONFIGURE_SETTING_DEFAULT_topics; + newprf->vs.tv = CONFIGURE_SETTING_DEFAULT_tv; + newprf->vs.tc = CONFIGURE_SETTING_DEFAULT_tc; + newprf->vs.ss = CONFIGURE_SETTING_DEFAULT_ss; + newprf->vs.lsel = CONFIGURE_SETTING_DEFAULT_lsel; + newprf->vs.tt = CONFIGURE_SETTING_DEFAULT_tt; + newprf->vs.tz = DATETIME_DEFAULT_TIMEZONE; + + // New status = 0 + newprf->Status = 0; + for( i=0; ifavs[i]=0; + + /* create new index */ + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) == NULL) + goto Unlock_and_return; + if((Fp_b = wcfopen(F_PROF_BODY, FILE_ACCESS_MODES_RW)) == NULL) + goto Unlock_and_return; + + /********* lock Fp_i, Fp_b files *********/ + lock_file(Fp_i); + lock_file(Fp_b); + + // read unique user ID + if(!fCheckedRead(&(newprf->UniqID), sizeof(newprf->UniqID), Fp_i)) + goto Unlock_and_return; + (newprf->UniqID)++; + + // read user count + if(!fCheckedRead(&ucount, sizeof(ucount), Fp_i)) + goto Unlock_and_return; + // increment user count + ucount++; + + // get free index for user info structure + if(GetSpaceforUInfo(&idx) == 0) + goto Unlock_and_return; + + if(ui_index != NULL) *ui_index = idx; + + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) + goto Unlock_and_return; + + // write SProfile_FullUserInfo + if(WriteFullInfo(&(newprf->FullInfo_ID), FullUI) == 0) { + goto Unlock_and_return; + } + + // write SProfile_UserInfo + if(WriteUInfo(idx, newprf) == 0) { + goto Unlock_and_return; + } + + if(AddStringToHashedIndex(newprf->username, idx) != HASHINDEX_ER_OK) { + DeleteUInfo(idx); + DeleteFullInfo(newprf->FullInfo_ID); + goto Unlock_and_return; + } + + // write new unique user ID and current user count + if(wcfseek(Fp_i, 0, SEEK_SET) != 0) + goto Unlock_and_return; + if(!fCheckedWrite(&(newprf->UniqID), sizeof(newprf->UniqID), Fp_i)) + goto Unlock_and_return; + if(!fCheckedWrite(&ucount, sizeof(ucount), Fp_i)) + goto Unlock_and_return; + + unlock_file(Fp_i); + unlock_file(Fp_b); + /********* unlock Fp_i, Fp_b files *********/ + + wcfclose(Fp_i); + wcfclose(Fp_b); + return PROFILE_RETURN_ALLOK; + +Unlock_and_return: + // error - unlock and exit + if(Fp_i) { + unlock_file(Fp_i); + wcfclose(Fp_i); + } + if(Fp_b) { + unlock_file(Fp_b); + wcfclose(Fp_b); + } + return PROFILE_RETURN_DB_ERROR; + } + + return PROFILE_RETURN_ALREADY_EXIST; +} + +/* delete user [name] from profile database + * return PROFILE_RETURN_ALLOK if successfull, otherwise standart error codes + */ +int CProfiles::DeleteUser(char *name) +{ + DWORD ret, idx, ucount; + SProfile_UserInfo *pi; + Fp_i = NULL; + Fp_b = NULL; + + ret = GetIndexOfString(name, &idx); + + switch(ret) { + case HASHINDEX_ER_NOT_FOUND: + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_OK: + pi = (SProfile_UserInfo*)malloc(sizeof(SProfile_UserInfo)); + + // index exist - try to read block + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) == NULL) + goto Do_Exit; + + if((Fp_b = wcfopen(F_PROF_BODY, FILE_ACCESS_MODES_RW)) == NULL) + goto Do_Exit; + + /********* lock Fp_i, Fp_b *********/ + lock_file(Fp_i); + lock_file(Fp_b); + + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) + goto Do_Exit; + + if(!fCheckedRead(pi, sizeof(SProfile_UserInfo), Fp_i)) + goto Do_Exit; + + if(strcmp(pi->username, name) == 0) { + if(DeleteFullInfo(pi->FullInfo_ID) == 0) + goto Do_Exit; + + if(DeleteUInfo(idx) == 0) + goto Do_Exit; + + if(DeleteStringFromHashedIndex(name) != HASHINDEX_ER_OK) + goto Do_Exit; + + // update user count + if(wcfseek(Fp_i, sizeof(DWORD), SEEK_SET) != 0) + goto Do_Exit; + if(!fCheckedRead(&ucount, sizeof(ucount), Fp_i)) + goto Do_Exit; + ucount++; + if(wcfseek(Fp_i, sizeof(DWORD), SEEK_SET) != 0) + goto Do_Exit; + if(!fCheckedWrite(&ucount, sizeof(ucount), Fp_i)) + goto Do_Exit; + + unlock_file(Fp_i); + unlock_file(Fp_b); + /******** unlock Fp_i, Fp_b ********/ + + wcfclose(Fp_i); + wcfclose(Fp_b); + + free(pi); + return PROFILE_RETURN_ALLOK; + } + + unlock_file(Fp_i); + unlock_file(Fp_b); + /******** unlock Fp_i, Fp_b ********/ + + wcfclose(Fp_i); + wcfclose(Fp_b); + + free(pi); + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_FORMAT: + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_IO_READ: + case HASHINDEX_ER_IO_CREATE: + goto Do_Exit; + + default: + return PROFILE_RETURN_UNKNOWN_ERROR; + } + +Do_Exit: + + if(Fp_i) { + unlock_file(Fp_i); + wcfclose(Fp_i); + } + if(Fp_b) { + unlock_file(Fp_b); + wcfclose(Fp_b); + } + + return PROFILE_RETURN_DB_ERROR; +} + +/* modify structures, user if user exist, UserName cannot be changed + * return PROFILE_RETURN_ALLOK if successfull, otherwise standart error codes + * also if Fui is NULL, ModifyUser() will not modify Full User Information + */ +int CProfiles::ModifyUser(SProfile_UserInfo *newprf, SProfile_FullUserInfo *FullUI, DWORD *ui_index) +{ + DWORD ret, idx; + SProfile_UserInfo *pi; + Fp_i = NULL; + Fp_b = NULL; + + if(!isLoginStrValid(newprf->username) || strlen(newprf->username) < 3) + return PROFILE_RETURN_INVALID_LOGIN; + + ret = GetIndexOfString(newprf->username, &idx); + + switch(ret) { + case HASHINDEX_ER_NOT_FOUND: + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_OK: + pi = (SProfile_UserInfo*)malloc(sizeof(SProfile_UserInfo)); + + // index exist - try to read block + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) == NULL) + goto Do_Exit; + + if((Fp_b = wcfopen(F_PROF_BODY, FILE_ACCESS_MODES_RW)) == NULL) + goto Do_Exit; + + /********* lock Fp_i, Fp_b *********/ + lock_file(Fp_i); + lock_file(Fp_b); + + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) + goto Do_Exit; + + if(!fCheckedRead(pi, sizeof(SProfile_UserInfo), Fp_i)) + goto Do_Exit; + + if(strcmp(pi->username, newprf->username) == 0) { + + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) goto Do_Exit; + + if(ui_index != NULL) *ui_index = idx; + + if(FullUI != NULL) { + // delete old and save new full info + if(DeleteFullInfo(pi->FullInfo_ID) == 0) + goto Do_Exit; + + if(WriteFullInfo(&(newprf->FullInfo_ID), FullUI) == 0) + goto Do_Exit; + } + else { + newprf->FullInfo_ID = pi->FullInfo_ID; + } + + // save old dinamic board information + newprf->postcount = pi->postcount; + newprf->UniqID = pi->UniqID; + newprf->persmsg = pi->persmsg; + newprf->lastIP = pi->lastIP; + newprf->persmescnt = pi->persmescnt; + newprf->readpersmescnt = pi->readpersmescnt; + newprf->postedmescnt = pi->postedmescnt; + newprf->postedpersmsg = pi->postedpersmsg; + newprf->RefreshCount = pi->RefreshCount; + + // and finally save user profile + if(!fCheckedWrite(newprf, sizeof(SProfile_UserInfo), Fp_i)) + goto Do_Exit; + + unlock_file(Fp_i); + unlock_file(Fp_b); + /******** unlock Fp_i, Fp_b ********/ + + wcfclose(Fp_i); + wcfclose(Fp_b); + + free(pi); + return PROFILE_RETURN_ALLOK; + } + + unlock_file(Fp_i); + unlock_file(Fp_b); + /******** unlock Fp_i, Fp_b ********/ + + wcfclose(Fp_i); + wcfclose(Fp_b); + + free(pi); + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_FORMAT: + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_IO_READ: + case HASHINDEX_ER_IO_CREATE: + goto Do_Exit; + + default: + return PROFILE_RETURN_UNKNOWN_ERROR; + } + +Do_Exit: + + if(Fp_i) { + unlock_file(Fp_i); + wcfclose(Fp_i); + } + if(Fp_b) { + unlock_file(Fp_b); + wcfclose(Fp_b); + } + + return PROFILE_RETURN_DB_ERROR; +} + +/* check, if there is user with same name in profile database + * return PROFILE_RETURN_ALLOK if successfull, otherwise standart error codes + * also if ui not NULL return SProfile_UserInfo for found user, and if also Fui not NULL + * return Fui information too + */ +int CProfiles::GetUserByName(char *name, SProfile_UserInfo *ui, SProfile_FullUserInfo *Fui, DWORD *ui_index) +{ + DWORD ret, idx; + SProfile_UserInfo *pi; + + ret = GetIndexOfString(name, &idx); + // error code returned - next strings - analizing it + + switch(ret) { + case HASHINDEX_ER_NOT_FOUND: + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_OK: + pi = (SProfile_UserInfo*)malloc(sizeof(SProfile_UserInfo)); + + // index exist - try to read block + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_R)) == NULL) + goto Do_Exit; + + if((Fp_b = wcfopen(F_PROF_BODY, FILE_ACCESS_MODES_R)) == NULL) + goto Do_Exit; + + if(wcfseek(Fp_i, idx, SEEK_SET) != 0) + goto Do_Exit; + + if(!fCheckedRead(pi, sizeof(SProfile_UserInfo), Fp_i)) + goto Do_Exit; + + if(strcmp(pi->username, name) == 0) { + // profile found + + if(ui != NULL) { + memcpy(ui, pi, sizeof(*pi)); + } + if(Fui != NULL) { + // read SProfile_FullUserInfo + if(ReadFullInfo(pi->FullInfo_ID, Fui) == 0) + goto Do_Exit; + } + if(ui_index != NULL) *ui_index = idx; + + free(pi); + wcfclose(Fp_b); + wcfclose(Fp_i); + return PROFILE_RETURN_ALLOK; + + } + + /* name not found - not exist */ + free(pi); + wcfclose(Fp_b); + wcfclose(Fp_i); + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_FORMAT: + return PROFILE_RETURN_INVALID_LOGIN; + + case HASHINDEX_ER_IO_READ: + case HASHINDEX_ER_IO_CREATE: + goto Do_Exit; + + default: + return PROFILE_RETURN_UNKNOWN_ERROR; + } + +Do_Exit: + + return PROFILE_RETURN_DB_ERROR; +} + +int CProfiles::GetUsersCount(DWORD *uc) +{ + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + + if(wcfseek(Fp_i, sizeof(DWORD), SEEK_SET) != 0) + return 0; + if(!fCheckedRead(uc, sizeof(DWORD), Fp_i)) + return 0; + + wcfclose(Fp_i); + return 1; +} + +int CProfiles::GetUInfo(DWORD idx, SProfile_UserInfo *FI) +{ + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_R)) == NULL) + return 0; + register DWORD x = (ReadUInfo(idx, FI) != 1); + wcfclose(Fp_i); + if(x) return 0; + return 1; +} + +int CProfiles::SetUInfo(DWORD idx, SProfile_UserInfo *FI) +{ + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) == NULL) + return 0; + lock_file(Fp_i); + register DWORD x = (WriteUInfo(idx, FI) != 1); + unlock_file(Fp_i); + wcfclose(Fp_i); + if(x) return 0; + return 1; +} + +int CProfiles::GetFullInfo(DWORD idx, SProfile_FullUserInfo *FI) +{ + if((Fp_b = wcfopen(F_PROF_BODY, FILE_ACCESS_MODES_R)) == NULL) + return 0; + register DWORD x = (ReadFullInfo(idx, FI) != 1); + wcfclose(Fp_b); + if(x) return 0; + return 1; +} + +int CProfiles::GenerateUserList(char ***buf, DWORD *cnt) +{ + DWORD *ii; + DWORD readed, i, curii = 0, c = 0, ac /* alloced count */, allc = 0; +#define ULIST_PROFILE_READ_COUNT 400 + SProfile_UserInfo pi[ULIST_PROFILE_READ_COUNT]; + + *buf = NULL; + *cnt = 0; + if(GenerateIndexList(&ii) != HASHINDEX_ER_OK) + return 0; + + if(ii[0] != 0xffffffff) { + *buf = (char**)malloc(ULIST_PROFILE_READ_COUNT*sizeof(char**)); + if(!(*buf)) return 0; + ac = ULIST_PROFILE_READ_COUNT; + + if((Fp_i = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_R)) == NULL) { + free(*buf); + *buf = NULL; + return 0; + } + + if(wcfseek(Fp_i, ii[0], SEEK_SET) != 0) + return 0; + + do { + readed = (DWORD)wcfread(&pi, 1, sizeof(SProfile_UserInfo)*ULIST_PROFILE_READ_COUNT, Fp_i); + if((readed % sizeof(SProfile_UserInfo)) != 0) { + wcfclose(Fp_i); + for(i = 0; i < c; i++) { + free((*buf)[i]); + } + free(*buf); + *buf = NULL; + return 0; + } + readed = readed / sizeof(SProfile_UserInfo); + + for(i = 0; i < readed; i++) { + // find this in our indexes (test for deleted profile) + while(ii[curii] < ((i + allc*ULIST_PROFILE_READ_COUNT)*sizeof(SProfile_UserInfo) + ii[0])) curii++; + if(ii[curii] == ((i + allc*ULIST_PROFILE_READ_COUNT)*sizeof(SProfile_UserInfo) + ii[0])) { + // modify right - reset all right if SUPERUSER + if((pi[i].right & USERRIGHT_SUPERUSER)) + pi[i].right = USERRIGHT_SUPERUSER; + // store it + int len = (int)strlen(pi[i].username) + 1; + (*buf)[c] = (char*)malloc(len + 5*sizeof(DWORD) + 1); + memcpy(((char*)((*buf)[c])), &pi[i].lastIP, sizeof(DWORD)); + memcpy(((char*)((*buf)[c])) + 4, &pi[i].postcount, sizeof(DWORD)); + memcpy(((char*)((*buf)[c])) + 8, &pi[i].LoginDate, sizeof(DWORD)); + memcpy(((char*)((*buf)[c])) + 12, &pi[i].RefreshCount, sizeof(DWORD)); + memcpy(((char*)((*buf)[c])) + 16, &pi[i].right, sizeof(DWORD)); + memcpy(((char*)((*buf)[c])) + 20, &pi[i].username, len); + c++; + // check for realloc + if(ac == c) { + ac += ULIST_PROFILE_READ_COUNT; + *buf = (char**)realloc(*buf, ac*sizeof(char**)); + } + } + // FOR DEBUG !!! + /*else { + if(curii > 3) { + for(int j = -3; j < 4; j++) { + print2log("%d", ii[curii + j]); + } + print2log("i=%d, name=%s, Done\n", (i + allc*ULIST_PROFILE_READ_COUNT)*sizeof(SProfile_UserInfo) + ii[0], pi[i].username); + } + }*/ + } + allc++; + } while(readed == ULIST_PROFILE_READ_COUNT); + + wcfclose(Fp_i); + + free(ii); + // realloc to the real size + *buf = (char**)realloc(*buf, c*sizeof(char**)); + + *cnt = c; + } + + return 1; +} + +int CProfiles::PostPersonalMessage(char *username, DWORD userindex, char *message, char *from, DWORD userindexfrom) +{ + SProfile_UserInfo ui, poster_ui; + int ret; + WCFILE *fp; + + // load recipient user profile + if(username != NULL && strcmp(username, "") != 0) { + // use username + if((ret = GetUserByName(username, &ui, NULL, &userindex)) != PROFILE_RETURN_ALLOK) + return ret; + } + else { + // use userindex + if(!GetUInfo(userindex, &ui)) + return PROFILE_RETURN_DB_ERROR; + } + + // load sender user profile + if(from != NULL && strcmp(from, "") != 0) { + // use username + if((ret = GetUserByName(from, &poster_ui, NULL, &userindexfrom)) != PROFILE_RETURN_ALLOK) + return ret; + } + else { + // use userindex + if(!GetUInfo(userindexfrom, &poster_ui)) + return PROFILE_RETURN_DB_ERROR; + } + + // prepare personal message structure + SPersonalMessage mes; + DWORD pos; + mes.Date = time(NULL); + strcpy(mes.NameFrom, poster_ui.username); + mes.UIdFrom = poster_ui.UniqID; + strcpy(mes.NameTo, ui.username); + mes.UIdTo = ui.UniqID; + strcpy(mes.Msg, message); + mes.Prev = ui.persmsg; + mes.PosterPrev = poster_ui.postedpersmsg; + + if((fp = wcfopen(F_PROF_PERSMSG, FILE_ACCESS_MODES_RW)) == NULL) + return PROFILE_RETURN_DB_ERROR; + lock_file(fp); + // write to the file + if(wcfseek(fp, 0, SEEK_END) != 0) + goto PostPersMsg_Error; + pos = wcftell(fp); + if(!fCheckedWrite(&mes, sizeof(mes), fp)) + goto PostPersMsg_Error; + + // update recipient user profile + ui.persmsg = pos; + ui.persmescnt++; + SetUInfo(userindex, &ui); + + // to correct bug with post to youself + if(poster_ui.UniqID == ui.UniqID) + memcpy(&poster_ui, &ui, sizeof(SProfile_UserInfo)); + + // update sender user profile + poster_ui.postedpersmsg = pos; + poster_ui.postedmescnt++; + SetUInfo(userindexfrom, &poster_ui); + + unlock_file(fp); + wcfclose(fp); + return PROFILE_RETURN_ALLOK; + +PostPersMsg_Error: + unlock_file(fp); + wcfclose(fp); + return PROFILE_RETURN_DB_ERROR; +} + +int CProfiles::ReadPersonalMessages(char *username, DWORD userindex, + SPersonalMessage **tomessages, DWORD *tocount, + SPersonalMessage **frommessages, DWORD *fromcount) +{ + SProfile_UserInfo ui; + int ret; + WCFILE *fp; + SPersonalMessage *msg; + DWORD toread, i, fromread, curpos; + + if(username != NULL && strcmp(username, "") != 0) { + // use username + if((ret = GetUserByName(username, &ui, NULL, &userindex)) != PROFILE_RETURN_ALLOK) + return ret; + } + else { + // use userindex + if(!GetUInfo(userindex, &ui)) + return PROFILE_RETURN_DB_ERROR; + } + + msg = *tomessages = *frommessages = NULL; + + // if we really need read to messages + if(tocount == NULL) { + // all messages + toread = ui.persmescnt; + } + else { + if(*tocount == 0) { + // only new messages + toread = ui.persmescnt - ui.readpersmescnt; + } + else { + // selected count + if(*tocount > ui.persmescnt) + *tocount = ui.persmescnt; + toread = *tocount; + } + } + if(!toread) { + *tomessages = NULL; + goto skip_to_msg_read; + } + + msg = (SPersonalMessage*)malloc(toread*sizeof(SPersonalMessage)); + + if((fp = wcfopen(F_PROF_PERSMSG, FILE_ACCESS_MODES_R)) == NULL) + return PROFILE_RETURN_DB_ERROR; + curpos = ui.persmsg; + for(i = 0; i < toread; i++) { + if(wcfseek(fp, curpos, SEEK_SET) != 0) + goto PostPersMsg_Error; + if(!fCheckedRead(&(msg[i]), sizeof(SPersonalMessage), fp)) + goto PostPersMsg_Error; + curpos = msg[i].Prev; + // this situation should not happen, but... + if(curpos == 0xffffffff) break; + } + msg[toread - 1].Prev = 0xffffffff; // last message mark + wcfclose(fp); + *tomessages = msg; + msg = NULL; + +skip_to_msg_read: + + // if we really need read from messages + if(fromcount == NULL) { + // all messages + fromread = ui.postedmescnt; + } + else { + // selected count + if(*fromcount > ui.postedmescnt) + *fromcount = ui.postedmescnt; + fromread = *fromcount; + } + if(!fromread) { + *frommessages = NULL; + return PROFILE_RETURN_ALLOK; + } + + msg = (SPersonalMessage*)malloc(fromread*sizeof(SPersonalMessage)); + + if((fp = wcfopen(F_PROF_PERSMSG, FILE_ACCESS_MODES_R)) == NULL) + return PROFILE_RETURN_DB_ERROR; + curpos = ui.postedpersmsg; + for(i = 0; i < fromread; i++) { + if(wcfseek(fp, curpos, SEEK_SET) != 0) + goto PostPersMsg_Error; + if(!fCheckedRead(&(msg[i]), sizeof(SPersonalMessage), fp)) + goto PostPersMsg_Error; + curpos = msg[i].PosterPrev; + msg[i].Prev = 0; + // this situation should not happen, but... + if(curpos == 0xffffffff) { + break; + } + } + msg[i].Prev = 0xffffffff; // last message mark + wcfclose(fp); + *frommessages = msg; + + return PROFILE_RETURN_ALLOK; + +PostPersMsg_Error: + if(msg) free(msg); + if(*tomessages){ + free(*tomessages); + *tomessages = NULL; + } + if(*frommessages){ + free(*frommessages); + *frommessages = NULL; + } + wcfclose(fp); + return PROFILE_RETURN_DB_ERROR; +} + +int CProfiles::ReadPersonalMessagesByDate(char *username, DWORD userindex, + SPersonalMessage **tomessages, time_t todate, + SPersonalMessage **frommessages, time_t fromdate) +{ + SProfile_UserInfo ui; + int ret; + WCFILE *fp; + SPersonalMessage *msg; + DWORD i, curpos; + + if(username != NULL && strcmp(username, "") != 0) { + // use username + if((ret = GetUserByName(username, &ui, NULL, &userindex)) != PROFILE_RETURN_ALLOK) + return ret; + } + else { + // use userindex + if(!GetUInfo(userindex, &ui)) + return PROFILE_RETURN_DB_ERROR; + } + + msg = *tomessages = *frommessages = NULL; + + // if we really need read "to" messages ? + if(!todate) { + *tomessages = NULL; + goto skip_to_msg_read; + } + + if((fp = wcfopen(F_PROF_PERSMSG, FILE_ACCESS_MODES_R)) == NULL) + return PROFILE_RETURN_DB_ERROR; + msg = (SPersonalMessage*)malloc(sizeof(SPersonalMessage)); + if(!msg) { + wcfclose(fp); + return PROFILE_RETURN_UNKNOWN_ERROR; + } + curpos = ui.persmsg; + i = 0; + if(curpos != 0xffffffff) { + for(0;;) { + if(wcfseek(fp, curpos, SEEK_SET) != 0) + goto PostPersMsg_Error; + if(!fCheckedRead(&(msg[i]), sizeof(SPersonalMessage), fp)) + goto PostPersMsg_Error; + curpos = msg[i].Prev; + if(msg[i].Date < todate) + break; + i++; + if(curpos == 0xffffffff) break; + msg = (SPersonalMessage*)realloc(msg, (i+1)*sizeof(SPersonalMessage)); + } + } + if(!i) { + free(msg); + msg = NULL; + } + else msg[i-1].Prev = 0xffffffff; // last message mark + wcfclose(fp); + *tomessages = msg; + msg = NULL; + +skip_to_msg_read: + + // if we really need read from messages + if(!fromdate) { + *frommessages = NULL; + return PROFILE_RETURN_ALLOK; + } + + if((fp = wcfopen(F_PROF_PERSMSG, FILE_ACCESS_MODES_R)) == NULL) + return PROFILE_RETURN_DB_ERROR; + msg = (SPersonalMessage*)malloc(sizeof(SPersonalMessage)); + if(!msg) { + wcfclose(fp); + return PROFILE_RETURN_UNKNOWN_ERROR; + } + curpos = ui.postedpersmsg; + i = 0; + if(curpos != 0xffffffff) { + for(;;) { + if(wcfseek(fp, curpos, SEEK_SET) != 0) + goto PostPersMsg_Error; + if(!fCheckedRead(&(msg[i]), sizeof(SPersonalMessage), fp)) + goto PostPersMsg_Error; + curpos = msg[i].PosterPrev; + msg[i].Prev = 0; + if(msg[i].Date < fromdate) + break; + i++; + if(curpos == 0xffffffff) break; + msg = (SPersonalMessage*)realloc(msg, (i+1)*sizeof(SPersonalMessage)); + } + } + if(!i) { + free(msg); + msg = NULL; + } + else msg[i - 1].Prev = 0xffffffff; // last message mark + wcfclose(fp); + *frommessages = msg; + + return PROFILE_RETURN_ALLOK; + +PostPersMsg_Error: + if(msg) free(msg); + if(*tomessages){ + free(*tomessages); + *tomessages = NULL; + } + if(*frommessages){ + free(*frommessages); + *frommessages = NULL; + } + wcfclose(fp); + return PROFILE_RETURN_DB_ERROR; +} + +int CProfiles::CheckandAddFavsList(DWORD userindex, DWORD msgindex, int doadd) +{ + int i, empty=0, fl=0; + if( (msgindex == 0) || (userindex == 0)) return PROFILE_RETURN_INVALID_FORMAT; + SProfile_UserInfo ui; + if(!GetUInfo(userindex, &ui)) return PROFILE_RETURN_DB_ERROR; + for( i =0; i < PROFILES_FAV_THREADS_COUNT; i++){ + if( ui.favs[i] == msgindex) return PROFILE_RETURN_ALREADY_EXIST; + if(ui.favs[i] == 0) { if(!empty) empty =i+1;} + else {if(ui.favs[i] < msgindex) fl=i+1;} + } + if( empty ){ + if( doadd == 0) return PROFILE_RETURN_ALLOK; + DWORD prev=0; + for( i =0; i < PROFILES_FAV_THREADS_COUNT; i++){ + if (i > fl && i > empty) { + prev=ui.favs[PROFILES_FAV_THREADS_COUNT-1]; + break; + } + if(i) ui.favs[i-1] = prev; + if( (i - empty + 2 > 0) && (i - fl + 1 < 0) ) { + prev=ui.favs[i+1]; + continue; + } + if( ((i - fl + 1 > 0) && (i - empty < 0)) || ((i -fl +1 == 0) && (i - empty + 2 > 0)) ) { + prev=msgindex; + msgindex=ui.favs[i]; + continue; + } + prev=ui.favs[i]; + } + ui.favs[PROFILES_FAV_THREADS_COUNT-1]=prev; + if(SetUInfo(userindex, &ui)) return PROFILE_RETURN_ALLOK; + return PROFILE_RETURN_DB_ERROR; + } + return PROFILE_RETURN_UNKNOWN_ERROR; +} + +int CProfiles::DelFavsList(DWORD userindex, DWORD msgindex) +{ + DWORD i; + if( (msgindex == 0) || (userindex == 0)) return PROFILE_RETURN_INVALID_FORMAT; + SProfile_UserInfo ui; + if(!GetUInfo(userindex, &ui)) return PROFILE_RETURN_DB_ERROR; + + for( i =0; i < PROFILES_FAV_THREADS_COUNT; i++){ + //check if msg is saved here and deleting if + if(ui.favs[i] == msgindex) { + ui.favs[i] = 0; + if(SetUInfo(userindex, &ui)) return PROFILE_RETURN_ALLOK; + return PROFILE_RETURN_DB_ERROR; + } + } + return PROFILE_RETURN_UNKNOWN_ERROR; +} blob - /dev/null blob + 6989385930c05a238fd0dffb49801ff17a0c97d8 (mode 644) --- /dev/null +++ src/profiles.h @@ -0,0 +1,202 @@ +/*************************************************************************** + profiles.h - profiles support include + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef PROFILES_H_INCLUDED +#define PROFILES_H_INCLUDED + +#include "basetypes.h" +#include "hashindex.h" + +/* database length parameters */ +#define PROFILES_MAX_PASSWORD_LENGTH 33 +#define PROFILES_MAX_ICQ_LEN 16 +#define PROFILES_MAX_ALT_DISPLAY_NAME 90 +#define PROFILES_FAV_THREADS_COUNT 20 //4*20 = 80 bytes real size +#define PROFILES_MAX_USERNAME_LENGTH 30 +#define PROFILES_MAX_SIGNATURE_LENGTH 255 +#define PROFILES_FULL_USERINFO_MAX_NAME 255 +#define PROFILES_FULL_USERINFO_MAX_EMAIL 255 +#define PROFILES_FULL_USERINFO_MAX_HOMEPAGE 70 +#define PROFILES_FULL_USERINFO_MAX_SELECTEDUSR 185 + +#define PROFILES_MIN_PASSWORD_LENGTH 3 + +/* bit mask for user flags */ +#define PROFILES_FLAG_HAVE_PICTURE 0x0001 +#define PROFILES_FLAG_HAVE_SIGNATURE 0x0002 +#define PROFILES_FLAG_INVISIBLE 0x0004 +#define PROFILES_FLAG_VISIBLE_EMAIL 0x0008 +#define PROFILES_FLAG_NOT_ACTIVATED 0x0010 +#define PROFILES_FLAG_VIEW_SETTINGS 0x0020 +#define PROFILES_FLAG_DISABLED 0x0040 +#define PROFILES_FLAG_PERSMSGDISABLED 0x0080 +#define PROFILES_FLAG_PERSMSGTOEMAIL 0x0100 +#define PROFILES_FLAG_ALWAYS_EMAIL_ACKN 0x0200 +#define PROFILES_FLAG_ALT_DISPLAY_NAME 0x0400 +#define PROFILES_FLAG_APPLY_CONF_LOGIN 0x0800 + + +/* profile function error codes */ +#define PROFILE_RETURN_ALLOK 0 +#define PROFILE_RETURN_ALREADY_EXIST 1 +#define PROFILE_RETURN_DB_ERROR 3 +#define PROFILE_RETURN_INVALID_FORMAT 4 +#define PROFILE_RETURN_INVALID_LOGIN 5 +#define PROFILE_RETURN_INVALID_PASSWORD 6 +#define PROFILE_RETURN_PASSWORD_SHORT 7 +#define PROFILE_RETURN_UNKNOWN_ERROR 9 + +#define PROFILE_LOGIN_MIN_LENGTH 3 + +#define PROFILE_NO_NEXT_INDEX 0xFFFFFFFF + +#define PROFILE_WASTED_FINFO_SIZE sizeof(SProfile_FullUserInfo) - sizeof(char*) + +#define PROFILE_PERSONAL_MESSAGE_LENGHT 385 + +struct SPersonalMessage { + DWORD Prev; + DWORD PosterPrev; + char NameFrom[PROFILES_MAX_USERNAME_LENGTH]; + DWORD UIdFrom; + char NameTo[PROFILES_MAX_USERNAME_LENGTH]; + DWORD UIdTo; + time_t Date; + char Msg[PROFILE_PERSONAL_MESSAGE_LENGHT]; +}; + + +#ifdef WIN32 +#pragma pack(push, 1) +#else +#pragma pack(1) +#endif + +struct SViewSettings +{ + WORD dsm; + DWORD topics; + WORD tv; + WORD tc; + unsigned char ss:3; + unsigned char lsel:2; + unsigned char tt:4; + char tz:5; + unsigned char resrvd:2; +}; + +/* Full user information */ +struct SProfile_FullUserInfo { + char FullName[PROFILES_FULL_USERINFO_MAX_NAME]; + char Email[PROFILES_FULL_USERINFO_MAX_EMAIL]; + char HomePage[PROFILES_FULL_USERINFO_MAX_HOMEPAGE]; + char SelectedUsers[PROFILES_FULL_USERINFO_MAX_SELECTEDUSR]; + char Signature[PROFILES_MAX_SIGNATURE_LENGTH]; + + time_t CreateDate; + + // Here you can define additional parameters + + // do not modify following 2 lines + DWORD size; + char *AboutUser; +}; + +/* Structure which keep information about user in profiles database */ +struct SProfile_UserInfo { + /* Username, password */ + char username[PROFILES_MAX_USERNAME_LENGTH]; + char password[PROFILES_MAX_PASSWORD_LENGTH]; + /* view settings */ + SViewSettings vs; + char icqnumber[PROFILES_MAX_ICQ_LEN]; + char altdisplayname[PROFILES_MAX_ALT_DISPLAY_NAME]; + DWORD favs[PROFILES_FAV_THREADS_COUNT]; + // count of refresh of this board + DWORD RefreshCount; + // recieved persmsg read count + WORD readpersmescnt; + // received persmsg current count + WORD persmescnt; + // posted persmsg count + WORD postedmescnt; + // personal message index (or 0xFFFFFFFF if does not exist) + DWORD persmsg; + // posted personal message index (or 0xFFFFFFFF) + DWORD postedpersmsg; + // user status + BYTE Status; + // Ip of last login + DWORD lastIP; + // security level for message header + BYTE secheader; + BYTE align1[3]; + // unique user identifier + DWORD UniqID; + // flags for user (ex: have picture... etc.) + DWORD Flags; + // security level of user (for message body) + BYTE secur; + BYTE align2[3]; + // right for user + DWORD right; + // number of posts to conference + DWORD postcount; + time_t LoginDate; + // index in profile bodies file of structure with common user information + DWORD FullInfo_ID; +}; +#ifdef WIN32 +#pragma pack(pop) +#else +#pragma pack(4) +#endif + +class CProfiles { +protected: + WCFILE *Fp_i, // profiles index file + *Fp_b; // profiles body file + + int ReadFullInfo(DWORD idx, SProfile_FullUserInfo *FI); + int WriteFullInfo(DWORD *idx, SProfile_FullUserInfo *FI); + int DeleteFullInfo(DWORD idx); + + int GetSpaceforUInfo(DWORD *idx); + int WriteUInfo(DWORD idx, SProfile_UserInfo *FI); + int DeleteUInfo(DWORD idx); + int ReadUInfo(DWORD idx, SProfile_UserInfo *FI); +public: + DWORD errnum; + CProfiles(); + ~CProfiles(); + + int AddNewUser(SProfile_UserInfo *newprf, SProfile_FullUserInfo *FullUI, DWORD *ui_index); + int ModifyUser(SProfile_UserInfo *newprf, SProfile_FullUserInfo *FullUI, DWORD *ui_index); + int DeleteUser(char *name); + int GetUserByName(char *name, SProfile_UserInfo *ui, SProfile_FullUserInfo *Fui, DWORD *ui_index); + + // personal messages + int PostPersonalMessage(char *username, DWORD userindex, char *message, char *from, DWORD userindexfrom); + int ReadPersonalMessages(char *username, DWORD userindex, + SPersonalMessage **tomessages, DWORD *tocount, SPersonalMessage **frommessages, DWORD *fromcount); + + int ReadPersonalMessagesByDate(char *username, DWORD userindex, + SPersonalMessage **tomessages, time_t todate, SPersonalMessage **frommessages, time_t fromdate); + + int GenerateUserList(char ***buf, DWORD *cnt); + + int GetUsersCount(DWORD *uc); + int GetUInfo(DWORD idx, SProfile_UserInfo *FI); + int SetUInfo(DWORD idx, SProfile_UserInfo *FI); + int GetFullInfo(DWORD idx, SProfile_FullUserInfo *FI); + + int CheckandAddFavsList(DWORD userindex, DWORD msgindex, int doadd); + int DelFavsList(DWORD userindex, DWORD msgindex); +}; + +#endif blob - /dev/null blob + 7078bf2e0007902306bb99f956b395a32677cd33 (mode 644) --- /dev/null +++ src/profman.cpp @@ -0,0 +1,822 @@ +/*************************************************************************** + profman.cpp - profile and database management tool + ------------------- + begin : Wed May 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "profiles.h" +#include "searcher.h" + +#define DIR_CREATION_MASK 511 +#define FILES_CREATION_MASK 511 + +void printusage(char *iam) +{ + printf("Usage:\n\t %s -n - create/renew database (create new messages and profiles database)\n" \ + "\t %s -nu - create/renew ONLY profiles database (delete all profiles)\n" \ + "\t %s -nm - create/renew ONLY messages database (delete all forum messages)\n" \ + "\t %s -dcheck - check database consistency and print database information\n" \ + "\t %s -v user - view user information for user 'username'\n" \ + "\t %s -vp username - view all private messages for user 'username'\n" \ + "\t %s -aa user passwd - create admin (spec. username and password)\n" \ + "\t %s -au user passwd - create user (spec. username and password)\n" \ + "\t %s -d user - delete user\n" \ + "\t %s -np - renew(delete) private messages database (in profiles)\n" \ + "\t %s -r - zero refresh count for all users\n" \ + "\t %s -vs - set default view settings for all users\n" \ + "\t %s -sr [max_index] - create search index (up to max_index message, optional))\n" \ + "\t %s -s [word] - search for word using index\n", + iam, iam, iam, iam, iam, iam, iam, iam, iam, iam, iam, iam, iam, iam); + exit(0); +} + +int mmkdir(const char *s) +{ + int r; + char *ss; + if((ss = strchr(s, '/')) || (ss = strchr(s, '\\'))) { + char os[1000]; + if(strlen(ss) > 1) { + strncpy(os, s, ss - s); + os[ss - s] = 0; +#ifdef WIN32 + mkdir(os); +#else + mkdir(os, DIR_CREATION_MASK); +#endif + } + if((r = +#ifdef WIN32 + mkdir(s) +#else + mkdir(s, DIR_CREATION_MASK) +#endif + ) != 0) + return r; + } + return r; +} + + +void printuserrigth(DWORD r) +{ + printf("User right: "); + int smthprinted = 0; + if(r & USERRIGHT_SUPERUSER) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("SuperUser"); + } + if(r & USERRIGHT_VIEW_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("View message"); + } + if(r & USERRIGHT_MODIFY_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Modify own message"); + } + if(r & USERRIGHT_CLOSE_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Close own message thread"); + } + if(r & USERRIGHT_OPEN_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Open own message thread"); + } + if(r & USERRIGHT_CREATE_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Reply on message"); + } + if(r & USERRIGHT_CREATE_MESSAGE_THREAD) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Create new message thread"); + } + if(r & USERRIGTH_ALLOW_HTML) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Allow HTML"); + } + if(r & USERRIGTH_PROFILE_MODIFY) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Own Profile modification"); + } + if(r & USERRIGTH_PROFILE_CREATE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("New profile creation"); + } + if(r & USERRIGHT_ROLL_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Roll own messages"); + } + if(r & USERRIGHT_UNROLL_MESSAGE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Unroll own messages"); + } + if(r & USERRIGHT_POST_GLOBAL_ANNOUNCE) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Post global announce"); + } + if(r & USERRIGHT_ALT_DISPLAY_NAME) { + if(smthprinted) printf(", "); + else smthprinted = 1; + printf("Alternative name"); + } + printf("\n"); +} + +void printerror(DWORD er) +{ + printf("Result: "); + switch(er) { + case PROFILE_RETURN_ALLOK: + printf("All ok\n"); + case PROFILE_RETURN_ALREADY_EXIST: + printf("User already exits\n"); + break; + case PROFILE_RETURN_DB_ERROR: + printf("Database error\n"); + break; + case PROFILE_RETURN_INVALID_FORMAT: + printf("Invalid file format\n"); + break; + case PROFILE_RETURN_INVALID_LOGIN: + printf("Invalid login name\n"); + break; + case PROFILE_RETURN_INVALID_PASSWORD: + printf("Invalid password\n"); + break; + case PROFILE_RETURN_PASSWORD_SHORT: + printf("Password too short\n"); + break; + case PROFILE_RETURN_UNKNOWN_ERROR: + printf("Unknown database error\n"); + break; + } +} + +int CreateProfilesDatabase() +{ + FILE *f; + if((f = fopen(F_PROF_NINDEX, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating Database file : %s\n" \ + "Please make sure you have necessary directory structure\n", + F_PROF_NINDEX); + return 0; + } + else { + DWORD x = 0; + fwrite(&x, 1, sizeof(x), f); + fwrite(&x, 1, sizeof(x), f); + fclose(f); + } + if((f = fopen(F_PROF_FREENIDX, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_PROF_FREENIDX); + return 0; + } + else fclose(f); + if((f = fopen(F_PROF_BODY, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_PROF_BODY); + return 0; + } + else fclose(f); + if((f = fopen(F_PROF_FREEBODY, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_PROF_FREEBODY); + return 0; + } + else fclose(f); + if((f = fopen(F_PROF_PERSMSG, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_PROF_PERSMSG); + return 0; + } + else fclose(f); + + remove(F_PROF_INDEX); + if(AddStringToHashedIndex("aaa", 1) != HASHINDEX_ER_OK) { + printf("Error creating profiles database file : %s\n", F_PROF_INDEX); + return 0; + } + if(DeleteStringFromHashedIndex("aaa") != HASHINDEX_ER_OK) { + printf("Error creating profiles database file : %s\n", F_PROF_INDEX); + return 0; + } + return 1; +} + +int CreateMessagesDatabase() +{ + FILE *f; + if((f = fopen(F_MSGINDEX, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_MSGINDEX); + return 0; + } + else fclose(f); + if((f = fopen(F_MSGBODY, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_MSGBODY); + return 0; + } + else fclose(f); + if((f = fopen(F_INDEX, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_INDEX); + return 0; + } + else fclose(f); + if((f = fopen(F_VINDEX, FILE_ACCESS_MODES_CW)) == NULL) { + printf("Error creating profiles database file : %s\n", F_VINDEX); + return 0; + } + else fclose(f); + return 1; +} + +int CheckAndCreateFolder(char *d, char *s) +{ + if(chdir(d) != 0) { + if(mmkdir(d) != 0) { + printf("Cannot create directory %s\n", d); + return 0; + } + else printf("%s created\n", d); + } + else { + // return to our folder + if(chdir(s) != 0) { + printf("Cannot change directory to %s\n", s); + return 0; + } + } + return 1; +} + +int CreateFullDatabase() +{ + // alloc mem and save our current folder + char *s = (char*)malloc(2560); + if(getcwd(s, 2559) == NULL) { + printf("Cannot get current directory\n"); + return 0; + } + + if(!CheckAndCreateFolder(DIR_MAINDATA, s)) + return 0; + + if(!CheckAndCreateFolder(DIR_MESSAGES, s)) + return 0; + + if(!CheckAndCreateFolder(DIR_SEARCHER, s)) + return 0; + + if(!CheckAndCreateFolder(DIR_PROFILES, s)) + return 0; + + if(!CheckAndCreateFolder(DIR_PROF_PIC, s)) + return 0; + + if(!CheckAndCreateFolder(DIR_SETTINGS, s)) + return 0; + + if(!CheckAndCreateFolder(DIR_INTERNALS, s)) + return 0; + free(s); + + if(!CreateProfilesDatabase()) + return 0; + if(!CreateMessagesDatabase()) + return 0; + + return 1; +} + +int main(int argc, char *argv[]) +{ + CProfiles *ul; + DWORD errcode; + + SProfile_UserInfo ui; + WCFILE *fw; + + ul = new CProfiles(); + if(ul->errnum != PROFILE_RETURN_ALLOK) { + } + + printf("WWWConf console management tool\n"); + +#if USE_LOCALE + if(setlocale(LC_ALL, LANGUAGE_LOCALE) == NULL) { + printf("Setting locale [%s] failed !\n", LANGUAGE_LOCALE); + printf("Bailing out to default locale \"C\""); + setlocale(LC_ALL, "C"); + } +#endif + + if(argc <= 1) { + goto go_end; + } + if((strcmp(argv[1], "-au") == 0 || strcmp(argv[1], "-aa") == 0) && argc == 4) { + // create user + SProfile_UserInfo ui; + SProfile_FullUserInfo fui; + + strcpy(fui.Email, ""); + strcpy(fui.FullName, argv[2]); + strcpy(fui.Signature, ""); + strcpy(fui.HomePage, ""); + strcpy(fui.SelectedUsers, ""); + strcpy(ui.username, argv[2]); + strcpy(ui.password, argv[3]); + strcpy(ui.icqnumber, ""); + strcpy(ui.altdisplayname, ""); + fui.AboutUser = NULL; + + ui.lastIP = 0; + ui.Flags = 0; // don't have picture or signature + if(strcmp(argv[1], "-aa") != 0) { + ui.right = DEFAULT_USER_RIGHT; + ui.secur = DEFAULT_USER_SECURITY_BYTE; + ui.secheader = DEFAULT_USER_HDR_SEC_BYTE; + } + else { + ui.right = DEFAULT_ADMIN_RIGHT; + ui.secur = DEFAULT_ADMIN_SECURITY_BYTE; + ui.secheader = DEFAULT_ADMIN_HDR_SEC_BYTE; + } + + if((errcode = ul->AddNewUser(&ui, &fui, NULL)) == PROFILE_RETURN_ALLOK) + printf("User successfully created\n"); + else printerror(errcode); + goto go_stop; + } + + if(strcmp(argv[1], "-d") == 0 && argc == 3) { + if((errcode = ul->DeleteUser(argv[2])) == PROFILE_RETURN_ALLOK) { + printf("User successfully deleted\n"); + } + else printerror(errcode); + goto go_stop; + } + + if(strcmp(argv[1], "-v") == 0 && argc == 3) { + SProfile_FullUserInfo fui; + DWORD ind; + if(ul->errnum != PROFILE_RETURN_ALLOK) { + printf("Fatal: profiles database could not be accessed\n"); + goto go_stop; + } + if((errcode = ul->GetUserByName(argv[2], &ui, &fui, &ind)) == PROFILE_RETURN_ALLOK) { + printf("User Information\n"); + int sr = ui.secheader; + int srb = ui.secur; + printf("Login name : %s Password : %s\n", ui.username, ui.password); + fui.SelectedUsers[PROFILES_FULL_USERINFO_MAX_SELECTEDUSR - 1] = 0; + printf("AltName : %s\n, Full name : %s, E-mail : %s\nSelected users: %s\nAbout : %s\nSignature: %s\n" + "Flags: 0x%08x\nSecurity right byte (hdr) : %d\nSecurity right byte (body) : %d\nRefresh count : %d\n", + ui.altdisplayname, fui.FullName, fui.Email, fui.SelectedUsers, fui.AboutUser, + fui.Signature, ui.Flags, sr, srb, ui.RefreshCount); + printuserrigth(ui.right); + + char *s; + s = ctime(&fui.CreateDate); + printf("Creation date: %s\n", s); + + int nf = 0; + + if(ui.LoginDate != 0) s = ctime(&ui.LoginDate); + else { + nf = 1; + s = (char*)malloc(100); + strcpy(s, "Never logged in"); + } + printf("Last access date: %s\n", s); + if(nf) free(s); +/* ui.LoginDate -= 36000*7; + ul->SetUInfo(ind, &ui);*/ + } + else printerror(errcode); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-np") == 0) { + printf("Renewing private messages database...\n"); + if((fw = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_CW)) != NULL) { + wcfclose(fw); + } + else { + printf("Fatal: profiles database could not be accessed !!!\n"); + return 0; + } + if((fw = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) != NULL) { + int i = 0; + lock_file(fw); + wcfseek(fw, 8, SEEK_SET); + while(!wcfeof(fw)) { + DWORD pos = wcftell(fw); + if(wcfread(&ui, 1, sizeof(SProfile_UserInfo), fw) < sizeof(SProfile_UserInfo)) + break; + ui.persmescnt = 0; + ui.persmsg = 0xffffffff; + ui.readpersmescnt = 0; + ui.postedpersmsg = 0xffffffff; + ui.postedmescnt = 0; + wcfseek(fw, pos, SEEK_SET); + wcfwrite(&ui, 1, sizeof(SProfile_UserInfo), fw); + wcfseek(fw, wcftell(fw), SEEK_SET); + i++; + } + printf("%d users processed\n", i); + unlock_file(fw); + wcfclose(fw); + printf("Done!\n"); + } + else printf("Fatal: profiles database could not be accessed !!!\n"); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-r") == 0) { + printf("Clearing refresh count...\n"); + if((fw = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) != NULL) { + int i = 0; + lock_file(fw); + wcfseek(fw, 8, SEEK_SET); + while(!wcfeof(fw)) { + DWORD pos = wcftell(fw); + if(wcfread(&ui, 1, sizeof(SProfile_UserInfo), fw) < sizeof(SProfile_UserInfo)) + break; + ui.RefreshCount = 0; + wcfseek(fw, pos, SEEK_SET); + wcfwrite(&ui, 1, sizeof(SProfile_UserInfo), fw); + wcfseek(fw, wcftell(fw), SEEK_SET); + i++; + } + printf("%d users processed\n", i); + unlock_file(fw); + wcfclose(fw); + printf("Done!\n"); + } + else printf("Fatal: profiles database couldn't be accessed !!!\n"); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-vs") == 0) { + printf("Clearing view settings...\n"); + if((fw = wcfopen(F_PROF_NINDEX, FILE_ACCESS_MODES_RW)) != NULL) { + int i = 0; + lock_file(fw); + wcfseek(fw, 8, SEEK_SET); + while(!wcfeof(fw)) { + DWORD pos = wcftell(fw); + if(wcfread(&ui, 1, sizeof(SProfile_UserInfo), fw) < sizeof(SProfile_UserInfo)) + break; + + /* ui.vs.dsm = CONFIGURE_SETTING_DEFAULT_dsm; + ui.vs.topics = CONFIGURE_SETTING_DEFAULT_topics; + ui.vs.tv = CONFIGURE_SETTING_DEFAULT_tv; + ui.vs.tc = CONFIGURE_SETTING_DEFAULT_tc; + ui.vs.ss = CONFIGURE_SETTING_DEFAULT_ss; + ui.vs.lsel = CONFIGURE_SETTING_DEFAULT_lsel; + ui.vs.tt = CONFIGURE_SETTING_DEFAULT_tt; + ui.icqnumber[0] = 0; + ui.Flags |= PROFILES_FLAG_VIEW_SETTINGS; + ui.vs.tz = DATETIME_DEFAULT_TIMEZONE; + */ + ui.vs.topics |= (1<<17); + + wcfseek(fw, pos, SEEK_SET); + wcfwrite(&ui, 1, sizeof(SProfile_UserInfo), fw); + wcfseek(fw, wcftell(fw), SEEK_SET); + i++; + } + printf("%d users processed\n", i); + unlock_file(fw); + wcfclose(fw); + printf("Done!\n"); + } + else printf("Fatal: profiles database couldn't be accessed !!!\n"); + goto go_stop; + } + + if(argc == 3 && strcmp(argv[1], "-vp") == 0) { + SPersonalMessage *topm, *frompm; + CProfiles prof; + int code; + if((code = prof.GetUserByName(argv[2], &ui, NULL, NULL)) != PROFILE_RETURN_ALLOK) { + printf("User not found!\n"); + exit(0); + } + if((code = prof.ReadPersonalMessages(argv[2], 0, &topm, NULL, &frompm, NULL)) == PROFILE_RETURN_ALLOK) { + char tostr[1000], newm[100]; + char *ss; + SPersonalMessage *pmsg; + int i = 0; + int j = 0; + int received = 0; // posted or received + int cnt = 0, postedcnt = 0; + if(topm) { + while(topm[cnt].Prev != 0xffffffff) cnt++; + cnt++; + } + if(frompm) { + while(frompm[postedcnt].Prev != 0xffffffff) postedcnt++; + postedcnt++; + } + printf(" Messages for user %s\n", argv[2]); + for(;;) { + // check exit expression + if(i == cnt && j == postedcnt) break; + if(i == cnt) { + pmsg = &(frompm[j]); + j++; + received = 0; + } else { + if(j == postedcnt) { + pmsg = &(topm[i]); + i++; + received = 1; + } + else { + if(frompm[j].Date > topm[i].Date) { + pmsg = &(frompm[j]); + j++; + received = 0; + } + else { + pmsg = &(topm[i]); + i++; + received = 1; + } + } + } + + if(!received) { + strcpy(tostr, pmsg->NameTo); + } + else { + strcpy(tostr, pmsg->NameFrom); + } + + ss = ctime(&pmsg->Date); + + if(received && i <= (ui.persmescnt - ui.readpersmescnt)) + strcpy(newm, "Not readed"); + else strcpy(newm, ""); + + if(!received) { + // posted message + printf("To user: %s, Date: %s\t\t\t%s", tostr, ss, newm); + } + else { + // received message + printf("From user: %s, Date: %s\t\t\t%s", tostr, ss, newm); + } + + printf("%s\n\n", pmsg->Msg); + } + } + else printf("ReadPersonalMessages() returned error code: %x (%s)\n", code, (code == PROFILE_RETURN_INVALID_LOGIN) ? "unknown user" : "database error"); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-nu") == 0) { + printf("Creating/Renewing profiles database...\n"); + if(!CreateProfilesDatabase()) + goto go_stop; + printf("Operation completed successfully\n"); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-n") == 0) { + printf("Creating/Renewing profiles and messages databases...\n"); + if(!CreateFullDatabase()) + goto go_stop; + printf("Operation completed successfully\n"); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-nm") == 0) { + printf("Creating/Renewing messages database...\n"); + if(!CreateMessagesDatabase()) + goto go_stop; + printf("Operation completed successfully\n"); + goto go_stop; + } + + if(argc == 2 && strcmp(argv[1], "-dcheck") == 0) { + printf("Checking profiles database...\n"); +#if 0 + printf("Operation completed successfully\n"); + printf("Checking messages database...\n"); + printf("Operation completed successfully\n"); +#else + printf("Function not yet implemented!\n"); +#endif + goto go_stop; + } + + if(strcmp(argv[1], "-s") == 0) { + if(argc == 3) { + CMessageSearcher *in = new CMessageSearcher(SEARCHER_INDEX_CREATE_EXISTING); + if(in->errnum != SEARCHER_RETURN_ALLOK) { + printf("Searcher init = failed\nMake sure that search index was created\n"); + goto go_stop; + } + DWORD c; + DWORD *buf = in->SearchMessagesByPattern(argv[2], &c); + if(c > 0) { + printf("Found %ld matches in messages : ", c); + for(register DWORD i = 0; i < c; i++) { + printf("%ld ", buf[i]); + } + free(buf); + } + else { + printf("Found 0 matches"); + } + printf("\n"); + delete in; + goto go_stop; + } + else { + printf("Invalid parameters count for -s\n"); + goto go_stop; + } + } + + if(strcmp(argv[1], "-sr") == 0) { + DWORD StartMsg = 0, LastDate = 0, DBDirty = 0, StopIndex = 0; + CMessageSearcher *in = NULL; + SMessage *sm; + time_t now, start; + FILE *fl, *f, *f1, *f2; + if(argc == 2) { + StopIndex = 0xffffffff; + } + else { + char *st; + StopIndex = strtol(argv[2], &st, 10); + if(((!(*(argv[2]) != '\0' && *st == '\0')) || errno == ERANGE)) { + printf("Invalid parameter for -sr command\n"); + goto go_stop; + } + } + + fl = fopen(F_SEARCH_LASTINDEX, FILE_ACCESS_MODES_RW); + if(fl != NULL) { + fscanf(fl, "%d %d", &StartMsg, &LastDate, &DBDirty); + fclose(fl); + if(DBDirty) { + printf("Database marked as dirty (another instance of indexer in progress?)\n", F_SEARCH_LASTINDEX); + goto go_stop; + } + } + + // mark as dirty + fl = fopen(F_SEARCH_LASTINDEX, FILE_ACCESS_MODES_CW); + if(f != NULL) { + fprintf(fl, "%d %d %d", StartMsg, LastDate, 1); + fclose(fl); + } + else { + printf("Couldn't create status file %s\n", F_SEARCH_LASTINDEX); + goto go_stop; + } + + if(StartMsg == 0) { + f = fopen(F_SEARCH_DB, FILE_ACCESS_MODES_CW); + if(f == NULL) { + printf("Error creating searcher database file %s\n", F_SEARCH_DB); + goto go_stop; + } + fclose(f); + in = new CMessageSearcher(SEARCHER_INDEX_CREATE_NEW); + } + else in = new CMessageSearcher(SEARCHER_INDEX_CREATE_EXISTING); + if(in->errnum != SEARCHER_RETURN_ALLOK) { + printf("Searcher init = failed\n"); + goto go_stop; + } + + sm = (SMessage*)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER); + in->indexed_word_count = 0; + + f = fopen(F_MSGINDEX, FILE_ACCESS_MODES_R); + f1 = fopen(F_MSGBODY, FILE_ACCESS_MODES_R); + f2 = fopen(F_VINDEX, FILE_ACCESS_MODES_R); + + if(f == NULL || f1 == NULL || f2 == NULL) { + free(sm); + printf("Error opening database files\n"); + goto go_stop; + } + + DWORD rr, idx; + char *mbody; + DWORD wc = 0; + time_t tm = time(NULL); + printf("Indexing(starting from %ld), report format: NUM-SEC, NUM-processed mess, SEC-seconds last 100 mess were indexed", StartMsg); + + if(fseek(f2, (StartMsg+1)*sizeof(DWORD), SEEK_SET) != 0) { + free(sm); + printf("Invalid starting index\n"); + goto go_stop; + } + + start = time(NULL); + while(!feof(f2)) { + + if(StartMsg >= StopIndex) { + printf("Stopped at index %ld (StopIndex)", StartMsg); + break; + } + + if(fread(&idx, 1, sizeof(DWORD), f2) != sizeof(DWORD)) { + break; + } + StartMsg++; + + if(idx == 0xFFFFFFFF) continue; + + if(fseek(f, idx, SEEK_SET) != 0) { + continue; + } + rr = (DWORD)fread(sm, 1, sizeof(SMessage), f); + if(rr != sizeof(SMessage) && rr != 0) { + printf("Error reading %s\n", F_MSGINDEX); + goto go_stop; + } + wc++; + in->InsertMessageToIndex(sm->MessageHeader, sm->ViIndex); + + if((sm->Flag & MESSAGE_HAVE_BODY) != 0 && sm->msize > 2) { + DWORD readed; + mbody = (char*)malloc(sm->msize + 10); + if(fseek(f1, sm->MIndex, SEEK_SET) != 0) { + free(mbody); + continue; + } + if((readed = (DWORD)fread(mbody, 1, sm->msize + 2, f1)) < sm->msize) { + free(mbody); + continue; + } + mbody[readed] = 0; + if(sm->msize != 0 && *mbody == 0) { + char *ss = mbody; + ss++; + while(*ss) { + *(ss-1) = *(ss); + ss++; + } + *(ss-1) = *ss; + } + if(strlen(mbody) > 65000) { + printf("\nIncorrect DB format: Body of message %d is too long\n", sm->ViIndex); + goto go_stop; + } + in->InsertMessageToIndex(mbody, sm->ViIndex); + free(mbody); + } + if((wc % 100) == 0) { + now = time(NULL); + printf("%ld-%d.", wc, start - now); + start = now; + fflush(stdout); + } + } + fclose(f); + fclose(f1); + fclose(f2); + printf("\nDone at %ld\nFlusing cache...", StartMsg); + DWORD iww = in->indexed_word_count; + DWORD tcache = time(NULL); + delete in; + printf("done in %ld seconds\n", time(NULL) - tcache); + + fl = fopen(F_SEARCH_LASTINDEX, FILE_ACCESS_MODES_CW); + if(f != NULL) { + fprintf(fl, "%d %d %d", StartMsg, LastDate, 0); + fclose(fl); + } + + printf("\nFinished in %ld seconds, words indexed %ld\n", time(NULL) - tm, iww); + free(sm); + goto go_stop; + } + +go_end: + printf("Fatal: Invalid option was specified: %s\n\n", argv[1] ? argv[1] : ""); + printusage(argv[0]); +go_stop: + delete ul; + return 0; +} blob - /dev/null blob + dad3646a31e0e95208285dad1ef2f5cd1e6854df (mode 644) --- /dev/null +++ src/reindex.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** + reindex.cpp - message index build tool + ------------------- + begin : Wed Apr 29 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "searcher.h" + +void printusage(char *iam) +{ + printf("Usage:\n" \ + " %s -r [max_index] - index messages (up to max_index (optional))\n" \ + " %s -s word - search for word\n", iam, iam); + exit(0); +} + +int main(int argc, char *argv[]) +{ + FILE *f, *f1, *f2, *fl; + DWORD StartMsg = 0, LastDate = 0, StopIndex = 0; + CMessageSearcher *in; + SMessage *sm; + time_t now, start; + + printf("WWWConf search index builder\n"); +#if USE_LOCALE + if(setlocale(LC_ALL, LANGUAGE_LOCALE) == NULL) { + printf("Setting locale [%s] failed !\n", LANGUAGE_LOCALE); + printf("Bailing out to default locale \"C\""); + setlocale(LC_ALL, "C"); + } +#endif + if(argc < 2 || (argc >= 2 && strcmp(argv[1], "-r") != 0)) { + if(argc == 3 && strcmp(argv[1], "-s") == 0) { + in = new CMessageSearcher(SEARCHER_INDEX_CREATE_EXISTING); + if(in->errnum != SEARCHER_RETURN_ALLOK) { + printf("Searcher init = failed\n"); + exit(0); + } + DWORD c; + DWORD *buf = in->SearchMessagesByPattern(argv[2], &c); + if(c > 0) { + printf("Found %ld matches in messages : ", c); + for(register DWORD i = 0; i < c; i++) { + printf("%ld ", buf[i]); + } + free(buf); + } + else { + printf("Found 0 matches"); + } + printf("\n"); + delete in; + exit(0); + } + else { + printusage(argv[0]); + exit(0); + } + } + + if(argc != 3 && argc != 2) { + printusage(argv[0]); + exit(0); + } + if(argc == 3) { + char *st; + StopIndex = strtol(argv[2], &st, 10); + if(((!(*(argv[2]) != '\0' && *st == '\0')) || errno == ERANGE)) { + printusage(argv[0]); + exit(0); + } + else { + // correct value + } + } + else StopIndex = 0xffffffff; + + fl = fopen("lastindex", FILE_ACCESS_MODES_RW); + if(fl == NULL) { + } + else { + fscanf(fl, "%d %d", &StartMsg, &LastDate); + fclose(fl); + } + + if(StartMsg == 0) { + f = fopen(F_SEARCH_DB, FILE_ACCESS_MODES_CW); + if(f == NULL) { + printf("Error opening DB file\n"); + exit(0); + } + fclose(f); + in = new CMessageSearcher(SEARCHER_INDEX_CREATE_NEW); + } + else in = new CMessageSearcher(SEARCHER_INDEX_CREATE_EXISTING); + if(in->errnum != SEARCHER_RETURN_ALLOK) { + printf("Searcher init = failed\n"); + exit(0); + } + + sm = (SMessage*)malloc(sizeof(SMessage)*READ_MESSAGE_HEADER); + in->indexed_word_count = 0; + + f = fopen(F_MSGINDEX, FILE_ACCESS_MODES_R); + f1 = fopen(F_MSGBODY, FILE_ACCESS_MODES_R); + f2 = fopen(F_VINDEX, FILE_ACCESS_MODES_R); + + if(f == NULL || f1 == NULL || f2 == NULL) { + printf("Error opening database files\n"); + exit(0); + } + + DWORD rr, idx; + char *mbody; + DWORD wc = 0; + DWORD tm = time(NULL); + printf("Indexing(starting from %ld), report format: NUM-SEC, NUM-processed mess, SEC-seconds last 100 mess were indexed", StartMsg); + + if(fseek(f2, (StartMsg+1)*sizeof(DWORD), SEEK_SET) != 0) { + printf(" Invalid starting index\n"); + exit(0); + } + + start = time(NULL); + while(!feof(f2)) { + + if(StartMsg >= StopIndex) { + printf("Stopped at index %ld (StopIndex)", StartMsg); + break; + } + + if(fread(&idx, 1, sizeof(DWORD), f2) != sizeof(DWORD)) { + break; + } + StartMsg++; + + if(idx == 0xFFFFFFFF) continue; + + if(fseek(f, idx, SEEK_SET) != 0) { + continue; + } + rr = fread(sm, 1, sizeof(SMessage), f); + if(rr != sizeof(SMessage) && rr != 0) { + printf("Error reading %s\n", F_MSGINDEX); + exit(0); + } + wc++; + in->InsertMessageToIndex(sm->MessageHeader, sm->ViIndex); + + // fflush(stdout); + if((sm->Flag & MESSAGE_HAVE_BODY) != 0 && sm->msize > 2) { + DWORD readed; + mbody = (char*)malloc(sm->msize + 10); + if(fseek(f1, sm->MIndex, SEEK_SET) != 0) { + free(mbody); + continue; + } + if((readed = fread(mbody, 1, sm->msize + 2, f1)) < sm->msize) { + free(mbody); + continue; + } + mbody[readed] = 0; + if(sm->msize != 0 && *mbody == 0) { + char *ss = mbody; + ss++; + while(*ss) { + *(ss-1) = *(ss); + ss++; + } + *(ss-1) = *ss; + } + if(strlen(mbody) > 65000) { + printf("\nIncorrect DB format: Body of message %d is too long\n", sm->ViIndex); + exit(0); + } + in->InsertMessageToIndex(mbody, sm->ViIndex); + free(mbody); + } + if((wc % 100) == 0) { + now = time(NULL); + printf("%ld-%d.", wc, start-now); + start = now; + fflush(stdout); + } + } + fclose(f); + fclose(f1); + fclose(f2); + printf("\nDone at %ld\nFlusing cache...", StartMsg); + DWORD iww = in->indexed_word_count; + delete in; + + fl = fopen("lastindex", FILE_ACCESS_MODES_CW); + if(f != NULL) { + fprintf(fl, "%d %d", StartMsg, LastDate); + fclose(fl); + } + + printf("\nFinished in %ld seconds, words indexed %ld\n", time(NULL) - tm, iww); + free(sm); + return 0; +} blob - /dev/null blob + 8e6cd3beba265e752ff76c46179a9737d4529111 (mode 644) --- /dev/null +++ src/robot_workaround.cpp @@ -0,0 +1,15 @@ +bool IsRobotNick(char *nick) // code by ring0 & jetsys +{ + static char robot_rus[]="ðîáîò-ìóðçîëîã-"; + static char robot_lat[]="poáoò-ìypçoëoã-"; + if(!nick) + return false; + for(int i = 0; i <= 14; i++) { + if( + nick[i] != robot_rus[i] && + nick[i] != robot_lat[i] + ) + return false; + } + return true; +} \ No newline at end of file blob - /dev/null blob + 397cee55915c78740956ef1a620eeae7d505699a (mode 644) --- /dev/null +++ src/robot_workaround.h @@ -0,0 +1 @@ +bool IsRobotNick(char *nick); \ No newline at end of file blob - /dev/null blob + ce07edc994ba203573b7caed63107dcda2220b14 (mode 644) --- /dev/null +++ src/searcher.cpp @@ -0,0 +1,650 @@ +/*************************************************************************** + searcher.cpp - message search support + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "searcher.h" + +#define SEARCHER_REALLOC_ALLSUBSTRINGS_MULTI 10 +#define SEARCHER_MAX_WORD_LENGTH 20 + +#define sr_lock_file() {lock_file(f);} +#define sr_unlock_file() {unlock_file(f);} +#define sr_unlock_and_db_error() {unlock_file(f); errnum = SEARCHER_RETURN_DB_ERROR; return SEARCHER_RETURN_DB_ERROR;} +#define sr_db_error() {errnum = SEARCHER_RETURN_DB_ERROR; return SEARCHER_RETURN_DB_ERROR;} +#define sr_db_error1() {errnum = SEARCHER_RETURN_DB_ERROR; return NULL;} + +/* toupper string using CP1251 + */ +char* toupperstr(char *s) +{ + if(s == NULL) return s; + register DWORD k = (DWORD)strlen(s); + for(register DWORD i = 0; i < k; i++) { + if(s[i] >= 'à' && s[i] <= 'ÿ') { + s[i] -= ('à' - 'À'); + } + else { + if(!(s[i] >= 'À' && s[i] <= 'ß')) + s[i] = (char)toupper((unsigned char)s[i]); + } + } + return s; +} + +/*************************** + * fast quick sort algorithm + */ +#define QSORT_MAXSTACK (sizeof(DWORD)*200) + +void inline swap(DWORD *a, DWORD *b) +{ + register DWORD t=*a; + *a=*b; + *b = t; +} + +int inline compar(const void *a, const void *b) { return *(DWORD *)a - *(DWORD *)b; } + +void inline mqsort(void *base, size_t nmemb) { + void *lbStack[QSORT_MAXSTACK], *ubStack[QSORT_MAXSTACK]; + int sp; + DWORD offset; + lbStack[0] = (char *)base; + ubStack[0] = (char *)base + (nmemb-1)*sizeof(DWORD); + for (sp = 0; sp >= 0; sp--) { + char *lb, *ub, *m; + char *P, *i, *j; + + lb = (char*)lbStack[sp]; + ub = (char*)ubStack[sp]; + + while (lb < ub) { + offset = DWORD((ub - lb) >> 1); + P = lb + offset - offset % sizeof(DWORD); + swap( (DWORD*)lb, (DWORD*)P); + + i = lb + sizeof(DWORD); + j = ub; + for(;;) { + while (i < j && compar(lb, i) > 0) i += sizeof(DWORD); + while (j >= i && compar(j, lb) > 0) j -= sizeof(DWORD); + if (i >= j) break; + swap((DWORD*)i, (DWORD*)j); + j -= sizeof(DWORD); + i += sizeof(DWORD); + } + + swap((DWORD*)lb, (DWORD*)j); + m = j; + + if (m - lb <= ub - m) { + if (m + sizeof(DWORD) < ub) { + lbStack[sp] = m + sizeof(DWORD); + ubStack[sp++] = ub; + } + ub = m - sizeof(DWORD); + } + else { + if (m - sizeof(DWORD) > lb) { + lbStack[sp] = lb; + ubStack[sp++] = m - sizeof(DWORD); + } + lb = m + sizeof(DWORD); + } + } + } +} + +/* Linear join two sorted arrays + * find an equals element in arrays buf1, buf2 and store them to rbuf + * return count of the found equal elements + */ +DWORD inline join_sorted(DWORD *buf1, DWORD c1, DWORD *buf2, DWORD c2, DWORD **rbuf) +{ + DWORD c = 0, minc; + DWORD p1 = 0, p2 = 0; + if(c1 > c2) minc = c2; else minc = c1; + *rbuf = (DWORD*)malloc(minc*sizeof(DWORD)); + + for(;;) { + if(buf1[p1] > buf2[p2]) { + if(p2 < (c2 - 1)) p2++; + else break; + } + else { + if(buf1[p1] < buf2[p2]) { + if(p1 < (c1 - 1)) p1++; + else break; + } + else { + (*rbuf)[c] = buf1[p1]; + c++; + if(p2 < (c2 - 1)) p2++; + else { + if(p1 < (c1 - 1)) p1++; + else break; + } + } + } + } + + if(c != 0) *rbuf = (DWORD*)realloc(*rbuf, c*sizeof(DWORD)); + else { + free(*rbuf); + *rbuf = NULL; + } + return c; +} + +/*************************** + * CMessageSearcher class + */ + +/* generate all substrings of string s with length > SEARCHER_MIN_WORD + * return number of substrings in resulting string *res, resulting string *res + * ended with 0x00 0x00 at the end + */ +int CMessageSearcher::GetAllSubstrings(char *s, char **res) +{ + DWORD a, b, i, j, mlen, len, inc; + DWORD wc = 0; + b = a = (DWORD)strlen(s); + inc = mlen = SEARCHER_REALLOC_ALLSUBSTRINGS_MULTI*b; + *res = (char*)malloc(mlen); + if(a <= SEARCHER_MIN_WORD) { + strcpy(*res, s); + *res = (char*)realloc(*res, b + 1); + return 1; + } + a -= SEARCHER_MIN_WORD; + len = 0; + DWORD r = 0; + for(i = 0; i <= a; i++) { + for(j = i + SEARCHER_MIN_WORD - 1; j < b; j++) { + char tmp = *(s + j + 1); + *(s + j + 1) = 0; + if(j - i + 1 +len >= mlen) { + mlen = mlen + inc; + *res = (char*)realloc(*res, mlen); + } + wc++; + strcpy((*res) + r, s + i); + r += j-i+2; + len += j-i+2; + *(s + j + 1) = tmp; + } + } + (*res)[r] = 0; + *res = (char*)realloc(*res, len + 1); + return wc; +} + +CMessageSearcher::CMessageSearcher(DWORD flags) +{ + DWORD i; + srch_str = NULL; + srch_str_len = 0; + SI = new CIndexFile(F_SEARCH_INDEX, flags, (WORD)strlen(SEARCHER_SYMBOLS_TABLE), + SEARCHER_SYMBOLS_TABLE, SEARCHER_INDEX_LENGTH); + f = NULL; + symtbl = NULL; + indexed_word_count = 0; + if(SI->errnum != INDEXFILE_ERROR_ALLOK) { + delete SI; + SI = NULL; + errnum = SEARCHER_RETURN_DB_ERROR; + return; + } + if((f = wcfopen(F_SEARCH_DB, + (flags & SEARCHER_INDEX_CREATE_NEW) ? FILE_ACCESS_MODES_CW : + FILE_ACCESS_MODES_RW)) == NULL && + (f = wcfopen(F_SEARCH_DB, + (flags & SEARCHER_INDEX_CREATE_EXISTING) ? FILE_ACCESS_MODES_CW : + FILE_ACCESS_MODES_RW)) == NULL + ) + { + delete SI; + SI = NULL; + errnum = SEARCHER_RETURN_DB_ERROR; + return; + } + symtbl = (char*)malloc(SEARCHER_MAX_CHARACTER_CODE); + if(symtbl == NULL) { + delete SI; + SI = NULL; + errnum = SEARCHER_RETURN_DB_ERROR; + return; + } + for(i = 0; i < SEARCHER_MAX_CHARACTER_CODE; i++) + symtbl[i] = 0; + + for(i = 0; i < strlen(SEARCHER_SYMBOLS_TABLE); i++) { + symtbl[(unsigned char)SEARCHER_SYMBOLS_TABLE[i]] = 1; + } + errnum = SEARCHER_RETURN_ALLOK; +} + +CMessageSearcher::~CMessageSearcher() +{ + if(SI != NULL) delete SI; + if(symtbl != NULL) free(symtbl); + if(srch_str != NULL) free(srch_str); + if(f != NULL) wcfclose(f); +} + +/* insert word [word] with message index [mid] to search index + * return SEARCHER_RETURN_ALLOK if successfull, otherwise error code returned + */ + +//int CMessageSearcher::InsertWordToIndex(char *word, DWORD mid) +//{ +// SSearcherHStruct sb, sb1, sv_sb; +// DWORD idx, dberr, curmalloc, pos_notfound, svpos; +// DWORD *buf; +// +// +// indexed_word_count++; +// +// if((dberr = SI->GetIndexByWord(word, &idx, NULL)) == INDEXFILE_ERROR_INDEX_NOT_EXIST) { +// /* create new index */ +// /********* lock f *********/ +// sr_lock_file(); +// +// if(wcfseek(f, 0, SEEK_END) != 0) sr_unlock_and_db_error(); +// +// idx = wcftell(f); +// +// /* tune sb1 - new block header */ +// sb1.prev = 0xFFFFFFFF; +// sb1.count = SEARCHER_NEW_CLUSTER_BLOCK_SIZE; +// sb1.used = 1; +// +// if(!fCheckedWrite(&sb1, sizeof(sb), f)) sr_unlock_and_db_error(); +// buf = (DWORD*)malloc(sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE); +// if(buf == NULL) sr_unlock_and_db_error(); +// buf[0] = mid; +// for(register DWORD i = 1; i < SEARCHER_NEW_CLUSTER_BLOCK_SIZE; i++) buf[i] = 0; +// if(!fCheckedWrite(buf, sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE, f)) { +// free(buf); +// sr_unlock_and_db_error(); +// } +// free(buf); +// +// if((dberr = SI->PutIndexByWord(word, idx)) != INDEXFILE_ERROR_ALLOK) +// sr_unlock_and_db_error(); +// +// goto Unlock_End; +// } +// if(dberr != INDEXFILE_ERROR_ALLOK) +// sr_db_error(); +// +// /* add index */ +// sb.prev = idx; +// +// if((buf = (DWORD*)malloc(sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE)) == NULL) sr_db_error(); +// curmalloc = SEARCHER_NEW_CLUSTER_BLOCK_SIZE; +// +// /********* lock f *********/ +// sr_lock_file(); +// +// pos_notfound = 1; +// +// if(sb.prev != 0xFFFFFFFF){ +// if(wcfseek(f, sb.Next, SEEK_SET) != 0) sr_unlock_and_db_error(); +// +// idx = sb.prev; +// +// if(!fCheckedRead(&sb, sizeof(SSearcherHStruct), f)) +// sr_unlock_and_db_error(); +// +// /* is block to long ? */ +// if(sb.used > curmalloc) { +// buf = (DWORD*)realloc(buf, sb.used*sizeof(DWORD)); +// curmalloc = sb.count; +// } +// +// if(!fCheckedRead(buf, sizeof(DWORD)*sb.used, f)) sr_unlock_and_db_error(); +// +// for(register DWORD i = 0; i < sb.used; i++) { +// if(buf[i] == mid) { +// /* already exist ! shouldn't add again */ +// free(buf); +// goto Unlock_End; +// } +// } +// +// if(sb.used < sb.count && pos_notfound) { +// /* save first usefull block */ +// pos_notfound = 0; +// sv_sb = sb; +// svpos = idx; +// } +// } +// +// free(buf); +// +// if(pos_notfound == 1) { +// /* add new block */ +// if(wcfseek(f, 0, SEEK_END) != 0) sr_unlock_and_db_error(); +// sb.Next = wcftell(f); +// +// /* tune sb1 - new block header */ +// sb1.Next = 0xFFFFFFFF; +// sb1.count = SEARCHER_NEW_CLUSTER_BLOCK_SIZE; +// sb1.used = 1; +// +// /* save new cluster block */ +// if(!fCheckedWrite(&sb1, sizeof(sb), f)) sr_unlock_and_db_error(); +// buf = (DWORD*)malloc(sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE); +// if(buf == NULL) sr_unlock_and_db_error(); +// buf[0] = mid; +// for(register DWORD i = 1; i < SEARCHER_NEW_CLUSTER_BLOCK_SIZE; i++) buf[i] = 0; +// if(!fCheckedWrite(buf, sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE, f)) { +// free(buf); +// sr_unlock_and_db_error(); +// } +// free(buf); +// if(wcfseek(f, idx, SEEK_SET) != 0) sr_unlock_and_db_error(); +// if(!fCheckedWrite(&sb, sizeof(sb), f)) sr_unlock_and_db_error(); +// } +// else { +// /* place for add found */ +// sv_sb.used++; +// +// if(wcfseek(f, svpos, SEEK_SET) != 0) sr_unlock_and_db_error(); +// +// if(!fCheckedWrite(&sv_sb, sizeof(sv_sb), f)) sr_unlock_and_db_error(); +// +// if(wcfseek(f, svpos + sizeof(sv_sb) + (sv_sb.used - 1)*sizeof(mid), SEEK_SET) != 0) +// sr_unlock_and_db_error(); +// if(!fCheckedWrite(&mid, sizeof(mid), f)) sr_unlock_and_db_error(); +// } +// +//Unlock_End: +// sr_unlock_file(); +// /****** unlock f ******/ +// +// errnum = SEARCHER_RETURN_ALLOK; +// return SEARCHER_RETURN_ALLOK; +//} + +/* + * return 1 if successfull otherwise zero returned + */ +/* Function create new block for storing references to messages(blocks, clusters, etc.) if bi = 0xFFFFFFF + * and put to new block message with CMessageSearcher::AddingMId + * return Id of created block or 0xFFFFFFFF if an error occured + */ +/*DWORD CMessageSearcher::AllocRefBlock()*/ +/*DWORD CMessageSearcher::AddMessageToRefBlock(DWORD bi)*/ +/* changed, get last block, checking last MId, adding, retunrnig block address */ + + +DWORD CMessageSearcher::AddMessageToRefBlock(DWORD bi) +{ + SSearcherHStruct sb; + DWORD buf[SEARCHER_NEW_CLUSTER_BLOCK_SIZE*SEARCHER_MAX_CONTIGIOUS_CLUSTERS]; + bool add_new = 1; + // we just have found out that there is an existing block for this word + // so we should only add new message index + + if (bi != INDEXFILE_NO_INDEX){ + if(wcfseek(f, bi, SEEK_SET) != 0) goto Ret_Error; + + if(!fCheckedRead(&sb, sizeof(SSearcherHStruct), f)) + goto Ret_Error; + + // is block to long ? + if(sb.used > SEARCHER_NEW_CLUSTER_BLOCK_SIZE*SEARCHER_MAX_CONTIGIOUS_CLUSTERS) { + // ASSERTION HERE - we do not support such large blocks + goto Ret_Error; + } + + if(!fCheckedRead(buf, sizeof(DWORD)*sb.used, f)) + goto Ret_Error; + + // check last id + // AlexBi: If we are having full block here it's not bad idea to check through it + for(register DWORD i = 0; i < sb.used; i++) { + if(buf[i] == AddingMId) { + // already exist ! shouldn't add again + goto Ret_Ok; + } + } + + if(sb.used < sb.count) { + // save first usefull block + sb.used++; + // update block header + if(wcfseek(f, bi, SEEK_SET) != 0) goto Ret_Error; + if(!fCheckedWrite(&sb, sizeof(sb), f)) goto Ret_Error; + + // update block data + if(wcfseek(f, bi + sizeof(sb) + (sb.used - 1)*sizeof(AddingMId), SEEK_SET) != 0) + goto Ret_Error; + if(!fCheckedWrite(&AddingMId, sizeof(AddingMId), f)) goto Ret_Error; + add_new = 0; + } + } + if(add_new) { + // add new block + + /* tune sb - new block header */ + sb.prev = bi; + sb.count = SEARCHER_NEW_CLUSTER_BLOCK_SIZE; + sb.used = 1; + + //get place + if(wcfseek(f, 0, SEEK_END) != 0) goto Ret_Error; + bi = wcftell(f); + + // save new block header + if(!fCheckedWrite(&sb, sizeof(sb), f)) goto Ret_Error; + + // create new block data + memset((void*)(&buf), 0, sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE); + buf[0] = AddingMId; + // save new block data + if(!fCheckedWrite(buf, sizeof(DWORD)*SEARCHER_NEW_CLUSTER_BLOCK_SIZE, f)) { + goto Ret_Error; + } + } +Ret_Ok: + //return current last block + return bi; +Ret_Error: + return 0; +} + +/* insert word [word] and subwords begining with [word] (lenght from + * SEARCHER_MIN_WORD to [word]) with message index [mid] to search index + * return SEARCHER_RETURN_ALLOK if successfull, otherwise error code returned + */ +int CMessageSearcher::InsertWordWithSubwordsToIndex(char *word, DWORD mid) +{ + indexed_word_count++; + + // create new index + //********* lock f **********/ + sr_lock_file(); + + // We have already allocated a new block if we'll need it later, so continue adding + // the word. Later, if we find out that do not need this block we simply skip creation step. + // this is not optimal realization, and later we should use a procedure varables. + // Then we should call PutOrGetIndexByWordAssoc() + + AddingMId = mid; + if(SI->PutOrGetIndexByWordAssoc(word, SEARCHER_MIN_WORD - 1, this) != INDEXFILE_ERROR_ALLOK) + sr_unlock_and_db_error(); + + sr_unlock_file(); + /****** unlock f ******/ + + errnum = SEARCHER_RETURN_ALLOK; + return SEARCHER_RETURN_ALLOK; +} + + +/* insert message with VIndex = mid to index + * return SEARCHER_RETURN_ALLOK if successfull, otherwise error code returned + */ +int CMessageSearcher::InsertMessageToIndex(char *body, DWORD mid) +{ + DWORD i, rr; + toupperstr(body); + do { + i = 0; + while(body[i] != 0 && symtbl[(unsigned char)body[i]] == 1 && i < SEARCHER_MAX_WORD_LENGTH) i++; + if(i >= SEARCHER_MIN_WORD) { + char x = body[i]; + body[i] = 0; + + DWORD a = i - SEARCHER_MIN_WORD; + for(register DWORD k = 0; k <= a; k++) { + rr = InsertWordWithSubwordsToIndex(body + k, mid); + if(rr != SEARCHER_RETURN_ALLOK) return rr; + } + + /*DWORD *xx; + DWORD cnt; + if((xx = SearchMessagesByPattern(body + 1, &cnt)) != 0) { + free(xx); + }*/ + + body[i] = x; + } + if(body[i] != 0) body += i + 1; + else body += i; + + } while(*body != 0); + errnum = SEARCHER_RETURN_ALLOK; + return SEARCHER_RETURN_ALLOK; +} + +DWORD* CMessageSearcher::SearchMessagesByWord(char *wmask, DWORD *count) +{ + DWORD cd; + int uniq; + SSearcherHStruct sb; + DWORD *buf; + + *count = 0; + + if((cd = SI->GetIndexByWord(wmask, &(sb.prev), &uniq)) != INDEXFILE_ERROR_ALLOK) { + switch(cd) { + case INDEXFILE_ERROR_INVALID_WORD: + errnum = SEARCHER_RETURN_INVALID_WORD; + return NULL; + break; + case INDEXFILE_ERROR_INDEX_NOT_EXIST: + errnum = SEARCHER_RETURN_WORD_NOT_FOUND; + return NULL; + break; + default: + errnum = SEARCHER_RETURN_DB_ERROR; + return NULL; + } + } + + buf = (DWORD*)malloc(1); + while(sb.prev != 0xFFFFFFFF) { + if(wcfseek(f, sb.prev, SEEK_SET) != 0) { + free(buf); + sr_db_error1(); + } + if(!fCheckedRead(&sb, sizeof(sb), f)) { + free(buf); + sr_db_error1(); + } + + buf = (DWORD*)realloc(buf, (*count)*sizeof(DWORD) + sb.used*sizeof(DWORD) + 1); + + if(!fCheckedRead(&(buf[*count]), sb.used*sizeof(DWORD), f)) { + free(buf); + sr_db_error1(); + } + *count += sb.used; + } + errnum = SEARCHER_RETURN_ALLOK; + return buf; +} + +DWORD* CMessageSearcher::SearchMessagesByPattern(char *wpat, DWORD *count) +{ + DWORD *buf, *res; + DWORD i, cnt, rescnt = 0; + *count = 0; + res = NULL; + + toupperstr(wpat); + + if(srch_str == NULL) { + srch_str = (char*)malloc(1); + srch_str_len = 1; + } + srch_str[0] = 0; + + do { + i = 0; + while(wpat[i] != 0 && symtbl[(unsigned char)wpat[i]] == 1) i++; + if(i >= SEARCHER_MIN_WORD) { + char x = wpat[i]; + wpat[i] = 0; + if(srch_str_len <= (strlen(srch_str) + strlen(wpat) + 10)) { + srch_str = (char*)realloc(srch_str, (strlen(srch_str) + strlen(wpat) + 10)); + srch_str_len = (DWORD)strlen(srch_str) + strlen(wpat) + 10; + /* first search ? */ + if(res != NULL) { + strcat(srch_str, " & "); + } + else strcat(srch_str, " "); + strcat(srch_str, wpat); + } + buf = SearchMessagesByWord(wpat, &cnt); + wpat[i] = x; + if(errnum == SEARCHER_RETURN_ALLOK && buf == NULL) + errnum = SEARCHER_RETURN_WORD_NOT_FOUND; + switch(errnum) { + + case SEARCHER_RETURN_WORD_NOT_FOUND: + if(res != NULL) free(res); + res = NULL; + *count = 0; + goto Finishing; + + case SEARCHER_RETURN_ALLOK: + mqsort(buf, cnt); + if(res != NULL) { + DWORD *buf1; + rescnt = join_sorted(res, rescnt, buf, cnt, &buf1); + free(buf); + free(res); + res = buf1; + } + else { + res = buf; + rescnt = cnt; + } + break; + + default: + errnum = SEARCHER_RETURN_DB_ERROR; + return NULL; + } + } + if(wpat[i] != 0) wpat += i + 1; + else wpat += i; + } while(*wpat != 0); + *count = rescnt; + +Finishing: + srch_str_len = (DWORD)strlen(srch_str) + 1; + srch_str = (char*)realloc(srch_str, strlen(srch_str) + 1); + errnum = SEARCHER_RETURN_ALLOK; + return res; +} blob - /dev/null blob + cb9d56e9a638dbaaa81dd61b8261e39da13d9c6e (mode 644) --- /dev/null +++ src/searcher.h @@ -0,0 +1,68 @@ +/*************************************************************************** + searcher.h - message search support + ------------------- + begin : Wed Mar 14 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef SEARCHER_H_INCLUDED +#define SEARCHER_H_INCLUDED + +#include "basetypes.h" +#include "indexer.h" + +#define SEARCHER_INDEX_CREATE_NEW INDEXFILE_CREATE_NEW +#define SEARCHER_INDEX_CREATE_EXISTING INDEXFILE_CREATE_EXISTING +#define SEARCHER_SYMBOLS_TABLE "QWERTYUIOPASDFGHJKLZXCVBNMÉÖÓÊÅÍÃØÙÇÕÚÔÛÂÀÏÐÎËÄÆÝß×ÑÌÈÒÜÁÞ¨1234567890_&@!" +#define SEARCHER_MAX_CHARACTER_CODE 256 +#define SEARCHER_INDEX_LENGTH 256 +#define SEARCHER_MIN_WORD 3 + +/* searcher function error codes */ +#define SEARCHER_RETURN_ALLOK 0 +#define SEARCHER_RETURN_ALREADY_EXIST 1 +#define SEARCHER_RETURN_DB_ERROR 2 +#define SEARCHER_RETURN_INVALID_WORD 3 +#define SEARCHER_RETURN_WORD_TOO_SHORT 4 +#define SEARCHER_RETURN_UNKNOWN_ERROR 5 +#define SEARCHER_RETURN_WORD_NOT_FOUND 6 + +#define SEARCHER_NEW_CLUSTER_BLOCK_SIZE 25 +#define SEARCHER_MAX_CONTIGIOUS_CLUSTERS 20 + +/* search cluster block header */ +struct SSearcherHStruct { + DWORD prev; // if no prev 0xFFFFFFFF + DWORD used; + DWORD count; +}; + +/* message searcher class */ +class CMessageSearcher +{ +protected: + int init; + WCFILE *f; + int GetAllSubstrings(char *s, char **res); +public: + + DWORD errnum, indexed_word_count; + CIndexFile *SI; + char *symtbl; + char *srch_str; + DWORD srch_str_len; + CMessageSearcher(DWORD flags); + ~CMessageSearcher(); + + //int insertwordtoindex(char *word, dword mid); + int InsertWordWithSubwordsToIndex(char *word, DWORD mid); + int InsertMessageToIndex(char *body, DWORD mid); + DWORD* SearchMessagesByWord(char *wmask, DWORD *count); + DWORD* SearchMessagesByPattern(char *wpat, DWORD *count); + + DWORD AddMessageToRefBlock(DWORD bi =INDEXFILE_NO_INDEX); + DWORD AddingMId; +}; + +#endif blob - /dev/null blob + 5f748c6328947dcc7c4b28d80b913c495174a4ff (mode 644) --- /dev/null +++ src/security.cpp @@ -0,0 +1,410 @@ +/*************************************************************************** + security.cpp - antispam&SSL and other secur. + ------------------- + begin : Tue Apr 3 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "security.h" +#include "error.h" +#include "messages.h" + +/* find out is IP and Msg in buf + * also find latest date of record in list + * if ip found it returns index of it in buf, otherwise -1 returned + */ +int CheckForIpAndMsgInQueue(DWORD ip, DWORD Msg, SReadQueue *buf, int n, int &Alatest) +{ + Alatest = 0; // Max time + + for(int i = 0; i < n; i++) + { + // also find latest date + if(buf[Alatest].Date > buf[i].Date) Alatest = i; + + if(buf[i].IP == ip && buf[i].MsgIndex == Msg) + { + return i; + } + } + + return -1; +} + +/* */ +int CheckReadValidity(DWORD IP, DWORD MsgIndex) +{ + WCFILE *f; + SReadQueue buf[READQUEUE_LENGTH + 1]; + time_t t = time(NULL); + int x, Alatest; + + if((f = wcfopen(F_ANTISPAM, FILE_ACCESS_MODES_RW)) == NULL) + { + if((f = wcfopen(F_ANTISPAM, FILE_ACCESS_MODES_CW)) != NULL) + { + // create and save post list + + lock_file(f); + + SSpamQueue *mbuf = (SSpamQueue*)malloc(SPAMQUEUE_LENGTH*sizeof(SSpamQueue) + 1); + memset(mbuf, 0, sizeof(SSpamQueue)*SPAMQUEUE_LENGTH); + + if(!fCheckedWrite(mbuf, SPAMQUEUE_LENGTH*sizeof(SSpamQueue), f)) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + free(mbuf); + + // create and save read list + + memset(buf, 0, sizeof(SReadQueue)*READQUEUE_LENGTH); + + if(!fCheckedWrite(buf, READQUEUE_LENGTH*sizeof(SReadQueue), f)) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + + unlock_file(f); + + wcfclose(f); + + if((f = wcfopen(F_ANTISPAM, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + } + else printhtmlerror(); + } + + lock_file(f); + + if(wcfseek(f, READQUEUE_PREFIX, SEEK_SET) != 0) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + + if(!fCheckedRead(buf, READQUEUE_LENGTH*sizeof(SReadQueue), f)) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + + if((x = CheckForIpAndMsgInQueue(IP, MsgIndex, buf, READQUEUE_LENGTH, Alatest)) != -1) + { + unlock_file(f); + wcfclose(f); + // return status = READ INVALID + return 0; + } + + // update: delete entry with most early date + // and set our client information + buf[Alatest].IP = IP; + buf[Alatest].Date = t; + buf[Alatest].MsgIndex = MsgIndex; + + if(wcfseek(f, READQUEUE_PREFIX, SEEK_SET) != 0) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + if(!fCheckedWrite(buf, READQUEUE_LENGTH*sizeof(SReadQueue), f)) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + unlock_file(f); + wcfclose(f); + // return status - READ VALID + return 1; +} + +/* find out is IP in buf + * if ip found it returns index of it in buf, otherwise -1 returned + */ +int CheckForIpInQueue(DWORD ip, SSpamQueue *buf, int n, int &Alatest) +{ + Alatest = 0; // Max time + + for(int i = 0; i < n; i++) + { + // also find latest date + if(buf[Alatest].Date > buf[i].Date) Alatest = i; + + if(buf[i].IP == ip) + { + return i; + } + } + + return -1; +} + + +int MarkPostfromIPInvalid(DWORD IP, int TimeInterval) +{ + int Alatest; + WCFILE *f; + time_t t = time(NULL); + SSpamQueue buf[SPAMQUEUE_LENGTH + 1]; + + if((f = wcfopen(F_ANTISPAM, FILE_ACCESS_MODES_RW)) == NULL) + printhtmlerror(); + + lock_file(f); + + if(!fCheckedRead(buf, SPAMQUEUE_LENGTH*sizeof(SSpamQueue), f)) + printhtmlerror(); + + Alatest = 0; // Max time + + for(int i = 0; i < SPAMQUEUE_LENGTH; i++) + { + // find earliest date + if(buf[Alatest].Date > buf[i].Date) Alatest = i; + } + + // update: delete entry with most early date + buf[Alatest].IP = IP; + buf[Alatest].Date = t; + + if(wcfseek(f, 0, SEEK_SET) != 0) + printhtmlerror(); + if(!fCheckedWrite(buf, SPAMQUEUE_LENGTH*sizeof(SSpamQueue), f)) + printhtmlerror(); + + unlock_file(f); + wcfclose(f); + + return 0; +} + +/* check if it valid enter of user with IP + * return 1 if valid, 0 otherwise + */ +int CheckPostfromIPValidity(DWORD IP, int TimeInterval) +{ + WCFILE *f; + SSpamQueue buf[SPAMQUEUE_LENGTH + 1]; + time_t t = time(NULL); + int x, Alatest; + + if((f = wcfopen(F_ANTISPAM, FILE_ACCESS_MODES_RW)) == NULL) + { + if((f = wcfopen(F_ANTISPAM, FILE_ACCESS_MODES_CW)) != NULL) + { + // create and save post list + + lock_file(f); + + memset(buf, 0, sizeof(SSpamQueue)*SPAMQUEUE_LENGTH); + + if(!fCheckedWrite(buf, SPAMQUEUE_LENGTH*sizeof(SSpamQueue), f)) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + + // create and save read list + + SReadQueue *mbuf = (SReadQueue*)malloc(READQUEUE_LENGTH*sizeof(SReadQueue) + 1); + memset(mbuf, 0, sizeof(SReadQueue)*READQUEUE_LENGTH); + + if(!fCheckedWrite(mbuf, READQUEUE_LENGTH*sizeof(SReadQueue), f)) { + unlock_file(f); + wcfclose(f); + printhtmlerror(); + } + free(mbuf); + + unlock_file(f); + + wcfclose(f); + + return 1; + } + else printhtmlerror(); + } + + lock_file(f); + + if(!fCheckedRead(buf, SPAMQUEUE_LENGTH*sizeof(SSpamQueue), f)) + printhtmlerror(); + + unlock_file(f); + wcfclose(f); + + if((x = CheckForIpInQueue(IP, buf, SPAMQUEUE_LENGTH, Alatest)) != -1) + { + if(buf[x].Date + TimeInterval > t && buf[x].Date < t ) + { + // return status - POST INVALID + return 0; + } + } + + // return status - POST VALID + return 1; +} + +// This code makes available Marsaglia's highly portable generator +// of uniformly distributed pseudo-random numbers. +// +// The sequence of 24 bit pseudo-random numbers produced has a period +// of about 2**144, and has passed stringent statistical tests for +// randomness and independence. +// +// Supplying a seed or seeds to init_rand(s1, s2) is optional. +// +// The correspondence between pairs of seeds and generated sequences +// of pseudo-random numbers is many-to-one. +// +// References: +// M G Harmon & T P Baker, ``An Ada Implementation of Marsaglia's +// "Universal" Random Number Generator'', Ada Letters, late 1987. +// +// G Marsaglia, ``Toward a universal random number generator'', +// to appear in the Journal of the American Statistical Association. + +// output values are in the range 0..2^(24)-1 + +static const unsigned long two_to_24 = 0x01000000; +static const unsigned short state_size = 97; + +static const unsigned short p = 179; +static const unsigned short pm1 = p - 1; +static const unsigned short q = p - 10; + +static const unsigned long init_c = 362436; +static const unsigned long cd = 7654321; +static const unsigned long cm = 16777213; + +// The state of the generator is described by the following +// variables + +static unsigned short index_i; // [0..state_size-1] +static unsigned short index_j; // [0..state_size-1] +static unsigned long u[state_size]; // the state array +static unsigned long c; +static bool init_done = false; + +// This procedure initialises the state table u for a lagged +// Fibonacci sequence generator, filling it with random bits +// from a small multiplicative congruential sequence. The +// auxilliaries c, index_i and index_j are also initialized. +// The seeds are transformed into an initial state in such a +// way that identical results are obtained on a wide variety +// of machines. + + // Return a value between 0 and size-1 inclusive. This value + // will be anyint itself if possible, otherwise another value + // in the required interval. + +static unsigned short col(short anyint, unsigned short size) +{ + short i = anyint; + if(i < 0) i = - (i / 2); + while (i >= size) i = i / 2; + return i; +} + +void init_rand(unsigned short seed_a, unsigned short seed_b) +{ + DWORD s,bit; + WORD ii,jj,kk,mm; // [0..p-1] + WORD ll; // [0..q-1] + short sd; + + sd = col(seed_a, pm1 * pm1); + ii = 1 + sd / pm1; jj = 1 + sd % pm1; + + sd = col(seed_b, pm1 * q); + kk = 1 + sd / pm1; ll = sd % q; + + if (ii == 1 && jj == 1 && kk == 1) + ii = 2; + + for(short ind = 0; ind < state_size; ind++) + { + s = 0; bit = 1; + + do + { + mm = (((ii * jj) % p) * kk) % p; + + ii = jj; jj = kk; kk = mm; + + ll = (53 * ll + 1) % q; + + if ((ll * mm) & 0x0020) + s += bit; + + bit <<= 1; + } while(bit < two_to_24); + + u [ind] = s; + } + + index_i = state_size - 1; index_j = state_size / 3; c = init_c; + + init_done = true; +} + +// Return uniformly distributed pseudo random numbers in the range +// 0..2^(24)-1 inclusive. There are 2^24 possible return values. + +static DWORD rand24(void) +{ + DWORD temp; + + if(!init_done) + { + temp = (DWORD)time(NULL); + init_rand((WORD)(temp >> 16), (WORD)temp); + } + + c = (c < cd ? c + (cm - cd) : c - cd); + + temp = (u[index_i] -= u[index_j]); + + if(!index_i--) + index_i = state_size - 1; + + if(!index_j--) + index_j = state_size - 1; + + return (temp - c) & (two_to_24 - 1); +} + +// Return uniformly distributed pseudo random number in the range +// 0..2^(32)-1 inclusive. There are 2^32 possible return values. + +static BYTE buf[13]; // buffer for conversion from 24 to + // 32 bit output +static unsigned short bno = 0; // number of output values in buffer + +DWORD rand32(void) +{ + if(!bno) + { + for(unsigned short i = 0; i < 12; i += 3) + *(DWORD*)(buf + i) = rand24(); + bno = 12; + } + bno -= 4; + return *(DWORD*)(buf + 8 - bno); +} + +void MakeSHA(char *origstring, char *shastring) +{ +// e CSHA1 sha1; +// e sha1.Reset(); +// e sha1.Update((UINT_8 *)origstring, strlen(origstring)); +// e sha1.Final(); +// e sha1.GetHash((UINT_8 *)shastring); +} + blob - /dev/null blob + 12562b3429d2c03692027f011f57ecbbb6229b44 (mode 644) --- /dev/null +++ src/security.h @@ -0,0 +1,50 @@ +/*************************************************************************** + security.h - description + ------------------- + begin : Tue Apr 3 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef SECURITY_H_INCLUDED +#define SECURITY_H_INCLUDED + +#include "basetypes.h" +#include "sha1.h" + +// antispam codes +#define POST_MSG 1 +#define REFRESH_INDEX 2 +#define READ_MSG 3 + +#define SPAMQUEUE_PREFIX 0 +#define SPAMQUEUE_LENGTH 60 + +#define READQUEUE_PREFIX 60*sizeof(SSpamQueue) +#define READQUEUE_LENGTH 60 + +struct SSpamQueue +{ + DWORD IP; // ip address + time_t Date; // date +}; + +struct SReadQueue +{ + time_t Date; // date + DWORD IP; // IP-address + DWORD MsgIndex; // message index +}; + +int MarkPostfromIPInvalid(DWORD IP, int TimeInterval); +int CheckPostfromIPValidity(DWORD IP, int TimeInterval); + +int CheckReadValidity(DWORD IP, DWORD MsgIndex); + +unsigned long rand32(void); + +void init_rand(unsigned short seed_a = 1991, unsigned short seed_b = 9880); + +void MakeSHA(char *origstring, char *shastring); + +#endif blob - /dev/null blob + 0352a759289e9e8697811a7c9e43471315b7bc37 (mode 644) --- /dev/null +++ src/sendmail.cpp @@ -0,0 +1,279 @@ +/*************************************************************************** + sendmail.cpp - mail sending support + ------------------- + begin : Mon Nov 11 2002 + copyright : (C) 2002 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "sendmail.h" +#include "messages.h" +#include "error.h" + + +static unsigned char dtable[512]; + +void buffer_new(struct buffer_st *b) +{ + b->length = 512; + b->data = (char *)malloc(sizeof(char)*(b->length)); + b->data[0] = 0; + b->ptr = b->data; + b->offset = 0; +} + +void buffer_add(struct buffer_st *b, char c) +{ + *(b->ptr++) = c; + b->offset++; + if (b->offset == b->length) { + b->length += 512; + b->data = (char *)realloc(b->data, b->length); + b->ptr = b->data + b->offset; + } +} + +void buffer_end(struct buffer_st *b) +{ + b->data[b->offset++]= 0; + //b->data = (char *)realloc(b->data, b->offset++); + +} + +void buffer_delete(struct buffer_st *b) +{ + free(b->data); + b->length = 0; + b->offset = 0; + b->ptr = NULL; + b->data = NULL; +} + + + + +void base64_encode(struct buffer_st *b, const char *source, int length) +{ + int i, hiteof = 0; + int offset = 0; + int olen; + + olen = 0; + + buffer_new(b); + + /* Fill dtable with character encodings. */ + + for (i = 0; i < 26; i++) { + dtable[i] = 'A' + i; + dtable[26 + i] = 'a' + i; + } + for (i = 0; i < 10; i++) { + dtable[52 + i] = '0' + i; + } + dtable[62] = '+'; + dtable[63] = '/'; + + while (!hiteof) { + unsigned char igroup[3], ogroup[4]; + int c, n; + + igroup[0] = igroup[1] = igroup[2] = 0; + for (n = 0; n < 3; n++) { + c = *(source++); + offset++; + if (offset > length) { + hiteof = 1; + break; + } + igroup[n] = (unsigned char) c; + } + if (n > 0) { + ogroup[0] = dtable[igroup[0] >> 2]; + ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; + ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; + ogroup[3] = dtable[igroup[2] & 0x3F]; + + /* Replace characters in output stream with "=" pad + characters if fewer than three characters were + read from the end of the input stream. */ + + if (n < 3) { + ogroup[3] = '='; + if (n < 2) { + ogroup[2] = '='; + } + } + for (i = 0; i < 4; i++) { + buffer_add(b, ogroup[i]); + //if (!(b->offset % 72)) { + // buffer_add(b, '\r'); + // buffer_add(b, '\n'); + //} + } + } + } + //buffer_add(b, '\r'); + //buffer_add(b, '\n'); + buffer_end(b); +} + + + +#if MA_TYPE == 1 + +/* Store the address of HOSTNAME, internet-style, to WHERE. First + check for it in the host list, and (if not found), use + ngethostbyname to get it. + Return 1 on successful finding of the hostname, 0 otherwise. */ +int store_hostaddress(unsigned char *where, const char *hostname) +{ + unsigned long addr; + struct hostent *hptr; + struct in_addr in; + + /* If the address is of the form d.d.d.d, there will be no trouble + with it. */ + addr = (unsigned long)inet_addr(hostname); + /* If we have the numeric address, just store it. */ + if((int)addr != -1) + { + /* This works on both little and big endian architecture, as + inet_addr returns the address in the proper order. It + appears to work on 64-bit machines too. */ + memcpy (where, &addr, 4); + return 1; + } + /* Since all else has failed, let's try gethostbyname(). Note that + we use gethostbyname() rather than ngethostbyname(), because we + *know* the address is not numerical. */ + hptr = gethostbyname (hostname); + if (!hptr) + return 0; + /* Copy the address of the host to socket description. */ + memcpy(where, hptr->h_addr_list[0], hptr->h_length); + /* Now that we're here, we could as well cache the hostname for + future use, as in realhost(). First, we have to look for it by + address to know if it's already in the cache by another name. */ + + /* Originally, we copied to in.s_addr, but it appears to be missing + on some systems. */ + memcpy(&in, *hptr->h_addr_list, sizeof (in)); + return 1; +} + +/* Create an internet connection to HOSTNAME on PORT. The created + socket will be stored to *SOCK. */ +int make_connection(int *sock, char *hostname, unsigned short port) +{ + struct sockaddr_in sock_name; + /* struct hostent *hptr; */ + + /* Get internet address of the host. We can do it either by calling + ngethostbyname, or by calling store_hostaddress, from host.c. + storehostaddress is better since it caches calls to + gethostbyname. */ + +#if 1 + if(!store_hostaddress ((unsigned char *)&sock_name.sin_addr, hostname)) + return 0; +#else /* never */ + if(!(hptr = ngethostbyname (hostname))) + return 0; + // Copy the address of the host to socket description. + memcpy(&sock_name.sin_addr, hptr->h_addr, hptr->h_length); +#endif /* never */ + + /* Set port and protocol */ + sock_name.sin_family = AF_INET; + sock_name.sin_port = htons (port); + + /* Make an internet socket, stream type. */ + if ((*sock = socket (AF_INET, SOCK_STREAM, 0)) == -1) + return 0; + + /* Connect the socket to the remote host. */ + if(connect(*sock, (struct sockaddr *) &sock_name, sizeof (sock_name))) + { + return 0; + } + + struct timeval tv; + tv.tv_sec = 3; + tv.tv_usec = 0; + + if(setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(timeval)) == -1) + return 0; + if(setsockopt(*sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(timeval)) == -1) + return 0; + + return 1; +} + + + + +int wcSendMail(char *to, char *subj, char *body) +{ + int ssock; + int rc; + char sbuf[100000]; + char rbuf[10000]; + + if(!make_connection(&ssock, MA_SENDER, 25)) + return 0; + sprintf(sbuf, MAIL_SEND_HELO, MA_FROM, to); + + if(send(ssock, sbuf, strlen(sbuf), 0) != (int)strlen(sbuf)) + return 0; + +#ifdef WIN32 + Sleep(500); +#else //ifdef WIN32 + sleep(1); +#endif //ifdef WIN32 + rc = recv(ssock, rbuf, 9999, 0); + + + buffer_st subj_base64; + base64_encode(&subj_base64, subj ,strlen(subj) ); + + //print2log("body %s to %s", body, to); + sprintf(sbuf, MAIL_SEND_DATA, MA_FROM, to, subj_base64.data, body); + + + buffer_delete(&subj_base64); + + if(send(ssock, sbuf, strlen(sbuf), 0) != (int)strlen(sbuf)) + return 0; + rc = recv(ssock, rbuf, 9999, 0); + +#ifdef WIN32 + Sleep(500); +#else //ifdef WIN32 + sleep(1); +#endif //ifdef WIN32 + shutdown(ssock, 2); + return 1; +} + +#else + +int wcSendMail(char *to, char *subj, char *body) +{ + + struct buffer_st subj_base64; + base64_encode(&subj_base64, subj, strlen(subj)); + + FILE* MA_SEND; + MA_SEND=popen(MA_SENDER, FILE_ACCESS_MODES_RW); + fprintf(MA_SEND, MAIL_SEND_DATA, MA_FROM, to, subj_base64.data, body); + pclose(MA_SEND); + + buffer_delete(&subj_base64); + + return 1; +} + + +#endif blob - /dev/null blob + edd55e6503c7bb925d30ee64838a778f88529c68 (mode 644) --- /dev/null +++ src/sendmail.h @@ -0,0 +1,36 @@ +/*************************************************************************** + sendmail.h - mail sending support include + ------------------- + begin : Wed Jun 13 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef SENDMAIL_H_INCLUDED +#define SENDMAIL_H_INCLUDED + +#include "basetypes.h" +#include "messages.h" +// from base64.h + +#define MAIL_SEND_HELO "HELO localhost\r\nMAIL FROM: <%s>\r\nRCPT TO: <%s>\r\nDATA\r\n" +#define MAIL_SEND_DATA "From: <%s>\r\nTo: <%s>\r\nSubject:=?Windows-1251?B?%s?=\r\n"\ + MAILACKN_HEADER "%s" MAIL_SEND_SIGNING "\r\n.\r\nQuit\r\n" + +int wcSendMail(char *to, char *subj, char *body); + +struct buffer_st { + char *data; + int length; + char *ptr; + int offset; +}; + +void buffer_new(struct buffer_st *b); +void buffer_add(struct buffer_st *b, char c); +void buffer_delete(struct buffer_st *b); + +void base64_encode(struct buffer_st *b, const char *source, int length); + + +#endif blob - /dev/null blob + 76028761b3184581b794a2a9f08a546c10b7539e (mode 644) --- /dev/null +++ src/sha1.cpp @@ -0,0 +1,281 @@ +/* + 100% free public domain implementation of the SHA-1 algorithm + by Dominik Reichl + Web: http://www.dominik-reichl.de/ + + Version 1.6 - 2005-02-07 (thanks to Howard Kapustein for patches) + - You can set the endianness in your files, no need to modify the + header file of the CSHA1 class any more + - Aligned data support + - Made support/compilation of the utility functions (ReportHash + and HashFile) optional (useful, if bytes count, for example in + embedded environments) + + Version 1.5 - 2005-01-01 + - 64-bit compiler compatibility added + - Made variable wiping optional (define SHA1_WIPE_VARIABLES) + - Removed unnecessary variable initializations + - ROL32 improvement for the Microsoft compiler (using _rotl) + + ======== Test Vectors (from FIPS PUB 180-1) ======== + + SHA1("abc") = + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + + SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + + SHA1(A million repetitions of "a") = + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +#include "sha1.h" + +#ifdef SHA1_UTILITY_FUNCTIONS +#define SHA1_MAX_FILE_BUFFER 8000 +#endif + +// Rotate x bits to the left +#ifndef ROL32 +#ifdef _MSC_VER +#define ROL32(_val32, _nBits) _rotl(_val32, _nBits) +#else +#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits)))) +#endif +#endif + +#ifdef SHA1_LITTLE_ENDIAN +#define SHABLK0(i) (m_block->l[i] = \ + (ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF)) +#else +#define SHABLK0(i) (m_block->l[i]) +#endif + +#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \ + ^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1)) + +// SHA-1 rounds +#define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } +#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } +#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); } +#define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); } +#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); } + +CSHA1::CSHA1() +{ + m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace; + Reset(); +} + +CSHA1::~CSHA1() +{ + Reset(); +} + +void CSHA1::Reset() +{ + // SHA1 initialization constants + m_state[0] = 0x67452301; + m_state[1] = 0xEFCDAB89; + m_state[2] = 0x98BADCFE; + m_state[3] = 0x10325476; + m_state[4] = 0xC3D2E1F0; + + m_count[0] = 0; + m_count[1] = 0; +} + +void CSHA1::Transform(UINT_32 *state, UINT_8 *buffer) +{ + // Copy state[] to working vars + UINT_32 a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; + + memcpy(m_block, buffer, 64); + + // 4 rounds of 20 operations each. Loop unrolled. + _R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3); + _R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7); + _R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11); + _R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15); + _R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19); + _R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23); + _R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27); + _R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31); + _R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35); + _R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39); + _R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43); + _R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47); + _R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51); + _R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55); + _R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59); + _R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63); + _R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67); + _R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71); + _R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75); + _R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79); + + // Add the working vars back into state + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + // Wipe variables +#ifdef SHA1_WIPE_VARIABLES + a = b = c = d = e = 0; +#endif +} + +// Use this function to hash in binary data and strings +void CSHA1::Update(UINT_8 *data, UINT_32 len) +{ + UINT_32 i, j; + + j = (m_count[0] >> 3) & 63; + + if((m_count[0] += len << 3) < (len << 3)) m_count[1]++; + + m_count[1] += (len >> 29); + + if((j + len) > 63) + { + i = 64 - j; + memcpy(&m_buffer[j], data, i); + Transform(m_state, m_buffer); + + for( ; i + 63 < len; i += 64) Transform(m_state, &data[i]); + + j = 0; + } + else i = 0; + + memcpy(&m_buffer[j], &data[i], len - i); +} + +#ifdef SHA1_UTILITY_FUNCTIONS +// Hash in file contents +bool CSHA1::HashFile(char *szFileName) +{ + unsigned long ulFileSize, ulRest, ulBlocks; + unsigned long i; + UINT_8 uData[SHA1_MAX_FILE_BUFFER]; + FILE *fIn; + + if(szFileName == NULL) return false; + + fIn = fopen(szFileName, "rb"); + if(fIn == NULL) return false; + + fseek(fIn, 0, SEEK_END); + ulFileSize = (unsigned long)ftell(fIn); + fseek(fIn, 0, SEEK_SET); + + if(ulFileSize != 0) + { + ulBlocks = ulFileSize / SHA1_MAX_FILE_BUFFER; + ulRest = ulFileSize % SHA1_MAX_FILE_BUFFER; + } + else + { + ulBlocks = 0; + ulRest = 0; + } + + for(i = 0; i < ulBlocks; i++) + { + fread(uData, 1, SHA1_MAX_FILE_BUFFER, fIn); + Update((UINT_8 *)uData, SHA1_MAX_FILE_BUFFER); + } + + if(ulRest != 0) + { + fread(uData, 1, ulRest, fIn); + Update((UINT_8 *)uData, ulRest); + } + + fclose(fIn); fIn = NULL; + return true; +} +#endif + +void CSHA1::Final() +{ + UINT_32 i; + UINT_8 finalcount[8]; + + for(i = 0; i < 8; i++) + finalcount[i] = (UINT_8)((m_count[((i >= 4) ? 0 : 1)] + >> ((3 - (i & 3)) * 8) ) & 255); // Endian independent + + Update((UINT_8 *)"\200", 1); + + while ((m_count[0] & 504) != 448) + Update((UINT_8 *)"\0", 1); + + Update(finalcount, 8); // Cause a SHA1Transform() + + for(i = 0; i < 20; i++) + { + m_digest[i] = (UINT_8)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255); + } + + // Wipe variables for security reasons +#ifdef SHA1_WIPE_VARIABLES + i = 0; + memset(m_buffer, 0, 64); + memset(m_state, 0, 20); + memset(m_count, 0, 8); + memset(finalcount, 0, 8); + Transform(m_state, m_buffer); +#endif +} + +#ifdef SHA1_UTILITY_FUNCTIONS +// Get the final hash as a pre-formatted string +void CSHA1::ReportHash(char *szReport, unsigned char uReportType) +{ + unsigned char i; + char szTemp[16]; + + if(szReport == NULL) return; + + if(uReportType == REPORT_HEX) + { + sprintf(szTemp, "%02X", m_digest[0]); + strcat(szReport, szTemp); + + for(i = 1; i < 20; i++) + { + sprintf(szTemp, " %02X", m_digest[i]); + strcat(szReport, szTemp); + } + } + else if(uReportType == REPORT_DIGIT) + { + sprintf(szTemp, "%u", m_digest[0]); + strcat(szReport, szTemp); + + for(i = 1; i < 20; i++) + { + sprintf(szTemp, " %u", m_digest[i]); + strcat(szReport, szTemp); + } + } + else if(uReportType == REPORT_STRING) + { + for(i = 0; i < 20; i++) + { + sprintf(szTemp, "%c", m_digest[i]); + strcat(szReport, szTemp); + } + } + else strcpy(szReport, "Error: Unknown report type!"); +} +#endif + +// Get the raw message digest +void CSHA1::GetHash(UINT_8 *puDest) +{ + memcpy(puDest, m_digest, 20); +} blob - /dev/null blob + 8b26b0e2f9e28478b856257ee822e303ea3619b0 (mode 644) --- /dev/null +++ src/sha1.h @@ -0,0 +1,149 @@ +/* + 100% free public domain implementation of the SHA-1 algorithm + by Dominik Reichl + Web: http://www.dominik-reichl.de/ + + Version 1.6 - 2005-02-07 (thanks to Howard Kapustein for patches) + - You can set the endianness in your files, no need to modify the + header file of the CSHA1 class any more + - Aligned data support + - Made support/compilation of the utility functions (ReportHash + and HashFile) optional (useful, if bytes count, for example in + embedded environments) + + Version 1.5 - 2005-01-01 + - 64-bit compiler compatibility added + - Made variable wiping optional (define SHA1_WIPE_VARIABLES) + - Removed unnecessary variable initializations + - ROL32 improvement for the Microsoft compiler (using _rotl) + + ======== Test Vectors (from FIPS PUB 180-1) ======== + + SHA1("abc") = + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + + SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + + SHA1(A million repetitions of "a") = + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +#ifndef ___SHA1_HDR___ +#define ___SHA1_HDR___ + +#if !defined(SHA1_UTILITY_FUNCTIONS) && !defined(SHA1_NO_UTILITY_FUNCTIONS) +#define SHA1_UTILITY_FUNCTIONS +#endif + +#include // Needed for memset and memcpy + +#ifdef SHA1_UTILITY_FUNCTIONS +#include // Needed for file access and sprintf +#include // Needed for strcat and strcpy +#endif + +#ifdef _MSC_VER +#include +#endif + +// You can define the endian mode in your files, without modifying the SHA1 +// source files. Just #define SHA1_LITTLE_ENDIAN or #define SHA1_BIG_ENDIAN +// in your files, before including the SHA1.h header file. If you don't +// define anything, the class defaults to little endian. + +#if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN) +#define SHA1_LITTLE_ENDIAN +#endif + +// Same here. If you want variable wiping, #define SHA1_WIPE_VARIABLES, if +// not, #define SHA1_NO_WIPE_VARIABLES. If you don't define anything, it +// defaults to wiping. + +#if !defined(SHA1_WIPE_VARIABLES) && !defined(SHA1_NO_WIPE_VARIABLES) +#define SHA1_WIPE_VARIABLES +#endif + +///////////////////////////////////////////////////////////////////////////// +// Define 8- and 32-bit variables + +#ifndef UINT_32 + +#ifdef _MSC_VER + +#define UINT_8 unsigned __int8 +#define UINT_32 unsigned __int32 + +#else + +#define UINT_8 unsigned char + +#if (ULONG_MAX == 0xFFFFFFFF) +#define UINT_32 unsigned long +#else +#define UINT_32 unsigned int +#endif + +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// +// Declare SHA1 workspace + +typedef union +{ + UINT_8 c[64]; + UINT_32 l[16]; +} SHA1_WORKSPACE_BLOCK; + +class CSHA1 +{ +public: +#ifdef SHA1_UTILITY_FUNCTIONS + // Two different formats for ReportHash(...) + enum + { + REPORT_HEX = 0, + REPORT_DIGIT = 1, + REPORT_STRING = 2 + }; +#endif + + // Constructor and Destructor + CSHA1(); + ~CSHA1(); + + UINT_32 m_state[5]; + UINT_32 m_count[2]; + UINT_32 __reserved1[1]; + UINT_8 m_buffer[64]; + UINT_8 m_digest[20]; + UINT_32 __reserved2[3]; + + void Reset(); + + // Update the hash value + void Update(UINT_8 *data, UINT_32 len); +#ifdef SHA1_UTILITY_FUNCTIONS + bool HashFile(char *szFileName); +#endif + + // Finalize hash and report + void Final(); + + // Report functions: as pre-formatted and raw data +#ifdef SHA1_UTILITY_FUNCTIONS + void ReportHash(char *szReport, unsigned char uReportType = REPORT_HEX); +#endif + void GetHash(UINT_8 *puDest); + +private: + // Private SHA-1 transformation + void Transform(UINT_32 *state, UINT_8 *buffer); + + // Member variables + UINT_8 m_workspace[64]; + SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above +}; + +#endif blob - /dev/null blob + befcd21ebc13795dd2cce529e18e354baadbe969 (mode 644) --- /dev/null +++ src/speller.cpp @@ -0,0 +1,340 @@ +/*************************************************************************** + speller.cpp - spell, ban, html checker + ------------------- + begin : Mon Mar 19 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#include "basetypes.h" +#include "speller.h" +#include "error.h" +#include "messages.h" +#include "boardtags.h" + +#define TO_HEX(a) (a > 9 ? (a - 10) + 'A': a + '0') + +char* CodeHttpString(char *s, int allocmem) +{ + static char rs[SPELLER_INTERNAL_BUFFER_SIZE]; + char *r, *rr; + DWORD sl = (DWORD)strlen(s); + if(allocmem) { + rr = r = (char*)malloc(3*sl + 10); + } + else { + if(sl > SPELLER_INTERNAL_BUFFER_SIZE/3) return NULL; + r = (char*)(&rs); + rr = r; + } + for(; *s != 0; s++) { + if (*s >= 'A' && *s <='z') { + r[0] = *s; + r+=1; + } else { + r[0] = '%'; + r[1] = TO_HEX( (((*s) & 0x00000000F0) >> 4) ); + r[2] = TO_HEX( ( (*s) & 0x000000000F) ); + r+=3; + } + } + *r = 0; + return rr; +} + +int IsMailCorrect(char *s) +{ + char *s1; + if(s == NULL) return 0; + if((s1 = strchr(s,'@')) == NULL) return 0; + if(strlen(s1) < 4) return 0; + if((s = strchr(s1,'.')) == NULL) return 0; + if(strlen(s) < 2) return 0; + return 1; +} + +int FilterBadWords(char *s) +{ + FILE *f; + char dic[MAX_STRING]; + char *sx, *ss = (char*)malloc(strlen(s) + 1); + int c; + int x = 0; + strcpy(ss, s); + ss = toupperstr(ss); + if((f = fopen(F_BADWORDS, FILE_ACCESS_MODES_R)) != NULL) + { + while(!feof(f)) { + dic[0] = 0; + fscanf(f,"%[^\n\10]", dic); + + if(dic[0] != 0 && (dic[strlen(dic) - 1] == 13 || dic[strlen(dic) - 1] == 10)) + dic[strlen(dic) - 1] = 0; + + fscanf(f,"%c",&c); + toupperstr(dic); + while ((dic[0] != 0 ) && ((sx = strstr(ss, dic)) != NULL)) { + x = 1; + register DWORD tm = (DWORD)strlen(dic); + for(register DWORD j = 0; j < tm; j++) { + s[sx - ss + j] = BAD_WORD_SYMBOL; + sx[j] = BAD_WORD_SYMBOL; + } + } + } + } + else print2log(LOG_WARN_UNABLETOOPENFILE, F_BADWORDS); + free(ss); + if(x) return 1; + else return 0; +} + +// return filtered string with length not more than ml bytes (include '\0') +char* FilterHTMLTags(char *s, WORD ml, int allocmem) +{ + char *os, *st; + static char *tb[SPELLER_INTERNAL_BUFFER_SIZE]; + + while(*s == '\n') s++; + + int h = 0, k = 0; + for(k = (int)strlen(s)-1; s[k]=='\n'; k--) h++; + k = (int)strlen(s); + s[k - h] = '\0'; + if(allocmem) + st = (char*)malloc(4*k + 1); + else { + st = (char*)(&tb); + } + os = st; + while(*s != '\0' && st - os < ml) { + if(*s == '<') { + strcpy(st, "<"); + st+= 3; + } + else if(*s == '>') { + strcpy(st, ">"); + st+= 3; + } + else if(*s == '"') { + strcpy(st, """); + st+= 5; + } + else if(*s == '&') { + strcpy(st, "&"); + st+= 4; + } + else *st = *s; + s++; + st++; + } + if(st - os > ml) st-=4; // if it was overflow because of '<' or '>' + *st = '\0'; + if(allocmem) os = (char *)realloc(os, strlen(os) +1); + return os; +} + +// removing all white spaces from beginning and end of string +char* FilterWhitespaces(char *s) +{ + while(isspace(((*s) & 0xff))) s++; + int h = 0, k = 0; + for(k = (int)strlen(s)-1; isspace((s[k] & 0xff)); k--) h++; + s[strlen(s) - h] = '\0'; + return s; +} + +// check if IP in mask +// return 1 if successfull, 0 otherwise +int CheckIPinSubnet(char *IP, char *mask) +{ + register DWORD i = 0, sl = (DWORD)strlen(mask); + if(sl == 0) return 1; + while(strlen(IP) > i && sl > i && IP[i] == mask[i]) { + i++; + } + if(sl == i && (mask[i - 1] == '.' || strlen(IP) == i)) return 1; + return 0; +} + +void FilterMessageForPreview(char *s, char **dd) +{ + char *d; + if(!s) { + *dd = NULL; + return; + } + d = *dd = (char*)malloc(strlen(s) + 1); + while(*s != 0) { + if(*s != 10) { + *d = *s; + d++; + } + s++; + } + *d = *s; + *dd = (char*)realloc(*dd, d - (*dd) + 2); +} + +int PrepareTextForPrint(char *msg, char **res, BYTE security, int flags, int spfl) +{ + DWORD tmp; + char *st; + int memalloc = 0; + + *res = NULL; + + if((SPELLER_FILTER_HTML & spfl) != 0) { + // if the message to small try to use internal buffers + if(strlen(msg) < SPELLER_INTERNAL_BUFFER_SIZE/2) { + st = FilterHTMLTags(msg, SPELLER_INTERNAL_BUFFER_SIZE - 10, 0); // do not allocate memory + } + else { + st = FilterHTMLTags(msg, MAX_PARAMETERS_STRING); + memalloc = 1; + } + } + if(!st) return 0; + + if((SPELLER_PARSE_TAGS & spfl) != 0) { + if(FilterBoardTags(st, res, security, MAX_PARAMETERS_STRING, flags, &tmp) == 0) + { + if(!memalloc) { + *res = (char*)malloc(strlen(st) + 1); + if(!(*res)) return 0; + strcpy(*res, st); + } + else *res = st; + } + else { + if(memalloc) free(st); + } + } + else { + if(!memalloc) { + *res = (char*)malloc(strlen(st) + 1); + if(!(*res)) return 0; + strcpy(*res, st); + } + else *res = st; + } + + return 1; +} + +int CheckSpellingBan(struct SMessage *mes, char **body, char **Reason, + DWORD CFlags, DWORD *RetFlags, bool fRegged) +{ + FILE *f; + char ip[MAX_STRING]; + char *reason = NULL; + char c, t; + + char *st; + DWORD flg = 0; + if(FilterBoardTags(mes->MessageHeader, &st, mes->Security, MESSAGE_HEADER_LENGTH, BOARDTAGS_TAG_PREPARSE, RetFlags) == 0) { + return MSG_CHK_ERROR_NOMSGHEADER; + } + else { + strcpy(mes->MessageHeader, st); + free(st); + } + + if(strlen(mes->MessageHeader) == 0 || strcmp(mes->MessageHeader, " ") == 0) return MSG_CHK_ERROR_NOMSGHEADER; + +#if MSG_REQURED_BODY + if(strlen(body) == 0) return MSG_CHK_ERROR_NOMSGBODY; +#endif + + // banned check + restriction check +#if BANNED_CHECK + + reason = (char*)malloc(MAX_STRING); + if((f = fopen(F_BANNEDIP, FILE_ACCESS_MODES_R)) != NULL) { + while(!feof(f)) { + bool fProxy = false; + ip[0] = 0; + fscanf(f, "%[^ \n]", &ip); // get ip + if(feof(f)) break; + fscanf(f, "%c", &c); // skip " " + if(c == '\n') continue; + fscanf(f, "%c", &t); // type + fscanf(f, "%c", &c); // skip " " + fscanf(f, "%[^\n]", reason); // ban reason + fscanf(f, "%c", &c); // skip \n + if(CheckIPinSubnet(Cip, ip) && + (t == '*' || (fProxy = ((t|0x20) == 'p' && !fRegged)))) + { + if(fProxy) + strncat(reason, "[PROXY]", MAX_STRING - 1); + *Reason = reason; + return MSG_CHK_ERROR_BANNED; + } + if(CheckIPinSubnet(Cip, ip) && t == '=') { + break; + } + } + fclose(f); + } + else print2log(LOG_WARN_UNABLETOOPENFILE, F_BANNEDIP); + free(reason); +#endif + + /* HTML Filtering and WWWConf Tags parsing option */ + + /* filter HTML in Headers */ + if((CFlags & MSG_CHK_ALLOW_HTML) == 0) { + // HTML tags check and filtering (%lt, %gt) + char *st; + st = FilterHTMLTags(mes->MessageHeader, MESSAGE_HEADER_LENGTH - 1); + st = FilterWhitespaces(st); + strcpy(mes->MessageHeader, st); + free(st); + st = FilterHTMLTags(mes->AuthorName, AUTHOR_NAME_LENGTH - 1); + strcpy(mes->AuthorName, st); + free(st); + } + + /* filter HTML in Body */ + if((CFlags & MSG_CHK_ALLOW_HTML) == 0) { + if(*body != NULL) { + char *st = FilterHTMLTags(*body, MAX_PARAMETERS_STRING - 1); + free(*body); + *body = st; + } + } + +#if SPELLING_CHECK == 1 + // spelling check + // if disallowed word was found in header we should boiling out + if(FilterBadWords(mes->MessageHeader)) return MSG_CHK_ERROR_BADSPELLING; + if(FilterBadWords(mes->AuthorName)) return MSG_CHK_ERROR_BADSPELLING; + // we should only replace with '#' all bad words in body + FilterBadWords(*body); +#endif + + /* parse WWWConf Tags and smiles */ + + /* set flags for body */ + flg = MESSAGE_ENABLED_SMILES | MESSAGE_ENABLED_TAGS; + + if(CFlags & MSG_CHK_DISABLE_SMILE_CODES) { + flg = flg & (~MESSAGE_ENABLED_SMILES); + } + if(CFlags & MSG_CHK_DISABLE_WWWCONF_TAGS) { + flg = flg & (~MESSAGE_ENABLED_TAGS); + } + + /* parse body */ + if(FilterBoardTags(*body, &st, mes->Security, MAX_PARAMETERS_STRING, flg | BOARDTAGS_TAG_PREPARSE, RetFlags) == 0) { + /* if to long - ignore tags */ + *RetFlags = 0; + } + else { + free(*body); + if(strcmp(st, " ") == 0) *st = 0; + *body = st; + } + + return MSG_CHK_ERROR_PASSED; +} blob - /dev/null blob + 23db09b813995a9e90cfb29fa65d01d9efd34b57 (mode 644) --- /dev/null +++ src/speller.h @@ -0,0 +1,75 @@ +/*************************************************************************** + speller.h - spelling, ban, html cheker header + ------------------- + begin : Mon Mar 19 2001 + copyright : (C) 2001 by Alexander Bilichenko + email : pricer@mail.ru + ***************************************************************************/ + +#ifndef SPELLER_H_INCLUDED +#define SPELLER_H_INCLUDED + +#include "basetypes.h" +#include "profiles.h" +#include "dbase.h" + +/* error codes for CheckSpellingBan() */ +#define MSG_CHK_ERROR_PASSED 1 +#define MSG_CHK_ERROR_NONAME 2 +//#define MSG_CHK_ERROR_NOEMAIL 3 +#define MSG_CHK_ERROR_NOMSGHEADER 4 +#define MSG_CHK_ERROR_NOMSGBODY 5 +#define MSG_CHK_ERROR_BADSPELLING 6 +#define MSG_CHK_ERROR_BANNED 7 +#define MSG_CHK_ERROR_CLOSED 8 +#define MSG_CHK_ERROR_INVALID_REPLY 9 +#define MSG_CHK_ERROR_INVALID_PASSW 10 +#define MSG_CHK_ERROR_ROBOT_MESSAGE 11 + +#define PROFILE_CHK_ERROR_ALLOK 1 +#define PROFILE_CHK_ERROR_ALREADY_EXIST 2 +#define PROFILE_CHK_ERROR_NOT_EXIST 3 +#define PROFILE_CHK_ERROR_INVALID_LOGIN_SPELL 4 +#define PROFILE_CHK_ERROR_INVALID_PASSWORD 5 +#define PROFILE_CHK_ERROR_INVALID_PASSWORD_REP 6 +#define PROFILE_CHK_ERROR_SHORT_PASSWORD 7 +#define PROFILE_CHK_ERROR_INVALID_EMAIL 8 +#define PROFILE_CHK_ERROR_CANNOT_DELETE_USR 9 +#define PROFILE_CHK_ERROR_UNKNOWN_ERROR 10 + +#define SPELLER_FILTER_HTML 0x0002 +#define SPELLER_PARSE_TAGS 0x0001 + +/* bit mask of CFlags format in CheckSpellingBan() */ +#define MSG_CHK_DISABLE_WWWCONF_TAGS 0x0001 +#define MSG_CHK_DISABLE_SMILE_CODES 0x0002 +#define MSG_CHK_ENABLE_EMAIL_ACKNL 0x0004 +#define MSG_CHK_ALLOW_HTML 0x0008 +#define MSG_CHK_DISABLE_SIGNATURE 0x0010 + +#define SPELLER_INTERNAL_BUFFER_SIZE 10000 + +/* code string to http format, if allocmem = 1 - function will allocate memory for you, + * otherwise internal buffer will be used (10K buffer) */ +char* CodeHttpString(char *s, int allocmem = 1); + +/* check email (with current #define settings) */ +int IsMailCorrect(char *s); + +/* Preprare message under WIN32 for preview - actually filter char #10 */ +void FilterMessageForPreview(char *s, char **dd); + +/* filter html tags, if allocmem = 1 - function will allocate memory for you, + * otherwise internal buffer will be used (10K buffer) */ +char* FilterHTMLTags(char *s, WORD ml, int allocmem = 1); + +char* FilterWhitespaces(char *s); + +/* prepare every text in this board to be printed to browser */ +int PrepareTextForPrint(char *msg, char **res, BYTE security, int flags, int spfl = SPELLER_FILTER_HTML | SPELLER_PARSE_TAGS); + +/* check message for correct and check HTML Tags, bad words list, and banned user */ +int CheckSpellingBan(struct SMessage *mes, char **body, char **Reason, + DWORD CFlags, DWORD *RetFlags, bool fRegged = true); + +#endif blob - /dev/null blob + a83cc65c3ce8258e9df61d6f9e5c6e0fa3c73e23 (mode 644) --- /dev/null +++ src/statfs.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include "statfs.h" + +typedef signed long long i64; + +bool isEnoughSpace(void) +{ +/* const i64 minsize = 10 * 1000 * 1000; //10Mb + struct statfs fsi; + if(statfs(".", &fsi)) + return false;*/ +// printf( +// "fs stats: fsi.f_bsize: %u; fsi.f_bavail: %u\n", +// fsi.f_bsize, +// fsi.f_bavail); + //return (i64)fsi.f_bsize * (i64)fsi.f_bavail > minsize; + return 1; +} blob - /dev/null blob + 3abf1b4566c8181c76db101e13eb89d3846f610d (mode 644) --- /dev/null +++ src/statfs.h @@ -0,0 +1 @@ +bool isEnoughSpace(void);