commit - 0cc8edab99deae5a987db984e957b733a51816ba
commit + 7dc1039c56f1f1a35707aea31b6bf10028f6c20e
blob - /dev/null
blob + 100bf7c26d33a82dcded3ac21b6f353f7c25cfbc (mode 644)
--- /dev/null
+++ ChangeLog.txt
+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
+#
+# 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <locale.h>
+#include <errno.h>
+#include <ctype.h>
+
+/****************** 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 <windows.h>
+#include <io.h>
+#include <direct.h>
+#include <winsock.h>
+
+#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 <assert.h>
+
+/* memory leaks detection */
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+
+#endif // _DEBUG_
+
+/**********Unix*********/
+#else
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+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
+/***************************************************************************
+ 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", "<B>", WC_TAG_TYPE_1, "</B>", WC_TAG_TYPE_1, 2},
+ {"E", "<EM>", WC_TAG_TYPE_1, "</EM>", WC_TAG_TYPE_1, 2},
+ {"I", "<I>", WC_TAG_TYPE_1, "</I>", WC_TAG_TYPE_1, 2},
+ {"U", "<U>", WC_TAG_TYPE_1, "</U>", WC_TAG_TYPE_1, 2},
+ {"H", "<B><FONT SIZE=4>", WC_TAG_TYPE_1, "</FONT></B>", WC_TAG_TYPE_1, 0},
+ {"S", "<FONT SIZE=1>", WC_TAG_TYPE_1, "</FONT>", WC_TAG_TYPE_1, 2},
+ /* Colour tags */
+ {"GREEN", "<FONT COLOR=#00FF00>", WC_TAG_TYPE_1, "</FONT>", WC_TAG_TYPE_1, 2},
+ {"RED", "<FONT COLOR=#FF0000>", WC_TAG_TYPE_1, "</FONT>", WC_TAG_TYPE_1, 0},
+ {"COLOR", "<FONT COLOR=%s>", WC_TAG_TYPE_2, "</FONT>", WC_TAG_TYPE_1, 0},
+ {"C", "<FONT COLOR=%s>", WC_TAG_TYPE_2, "</FONT>", WC_TAG_TYPE_1, 0},
+ /* URL, Picture, Mail */
+ {"URL", "<A HREF=\"%s\" STYLE=\"text-decoration:underline;\" TARGET=_blank>", WC_TAG_TYPE_2, "</A>", WC_TAG_TYPE_1, 10},
+ {"PIC", "<IMG src=\"", WC_TAG_TYPE_1, "\">", WC_TAG_TYPE_1, 10},
+ {"MAIL", "<A HREF=\"mailto:%s\" STYLE=\"text-decoration:underline;\">", WC_TAG_TYPE_2, "</A>", WC_TAG_TYPE_1, 10},
+ /* HR SIZE=1 */
+ {"HR", "<HR SIZE=2>", WC_TAG_TYPE_ONLYOPEN, "", WC_TAG_TYPE_DISABLED, 2},
+ /* quotation */
+ {"Q", "<P><B>Quotation:</B><DL><BOLD><FONT COLOR=#222222 SIZE=2><STRONG>",
+ WC_TAG_TYPE_1, "</STRONG></FONT></BOLD></DL></P>", WC_TAG_TYPE_1, 2},
+ /* Center */
+ {"CENTER", "<CENTER>", WC_TAG_TYPE_1, "</CENTER>", WC_TAG_TYPE_1, 10},
+ /* Pre */
+ {"PRE", "<PRE STYLE=\"margin-left:25px\">", WC_TAG_TYPE_1, "</PRE>", WC_TAG_TYPE_1, 10},
+ {"STRIKE", "<STRIKE>", WC_TAG_TYPE_1, "</STRIKE>", 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 <BR>
+ memcpy(d, "<BR>", 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 <BR>
+ memcpy(d, "<BR>", 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, "<IMG BORDER=0 SRC=\"" BOARD_PIC_URL);
+ strcat(dd, PicConvTable[j].url);
+ strcat(dd, "\" ALT=\"");
+ strcat(dd, PicConvTable[j].tag);
+ 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 <BR>
+ memcpy(dd, "<BR>", 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 -> <BR> 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" -> "<br>" 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<opentag; i++) {
+ free(OldTag[i].oldexp);
+ free(OldTag[i].tagexp);
+ }
+ return 0;
+ }
+ if(opentag) {
+ register DWORD k;
+ for(k = opentag; k > 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
+/***************************************************************************
+ 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 "<A HREF=\"%s\" STYLE=\"text-decoration:underline;\" TARGET=_blank>%s</A>"
+
+#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
+/***************************************************************************
+ 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<DWORD, char*>::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<DWORD, char*>::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
+/***************************************************************************
+ 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 <hash_map>
+# elif __GNUC__ >= 3
+# include <ext/hash_map>
+namespace std{
+ using namespace __gnu_cxx;
+}
+# else
+# include <hash_map.h>
+# endif
+#elif defined(_MSC_VER)
+# if _MSC_VER >= 1100
+# include <hash_map>
+# else
+# error "std::hash_map is not available with this compiler, compile using MSVC7 and later"
+# endif
+#elif defined(__sgi__)
+# include <hash_map>
+#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<DWORD, char*> 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
+/***************************************************************************
+ 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, "<A HREF=\"%s?uinfo=%s\" target=\"_blank\"><B>%s</B></A>", 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("<BR>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("<BR>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("<BR>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("<SMALL>");
+
+ printf("<A NAME=%ld", mes->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("><B>");
+ 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("</B>");
+
+ PRINT_COMMON_POST_MESSAGE_INFO();
+
+ if(mes->Readed) printf("</A> <EM>(%d)</EM>", mes->Readed);
+ else printf("</A>");
+
+ printf(" -- <nobr>%s</nobr>", aname);
+ if((currentdsm & 32) == 0)printf(" <EM>(%s)</EM>", mes->HostName);
+ printf(" -- <EM>%s</EM>", tm);
+
+ if((mes->Flag & MESSAGE_IS_INVISIBLE) != 0)
+ printf("</SMALL>");
+
+ 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("<P>");
+ /* 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." "<A HREF=" MY_CGI_URL "?favdel=%ld target=_blank>" DESIGN_FAVORITES_DEL_THREAD "</A> ",
+ 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("<P>");
+ 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("<BIG>%s</BIG>", 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(" <A HREF=\"" MY_CGI_URL "?favadd=%ld\" target=_blank>"
+ DESIGN_FAVORITES_ADD_THREAD "</A>", favtemp);
+ break;
+ case PROFILE_RETURN_ALREADY_EXIST:
+ printf(" <A HREF=\"" MY_CGI_URL "?favdel=%ld\" target=_blank>"
+ DESIGN_FAVORITES_DEL_THREAD "</A>", 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<FORM><INPUT TYPE=HIDDEN NAME=\"ChangeTopic\" VALUE=\"%ld\">"
+ "<SELECT NAME=\"topic\">", parmes.ViIndex);
+ for(DWORD i = 0; i < TOPICS_COUNT; i++) {
+ if(Topics_List_map[i] == msg->Topics) {
+ // define default choise
+ printf("<OPTION VALUE=\"%d\"" LISTBOX_SELECTED ">%s\n",
+ Topics_List_map[i], Topics_List[Topics_List_map[i]]);
+ }
+ else {
+ printf("<OPTION VALUE=\"%d\">%s\n",
+ Topics_List_map[i], Topics_List[Topics_List_map[i]]);
+ }
+ }
+ printf("</SELECT> <INPUT TYPE=SUBMIT NAME=\"ChangeTopic\" VALUE=\"Change\"></FORM>\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("<P></P><BR>");
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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<HTML><HEAD><TITLE>" \
+ TITLE_WWWConfBegining TITLE_divider "Error during page refresh</TITLE></HEAD>");
+
+ printf("<p><B><H3>An error occured</H3></B></p><p>Try to refresh this page, and if"
+ " this occure again please contact server <a href=\"mailto:%s\">"
+ " administrator </a> for support", ADMIN_MAIL);
+#if ERROR_ON_SCREEN == 0
+#if ENABLE_LOG
+ printf("<p><font color=#ff0000> This error have been logged to the"
+ " server log");
+#endif
+#else
+ printf("<P><font color=#ff0000><I>Technical details</I></font><BR>" \
+ "<font color=#0000ff>" LOG_UNHANDLED_HTML, file, line, getenv(REMOTE_ADDR),
+ (s && (*s != 0)) ? s : LOG_ERRORTYPEUNKN, getenv(QUERY_STRING));
+#endif
+ printf("</HTML>");
+ fflush(stdout);
+ exit(0);
+}
blob - /dev/null
blob + 4cdc6fb05cb47fdd1f028c6152dd448afcd8feda (mode 644)
--- /dev/null
+++ src/error.h
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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 <config.h>
+//#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("<CENTER><FORM METHOD=POST NAME=\"postform\" onSubmit=\"return false;\" ACTION=\"%s?xpost=%lu\">",
+ MY_CGI_URL, s);
+
+ printf(DESIGN_POST_NEW_MESSAGE_TABLE "<TR><TD COLSPAN=2 ALIGN=CENTER><BIG>");
+ if(code & ACTION_BUTTON_EDIT) printf(MESSAGEMAIN_post_editmessage);
+ else if(code & ACTION_BUTTON_FAKEREPLY) printf("<A NAME=Reply>" MESSAGEMAIN_post_replymessage "</A>");
+ else printf(MESSAGEMAIN_post_newmessage);
+
+ printf("</BIG></TD></TR>");
+ printf("<TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR>");
+
+ if(!(code & ACTION_BUTTON_EDIT)) {
+ if(ULogin.LU.ID[0] == 0) {
+ // print name/password form
+ printf("<TR><TD ALIGN=CENTER>%s "
+ "<INPUT TYPE=TEXT NAME=\"name\" SIZE=22 MAXLENGTH=%d VALUE=\"%s\"></TD>\n",
+ MESSAGEMAIN_post_you_name, AUTHOR_NAME_LENGTH - 1, msg->AuthorName);
+ // print password
+ printf("<TD ALIGN=LEFT>%s <INPUT TYPE=PASSWORD NAME=\"pswd\" SIZE=22"
+ " MAXLENGTH=%d VALUE=\"\"> %s<INPUT TYPE=CHECKBOX NAME=\"lmi\"></TD></TR>\n",
+ MESSAGEMAIN_post_your_password, PROFILES_MAX_PASSWORD_LENGTH - 1, MESSAGEMAIN_post_login_me);
+ }
+ else {
+ // print name
+ printf("<TR><TD ALIGN=CENTER>%s </TD><TD><B>%s</B> <A HREF=\"%s?login=logoff\"><SMALL>[%s] </SMALL></A></TD></TR>\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("<TR><TD ALIGN=CENTER>%s " \
+ "<INPUT TYPE=TEXT NAME=\"name\" SIZE=29 MAXLENGTH=%d VALUE=\"%s\"></TD>" \
+ "<TD>%s <INPUT TYPE=TEXT NAME=\"host\" SIZE=40 MAXLENGTH=%d" \
+ " VALUE=\"%s\"></TD></TR>", 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("<TR><TD ALIGN=CENTER>%s ", MESSAGEMAIN_post_message_subject);
+ // Only for ROOT messages
+ printf("<SELECT NAME=\"topic\">");
+ for(DWORD i = 0; i < TOPICS_COUNT; i++) {
+ if(Topics_List_map[i] == msg->Topics) {
+ // define default choise
+ printf("<OPTION VALUE=\"%d\"" LISTBOX_SELECTED ">%s\n",
+ Topics_List_map[i], Topics_List[Topics_List_map[i]]);
+ }
+ else {
+ printf("<OPTION VALUE=\"%d\">%s\n", Topics_List_map[i], Topics_List[Topics_List_map[i]]);
+ }
+ }
+ printf("</SELECT></TD><TD>");
+ }
+ else {
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER>%s ", MESSAGEMAIN_post_message_subject);
+ }
+
+ printf("<INPUT TYPE=TEXT NAME=\"subject\" SIZE=%d MAXLENGTH=%d VALUE=\"%s\"></TD></TR>\n",
+ s? 88: 62, MESSAGE_HEADER_LENGTH - 1, msg->MessageHeader);
+
+#else
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER>%s ", MESSAGEMAIN_post_message_subject);
+ printf("<INPUT TYPE=TEXT NAME=\"subject\" SIZE=88 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>\n",
+ MESSAGE_HEADER_LENGTH - 1, msg->MessageHeader);
+#endif
+
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG>\n",
+ MESSAGEMAIN_post_message_body);
+
+
+ printf("</TD></TD></TR><TR><TD COLSPAN=2 ALIGN=CENTER><TEXTAREA COLS=75 ROWS=12 NAME=\"body\" WRAP=VIRTUAL>%s</TEXTAREA></TD></TR>",
+ 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("<TR><TD COLSPAN=2 ALIGN=RIGHT class=cl>%s <INPUT TYPE=CHECKBOX NAME=\"dct\"%s class=cl></TD></TR>"
+ "<TR><TD COLSPAN=2 ALIGN=RIGHT class=cl>%s <INPUT TYPE=CHECKBOX NAME=\"dst\"%s class=cl></TD></TR>",
+ 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("<TR><TD COLSPAN=2 ALIGN=RIGHT class=cl>%s<INPUT TYPE=CHECKBOX NAME=\"wen\"%s class=cl></TD></TR>",
+ MESSAGEMAIN_post_reply_acknl, tstr[0]);
+// }
+
+ printf("<TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR><BR>");
+
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER>");
+
+ char onSubmitScript[] =
+ "<script>\n"
+ "var cTries=0\n"
+ "function onSubmit(obj)\n"
+ "{\n"
+ " var x=document.postform\n"
+ " if (x.subject.value.length == 0) {\n"
+ " alert(\"" MESSAGEMAIN_add_emptymsg_java "\");\n"
+ " return false;\n"
+ " }\n"
+ " if (x.subject.value.length > 65530) {\n"
+ " alert(\"" MESSAGEMAIN_add_tolong_java "\");\n"
+ " return false;\n"
+ " }\n"
+ " if(obj)x.jpost.value = obj.name;\n"
+ " if(document.all||document.getElementById) {\n"
+ " for(i = 0; i < x.length; i++) {\n"
+ " var tempobj = x.elements[i]\n"
+ " if(\n"
+ " tempobj.type &&\n"
+ " (tempobj.type.toLowerCase() == \"submit\" || tempobj.type.toLowerCase() == \"reset\"))\n"
+ " tempobj.disabled=true\n"
+ " }\n"
+ " }\n"
+ " if(cTries++ == 0)\n"
+ " x.submit();\n"
+ " return false;\n"
+ "}\n"
+ "</script>\n";
+ printf("%s", onSubmitScript);
+
+ if(code & ACTION_BUTTON_EDIT) {
+ printf("\n<INPUT TYPE=SUBMIT NAME=\"edit\" onClick=\"onSubmit(this)\" VALUE=\"%s\">", MESSAGEMAIN_post_edit_message);
+ }
+ else {
+ if(code & ACTION_BUTTON_PREVIEW) {
+ printf("\n<INPUT TYPE=SUBMIT NAME=\"preview\" onClick=\"onSubmit(this)\" VALUE=\"%s\"> ",MESSAGEMAIN_post_preview_message);
+ }
+ if(code & ACTION_BUTTON_POST) {
+ printf("<INPUT TYPE=SUBMIT NAME=\"post\" onClick=\"onSubmit(this)\" VALUE=\"%s\">", MESSAGEMAIN_post_post_message);
+ }
+ }
+ printf("<INPUT TYPE=HIDDEN NAME=\"jpost\" VALUE=\"%s\">", "");
+
+ printf("</TD></TR></TABLE></FORM></CENTER><P> ");
+}
+
+static void PrintLoginForm()
+{
+ printf("<P><FORM METHOD=POST ACTION=\"%s?login=action\">", MY_CGI_URL);
+
+ printf(DESIGN_BEGIN_LOGIN_OPEN);
+
+ printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><INPUT TYPE=TEXT NAME=\"mname\" SIZE=20 " \
+ "MAXLENGTH=%d VALUE=\"%s\"></TD></TR><TR><TD ALIGN=RIGHT>%s</TD><TD>" \
+ "<INPUT TYPE=PASSWORD NAME=\"mpswd\" SIZE=20 MAXLENGTH=30 VALUE=\"\"></TD></TR>",
+ MESSAGEMAIN_login_loginname, AUTHOR_NAME_LENGTH - 1,
+ FilterHTMLTags(cookie_name, 1000, 0), MESSAGEMAIN_login_password);
+
+ printf("<TR><TD COLSPAN=2><CENTER><INPUT TYPE=CHECKBOX NAME=\"ipoff\" VALUE=1>" \
+ MESSAGEMAIN_login_ipcheck "</CENTER></TD></TR>");
+
+ printf("<P><TR><TD COLSPAN=2 ALIGN=CENTER><INPUT TYPE=SUBMIT VALUE=\"Enter\"></TD></TR>" DESIGN_END_LOGIN_CLOSE "</FORM>");
+
+ printf(MESSAGEMAIN_login_lostpassw);
+}
+
+static void PrintPrivateMessageForm(char *name, char *body)
+{
+ printf("<CENTER><FORM METHOD=POST ACTION=\"%s?persmsgpost\"><P> <P>", MY_CGI_URL);
+
+ printf(DESIGN_POST_NEW_MESSAGE_TABLE "<TH COLSPAN=2><BIG>" MESSAGEMAIN_privatemsg_send_msg_hdr
+ "</BIG></TR><TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR>");
+ printf("<TR><TH ALIGN=RIGHT>%s </TH><TD>"
+ "<INPUT TYPE=TEXT NAME=\"name\" SIZE=30 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>"
+ "<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG>",
+ MESSAGEMAIN_privatemsg_send_msg_usr, PROFILES_MAX_USERNAME_LENGTH - 1,
+ name, MESSAGEMAIN_privatemsg_send_msg_bdy);
+
+ printf("<BR><TEXTAREA COLS=50 ROWS=7 NAME=\"body\" WRAP=VIRTUAL>%s</TEXTAREA></TD></TR>", body);
+
+ printf("<TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR><BR><TR><TD COLSPAN=2 ALIGN=CENTER>"
+ "<INPUT TYPE=SUBMIT NAME=\"Post\" VALUE=\"%s\"> <INPUT TYPE=SUBMIT NAME=\"Post\" VALUE=\"%s\"></TD></TR></TABLE></FORM></CENTER>",
+ MESSAGEMAIN_privatemsg_prev_msg_btn, MESSAGEMAIN_privatemsg_send_msg_btn);
+}
+
+static void PrintAnnounceForm(char *body, int ChangeAnn = 0)
+{
+ printf("<CENTER><FORM METHOD=POST ACTION=\"%s?globann=post\"><P> <P>", MY_CGI_URL);
+
+ printf(DESIGN_POST_NEW_MESSAGE_TABLE "<TH COLSPAN=2><BIG>%s</BIG></TR><TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR>",
+ ChangeAnn ? MESSAGEMAIN_globann_upd_ann_hdr : MESSAGEMAIN_globann_send_ann_hdr);
+
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><BR>"
+ "<TEXTAREA COLS=50 ROWS=7 NAME=\"body\" WRAP=VIRTUAL>%s</TEXTAREA></TD></TR>",
+ MESSAGEMAIN_globann_send_ann_body, body);
+
+ if(ChangeAnn) printf("<TR><TD COLSPAN=2><CENTER><INPUT TYPE=CHECKBOX NAME=\"refid\" VALUE=1>" \
+ MESSAGEMAIN_globann_upd_ann_id "</CENTER></TD></TR>");
+ printf("<TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR><BR><TR><TD COLSPAN=2 ALIGN=CENTER>");
+ if(ChangeAnn) printf("<INPUT TYPE=HIDDEN NAME=\"cgann\" VALUE=\"%d\">", ChangeAnn);
+ printf("<INPUT TYPE=SUBMIT NAME=\"Post\" VALUE=\"%s\"><INPUT TYPE=SUBMIT NAME=\"Post\" VALUE=\"%s\"></TD></TR></TABLE></FORM></CENTER>",
+ MESSAGEMAIN_globann_prev_ann_btn, MESSAGEMAIN_globann_send_ann_btn);
+}
+
+static void PrintLostPasswordForm()
+{
+ printf("<P><FORM METHOD=POST ACTION=\"%s?login=lostpasswaction\">", MY_CGI_URL);
+
+ printf(DESIGN_BEGIN_LOSTPASSW_OPEN);
+
+ printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><INPUT TYPE=TEXT NAME=\"mname\" SIZE=20 MAXLENGTH=%d "
+ "VALUE=\"%s\"></TD></TR><TR><TD ALIGN=RIGHT>%s</TD><TD><INPUT TYPE=TEXT NAME=\"memail\" SIZE=20 "
+ "MAXLENGTH=%d VALUE=\"\"></TD></TR>", MESSAGEMAIN_lostpassw_loginname, AUTHOR_NAME_LENGTH - 1,
+ FilterHTMLTags(cookie_name, 1000, 0), MESSAGEMAIN_lostpassw_email, PROFILES_FULL_USERINFO_MAX_EMAIL - 1);
+
+ printf("<P><TR><TD COLSPAN=2 ALIGN=CENTER><INPUT TYPE=SUBMIT VALUE=\"" MESSAGEMAIN_lostpassw_getpassw "\"><CENTER></TD></TR>" DESIGN_END_LOSTPASSW_CLOSE "</FORM>");
+}
+
+/* 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("<TABLE align=center width=100%%><tr><td><FORM METHOD=POST ACTION=\"%s?configure=action\" name=\"configure\">",
+ MY_CGI_URL);
+
+ printf("<CENTER><P><B>%s</B><BR><P>", MESSAGEHEAD_configure);
+
+ printf("<P><B>%s</B><BR><P>", 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("<INPUT TYPE=RADIO NAME=lsel VALUE=1%s>%s" \
+ "<INPUT TYPE=TEXT NAME=\"tv\" SIZE=2 VALUE=%d><SELECT NAME=\"tt\">" \
+ "<OPTION VALUE=\"1\"%s>%s<OPTION VALUE=\"2\"%s>%s<OPTION VALUE=\"3\"%s>" \
+ "%s<OPTION VALUE=\"4\"%s>%s</SELECT><BR>",
+ 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("<INPUT TYPE=RADIO NAME=lsel VALUE=2%s>%s<INPUT TYPE=TEXT NAME=\"tc\" SIZE=3 VALUE=%d>"
+ "%s<P>%s<SELECT NAME=\"ss\"><OPTION VALUE=\"2\"%s>%s<OPTION VALUE=\"3\"%s>%s<OPTION VALUE=\"4\"%s>"
+ "%s</SELECT>",
+ str1, MESSAGEHEAD_configure_lastnum, currenttc, MESSAGEHEAD_configure_lastnum2,
+ MESSAGEHEAD_configure_showstyle, str3,
+ MESSAGEHEAD_configure_showhronbackward, str4,
+ MESSAGEHEAD_configure_showhronwothreads, str5,
+ MESSAGEHEAD_configure_showhrononlyheaders);
+
+ printf("<BR><BR>┬Ёхьхээющ яю ё: <SELECT NAME=\"tz\">");
+ for(i = -12; i <= 12; i++)
+ printf("<OPTION VALUE=\"%d\"%s>Timezone GMT%s%02d", i,
+ (i == currenttz) ? LISTBOX_SELECTED : "", (i>=0) ? "+" : "-", (i>0)? i : -i);
+ printf("</SELECT><BR>");
+
+
+#if TOPICS_SYSTEM_SUPPORT
+ // use str4 for temporaty buffer
+ printf("<BR><P><TABLE BORDER=1 CELLSPACING=0 CELLPADDING=6 BGCOLOR=#BBAAAA>\
+<TR><TD ALIGN=CENTER>" DESIGN_CONFIGURE_CHECKALL "</TD></TR><TR><TD ALIGN=RIGHT>");
+ for(DWORD i = 0; i < TOPICS_COUNT; i++)
+ {
+ if(currenttopics & (1<<Topics_List_map[i]))
+ strcpy(str4, RADIO_CHECKED);
+ else str4[0] = 0;
+ printf("%s <INPUT TYPE=CHECKBOX NAME=\"topic%d\"%s><br>\n",
+ Topics_List[Topics_List_map[i]], Topics_List_map[i], str4);
+ }
+ printf("</TD></TR></TABLE>");
+#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("<TABLE><TR><TD ALIGN=RIGHT>%s<INPUT TYPE=CHECKBOX NAME=\"dsm\" VALUE=1%s>",
+ MESSAGEHEAD_configure_disablesmiles, str3);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"dup\" VALUE=1%s>",
+ MESSAGEHEAD_configure_disableuppic, str4);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"dul\" VALUE=1%s>",
+ MESSAGEHEAD_configure_disable2links, str5);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"onh\" VALUE=1%s>",
+ MESSAGEHEAD_configure_ownpostshighlight, str2);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"host\" VALUE=1%s>",
+ MESSAGEHEAD_configure_showhostnames, str6);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"nalt\" VALUE=1%s>",
+ MESSAGEHEAD_configure_showaltnames, str7);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"dsig\" VALUE=1%s>",
+ MESSAGEHEAD_configure_showsign, str8);
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"shrp\" VALUE=1%s>",
+ MESSAGEHEAD_configure_showreplyform, str9);
+#if ALLOW_MARK_NEW_MESSAGES == 2
+ printf("<BR>%s<INPUT TYPE=CHECKBOX NAME=\"plu\" VALUE=1%s>",
+ MESSAGEHEAD_configure_plus_is_href, str1);
+#endif
+ printf("</TD></TR></TABLE>");
+
+ if(ULogin.LU.ID[0] && (ULogin.pui->Flags & PROFILES_FLAG_VIEW_SETTINGS) )
+ printf("<P>" MESSAGEHEAD_configure_saving_to_profile "<BR>");
+ else printf("<P>" MESSAGEHEAD_configure_saving_to_browser "<BR>");
+ if(ULogin.LU.ID[0]) printf(MESSAGEHEAD_configure_view_saving "<BR>");
+
+ printf("<P><INPUT TYPE=SUBMIT VALUE=\"%s\"></CENTER></FORM></form></td></tr></table>",
+ 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("<A HREF=\"#%ld\" STYLE=\"text-decoration:underline;\">%s</A>", 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("<A HREF=\"%s?form=%ld\" STYLE=\"text-decoration:underline;\">%s</A>",
+ MY_CGI_URL, ret, MESSAGEMAIN_post_replymessage);
+ else printf("<A HREF=\"#Reply\" STYLE=\"text-decoration:underline;\">%s</A>",
+ 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("<A HREF=\"%s?index\" STYLE=\"text-decoration:underline;\">%s</A>",
+ MY_CGI_URL, MESSAGEHEAD_return_to_main_page);
+ else printf("<A HREF=\"%s?index#%ld\"><font color=\"#F00F0F\" STYLE=\"text-decoration:underline;\">%s</font></A>",
+ MY_CGI_URL, ind, MESSAGEHEAD_return_to_main_page);
+ g = 1;
+ }
+
+ if(c & HEADERSTRING_POST_NEW_MESSAGE) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?form\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_post_new_message);
+ g = 1;
+ }
+
+ if((c & HEADERSTRING_DISABLE_SEARCH) == 0) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?search=form\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_search);
+ g = 1;
+ }
+
+ if(c & HEADERSTRING_CONFIGURE) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?configure=form\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_configure);
+ g = 1;
+ }
+
+ if(c & HEADERSTRING_ENABLE_RESETNEW) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?resetnew\" STYLE=\"text-decoration:underline;\">%s</A>", 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("<A HREF=\"%s?register=form\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_registerprf);
+ else
+ printf("<A HREF=\"%s?register=form\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_register);
+ g = 1;
+ }
+
+ if(c & HEADERSTRING_REG_USER_LIST) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?userlist\" STYLE=\"text-decoration:underline;\">%s</A>", 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("<A HREF=\"%s?banlist\" STYLE=\"text-decoration:underline;\">%s</a>", MY_CGI_URL, MESSAGEHEAD_banlist);
+ }
+
+ if((ULogin.LU.ID[0] == 0) && ((c & HEADERSTRING_DISABLE_LOGIN) == 0)) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?login=form\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_login);
+ g = 1;
+ }
+
+ if((c & HEADERSTRING_DISABLE_FAQHELP) == 0) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"rules.html\" STYLE=\"text-decoration:underline;\">" MESSAGEHEAD_help_showhelp "</A>");
+ g = 1;
+ }
+
+#if USER_FAVOURITES_SUPPORT
+ if(ULogin.LU.ID[0] != 0 && (c & HEADERSTRING_DISABLE_FAVOURITES) == 0) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?favs\" STYLE=\"text-decoration:underline;\">%s</A>",
+ 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("<A HREF=\"%s?persmsg\" STYLE=\"text-decoration:underline;\"><FONT COLOR=RED><BOLD>%s(%d)</BOLD></FONT></A>",
+ MY_CGI_URL, MESSAGEHEAD_personalmsg, ULogin.pui->persmescnt - ULogin.pui->readpersmescnt);
+ else
+ printf("<A HREF=\"%s?persmsg\" STYLE=\"text-decoration:underline;\">%s</A>", 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("<A HREF=\"%s?globann=form\" STYLE=\"text-decoration:underline;\">%s</A>", 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("<A HREF=\"%s?login=logoff\" STYLE=\"text-decoration:underline;\">%s</A>", MY_CGI_URL, MESSAGEHEAD_logoff);
+ g = 1;
+ }
+
+ printf("</TD></TR></TABLE>");
+}
+
+void PrintTopStaticLinks(DWORD c)
+{
+ //print stable links on index page
+ if ((c & HEADERSTRING_REG_USER_LIST) != 0 && (currentdsm & 4) == 0) {
+ //printf("<TR><TD class=cs align=center>");
+ printf(DESIGN_COMMAND_TABLE_BEGIN);
+ printf("<!--<A HREF=\"/dev/\" target=_blank STYLE=\"text-decoration:underline;\"><nobr>%s</nobr></A>", "Programming Board-->");
+ //gray space after top links
+ printf("<TR><TD class=cl> </TD></TR>");
+ printf("</TD></TR></TABLE>");
+ }
+
+}
+
+/* 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("<meta http-equiv=\"Refresh\" content=\"0; url=%s?index\"></head></html>", MY_CGI_URL);
+ return;
+ }
+
+ if(code & HEADERSTRING_REFRESH_TO_MAIN_PAGE) {
+ if(curind == MAINPAGE_INDEX || curind == 0)
+ printf("<meta http-equiv=\"Refresh\" content=\"%d; url=%s?index\">",
+ AUTO_REFRESH_TIME, MY_CGI_URL);
+ else
+ printf("<meta http-equiv=\"Refresh\" content=\"%d; url=%s?index#%ld\">",
+ AUTO_REFRESH_TIME, MY_CGI_URL, curind);
+ }
+
+ // print output encoding (charset)
+ printf(TEXT_ENCODING_HEADER);
+
+ // print title
+#if STABLE_TITLE == 0
+ printf("<title>%s</title>", ConfTitle);
+#else
+ printf("<title>%s</title>", 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("<BR><CENTER><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=1"
+ "BGCOLOR=\"#eeeeee\"><TR><TD ALIGN=CENTER>[ <SMALL>");
+
+ /* close thread */
+ if(fl & 0x0001) {
+ printf("<A HREF=\"%s?close=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_close_thread);
+ g = 1;
+ }
+
+ /* open thread */
+ if(fl & 0x0002) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?unclose=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_unclose_thread);
+ g = 1;
+ }
+
+ // change message
+ if(fl & 0x0004) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?changemsg=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_change_message);
+ }
+
+ /* collapse thread */
+ if(fl & 0x0020) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?roll=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_roll);
+ }
+
+ /* uncollapse thread */
+ if(fl & 0x0040) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?roll=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_unroll);
+ }
+
+ /* hide thread */
+ if(fl & 0x0008) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?hide=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_hide_thread);
+ g = 1;
+ }
+
+ /* unhide thread */
+ if(fl & 0x0010) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?unhide=%ld\"><font color=\"#AF0000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_unhide_thread);
+ g =1;
+ }
+
+ /* delete thread */
+ if(fl & 0x0080) {
+ if(g) printf(DESIGN_BUTTONS_DIVIDER);
+ printf("<A HREF=\"%s?delmsg=%d\"><font color=\"#FF1000\">%s</font></A>",
+ MY_CGI_URL, root, MESSAGEMAIN_moderate_delete_thread);
+ }
+
+ printf("</SMALL> ]</TD></TR></TABLE></CENTER>");
+ }
+ 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("<FORM METHOD=POST ACTION=\"%s?search=action\">",
+ MY_CGI_URL);
+
+ printf("<CENTER><P><B>%s</B><BR><P>", 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("<P>%s<P>%s : %s<P>", MESSAGEMAIN_search_howtouse, MESSAGEMAIN_search_lastindexed, LastMsgStr);
+ }
+
+ printf("<P><EM>%s</EM><BR>", MESSAGEMAIN_search_searchmsg);
+ printf("<INPUT TYPE=RADIO NAME=sel VALUE=1 CHECKED>%s <FONT FACE=\"Courier\">"
+ "<INPUT TYPE=TEXT NAME=\"find\" SIZE=45 VALUE=\"%s\"></FONT>",
+ MESSAGEMAIN_search_containing, s);
+
+
+ printf("<P><INPUT TYPE=SUBMIT VALUE=\"%s\"></CENTER></FORM>",
+ 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("<FORM METHOD=POST ACTION=\"%s?register=action\">",
+ MY_CGI_URL);
+
+ if(ULogin.LU.ID[0] == 0) {
+ printf(DESIGN_BEGIN_REGISTER_OPEN "<TD COLSPAN=2 ALIGN=CENTER>"
+ "<BIG>%s</BIG></TD></TR>", MESSAGEMAIN_register_intro);
+ }
+ else
+ printf(DESIGN_BEGIN_REGISTER_OPEN "<TD COLSPAN=2 ALIGN=CENTER>"
+ "<BIG>%s</BIG></TD></TR>", MESSAGEMAIN_register_chg_prof_intro);
+
+ printf("<TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TD></TR><TR><TD ALIGN=RIGHT>%s </TD>",
+ MESSAGEMAIN_register_login);
+
+ if( (ULogin.LU.ID[0] == 0) || (ULogin.LU.ID[0] != 0 && ((ULogin.pui->right & USERRIGHT_SUPERUSER) != 0)) ) {
+ printf("<TD><INPUT TYPE=TEXT NAME=\"login\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>",
+ AUTHOR_NAME_LENGTH - 1, ui->username);
+ }
+ else {
+ printf("<TD>%s</TD></TR>", ui->username);
+ }
+
+ if( ULogin.LU.ID[0] != 0 && ((ULogin.LU.right & USERRIGHT_ALT_DISPLAY_NAME) != 0) ) {
+ printf("<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=TEXT NAME=\"dispnm\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>",
+ MESSAGEMAIN_register_displayname, PROFILES_MAX_ALT_DISPLAY_NAME - 1, ui->altdisplayname);
+ }
+
+ if((flags & 0x01) == 0) {
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>" MESSAGEMAIN_register_oldpass_req "</STRONG></TR>" \
+ "<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=PASSWORD NAME=\"opswd\" SIZE=35 " \
+ "MAXLENGTH=%d VALUE=\"\"></TD></TR>",
+ MESSAGEMAIN_register_oldpassword, PROFILES_MAX_PASSWORD_LENGTH - 1);
+ }
+
+ if(ui->Flags & PROFILES_FLAG_VISIBLE_EMAIL)
+ strcpy(str1, RADIO_CHECKED);
+ else *str1 = 0;
+
+ printf("<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>" MESSAGEMAIN_register_if_want_change "</STRONG></TR>" \
+"<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=PASSWORD NAME=\"pswd1\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=PASSWORD NAME=\"pswd2\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=TEXT NAME=\"name\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>" MESSAGEMAIN_register_validemail_req "</STRONG></TR>" \
+"<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=TEXT NAME=\"email\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><INPUT TYPE=CHECKBOX NAME=\"pem\" VALUE=1%s></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=TEXT NAME=\"hpage\" SIZE=35 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s </TD><TD><INPUT TYPE=TEXT NAME=\"icq\" SIZE=15 MAXLENGTH=%d VALUE=\"%s\"></TD></TR>",
+ 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(
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><BR><TEXTAREA COLS=60 ROWS=3 NAME=\"about\" WRAP=VIRTUAL>%s</TEXTAREA></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><BR><TEXTAREA COLS=60 ROWS=3 NAME=\"sign\" WRAP=VIRTUAL>%s</TEXTAREA></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><BR><TEXTAREA COLS=30 ROWS=4 NAME=\"susr\" WRAP=VIRTUAL>%s</TEXTAREA></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><INPUT TYPE=CHECKBOX NAME=\"vprf\" VALUE=1%s></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><INPUT TYPE=CHECKBOX NAME=\"apem\" VALUE=1%s></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><INPUT TYPE=CHECKBOX NAME=\"pdis\" VALUE=1%s></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><INPUT TYPE=CHECKBOX NAME=\"peml\" VALUE=1%s></TD></TR>" \
+"<TR><TD COLSPAN=2 ALIGN=CENTER><STRONG>%s</STRONG><INPUT TYPE=CHECKBOX NAME=\"vprs\" VALUE=1%s></TD></TR>",
+ 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("<TR><TD COLSPAN=2></TR><TR><TD COLSPAN=2 ALIGN=CENTER><B><FONT COLOR=RED>" \
+ MESSAGEMAIN_register_req_fields "</FONT><B></TR><TR><TD COLSPAN=2>" \
+ "<HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR><TR><TD COLSPAN=2 ALIGN=CENTER>");
+
+ /* print buttons */
+ if(flags & 0x01)
+ printf("<INPUT TYPE=SUBMIT NAME=\"register\" VALUE=\"%s\"> ", MESSAGEMAIN_register_register);
+
+ if(flags & 0x02)
+ printf("<INPUT TYPE=SUBMIT NAME=\"register\" VALUE=\"%s\"> ", MESSAGEMAIN_register_edit);
+
+ if(flags & 0x04)
+ printf(
+ "<INPUT TYPE=SUBMIT NAME=\"register\" VALUE=\"" MESSAGEMAIN_register_delete "\">"
+ "<INPUT TYPE=CHECKBOX NAME=\"" CONFIRM_DELETE_CHECKBOX_TEXT "\" VALUE=\"true\">"
+ MESSAGEMAIN_register_confirm_delete);
+
+ printf("</TD></TR>" DESIGN_END_REGISTER_CLOSE "</FORM>");
+}
+
+
+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("<TR><TD ALIGN=RIGHT>%ld. "MESSAGEMAIN_session_ip"</TD><TD"
+ " ALIGN=LEFT><STRONG>%u.%u.%u.%u</STRONG> %s</TD></TR>",
+ 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("<TR><TD ALIGN=RIGHT>"MESSAGEMAIN_session_date"</TD><TD ALIGN=LEFT>"
+ " <STRONG>%s</STRONG></TD></TR>", seqdate);
+ printf("<TR><TD ALIGN=RIGHT>"MESSAGEMAIN_session_state"</TD><TD ALIGN=LEFT><STRONG>");
+
+ 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(" [<a href=\"%s?clsession1=%ld&clsession2=%ld\">"MESSAGEMAIN_session_state_toclose"</a>]", MY_CGI_URL, seqid[0], seqid[1]);
+ }
+ else printf(MESSAGEMAIN_session_state_closed);
+ printf("</STRONG></TD></TR><TR><TD><BR></TD></TR>");
+ free(buf[i]);
+ }
+ printf(DESIGN_END_USERINFO_INTRO_CLOSE);
+ }
+ else printf(DESIGN_BEGIN_USERINFO_INTRO_OPEN "<TR><TD ALIGN=CENTER><B>"
+ MESSAGEMAIN_session_no "</B></TD></TR>" 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("<P></P>" DESIGN_BEGIN_USERINFO_INTRO_OPEN
+ "<TD COLSPAN=2><BIG>%s %s</BIG></TD></TR>", MESSAGEMAIN_profview_intro, nickname);
+
+ printf("<TR><TD COLSPAN=2><HR ALIGN=CENTER WIDTH=80%% NOSHADE></TR>");
+
+ printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG><SMALL>", MESSAGEMAIN_profview_login, nickname );
+
+
+ if(ULogin.LU.UniqID == ui.UniqID){
+ printf(" <A HREF=\"?register=form\">(%s)</A>", MESSAGEMAIN_profview_editinfo);
+ }
+
+ if(ULogin.LU.ID[0] && ULogin.LU.UniqID != ui.UniqID){
+ printf(" <A HREF=\"?persmsgform=%s\">(%s)</A>", CodeHttpString(name), MESSAGEMAIN_profview_postpersmsg);
+ }
+
+ printf("</SMALL></TD></TR>");
+
+ 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("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>",
+ MESSAGEMAIN_profview_altname, st);
+ free(st);
+ }
+
+ if(((ui.Flags & PROFILES_FLAG_INVISIBLE) == 0) || (ULogin.LU.right & USERRIGHT_SUPERUSER) ||
+ (ULogin.LU.UniqID == ui.UniqID) )
+ {
+ printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>" \
+ "<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG><A HREF=\"%s\">%s</A></STRONG></TD></TR>",
+ 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("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG><A HREF=mailto:%s>%s</A></STRONG></TD></TR>",
+ MESSAGEMAIN_profview_email, fui.Email, fui.Email);
+ }
+ else printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG><FONT COLOR=#0000F0>%s</FONT></STRONG></TD></TR>",
+ 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, "<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>" \
+ "<IMG src=\"http://online.mirabilis.com/scripts/online.dll?icq=%s&img=5\">%s</STRONG></TD></TR><BR>",
+ MESSAGEMAIN_profview_user_icq, ui.icqnumber, ui.icqnumber);
+ }
+
+ printf("%s<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%ld</STRONG></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>" \
+"<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>",
+ 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("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%d</STRONG></TD></TR>",
+ MESSAGEMAIN_profview_refreshcnt, ui.RefreshCount);
+ printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%s</STRONG></TD></TR>",
+ MESSAGEMAIN_profview_lastip, hname);
+ printf("<TR><TD ALIGN=RIGHT>%s</TD><TD><STRONG>%d(%d)</STRONG></TD></TR>",
+ MESSAGEMAIN_profview_persmsgcnt, ui.persmescnt, ui.readpersmescnt);
+ }
+
+ free(logdate);
+ free(ustatus);
+ }
+ else {
+ printf("<TR><TD COLSPAN=2><BIG>%s</BIG></TD></TR><BR>", MESSAGEMAIN_profview_privacy_prof);
+ }
+ printf(DESIGN_END_USERINFO_INTRO_CLOSE);
+
+
+ printf("<BR>");
+
+ 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("<BR><CENTER><FORM METHOD=POST ACTION=\"%s?changeusr=action\"> User Status: ", MY_CGI_URL);
+
+ printf("<SELECT NAME=\"ustat\">");
+ for(i = 0; i < USER_STATUS_COUNT; i++) {
+
+ if(i == ui.Status) strcpy(sel, LISTBOX_SELECTED);
+ else strcpy(sel, "");
+
+ printf("<OPTION VALUE=\"%d\"%s>%s", i, sel, UserStatus_List[i]);
+ }
+ printf("</SELECT>");
+
+ printf("<BR>" MESSAGEMAIN_profview_sechdr "<INPUT TYPE=TEXT SIZE=3 NAME=\"sechdr\" VALUE=\"%d\">", (DWORD)ui.secheader);
+ printf("<BR>" MESSAGEMAIN_profview_secbdy "<INPUT TYPE=TEXT SIZE=3 NAME=\"secbdy\" VALUE=\"%d\">", (DWORD)ui.secur);
+ printf("<INPUT TYPE=HIDDEN SIZE=0 NAME=\"name\" VALUE=\"%s\">", nickname);
+
+ // user rights here
+ puts("<BR><P><TABLE BORDER=1 CELLSPACING=0 CELLPADDING=6 BGCOLOR=#FFFFFF><TR><TH ALIGN=RIGHT>");
+ for(i = 0; i < USERRIGHT_COUNT; i++)
+ {
+ if( (ui.right & (1<<i)) != 0)
+ strcpy(sel, RADIO_CHECKED);
+ else sel[0] = 0;
+ printf("%s <INPUT TYPE=CHECKBOX NAME=\"right%d\"%s><BR>",
+ UserRight_List[i], i, sel);
+ }
+ puts("</TH></TR></TABLE>");
+
+ printf("<BR><BR><INPUT TYPE=SUBMIT NAME=\"update\" VALUE=\"%s\">", MESSAGEMAIN_register_edit);
+
+ printf("</FORM></CENTER>");
+ }
+
+ 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("<CENTER><P><B>%s</B><BR>%s%d<P>", 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("<B>%s</B>", MESSAGEMAIN_userlist_sortby);
+ if(code != 1) printf("<A HREF=\"%s?userlist=1\">%s</A> | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyname);
+ else printf("<B>%s</B> | ", MESSAGEMAIN_userlist_sortbyname);
+ if(code != 2) printf("<A HREF=\"%s?userlist=2\">%s</A> | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbypcnt);
+ else printf("<B>%s</B> | ", MESSAGEMAIN_userlist_sortbypcnt);
+ if(code != 3) printf("<A HREF=\"%s?userlist=3\">%s</A> | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyhost);
+ else printf("<B>%s</B> | ", MESSAGEMAIN_userlist_sortbyhost);
+ if(code != 4) printf("<A HREF=\"%s?userlist=4\">%s</A> | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbydate);
+ else printf("<B>%s</B> | ", MESSAGEMAIN_userlist_sortbydate);
+ if(code != 5) printf("<A HREF=\"%s?userlist=5\">%s</A> | ", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyrefresh);
+ else printf("<B>%s</B> | ", MESSAGEMAIN_userlist_sortbyrefresh);
+ if(code != 6) printf("<A HREF=\"%s?userlist=6\">%s</A><BR><BR>", MY_CGI_URL, MESSAGEMAIN_userlist_sortbyright);
+ else printf("<B>%s</B><BR><BR>", MESSAGEMAIN_userlist_sortbyright);
+ }
+
+ DWORD oldval;
+ if(uc) {
+ unsigned char *aa = (unsigned char*)buf[0];
+ switch(code) {
+ case 2:
+ oldval = *((DWORD*)(buf[0] + 4));
+ printf("<B>(%lu)</B><BR>", *((DWORD*)(buf[0] + 4)));
+ break;
+ case 3:
+ oldval = *((DWORD*)(buf[0]));
+ printf("<B>(%u.%u.%u.%u)</B><BR>", 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("<B>(%lu)</B><BR>", *((DWORD*)(buf[0] + 12)));
+ break;
+ case 6:
+ oldval = *((DWORD*)(buf[0] + 16));
+ printf("<B>(%08x)</B><BR>", *((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("<BR><BR><B>(%lu)</B><BR>", *((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("<BR><BR><B>(%u.%u.%u.%u)</B><BR>", 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("<BR><BR><B>(%lu)</B><BR>", *((DWORD*)(buf[i] + 12)));
+ oldval = *((DWORD*)(buf[i] + 12));
+ cc = 0;
+ }
+ break;
+ case 6:
+ if(oldval != *((DWORD*)(buf[i] + 16))) {
+ printf("<BR><BR><B>(%08x)</B><BR>", *((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("</CENTER><BR><CENTER>");
+ }
+ cc++;
+
+ dbb->Profile_UserName(buf[i] + 20, name, 1);
+ printf("%s", name);
+ free(buf[i]);
+ }
+ if(buf) free(buf);
+ printf("</CENTER>");
+}
+
+/* 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("<CENTER><P><B>%s</B><BR>", MESSAGEHEAD_favourites);
+ //for( int i=0; i<20; i++){
+ // printf("ULogin.pui->favs[%ld]=%ld<br>",i, ULogin.pui->favs[i]);
+ //}
+ //DB.PrintHtmlMessageBufferByVI(ULogin.pui->favs, PROFILES_FAV_THREADS_COUNT);
+ printf("</CENTER>");
+}
+
+
+/* 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 <DIV> or <DL>?
+ 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;i<sizeof(SMessage);i++) s[i]=0;
+ s = (char *)&mbody;
+ for(i=0;i<sizeof(SMessageBody);i++) s[i]=0;
+ strcpy(mes.AuthorName,"www");
+ strcpy(mes.MessageHeader,"1111111");
+ strcpy(mes.HostName,"194.85.83.213");
+ char sx[100] = "[i][code];))111 ;)serial[url=http:\\www.ru]serial[/url][code]";
+ i = DB.DB_InsertMessage(&mes, 0, strlen(sx), sx, &mbody, 0xFFFFFFF, "www");
+ goto End_part;
+ // -----------------------------
+ */
+
+#if USE_LOCALE
+ /* set locale */
+ setlocale(LC_ALL, LANGUAGE_LOCALE);
+#endif
+
+ /* get cookie string, if available, and parse it */
+ ParseCookie();
+
+
+#if STABLE_TITLE == 0
+ // set default title
+ ConfTitle = (char*)malloc(strlen(TITLE_WWWConfBegining) + 1);
+ strcpy(ConfTitle, TITLE_WWWConfBegining);
+#endif
+
+
+
+ // get parameters with we have been run
+ if((st = getenv(QUERY_STRING)) != NULL)
+ {
+ deal = (char*)malloc(strlen(st) + 2);
+ strcpy(deal, st);
+ }
+ else deal = NULL;
+
+ if(deal == NULL || (strcmp(deal,"") == 0))
+ {
+ deal = (char*)malloc(20);
+ strcpy(deal,"index");
+ }
+
+ // detect IP
+ if((tmp = getenv(REMOTE_ADDR)) != NULL)
+ {
+ Cip = (char*)malloc(strlen(tmp) + 1);
+ strcpy(Cip, tmp);
+ }
+ else {
+ Cip = (char*)malloc(strlen(TAG_IP_NOT_DETECTED) + 1);
+ strcpy(Cip, TAG_IP_NOT_DETECTED);
+ }
+
+ // translate IP
+ // if it fails, we will have Nip = 0
+ char *tst, *tms;
+ tst = Cip;
+ {
+ for(register DWORD i = 0; i < 4; i++)
+ {
+ if((tms = strchr(tst,'.')) != NULL || (tms = strchr(tst,'\0')) != NULL)
+ {
+ *tms = '\0';
+ ((char*)(&Nip))[i] = (unsigned char)atoi(tst);
+ tst = tms + 1;
+ if(i < 3) *tms = '.';
+ }
+ else break;
+ }
+ }
+ if(Nip == 0) Nip = 1;
+
+#if ACTIVITY_LOGGING_SUPPORT
+ // user activity logging
+ DWORD hostcnt, hitcnt;
+ RegisterActivityFrom(Nip, hitcnt, hostcnt);
+#endif
+
+#if _DEBUG_ == 1
+ // print2log("Entering from : %s, deal=%s", Cip, deal);
+#endif
+
+ strcat(deal,"&");
+
+ /************ get user info from session ************/
+ {
+ DWORD tmp[2];
+ if(strlen(cookie_seq) == 16 &&
+ ConvertHex(cookie_seq, (char*)&tmp) == 8)
+ {
+ tmp[0] = ntohl(tmp[0]); // use network order due printf()
+ tmp[1] = ntohl(tmp[1]);
+ // if session code not zero let's open session
+ if(tmp[0] != 0 && tmp[1] != 0)
+ {
+ // try to open sequence
+ if(ULogin.CheckSession(tmp, Nip, 0))
+ strcpy(cookie_name, ULogin.pui->username);
+ }
+ }
+ }
+
+ //
+ // 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, "<OPTION VALUE=\"?index=%d\"%s>%s</OPTION>\n", Topics_List_map[i]+1, sel, Topics_List[Topics_List_map[i]]);
+ strcat(topicselect, tmp);
+ }
+ strcat(topicselect, "</SELECT>");
+ }
+#endif
+
+ // moved to PrintTopStaticLinks //printf("<TR><TD class=cl> </TD></TR>");
+
+ // print info about personal messages
+ if(ULogin.LU.ID[0] != 0 && ULogin.pui->persmescnt - ULogin.pui->readpersmescnt > 0) {
+ sprintf( privmesinfo, ", <A HREF=\"" MY_CGI_URL "?persmsg\" STYLE=\"text-decoration:underline;\"><FONT COLOR=RED>" MESSAGEMAIN_privatemsg_newmsgann " %ld " \
+ MESSAGEMAIN_privatemsg_newmsgann1 "</FONT></A>", (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, "<A HREF=\"" MY_CGI_URL "?ganndel=%d\" "
+ "STYLE=\"text-decoration:underline;\">" MESSAGEMAIN_globann_delannounce
+ "</A> <A HREF=\"" MY_CGI_URL "?globann=%d\" "
+ "STYLE=\"text-decoration:underline;\">" MESSAGEMAIN_globann_updannounce
+ "</A>", ga[i].Number, ga[i].Number);
+ }
+ else del[0] = 0;
+
+ ConvertTime(ga[i].Date, date);
+
+ if(!something_printed) {
+ if(!formstarted) printf("<BR>");
+ else printf("</FORM>");
+ }
+
+ 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("<CENTER><A HREF=\"?rann=%d\" STYLE=\"text-decoration:underline;\" class=cl>" MESSAGEMAIN_globann_hidenewann "</A></CENTER><BR>", ga[cnt-1].Number);
+ }
+ else {
+ // show all announces
+ printf("<CENTER><A HREF=\"?rann=0\" STYLE=\"text-decoration:underline;\" class=cl>" MESSAGEMAIN_globann_showall "(%d)</A></CENTER><BR>", cnt);
+ // gap between welcome header and messages
+ if(formstarted) printf("</FORM>");
+ else printf(DESIGN_INDEX_WELCOME_CLOSE);
+ }
+ }
+ else {
+ // gap between welcome header and messages
+ if(formstarted) printf("</FORM>");
+ 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<<i);
+ }
+ free(ss);
+ }
+ }
+ }
+#endif
+
+ //
+ // saving values - profile or cookie way
+ //
+
+ if((ULogin.LU.ID[0] != 0) && (ULogin.pui->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("<CENTER>" 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("<BR>");
+ if(i != start - 1) printf(" <A HREF=\"?searchword=%s&start=%d\">%d</A> ", wrd, i+1, i+1);
+ else printf("<BOLD> %d </BOLD>", i+1);
+ }
+ printf("</CENTER>");
+ }
+ }
+
+ 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("<BR><CENTER>" 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("<BR>");
+ if(i != start - 1) printf(" <A HREF=\"?searchword=%s&start=%d\">%d</A> ", wrd, i+1, i+1);
+ else printf("<BOLD> %d </BOLD>", i+1);
+ }
+ printf("</CENTER>");
+ }
+ }
+ }
+ 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("<CENTER>" 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("<BR>");
+ if(i != 0) printf(" <A HREF=\"?searchword=%s&start=%d\">%d</A> ", wrd, i+1, i+1);
+ else printf("<BOLD> %d </BOLD>", i+1);
+ }
+ printf("</CENTER>");
+ }
+ }
+ 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("<BR><CENTER>" 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("<BR>");
+ if(i != 0) printf(" <A HREF=\"?searchword=%s&start=%d\">%d</A> ", wrd, i+1, i+1);
+ else printf("<BOLD> %d </BOLD>", i+1);
+ }
+ printf("</CENTER>");
+ }
+ }
+ }
+ 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<<i);
+ }
+ free(ss);
+ }
+ }
+ }
+
+ //
+ // Update the user
+ //
+ int updated = 0;
+ if(name) {
+ CProfiles *uprof;
+ SProfile_UserInfo ui;
+ SProfile_FullUserInfo fui;
+ DWORD err = 0;
+ DWORD idx;
+
+ uprof = new CProfiles();
+ err = uprof->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 "<BR>", 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("<P><CENTER><LI> <FONT COLOR=RED><BOLD>" MESSAGEMAIN_privatemsg_disable_pmsg "</BOLD></FONT></CENTER>");
+ }
+ else {
+ if(!nameok)
+ printf("<P><CENTER><LI> <FONT COLOR=RED>" MESSAGEMAIN_privatemsg_invalid_user "</FONT></CENTER>");
+ if(!bodyok)
+ printf("<P><CENTER><LI> <FONT COLOR=RED>" MESSAGEMAIN_privatemsg_invalid_body "</FONT></CENTER>");
+ if(tolong)
+ printf("<P><CENTER><LI> <FONT COLOR=RED>" MESSAGEMAIN_privatemsg_tolong_body "</FONT></CENTER>");
+ }
+
+ 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("<BR><BR><CENTER><B>" MESSAGEMAIN_privatemsg_header " %s</B><BR>", uuname);
+ if((ULogin.pui->Flags & PROFILES_FLAG_PERSMSGDISABLED))
+ printf("<U>" MESSAGEMAIN_privatemsg_disabled "</U><BR>");
+
+ 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<BR>"
+ "<A HREF=\"" MY_CGI_URL "?persmsgform\" STYLE=\"text-decoration:underline;\">" MESSAGEMAIN_privatemsg_writenewmsg
+ "</A></CENTER><P><P>", 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 <A HREF=\"" MY_CGI_URL "?persmsgform=%s\" STYLE=\"text-decoration:underline;\">" MESSAGEMAIN_privatemsg_answer "</A> %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("<P><CENTER><LI> <FONT COLOR=RED>" MESSAGEMAIN_globann_tolong "</FONT></CENTER>");
+
+ 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("<BR><BR><CENTER><B>%s</B></CENTER>", 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("<P><CENTER><LI> <FONT COLOR=RED>" MESSAGEMAIN_globann_toshort "</FONT></CENTER>");
+
+ 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("<P><CENTER><P><B>%s</B><BR></CENTER>", MESSAGEHEAD_favourites);
+
+ int updated;
+ if( (num = DB.PrintandCheckMessageFavsExistandInv(ULogin.pui,
+ ULogin.LU.right & USERRIGHT_SUPERUSER, &updated)) == 0)
+ printf("<P><CENTER><B>" MESSAGEMAIN_favourites_listclear "</B></CENTER><P>");
+ 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("<BR><BR><center>");
+ printf(
+ "<font color=\"red\">%s</font><br>\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("<br>");
+ 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<uc;)
+ if(fDelete) {
+ printf(
+ "<br /> <b>єфрыхэю %d шч %d яюы№чютрЄхыхщ</b> \n",
+ ii,
+ uc);
+ } else {
+ printf(
+ "<br /> <b>┴єфхЄ єфрыхэю <fonc color=red>%d</font> шч %d яюы№чютрЄхыхщ</b> \n",
+ ii,
+ uc);
+ printf(
+ "<br /><a href=\"" MY_CGI_URL "?cluserlist=yes\">"
+ "<font color=\"red\">╧ЁюфюыцшЄ№ ?</font></a>");
+ }
+ }//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
+/***************************************************************************
+ 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
+ /***************************************************************************
+ messages.h - ┬ёх ёююс∙хэш ъюэЇхЁхэЎшш
+ -------------------
+ begin : Fri Mar 23 2001
+ яхЁхтюф : └ыхъёрэфЁ ├ы ъют <vektor@3ka.mipt.ru>
+ 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 "╧ЁютхЁ№Єх яЁртшы№эюёЄ№ эряшёрэш ярЁюы ш шьхэш<BR>┼ёыш ┬√ їюЄшЄх юЄяЁртшЄ№ ёююс∙хэшх эх ЁхухёЄЁшЁє ё№ т ъюэЇхЁхэЎшш яюяЁюсєщЄх єърчрЄ№ фЁєуюх эх чрэ Єюх шь "
+
+#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 "╧ЁютхЁ№Єх, тю°ыш ыш т√ т ъюэЇхЁхэЎш■<BR>┼ёыш ┬√ ёўшЄрхЄх, ўЄю ¤Єю ю°шсър - юсЁрЄшЄхё№ ъ ьюфхЁрЄюЁрь ъюэЇхЁхэЎшш"
+
+#define MESSAGEMAIN_spamtry "┴ыюъшЁютър яюя√Єъш ёярьр шыш чр∙шЄр юЄ яютЄюЁэющ юЄяЁртъш"
+#define MESSAGEMAIN_spamtry2 "┼ёыш ┬√ я√ЄрхЄхё№ юЄяЁртшЄ№ ёююс∙хэшх, Єю ¤Єю чэрўшЄ, ўЄю юэю єцх юЄяЁртыхэю ш трь эхчрўхь фхырЄ№ ¤Єю х∙х Ёрч"
+
+#define MESSAGEMAIN_BANNED_REASON "╧Ёшўшэр чряЁхЄр фюсртыхэш ёююс∙хэшщ фы ┬рё с√ыр :"
+
+#define MESSAGEMAIN_browser_return "<P ALIGN=CENTER>┬р° сЁюєчхЁ фюыцхэ тхЁэєЄ№ трё ъ ёяшёъє ёююс∙хэшщ ўхЁхч эхёъюы№ъю ёхъєэф</P>"
+
+#define MESSAGEMAIN_browser_to_thread "<P><P ALIGN=CENTER><B><A STYLE=\"text-decoration:underline;\" HREF=\"" MY_CGI_URL "?read=%d\">┬хЁэєЄ№ё </A> ъ ётюхьє ёююс∙хэш■</B></P></P><P></P>"
+
+#define MESSAGEMAIN_admin_contact "┼ёыш ┬√ ёўшЄрхЄх ўЄю ¤Єю эхяЁртшы№эю, юсЁрЄшЄхё№ ъ <A HREF=\"mailto:" ADMIN_MAIL "\">└фьшэшёЄЁрЄюЁє</A> ъюэЇхЁхэЎшш"
+
+/***************** ╘юЁьр юЄяЁртъш ёююс∙хэшщ ******************/
+#define MESSAGEMAIN_post_newmessage "═ютюх ёююс∙хэшх"
+#define MESSAGEMAIN_post_replymessage "╬ЄтхЄшЄ№"
+#define MESSAGEMAIN_post_editmessage "╚чьхэшЄ№ ёююс∙хэшх"
+
+#define MESSAGEMAIN_post_you_name "<b>╚ь :</b>"
+#define MESSAGEMAIN_post_your_password "<b>╧рЁюы№:</b>"
+#define MESSAGEMAIN_post_login_me "<b>└тЄюыюушэ</b>"
+#define MESSAGEMAIN_post_hostname "<b>Host:</b>"
+#define MESSAGEMAIN_post_message_subject "<b>╥хьр:</b>"
+#define MESSAGEMAIN_post_message_body "<b>╤ююс∙хэшх:</b> <FONT class=cl>(<A HREF=\"" MY_CGI_URL \
+ "?help\" STYLE=\"text-decoration:underline;\" target=_blank>╩ръ фюсртшЄ№ ЇюЁьрЄшЁютрэшх, ърЁЄшэъш, ш Є.ф. т тр°х ёююс∙хэшх</A>)</FONT>"
+
+#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 "─ы шчьхэхэш яЁюЇрщыр ┬√ <U>фюыцэ√</U> єърчрЄ№ ┬р° ярЁюы№ !"
+#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 рфЁхё <BR>(юэ сєфхЄ шёяюы№чютрЄ№ё фы яюыєўхэш ярЁюы ш ётюфюъ яю ъюэЇхЁхэЎшш)"
+#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 "┼ёыш ┬√ їюЄшЄх ёюсёЄтхээє■ яюфяшё№ (сєфхЄ яю ты Є№ё т" \
+ " эют√ї ёююс∙хэш ї яю єьюыўрэш■,<BR>ш эх ьюцхЄ с√Є№ фышээхх 255 ёшьтюыют), ттхфшЄх хх чфхё№," \
+ " шыш юёЄрт№Єх яюых яєёЄ√ь"
+#define MESSAGEMAIN_register_selectedusers "┬√сЁрэ√х яюы№чютрЄхыш, ёююс∙хэш ъюЄюЁ√ї сєфєЄ яюфётхўштрЄ№ё <BR>" \
+ "(ърцфюх шь яш°хЄё эр эютющ ёЄЁюъх, ьръёшьры№эю ьюцэю ттхёЄш 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 "<FONT COLOR=#FF0000>╠юфхЁрЄюЁ</FONT>"
+#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 "<P></P><CENTER>╧юы№чютрЄхы№ %s эх чрЁхушёЄЁшЁютрэ т ¤Єющ ъюэЇхЁхэЎшш</CENTER>"
+
+#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 "╤хёёш чръЁ√Єр<BR>"
+#define MESSAGEMAIN_session_closed_ok2 "╤ярёшсю чр єўрёЄшх!"
+#define MESSAGEMAIN_session_closed_no "╤хёёш эх чръЁ√Єр<BR>"
+#define MESSAGEMAIN_session_check_failed "╤хёёш эх эрщфхэр<BR>┬ючьюцэю, юэр с√ыр Єюы№ъю ўЄю чръЁ√Єр"
+#define MESSAGEMAIN_session_close_failed "╬°шсър яЁш чръЁ√Єшш ёхёёшш<BR>"
+#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 "─рээр тючьюцэюёЄ№ эхфюёЄєяэр эхчрЁхушёЄЁшЁютрээ√ь яюы№чютрЄхы ь !<BR>"
+#define MESSAGEMAIN_privatemsg_denyunreg2 "─ы Єюую ўЄюс шьхЄ№ тючьюцэюёЄ№ юЄяЁрты Є№ ш яюыєўрЄ№ яхЁёюэры№эюх ёююс∙хэшх ┬√ фюыцэ√ чрЁхушёЄЁшЁютрЄ№ё т ъюэЇхЁхэЎшш !<BR><BR>"
+
+#define MESSAGEMAIN_privatemsg_invalid_user "┬√ фюыцэ√ єърчрЄ№ ёє∙хёЄтє■∙шщ эшъ яюы№чютрЄхы "
+#define MESSAGEMAIN_privatemsg_invalid_body "╤ююс∙хэшх эх ьюцхЄ с√Є№ яєёЄюх (шэрўх ъръющ ёь√ёы хую яюё√ырЄ№ ?)"
+#define MESSAGEMAIN_privatemsg_tolong_body "╤ююс∙хэшх ёыш°ъюь фышээюх, єьхэ№°шЄх хую фышэє"
+#define MESSAGEMAIN_privatemsg_disable_pmsg "╧юы№чютрЄхы№ чряЁхЄшы яюыєўхэшх яхЁёюэры№э√ї ёююс∙хэшщ,<BR>юЄяЁртшЄ№ хьє яхЁёюэры№эюх ёююс∙хэшх эхтючьюцэю"
+
+#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 "<font color=red>[ ═ютюх !]</font>"
+
+#define MESSAGEMAIN_privatemsg_answer "[╬ЄтхЄшЄ№]"
+
+#define MESSAGEMAIN_privatemsg_fromuser "╬Є яюы№чютрЄхы :"
+#define MESSAGEMAIN_privatemsg_touser "╧юы№чютрЄхы■:"
+#define MESSAGEMAIN_privatemsg_date "╬ЄяЁртыхэю:"
+
+/***************** favourites system *****************/
+#define MESSAGEMAIN_favourites_denyunreg "─рээр тючьюцэюёЄ№ эхфюёЄєяэр эхчрЁхушёЄЁшЁютрээ√ь яюы№чютрЄхы ь !<BR>"
+#define MESSAGEMAIN_favourites_denyunreg2 "─ы Єюую, ўЄюс√ шьхЄ№ тючьюцэюёЄ№ їЁрэшЄ№ ёё√ыъш эр шчсЁрээ√х ёююс∙хэш , ┬√ фюыцэ√ чрЁхушёЄЁшЁютрЄ№ё ш тющЄш т ъюэЇхЁхэЎш■ !<BR><BR>"
+
+#define MESSAGEMAIN_favourites_listclear "┬р° ёяшёюъ шчсЁрээюую яєёЄ"
+
+#if USER_FAVOURITES_SUPPORT == 1
+#define MESSAGEMAIN_favourites_added "╤ююс∙хэшх чрэхёхэю т ╚чсЁрээюх!<BR>"
+#define MESSAGEMAIN_favourites_added2 "╤ярёшсю чр єўрёЄшх !<BR>╥хяхЁ№ ёё√ыъє эр ¤Єю ёююс∙хэшх ьюцэю эрщЄш т ёяшёъх<BR>"
+#define MESSAGEMAIN_favourites_addno "╤ююс∙хэшх эх чрэхёхэю т ╚чсЁрээюх!<BR>"
+#define MESSAGEMAIN_favourites_addexist "╤ююс∙хэшх єцх яЁшёєЄёЄтєхЄ т ёяшёъх!<BR>┬ючьюцэю, ┬√ Єюы№ъю ўЄю хую фюсртшыш ш я√ЄрхЄхё№ ёфхырЄ№ ¤Єю х∙х Ёрч<BR>"
+#define MESSAGEMAIN_favourites_addnoplace "╙ ┬рё єцх ёюїЁрэхэю 20 ёююс∙хэшщ!<BR>─ы Єюую, ўЄюс√ фюсртшЄ№ ¤Єю ёююс∙хэшх, эхюсїюфшью єфрышЄ№ їюЄ с√ юфэю шч єцх ёюїЁрэхээ√ї<BR>"
+#define MESSAGEMAIN_favourites_deleted "╤ююс∙хэшх єфрыхэю шч ╚чсЁрээюую!<BR>"
+#define MESSAGEMAIN_favourites_deleted2 "╤ярёшсю чр єўрёЄшх !<BR><BR>"
+#define MESSAGEMAIN_favourites_delno "╤ююс∙хэшх эх єфрыхэю шч ╚чсЁрээюую!<BR>"
+#define MESSAGEMAIN_favourites_delnoexist "╤ююс∙хэш эхЄ т ёяшёъх !<BR> ┬ючьюцэю, ┬√ Єюы№ъю ўЄю хую єфрышыш<BR>"
+#else
+#define MESSAGEMAIN_favourites_added "╧юЄюъ чрэхёхэ т ╚чсЁрээюх!<BR>"
+#define MESSAGEMAIN_favourites_added2 "╤ярёшсю чр єўрёЄшх !<BR>╥хяхЁ№ ёё√ыъє эр ¤ЄюЄ яюЄюъ ьюцэю эрщЄш т ёяшёъх<BR>"
+#define MESSAGEMAIN_favourites_addno "╧юЄюъ эх чрэхёхэ т ╚чсЁрээюх!<BR>"
+#define MESSAGEMAIN_favourites_addexist "╧юЄюъ єцх яЁшёєЄёЄтєхЄ т ёяшёъх!<BR>┬ючьюцэю, ┬√ Єюы№ъю ўЄю хую фюсртшыш<BR>"
+#define MESSAGEMAIN_favourites_addnoplace "╙ ┬рё єцх ёюїЁрэхэю 20 яюЄюъют!<BR>─ы Єюую, ўЄюс√ фюсртшЄ№ ¤ЄюЄ ЄЁхф, эхюсїюфшью єфрышЄ№ їюЄ с√ юфшэ шч єцх ёюїЁрэхээ√ї<BR>"
+#define MESSAGEMAIN_favourites_deleted "╧юЄюъ єфрыхэ шч ╚чсЁрээюую!<BR>"
+#define MESSAGEMAIN_favourites_deleted2 "╤ярёшсю чр єўрёЄшх !<BR><BR>"
+#define MESSAGEMAIN_favourites_delno "╧юЄюъ эх єфрыхэ шч ╚чсЁрээюую!<BR>"
+#define MESSAGEMAIN_favourites_delnoexist "╧юЄюър эхЄ т ёяшёъх !<BR> ┬ючьюцэю, ┬√ Єюы№ъю ўЄю хую єфрышыш<BR>"
+#define MESSAGEMAIN_favourites_addnoparent "╤ююс∙хэшх эх ты хЄё яхЁт√ь фы фрээюую яюЄюър!<BR>─юсрты Є№ ьюцэю Єюы№ъю яхЁт√х ёююс∙хэш т ЄЁхфх"
+#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 "<BR>"
+
+#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 "<CENTER>┼ёыш ┬√ чрс√ыш ┬р° ярЁюы№ <A HREF=\"" MY_CGI_URL "?login=lostpasswform\">ъышъэшЄх ЄєЄ</A></CENTER><BR><BR>"
+
+/**************** ╘юЁьр "чрс√ыш ярЁюы№" ****************/
+#define MESSAGEMAIN_lostpassw_header "<BIG>╤шёЄхьр эряюьшэрэш ярЁюы </BIG><BR><BR>┬тхфшЄх ┬р° эшъ ш рфЁхё ¤ыхъЄЁюээющ яюўЄ√<BR>" \
+ "ш ┬√ яюыєўшЄх яшё№ью ё тр°шь ярЁюыхь"
+#define MESSAGEMAIN_lostpassw_hretry "<BOLD><FONT COLOR=RED>┬√ єърчрыш эхтхЁэ√щ эшъ ш/шыш рфЁхё ¤ыхъЄЁюээющ яюўЄ√</FONT></BOLD><BR>" \
+ "╧юцрыєщёЄр, яЁютхЁ№Єх ┬р° эшъ ш email ш яютЄюЁшЄх яюя√Єъє х∙х Ёрч"
+#define MESSAGEMAIN_lostpassw_loginname " ═шъ : "
+#define MESSAGEMAIN_lostpassw_email " Email : "
+#define MESSAGEMAIN_lostpassw_getpassw "╧юыєўшЄ№ ярЁюы№"
+
+/****************** search form ******************/
+#define MESSAGEMAIN_search_searchmsg "╚ёърЄ№ ёююс∙хэш "
+
+#define MESSAGEMAIN_search_howtouse "┬тхфхэшх т яЁртшыр шёяюы№чютрэш яюшёър.<BR>╧юшёъ тхфхЄё яю <U><B>ўрёЄшўэ√ь</B></U> ъєёърь ёыют <B>(эх ьхэ№°х ЄЁхї ёшьтюыют!)</B> ёюфхЁцр∙шьё т " \
+ "<U>Єхых</U> шыш <U>чруюыютъх</U> ёююс∙хэш .<BR>╤ыютр т ёЄЁюъх яюшёър ьюцэю Ёрчфхы Є№ яЁюсхырьш, ўЄю чэрўшЄ шёърЄ№" \
+ " ёююс∙хэш ёюфхЁцр∙шх тёх Єръшх яюфёЄЁюъш.<BR>═р фрээюь ёхЁтхЁх яюшёъ ьюцхЄ чрэ Є№ юЄ 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 "ёютярфхэшщ эрщфхэю <EM>(┴єфхЄ яюърчрэю 100 эр ёЄЁрэшЎє)</EM>"
+#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 "<U><I><SMALL>╧юы№чютрЄхы№ шьххЄ яюфяшё№, эю юЄюсЁрцхэшх яюфяшёхщ чряЁх∙хэю т эрёЄЁющърї.</SMALL></I></U>"
+#define MESSAGEMAIN_in_this_thread "<CENTER><BIG>╤ююс∙хэш т ¤Єюь яюЄюъх</BIG></CENTER>"
+
+/********************** 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 "╚чьхэшЄ№ ёяюёюс їЁрэхэш эрёЄЁюхъ ьюцэю эр <a href=\""MY_CGI_URL"?register=form\" style=\"text-decoration:underline;\" >ёЄЁрэшЎх ЁхфръЄшЁютрэш яЁюЇрщыр</a>"
+
+// 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 "<B>┬їюф:</B> "//"<U><B>┬ёхыхэёъюх ╟╦╬:</B></U> " // :))) // namek ponyat :)
+//#define ZLO ""
+
+#define MESSAGEMAIN_ACTIVITY_STATVIEW "└ъЄштэюёЄ№: <B><FONT COLOR=BLUE>%ld</FONT> <FONT COLOR=#229911>%ld</FONT></B>" \
+ " чр яюёыхфэшх 10 ьшэєЄ"
+#define MESSAGEMAIN_WELCOME_LOGGEDSTART "<table class=cl><tr><td><font class=cl> " \
+ WELCOME_CONFERENCE_HEADER MESSAGEMAIN_WELCOME_HELLOREG "<FONT COLOR=BLUE>%s</FONT>%s<BR>%s%s</td>" \
+ "<td align=right class=cl>%s<BR>" MESSAGEMAIN_WELCOME_SELECTTOPIC " %s</font></td></tr></table>"
+
+#define MESSAGEMAIN_WELCOME_START "<table class=cl><tr><td>"\
+ "<form method=post action=\""MY_CGI_URL "?login=action\">"\
+ "<font class=cl> " WELCOME_CONFERENCE_HEADER MESSAGEMAIN_login_loginname \
+ "<INPUT TYPE=TEXT NAME=\"mname\" class=cl SIZE=15 " \
+ "MAXLENGTH=%d VALUE=\"%s\"> " MESSAGEMAIN_login_password \
+ "<INPUT TYPE=PASSWORD NAME=\"mpswd\" SIZE=15 class=cl MAXLENGTH=%d> "\
+ "<INPUT TYPE=CHECKBOX NAME=\"ipoff\" class=cl VALUE=1>" MESSAGEMAIN_login_ipcheckshort \
+ " <INPUT TYPE=SUBMIT class=cl VALUE=\"Enter\"></font><BR>%s%s</td>" \
+ "<td align=right class=cl>%s<BR>" MESSAGEMAIN_WELCOME_SELECTTOPIC " %s</font></td></tr></table>"
+
+#define MESSAGEMAIN_WELCOME_HELLOREG "┬√ тю°ыш т ъюэЇхЁхэЎш■ ъръ "
+#define MESSAGEMAIN_WELCOME_SELECTTOPIC "┬√схЁшЄх Єхьє:"
+
+#define MESSAGEMAIN_WELCOME_NEWTHREADS_TEXT "эют√ї яюЄюъют(ёююс∙хэшщ): %ld(%ld) шч %ld"
+#define MESSAGEMAIN_WELCOME_NEWTHREADS "<span id=\"new_count\">"\
+ MESSAGEMAIN_WELCOME_NEWTHREADS_TEXT"</span>"
+
+#define MESSAGEMAIN_WELCOME_NONEWTHREADS_TEXT "эют√ї ёююс∙хэшщ эхЄ, тёхую %ld"
+#define MESSAGEMAIN_WELCOME_NONEWTHREADS "<span id=\"new_count\">"\
+ MESSAGEMAIN_WELCOME_NONEWTHREADS_TEXT"</span>"
+
+
+#define MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT_NEW "<script>update_counter('new_count','"MESSAGEMAIN_WELCOME_NEWTHREADS_TEXT"');</script>"
+#define MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT_NO_NEW "<script>update_counter('new_count','"MESSAGEMAIN_WELCOME_NONEWTHREADS_TEXT"');</script>"
+
+#define MESSAGEMAIN_WELCOME_NEWCOUNT_SCRIPT "<script>"\
+ "function update_counter(id, value){"\
+ "if (document.getElementById){"\
+ "el = document.getElementById(id);"\
+ "if(document.all) el.innerHTML = value;"\
+ "else{"\
+ "rng = document.createRange();"\
+ "rng.setStartBefore(el);"\
+ "htmlFrag = rng.createContextualFragment(value);"\
+ "while (el.hasChildNodes()) el.removeChild(el.lastChild);"\
+ "el.appendChild(htmlFrag);"\
+ "}}}</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 "<HTML>╟фЁртёЄтєщЄх, <bold><font color=#009000>"\
+ "<strong>%s</strong></font></bold>.<br />"
+
+#define MAIL_SEND_SIGNING "▌Єю яшё№ью яюёырэю ртЄюьрЄшўхёъш ЇюЁєьюь "WWWCONF_FULL_NAME \
+ ".<br />┬рь <b>эх</b> ёыхфєхЄ юЄтхўрЄ№ эр эхую.<br /></HTML>"
+
+// reply notification
+#define MAILACKN_REPLY_SUBJECT WWWCONF_FULL_NAME ": %s"
+#define MAILACKN_REPLY_BODY MAIL_SEND_GREETING \
+"%s юЄтхЄшы эр тр°х ёююс∙хэшх <strong>%s</strong>.<br /><br />"\
+"╥хьр юЄтхЄр:<strong> %s</strong><br />"\
+"----------- ╤ююс∙хэшх ---------<br />%s<br />-------------------------------<br /><br />"\
+"┬хё№ ЄЁхф ьюцэю єтшфхЄ№ <a href=\"" MA_READURL "?read=%d\">чфхё№</A><br /><br />"
+
+// password recovery
+#define MAILACKN_LOSTPASS_SUBJECT WWWCONF_FULL_NAME ": ярЁюы№ фы яЁюЇшы %s"
+#define MAILACKN_LOSTPASS_BODY MAIL_SEND_GREETING \
+"╥хъє∙шщ ярЁюы№ фы тр°хую яЁюЇшы : %s<br /><br /><br />"
+
+
+// private message
+#define MAILACKN_PRIVATEMSG_SUBJECT WWWCONF_FULL_NAME ": эютюх ышўэюх ёююс∙хэшх юЄ %s"
+#define MAILACKN_PRIVATEMSG_BODY MAIL_SEND_GREETING \
+"─ы ┬рё яюыєўхэю эютюх ышўэюх ёююс∙хэшх юЄ <strong>%s</strong>.<br /><br />"\
+"----------- ╤ююс∙хэшх ---------<br />%s<br />-------------------------------<br /><br />"\
+"╬ЄтхЄшЄ№ эр эхую ьюцэю <a href=\"" MA_READURL "?persmsgform=%s\">чфхё№</a><br />" \
+"╧юёьюЄЁхЄ№ юёЄры№э√х ышўэ√х ёююс∙хэш ┬√ ьюцхЄх <a href=\"" MA_READURL "?persmsg\">чфхё№</A><br /><br />"
+
+
+
+/**************************** mailing messeges ***************************/
+/*#define MAILACKN_SUBJECT WWWCONF_FULL_NAME ": %s"
+#define MAILACKN_MAINBODY_FORMAT "Content-type: text/html; charset=\"windows-1251\"\n<HTML>" \
+"╟фЁртёЄтєщЄх, <BOLD><FONT COLOR=#009000><STRONG>%s</STRONG></FONT></BOLD>.<BR> %s юЄтхЄшы эр тр°х ёююс∙хэшх <STRONG>%s</STRONG>." \
+"<BR><BR>╥хьр юЄтхЄр:<STRONG> %s</STRONG>\n<BR>----------- ╤ююс∙хэшх ---------<BR>%s<BR>-------------------------------" \
+"<BR><BR>┬хё№ ЄЁхф ьюцэю єтшфхЄ№ <A HREF=" WC_EMAILACN_READURL "?read=%d>чфхё№</A>" \
+"<BR><BR>This mail was generated automatically by mailing engine" \
+" of " WWWCONF_FULL_NAME ".<BR>You <B>SHOULD NOT REPLY</B> to this message.<BR></HTML>"
+*/
+// password recovery
+/*#define MAILLOSTPASSW_SUBJECT WWWCONF_FULL_NAME ": ярЁюы№ фы яЁюЇшы %s"
+#define MAILLOSTPASSW_MAINBODY_FORMAT "Content-type: text/html; charset=\"windows-1251\"\n<HTML>" \
+"╟фЁртёЄтєщЄх, <BOLD><FONT COLOR=#009000><STRONG>%s</STRONG></FONT></BOLD>.<BR>╥хъє∙шщ ярЁюы№ фы тр°хую яЁюЇшы : %s<BR>" \
+"<BR><BR>This mail was generated automatically by mailing engine" \
+" of " WWWCONF_FULL_NAME ".<BR>You <B>SHOULD NOT REPLY</B> to this message.<BR></HTML>"
+
+#define MAILACKN_PRIVATEMSG_SUBJECT WWWCONF_FULL_NAME ": эютюх ышўэюх ёююс∙хэшх юЄ %s"
+#define MAILACKN_PRIVATEMSG_MAINBODY_FORMAT "Content-type: text/html; charset=\"windows-1251\"\n<HTML>" \
+"╟фЁртёЄтєщЄх, <BOLD><FONT COLOR=#009000><STRONG>%s</STRONG></FONT></BOLD>.<BR> фы ┬рё яюыєўхэю эютюх ышўэюх ёююс∙хэшх юЄ <STRONG>%s</STRONG>." \
+"<BR><BR>----------- ╤ююс∙хэшх ---------<BR>%s<BR>-------------------------------" \
+"<BR><BR>╬ЄтхЄшЄ№ эр эхую ьюцэю <A HREF=" WC_EMAILACN_READURL "?persmsgform=%s>чфхё№</A><BR>" \
+"╧юёьюЄЁхЄ№ юёЄры№э√х ышўэ√х ёююс∙хэш ┬√ ьюцхЄх <A HREF=" WC_EMAILACN_READURL "?persmsg>чфхё№</A>" \
+"<BR><BR>This mail was generated automatically by mailing engine" \
+" of " WWWCONF_FULL_NAME ".<BR>You <B>SHOULD NOT REPLY</B> to this message.<BR></HTML>"
+*/
+
+/**************************** 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<BR><table width=100%% cellpadding=1 cellspacing=1 border=1 bgcolor=#E1E1E1><TR><TD>%s</TD><TD>QUERY_STRING=%s</TD></TR></TABLE>"
+#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 " <FONT COLOR=BLACK>(-)</FONT>"
+#define TAG_MSG_HAVE_PIC " (pic)"
+#define TAG_MSG_HAVE_URL " (url)"
+#define TAG_MSG_CLOSED_THREAD "<EM><SMALL><font color=#900000>(чръЁ√Єю) </font></EM></SMALL>"
+#define TAG_MSG_ROLLED_THREAD "<EM><font color=#900000>CтхЁэєЄю: </font></EM>"
+#define TAG_ONLYHEADERS_POSTCNT "%s%s<EM>(юЄтхЄют: <b>%d</b>)</EM>%s"
+#define TAG_ONLYHEADERS_POSTCNT_MARKNEW "%s%s<EM>(юЄтхЄют: <b>%d</b>, эют√ї: <b>%d</b>," \
+ " яюёыхфэшщ юЄтхЄ: <A STYLE=\"text-decoration:underline;\" " \
+ "HREF=%s?read=%ld>юЄ %s, %s</A>)</EM>%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 "<A NAME=\"n%d\" HREF=\"#n%d\"><EM class=e>+ </EM></A>"
+#define TAG_NEW_MSG_MARK "<EM class=e>+ </EM>"
+
+/*********************** Topics **************************/
+#define DESIGN_TOPIC_TAG_OPEN "["
+#define DESIGN_TOPIC_TAG_CLOSE "]"
+#define DESIGN_TOPIC_DIVIDER " "
+
+/***************** nick name information *****************/
+#define DESIGN_REGISTRED_NICK "<b>%s</b>"
+#define DESIGN_REGISTRED_OWN_NICK "<b><font color=red>%s</font></b>"
+#define DESIGN_SELECTEDUSER_NICK "<b><font color=#FF9900>%s</font></b>"
+#define DESIGN_UNREGISTRED_NICK "<b>%s</b>"
+
+/********************** favorites ************************/
+#define DESIGN_FAVORITES_DEL_THREAD "<FONT COLOR=RED SIZE=3>[X]</FONT>"
+#define DESIGN_FAVORITES_ADD_THREAD "<FONT COLOR=GREEN SIZE=3>[+]</FONT>"
+
+#define DESIGN_THREADS_DIVIDER_IMG ""
+#define DESIGN_THREADS_DIVIDER_HR "\n<HR size=1>"
+#define DESIGN_THREADS_DIVIDER_grey "#E9E9E9"
+extern char DESIGN_threads_divider[500];
+
+#define DESIGN_OP_DL "<DL><DD>"
+#define DESIGN_CL_DL "</DL>"
+#define DESIGN_OP_DIV "<DIV>"
+#define DESIGN_OP_DIV_grey "<DIV class=g>"
+#define DESIGN_OP_DIV_white "<DIV class=w>"
+#define DESIGN_CL_DIV "</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 "<BR>"
+#define DESIGN_DD "<DD>"
+extern char DESIGN_break[10];
+
+#define DESIGN_BUTTONS_DIVIDER " "
+
+#define DESIGN_GLOBAL_BOARD_MESSAGE "<P ALIGN=CENTER><BIG><STRONG>%s</STRONG></BIG><BR><BR>%s"
+
+#define DESIGN_VIEW_THREAD_BODY "<br /><div class=\"body\">%s</div>"
+#define DESIGN_VIEW_THREAD_SIGN "<br /><div class=\"sign\">%s</div>"
+#define DESIGN_VIEW_THREAD_MSG_HEADER "<BR><DIV ALIGN=CENTER>"
+// meesage was sent by NIK
+#define DESIGN_VIEW_THREAD_MSG_SENT "<BR>%s %s "
+#define DESIGN_VIEW_THREAD_MSG_SENT1 "<<A HREF=\"mailto:%s\">%s</A>> "
+#define DESIGN_VIEW_THREAD_MSG_SENT2 "<small>(%s)</small>"
+#define DESIGN_VIEW_THREAD_MSG_SENT3 "</DIV><BR>"
+// topic when reading
+#define DESIGN_VIEW_THREAD_TOPIC "<BIG>[%s]</BIG> "
+//date
+#define DESIGN_VIEW_THREAD_DATE "<BR>%s %s"
+#define DESIGN_VIEW_THREAD_MDATE "<I>(%s %s)</I>"
+
+#define DESIGN_INDEX_WELCOME_STRING "<P ALIGN=CENTER> %s <big>%s</big>!"
+#define DESIGN_INDEX_WELCOME_STRING1 " %s %ld %s, тёхую %d"
+#define DESIGN_INDEX_WELCOME_CLOSE "</P>"
+
+#define DESIGN_POST_NEW_MESSAGE_TABLE "<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3>"
+
+#define DESIGN_PREVIEW_PREVIEWMESSAGE "<P ALIGN=CENTER><STRONG>%s</STRONG>"
+#define DESIGN_PREVIEW_CHANGEMESSAGE "<P ALIGN=CENTER><STRONG>%s</STRONG>"
+
+#define DESIGN_BAN_REASON_STYLE "<P ALIGN=CENTER> %s <BOLD><EM>%s</EM></BOLD>"
+
+#define DESIGN_MODERATOR_ENTER_HEADER "<P ALIGN=CENTER>%s"
+
+#define DESIGN_LOSTPASSW_HEADER "<P ALIGN=CENTER>%s"
+
+#define DESIGN_SEARCH_SEARCH_STR_WAS "<BR><CENTER><EM>%s</EM>%s</CENTER>"
+#define DESIGN_SEARCH_RESULT "<BR><CENTER>%s%ld %s</CENTER><BR>"
+#define DESIGN_SEARCH_NO_RESULT "<BR><CENTER><B>%s %s</B></CENTER><BR>"
+
+#define DESIGN_COMMAND_TABLE_BEGIN "<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=1 BGCOLOR=#dfdfdf width=100%%><TR><TD class=cs align=center>"
+#define DESIGN_COMMAND_TABLE_END " ]</TD></TR></TABLE></CENTER>\n"
+
+#define DESIGN_BEGIN_LOGIN_OPEN "<CENTER><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3>"
+#define DESIGN_END_LOGIN_CLOSE "</TABLE></CENTER>"
+
+#define DESIGN_BEGIN_LOSTPASSW_OPEN "<CENTER><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3>"
+#define DESIGN_END_LOSTPASSW_CLOSE "</TABLE></CENTER>"
+
+#define DESIGN_BEGIN_REGISTER_OPEN "<CENTER><TABLE BORDER=0 CELLSPACING=1 CELLPADDING=3>"
+#define DESIGN_END_REGISTER_CLOSE "</TABLE></CENTER>"
+// nick in read_message
+#define DESIGN_MESSAGE_UNREG "<b>%s</b><SMALL> (unreg)</SMALL>"
+
+#define DESIGN_BEGIN_USERINFO_INTRO_OPEN "<CENTER><TABLE BORDER=0 CELLSPACING=1 CELLPADDING=3>"
+#define DESIGN_END_USERINFO_INTRO_CLOSE "</TABLE></CENTER>"
+
+#define DESIGN_SEARCH_RESULT "<BR><CENTER>%s%ld %s</CENTER><BR>"
+
+/******************* private messages *******************/
+#define DESIGN_PRIVATEMSG_FRAME "%s <TABLE WIDTH=95%% BORDER=1 CELLSPACING=0 CELLPADDING=6 BGCOLOR=%s>" \
+ "<TR><TD ALIGN=LEFT> %s </TD></TR></TABLE> %s%s"
+#define DESIGN_PRIVATEMSG_FRAME_BGCL_IN "#FFBBBB"
+#define DESIGN_PRIVATEMSG_FRAME_BGCL_OUT "#BBBBFF"
+
+/********************** announces ***********************/
+#define DESIGN_GLOBALANN_FRAME "%s <TABLE WIDTH=96%% BORDER=1 CELLSPACING=0 CELLPADDING=4 BGCOLOR=#DDDDDD>" \
+ "<TR><TD ALIGN=LEFT style=\"border-style:solid;border-width:1px;" \
+ "border-color:#AAAAAA;\" class=cl> %s<BR>%s" \
+ " %s (%s) %s</TD></TR></TABLE> %s"
+
+#define DESIGN_CONFIGURE_CHECKALL "Check/Uncheck All <input type=checkbox checked onClick=\"javascript:selectall(checked)\">" \
+"\n<script language=\"JavaScript\">\n" \
+"function selectall(state){\n" \
+" var item,i=0;\n" \
+" while (1) {\n" \
+" item=eval(\"document.configure.topic\"+i);\n" \
+" if (item) { item.checked = state;i++;\n" \
+" } else { break; }\n" \
+" }\n" \
+"}" \
+"</script>\n"
+
+#define DESIGN_WELCOME_QUICKNAV "<SELECT CLASS=CL onchange=\"if (this.options[this.selectedIndex].value == '') this.selectedIndex=0;" \
+"else window.open(this.options[this.selectedIndex].value,'_top')\"><OPTION VALUE=\"" MY_CGI_URL "?index=0\"%s>%s</OPTION>" \
+"<OPTION VALUE=\"" MY_CGI_URL "?index=all\"%s>%s</OPTION>"
+
+
+/************************* ban list *************************/
+#define DESIGN_BAN_FORM "<center><form action=\""MY_CGI_URL"?banlist=save\" method=\"post\">"\
+ "<textarea name=\"ban_list\" rows=\"30\" cols=\"70\" wrap=\"soft\">"
+
+#define DESIGN_BAN_FORM2 "</textarea><br /><input type=\"submit\" name=\"submit\" value=\"Save\">"\
+ "</form></center>"
+
+//****************************************************//
+#define HTML_START "<html><head>"
+
+#define TEXT_ENCODING_HEADER "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\"><link rel=\"shortcut icon\" href=\"favicon.ico\"><meta http-equiv=\"Page-Exit\" content=\"progid:DXImageTransform.Microsoft.Fade(Duration=0.2)\">"
+
+#define TEXT_TOPBANNER_HEADER ""
+
+#define TEXT_STYLE_HEADER "<style>"\
+"body { background-color: #f0f0f0; color: #000000; margin: 0;padding:0;border: 0; }"\
+"A {text-decoration: none;}\nA:visited {color: #000088;}\n" \
+"table.cl {width: 100%%;background-color: #E1E1E1; padding: 8px; border: 0; margin:0; } "\
+"TD.under {font-size: 7pt;font-weight: bold;vertical-align: top;}\n" \
+".underhref {font-size: 7pt;}\n"\
+"BIG {font-size: 14pt;font-weight: bold;}\n" \
+"/* name */ NOBR B {font-size: 12pt;color: #207025;}\n"\
+"/* ip,counter */ EM {font-size: 9pt;font-style: normal;}\n"\
+"/* + for new */ A EM.e, EM.e {color: #cc0000;font-weight: bold;font-size: 13pt;}\n" \
+".cl, .cs {font-family: Verdana, Arial; font-size: 8pt}\n" \
+"div {padding: 1px 0 1px 25px;}\n"\
+"div.g, div.w {border-top: 1px solid #ccc; padding: 5px 0 2px 10px;padding-left: 10px}"\
+"div.g {background-color:" DESIGN_THREADS_DIVIDER_grey ";}\n" \
+"DD DL{margin-left:-15px;}\n" \
+"</style></head><body>\n" \
+"<a name=\"up\"></a>"
+
+#define TEXT_TOPBANNER_MAP "<map name=\"bottom_map\">" \
+"<area shape=\"rect\" coords=\"669,11,700,39\" href=\"#up\" alt=\"═ртхЁї\">" \
+"<area shape=\"rect\" coords=\"700,11,732,39\" href=\"mailto:estet@pisem.net\" alt=\"Webmaster\">" \
+"</map>" \
+"<center><img src=\"files/top_image.gif\" usemap=\"#top_map\" border=\"0\" height=\"104\" width=\"750\"><br>" \
+"<!-- END Header -->"
+
+#define TEXT_BOTTOMBANNER "\n<!-- Footer -->\n" \
+"<center><img src=\"files/bottom_image.gif\" usemap=\"#bottom_map\" border=\"0\" height=\"55\" width=\"750\"><br>" \
+"<table border=\"0\" width=\"750\"><tbody>" \
+"<tr><td class=\"under\" align=\"left\"></td>" \
+"<td class=\"under\" align=\"right\"></td></tr>" \
+"</tbody></table></center>" \
+"<!-- END Footer -->\n" \
+"</body></html>\n"
+
+#define TEXT_BOTTOMBANNER_SHORT "" /* "<P></P><CENTER><SMALL>╩юэЇхЁхэЎш юёэютрэр эр фтшцъх " \
+"<A STYLE=\"text-decoration:underline;\" href=\"http://2ka.mipt.ru/~www/\" TARGET=\"_blank\">WWWConf " VERSION \
+"</A>, яюффхЁцштрхЄё ш ьюфхЁшЁєхЄё уЁєяяющ <a STYLE=\"text-decoration:underline;\" " \
+ "href=\"http://board.rt.mipt.ru/authors.html\">¤эЄєчшрёЄют</a>.</SMALL></CENTER></BODY></HTML>"*/
+
+#endif
blob - /dev/null
blob + b29b801f46fe170fccd8959e37e4f994fd3a5be6 (mode 644)
--- /dev/null
+++ src/profiles.cpp
+/***************************************************************************
+ 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; i<PROFILES_FAV_THREADS_COUNT; i++)
+ newprf->favs[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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+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
+bool IsRobotNick(char *nick);
\ No newline at end of file
blob - /dev/null
blob + ce07edc994ba203573b7caed63107dcda2220b14 (mode 644)
--- /dev/null
+++ src/searcher.cpp
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+/*
+ 100% free public domain implementation of the SHA-1 algorithm
+ by Dominik Reichl <dominik.reichl@t-online.de>
+ 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
+/*
+ 100% free public domain implementation of the SHA-1 algorithm
+ by Dominik Reichl <dominik.reichl@t-online.de>
+ 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 <memory.h> // Needed for memset and memcpy
+
+#ifdef SHA1_UTILITY_FUNCTIONS
+#include <stdio.h> // Needed for file access and sprintf
+#include <string.h> // Needed for strcat and strcpy
+#endif
+
+#ifdef _MSC_VER
+#include <stdlib.h>
+#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
+/***************************************************************************
+ 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
+/***************************************************************************
+ 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
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#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
+bool isEnoughSpace(void);