From 8cc6896bcb0cd2e3d718352dd3695d7b03696d26 Mon Sep 17 00:00:00 2001 From: blubbizmb <55148207+blubbizmb@users.noreply.github.com> Date: Sun, 15 Sep 2019 13:32:23 +0000 Subject: [PATCH 1/4] store private messages to SQLite3 database new option ./dbtool -npriv for initializing DB table for private messages (without touching user profiles) --- Makefile | 7 +- dbaseutils.cpp | 26 ++++ dbaseutils.h | 1 + main.cpp | 152 ++++++++++------------ messages.h | 2 + profiles.cpp | 340 +++++++++++++++++++------------------------------ profiles.h | 14 +- profman.cpp | 80 +++++++----- tables.sql | 1 + 9 files changed, 288 insertions(+), 335 deletions(-) create mode 100644 tables.sql diff --git a/Makefile b/Makefile index f66ffb6..e7b7528 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,9 @@ SRCS=$(INDEX_SRCS) $(DBTOOL_SRCS) INDEX_OBJS=$(INDEX_SRCS:.cpp=.o) DBTOOL_OBJS=$(DBTOOL_SRCS:.cpp=.o) +INDEX_LIBS=-lsqlite3 +DBTOOL_LIBS=-lsqlite3 + .SUFFIXES: .cpp .o .cpp.o: $(CXX) $(CXXFLAGS) -c $*.cpp @@ -37,10 +40,10 @@ all: index.cgi dbtool @echo Compiling Done index.cgi: $(INDEX_OBJS) .depend - $(CXX) $(CXXFLAGS) -o index.cgi -Wl,-\( $(INDEX_OBJS) -Wl,-\) + $(CXX) $(CXXFLAGS) -o index.cgi -Wl,-\( $(INDEX_OBJS) -Wl,-\) $(INDEX_LIBS) dbtool: $(DBTOOL_OBJS) .depend - $(CXX) $(CXXFLAGS) -o dbtool -Wl,-\( $(DBTOOL_OBJS) -Wl,-\) + $(CXX) $(CXXFLAGS) -o dbtool -Wl,-\( $(DBTOOL_OBJS) -Wl,-\) $(DBTOOL_LIBS) clean: @rm -f *.o .depend diff --git a/dbaseutils.cpp b/dbaseutils.cpp index b78e678..20a1468 100644 --- a/dbaseutils.cpp +++ b/dbaseutils.cpp @@ -2,6 +2,7 @@ #include "basetypes.h" #include "error.h" #include "messages.h" +#include DWORD Fsize(const char *s) { @@ -128,3 +129,28 @@ DWORD TranslateMsgIndexDel(DWORD root) return i; } + +/** Executes SQL query on the given database. Query updates database and does not return column data. */ +int execute_update(char *dbname, char *query) { + sqlite3 *db; + int rc; + char *zErrMsg = 0; + + rc = sqlite3_open(dbname, &db); + if( rc ){ + print2log("Can't open database: %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return(1); + } + + rc = sqlite3_exec(db, query, NULL, 0, &zErrMsg); + if( rc!=SQLITE_OK ){ + print2log("SQL error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + return 1; + } + + sqlite3_close(db); + + return 0; +} diff --git a/dbaseutils.h b/dbaseutils.h index ccc20fc..eca047f 100644 --- a/dbaseutils.h +++ b/dbaseutils.h @@ -10,5 +10,6 @@ int WriteDBMessage(DWORD midx, SMessage *mes); int WriteDBMessageBody(char *buf, DWORD index, DWORD size); DWORD VIndexCountInDB(); DWORD TranslateMsgIndexDel(DWORD root); +int execute_update(char *dbname, char *query); #endif diff --git a/main.cpp b/main.cpp index 4aac038..a104687 100644 --- a/main.cpp +++ b/main.cpp @@ -1619,12 +1619,14 @@ int CheckAndCreateProfile(SProfile_UserInfo *ui, SProfile_FullUserInfo *fui, cha print2log("Profiles database error: DB ERROR, deal=%s", deal); #endif printhtmlerror(); + // fall through case PROFILE_RETURN_INVALID_FORMAT: #if ENABLE_LOG >= 1 print2log("Profiles database error: INVALID FORMAT, deal=%s", deal); #endif printhtmlerror(); + // fall through case PROFILE_RETURN_INVALID_LOGIN: if(op == 1 || op == 2) @@ -2187,6 +2189,7 @@ static void PrepareActionResult(int action, const char **c_par1, const char **c_ case MSG_CHK_ERROR_INVISIBLE: *c_par1 = MESSAGEMAN_invisible; *c_par2 = MESSAGEMAN_invisible2; + // fall through default: *c_par1 = MESSAGEMAIN_unknownerr; *c_par2 = MESSAGEMAIN_unknownerr2; @@ -4746,75 +4749,49 @@ print2log("incor pass %s", par); } if(strncmp(deal, "persmsg", 7) == 0) { - if(ULogin.LU.UniqID != 0) { + if(ULogin.LU.UniqID != 0) { // personal messages char *sn; - DWORD type = 0; + DWORD type = 0;// show either limited num of messages (0) or all messages (1) + DWORD limit = 10;// show no more messages than limit + DWORD offset = 0;// show N messages starting from 'offset' if((sn = strget(deal, "persmsg=", 255 - 1, '&')) != NULL) { if(strcmp(sn, "all") == 0) { type = 1; } - free(sn); + //free(sn); + } + if((sn = strget(deal, "from=", 255 - 1, '&')) != NULL) { + offset = strtoul(sn, NULL, 10); + //free(sn); } + free(sn); + print2log("offset = %d", offset); CProfiles prof; - SPersonalMessage *msg, *frommsg; - DWORD *tt, *ft; + SPersonalMessage *msg; + DWORD *tt; if(type) { tt = NULL; - ft = NULL; } else { tt = (DWORD*)malloc(sizeof(DWORD)); - *tt = 10; - ft = (DWORD*)malloc(sizeof(DWORD)); - *ft = 0; + *tt = limit; } - // let's read to messages (maybe from too) - if(prof.ReadPersonalMessages(NULL, ULogin.LU.SIndex, &msg, tt, &frommsg, ft) != PROFILE_RETURN_ALLOK) + // let's read messages + int itt = tt ? *tt : -1; + print2log("ReadPersonalMessages tt = %d", itt); + if(prof.ReadPersonalMessages(NULL, ULogin.LU.SIndex, &msg, tt, offset) != PROFILE_RETURN_ALLOK) printhtmlerror(); // let's get received message count - DWORD cnt = 0, postedcnt = 0; + DWORD cnt = 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++; - } - } - + print2log("cnt = %d", cnt); + // render priv messages // Tittle_cat(TITLE_PrivateMsg); PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE | HEADERSTRING_DISABLE_PRIVATEMSG, MAINPAGE_INDEX); @@ -4838,34 +4815,25 @@ print2log("incor pass %s", par); char *ss; SPersonalMessage *pmsg; DWORD i = 0; - DWORD j = 0; int received = 0; // posted or received + int self = 0; // message from user to himself for(;;) { // check exit expression - if(i == cnt && j == postedcnt) break; - if(i == cnt) { - pmsg = &(frommsg[j]); - j++; + if(i == cnt) break; + pmsg = &(msg[i]); + print2log("NameTo = %s, NameFrom = %s, ui.name = %s", pmsg->NameTo, pmsg->NameFrom, ULogin.pui->username); + i++; + if(strcmp(pmsg->NameTo, pmsg->NameFrom) == 0) { + self = 1; 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; - } - } + } else if (strcmp(pmsg->NameTo, ULogin.pui->username) == 0) { + received = 1; + self = 0; } + else { + received = 0; + self = 0; + } if(!received) { DB.Profile_UserName(pmsg->NameTo, tostr, 1); @@ -4898,35 +4866,49 @@ print2log("incor pass %s", par); st1_f = FilterBiDi(st1); - if(!received) { + if (self) { + printf(DESIGN_PRIVATEMSG_FRAME, ss, MESSAGEMAIN_privatemsg_self, tostr, CodeHttpString(pmsg->NameTo, 0), + MESSAGEMAIN_privatemsg_write, DESIGN_PRIVATEMSG_FRAME_SELF, st1_f); + } + else if(!received) { printf(DESIGN_PRIVATEMSG_FRAME, ss, MESSAGEMAIN_privatemsg_touser, tostr, CodeHttpString(pmsg->NameTo, 0), MESSAGEMAIN_privatemsg_write, DESIGN_PRIVATEMSG_FRAME_OUT, st1_f); - }else{ + } else { printf(DESIGN_PRIVATEMSG_FRAME, ss, MESSAGEMAIN_privatemsg_fromuser, tostr, CodeHttpString(pmsg->NameFrom, 0), MESSAGEMAIN_privatemsg_answer, DESIGN_PRIVATEMSG_FRAME_IN, st1_f); } if(st) free(st); if(st1) free(st1); - if (st1_f) - free(st1_f); - } + if (st1_f) free(st1_f); + }//for + + printf("
"); + if (offset > 0) { + DWORD new_offset = offset < limit ? 0 : offset - limit; + printf("Recent messages
", new_offset); + } + if (offset + limit < ULogin.pui->persmescnt + ULogin.pui->postedmescnt) { + DWORD new_offset = offset + limit; + printf("Later messages
", new_offset); + } + printf("
"); + ULogin.pui->readpersmescnt = ULogin.pui->persmescnt; prof.SetUInfo(ULogin.LU.SIndex, ULogin.pui); PrintBottomLines(); 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(); - } - goto End_part; + }// if UniqID + else { + Tittle_cat(TITLE_Error); + + PrintHTMLHeader(HEADERSTRING_RETURN_TO_MAIN_PAGE, MAINPAGE_INDEX); + PrintBoardError(MESSAGEMAIN_privatemsg_denyunreg, MESSAGEMAIN_privatemsg_denyunreg2, 0); + PrintBottomLines(); + } + goto End_part; } if(strncmp(deal, "globann", 7) == 0) { diff --git a/messages.h b/messages.h index 2453f8a..ec4778c 100644 --- a/messages.h +++ b/messages.h @@ -340,6 +340,7 @@ extern const char *UserRight_List[USERRIGHT_COUNT]; #define MESSAGEMAIN_privatemsg_fromuser "От пользователя:" #define MESSAGEMAIN_privatemsg_touser "Пользователю:" +#define MESSAGEMAIN_privatemsg_self "myself" #define MESSAGEMAIN_privatemsg_showall "Просмотреть все сообщения" @@ -816,6 +817,7 @@ extern char DESIGN_break[10]; "%s
%s
" #define DESIGN_PRIVATEMSG_FRAME_IN "pr_from" #define DESIGN_PRIVATEMSG_FRAME_OUT "pr_to" +#define DESIGN_PRIVATEMSG_FRAME_SELF "pr_self" /********************** announces ***********************/ #define DESIGN_GLOBALANN_FRAME "
%s
%s %s (%s) %s
" diff --git a/profiles.cpp b/profiles.cpp index 9a53888..b3ae174 100644 --- a/profiles.cpp +++ b/profiles.cpp @@ -11,6 +11,8 @@ #include "profiles.h" #include "freedb.h" #include "error.h" +#include "dbaseutils.h" +#include /* return 1 if valid, 0 otherwise */ @@ -26,6 +28,102 @@ int isLoginStrValid(register char *s) return 1; } +int read_messages_from_db(char *query, SPersonalMessage **messages){ + + SPersonalMessage *msg; + sqlite3 *db; + sqlite3_stmt *res; + DWORD i; + + int rc = sqlite3_open("profiles", &db); + if( rc ){ + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return(1); + } + + rc = sqlite3_prepare_v2(db, query, -1, &res, 0); + + if (rc != SQLITE_OK) { + fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + + return 1; + } + + msg = (SPersonalMessage*)malloc(sizeof(SPersonalMessage)); + + rc = sqlite3_step(res); + + //struct tm tm; + for(i = 0; ; i++) { + if (rc == SQLITE_ROW) { + + if (i > 0){ + msg = (SPersonalMessage*)realloc(msg, (i+1)*sizeof(SPersonalMessage)); + } + + msg[i].Prev = 0;//flag + msg[i].Id = sqlite3_column_int64(res, 0); + msg[i].DeletedForSender = sqlite3_column_int(res, 1); + msg[i].DeletedForRecipient = sqlite3_column_int(res, 2); + sprintf(msg[i].NameFrom, "%s", sqlite3_column_text(res, 3)); + msg[i].UIdFrom = sqlite3_column_int64(res, 4); + sprintf(msg[i].NameTo, "%s", sqlite3_column_text(res, 5)); + msg[i].UIdTo = sqlite3_column_int64(res, 6); + msg[i].Date = sqlite3_column_int64(res, 7); + sprintf(msg[i].Msg, "%s", sqlite3_column_text(res, 8)); + + } + else { + break; + } + + rc = sqlite3_step(res); + } + msg[i - 1].Prev = 0xffffffff; // last message mark + print2log("fetched %d object(s)", i); + + sqlite3_finalize(res); + sqlite3_close(db); + + if (i > 0) { + *messages = msg; + } + else { + *messages = NULL; + } + msg = NULL; + + return 0; +} + +int insert_message(SPersonalMessage mes){ + char insert[1000]; + char dbname[32]; + + sprintf(dbname, "profiles"); + + sprintf(insert, "insert into PersonalMessage (NameFrom, UIdFrom, NameTo, UIdTo, MsgDate, DelForSender, DelForRecipient, Msg) values ('%s', %lu, '%s', %lu, %lu, %u, %u, '%s')", + mes.NameFrom, // 30 + mes.UIdFrom, + mes.NameTo, // 30 + mes.UIdTo, + mes.Date, + mes.DeletedForSender, + mes.DeletedForRecipient, + mes.Msg); // 385 + print2log(insert); + + int rc = execute_update(dbname, insert); + if( rc != 0){ + print2log("Can't insert personal message\n"); + return(1); + } + + return 0; +} + /* constructor */ CProfiles::CProfiles() { @@ -749,7 +847,6 @@ int CProfiles::PostPersonalMessage(char *username, DWORD userindex, char *messag { SProfile_UserInfo ui, poster_ui; int ret; - WCFILE *fp; // load recipient user profile if(username != NULL && strcmp(username, "") != 0) { @@ -777,28 +874,24 @@ int CProfiles::PostPersonalMessage(char *username, DWORD userindex, char *messag // prepare personal message structure SPersonalMessage mes; - DWORD pos; + //DWORD pos; + mes.Id = 0; 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; + mes.DeletedForSender = mes.DeletedForRecipient = 0; + mes.Prev = 0; + mes.PosterPrev = 0; + if (insert_message(mes) != 0){ + goto PostPersMsg_Error; + } // update recipient user profile - ui.persmsg = pos; + + ui.persmsg = 0;// avoid 0xffffffff ui.persmescnt++; SetUInfo(userindex, &ui); @@ -807,29 +900,24 @@ int CProfiles::PostPersonalMessage(char *username, DWORD userindex, char *messag memcpy(&poster_ui, &ui, sizeof(SProfile_UserInfo)); // update sender user profile - poster_ui.postedpersmsg = pos; + poster_ui.postedpersmsg = 0;// avoid 0xffffffff poster_ui.postedmescnt++; SetUInfo(userindexfrom, &poster_ui); + + printf("return PROFILE_RETURN_ALLOK"); - unlock_file(fp); - wcfclose(fp); return PROFILE_RETURN_ALLOK; PostPersMsg_Error: - unlock_file(fp); - wcfclose(fp); + printf("PostPersMsg_Error"); return PROFILE_RETURN_DB_ERROR; } -int CProfiles::ReadPersonalMessages(char *username, DWORD userindex, - SPersonalMessage **tomessages, DWORD *tocount, - SPersonalMessage **frommessages, DWORD *fromcount) +int CProfiles::ReadPersonalMessages(char *username, DWORD userindex, SPersonalMessage **tomessages, DWORD *tocount, DWORD offset) { SProfile_UserInfo ui; int ret; - WCFILE *fp; - SPersonalMessage *msg; - DWORD toread, i, fromread, curpos; + DWORD toread; if(username != NULL && strcmp(username, "") != 0) { // use username @@ -842,12 +930,12 @@ int CProfiles::ReadPersonalMessages(char *username, DWORD userindex, return PROFILE_RETURN_DB_ERROR; } - msg = *tomessages = *frommessages = NULL; + *tomessages = NULL; - // if we really need read to messages + // if we really need read all messages if(tocount == NULL) { // all messages - toread = ui.persmescnt; + toread = ui.persmescnt + ui.postedmescnt; } else { if(*tocount == 0) { @@ -856,204 +944,36 @@ int CProfiles::ReadPersonalMessages(char *username, DWORD userindex, } else { // selected count - if(*tocount > ui.persmescnt) - *tocount = ui.persmescnt; + if(*tocount > ui.persmescnt + ui.postedmescnt) + *tocount = ui.persmescnt + ui.postedmescnt; 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; + 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.persmsg; - 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].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; - } + char sql[1000]; - 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; + sprintf(sql, "select MsgId, DelForSender, DelForRecipient, NameFrom, UIdFrom, NameTo, UIdTo, MsgDate, Msg from PersonalMessage where (NameTo = '%s' and DelForRecipient = 0) or (NameFrom = '%s' and DelForSender = 0) order by MsgDate desc LIMIT %lu OFFSET %lu", ui.username, ui.username, toread, offset); + print2log(sql); + + if (read_messages_from_db(sql, tomessages) != 0){ + goto PostPersMsg_Error; } - else msg[i - 1].Prev = 0xffffffff; // last message mark - wcfclose(fp); - *frommessages = msg; + + if (*tomessages != NULL) { + (*tomessages)[toread - 1].Prev = 0xffffffff; // last message mark + } 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; } diff --git a/profiles.h b/profiles.h index 23bd751..30fa14e 100644 --- a/profiles.h +++ b/profiles.h @@ -60,17 +60,19 @@ #define PROFILE_PERSONAL_MESSAGE_LENGHT 385 struct SPersonalMessage { - DWORD Prev; - DWORD PosterPrev; + DWORD Id; + DWORD Prev;// used as flag + DWORD PosterPrev;// not used anymore char NameFrom[PROFILES_MAX_USERNAME_LENGTH]; DWORD UIdFrom; char NameTo[PROFILES_MAX_USERNAME_LENGTH]; DWORD UIdTo; time_t Date; + unsigned char DeletedForSender; + unsigned char DeletedForRecipient; char Msg[PROFILE_PERSONAL_MESSAGE_LENGHT]; }; - #pragma pack(1) struct SViewSettings @@ -177,10 +179,10 @@ class CProfiles { // 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); + SPersonalMessage **tomessages, DWORD *tocount, DWORD offset); - int ReadPersonalMessagesByDate(char *username, DWORD userindex, - SPersonalMessage **tomessages, time_t todate, SPersonalMessage **frommessages, time_t fromdate); + //int ReadPersonalMessagesByDate(char *username, DWORD userindex, + // SPersonalMessage **tomessages, time_t todate, SPersonalMessage **frommessages, time_t fromdate); int GenerateUserList(char ***buf, DWORD *cnt); diff --git a/profman.cpp b/profman.cpp index 77fd911..10c35c6 100644 --- a/profman.cpp +++ b/profman.cpp @@ -31,6 +31,7 @@ void printusage(char *iam) " -au user passwd - create user (spec. username and password)\n" " -d user - delete user\n" " -np - renew(delete) private messages database (in profiles)\n" + " -npriv - drop/create table for private messages (in SQLite3 database profiles)\n" " -r - zero refresh count for all users\n" " -vs - set default view settings for all users\n" " -fixcr - replace '\\r' by '\\n' in all message bodies\n", @@ -120,6 +121,7 @@ void printerror(DWORD er) switch(er) { case PROFILE_RETURN_ALLOK: printf("All ok\n"); + // fall through case PROFILE_RETURN_ALREADY_EXIST: printf("User already exits\n"); break; @@ -373,6 +375,33 @@ int main(int argc, char *argv[]) goto go_stop; } + if(argc == 2 && strcmp(argv[1], "-npriv") == 0) { + printf("Drop/create private messages database...\n"); + + char sql[1000]; + char dbname[32]; + + sprintf(dbname, "profiles"); + + sprintf(sql, "drop table PersonalMessage"); + int rc = execute_update(dbname, sql); + if ( rc != 0 ) { + printf("Can't drop private message table\n"); + } + + sprintf(sql, "create table PersonalMessage (MsgId INTEGER PRIMARY KEY AUTOINCREMENT, NameFrom TEXT, UIdFrom INT, NameTo TEXT, UIdTo INT, MsgDate INT, DelForSender INT, DelForRecipient INT, Msg TEXT)"); + rc = execute_update(dbname, sql); + if ( rc != 0 ) { + printf("Can't create preivate message table\n"); + } + else { + printf("Private message table successfully created\n"); + } + + 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) { @@ -500,56 +529,43 @@ int main(int argc, char *argv[]) } if(argc == 3 && strcmp(argv[1], "-vp") == 0) { - SPersonalMessage *topm, *frompm; + SPersonalMessage *topm; 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) { + if((code = prof.ReadPersonalMessages(argv[2], 0, &topm, NULL, 0)) == PROFILE_RETURN_ALLOK) { + // TODO private messages + // frompm = topm; char tostr[1000], newm[100]; char *ss; SPersonalMessage *pmsg; int i = 0; - int j = 0; + //int j = 0; int received = 0; // posted or received - int cnt = 0, postedcnt = 0; + int cnt = 0; if(topm) { while(topm[cnt].Prev != 0xffffffff) cnt++; cnt++; } - if(frompm) { - while(frompm[postedcnt].Prev != 0xffffffff) postedcnt++; - postedcnt++; - } + //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(i == cnt) break; + pmsg = &(topm[i]); + i++; + if (strcmp(pmsg->NameTo, argv[2]) == 0) { + received = 1; + } + else { + received = 0; + } if(!received) { strcpy(tostr, pmsg->NameTo); diff --git a/tables.sql b/tables.sql new file mode 100644 index 0000000..2a7b0d1 --- /dev/null +++ b/tables.sql @@ -0,0 +1 @@ +create table PersonalMessage (MsgId INTEGER PRIMARY KEY AUTOINCREMENT, NameFrom TEXT, UIdFrom INT, NameTo TEXT, UIdTo INT, MsgDate INT, DelForSender INT, DelForRecipient INT, Msg TEXT) From 66e97ead0ef07e393cc425fd87c11a1c66ad7b3b Mon Sep 17 00:00:00 2001 From: blubbizmb <55148207+blubbizmb@users.noreply.github.com> Date: Sun, 15 Sep 2019 13:34:47 +0000 Subject: [PATCH 2/4] add new styles for previous commit --- static/main.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/static/main.css b/static/main.css index 3557821..2b2e435 100644 --- a/static/main.css +++ b/static/main.css @@ -261,6 +261,13 @@ div.pr_from{ border: 1px solid #777; } +div.pr_self{ + padding: 3px; + margin: 1px 10px 20px 10px; + background-color: #bbffbb; + border: 1px solid #777; +} + div.pr_info{ margin-left: 20px; } From 86ec04ced276b676cd52a510cf826e688d778d3e Mon Sep 17 00:00:00 2001 From: blubbizmb <55148207+blubbizmb@users.noreply.github.com> Date: Sun, 15 Sep 2019 13:50:29 +0000 Subject: [PATCH 3/4] fix some labels --- main.cpp | 7 ++++--- messages.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/main.cpp b/main.cpp index a104687..232e859 100644 --- a/main.cpp +++ b/main.cpp @@ -4886,11 +4886,12 @@ print2log("incor pass %s", par); printf("
"); if (offset > 0) { DWORD new_offset = offset < limit ? 0 : offset - limit; - printf("Recent messages
", new_offset); + printf("Более свежие
", new_offset); } + printf(" ... "); if (offset + limit < ULogin.pui->persmescnt + ULogin.pui->postedmescnt) { DWORD new_offset = offset + limit; - printf("Later messages
", new_offset); + printf("Более ранние
", new_offset); } printf("
"); @@ -5363,7 +5364,7 @@ print2log("incor pass %s", par); printf("

"); printf("%s
\n", fDelete ? - "Следующие пользователи были успешно удалены:" : + "Следующие пользователи были успешно удалены:" : "Список пользователей подлежащих удалению:" ); diff --git a/messages.h b/messages.h index ec4778c..1c59441 100644 --- a/messages.h +++ b/messages.h @@ -179,7 +179,7 @@ extern const char *MESSAGEHEAD_timetypes[4]; #define MESSAGEMAIN_register_full_name "Ваше полное имя:" #define MESSAGEMAIN_register_validemail_req "Вы должны указать действующий E-Mail адрес
(он будет использоваться для получения пароля и сводок по конференции)" #define MESSAGEMAIN_register_bot "Внимание!
Если вы видите два поля, то введите e-mail только
во второе, оставьте первое пустым!
Attention!
If you see two fields, fill with e-mail only
the second one, leave the first one blank!" -#define MESSAGEMAIN_register_email "E-Mail адрес (*):" +#define MESSAGEMAIN_register_email "E-Mail адрес (*):" #define MESSAGEMAIN_register_email_pub "Публичный доступ к Вашему E-Mail" #define MESSAGEMAIN_register_homepage "Адрес Вашей домашней страницы:" #define MESSAGEMAIN_register_icq "ICQ :" @@ -340,7 +340,7 @@ extern const char *UserRight_List[USERRIGHT_COUNT]; #define MESSAGEMAIN_privatemsg_fromuser "От пользователя:" #define MESSAGEMAIN_privatemsg_touser "Пользователю:" -#define MESSAGEMAIN_privatemsg_self "myself" +#define MESSAGEMAIN_privatemsg_self "Своё сообщение:" #define MESSAGEMAIN_privatemsg_showall "Просмотреть все сообщения" From 648f26b64f6679657bcaddba6352014aed7a08c0 Mon Sep 17 00:00:00 2001 From: blubbizmb <55148207+blubbizmb@users.noreply.github.com> Date: Wed, 18 Sep 2019 06:27:05 +0000 Subject: [PATCH 4/4] use sql parameters --- profiles.cpp | 85 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/profiles.cpp b/profiles.cpp index b3ae174..6c31bfb 100644 --- a/profiles.cpp +++ b/profiles.cpp @@ -37,7 +37,7 @@ int read_messages_from_db(char *query, SPersonalMessage **messages){ int rc = sqlite3_open("profiles", &db); if( rc ){ - fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); + print2log("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); return(1); } @@ -45,7 +45,7 @@ int read_messages_from_db(char *query, SPersonalMessage **messages){ rc = sqlite3_prepare_v2(db, query, -1, &res, 0); if (rc != SQLITE_OK) { - fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db)); + print2log("Failed to fetch data: %s", sqlite3_errmsg(db)); sqlite3_close(db); return 1; @@ -99,28 +99,79 @@ int read_messages_from_db(char *query, SPersonalMessage **messages){ } int insert_message(SPersonalMessage mes){ + sqlite3 *db; + sqlite3_stmt *stmt; char insert[1000]; - char dbname[32]; - sprintf(dbname, "profiles"); - - sprintf(insert, "insert into PersonalMessage (NameFrom, UIdFrom, NameTo, UIdTo, MsgDate, DelForSender, DelForRecipient, Msg) values ('%s', %lu, '%s', %lu, %lu, %u, %u, '%s')", - mes.NameFrom, // 30 - mes.UIdFrom, - mes.NameTo, // 30 - mes.UIdTo, - mes.Date, - mes.DeletedForSender, - mes.DeletedForRecipient, - mes.Msg); // 385 + sprintf(insert, "insert into PersonalMessage (NameFrom, UIdFrom, NameTo, UIdTo, MsgDate, DelForSender, DelForRecipient, Msg) values (?, ?, ?, ?, ?, ?, ?, ?)"); print2log(insert); - int rc = execute_update(dbname, insert); - if( rc != 0){ - print2log("Can't insert personal message\n"); + int rc = sqlite3_open("profiles", &db); + if( rc ){ + print2log("Can't open database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + return(1); + } + + rc = sqlite3_prepare_v2(db, insert, -1, &stmt, 0); + if (rc != SQLITE_OK) { + print2log("Failed to prepare stmt: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + return 1; + } + + int n = 0;// param index + int err = 0; + if (sqlite3_bind_text(stmt, ++n, mes.NameFrom, strlen(mes.NameFrom), SQLITE_STATIC) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + }print2log("binded # %d", n); + if (sqlite3_bind_int64(stmt, ++n, mes.UIdFrom) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + if (sqlite3_bind_text(stmt, ++n, mes.NameTo, strlen(mes.NameTo), SQLITE_STATIC) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + if (sqlite3_bind_int64(stmt, ++n, mes.UIdTo) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + if (sqlite3_bind_int64(stmt, ++n, mes.Date) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + if (sqlite3_bind_int(stmt, ++n, mes.DeletedForSender) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + if (sqlite3_bind_int(stmt, ++n, mes.DeletedForRecipient) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + if (sqlite3_bind_text(stmt, ++n, mes.Msg, strlen(mes.Msg), SQLITE_STATIC) != SQLITE_OK){ + print2log("Failed to bind # %d param: %s", n, sqlite3_errmsg(db)); + err++; + } + + if (err > 0){ + print2log("Failed to bind parameters"); + sqlite3_close(db); + return 1; + } + + rc = sqlite3_step(stmt); + if( rc != SQLITE_DONE){ + print2log("Can't insert personal message: %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + sqlite3_close(db); return(1); } + sqlite3_finalize(stmt); + sqlite3_close(db); + return 0; }