├── logs └── .logs_here ├── res └── wait.gif ├── src ├── t ├── t.bat ├── m ├── m.bat ├── npp_app.h ├── npp_svc.cpp └── npp_app.cpp ├── README.md ├── resmin ├── npp.css ├── dsk.css ├── dsk.js └── npp.js ├── LICENSE ├── bin ├── npp.conf ├── nppstop ├── nppstart ├── nppmake.bat └── nppmake └── lib ├── Cusers_groups.h ├── Cusers_avatars.h ├── Cusers_p_resets.h ├── Cusers_settings.h ├── Cusers_messages.h ├── Cusers_activations.h ├── Cusers_logins.h ├── users.sql ├── Cusers.h ├── npp_watcher.c ├── Cusers_groups.cpp ├── Cusers_avatars.cpp ├── Cusers_settings.cpp ├── Cusers_p_resets.cpp ├── Cusers_messages.cpp ├── Cusers_activations.cpp ├── Cusers_logins.cpp ├── npp_usr.h ├── Cusers.cpp └── npp_update.c /logs/.logs_here: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /res/wait.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekmus/perf-web/master/res/wait.gif -------------------------------------------------------------------------------- /src/t: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export NPP_DIR=.. 4 | 5 | $NPP_DIR/bin/npp_app 8080 6 | -------------------------------------------------------------------------------- /src/t.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set NPP_DIR=.. 4 | 5 | %NPP_DIR%\bin\npp_app 8080 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # perf 2 | Web application performance tester with browser interface (based on Node++) 3 | 4 |
5 | 6 |
7 | 8 | -------------------------------------------------------------------------------- /resmin/npp.css: -------------------------------------------------------------------------------- 1 | // ---------------------------------------- 2 | // wait animation 3 | .wt 4 | { 5 | display: none; 6 | position: fixed; 7 | top: 0; 8 | left: 0; 9 | width: 100%; 10 | height: 100%; 11 | z-index: 900; 12 | background: url('/wait.gif') 50% 50% no-repeat; 13 | background-size: 52px; 14 | } 15 | 16 | 17 | // ---------------------------------------- 18 | // modal window 19 | .mw 20 | { 21 | font-size: 12pt; 22 | background-color: white; 23 | padding: 3px 12px 13px 14px; 24 | box-shadow: 4px 4px 16px 0px rgba(0,0,0,0.2); 25 | border: 1px solid #bbbbbb; 26 | z-index: 1000; 27 | } 28 | 29 | 30 | // ---------------------------------------- 31 | // yes/no buttons 32 | .ynb 33 | { 34 | width: 80px; 35 | height: 32px; 36 | margin-top: 20px; 37 | } 38 | -------------------------------------------------------------------------------- /src/m: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ---------------------------------------------------------------------------- 4 | # Set the local compilation environment here 5 | # ---------------------------------------------------------------------------- 6 | 7 | 8 | # ---------------------------------------------------------------------------- 9 | # Set include path (might be required for OpenSSL and MySQL) 10 | # Example: export CPATH=/usr/include/mysql 11 | 12 | #export CPATH= 13 | 14 | 15 | # ---------------------------------------------------------------------------- 16 | # Set library path (might be required for OpenSSL and MySQL) 17 | # Example: export LIBRARY_PATH=/usr/lib64/mysql 18 | 19 | #export LIBRARY_PATH= 20 | 21 | 22 | # ---------------------------------------------------------------------------- 23 | # Call the main making script (don't change this) 24 | 25 | ../bin/nppmake $1 26 | -------------------------------------------------------------------------------- /src/m.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ---------------------------------------------------------------------------- 4 | rem Set the local compilation environment here 5 | rem ---------------------------------------------------------------------------- 6 | 7 | 8 | rem ---------------------------------------------------------------------------- 9 | rem Set include path (might be required for OpenSSL and MySQL) 10 | rem Example: set CPATH=C:\usr\include;C:\usr\include\mysql 11 | 12 | rem set CPATH= 13 | 14 | 15 | rem ---------------------------------------------------------------------------- 16 | rem Set library path (might be required for OpenSSL and MySQL) 17 | rem Example: set LIBRARY_PATH=C:\usr\lib\openssl;C:\usr\lib\mysql 18 | 19 | rem set LIBRARY_PATH= 20 | 21 | 22 | rem ---------------------------------------------------------------------------- 23 | rem Call the main making script (don't change this) 24 | 25 | call ..\bin\nppmake.bat %1 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jurek Muszynski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/npp_app.h: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Silgy Web App 3 | Jurek Muszynski 4 | ----------------------------------------------------------------------------- 5 | Web App Performance Tester 6 | -------------------------------------------------------------------------- */ 7 | 8 | #ifndef NPP_APP_H 9 | #define NPP_APP_H 10 | 11 | 12 | #define NPP_APP_NAME "Web App Performance Tester" 13 | #define NPP_REQUIRED_AUTH_LEVEL AUTH_LEVEL_ANONYMOUS 14 | 15 | 16 | /* List of additional C/C++ modules to compile. They have to be one-liners */ 17 | 18 | #define NPP_APP_MODULES "" 19 | #define NPP_SVC_MODULES NPP_APP_MODULES 20 | 21 | 22 | #define NPP_ASYNC 23 | #define NPP_ASYNC_INCLUDE_SESSION_DATA 24 | 25 | #define NPP_MEM_MEDIUM 26 | 27 | 28 | #define NPP_HTTPS 29 | #define NPP_NO_HSTS 30 | 31 | //#define NPP_FD_MON_LINUX_POLL 32 | //#define NPP_DEBUG 33 | 34 | 35 | #define WAIT "onClick=\"wait();\"" 36 | #define ONKEYDOWN "onkeydown=\"ent(event);\"" 37 | 38 | 39 | /* app session data */ 40 | /* accessible via SESSION_DATA macro */ 41 | 42 | typedef struct { 43 | char url[256]; 44 | int batch; 45 | int times; 46 | bool keep; 47 | double elapsed; 48 | } app_session_data_t; 49 | 50 | 51 | #endif /* NPP_APP_H */ 52 | -------------------------------------------------------------------------------- /bin/npp.conf: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # Node++ application configuration file 3 | # 4 | # This file should be placed in $NPP_DIR/bin 5 | # 6 | # By default it's read at startup only 7 | # 8 | # With NPP_ENABLE_RELOAD_CONF defined in npp_app.h 9 | # it can be reloaded online by sending 10 | # POST /npp_reload_conf from its host (i.e. using curl) 11 | # ---------------------------------------------------------------------------- 12 | 13 | # ---------------------------------------------------------------------------- 14 | # Log 15 | 16 | logLevel=2 # between 0...4 (most detailed) 17 | logToStdout=0 18 | logCombined=0 19 | 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Ports 23 | 24 | httpPort=8080 25 | httpsPort=8443 26 | 27 | 28 | # ---------------------------------------------------------------------------- 29 | # HTTPS 30 | 31 | #certFile=/home/ec2-user/dev/bin/cert.pem 32 | #keyFile=/home/ec2-user/dev/bin/key.pem 33 | 34 | 35 | # ---------------------------------------------------------------------------- 36 | # Database connection details 37 | 38 | #dbName=nodepp 39 | #dbUser=nodepp 40 | #dbPassword=nodepp 41 | 42 | 43 | # ---------------------------------------------------------------------------- 44 | # Number of ASYNC (npp_svc) processes 45 | 46 | ASYNCSvcProcesses=10 47 | 48 | 49 | # ---------------------------------------------------------------------------- 50 | # Setting this to 1 will add _t to the log file name and will cause 51 | # engine to ignore security redirections (NPP_DOMAIN_ONLY and HSTS) 52 | # to allow testing from localhost and without SSL. 53 | # For details search for "redirections table" in npp_eng_app.c. 54 | 55 | test=0 56 | -------------------------------------------------------------------------------- /lib/Cusers_groups.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:15:25, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_GROUPS_H 9 | #define CUSERS_GROUPS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_GROUPS_NAME[120+1]; 16 | typedef char USERS_GROUPS_ABOUT[250+1]; 17 | 18 | 19 | typedef struct 20 | { 21 | int id; 22 | USERS_GROUPS_NAME name; 23 | USERS_GROUPS_ABOUT about; 24 | char auth_level; 25 | } USERS_GROUPS_REC; 26 | 27 | 28 | class Cusers_groups : public USERS_GROUPS_REC, public Cdb 29 | { 30 | public: 31 | Cusers_groups(); 32 | ~Cusers_groups(); 33 | 34 | // Get the next record 35 | // Return false if end of record set 36 | bool Fetch(); 37 | 38 | // Get one record by PK 39 | // Not Found will return false 40 | bool Get(int arg_id); 41 | 42 | // Insert record 43 | unsigned Insert(); 44 | 45 | // Update record by PK 46 | void Update(int arg_id); 47 | 48 | // Delete record by PK 49 | void Delete(int arg_id); 50 | 51 | // Insert or update record by PK 52 | void Set(int arg_id); 53 | 54 | // Reset all values 55 | void Reset(); 56 | 57 | 58 | private: 59 | static bool slots_[CDB_MAX_INSTANCES]; 60 | 61 | int k_id_; 62 | 63 | unsigned long name_len_; 64 | unsigned long about_len_; 65 | 66 | 67 | my_bool id_is_null_; 68 | my_bool name_is_null_; 69 | my_bool about_is_null_; 70 | my_bool auth_level_is_null_; 71 | 72 | MYSQL_BIND bndk_[1]; 73 | MYSQL_BIND bndi_[5]; 74 | MYSQL_BIND bndo_[4]; 75 | 76 | void bindKey(MYSQL_STMT *s, int arg_id); 77 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_id=0); 78 | void bindOutput(MYSQL_STMT *s); 79 | void bindSetOutput(); 80 | 81 | }; 82 | 83 | 84 | #endif /* CUSERS_GROUPS_H */ 85 | -------------------------------------------------------------------------------- /resmin/dsk.css: -------------------------------------------------------------------------------- 1 | body {font-family:"Roboto", sans-serif; font-size:11pt; margin-bottom:3em;} 2 | h1 {display:inline-block; font-size:26pt; margin-left:10px; vertical-align:top; margin-top:10px; margin-bottom:0.8em; color:#303030;} 3 | h2 {text-align:center;} 4 | h3 {margin-top:30px;} 5 | input {font-size:11pt; padding-left:1px; padding-top:1px; box-sizing:border-box; -moz-box-sizing:border-box; -webkit-box-sizing:border-box;} 6 | a {color:#103890;} 7 | p {margin-top:5px; margin-bottom:5px;} 8 | .f13 {font-size:13pt;} 9 | .mt {padding:3px 5px;} 10 | .p2 {padding:2px 7px;} 11 | .wt {display:none; position:fixed; top:0; left:0; width:100%; height:100%; z-index:100; background:url(wait.gif) 50% 50% no-repeat; background-size:52px;} 12 | .ct {text-align:center;} 13 | .rt {text-align:right;} 14 | .m10 {margin-top:1em;} 15 | .m15 {margin-top:1.5em;} 16 | .m20 {margin-top:2em;} 17 | .m25 {margin-top:2.5em;} 18 | .m30 {margin-top:3em;} 19 | .m40 {margin-top:4em;} 20 | .m50 {margin-top:5em;} 21 | .sbb {width:7em; height:2.2em; margin-left:0.9em;} 22 | .w10p {width:10%;} 23 | .w30p {width:30%;} 24 | .w40p {width:40%;} 25 | .w50p {width:50%;} 26 | .w70p {width:70%;} 27 | .w75p {width:75%;} 28 | .w90p {width:90%;} 29 | .w100p {width:100%;} 30 | .w30em {width:30em;} 31 | .w40em {width:40em;} 32 | .mb5 {margin-bottom:5px;} 33 | .mono {font-family:monospace; font-size:10pt; white-space:pre;} 34 | .fl {display:flex;} 35 | .cl {font-size:1.5em; cursor:pointer;} 36 | .mm {display:inline-block; font-size:13pt; float:right; text-align:right; margin-top:12px; margin-right:17px;} 37 | .gr {color:grey;} 38 | .red {color:#b40000;} 39 | .ylw {color:#b09000;} 40 | .grn {color:#00a000;} 41 | .rlform {margin-top:50px; margin-left:10%; width:50%; text-align:right;} 42 | .rlbutton {margin-top:20px; height:36px; width:30%; margin-right:10%;} 43 | .acchist {border-collapse:collapse; border:1px solid #d8d8d8; padding:3px 6px;} 44 | .tdb {border-collapse:collapse; border:1px solid #d8d8d8; padding:3px 6px;} 45 | th {background-color:#f0f0f0;} 46 | .pt5 {padding-top:5px;} 47 | .pt20 {padding-top:20px;} 48 | .vat {vertical-align:top;} 49 | .but {margin-left:5px; width:84px; height:32px;} 50 | -------------------------------------------------------------------------------- /lib/Cusers_avatars.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-29 20:06:23, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_AVATARS_H 9 | #define CUSERS_AVATARS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_AVATARS_AVATAR_NAME[120+1]; 16 | typedef char USERS_AVATARS_AVATAR_DATA[65535+1]; 17 | 18 | 19 | typedef struct 20 | { 21 | int user_id; 22 | USERS_AVATARS_AVATAR_NAME avatar_name; 23 | USERS_AVATARS_AVATAR_DATA avatar_data; 24 | int avatar_len; 25 | } USERS_AVATARS_REC; 26 | 27 | 28 | class Cusers_avatars : public USERS_AVATARS_REC, public Cdb 29 | { 30 | public: 31 | unsigned long avatar_data_len; 32 | 33 | Cusers_avatars(); 34 | ~Cusers_avatars(); 35 | 36 | // Get the next record 37 | // Return false if end of record set 38 | bool Fetch(); 39 | 40 | // Get one record by PK 41 | // Not Found will return false 42 | bool Get(int arg_user_id); 43 | 44 | // Insert record 45 | unsigned Insert(); 46 | 47 | // Update record by PK 48 | void Update(int arg_user_id); 49 | 50 | // Delete record by PK 51 | void Delete(int arg_user_id); 52 | 53 | // Insert or update record by PK 54 | void Set(int arg_user_id); 55 | 56 | // Reset all values 57 | void Reset(); 58 | 59 | 60 | private: 61 | static bool slots_[CDB_MAX_INSTANCES]; 62 | 63 | int k_user_id_; 64 | 65 | unsigned long avatar_name_len_; 66 | 67 | 68 | my_bool user_id_is_null_; 69 | my_bool avatar_name_is_null_; 70 | my_bool avatar_data_is_null_; 71 | my_bool avatar_len_is_null_; 72 | 73 | MYSQL_BIND bndk_[1]; 74 | MYSQL_BIND bndi_[5]; 75 | MYSQL_BIND bndo_[4]; 76 | 77 | void bindKey(MYSQL_STMT *s, int arg_user_id); 78 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_user_id=0); 79 | void bindOutput(MYSQL_STMT *s); 80 | void bindSetOutput(); 81 | 82 | void genDTStrings(); 83 | }; 84 | 85 | 86 | #endif /* CUSERS_AVATARS_H */ 87 | -------------------------------------------------------------------------------- /lib/Cusers_p_resets.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:16:49, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_P_RESETS_H 9 | #define CUSERS_P_RESETS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_P_RESETS_LINKKEY[20+1]; 16 | typedef char USERS_P_RESETS_CREATED[19+1]; 17 | 18 | 19 | typedef struct 20 | { 21 | USERS_P_RESETS_LINKKEY linkkey; 22 | int user_id; 23 | USERS_P_RESETS_CREATED created; 24 | short tries; 25 | } USERS_P_RESETS_REC; 26 | 27 | 28 | class Cusers_p_resets : public USERS_P_RESETS_REC, public Cdb 29 | { 30 | public: 31 | Cusers_p_resets(); 32 | ~Cusers_p_resets(); 33 | 34 | // Get the next record 35 | // Return false if end of record set 36 | bool Fetch(); 37 | 38 | // Get one record by PK 39 | // Not Found will return false 40 | bool Get(const std::string& arg_linkkey); 41 | 42 | // Insert record 43 | unsigned Insert(); 44 | 45 | // Update record by PK 46 | void Update(const std::string& arg_linkkey); 47 | 48 | // Delete record by PK 49 | void Delete(const std::string& arg_linkkey); 50 | 51 | // Insert or update record by PK 52 | void Set(const std::string& arg_linkkey); 53 | 54 | // Reset all values 55 | void Reset(); 56 | 57 | 58 | private: 59 | static bool slots_[CDB_MAX_INSTANCES]; 60 | 61 | USERS_P_RESETS_LINKKEY k_linkkey_; 62 | 63 | unsigned long linkkey_len_; 64 | MYSQL_TIME t_created_; 65 | 66 | unsigned long k_linkkey_len_; 67 | 68 | my_bool linkkey_is_null_; 69 | my_bool user_id_is_null_; 70 | my_bool created_is_null_; 71 | my_bool tries_is_null_; 72 | 73 | MYSQL_BIND bndk_[1]; 74 | MYSQL_BIND bndi_[5]; 75 | MYSQL_BIND bndo_[4]; 76 | 77 | void bindKey(MYSQL_STMT *s, const std::string& arg_linkkey); 78 | void bindInput(MYSQL_STMT *s, bool withKey=false, const std::string& arg_linkkey=""); 79 | void bindOutput(MYSQL_STMT *s); 80 | void bindSetOutput(); 81 | 82 | void genDTStrings(); 83 | }; 84 | 85 | 86 | #endif /* CUSERS_P_RESETS_H */ 87 | -------------------------------------------------------------------------------- /lib/Cusers_settings.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:16:04, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_SETTINGS_H 9 | #define CUSERS_SETTINGS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_SETTINGS_US_KEY[30+1]; 16 | typedef char USERS_SETTINGS_US_VAL[250+1]; 17 | 18 | 19 | typedef struct 20 | { 21 | int user_id; 22 | USERS_SETTINGS_US_KEY us_key; 23 | USERS_SETTINGS_US_VAL us_val; 24 | } USERS_SETTINGS_REC; 25 | 26 | 27 | class Cusers_settings : public USERS_SETTINGS_REC, public Cdb 28 | { 29 | public: 30 | Cusers_settings(); 31 | ~Cusers_settings(); 32 | 33 | // Get the next record 34 | // Return false if end of record set 35 | bool Fetch(); 36 | 37 | // Get one record by PK 38 | // Not Found will return false 39 | bool Get(int arg_user_id, const std::string& arg_us_key); 40 | 41 | // Insert record 42 | unsigned Insert(); 43 | 44 | // Update record by PK 45 | void Update(int arg_user_id, const std::string& arg_us_key); 46 | 47 | // Delete record by PK 48 | void Delete(int arg_user_id, const std::string& arg_us_key); 49 | 50 | // Insert or update record by PK 51 | void Set(int arg_user_id, const std::string& arg_us_key); 52 | 53 | // Reset all values 54 | void Reset(); 55 | 56 | 57 | private: 58 | static bool slots_[CDB_MAX_INSTANCES]; 59 | 60 | int k_user_id_; 61 | USERS_SETTINGS_US_KEY k_us_key_; 62 | 63 | unsigned long us_key_len_; 64 | unsigned long us_val_len_; 65 | 66 | unsigned long k_us_key_len_; 67 | 68 | my_bool user_id_is_null_; 69 | my_bool us_key_is_null_; 70 | my_bool us_val_is_null_; 71 | 72 | MYSQL_BIND bndk_[2]; 73 | MYSQL_BIND bndi_[5]; 74 | MYSQL_BIND bndo_[3]; 75 | 76 | void bindKey(MYSQL_STMT *s, int arg_user_id, const std::string& arg_us_key); 77 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_user_id=0, const std::string& arg_us_key=""); 78 | void bindOutput(MYSQL_STMT *s); 79 | void bindSetOutput(); 80 | 81 | }; 82 | 83 | 84 | #endif /* CUSERS_SETTINGS_H */ 85 | -------------------------------------------------------------------------------- /lib/Cusers_messages.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:17:27, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_MESSAGES_H 9 | #define CUSERS_MESSAGES_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_MESSAGES_EMAIL[120+1]; 16 | typedef char USERS_MESSAGES_MESSAGE[65535+1]; 17 | typedef char USERS_MESSAGES_CREATED[19+1]; 18 | 19 | 20 | typedef struct 21 | { 22 | int user_id; 23 | int msg_id; 24 | USERS_MESSAGES_EMAIL email; 25 | USERS_MESSAGES_MESSAGE message; 26 | USERS_MESSAGES_CREATED created; 27 | } USERS_MESSAGES_REC; 28 | 29 | 30 | class Cusers_messages : public USERS_MESSAGES_REC, public Cdb 31 | { 32 | public: 33 | Cusers_messages(); 34 | ~Cusers_messages(); 35 | 36 | // Get the next record 37 | // Return false if end of record set 38 | bool Fetch(); 39 | 40 | // Get one record by PK 41 | // Not Found will return false 42 | bool Get(int arg_user_id, int arg_msg_id); 43 | 44 | // Insert record 45 | unsigned Insert(); 46 | 47 | // Update record by PK 48 | void Update(int arg_user_id, int arg_msg_id); 49 | 50 | // Delete record by PK 51 | void Delete(int arg_user_id, int arg_msg_id); 52 | 53 | // Insert or update record by PK 54 | void Set(int arg_user_id, int arg_msg_id); 55 | 56 | // Reset all values 57 | void Reset(); 58 | 59 | 60 | private: 61 | static bool slots_[CDB_MAX_INSTANCES]; 62 | 63 | int k_user_id_; 64 | int k_msg_id_; 65 | 66 | unsigned long email_len_; 67 | unsigned long message_len_; 68 | MYSQL_TIME t_created_; 69 | 70 | 71 | my_bool user_id_is_null_; 72 | my_bool msg_id_is_null_; 73 | my_bool email_is_null_; 74 | my_bool message_is_null_; 75 | my_bool created_is_null_; 76 | 77 | MYSQL_BIND bndk_[2]; 78 | MYSQL_BIND bndi_[7]; 79 | MYSQL_BIND bndo_[5]; 80 | 81 | void bindKey(MYSQL_STMT *s, int arg_user_id, int arg_msg_id); 82 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_user_id=0, int arg_msg_id=0); 83 | void bindOutput(MYSQL_STMT *s); 84 | void bindSetOutput(); 85 | 86 | void genDTStrings(); 87 | }; 88 | 89 | 90 | #endif /* CUSERS_MESSAGES_H */ 91 | -------------------------------------------------------------------------------- /lib/Cusers_activations.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:16:31, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_ACTIVATIONS_H 9 | #define CUSERS_ACTIVATIONS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_ACTIVATIONS_LINKKEY[20+1]; 16 | typedef char USERS_ACTIVATIONS_CREATED[19+1]; 17 | typedef char USERS_ACTIVATIONS_ACTIVATED[19+1]; 18 | 19 | 20 | typedef struct 21 | { 22 | USERS_ACTIVATIONS_LINKKEY linkkey; 23 | int user_id; 24 | USERS_ACTIVATIONS_CREATED created; 25 | USERS_ACTIVATIONS_ACTIVATED activated; 26 | } USERS_ACTIVATIONS_REC; 27 | 28 | 29 | class Cusers_activations : public USERS_ACTIVATIONS_REC, public Cdb 30 | { 31 | public: 32 | Cusers_activations(); 33 | ~Cusers_activations(); 34 | 35 | // Get the next record 36 | // Return false if end of record set 37 | bool Fetch(); 38 | 39 | // Get one record by PK 40 | // Not Found will return false 41 | bool Get(const std::string& arg_linkkey); 42 | 43 | // Insert record 44 | unsigned Insert(); 45 | 46 | // Update record by PK 47 | void Update(const std::string& arg_linkkey); 48 | 49 | // Delete record by PK 50 | void Delete(const std::string& arg_linkkey); 51 | 52 | // Insert or update record by PK 53 | void Set(const std::string& arg_linkkey); 54 | 55 | // Reset all values 56 | void Reset(); 57 | 58 | 59 | private: 60 | static bool slots_[CDB_MAX_INSTANCES]; 61 | 62 | USERS_ACTIVATIONS_LINKKEY k_linkkey_; 63 | 64 | unsigned long linkkey_len_; 65 | MYSQL_TIME t_created_; 66 | MYSQL_TIME t_activated_; 67 | 68 | unsigned long k_linkkey_len_; 69 | 70 | my_bool linkkey_is_null_; 71 | my_bool user_id_is_null_; 72 | my_bool created_is_null_; 73 | my_bool activated_is_null_; 74 | 75 | MYSQL_BIND bndk_[1]; 76 | MYSQL_BIND bndi_[5]; 77 | MYSQL_BIND bndo_[4]; 78 | 79 | void bindKey(MYSQL_STMT *s, const std::string& arg_linkkey); 80 | void bindInput(MYSQL_STMT *s, bool withKey=false, const std::string& arg_linkkey=""); 81 | void bindOutput(MYSQL_STMT *s); 82 | void bindSetOutput(); 83 | 84 | void genDTStrings(); 85 | }; 86 | 87 | 88 | #endif /* CUSERS_ACTIVATIONS_H */ 89 | -------------------------------------------------------------------------------- /resmin/dsk.js: -------------------------------------------------------------------------------- 1 | var started; 2 | var batches_done=0; 3 | var elapsed=0; 4 | 5 | 6 | // -------------------------------------------------------------------------- 7 | // AJAX call 8 | // -------------------------------------------------------------------------- 9 | function sendreqs() 10 | { 11 | wait(); 12 | 13 | let url = document.getElementById("url").value; 14 | let batches = document.getElementById("batches").value; 15 | let times = document.getElementById("times").value; 16 | let keep = document.getElementById("keep").checked; 17 | 18 | if ( batches < 1 ) batches = 1; 19 | if ( batches > 1000 ) batches = 1000; 20 | 21 | if ( times < 1 ) times = 1; 22 | if ( times > 100000 ) times = 100000; 23 | 24 | p(" "); 25 | 26 | p("Sending "+batches+" batch(es) of "+times+" requests each to "+url); 27 | 28 | p("keep = " + keep); 29 | 30 | url = encodeURIComponent(url); 31 | 32 | batches_done = 0; 33 | started = performance.now(); 34 | elapsed = 0; 35 | 36 | for ( i=1; i<=batches; ++i ) 37 | sendbatch(url, times, keep, i, batches); 38 | 39 | document.getElementById("url").focus(); 40 | } 41 | 42 | 43 | // -------------------------------------------------------------------------- 44 | // Send one request 45 | // -------------------------------------------------------------------------- 46 | function sendbatch(url, times, keep, i, batches) 47 | { 48 | let x = new XMLHttpRequest(); 49 | 50 | x.onreadystatechange = function(e) 51 | { 52 | if ( x.readyState == 4 ) // Done 53 | { 54 | ++batches_done; 55 | 56 | let ret = x.responseText.split("|"); 57 | 58 | if ( ret[0]=="0" ) // OK 59 | { 60 | p(i+": Average = "+ret[2]+" ms"); 61 | 62 | if ( batches_done==batches ) // the last one 63 | { 64 | elapsed = performance.now() - started; 65 | wait_off(); 66 | p("elapsed: "+elapsed+" ms"); 67 | let seconds = elapsed / 1000; 68 | let per_second = (times*batches) / seconds; 69 | p(parseInt(per_second, 10) + " per second"); 70 | } 71 | } 72 | else // error 73 | { 74 | p(i+": Error: "+ret[1]); 75 | 76 | if ( batches_done==batches ) // the last one 77 | { 78 | wait_off(); 79 | } 80 | } 81 | } 82 | }; 83 | 84 | x.open("GET", "sendbatch?batch="+i+"&url="+url+"×="+times+"&keep="+keep, true); 85 | x.send(); 86 | } 87 | -------------------------------------------------------------------------------- /lib/Cusers_logins.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 14:28:27, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_LOGINS_H 9 | #define CUSERS_LOGINS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_LOGINS_SESSID[15+1]; 16 | typedef char USERS_LOGINS_UAGENT[250+1]; 17 | typedef char USERS_LOGINS_IP[45+1]; 18 | typedef char USERS_LOGINS_CSRFT[7+1]; 19 | typedef char USERS_LOGINS_CREATED[19+1]; 20 | typedef char USERS_LOGINS_LAST_USED[19+1]; 21 | 22 | 23 | typedef struct 24 | { 25 | USERS_LOGINS_SESSID sessid; 26 | USERS_LOGINS_UAGENT uagent; 27 | USERS_LOGINS_IP ip; 28 | int user_id; 29 | USERS_LOGINS_CSRFT csrft; 30 | USERS_LOGINS_CREATED created; 31 | USERS_LOGINS_LAST_USED last_used; 32 | } USERS_LOGINS_REC; 33 | 34 | 35 | class Cusers_logins : public USERS_LOGINS_REC, public Cdb 36 | { 37 | public: 38 | Cusers_logins(); 39 | ~Cusers_logins(); 40 | 41 | // Get the next record 42 | // Return false if end of record set 43 | bool Fetch(); 44 | 45 | // Get one record by PK 46 | // Not Found will return false 47 | bool Get(const std::string& arg_sessid); 48 | 49 | // Insert record 50 | unsigned Insert(); 51 | 52 | // Update record by PK 53 | void Update(const std::string& arg_sessid); 54 | 55 | // Delete record by PK 56 | void Delete(const std::string& arg_sessid); 57 | 58 | // Insert or update record by PK 59 | void Set(const std::string& arg_sessid); 60 | 61 | // Reset all values 62 | void Reset(); 63 | 64 | 65 | private: 66 | static bool slots_[CDB_MAX_INSTANCES]; 67 | 68 | USERS_LOGINS_SESSID k_sessid_; 69 | 70 | unsigned long sessid_len_; 71 | unsigned long uagent_len_; 72 | unsigned long ip_len_; 73 | unsigned long csrft_len_; 74 | MYSQL_TIME t_created_; 75 | MYSQL_TIME t_last_used_; 76 | 77 | unsigned long k_sessid_len_; 78 | 79 | my_bool sessid_is_null_; 80 | my_bool uagent_is_null_; 81 | my_bool ip_is_null_; 82 | my_bool user_id_is_null_; 83 | my_bool csrft_is_null_; 84 | my_bool created_is_null_; 85 | my_bool last_used_is_null_; 86 | 87 | MYSQL_BIND bndk_[1]; 88 | MYSQL_BIND bndi_[8]; 89 | MYSQL_BIND bndo_[7]; 90 | 91 | void bindKey(MYSQL_STMT *s, const std::string& arg_sessid); 92 | void bindInput(MYSQL_STMT *s, bool withKey=false, const std::string& arg_sessid=""); 93 | void bindOutput(MYSQL_STMT *s); 94 | void bindSetOutput(); 95 | 96 | void genDTStrings(); 97 | }; 98 | 99 | 100 | #endif /* CUSERS_LOGINS_H */ 101 | -------------------------------------------------------------------------------- /bin/nppstop: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ------------------------------------------------------------------------------ 4 | # 5 | # MIT License 6 | # 7 | # Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all 17 | # copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | # 27 | # ------------------------------------------------------------------------------ 28 | # 29 | # Node++ stop 30 | # nodepp.org 31 | # 32 | # ------------------------------------------------------------------------------ 33 | 34 | 35 | # --------------------------------------------------------------------- 36 | # Environment check 37 | 38 | if [ -z $NPP_DIR ] 39 | then 40 | if [ -f ./npp_app ] 41 | then 42 | echo "WARNING: No NPP_DIR variable, setting to parent directory" 43 | export NPP_DIR=.. 44 | else 45 | echo "ERROR: No NPP_DIR variable and no npp_app file present in the current directory, couldn't stop." 46 | echo "Your npp_app should be in \$NPP_DIR/bin" 47 | echo "Set the NPP_DIR environment variable like this:" 48 | echo "" 49 | echo "export NPP_DIR=/path/to/npp_application" 50 | echo "" 51 | exit 1 52 | fi 53 | fi 54 | 55 | # --------------------------------------------------------------------- 56 | 57 | echo "Stopping Node++ App..." 58 | 59 | # --------------------------------------------------------------------- 60 | # Services 61 | 62 | if [ -n "$(find $NPP_DIR/bin -name 's_*.pid' | head -1)" ] 63 | then 64 | for f in $NPP_DIR/bin/s_*.pid 65 | do 66 | kill `cat ${f}` 67 | done 68 | fi 69 | 70 | # --------------------------------------------------------------------- 71 | # Main app 72 | 73 | if [ -f $NPP_DIR/bin/npp_app.pid ] 74 | then 75 | kill `cat $NPP_DIR/bin/npp_app.pid` 76 | fi 77 | 78 | # --------------------------------------------------------------------- 79 | -------------------------------------------------------------------------------- /bin/nppstart: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ------------------------------------------------------------------------------ 4 | # 5 | # MIT License 6 | # 7 | # Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all 17 | # copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | # 27 | # ------------------------------------------------------------------------------ 28 | # 29 | # Node++ startup 30 | # nodepp.org 31 | # 32 | # ------------------------------------------------------------------------------ 33 | 34 | 35 | # --------------------------------------------------------------------- 36 | # Environment check 37 | 38 | if [ -z $NPP_DIR ] 39 | then 40 | if [ -f ./npp_app ] 41 | then 42 | echo "WARNING: No NPP_DIR variable, setting to parent directory" 43 | export NPP_DIR=.. 44 | else 45 | echo "ERROR: No NPP_DIR variable and no npp_app file present in the current directory, couldn't start." 46 | echo "Your npp_app should be in \$NPP_DIR/bin" 47 | echo "Set the NPP_DIR environment variable like this:" 48 | echo "" 49 | echo "export NPP_DIR=/path/to/npp_application" 50 | echo "" 51 | exit 1 52 | fi 53 | fi 54 | 55 | # --------------------------------------------------------------------- 56 | 57 | echo "Starting Node++ App..." 58 | 59 | # --------------------------------------------------------------------- 60 | # Main app 61 | 62 | nohup $NPP_DIR/bin/npp_app > /dev/null 2>&1 & 63 | 64 | # --------------------------------------------------------------------- 65 | # Services 66 | 67 | if [ -f $NPP_DIR/bin/npp.conf ] 68 | then 69 | NPP_SVC_PROCESSES=`grep '^ASYNCSvcProcesses' $NPP_DIR/bin/npp.conf | head -1 | cut -d '=' -f 2 | sed 's/\r$//'` 70 | fi 71 | 72 | if [ -z $NPP_SVC_PROCESSES ] 73 | then 74 | NPP_SVC_PROCESSES=0 75 | fi 76 | 77 | if [ $NPP_SVC_PROCESSES -ne 0 ] 78 | then 79 | echo "Starting" $NPP_SVC_PROCESSES "svc process(es)..." 80 | 81 | sleep 1 # wait for the ASYNC queues to open 82 | 83 | for i in `seq 1 $NPP_SVC_PROCESSES` 84 | do 85 | nohup $NPP_DIR/bin/npp_svc > /dev/null 2>&1 & 86 | done 87 | fi 88 | 89 | # --------------------------------------------------------------------- 90 | 91 | sleep 1 # return to prompt 92 | -------------------------------------------------------------------------------- /lib/users.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------------------------------------------------------- 2 | -- Node++ USERS module tables -- MySQL version 3 | -- nodepp.org 4 | -- ---------------------------------------------------------------------------- 5 | 6 | -- users 7 | 8 | CREATE TABLE users 9 | ( 10 | id INT auto_increment PRIMARY KEY, 11 | login CHAR(30), 12 | login_u CHAR(30), -- uppercase version 13 | email VARCHAR(120), 14 | email_u VARCHAR(120), -- uppercase version 15 | name VARCHAR(120), 16 | phone VARCHAR(30), 17 | passwd1 CHAR(44), -- SHA256 hash in base64 18 | passwd2 CHAR(44), -- SHA256 hash in base64 19 | lang CHAR(5), 20 | about VARCHAR(250), 21 | group_id INT, 22 | auth_level TINYINT, -- 10 = user, 20 = customer, 30 = staff, 40 = moderator, 50 = admin, 100 = root 23 | status TINYINT, -- 0 = inactive, 1 = active, 2 = locked, 3 = requires password change, 9 = deleted 24 | created DATETIME, 25 | last_login DATETIME, 26 | visits INT, 27 | ula_cnt INT, -- unsuccessful login attempt count 28 | ula_time DATETIME -- and time 29 | ); 30 | 31 | CREATE INDEX users_login ON users (login_u); 32 | CREATE INDEX users_email ON users (email_u); 33 | CREATE INDEX users_last_login ON users (last_login); 34 | 35 | 36 | -- avatars 37 | 38 | CREATE TABLE users_avatars 39 | ( 40 | user_id INT PRIMARY KEY, 41 | avatar_name VARCHAR(120), 42 | avatar_data BLOB, -- 64 KiB 43 | avatar_len INT 44 | ); 45 | 46 | 47 | -- groups 48 | 49 | CREATE TABLE users_groups 50 | ( 51 | id INT auto_increment PRIMARY KEY, 52 | name VARCHAR(120), 53 | about VARCHAR(250), 54 | auth_level TINYINT 55 | ); 56 | 57 | 58 | -- user settings 59 | 60 | CREATE TABLE users_settings 61 | ( 62 | user_id INT, 63 | us_key CHAR(30), 64 | us_val VARCHAR(250), 65 | PRIMARY KEY (user_id, us_key) 66 | ); 67 | 68 | 69 | -- user logins 70 | 71 | CREATE TABLE users_logins 72 | ( 73 | sessid CHAR(15) CHARACTER SET latin1 COLLATE latin1_bin PRIMARY KEY, 74 | uagent VARCHAR(250), 75 | ip CHAR(45), 76 | user_id INT, 77 | csrft CHAR(7), 78 | created DATETIME, 79 | last_used DATETIME 80 | ); 81 | 82 | CREATE INDEX users_logins_uid ON users_logins (user_id); 83 | 84 | 85 | -- account activations 86 | 87 | CREATE TABLE users_activations 88 | ( 89 | linkkey CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin PRIMARY KEY, 90 | user_id INT, 91 | created DATETIME, 92 | activated DATETIME 93 | ); 94 | 95 | 96 | -- password resets 97 | 98 | CREATE TABLE users_p_resets 99 | ( 100 | linkkey CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin PRIMARY KEY, 101 | user_id INT, 102 | created DATETIME, 103 | tries SMALLINT 104 | ); 105 | 106 | CREATE INDEX users_p_resets_uid ON users_p_resets (user_id); 107 | 108 | 109 | -- messages 110 | 111 | CREATE TABLE users_messages 112 | ( 113 | user_id INT, 114 | msg_id INT, 115 | email VARCHAR(120), 116 | message TEXT, -- 64 KiB limit 117 | created DATETIME, 118 | PRIMARY KEY (user_id, msg_id) 119 | ); 120 | -------------------------------------------------------------------------------- /src/npp_svc.cpp: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Node++ Web App 3 | Jurek Muszynski 4 | ----------------------------------------------------------------------------- 5 | Web App Performance Tester 6 | -------------------------------------------------------------------------- */ 7 | 8 | 9 | #include 10 | 11 | 12 | /* ======================================================================= */ 13 | /* =============================== SERVICES ============================== */ 14 | /* ======================================================================= */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- 18 | Service 19 | -------------------------------------------------------------------------- */ 20 | int sendbatch(int ci) 21 | { 22 | INF("sendbatch"); 23 | 24 | INF("batch = %d", SESSION_DATA.batch); 25 | INF("URL [%s]", SESSION_DATA.url); 26 | INF("times = %d", SESSION_DATA.times); 27 | 28 | struct timespec start; 29 | clock_gettime(MONOTONIC_CLOCK_NAME, &start); 30 | 31 | char perfreqid[256]; 32 | bool success; 33 | 34 | for ( int i=0; itm_hour, G_ptm->tm_min, G_ptm->tm_sec, SESSION_DATA.batch, i); 40 | INF("perfreqid [%s]", perfreqid); 41 | CALL_HTTP_HEADER_SET("perfreqid", perfreqid); 42 | 43 | // if ( SESSION_DATA.keep ) 44 | // success = npp_call_http(NULL, NULL, "GET", SESSION_DATA.url, FALSE, TRUE); 45 | // else 46 | success = CALL_HTTP(NULL, NULL, "GET", SESSION_DATA.url, SESSION_DATA.keep); 47 | 48 | if ( !success ) 49 | { 50 | ERR("Remote call failed\n"); 51 | SESSION_DATA.elapsed = npp_elapsed(&start); 52 | return ERR_REMOTE_CALL; 53 | } 54 | 55 | // INF("Remote call status: %d", CALL_HTTP_STATUS); 56 | } 57 | 58 | SESSION_DATA.elapsed = npp_elapsed(&start); 59 | 60 | INF("elapsed: %.3lf ms\n", SESSION_DATA.elapsed); 61 | 62 | return OK; 63 | } 64 | 65 | 66 | 67 | 68 | /* ======================================================================= */ 69 | /* ========================== END OF SERVICES ============================ */ 70 | /* ======================================================================= */ 71 | 72 | 73 | 74 | /* -------------------------------------------------------------------------- 75 | Entry point 76 | -------------------------------------------------------------------------- */ 77 | void npp_svc_main(int ci) 78 | { 79 | if ( SVC("sendbatch") ) 80 | ASYNC_ERR_CODE = sendbatch(ci); 81 | 82 | OUT("%d|", ASYNC_ERR_CODE); 83 | 84 | if ( ASYNC_ERR_CODE == ERR_REMOTE_CALL ) 85 | OUT("Call failed"); 86 | else if ( ASYNC_ERR_CODE == ERR_REMOTE_CALL_STATUS ) 87 | OUT("Call response status wasn't successful"); 88 | else if ( ASYNC_ERR_CODE == OK ) 89 | OUT("OK"); 90 | 91 | OUT("|%s", AMT(G_call_http_average)); 92 | OUT("|%0.3lf", SESSION_DATA.elapsed); 93 | 94 | RES_DONT_CACHE; 95 | } 96 | 97 | 98 | /* -------------------------------------------------------------------------- 99 | Server start 100 | Return true if successful 101 | -------------------------------------------------------------------------- */ 102 | bool npp_svc_init() 103 | { 104 | return true; 105 | } 106 | 107 | 108 | /* -------------------------------------------------------------------------- 109 | Server stop 110 | -------------------------------------------------------------------------- */ 111 | void npp_svc_done() 112 | { 113 | } 114 | -------------------------------------------------------------------------------- /lib/Cusers.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-29 20:05:41, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #ifndef CUSERS_H 9 | #define CUSERS_H 10 | 11 | 12 | #include 13 | 14 | 15 | typedef char USERS_LOGIN[30+1]; 16 | typedef char USERS_LOGIN_U[30+1]; 17 | typedef char USERS_EMAIL[120+1]; 18 | typedef char USERS_EMAIL_U[120+1]; 19 | typedef char USERS_NAME[120+1]; 20 | typedef char USERS_PHONE[30+1]; 21 | typedef char USERS_PASSWD1[44+1]; 22 | typedef char USERS_PASSWD2[44+1]; 23 | typedef char USERS_LANG[5+1]; 24 | typedef char USERS_ABOUT[250+1]; 25 | typedef char USERS_CREATED[19+1]; 26 | typedef char USERS_LAST_LOGIN[19+1]; 27 | typedef char USERS_ULA_TIME[19+1]; 28 | 29 | 30 | typedef struct 31 | { 32 | int id; 33 | USERS_LOGIN login; 34 | USERS_LOGIN_U login_u; 35 | USERS_EMAIL email; 36 | USERS_EMAIL_U email_u; 37 | USERS_NAME name; 38 | USERS_PHONE phone; 39 | USERS_PASSWD1 passwd1; 40 | USERS_PASSWD2 passwd2; 41 | USERS_LANG lang; 42 | USERS_ABOUT about; 43 | int group_id; 44 | char auth_level; 45 | char status; 46 | USERS_CREATED created; 47 | USERS_LAST_LOGIN last_login; 48 | int visits; 49 | int ula_cnt; 50 | USERS_ULA_TIME ula_time; 51 | } USERS_REC; 52 | 53 | 54 | class Cusers : public USERS_REC, public Cdb 55 | { 56 | public: 57 | Cusers(); 58 | ~Cusers(); 59 | 60 | // Get the next record 61 | // Return false if end of record set 62 | bool Fetch(); 63 | 64 | // Get one record by PK 65 | // Not Found will return false 66 | bool Get(int arg_id); 67 | 68 | // Insert record 69 | unsigned Insert(); 70 | 71 | // Update record by PK 72 | void Update(int arg_id); 73 | 74 | // Delete record by PK 75 | void Delete(int arg_id); 76 | 77 | // Insert or update record by PK 78 | void Set(int arg_id); 79 | 80 | // Reset all values 81 | void Reset(); 82 | 83 | 84 | private: 85 | static bool slots_[CDB_MAX_INSTANCES]; 86 | 87 | int k_id_; 88 | 89 | unsigned long login_len_; 90 | unsigned long login_u_len_; 91 | unsigned long email_len_; 92 | unsigned long email_u_len_; 93 | unsigned long name_len_; 94 | unsigned long phone_len_; 95 | unsigned long passwd1_len_; 96 | unsigned long passwd2_len_; 97 | unsigned long lang_len_; 98 | unsigned long about_len_; 99 | MYSQL_TIME t_created_; 100 | MYSQL_TIME t_last_login_; 101 | MYSQL_TIME t_ula_time_; 102 | 103 | 104 | my_bool id_is_null_; 105 | my_bool login_is_null_; 106 | my_bool login_u_is_null_; 107 | my_bool email_is_null_; 108 | my_bool email_u_is_null_; 109 | my_bool name_is_null_; 110 | my_bool phone_is_null_; 111 | my_bool passwd1_is_null_; 112 | my_bool passwd2_is_null_; 113 | my_bool lang_is_null_; 114 | my_bool about_is_null_; 115 | my_bool group_id_is_null_; 116 | my_bool auth_level_is_null_; 117 | my_bool status_is_null_; 118 | my_bool created_is_null_; 119 | my_bool last_login_is_null_; 120 | my_bool visits_is_null_; 121 | my_bool ula_cnt_is_null_; 122 | my_bool ula_time_is_null_; 123 | 124 | MYSQL_BIND bndk_[1]; 125 | MYSQL_BIND bndi_[20]; 126 | MYSQL_BIND bndo_[19]; 127 | 128 | void bindKey(MYSQL_STMT *s, int arg_id); 129 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_id=0); 130 | void bindOutput(MYSQL_STMT *s); 131 | void bindSetOutput(); 132 | 133 | void genDTStrings(); 134 | }; 135 | 136 | 137 | #endif /* CUSERS_H */ 138 | -------------------------------------------------------------------------------- /lib/npp_watcher.c: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | ----------------------------------------------------------------------------- 26 | 27 | Node++ Web App Engine 28 | Restart Node++ app if dead 29 | nodepp.org 30 | 31 | -------------------------------------------------------------------------- */ 32 | 33 | 34 | #include "npp.h" 35 | 36 | 37 | #define STOP_COMMAND "$NPP_DIR/bin/nppstop" 38 | #define START_COMMAND "$NPP_DIR/bin/nppstart" 39 | 40 | 41 | int G_httpPort=80; 42 | 43 | 44 | static char M_watcherStopCmd[256]; 45 | static char M_watcherStartCmd[256]; 46 | static int M_watcherWait; 47 | static int M_watcherLogRestart; 48 | 49 | 50 | /* -------------------------------------------------------------------------- 51 | Restart 52 | -------------------------------------------------------------------------- */ 53 | static void restart() 54 | { 55 | ALWAYS_T("Restarting..."); 56 | 57 | INF_T("Stopping..."); 58 | INF_T(M_watcherStopCmd); 59 | 60 | if ( system(M_watcherStopCmd) != EXIT_SUCCESS ) 61 | WAR("Couldn't execute %s", M_watcherStopCmd); 62 | 63 | npp_update_time_globals(); 64 | 65 | INF_T("Waiting %d second(s)...", M_watcherWait); 66 | #ifdef _WIN32 67 | Sleep(M_watcherWait*1000); 68 | #else /* Linux */ 69 | sleep(M_watcherWait); 70 | #endif 71 | 72 | npp_update_time_globals(); 73 | 74 | INF_T("Starting..."); 75 | INF_T(M_watcherStartCmd); 76 | 77 | if ( system(M_watcherStartCmd) != EXIT_SUCCESS ) 78 | WAR("Couldn't execute %s", M_watcherStartCmd); 79 | 80 | #ifdef NPP_ADMIN_EMAIL 81 | if ( strlen(NPP_ADMIN_EMAIL) ) 82 | { 83 | char message[1024]; 84 | strcpy(message, "Node++ Watcher had to restart web server."); 85 | npp_email(NPP_ADMIN_EMAIL, "Node++ restart", message); 86 | } 87 | #endif 88 | } 89 | 90 | 91 | /* -------------------------------------------------------------------------- 92 | main 93 | -------------------------------------------------------------------------- */ 94 | int main(int argc, char *argv[]) 95 | { 96 | /* library init ------------------------------------------------------ */ 97 | 98 | if ( !npp_lib_init(FALSE, NULL) ) 99 | return EXIT_FAILURE; 100 | 101 | /* ------------------------------------------------------------------- */ 102 | 103 | if ( !npp_read_param_int("watcherLogLevel", &G_logLevel) ) 104 | G_logLevel = 0; /* don't create log file */ 105 | 106 | if ( !npp_read_param_int("watcherLogToStdout", &G_logToStdout) ) 107 | G_logToStdout = 0; 108 | 109 | if ( !npp_read_param_str("watcherStopCmd", M_watcherStopCmd) ) 110 | strcpy(M_watcherStopCmd, STOP_COMMAND); 111 | 112 | if ( !npp_read_param_str("watcherStartCmd", M_watcherStartCmd) ) 113 | strcpy(M_watcherStartCmd, START_COMMAND); 114 | 115 | if ( !npp_read_param_int("watcherWait", &M_watcherWait) ) 116 | M_watcherWait = 10; 117 | 118 | if ( !npp_read_param_int("watcherLogRestart", &M_watcherLogRestart) ) 119 | M_watcherLogRestart = 3; 120 | 121 | /* start log --------------------------------------------------------- */ 122 | 123 | if ( G_logLevel && !npp_log_start("watcher", FALSE, FALSE) ) 124 | return EXIT_FAILURE; 125 | 126 | /* ------------------------------------------------------------------- */ 127 | 128 | INF_T("Trying to connect..."); 129 | 130 | G_callHTTPTimeout = 60000; /* 60 seconds */ 131 | 132 | char url[1024]; 133 | 134 | sprintf(url, "127.0.0.1:%d", G_httpPort); 135 | 136 | CALL_HTTP_HEADER_SET("User-Agent", "Node++ Watcher Bot"); 137 | 138 | if ( !CALL_HTTP(NULL, NULL, "GET", url, FALSE) ) 139 | { 140 | npp_update_time_globals(); 141 | 142 | if ( M_watcherLogRestart > G_logLevel ) 143 | { 144 | int old_level = G_logLevel; 145 | G_logLevel = M_watcherLogRestart; 146 | if ( old_level < 1 ) 147 | npp_log_start("watcher", FALSE, FALSE); 148 | } 149 | 150 | ERR_T("Couldn't connect"); 151 | 152 | restart(); 153 | } 154 | 155 | /* ------------------------------------------------------------------- */ 156 | 157 | npp_update_time_globals(); 158 | 159 | INF_T("npp_watcher ended"); 160 | 161 | npp_lib_done(); 162 | 163 | return EXIT_SUCCESS; 164 | } 165 | -------------------------------------------------------------------------------- /resmin/npp.js: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------- 2 | // Show wait animation 3 | // -------------------------------------------------------------------------- 4 | function wait() 5 | { 6 | if ( !document.getElementById("wait") ) 7 | { 8 | let w = document.createElement("div"); 9 | w.id = "wait"; 10 | w.className = "wt"; // see npp.css 11 | w.style.display = "block"; 12 | document.body.appendChild(w); 13 | } 14 | else 15 | document.getElementById("wait").style.display = "block"; 16 | } 17 | 18 | 19 | // -------------------------------------------------------------------------- 20 | // Turn the spinning wheel off 21 | // -------------------------------------------------------------------------- 22 | function wait_off() 23 | { 24 | document.getElementById("wait").style.display = "none"; 25 | } 26 | 27 | 28 | // -------------------------------------------------------------------------- 29 | // Go to link 30 | // l = url 31 | // -------------------------------------------------------------------------- 32 | function gt(l) 33 | { 34 | wait(); 35 | window.location.href = l; 36 | } 37 | 38 | 39 | // -------------------------------------------------------------------------- 40 | // Append a paragraph to the page 41 | // -------------------------------------------------------------------------- 42 | function p(t) 43 | { 44 | let p = document.createElement("p"); 45 | if ( t ) p.innerHTML = t; 46 | document.body.appendChild(p); 47 | return p; 48 | } 49 | 50 | 51 | // -------------------------------------------------------------------------- 52 | // Enter or Esc key hit 53 | // -------------------------------------------------------------------------- 54 | function ent(e) 55 | { 56 | if (e.keyCode==13) // Enter 57 | { 58 | document.getElementById("sbm").click(); // submit 59 | return false; 60 | } 61 | else if (e.keyCode==27) // Esc 62 | { 63 | document.getElementById("cnc").click(); // cancel 64 | return false; 65 | } 66 | 67 | return true; 68 | } 69 | 70 | 71 | // -------------------------------------------------------------------------- 72 | // Return true if cookies are enabled 73 | // -------------------------------------------------------------------------- 74 | function cookies() 75 | { 76 | try 77 | { 78 | document.cookie = "ct=1"; 79 | let enabled = document.cookie.indexOf("ct=") !== -1; 80 | document.cookie = "ct=1; expires=Thu, 01-Jan-1970 00:00:01 GMT"; 81 | return enabled; 82 | } 83 | catch (e) 84 | { 85 | return false; 86 | } 87 | } 88 | 89 | 90 | // -------------------------------------------------------------------------- 91 | // Center div 92 | // Call after appendChild 93 | // d = div handle 94 | // -------------------------------------------------------------------------- 95 | function center(d) 96 | { 97 | d.style.position = "fixed"; 98 | d.style.top = "50%"; 99 | d.style.left = "50%"; 100 | d.style.marginTop = -d.offsetTop/2 + "px"; 101 | d.style.marginLeft = -d.offsetWidth/2 + "px"; 102 | } 103 | 104 | 105 | // -------------------------------------------------------------------------- 106 | // Create modal window 107 | // l1 = first line 108 | // l2 = second line 109 | // w = width (em) 110 | // -------------------------------------------------------------------------- 111 | function mw(l1, l2, w) 112 | { 113 | let d = document.createElement("div"); 114 | 115 | if ( w ) 116 | d.style.width = w + "em"; 117 | else 118 | d.style.width = "20em"; 119 | 120 | d.className = "mw"; 121 | d.id = "mw"; 122 | 123 | let s1 = document.createElement("span"); 124 | 125 | s1.innerHTML = "
" 126 | + "" + l1 + "" 127 | + "
" 128 | + "

"; 129 | 130 | d.appendChild(s1); 131 | 132 | if ( l2 ) 133 | { 134 | let s2 = document.createElement("span"); 135 | s2.innerHTML = l2; 136 | d.appendChild(s2); 137 | } 138 | 139 | document.body.appendChild(d); 140 | center(d); 141 | 142 | window.addEventListener("keydown", mw_off); // allow keyboard escape 143 | } 144 | 145 | 146 | // -------------------------------------------------------------------------- 147 | // Remove modal window 148 | // -------------------------------------------------------------------------- 149 | function mw_off(e) 150 | { 151 | if ( e && e.keyCode!=27 ) return; 152 | window.removeEventListener("keydown", mw_off); 153 | let d = document.getElementById("mw"); 154 | d.parentNode.removeChild(d); 155 | } 156 | 157 | 158 | // -------------------------------------------------------------------------- 159 | // Create Yes/No modal window 160 | // t = text to display 161 | // a = action if Yes 162 | // w = width (em) 163 | // -------------------------------------------------------------------------- 164 | function yn(t, a, w) 165 | { 166 | mw(t, "
 
", w); 167 | } 168 | 169 | 170 | // -------------------------------------------------------------------------- 171 | // Set client's time on the server 172 | // -------------------------------------------------------------------------- 173 | function set_tz() 174 | { 175 | let dt = new Date(); 176 | 177 | let x = new XMLHttpRequest(); 178 | 179 | x.open("POST", "/npp_set_tz", true); 180 | x.send("tz=" + Intl.DateTimeFormat().resolvedOptions().timeZone + "&tzo=" + dt.getTimezoneOffset()); 181 | } 182 | -------------------------------------------------------------------------------- /bin/nppmake.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ---------------------------------------------------------------------------- 4 | rem 5 | rem MIT License 6 | rem 7 | rem Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 8 | rem 9 | rem Permission is hereby granted, free of charge, to any person obtaining a copy 10 | rem of this software and associated documentation files (the "Software"), to deal 11 | rem in the Software without restriction, including without limitation the rights 12 | rem to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | rem copies of the Software, and to permit persons to whom the Software is 14 | rem furnished to do so, subject to the following conditions: 15 | rem 16 | rem The above copyright notice and this permission notice shall be included in all 17 | rem copies or substantial portions of the Software. 18 | rem 19 | rem THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | rem IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | rem FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | rem AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | rem LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | rem OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | rem SOFTWARE. 26 | rem 27 | rem ---------------------------------------------------------------------------- 28 | rem 29 | rem Compile/make Node++ application on Windows 30 | rem This is a generic script -- customize your environment in src\m.bat 31 | rem nodepp.org 32 | rem 33 | rem ---------------------------------------------------------------------------- 34 | 35 | 36 | set NPP_VERBOSE=0 37 | if /i "%1"=="v" set NPP_VERBOSE=1 38 | 39 | 40 | rem ---------------------------------------------------------------------------- 41 | rem Determine Node++ modules that are enabled in npp_app.h 42 | 43 | call :get_presence "NPP_HTTPS" NPP_HTTPS 44 | 45 | call :get_presence "NPP_MYSQL" NPP_MYSQL 46 | 47 | call :get_presence "NPP_USERS" NPP_USERS 48 | 49 | call :get_presence "NPP_ICONV" NPP_ICONV 50 | 51 | 52 | rem ---------------------------------------------------------------------------- 53 | rem APP modules to compile 54 | 55 | set "NPP_M_MODULES_APP=npp_app.cpp ..\lib\npp_eng_app.c ..\lib\npp_lib.c" 56 | 57 | call :get_quoted_value "NPP_APP_MODULES" NPP_APP_MODULES 58 | 59 | if not "%NPP_APP_MODULES%"=="" ( 60 | set "NPP_M_MODULES_APP=%NPP_M_MODULES_APP% %NPP_APP_MODULES%" 61 | ) 62 | 63 | if %NPP_MYSQL%==1 ( 64 | set "NPP_M_MODULES_APP=%NPP_M_MODULES_APP% ..\lib\npp_mysql.cpp" 65 | ) 66 | 67 | if %NPP_USERS%==1 ( 68 | set "NPP_M_MODULES_APP=%NPP_M_MODULES_APP% ..\lib\npp_usr.cpp ..\lib\Cusers.cpp ..\lib\Cusers_avatars.cpp ..\lib\Cusers_groups.cpp ..\lib\Cusers_settings.cpp ..\lib\Cusers_logins.cpp ..\lib\Cusers_activations.cpp ..\lib\Cusers_p_resets.cpp ..\lib\Cusers_messages.cpp" 69 | ) 70 | 71 | if %NPP_VERBOSE%==1 echo NPP_M_MODULES_APP=%NPP_M_MODULES_APP% 72 | 73 | 74 | rem ---------------------------------------------------------------------------- 75 | rem NPP_CPP_STRINGS 76 | 77 | call :get_presence "NPP_CPP_STRINGS" NPP_CPP_STRINGS 78 | 79 | if %NPP_CPP_STRINGS%==1 ( 80 | set "NPP_M_MODULES_APP=%NPP_M_MODULES_APP% -std=c++17" 81 | ) 82 | 83 | 84 | rem ---------------------------------------------------------------------------- 85 | rem Include paths 86 | 87 | set "NPP_M_INCLUDE=-I. -I..\lib" 88 | 89 | if %NPP_VERBOSE%==1 echo NPP_M_INCLUDE=%NPP_M_INCLUDE% 90 | 91 | 92 | rem ---------------------------------------------------------------------------- 93 | rem System and third-party libraries 94 | 95 | set "NPP_M_LIBS_APP=" 96 | set "NPP_M_LIBS_UPDATE=" 97 | 98 | if %NPP_HTTPS%==1 ( 99 | set "NPP_M_LIBS_APP=-lssl -lcrypto" 100 | set "NPP_M_LIBS_UPDATE=-lssl -lcrypto" 101 | ) 102 | 103 | if %NPP_MYSQL%==1 ( 104 | set "NPP_M_LIBS_APP=%NPP_M_LIBS_APP% -lmysql" 105 | ) 106 | 107 | if %NPP_ICONV%==1 ( 108 | set "NPP_M_LIBS_APP=%NPP_M_LIBS_APP% -liconv" 109 | ) 110 | 111 | set "NPP_M_LIBS_APP=%NPP_M_LIBS_APP% -lpsapi -lws2_32" 112 | set "NPP_M_LIBS_UPDATE=%NPP_M_LIBS_UPDATE% -lpsapi -lws2_32" 113 | 114 | if %NPP_VERBOSE%==1 echo NPP_M_LIBS_APP=%NPP_M_LIBS_APP% 115 | if %NPP_VERBOSE%==1 echo NPP_M_LIBS_UPDATE=%NPP_M_LIBS_UPDATE% 116 | 117 | 118 | rem ---------------------------------------------------------------------------- 119 | rem Compile 120 | 121 | call :get_quoted_value "NPP_APP_NAME" NPP_APP_NAME 122 | 123 | if not "%NPP_APP_NAME%"=="" ( 124 | echo Building %NPP_APP_NAME%... 125 | ) else ( 126 | echo Building application... 127 | ) 128 | 129 | echo Making npp_app... 130 | 131 | g++ %NPP_M_MODULES_APP% ^ 132 | -D NPP_APP ^ 133 | %NPP_M_INCLUDE% ^ 134 | %NPP_M_LIBS_APP% ^ 135 | -O3 ^ 136 | -o ..\bin\npp_app ^ 137 | -static 138 | 139 | 140 | if %errorlevel% neq 0 goto :eof 141 | 142 | 143 | if /i "%1"=="all" ( 144 | 145 | echo Making npp_watcher... 146 | 147 | gcc ..\lib\npp_watcher.c ^ 148 | ..\lib\npp_lib.c ^ 149 | -D NPP_WATCHER ^ 150 | %NPP_M_INCLUDE% ^ 151 | -lws2_32 -lpsapi ^ 152 | -O3 ^ 153 | -o ..\bin\npp_watcher ^ 154 | -static 155 | 156 | 157 | echo Making npp_update... 158 | 159 | gcc ..\lib\npp_update.c ^ 160 | ..\lib\npp_lib.c ^ 161 | -D NPP_UPDATE ^ 162 | %NPP_M_INCLUDE% ^ 163 | %NPP_M_LIBS_UPDATE% ^ 164 | -O3 ^ 165 | -o ..\bin\npp_update ^ 166 | -static 167 | 168 | ) 169 | 170 | 171 | goto :eof 172 | 173 | 174 | rem ---------------------------------------------------------------------------- 175 | rem Functions 176 | 177 | :get_presence 178 | set %~2=0 179 | set FIRST_TOKEN="x" 180 | for /f %%i in ('findstr /r /c:"^#define *%~1$" npp_app.h') do set FIRST_TOKEN=%%i 181 | if "%FIRST_TOKEN%"=="#define" set %~2=1 182 | goto :eof 183 | 184 | 185 | :get_value 186 | set "%~2=" 187 | for /f tokens^=3 %%i in ('findstr /r /c:"^#define *%~1" npp_app.h') do set %~2=%%i 188 | goto :eof 189 | 190 | 191 | :get_quoted_value 192 | set "%~2=" 193 | for /f delims^=^"^ tokens^=2 %%i in ('findstr /r /c:"^#define *%~1" npp_app.h') do set %~2=%%i 194 | goto :eof 195 | -------------------------------------------------------------------------------- /src/npp_app.cpp: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Node++ Web App 3 | Jurek Muszynski 4 | ----------------------------------------------------------------------------- 5 | Web App Performance Tester 6 | -------------------------------------------------------------------------- */ 7 | 8 | 9 | #include 10 | 11 | 12 | /* -------------------------------------------------------------------------- 13 | Output HTML & page header 14 | -------------------------------------------------------------------------- */ 15 | void gen_header(int ci) 16 | { 17 | OUT(""); 18 | OUT(""); 19 | OUT(""); 20 | OUT(""); 21 | OUT("%s", NPP_APP_NAME); 22 | OUT(""); 23 | OUT(""); 24 | OUT(""); 25 | OUT(""); 26 | OUT(""); 27 | 28 | OUT(""); 29 | 30 | if ( REQ("") || REQ("dashboard") ) 31 | OUT("

%s

", NPP_APP_NAME); 32 | else 33 | OUT("

%s

", WAIT, NPP_APP_NAME); 34 | 35 | char lnk_home[256]="Home"; 36 | 37 | if ( REQ("") ) 38 | strcpy(lnk_home, "Home"); 39 | 40 | OUT("
"); 41 | if ( !REQ("") ) OUT(lnk_home); 42 | OUT("
"); 43 | } 44 | 45 | 46 | /* -------------------------------------------------------------------------- 47 | Output footer; body & html tags close here 48 | -------------------------------------------------------------------------- */ 49 | void gen_footer(int ci) 50 | { 51 | OUT(""); 52 | } 53 | 54 | 55 | /* -------------------------------------------------------------------------- 56 | Show main page 57 | -------------------------------------------------------------------------- */ 58 | void gen_page_main(int ci) 59 | { 60 | gen_header(ci); 61 | 62 | OUT(""); 63 | OUT("", ONKEYDOWN); 64 | OUT("", ONKEYDOWN); 65 | OUT("", ONKEYDOWN); 66 | OUT("", ONKEYDOWN); 67 | OUT(""); 68 | OUT("
URL:
Batches:
Reqs/batch:
"); 69 | 70 | gen_footer(ci); 71 | } 72 | 73 | 74 | /* -------------------------------------------------------------------------- 75 | Send one batch (AJAX) 76 | -------------------------------------------------------------------------- */ 77 | void sendbatch(int ci) 78 | { 79 | if ( !QSI("batch", &SESSION_DATA.batch) ) return; 80 | if ( !QS("url", SESSION_DATA.url) ) return; 81 | if ( !QSI("times", &SESSION_DATA.times) ) return; 82 | 83 | QSB("keep", &SESSION_DATA.keep); 84 | 85 | if ( SESSION_DATA.times < 1 ) SESSION_DATA.times = 1; 86 | if ( SESSION_DATA.times > 100000 ) SESSION_DATA.times = 100000; 87 | 88 | INF("batch = %d", SESSION_DATA.batch); 89 | INF("URL [%s]", SESSION_DATA.url); 90 | INF("times = %d", SESSION_DATA.times); 91 | INF("keep = %s", SESSION_DATA.keep?"true":"false"); 92 | 93 | CALL_ASYNC_TM("sendbatch", 600); // 10 minutes timeout 94 | } 95 | 96 | 97 | /* -------------------------------------------------------------------------------- 98 | This is the main entry point for a request 99 | ------------------------------ 100 | Called after parsing HTTP request headers 101 | ------------------------------ 102 | If required (NPP_REQUIRED_AUTH_LEVEL >= AUTH_LEVEL_ANONYMOUS), 103 | the session is already created 104 | 105 | If valid ls cookie is present in the request or 106 | it's over existing connection that has already been authenticated, 107 | the session is already authenticated 108 | ------------------------------ 109 | Response status is 200 by default 110 | Use RES_STATUS() if you want to change it 111 | 112 | Response content type is text/html by default 113 | Use RES_CONTENT_TYPE() if you want to change it 114 | -------------------------------------------------------------------------------- */ 115 | void npp_app_main(int ci) 116 | { 117 | if ( REQ("sendbatch") ) 118 | sendbatch(ci); 119 | else 120 | gen_page_main(ci); 121 | } 122 | 123 | 124 | /* -------------------------------------------------------------------------------- 125 | Called when application starts 126 | ------------------------------ 127 | Return true if everything OK 128 | ------------------------------ 129 | Returning false will stop booting process, 130 | npp_app_done() will be called and application will be terminated 131 | -------------------------------------------------------------------------------- */ 132 | bool npp_app_init(int argc, char *argv[]) 133 | { 134 | return true; 135 | } 136 | 137 | 138 | /* -------------------------------------------------------------------------------- 139 | Called when new anonymous user session starts 140 | ------------------------------ 141 | Return true if everything OK 142 | ------------------------------ 143 | Returning false will cause the session to be closed 144 | and npp_app_session_done() will be called 145 | Response status will be set to 500 146 | -------------------------------------------------------------------------------- */ 147 | bool npp_app_session_init(int ci) 148 | { 149 | return true; 150 | } 151 | 152 | 153 | /* -------------------------------------------------------------------------------- 154 | ******* Only for USERS ******* 155 | ------------------------------ 156 | Called after successful authentication (using password or cookie) 157 | when user session is upgraded from anonymous to logged in 158 | ------------------------------ 159 | Return true if everything OK 160 | ------------------------------ 161 | Returning false will cause the session to be downgraded back to anonymous 162 | and npp_app_user_logout() will be called 163 | -------------------------------------------------------------------------------- */ 164 | bool npp_app_user_login(int ci) 165 | { 166 | return true; 167 | } 168 | 169 | 170 | /* -------------------------------------------------------------------------------- 171 | ******* Only for USERS ******* 172 | ------------------------------ 173 | Called when downgrading logged in user session to anonymous 174 | -------------------------------------------------------------------------------- */ 175 | void npp_app_user_logout(int ci) 176 | { 177 | } 178 | 179 | 180 | /* -------------------------------------------------------------------------------- 181 | Called when closing anonymous user session 182 | After calling this the session memory will be zero-ed 183 | -------------------------------------------------------------------------------- */ 184 | void npp_app_session_done(int ci) 185 | { 186 | } 187 | 188 | 189 | /* -------------------------------------------------------------------------------- 190 | Called when application shuts down 191 | -------------------------------------------------------------------------------- */ 192 | void npp_app_done() 193 | { 194 | } 195 | -------------------------------------------------------------------------------- /bin/nppmake: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ------------------------------------------------------------------------------ 4 | # 5 | # MIT License 6 | # 7 | # Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all 17 | # copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | # 27 | # ------------------------------------------------------------------------------ 28 | # 29 | # Compile/make Node++ application on Linux/Unix 30 | # This is a generic script -- customize your environment in src/m 31 | # nodepp.org 32 | # 33 | # ------------------------------------------------------------------------------ 34 | 35 | 36 | NPP_VERBOSE=0 37 | if [ "$1" = "v" ] || [ "$1" = "V" ] 38 | then 39 | NPP_VERBOSE=1 40 | fi 41 | 42 | 43 | # ---------------------------------------------------------------------------- 44 | # Functions 45 | 46 | get_presence () { 47 | local present=`grep "^#define\s*$1[[:cntrl:]]*$" npp_app.h | head -1 | awk '{ print $2 }' | sed 's/\r$//'` 48 | 49 | if [ "$present" = "$1" ] 50 | then 51 | echo 1 52 | else 53 | echo 0 54 | fi 55 | } 56 | 57 | get_value () { 58 | echo `grep "^#define\s*$1\s" npp_app.h | head -1 | awk '{ print $3 }' | sed 's/\r$//'` 59 | } 60 | 61 | get_quoted_value () { 62 | echo `grep "^#define\s*$1\s" npp_app.h | head -1 | awk -F'"' '{ print $2 }'` 63 | } 64 | 65 | 66 | # ---------------------------------------------------------------------------- 67 | # Determine the OS family 68 | 69 | NPP_OS=`grep ID_LIKE /etc/os-release | head -1 | cut -d '=' -f 2` 70 | 71 | if [ $NPP_VERBOSE -eq 1 ] 72 | then 73 | echo "NPP_OS=${NPP_OS}" 74 | fi 75 | 76 | 77 | # ---------------------------------------------------------------------------- 78 | # Determine Node++ modules that are enabled in npp_app.h 79 | 80 | NPP_HTTPS=$(get_presence "NPP_HTTPS") 81 | 82 | NPP_MYSQL=$(get_presence "NPP_MYSQL") 83 | 84 | NPP_USERS=$(get_presence "NPP_USERS") 85 | 86 | NPP_ASYNC=$(get_presence "NPP_ASYNC") 87 | 88 | 89 | # ---------------------------------------------------------------------------- 90 | # APP & SVC modules to compile 91 | 92 | NPP_M_MODULES_APP="npp_app.cpp ../lib/npp_eng_app.c ../lib/npp_lib.c" 93 | NPP_M_MODULES_SVC="npp_svc.cpp ../lib/npp_eng_svc.c ../lib/npp_lib.c" 94 | 95 | NPP_APP_MODULES=$(get_quoted_value "NPP_APP_MODULES") 96 | 97 | if [ ! -z "$NPP_APP_MODULES" ] 98 | then 99 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} ${NPP_APP_MODULES}" 100 | fi 101 | 102 | NPP_SVC_MODULES_SAME=$(get_value "NPP_SVC_MODULES") 103 | 104 | if [ "$NPP_SVC_MODULES_SAME" = "NPP_APP_MODULES" ] 105 | then 106 | NPP_SVC_MODULES=$NPP_APP_MODULES 107 | else 108 | NPP_SVC_MODULES=$(get_quoted_value "NPP_SVC_MODULES") 109 | fi 110 | 111 | if [ ! -z "$NPP_SVC_MODULES" ] 112 | then 113 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} ${NPP_SVC_MODULES}" 114 | fi 115 | 116 | if [ $NPP_MYSQL -eq 1 ] 117 | then 118 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} ../lib/npp_mysql.cpp" 119 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} ../lib/npp_mysql.cpp" 120 | fi 121 | 122 | if [ $NPP_USERS -eq 1 ] 123 | then 124 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} ../lib/npp_usr.cpp ../lib/Cusers.cpp ../lib/Cusers_avatars.cpp ../lib/Cusers_groups.cpp ../lib/Cusers_settings.cpp ../lib/Cusers_logins.cpp ../lib/Cusers_activations.cpp ../lib/Cusers_p_resets.cpp ../lib/Cusers_messages.cpp" 125 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} ../lib/npp_usr.cpp ../lib/Cusers.cpp ../lib/Cusers_avatars.cpp ../lib/Cusers_groups.cpp ../lib/Cusers_settings.cpp ../lib/Cusers_logins.cpp ../lib/Cusers_activations.cpp ../lib/Cusers_p_resets.cpp ../lib/Cusers_messages.cpp" 126 | fi 127 | 128 | if [ $NPP_VERBOSE -eq 1 ] 129 | then 130 | echo "NPP_M_MODULES_APP=${NPP_M_MODULES_APP}" 131 | echo "NPP_M_MODULES_SVC=${NPP_M_MODULES_SVC}" 132 | fi 133 | 134 | 135 | # ---------------------------------------------------------------------------- 136 | # NPP_CPP_STRINGS 137 | 138 | NPP_CPP_STRINGS=$(get_presence "NPP_CPP_STRINGS") 139 | 140 | if [ $NPP_CPP_STRINGS -eq 1 ] 141 | then 142 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} -std=c++17" 143 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} -std=c++17" 144 | fi 145 | 146 | 147 | # ---------------------------------------------------------------------------- 148 | # Include paths 149 | 150 | NPP_INCLUDE="-I. -I../lib" 151 | 152 | if [ $NPP_VERBOSE -eq 1 ] 153 | then 154 | echo "NPP_INCLUDE=${NPP_INCLUDE}" 155 | fi 156 | 157 | 158 | # ---------------------------------------------------------------------------- 159 | # System and third-party libraries 160 | 161 | NPP_LIBS_APP="" 162 | NPP_LIBS_SVC="" 163 | 164 | if [ $NPP_ASYNC -eq 1 ] 165 | then 166 | if [ "$NPP_OS" = "debian" ] || [ -z "${NPP_OS##*rhel*}" ] || [ -z "${NPP_OS##*fedora*}" ] 167 | then 168 | NPP_LIBS_APP="-lrt" 169 | NPP_LIBS_SVC="-lrt" 170 | fi 171 | fi 172 | 173 | NPP_LIBS_UPDATE="" 174 | 175 | if [ $NPP_HTTPS -eq 1 ] 176 | then 177 | NPP_LIBS_APP="${NPP_LIBS_APP} -lssl -lcrypto" 178 | NPP_LIBS_SVC="${NPP_LIBS_SVC} -lssl -lcrypto" 179 | NPP_LIBS_UPDATE="${NPP_LIBS_UPDATE} -lssl -lcrypto" 180 | fi 181 | 182 | if [ $NPP_MYSQL -eq 1 ] 183 | then 184 | NPP_LIBS_APP="${NPP_LIBS_APP} -lmysqlclient" 185 | NPP_LIBS_SVC="${NPP_LIBS_SVC} -lmysqlclient" 186 | fi 187 | 188 | NPP_LIBS_APP="${NPP_LIBS_APP} -lz" 189 | 190 | if [ $NPP_VERBOSE -eq 1 ] 191 | then 192 | echo "NPP_LIBS_APP=${NPP_LIBS_APP}" 193 | echo "NPP_LIBS_SVC=${NPP_LIBS_SVC}" 194 | echo "NPP_LIBS_UPDATE=${NPP_LIBS_UPDATE}" 195 | fi 196 | 197 | 198 | # ---------------------------------------------------------------------------- 199 | # Compile 200 | 201 | NPP_APP_NAME=$(get_quoted_value "NPP_APP_NAME") 202 | 203 | if [ ! -z "$NPP_APP_NAME" ] 204 | then 205 | echo Building ${NPP_APP_NAME}... 206 | else 207 | echo Building application... 208 | fi 209 | 210 | echo Making npp_app... 211 | 212 | g++ $NPP_M_MODULES_APP \ 213 | -D NPP_APP \ 214 | $NPP_INCLUDE \ 215 | $NPP_LIBS_APP \ 216 | -O3 \ 217 | -o ../bin/npp_app 218 | 219 | 220 | if [ $? -ne 0 ] # error 221 | then 222 | exit 1 223 | fi 224 | 225 | 226 | if [ $NPP_ASYNC -eq 1 ] 227 | then 228 | echo Making npp_svc... 229 | 230 | g++ $NPP_M_MODULES_SVC \ 231 | -D NPP_SVC \ 232 | $NPP_INCLUDE \ 233 | $NPP_LIBS_SVC \ 234 | -O3 \ 235 | -o ../bin/npp_svc 236 | fi 237 | 238 | 239 | if [ "$1" = "all" ] 240 | then 241 | echo Making npp_watcher... 242 | 243 | gcc ../lib/npp_watcher.c \ 244 | ../lib/npp_lib.c \ 245 | -D NPP_WATCHER \ 246 | $NPP_INCLUDE \ 247 | -O3 \ 248 | -o ../bin/npp_watcher 249 | 250 | 251 | echo Making npp_update... 252 | 253 | gcc ../lib/npp_update.c \ 254 | ../lib/npp_lib.c \ 255 | -D NPP_UPDATE \ 256 | $NPP_INCLUDE \ 257 | $NPP_LIBS_UPDATE \ 258 | -O3 \ 259 | -o ../bin/npp_update 260 | fi 261 | -------------------------------------------------------------------------------- /lib/Cusers_groups.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:15:25, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_groups.h" 9 | 10 | 11 | bool Cusers_groups::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_groups::Cusers_groups() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_groups"; 22 | 23 | columnList_ = "id," 24 | "name," 25 | "about," 26 | "auth_level"; 27 | 28 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 29 | ThrowSQL("mysql_stmt_init"); 30 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 31 | ThrowSQL("mysql_stmt_init"); 32 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 33 | ThrowSQL("mysql_stmt_init"); 34 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 35 | ThrowSQL("mysql_stmt_init"); 36 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 37 | ThrowSQL("mysql_stmt_init"); 38 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 39 | ThrowSQL("mysql_stmt_init"); 40 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 41 | ThrowSQL("mysql_stmt_init"); 42 | 43 | Reset(); 44 | } 45 | 46 | 47 | /* --------------------------------------------------------------------------- 48 | Destructor 49 | --------------------------------------------------------------------------- */ 50 | Cusers_groups::~Cusers_groups() 51 | { 52 | mysql_stmt_close(s_); 53 | mysql_stmt_close(sGet_); 54 | mysql_stmt_close(sUpdate_); 55 | mysql_stmt_close(sInsert_); 56 | mysql_stmt_close(sDelete_); 57 | mysql_stmt_close(sSet_); 58 | 59 | slots_[instance_] = false; 60 | } 61 | 62 | 63 | /* --------------------------------------------------------------------------- 64 | Get the next record 65 | Return false if end of record set 66 | --------------------------------------------------------------------------- */ 67 | bool Cusers_groups::Fetch() 68 | { 69 | int ret; 70 | 71 | ret = mysql_stmt_fetch(s_); 72 | 73 | if ( ret != 0 ) 74 | { 75 | Reset(); 76 | 77 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 78 | return false; 79 | else 80 | { 81 | Cdb::ThrowSQL("Cusers_groups::Fetch | mysql_stmt_fetch"); 82 | return false; 83 | } 84 | } 85 | 86 | return true; 87 | } 88 | 89 | 90 | /* --------------------------------------------------------------------------- 91 | Get record by PK 92 | Not Found will return false 93 | --------------------------------------------------------------------------- */ 94 | bool Cusers_groups::Get(int arg_id) 95 | { 96 | int ret; 97 | 98 | if ( firstGet_ ) 99 | { 100 | char q[CDB_SQLBUF]; 101 | sprintf(q, "SELECT id,name,about,auth_level FROM users_groups WHERE id=?"); 102 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 103 | if ( ret != 0 ) 104 | Cdb::ThrowSQL("Cusers_groups::Get | mysql_stmt_prepare"); 105 | firstGet_ = false; 106 | } 107 | 108 | bindKey(sGet_, arg_id); 109 | 110 | if ( mysql_stmt_execute(sGet_) ) 111 | Cdb::ThrowSQL("Cusers_groups::Get | mysql_stmt_execute"); 112 | 113 | bindOutput(sGet_); 114 | 115 | if ( mysql_stmt_store_result(sGet_) ) 116 | Cdb::ThrowSQL("Cusers_groups::Get | mysql_stmt_store_result"); 117 | 118 | ret = mysql_stmt_fetch(sGet_); 119 | 120 | if ( ret != 0 ) 121 | { 122 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 123 | return false; 124 | else 125 | Cdb::ThrowSQL("Cusers_groups::Get | mysql_stmt_fetch"); 126 | } 127 | 128 | return true; 129 | } 130 | 131 | 132 | /* --------------------------------------------------------------------------- 133 | Insert record 134 | --------------------------------------------------------------------------- */ 135 | unsigned Cusers_groups::Insert() 136 | { 137 | int ret; 138 | 139 | if ( firstInsert_ ) 140 | { 141 | char q[CDB_SQLBUF]; 142 | sprintf(q, "INSERT INTO users_groups (name,about,auth_level) VALUES (?,?,?)"); 143 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 144 | if ( ret != 0 ) 145 | Cdb::ThrowSQL("Cusers_groups::Insert | mysql_stmt_prepare"); 146 | firstInsert_ = false; 147 | } 148 | 149 | bindInput(sInsert_); 150 | 151 | ret = mysql_stmt_execute(sInsert_); 152 | 153 | if ( ret != 0 ) 154 | Cdb::ThrowSQL("Cusers_groups::Insert | mysql_stmt_execute"); 155 | 156 | id = mysql_insert_id(dbConn_); 157 | 158 | return id; 159 | } 160 | 161 | 162 | /* --------------------------------------------------------------------------- 163 | Update record by PK 164 | --------------------------------------------------------------------------- */ 165 | void Cusers_groups::Update(int arg_id) 166 | { 167 | int ret; 168 | 169 | if ( firstUpdate_ ) 170 | { 171 | char q[CDB_SQLBUF]; 172 | sprintf(q, "UPDATE users_groups SET name=?,about=?,auth_level=? WHERE id=?"); 173 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 174 | if ( ret != 0 ) 175 | Cdb::ThrowSQL("Cusers_groups::Update | mysql_stmt_prepare"); 176 | firstUpdate_ = false; 177 | } 178 | 179 | bindInput(sUpdate_, true, arg_id); 180 | 181 | ret = mysql_stmt_execute(sUpdate_); 182 | 183 | if ( ret != 0 ) 184 | Cdb::ThrowSQL("Cusers_groups::Update | mysql_stmt_execute"); 185 | } 186 | 187 | 188 | /* --------------------------------------------------------------------------- 189 | Delete record by PK 190 | --------------------------------------------------------------------------- */ 191 | void Cusers_groups::Delete(int arg_id) 192 | { 193 | int ret; 194 | 195 | if ( firstDelete_ ) 196 | { 197 | char q[CDB_SQLBUF]; 198 | sprintf(q, "DELETE FROM users_groups WHERE id=?"); 199 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 200 | if ( ret != 0 ) 201 | Cdb::ThrowSQL("Cusers_groups::Delete | mysql_stmt_prepare"); 202 | firstDelete_ = false; 203 | } 204 | 205 | bindKey(sDelete_, arg_id); 206 | 207 | ret = mysql_stmt_execute(sDelete_); 208 | 209 | if ( ret != 0 ) 210 | Cdb::ThrowSQL("Cusers_groups::Delete | mysql_stmt_execute"); 211 | } 212 | 213 | 214 | /* --------------------------------------------------------------------------- 215 | Insert or update record by PK 216 | --------------------------------------------------------------------------- */ 217 | void Cusers_groups::Set(int arg_id) 218 | { 219 | int ret; 220 | 221 | if ( firstSet_ ) 222 | { 223 | char q[CDB_SQLBUF]; 224 | sprintf(q, "SELECT id FROM users_groups WHERE id=?"); 225 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 226 | if ( ret != 0 ) 227 | Cdb::ThrowSQL("Cusers_groups::Set | mysql_stmt_prepare"); 228 | firstSet_ = false; 229 | } 230 | 231 | bindKey(sSet_, arg_id); 232 | 233 | if ( mysql_stmt_execute(sSet_) ) 234 | Cdb::ThrowSQL("Cusers_groups::Set | mysql_stmt_execute"); 235 | 236 | bindSetOutput(); 237 | 238 | if ( mysql_stmt_store_result(sSet_) ) 239 | Cdb::ThrowSQL("Cusers_groups::Set | mysql_stmt_store_result"); 240 | 241 | ret = mysql_stmt_fetch(sSet_); 242 | 243 | if ( ret == 0 ) /* record existed */ 244 | { 245 | Update(arg_id); 246 | } 247 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 248 | { 249 | id = arg_id; 250 | 251 | Insert(); 252 | } 253 | else 254 | Cdb::ThrowSQL("Cusers_groups::Set | mysql_stmt_fetch"); 255 | } 256 | 257 | 258 | /* --------------------------------------------------------------------------- 259 | Bind key values 260 | --------------------------------------------------------------------------- */ 261 | void Cusers_groups::bindKey(MYSQL_STMT *s, int arg_id) 262 | { 263 | k_id_ = arg_id; 264 | 265 | memset(&bndk_, 0, sizeof(bndk_)); 266 | 267 | bndk_[0].buffer_type = MYSQL_TYPE_LONG; 268 | bndk_[0].buffer = (char*)&k_id_; 269 | 270 | if ( mysql_stmt_bind_param(s, bndk_) ) 271 | Cdb::ThrowSQL("Cusers_groups::bindKey | mysql_stmt_bind_param"); 272 | } 273 | 274 | 275 | /* --------------------------------------------------------------------------- 276 | Bind input values 277 | --------------------------------------------------------------------------- */ 278 | void Cusers_groups::bindInput(MYSQL_STMT *s, bool withKey, int arg_id) 279 | { 280 | name_len_ = strlen(name); 281 | about_len_ = strlen(about); 282 | 283 | memset(&bndi_, 0, sizeof(bndi_)); 284 | 285 | bndi_[0].buffer_type = MYSQL_TYPE_STRING; 286 | bndi_[0].buffer = (char*)name; 287 | bndi_[0].length = &name_len_; 288 | 289 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 290 | bndi_[1].buffer = (char*)about; 291 | bndi_[1].length = &about_len_; 292 | 293 | bndi_[2].buffer_type = MYSQL_TYPE_TINY; 294 | bndi_[2].buffer = (char*)&auth_level; 295 | 296 | if ( withKey ) /* after WHERE */ 297 | { 298 | k_id_ = arg_id; 299 | 300 | bndi_[3].buffer_type = MYSQL_TYPE_LONG; 301 | bndi_[3].buffer = (char*)&k_id_; 302 | 303 | } 304 | 305 | if ( mysql_stmt_bind_param(s, bndi_) ) 306 | Cdb::ThrowSQL("Cusers_groups::bindInput | mysql_stmt_bind_param"); 307 | } 308 | 309 | 310 | /* --------------------------------------------------------------------------- 311 | Bind output values 312 | --------------------------------------------------------------------------- */ 313 | void Cusers_groups::bindOutput(MYSQL_STMT *s) 314 | { 315 | memset(&bndo_, 0, sizeof(bndo_)); 316 | 317 | bndo_[0].buffer_type = MYSQL_TYPE_LONG; 318 | bndo_[0].buffer = (char*)&id; 319 | bndo_[0].is_null = &id_is_null_; 320 | 321 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 322 | bndo_[1].buffer = (char*)name; 323 | bndo_[1].buffer_length = 121; 324 | bndo_[1].is_null = &name_is_null_; 325 | 326 | bndo_[2].buffer_type = MYSQL_TYPE_STRING; 327 | bndo_[2].buffer = (char*)about; 328 | bndo_[2].buffer_length = 251; 329 | bndo_[2].is_null = &about_is_null_; 330 | 331 | bndo_[3].buffer_type = MYSQL_TYPE_TINY; 332 | bndo_[3].buffer = (char*)&auth_level; 333 | bndo_[3].is_null = &auth_level_is_null_; 334 | 335 | if ( mysql_stmt_bind_result(s, bndo_) ) 336 | Cdb::ThrowSQL("Cusers_groups::bindOutput | mysql_stmt_bind_result"); 337 | } 338 | 339 | 340 | /* --------------------------------------------------------------------------- 341 | Bind output value for Set 342 | --------------------------------------------------------------------------- */ 343 | void Cusers_groups::bindSetOutput() 344 | { 345 | static int id; /* to be scrapped anyway */ 346 | 347 | memset(&bndso_, 0, sizeof(bndso_)); 348 | 349 | bndso_[0].buffer_type = MYSQL_TYPE_LONG; 350 | bndso_[0].buffer = (char*)&id; 351 | 352 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 353 | Cdb::ThrowSQL("Cusers_groups::bindSetOutput | mysql_stmt_bind_result"); 354 | } 355 | 356 | 357 | /* --------------------------------------------------------------------------- 358 | Reset (zero) public variables 359 | --------------------------------------------------------------------------- */ 360 | void Cusers_groups::Reset() 361 | { 362 | id = 0; 363 | name[0] = EOS; 364 | about[0] = EOS; 365 | auth_level = 0; 366 | } 367 | -------------------------------------------------------------------------------- /lib/Cusers_avatars.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-29 20:06:23, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_avatars.h" 9 | 10 | 11 | bool Cusers_avatars::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_avatars::Cusers_avatars() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_avatars"; 22 | 23 | columnList_ = "user_id," 24 | "avatar_name," 25 | "avatar_data," 26 | "avatar_len"; 27 | 28 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 29 | ThrowSQL("mysql_stmt_init"); 30 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 31 | ThrowSQL("mysql_stmt_init"); 32 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 33 | ThrowSQL("mysql_stmt_init"); 34 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 35 | ThrowSQL("mysql_stmt_init"); 36 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 37 | ThrowSQL("mysql_stmt_init"); 38 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 39 | ThrowSQL("mysql_stmt_init"); 40 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 41 | ThrowSQL("mysql_stmt_init"); 42 | 43 | avatar_data_len = 0; 44 | 45 | Reset(); 46 | } 47 | 48 | 49 | /* --------------------------------------------------------------------------- 50 | Destructor 51 | --------------------------------------------------------------------------- */ 52 | Cusers_avatars::~Cusers_avatars() 53 | { 54 | mysql_stmt_close(s_); 55 | mysql_stmt_close(sGet_); 56 | mysql_stmt_close(sUpdate_); 57 | mysql_stmt_close(sInsert_); 58 | mysql_stmt_close(sDelete_); 59 | mysql_stmt_close(sSet_); 60 | 61 | slots_[instance_] = false; 62 | } 63 | 64 | 65 | /* --------------------------------------------------------------------------- 66 | Get the next record 67 | Return false if end of record set 68 | --------------------------------------------------------------------------- */ 69 | bool Cusers_avatars::Fetch() 70 | { 71 | int ret; 72 | 73 | ret = mysql_stmt_fetch(s_); 74 | 75 | if ( ret != 0 ) 76 | { 77 | Reset(); 78 | 79 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 80 | return false; 81 | else 82 | { 83 | Cdb::ThrowSQL("Cusers_avatars::Fetch | mysql_stmt_fetch"); 84 | return false; 85 | } 86 | } 87 | 88 | genDTStrings(); 89 | 90 | return true; 91 | } 92 | 93 | 94 | /* --------------------------------------------------------------------------- 95 | Get record by PK 96 | Not Found will return false 97 | --------------------------------------------------------------------------- */ 98 | bool Cusers_avatars::Get(int arg_user_id) 99 | { 100 | int ret; 101 | 102 | if ( firstGet_ ) 103 | { 104 | char q[CDB_SQLBUF]; 105 | sprintf(q, "SELECT user_id,avatar_name,avatar_data,avatar_len FROM users_avatars WHERE user_id=?"); 106 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 107 | if ( ret != 0 ) 108 | Cdb::ThrowSQL("Cusers_avatars::Get | mysql_stmt_prepare"); 109 | firstGet_ = false; 110 | } 111 | 112 | bindKey(sGet_, arg_user_id); 113 | 114 | if ( mysql_stmt_execute(sGet_) ) 115 | Cdb::ThrowSQL("Cusers_avatars::Get | mysql_stmt_execute"); 116 | 117 | bindOutput(sGet_); 118 | 119 | if ( mysql_stmt_store_result(sGet_) ) 120 | Cdb::ThrowSQL("Cusers_avatars::Get | mysql_stmt_store_result"); 121 | 122 | ret = mysql_stmt_fetch(sGet_); 123 | 124 | if ( ret != 0 ) 125 | { 126 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 127 | return false; 128 | else 129 | Cdb::ThrowSQL("Cusers_avatars::Get | mysql_stmt_fetch"); 130 | } 131 | 132 | genDTStrings(); 133 | 134 | return true; 135 | } 136 | 137 | 138 | /* --------------------------------------------------------------------------- 139 | Insert record 140 | --------------------------------------------------------------------------- */ 141 | unsigned Cusers_avatars::Insert() 142 | { 143 | int ret; 144 | 145 | if ( firstInsert_ ) 146 | { 147 | char q[CDB_SQLBUF]; 148 | sprintf(q, "INSERT INTO users_avatars (user_id,avatar_name,avatar_data,avatar_len) VALUES (?,?,?,?)"); 149 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 150 | if ( ret != 0 ) 151 | Cdb::ThrowSQL("Cusers_avatars::Insert | mysql_stmt_prepare"); 152 | firstInsert_ = false; 153 | } 154 | 155 | bindInput(sInsert_); 156 | 157 | ret = mysql_stmt_execute(sInsert_); 158 | 159 | if ( ret != 0 ) 160 | Cdb::ThrowSQL("Cusers_avatars::Insert | mysql_stmt_execute"); 161 | 162 | return mysql_insert_id(dbConn_); 163 | } 164 | 165 | 166 | /* --------------------------------------------------------------------------- 167 | Update record by PK 168 | --------------------------------------------------------------------------- */ 169 | void Cusers_avatars::Update(int arg_user_id) 170 | { 171 | int ret; 172 | 173 | if ( firstUpdate_ ) 174 | { 175 | char q[CDB_SQLBUF]; 176 | sprintf(q, "UPDATE users_avatars SET user_id=?,avatar_name=?,avatar_data=?,avatar_len=? WHERE user_id=?"); 177 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 178 | if ( ret != 0 ) 179 | Cdb::ThrowSQL("Cusers_avatars::Update | mysql_stmt_prepare"); 180 | firstUpdate_ = false; 181 | } 182 | 183 | bindInput(sUpdate_, true, arg_user_id); 184 | 185 | ret = mysql_stmt_execute(sUpdate_); 186 | 187 | if ( ret != 0 ) 188 | Cdb::ThrowSQL("Cusers_avatars::Update | mysql_stmt_execute"); 189 | } 190 | 191 | 192 | /* --------------------------------------------------------------------------- 193 | Delete record by PK 194 | --------------------------------------------------------------------------- */ 195 | void Cusers_avatars::Delete(int arg_user_id) 196 | { 197 | int ret; 198 | 199 | if ( firstDelete_ ) 200 | { 201 | char q[CDB_SQLBUF]; 202 | sprintf(q, "DELETE FROM users_avatars WHERE user_id=?"); 203 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 204 | if ( ret != 0 ) 205 | Cdb::ThrowSQL("Cusers_avatars::Delete | mysql_stmt_prepare"); 206 | firstDelete_ = false; 207 | } 208 | 209 | bindKey(sDelete_, arg_user_id); 210 | 211 | ret = mysql_stmt_execute(sDelete_); 212 | 213 | if ( ret != 0 ) 214 | Cdb::ThrowSQL("Cusers_avatars::Delete | mysql_stmt_execute"); 215 | } 216 | 217 | 218 | /* --------------------------------------------------------------------------- 219 | Insert or update record by PK 220 | --------------------------------------------------------------------------- */ 221 | void Cusers_avatars::Set(int arg_user_id) 222 | { 223 | int ret; 224 | 225 | if ( firstSet_ ) 226 | { 227 | char q[CDB_SQLBUF]; 228 | sprintf(q, "SELECT user_id FROM users_avatars WHERE user_id=?"); 229 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 230 | if ( ret != 0 ) 231 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_prepare"); 232 | firstSet_ = false; 233 | } 234 | 235 | bindKey(sSet_, arg_user_id); 236 | 237 | if ( mysql_stmt_execute(sSet_) ) 238 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_execute"); 239 | 240 | bindSetOutput(); 241 | 242 | if ( mysql_stmt_store_result(sSet_) ) 243 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_store_result"); 244 | 245 | ret = mysql_stmt_fetch(sSet_); 246 | 247 | if ( ret == 0 ) /* record existed */ 248 | { 249 | Update(arg_user_id); 250 | } 251 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 252 | { 253 | user_id = arg_user_id; 254 | 255 | Insert(); 256 | } 257 | else 258 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_fetch"); 259 | } 260 | 261 | 262 | /* --------------------------------------------------------------------------- 263 | Bind key values 264 | --------------------------------------------------------------------------- */ 265 | void Cusers_avatars::bindKey(MYSQL_STMT *s, int arg_user_id) 266 | { 267 | k_user_id_ = arg_user_id; 268 | 269 | memset(&bndk_, 0, sizeof(bndk_)); 270 | 271 | bndk_[0].buffer_type = MYSQL_TYPE_LONG; 272 | bndk_[0].buffer = (char*)&k_user_id_; 273 | 274 | if ( mysql_stmt_bind_param(s, bndk_) ) 275 | Cdb::ThrowSQL("Cusers_avatars::bindKey | mysql_stmt_bind_param"); 276 | } 277 | 278 | 279 | /* --------------------------------------------------------------------------- 280 | Bind input values 281 | --------------------------------------------------------------------------- */ 282 | void Cusers_avatars::bindInput(MYSQL_STMT *s, bool withKey, int arg_user_id) 283 | { 284 | avatar_name_len_ = strlen(avatar_name); 285 | 286 | 287 | memset(&bndi_, 0, sizeof(bndi_)); 288 | 289 | bndi_[0].buffer_type = MYSQL_TYPE_LONG; 290 | bndi_[0].buffer = (char*)&user_id; 291 | 292 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 293 | bndi_[1].buffer = (char*)avatar_name; 294 | bndi_[1].length = &avatar_name_len_; 295 | 296 | bndi_[2].buffer_type = MYSQL_TYPE_BLOB; 297 | bndi_[2].buffer = (char*)avatar_data; 298 | bndi_[2].length = &avatar_data_len; 299 | 300 | bndi_[3].buffer_type = MYSQL_TYPE_LONG; 301 | bndi_[3].buffer = (char*)&avatar_len; 302 | 303 | if ( withKey ) /* after WHERE */ 304 | { 305 | k_user_id_ = arg_user_id; 306 | 307 | bndi_[4].buffer_type = MYSQL_TYPE_LONG; 308 | bndi_[4].buffer = (char*)&k_user_id_; 309 | 310 | } 311 | 312 | if ( mysql_stmt_bind_param(s, bndi_) ) 313 | Cdb::ThrowSQL("Cusers_avatars::bindInput | mysql_stmt_bind_param"); 314 | } 315 | 316 | 317 | /* --------------------------------------------------------------------------- 318 | Bind output values 319 | --------------------------------------------------------------------------- */ 320 | void Cusers_avatars::bindOutput(MYSQL_STMT *s) 321 | { 322 | memset(&bndo_, 0, sizeof(bndo_)); 323 | 324 | bndo_[0].buffer_type = MYSQL_TYPE_LONG; 325 | bndo_[0].buffer = (char*)&user_id; 326 | bndo_[0].is_null = &user_id_is_null_; 327 | 328 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 329 | bndo_[1].buffer = (char*)avatar_name; 330 | bndo_[1].buffer_length = 121; 331 | bndo_[1].is_null = &avatar_name_is_null_; 332 | 333 | bndo_[2].buffer_type = MYSQL_TYPE_BLOB; 334 | bndo_[2].buffer = (char*)avatar_data; 335 | bndo_[2].buffer_length = 65536; 336 | bndo_[2].length = &avatar_data_len; 337 | bndo_[2].is_null = &avatar_data_is_null_; 338 | 339 | bndo_[3].buffer_type = MYSQL_TYPE_LONG; 340 | bndo_[3].buffer = (char*)&avatar_len; 341 | bndo_[3].is_null = &avatar_len_is_null_; 342 | 343 | if ( mysql_stmt_bind_result(s, bndo_) ) 344 | Cdb::ThrowSQL("Cusers_avatars::bindOutput | mysql_stmt_bind_result"); 345 | } 346 | 347 | 348 | /* --------------------------------------------------------------------------- 349 | Bind output value for Set 350 | --------------------------------------------------------------------------- */ 351 | void Cusers_avatars::bindSetOutput() 352 | { 353 | static int user_id; /* to be scrapped anyway */ 354 | 355 | memset(&bndso_, 0, sizeof(bndso_)); 356 | 357 | bndso_[0].buffer_type = MYSQL_TYPE_LONG; 358 | bndso_[0].buffer = (char*)&user_id; 359 | 360 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 361 | Cdb::ThrowSQL("Cusers_avatars::bindSetOutput | mysql_stmt_bind_result"); 362 | } 363 | 364 | 365 | /* --------------------------------------------------------------------------- 366 | Generate date-time strings 367 | --------------------------------------------------------------------------- */ 368 | void Cusers_avatars::genDTStrings() 369 | { 370 | } 371 | 372 | 373 | /* --------------------------------------------------------------------------- 374 | Reset (zero) public variables 375 | --------------------------------------------------------------------------- */ 376 | void Cusers_avatars::Reset() 377 | { 378 | user_id = 0; 379 | avatar_name[0] = EOS; 380 | avatar_data[0] = EOS; 381 | avatar_len = 0; 382 | } 383 | -------------------------------------------------------------------------------- /lib/Cusers_settings.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:16:04, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_settings.h" 9 | 10 | 11 | bool Cusers_settings::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_settings::Cusers_settings() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_settings"; 22 | 23 | columnList_ = "user_id," 24 | "us_key," 25 | "us_val"; 26 | 27 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 28 | ThrowSQL("mysql_stmt_init"); 29 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 30 | ThrowSQL("mysql_stmt_init"); 31 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 32 | ThrowSQL("mysql_stmt_init"); 33 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 34 | ThrowSQL("mysql_stmt_init"); 35 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 36 | ThrowSQL("mysql_stmt_init"); 37 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 38 | ThrowSQL("mysql_stmt_init"); 39 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 40 | ThrowSQL("mysql_stmt_init"); 41 | 42 | Reset(); 43 | } 44 | 45 | 46 | /* --------------------------------------------------------------------------- 47 | Destructor 48 | --------------------------------------------------------------------------- */ 49 | Cusers_settings::~Cusers_settings() 50 | { 51 | mysql_stmt_close(s_); 52 | mysql_stmt_close(sGet_); 53 | mysql_stmt_close(sUpdate_); 54 | mysql_stmt_close(sInsert_); 55 | mysql_stmt_close(sDelete_); 56 | mysql_stmt_close(sSet_); 57 | 58 | slots_[instance_] = false; 59 | } 60 | 61 | 62 | /* --------------------------------------------------------------------------- 63 | Get the next record 64 | Return false if end of record set 65 | --------------------------------------------------------------------------- */ 66 | bool Cusers_settings::Fetch() 67 | { 68 | int ret; 69 | 70 | ret = mysql_stmt_fetch(s_); 71 | 72 | if ( ret != 0 ) 73 | { 74 | Reset(); 75 | 76 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 77 | return false; 78 | else 79 | { 80 | Cdb::ThrowSQL("Cusers_settings::Fetch | mysql_stmt_fetch"); 81 | return false; 82 | } 83 | } 84 | 85 | return true; 86 | } 87 | 88 | 89 | /* --------------------------------------------------------------------------- 90 | Get record by PK 91 | Not Found will return false 92 | --------------------------------------------------------------------------- */ 93 | bool Cusers_settings::Get(int arg_user_id, const std::string& arg_us_key) 94 | { 95 | int ret; 96 | 97 | if ( firstGet_ ) 98 | { 99 | char q[CDB_SQLBUF]; 100 | sprintf(q, "SELECT user_id,us_key,us_val FROM users_settings WHERE user_id=? AND us_key=?"); 101 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 102 | if ( ret != 0 ) 103 | Cdb::ThrowSQL("Cusers_settings::Get | mysql_stmt_prepare"); 104 | firstGet_ = false; 105 | } 106 | 107 | bindKey(sGet_, arg_user_id, arg_us_key); 108 | 109 | if ( mysql_stmt_execute(sGet_) ) 110 | Cdb::ThrowSQL("Cusers_settings::Get | mysql_stmt_execute"); 111 | 112 | bindOutput(sGet_); 113 | 114 | if ( mysql_stmt_store_result(sGet_) ) 115 | Cdb::ThrowSQL("Cusers_settings::Get | mysql_stmt_store_result"); 116 | 117 | ret = mysql_stmt_fetch(sGet_); 118 | 119 | if ( ret != 0 ) 120 | { 121 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 122 | return false; 123 | else 124 | Cdb::ThrowSQL("Cusers_settings::Get | mysql_stmt_fetch"); 125 | } 126 | 127 | return true; 128 | } 129 | 130 | 131 | /* --------------------------------------------------------------------------- 132 | Insert record 133 | --------------------------------------------------------------------------- */ 134 | unsigned Cusers_settings::Insert() 135 | { 136 | int ret; 137 | 138 | if ( firstInsert_ ) 139 | { 140 | char q[CDB_SQLBUF]; 141 | sprintf(q, "INSERT INTO users_settings (user_id,us_key,us_val) VALUES (?,?,?)"); 142 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 143 | if ( ret != 0 ) 144 | Cdb::ThrowSQL("Cusers_settings::Insert | mysql_stmt_prepare"); 145 | firstInsert_ = false; 146 | } 147 | 148 | bindInput(sInsert_); 149 | 150 | ret = mysql_stmt_execute(sInsert_); 151 | 152 | if ( ret != 0 ) 153 | Cdb::ThrowSQL("Cusers_settings::Insert | mysql_stmt_execute"); 154 | 155 | return mysql_insert_id(dbConn_); 156 | } 157 | 158 | 159 | /* --------------------------------------------------------------------------- 160 | Update record by PK 161 | --------------------------------------------------------------------------- */ 162 | void Cusers_settings::Update(int arg_user_id, const std::string& arg_us_key) 163 | { 164 | int ret; 165 | 166 | if ( firstUpdate_ ) 167 | { 168 | char q[CDB_SQLBUF]; 169 | sprintf(q, "UPDATE users_settings SET user_id=?,us_key=?,us_val=? WHERE user_id=? AND us_key=?"); 170 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 171 | if ( ret != 0 ) 172 | Cdb::ThrowSQL("Cusers_settings::Update | mysql_stmt_prepare"); 173 | firstUpdate_ = false; 174 | } 175 | 176 | bindInput(sUpdate_, true, arg_user_id, arg_us_key); 177 | 178 | ret = mysql_stmt_execute(sUpdate_); 179 | 180 | if ( ret != 0 ) 181 | Cdb::ThrowSQL("Cusers_settings::Update | mysql_stmt_execute"); 182 | } 183 | 184 | 185 | /* --------------------------------------------------------------------------- 186 | Delete record by PK 187 | --------------------------------------------------------------------------- */ 188 | void Cusers_settings::Delete(int arg_user_id, const std::string& arg_us_key) 189 | { 190 | int ret; 191 | 192 | if ( firstDelete_ ) 193 | { 194 | char q[CDB_SQLBUF]; 195 | sprintf(q, "DELETE FROM users_settings WHERE user_id=? AND us_key=?"); 196 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 197 | if ( ret != 0 ) 198 | Cdb::ThrowSQL("Cusers_settings::Delete | mysql_stmt_prepare"); 199 | firstDelete_ = false; 200 | } 201 | 202 | bindKey(sDelete_, arg_user_id, arg_us_key); 203 | 204 | ret = mysql_stmt_execute(sDelete_); 205 | 206 | if ( ret != 0 ) 207 | Cdb::ThrowSQL("Cusers_settings::Delete | mysql_stmt_execute"); 208 | } 209 | 210 | 211 | /* --------------------------------------------------------------------------- 212 | Insert or update record by PK 213 | --------------------------------------------------------------------------- */ 214 | void Cusers_settings::Set(int arg_user_id, const std::string& arg_us_key) 215 | { 216 | int ret; 217 | 218 | if ( firstSet_ ) 219 | { 220 | char q[CDB_SQLBUF]; 221 | sprintf(q, "SELECT user_id FROM users_settings WHERE user_id=? AND us_key=?"); 222 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 223 | if ( ret != 0 ) 224 | Cdb::ThrowSQL("Cusers_settings::Set | mysql_stmt_prepare"); 225 | firstSet_ = false; 226 | } 227 | 228 | bindKey(sSet_, arg_user_id, arg_us_key); 229 | 230 | if ( mysql_stmt_execute(sSet_) ) 231 | Cdb::ThrowSQL("Cusers_settings::Set | mysql_stmt_execute"); 232 | 233 | bindSetOutput(); 234 | 235 | if ( mysql_stmt_store_result(sSet_) ) 236 | Cdb::ThrowSQL("Cusers_settings::Set | mysql_stmt_store_result"); 237 | 238 | ret = mysql_stmt_fetch(sSet_); 239 | 240 | if ( ret == 0 ) /* record existed */ 241 | { 242 | Update(arg_user_id, arg_us_key); 243 | } 244 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 245 | { 246 | user_id = arg_user_id; 247 | strncpy(us_key, arg_us_key.c_str(), 30); 248 | us_key[30] = EOS; 249 | 250 | Insert(); 251 | } 252 | else 253 | Cdb::ThrowSQL("Cusers_settings::Set | mysql_stmt_fetch"); 254 | } 255 | 256 | 257 | /* --------------------------------------------------------------------------- 258 | Bind key values 259 | --------------------------------------------------------------------------- */ 260 | void Cusers_settings::bindKey(MYSQL_STMT *s, int arg_user_id, const std::string& arg_us_key) 261 | { 262 | k_user_id_ = arg_user_id; 263 | strncpy(k_us_key_, arg_us_key.c_str(), 30); 264 | k_us_key_[30] = EOS; 265 | 266 | k_us_key_len_ = strlen(k_us_key_); 267 | 268 | memset(&bndk_, 0, sizeof(bndk_)); 269 | 270 | bndk_[0].buffer_type = MYSQL_TYPE_LONG; 271 | bndk_[0].buffer = (char*)&k_user_id_; 272 | 273 | bndk_[1].buffer_type = MYSQL_TYPE_STRING; 274 | bndk_[1].buffer = (char*)k_us_key_; 275 | bndk_[1].length = &k_us_key_len_; 276 | 277 | if ( mysql_stmt_bind_param(s, bndk_) ) 278 | Cdb::ThrowSQL("Cusers_settings::bindKey | mysql_stmt_bind_param"); 279 | } 280 | 281 | 282 | /* --------------------------------------------------------------------------- 283 | Bind input values 284 | --------------------------------------------------------------------------- */ 285 | void Cusers_settings::bindInput(MYSQL_STMT *s, bool withKey, int arg_user_id, const std::string& arg_us_key) 286 | { 287 | us_key_len_ = strlen(us_key); 288 | us_val_len_ = strlen(us_val); 289 | 290 | memset(&bndi_, 0, sizeof(bndi_)); 291 | 292 | bndi_[0].buffer_type = MYSQL_TYPE_LONG; 293 | bndi_[0].buffer = (char*)&user_id; 294 | 295 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 296 | bndi_[1].buffer = (char*)us_key; 297 | bndi_[1].length = &us_key_len_; 298 | 299 | bndi_[2].buffer_type = MYSQL_TYPE_STRING; 300 | bndi_[2].buffer = (char*)us_val; 301 | bndi_[2].length = &us_val_len_; 302 | 303 | if ( withKey ) /* after WHERE */ 304 | { 305 | k_user_id_ = arg_user_id; 306 | strncpy(k_us_key_, arg_us_key.c_str(), 30); 307 | k_us_key_[30] = EOS; 308 | 309 | k_us_key_len_ = strlen(k_us_key_); 310 | 311 | bndi_[3].buffer_type = MYSQL_TYPE_LONG; 312 | bndi_[3].buffer = (char*)&k_user_id_; 313 | 314 | bndi_[4].buffer_type = MYSQL_TYPE_STRING; 315 | bndi_[4].buffer = (char*)k_us_key_; 316 | bndi_[4].length = &k_us_key_len_; 317 | 318 | } 319 | 320 | if ( mysql_stmt_bind_param(s, bndi_) ) 321 | Cdb::ThrowSQL("Cusers_settings::bindInput | mysql_stmt_bind_param"); 322 | } 323 | 324 | 325 | /* --------------------------------------------------------------------------- 326 | Bind output values 327 | --------------------------------------------------------------------------- */ 328 | void Cusers_settings::bindOutput(MYSQL_STMT *s) 329 | { 330 | memset(&bndo_, 0, sizeof(bndo_)); 331 | 332 | bndo_[0].buffer_type = MYSQL_TYPE_LONG; 333 | bndo_[0].buffer = (char*)&user_id; 334 | bndo_[0].is_null = &user_id_is_null_; 335 | 336 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 337 | bndo_[1].buffer = (char*)us_key; 338 | bndo_[1].buffer_length = 31; 339 | bndo_[1].is_null = &us_key_is_null_; 340 | 341 | bndo_[2].buffer_type = MYSQL_TYPE_STRING; 342 | bndo_[2].buffer = (char*)us_val; 343 | bndo_[2].buffer_length = 251; 344 | bndo_[2].is_null = &us_val_is_null_; 345 | 346 | if ( mysql_stmt_bind_result(s, bndo_) ) 347 | Cdb::ThrowSQL("Cusers_settings::bindOutput | mysql_stmt_bind_result"); 348 | } 349 | 350 | 351 | /* --------------------------------------------------------------------------- 352 | Bind output value for Set 353 | --------------------------------------------------------------------------- */ 354 | void Cusers_settings::bindSetOutput() 355 | { 356 | static int user_id; /* to be scrapped anyway */ 357 | 358 | memset(&bndso_, 0, sizeof(bndso_)); 359 | 360 | bndso_[0].buffer_type = MYSQL_TYPE_LONG; 361 | bndso_[0].buffer = (char*)&user_id; 362 | 363 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 364 | Cdb::ThrowSQL("Cusers_settings::bindSetOutput | mysql_stmt_bind_result"); 365 | } 366 | 367 | 368 | /* --------------------------------------------------------------------------- 369 | Reset (zero) public variables 370 | --------------------------------------------------------------------------- */ 371 | void Cusers_settings::Reset() 372 | { 373 | user_id = 0; 374 | us_key[0] = EOS; 375 | us_val[0] = EOS; 376 | } 377 | -------------------------------------------------------------------------------- /lib/Cusers_p_resets.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:16:49, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_p_resets.h" 9 | 10 | 11 | bool Cusers_p_resets::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_p_resets::Cusers_p_resets() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_p_resets"; 22 | 23 | columnList_ = "linkkey," 24 | "user_id," 25 | "created," 26 | "tries"; 27 | 28 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 29 | ThrowSQL("mysql_stmt_init"); 30 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 31 | ThrowSQL("mysql_stmt_init"); 32 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 33 | ThrowSQL("mysql_stmt_init"); 34 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 35 | ThrowSQL("mysql_stmt_init"); 36 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 37 | ThrowSQL("mysql_stmt_init"); 38 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 39 | ThrowSQL("mysql_stmt_init"); 40 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 41 | ThrowSQL("mysql_stmt_init"); 42 | 43 | Reset(); 44 | } 45 | 46 | 47 | /* --------------------------------------------------------------------------- 48 | Destructor 49 | --------------------------------------------------------------------------- */ 50 | Cusers_p_resets::~Cusers_p_resets() 51 | { 52 | mysql_stmt_close(s_); 53 | mysql_stmt_close(sGet_); 54 | mysql_stmt_close(sUpdate_); 55 | mysql_stmt_close(sInsert_); 56 | mysql_stmt_close(sDelete_); 57 | mysql_stmt_close(sSet_); 58 | 59 | slots_[instance_] = false; 60 | } 61 | 62 | 63 | /* --------------------------------------------------------------------------- 64 | Get the next record 65 | Return false if end of record set 66 | --------------------------------------------------------------------------- */ 67 | bool Cusers_p_resets::Fetch() 68 | { 69 | int ret; 70 | 71 | ret = mysql_stmt_fetch(s_); 72 | 73 | if ( ret != 0 ) 74 | { 75 | Reset(); 76 | 77 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 78 | return false; 79 | else 80 | { 81 | Cdb::ThrowSQL("Cusers_p_resets::Fetch | mysql_stmt_fetch"); 82 | return false; 83 | } 84 | } 85 | 86 | genDTStrings(); 87 | 88 | return true; 89 | } 90 | 91 | 92 | /* --------------------------------------------------------------------------- 93 | Get record by PK 94 | Not Found will return false 95 | --------------------------------------------------------------------------- */ 96 | bool Cusers_p_resets::Get(const std::string& arg_linkkey) 97 | { 98 | int ret; 99 | 100 | if ( firstGet_ ) 101 | { 102 | char q[CDB_SQLBUF]; 103 | sprintf(q, "SELECT linkkey,user_id,created,tries FROM users_p_resets WHERE linkkey=BINARY ?"); 104 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 105 | if ( ret != 0 ) 106 | Cdb::ThrowSQL("Cusers_p_resets::Get | mysql_stmt_prepare"); 107 | firstGet_ = false; 108 | } 109 | 110 | bindKey(sGet_, arg_linkkey); 111 | 112 | if ( mysql_stmt_execute(sGet_) ) 113 | Cdb::ThrowSQL("Cusers_p_resets::Get | mysql_stmt_execute"); 114 | 115 | bindOutput(sGet_); 116 | 117 | if ( mysql_stmt_store_result(sGet_) ) 118 | Cdb::ThrowSQL("Cusers_p_resets::Get | mysql_stmt_store_result"); 119 | 120 | ret = mysql_stmt_fetch(sGet_); 121 | 122 | if ( ret != 0 ) 123 | { 124 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 125 | return false; 126 | else 127 | Cdb::ThrowSQL("Cusers_p_resets::Get | mysql_stmt_fetch"); 128 | } 129 | 130 | genDTStrings(); 131 | 132 | return true; 133 | } 134 | 135 | 136 | /* --------------------------------------------------------------------------- 137 | Insert record 138 | --------------------------------------------------------------------------- */ 139 | unsigned Cusers_p_resets::Insert() 140 | { 141 | int ret; 142 | 143 | if ( firstInsert_ ) 144 | { 145 | char q[CDB_SQLBUF]; 146 | sprintf(q, "INSERT INTO users_p_resets (linkkey,user_id,created,tries) VALUES (?,?,?,?)"); 147 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 148 | if ( ret != 0 ) 149 | Cdb::ThrowSQL("Cusers_p_resets::Insert | mysql_stmt_prepare"); 150 | firstInsert_ = false; 151 | } 152 | 153 | bindInput(sInsert_); 154 | 155 | ret = mysql_stmt_execute(sInsert_); 156 | 157 | if ( ret != 0 ) 158 | Cdb::ThrowSQL("Cusers_p_resets::Insert | mysql_stmt_execute"); 159 | 160 | return mysql_insert_id(dbConn_); 161 | } 162 | 163 | 164 | /* --------------------------------------------------------------------------- 165 | Update record by PK 166 | --------------------------------------------------------------------------- */ 167 | void Cusers_p_resets::Update(const std::string& arg_linkkey) 168 | { 169 | int ret; 170 | 171 | if ( firstUpdate_ ) 172 | { 173 | char q[CDB_SQLBUF]; 174 | sprintf(q, "UPDATE users_p_resets SET linkkey=?,user_id=?,created=?,tries=? WHERE linkkey=BINARY ?"); 175 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 176 | if ( ret != 0 ) 177 | Cdb::ThrowSQL("Cusers_p_resets::Update | mysql_stmt_prepare"); 178 | firstUpdate_ = false; 179 | } 180 | 181 | bindInput(sUpdate_, true, arg_linkkey); 182 | 183 | ret = mysql_stmt_execute(sUpdate_); 184 | 185 | if ( ret != 0 ) 186 | Cdb::ThrowSQL("Cusers_p_resets::Update | mysql_stmt_execute"); 187 | } 188 | 189 | 190 | /* --------------------------------------------------------------------------- 191 | Delete record by PK 192 | --------------------------------------------------------------------------- */ 193 | void Cusers_p_resets::Delete(const std::string& arg_linkkey) 194 | { 195 | int ret; 196 | 197 | if ( firstDelete_ ) 198 | { 199 | char q[CDB_SQLBUF]; 200 | sprintf(q, "DELETE FROM users_p_resets WHERE linkkey=BINARY ?"); 201 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 202 | if ( ret != 0 ) 203 | Cdb::ThrowSQL("Cusers_p_resets::Delete | mysql_stmt_prepare"); 204 | firstDelete_ = false; 205 | } 206 | 207 | bindKey(sDelete_, arg_linkkey); 208 | 209 | ret = mysql_stmt_execute(sDelete_); 210 | 211 | if ( ret != 0 ) 212 | Cdb::ThrowSQL("Cusers_p_resets::Delete | mysql_stmt_execute"); 213 | } 214 | 215 | 216 | /* --------------------------------------------------------------------------- 217 | Insert or update record by PK 218 | --------------------------------------------------------------------------- */ 219 | void Cusers_p_resets::Set(const std::string& arg_linkkey) 220 | { 221 | int ret; 222 | 223 | if ( firstSet_ ) 224 | { 225 | char q[CDB_SQLBUF]; 226 | sprintf(q, "SELECT linkkey FROM users_p_resets WHERE linkkey=BINARY ?"); 227 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 228 | if ( ret != 0 ) 229 | Cdb::ThrowSQL("Cusers_p_resets::Set | mysql_stmt_prepare"); 230 | firstSet_ = false; 231 | } 232 | 233 | bindKey(sSet_, arg_linkkey); 234 | 235 | if ( mysql_stmt_execute(sSet_) ) 236 | Cdb::ThrowSQL("Cusers_p_resets::Set | mysql_stmt_execute"); 237 | 238 | bindSetOutput(); 239 | 240 | if ( mysql_stmt_store_result(sSet_) ) 241 | Cdb::ThrowSQL("Cusers_p_resets::Set | mysql_stmt_store_result"); 242 | 243 | ret = mysql_stmt_fetch(sSet_); 244 | 245 | if ( ret == 0 ) /* record existed */ 246 | { 247 | Update(arg_linkkey); 248 | } 249 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 250 | { 251 | strncpy(linkkey, arg_linkkey.c_str(), 20); 252 | linkkey[20] = EOS; 253 | 254 | Insert(); 255 | } 256 | else 257 | Cdb::ThrowSQL("Cusers_p_resets::Set | mysql_stmt_fetch"); 258 | } 259 | 260 | 261 | /* --------------------------------------------------------------------------- 262 | Bind key values 263 | --------------------------------------------------------------------------- */ 264 | void Cusers_p_resets::bindKey(MYSQL_STMT *s, const std::string& arg_linkkey) 265 | { 266 | strncpy(k_linkkey_, arg_linkkey.c_str(), 20); 267 | k_linkkey_[20] = EOS; 268 | 269 | k_linkkey_len_ = strlen(k_linkkey_); 270 | 271 | memset(&bndk_, 0, sizeof(bndk_)); 272 | 273 | bndk_[0].buffer_type = MYSQL_TYPE_STRING; 274 | bndk_[0].buffer = (char*)k_linkkey_; 275 | bndk_[0].length = &k_linkkey_len_; 276 | 277 | if ( mysql_stmt_bind_param(s, bndk_) ) 278 | Cdb::ThrowSQL("Cusers_p_resets::bindKey | mysql_stmt_bind_param"); 279 | } 280 | 281 | 282 | /* --------------------------------------------------------------------------- 283 | Bind input values 284 | --------------------------------------------------------------------------- */ 285 | void Cusers_p_resets::bindInput(MYSQL_STMT *s, bool withKey, const std::string& arg_linkkey) 286 | { 287 | linkkey_len_ = strlen(linkkey); 288 | 289 | set_datetime(&t_created_, created); 290 | 291 | memset(&bndi_, 0, sizeof(bndi_)); 292 | 293 | bndi_[0].buffer_type = MYSQL_TYPE_STRING; 294 | bndi_[0].buffer = (char*)linkkey; 295 | bndi_[0].length = &linkkey_len_; 296 | 297 | bndi_[1].buffer_type = MYSQL_TYPE_LONG; 298 | bndi_[1].buffer = (char*)&user_id; 299 | 300 | bndi_[2].buffer_type = MYSQL_TYPE_DATETIME; 301 | bndi_[2].buffer = (char*)&t_created_; 302 | 303 | bndi_[3].buffer_type = MYSQL_TYPE_SHORT; 304 | bndi_[3].buffer = (char*)&tries; 305 | 306 | if ( withKey ) /* after WHERE */ 307 | { 308 | strncpy(k_linkkey_, arg_linkkey.c_str(), 20); 309 | k_linkkey_[20] = EOS; 310 | 311 | k_linkkey_len_ = strlen(k_linkkey_); 312 | 313 | bndi_[4].buffer_type = MYSQL_TYPE_STRING; 314 | bndi_[4].buffer = (char*)k_linkkey_; 315 | bndi_[4].length = &k_linkkey_len_; 316 | 317 | } 318 | 319 | if ( mysql_stmt_bind_param(s, bndi_) ) 320 | Cdb::ThrowSQL("Cusers_p_resets::bindInput | mysql_stmt_bind_param"); 321 | } 322 | 323 | 324 | /* --------------------------------------------------------------------------- 325 | Bind output values 326 | --------------------------------------------------------------------------- */ 327 | void Cusers_p_resets::bindOutput(MYSQL_STMT *s) 328 | { 329 | memset(&bndo_, 0, sizeof(bndo_)); 330 | 331 | bndo_[0].buffer_type = MYSQL_TYPE_STRING; 332 | bndo_[0].buffer = (char*)linkkey; 333 | bndo_[0].buffer_length = 21; 334 | bndo_[0].is_null = &linkkey_is_null_; 335 | 336 | bndo_[1].buffer_type = MYSQL_TYPE_LONG; 337 | bndo_[1].buffer = (char*)&user_id; 338 | bndo_[1].is_null = &user_id_is_null_; 339 | 340 | bndo_[2].buffer_type = MYSQL_TYPE_DATETIME; 341 | bndo_[2].buffer = (char*)&t_created_; 342 | bndo_[2].is_null = &created_is_null_; 343 | 344 | bndo_[3].buffer_type = MYSQL_TYPE_SHORT; 345 | bndo_[3].buffer = (char*)&tries; 346 | bndo_[3].is_null = &tries_is_null_; 347 | 348 | if ( mysql_stmt_bind_result(s, bndo_) ) 349 | Cdb::ThrowSQL("Cusers_p_resets::bindOutput | mysql_stmt_bind_result"); 350 | } 351 | 352 | 353 | /* --------------------------------------------------------------------------- 354 | Bind output value for Set 355 | --------------------------------------------------------------------------- */ 356 | void Cusers_p_resets::bindSetOutput() 357 | { 358 | static USERS_P_RESETS_LINKKEY linkkey; /* to be scrapped anyway */ 359 | 360 | memset(&bndso_, 0, sizeof(bndso_)); 361 | 362 | bndso_[0].buffer_type = MYSQL_TYPE_STRING; 363 | bndso_[0].buffer = (char*)linkkey; 364 | bndso_[0].buffer_length = 21; 365 | 366 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 367 | Cdb::ThrowSQL("Cusers_p_resets::bindSetOutput | mysql_stmt_bind_result"); 368 | } 369 | 370 | 371 | /* --------------------------------------------------------------------------- 372 | Generate date-time strings 373 | --------------------------------------------------------------------------- */ 374 | void Cusers_p_resets::genDTStrings() 375 | { 376 | if ( created_is_null_ ) 377 | created[0] = EOS; 378 | else 379 | sprintf(created, "%04d-%02d-%02d %02d:%02d:%02d", t_created_.year, t_created_.month, t_created_.day, t_created_.hour, t_created_.minute, t_created_.second); 380 | 381 | } 382 | 383 | 384 | /* --------------------------------------------------------------------------- 385 | Reset (zero) public variables 386 | --------------------------------------------------------------------------- */ 387 | void Cusers_p_resets::Reset() 388 | { 389 | linkkey[0] = EOS; 390 | user_id = 0; 391 | created[0] = EOS; 392 | tries = 0; 393 | } 394 | -------------------------------------------------------------------------------- /lib/Cusers_messages.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:17:27, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_messages.h" 9 | 10 | 11 | bool Cusers_messages::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_messages::Cusers_messages() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_messages"; 22 | 23 | columnList_ = "user_id," 24 | "msg_id," 25 | "email," 26 | "message," 27 | "created"; 28 | 29 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 30 | ThrowSQL("mysql_stmt_init"); 31 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 32 | ThrowSQL("mysql_stmt_init"); 33 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 34 | ThrowSQL("mysql_stmt_init"); 35 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 36 | ThrowSQL("mysql_stmt_init"); 37 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 38 | ThrowSQL("mysql_stmt_init"); 39 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 40 | ThrowSQL("mysql_stmt_init"); 41 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 42 | ThrowSQL("mysql_stmt_init"); 43 | 44 | Reset(); 45 | } 46 | 47 | 48 | /* --------------------------------------------------------------------------- 49 | Destructor 50 | --------------------------------------------------------------------------- */ 51 | Cusers_messages::~Cusers_messages() 52 | { 53 | mysql_stmt_close(s_); 54 | mysql_stmt_close(sGet_); 55 | mysql_stmt_close(sUpdate_); 56 | mysql_stmt_close(sInsert_); 57 | mysql_stmt_close(sDelete_); 58 | mysql_stmt_close(sSet_); 59 | 60 | slots_[instance_] = false; 61 | } 62 | 63 | 64 | /* --------------------------------------------------------------------------- 65 | Get the next record 66 | Return false if end of record set 67 | --------------------------------------------------------------------------- */ 68 | bool Cusers_messages::Fetch() 69 | { 70 | int ret; 71 | 72 | ret = mysql_stmt_fetch(s_); 73 | 74 | if ( ret != 0 ) 75 | { 76 | Reset(); 77 | 78 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 79 | return false; 80 | else 81 | { 82 | Cdb::ThrowSQL("Cusers_messages::Fetch | mysql_stmt_fetch"); 83 | return false; 84 | } 85 | } 86 | 87 | genDTStrings(); 88 | 89 | return true; 90 | } 91 | 92 | 93 | /* --------------------------------------------------------------------------- 94 | Get record by PK 95 | Not Found will return false 96 | --------------------------------------------------------------------------- */ 97 | bool Cusers_messages::Get(int arg_user_id, int arg_msg_id) 98 | { 99 | int ret; 100 | 101 | if ( firstGet_ ) 102 | { 103 | char q[CDB_SQLBUF]; 104 | sprintf(q, "SELECT user_id,msg_id,email,message,created FROM users_messages WHERE user_id=? AND msg_id=?"); 105 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 106 | if ( ret != 0 ) 107 | Cdb::ThrowSQL("Cusers_messages::Get | mysql_stmt_prepare"); 108 | firstGet_ = false; 109 | } 110 | 111 | bindKey(sGet_, arg_user_id, arg_msg_id); 112 | 113 | if ( mysql_stmt_execute(sGet_) ) 114 | Cdb::ThrowSQL("Cusers_messages::Get | mysql_stmt_execute"); 115 | 116 | bindOutput(sGet_); 117 | 118 | if ( mysql_stmt_store_result(sGet_) ) 119 | Cdb::ThrowSQL("Cusers_messages::Get | mysql_stmt_store_result"); 120 | 121 | ret = mysql_stmt_fetch(sGet_); 122 | 123 | if ( ret != 0 ) 124 | { 125 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 126 | return false; 127 | else 128 | Cdb::ThrowSQL("Cusers_messages::Get | mysql_stmt_fetch"); 129 | } 130 | 131 | genDTStrings(); 132 | 133 | return true; 134 | } 135 | 136 | 137 | /* --------------------------------------------------------------------------- 138 | Insert record 139 | --------------------------------------------------------------------------- */ 140 | unsigned Cusers_messages::Insert() 141 | { 142 | int ret; 143 | 144 | if ( firstInsert_ ) 145 | { 146 | char q[CDB_SQLBUF]; 147 | sprintf(q, "INSERT INTO users_messages (user_id,msg_id,email,message,created) VALUES (?,?,?,?,?)"); 148 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 149 | if ( ret != 0 ) 150 | Cdb::ThrowSQL("Cusers_messages::Insert | mysql_stmt_prepare"); 151 | firstInsert_ = false; 152 | } 153 | 154 | bindInput(sInsert_); 155 | 156 | ret = mysql_stmt_execute(sInsert_); 157 | 158 | if ( ret != 0 ) 159 | Cdb::ThrowSQL("Cusers_messages::Insert | mysql_stmt_execute"); 160 | 161 | return mysql_insert_id(dbConn_); 162 | } 163 | 164 | 165 | /* --------------------------------------------------------------------------- 166 | Update record by PK 167 | --------------------------------------------------------------------------- */ 168 | void Cusers_messages::Update(int arg_user_id, int arg_msg_id) 169 | { 170 | int ret; 171 | 172 | if ( firstUpdate_ ) 173 | { 174 | char q[CDB_SQLBUF]; 175 | sprintf(q, "UPDATE users_messages SET user_id=?,msg_id=?,email=?,message=?,created=? WHERE user_id=? AND msg_id=?"); 176 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 177 | if ( ret != 0 ) 178 | Cdb::ThrowSQL("Cusers_messages::Update | mysql_stmt_prepare"); 179 | firstUpdate_ = false; 180 | } 181 | 182 | bindInput(sUpdate_, true, arg_user_id, arg_msg_id); 183 | 184 | ret = mysql_stmt_execute(sUpdate_); 185 | 186 | if ( ret != 0 ) 187 | Cdb::ThrowSQL("Cusers_messages::Update | mysql_stmt_execute"); 188 | } 189 | 190 | 191 | /* --------------------------------------------------------------------------- 192 | Delete record by PK 193 | --------------------------------------------------------------------------- */ 194 | void Cusers_messages::Delete(int arg_user_id, int arg_msg_id) 195 | { 196 | int ret; 197 | 198 | if ( firstDelete_ ) 199 | { 200 | char q[CDB_SQLBUF]; 201 | sprintf(q, "DELETE FROM users_messages WHERE user_id=? AND msg_id=?"); 202 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 203 | if ( ret != 0 ) 204 | Cdb::ThrowSQL("Cusers_messages::Delete | mysql_stmt_prepare"); 205 | firstDelete_ = false; 206 | } 207 | 208 | bindKey(sDelete_, arg_user_id, arg_msg_id); 209 | 210 | ret = mysql_stmt_execute(sDelete_); 211 | 212 | if ( ret != 0 ) 213 | Cdb::ThrowSQL("Cusers_messages::Delete | mysql_stmt_execute"); 214 | } 215 | 216 | 217 | /* --------------------------------------------------------------------------- 218 | Insert or update record by PK 219 | --------------------------------------------------------------------------- */ 220 | void Cusers_messages::Set(int arg_user_id, int arg_msg_id) 221 | { 222 | int ret; 223 | 224 | if ( firstSet_ ) 225 | { 226 | char q[CDB_SQLBUF]; 227 | sprintf(q, "SELECT user_id FROM users_messages WHERE user_id=? AND msg_id=?"); 228 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 229 | if ( ret != 0 ) 230 | Cdb::ThrowSQL("Cusers_messages::Set | mysql_stmt_prepare"); 231 | firstSet_ = false; 232 | } 233 | 234 | bindKey(sSet_, arg_user_id, arg_msg_id); 235 | 236 | if ( mysql_stmt_execute(sSet_) ) 237 | Cdb::ThrowSQL("Cusers_messages::Set | mysql_stmt_execute"); 238 | 239 | bindSetOutput(); 240 | 241 | if ( mysql_stmt_store_result(sSet_) ) 242 | Cdb::ThrowSQL("Cusers_messages::Set | mysql_stmt_store_result"); 243 | 244 | ret = mysql_stmt_fetch(sSet_); 245 | 246 | if ( ret == 0 ) /* record existed */ 247 | { 248 | Update(arg_user_id, arg_msg_id); 249 | } 250 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 251 | { 252 | user_id = arg_user_id; 253 | msg_id = arg_msg_id; 254 | 255 | Insert(); 256 | } 257 | else 258 | Cdb::ThrowSQL("Cusers_messages::Set | mysql_stmt_fetch"); 259 | } 260 | 261 | 262 | /* --------------------------------------------------------------------------- 263 | Bind key values 264 | --------------------------------------------------------------------------- */ 265 | void Cusers_messages::bindKey(MYSQL_STMT *s, int arg_user_id, int arg_msg_id) 266 | { 267 | k_user_id_ = arg_user_id; 268 | k_msg_id_ = arg_msg_id; 269 | 270 | memset(&bndk_, 0, sizeof(bndk_)); 271 | 272 | bndk_[0].buffer_type = MYSQL_TYPE_LONG; 273 | bndk_[0].buffer = (char*)&k_user_id_; 274 | 275 | bndk_[1].buffer_type = MYSQL_TYPE_LONG; 276 | bndk_[1].buffer = (char*)&k_msg_id_; 277 | 278 | if ( mysql_stmt_bind_param(s, bndk_) ) 279 | Cdb::ThrowSQL("Cusers_messages::bindKey | mysql_stmt_bind_param"); 280 | } 281 | 282 | 283 | /* --------------------------------------------------------------------------- 284 | Bind input values 285 | --------------------------------------------------------------------------- */ 286 | void Cusers_messages::bindInput(MYSQL_STMT *s, bool withKey, int arg_user_id, int arg_msg_id) 287 | { 288 | email_len_ = strlen(email); 289 | message_len_ = strlen(message); 290 | 291 | set_datetime(&t_created_, created); 292 | 293 | memset(&bndi_, 0, sizeof(bndi_)); 294 | 295 | bndi_[0].buffer_type = MYSQL_TYPE_LONG; 296 | bndi_[0].buffer = (char*)&user_id; 297 | 298 | bndi_[1].buffer_type = MYSQL_TYPE_LONG; 299 | bndi_[1].buffer = (char*)&msg_id; 300 | 301 | bndi_[2].buffer_type = MYSQL_TYPE_STRING; 302 | bndi_[2].buffer = (char*)email; 303 | bndi_[2].length = &email_len_; 304 | 305 | bndi_[3].buffer_type = MYSQL_TYPE_STRING; 306 | bndi_[3].buffer = (char*)message; 307 | bndi_[3].length = &message_len_; 308 | 309 | bndi_[4].buffer_type = MYSQL_TYPE_DATETIME; 310 | bndi_[4].buffer = (char*)&t_created_; 311 | 312 | if ( withKey ) /* after WHERE */ 313 | { 314 | k_user_id_ = arg_user_id; 315 | k_msg_id_ = arg_msg_id; 316 | 317 | bndi_[5].buffer_type = MYSQL_TYPE_LONG; 318 | bndi_[5].buffer = (char*)&k_user_id_; 319 | 320 | bndi_[6].buffer_type = MYSQL_TYPE_LONG; 321 | bndi_[6].buffer = (char*)&k_msg_id_; 322 | 323 | } 324 | 325 | if ( mysql_stmt_bind_param(s, bndi_) ) 326 | Cdb::ThrowSQL("Cusers_messages::bindInput | mysql_stmt_bind_param"); 327 | } 328 | 329 | 330 | /* --------------------------------------------------------------------------- 331 | Bind output values 332 | --------------------------------------------------------------------------- */ 333 | void Cusers_messages::bindOutput(MYSQL_STMT *s) 334 | { 335 | memset(&bndo_, 0, sizeof(bndo_)); 336 | 337 | bndo_[0].buffer_type = MYSQL_TYPE_LONG; 338 | bndo_[0].buffer = (char*)&user_id; 339 | bndo_[0].is_null = &user_id_is_null_; 340 | 341 | bndo_[1].buffer_type = MYSQL_TYPE_LONG; 342 | bndo_[1].buffer = (char*)&msg_id; 343 | bndo_[1].is_null = &msg_id_is_null_; 344 | 345 | bndo_[2].buffer_type = MYSQL_TYPE_STRING; 346 | bndo_[2].buffer = (char*)email; 347 | bndo_[2].buffer_length = 121; 348 | bndo_[2].is_null = &email_is_null_; 349 | 350 | bndo_[3].buffer_type = MYSQL_TYPE_STRING; 351 | bndo_[3].buffer = (char*)message; 352 | bndo_[3].buffer_length = 65536; 353 | bndo_[3].is_null = &message_is_null_; 354 | 355 | bndo_[4].buffer_type = MYSQL_TYPE_DATETIME; 356 | bndo_[4].buffer = (char*)&t_created_; 357 | bndo_[4].is_null = &created_is_null_; 358 | 359 | if ( mysql_stmt_bind_result(s, bndo_) ) 360 | Cdb::ThrowSQL("Cusers_messages::bindOutput | mysql_stmt_bind_result"); 361 | } 362 | 363 | 364 | /* --------------------------------------------------------------------------- 365 | Bind output value for Set 366 | --------------------------------------------------------------------------- */ 367 | void Cusers_messages::bindSetOutput() 368 | { 369 | static int user_id; /* to be scrapped anyway */ 370 | 371 | memset(&bndso_, 0, sizeof(bndso_)); 372 | 373 | bndso_[0].buffer_type = MYSQL_TYPE_LONG; 374 | bndso_[0].buffer = (char*)&user_id; 375 | 376 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 377 | Cdb::ThrowSQL("Cusers_messages::bindSetOutput | mysql_stmt_bind_result"); 378 | } 379 | 380 | 381 | /* --------------------------------------------------------------------------- 382 | Generate date-time strings 383 | --------------------------------------------------------------------------- */ 384 | void Cusers_messages::genDTStrings() 385 | { 386 | if ( created_is_null_ ) 387 | created[0] = EOS; 388 | else 389 | sprintf(created, "%04d-%02d-%02d %02d:%02d:%02d", t_created_.year, t_created_.month, t_created_.day, t_created_.hour, t_created_.minute, t_created_.second); 390 | 391 | } 392 | 393 | 394 | /* --------------------------------------------------------------------------- 395 | Reset (zero) public variables 396 | --------------------------------------------------------------------------- */ 397 | void Cusers_messages::Reset() 398 | { 399 | user_id = 0; 400 | msg_id = 0; 401 | email[0] = EOS; 402 | message[0] = EOS; 403 | created[0] = EOS; 404 | } 405 | -------------------------------------------------------------------------------- /lib/Cusers_activations.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 15:16:31, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_activations.h" 9 | 10 | 11 | bool Cusers_activations::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_activations::Cusers_activations() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_activations"; 22 | 23 | columnList_ = "linkkey," 24 | "user_id," 25 | "created," 26 | "activated"; 27 | 28 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 29 | ThrowSQL("mysql_stmt_init"); 30 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 31 | ThrowSQL("mysql_stmt_init"); 32 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 33 | ThrowSQL("mysql_stmt_init"); 34 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 35 | ThrowSQL("mysql_stmt_init"); 36 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 37 | ThrowSQL("mysql_stmt_init"); 38 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 39 | ThrowSQL("mysql_stmt_init"); 40 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 41 | ThrowSQL("mysql_stmt_init"); 42 | 43 | Reset(); 44 | } 45 | 46 | 47 | /* --------------------------------------------------------------------------- 48 | Destructor 49 | --------------------------------------------------------------------------- */ 50 | Cusers_activations::~Cusers_activations() 51 | { 52 | mysql_stmt_close(s_); 53 | mysql_stmt_close(sGet_); 54 | mysql_stmt_close(sUpdate_); 55 | mysql_stmt_close(sInsert_); 56 | mysql_stmt_close(sDelete_); 57 | mysql_stmt_close(sSet_); 58 | 59 | slots_[instance_] = false; 60 | } 61 | 62 | 63 | /* --------------------------------------------------------------------------- 64 | Get the next record 65 | Return false if end of record set 66 | --------------------------------------------------------------------------- */ 67 | bool Cusers_activations::Fetch() 68 | { 69 | int ret; 70 | 71 | ret = mysql_stmt_fetch(s_); 72 | 73 | if ( ret != 0 ) 74 | { 75 | Reset(); 76 | 77 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 78 | return false; 79 | else 80 | { 81 | Cdb::ThrowSQL("Cusers_activations::Fetch | mysql_stmt_fetch"); 82 | return false; 83 | } 84 | } 85 | 86 | genDTStrings(); 87 | 88 | return true; 89 | } 90 | 91 | 92 | /* --------------------------------------------------------------------------- 93 | Get record by PK 94 | Not Found will return false 95 | --------------------------------------------------------------------------- */ 96 | bool Cusers_activations::Get(const std::string& arg_linkkey) 97 | { 98 | int ret; 99 | 100 | if ( firstGet_ ) 101 | { 102 | char q[CDB_SQLBUF]; 103 | sprintf(q, "SELECT linkkey,user_id,created,activated FROM users_activations WHERE linkkey=BINARY ?"); 104 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 105 | if ( ret != 0 ) 106 | Cdb::ThrowSQL("Cusers_activations::Get | mysql_stmt_prepare"); 107 | firstGet_ = false; 108 | } 109 | 110 | bindKey(sGet_, arg_linkkey); 111 | 112 | if ( mysql_stmt_execute(sGet_) ) 113 | Cdb::ThrowSQL("Cusers_activations::Get | mysql_stmt_execute"); 114 | 115 | bindOutput(sGet_); 116 | 117 | if ( mysql_stmt_store_result(sGet_) ) 118 | Cdb::ThrowSQL("Cusers_activations::Get | mysql_stmt_store_result"); 119 | 120 | ret = mysql_stmt_fetch(sGet_); 121 | 122 | if ( ret != 0 ) 123 | { 124 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 125 | return false; 126 | else 127 | Cdb::ThrowSQL("Cusers_activations::Get | mysql_stmt_fetch"); 128 | } 129 | 130 | genDTStrings(); 131 | 132 | return true; 133 | } 134 | 135 | 136 | /* --------------------------------------------------------------------------- 137 | Insert record 138 | --------------------------------------------------------------------------- */ 139 | unsigned Cusers_activations::Insert() 140 | { 141 | int ret; 142 | 143 | if ( firstInsert_ ) 144 | { 145 | char q[CDB_SQLBUF]; 146 | sprintf(q, "INSERT INTO users_activations (linkkey,user_id,created,activated) VALUES (?,?,?,?)"); 147 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 148 | if ( ret != 0 ) 149 | Cdb::ThrowSQL("Cusers_activations::Insert | mysql_stmt_prepare"); 150 | firstInsert_ = false; 151 | } 152 | 153 | bindInput(sInsert_); 154 | 155 | ret = mysql_stmt_execute(sInsert_); 156 | 157 | if ( ret != 0 ) 158 | Cdb::ThrowSQL("Cusers_activations::Insert | mysql_stmt_execute"); 159 | 160 | return mysql_insert_id(dbConn_); 161 | } 162 | 163 | 164 | /* --------------------------------------------------------------------------- 165 | Update record by PK 166 | --------------------------------------------------------------------------- */ 167 | void Cusers_activations::Update(const std::string& arg_linkkey) 168 | { 169 | int ret; 170 | 171 | if ( firstUpdate_ ) 172 | { 173 | char q[CDB_SQLBUF]; 174 | sprintf(q, "UPDATE users_activations SET linkkey=?,user_id=?,created=?,activated=? WHERE linkkey=BINARY ?"); 175 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 176 | if ( ret != 0 ) 177 | Cdb::ThrowSQL("Cusers_activations::Update | mysql_stmt_prepare"); 178 | firstUpdate_ = false; 179 | } 180 | 181 | bindInput(sUpdate_, true, arg_linkkey); 182 | 183 | ret = mysql_stmt_execute(sUpdate_); 184 | 185 | if ( ret != 0 ) 186 | Cdb::ThrowSQL("Cusers_activations::Update | mysql_stmt_execute"); 187 | } 188 | 189 | 190 | /* --------------------------------------------------------------------------- 191 | Delete record by PK 192 | --------------------------------------------------------------------------- */ 193 | void Cusers_activations::Delete(const std::string& arg_linkkey) 194 | { 195 | int ret; 196 | 197 | if ( firstDelete_ ) 198 | { 199 | char q[CDB_SQLBUF]; 200 | sprintf(q, "DELETE FROM users_activations WHERE linkkey=BINARY ?"); 201 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 202 | if ( ret != 0 ) 203 | Cdb::ThrowSQL("Cusers_activations::Delete | mysql_stmt_prepare"); 204 | firstDelete_ = false; 205 | } 206 | 207 | bindKey(sDelete_, arg_linkkey); 208 | 209 | ret = mysql_stmt_execute(sDelete_); 210 | 211 | if ( ret != 0 ) 212 | Cdb::ThrowSQL("Cusers_activations::Delete | mysql_stmt_execute"); 213 | } 214 | 215 | 216 | /* --------------------------------------------------------------------------- 217 | Insert or update record by PK 218 | --------------------------------------------------------------------------- */ 219 | void Cusers_activations::Set(const std::string& arg_linkkey) 220 | { 221 | int ret; 222 | 223 | if ( firstSet_ ) 224 | { 225 | char q[CDB_SQLBUF]; 226 | sprintf(q, "SELECT linkkey FROM users_activations WHERE linkkey=BINARY ?"); 227 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 228 | if ( ret != 0 ) 229 | Cdb::ThrowSQL("Cusers_activations::Set | mysql_stmt_prepare"); 230 | firstSet_ = false; 231 | } 232 | 233 | bindKey(sSet_, arg_linkkey); 234 | 235 | if ( mysql_stmt_execute(sSet_) ) 236 | Cdb::ThrowSQL("Cusers_activations::Set | mysql_stmt_execute"); 237 | 238 | bindSetOutput(); 239 | 240 | if ( mysql_stmt_store_result(sSet_) ) 241 | Cdb::ThrowSQL("Cusers_activations::Set | mysql_stmt_store_result"); 242 | 243 | ret = mysql_stmt_fetch(sSet_); 244 | 245 | if ( ret == 0 ) /* record existed */ 246 | { 247 | Update(arg_linkkey); 248 | } 249 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 250 | { 251 | strncpy(linkkey, arg_linkkey.c_str(), 20); 252 | linkkey[20] = EOS; 253 | 254 | Insert(); 255 | } 256 | else 257 | Cdb::ThrowSQL("Cusers_activations::Set | mysql_stmt_fetch"); 258 | } 259 | 260 | 261 | /* --------------------------------------------------------------------------- 262 | Bind key values 263 | --------------------------------------------------------------------------- */ 264 | void Cusers_activations::bindKey(MYSQL_STMT *s, const std::string& arg_linkkey) 265 | { 266 | strncpy(k_linkkey_, arg_linkkey.c_str(), 20); 267 | k_linkkey_[20] = EOS; 268 | 269 | k_linkkey_len_ = strlen(k_linkkey_); 270 | 271 | memset(&bndk_, 0, sizeof(bndk_)); 272 | 273 | bndk_[0].buffer_type = MYSQL_TYPE_STRING; 274 | bndk_[0].buffer = (char*)k_linkkey_; 275 | bndk_[0].length = &k_linkkey_len_; 276 | 277 | if ( mysql_stmt_bind_param(s, bndk_) ) 278 | Cdb::ThrowSQL("Cusers_activations::bindKey | mysql_stmt_bind_param"); 279 | } 280 | 281 | 282 | /* --------------------------------------------------------------------------- 283 | Bind input values 284 | --------------------------------------------------------------------------- */ 285 | void Cusers_activations::bindInput(MYSQL_STMT *s, bool withKey, const std::string& arg_linkkey) 286 | { 287 | linkkey_len_ = strlen(linkkey); 288 | 289 | set_datetime(&t_created_, created); 290 | set_datetime(&t_activated_, activated); 291 | 292 | memset(&bndi_, 0, sizeof(bndi_)); 293 | 294 | bndi_[0].buffer_type = MYSQL_TYPE_STRING; 295 | bndi_[0].buffer = (char*)linkkey; 296 | bndi_[0].length = &linkkey_len_; 297 | 298 | bndi_[1].buffer_type = MYSQL_TYPE_LONG; 299 | bndi_[1].buffer = (char*)&user_id; 300 | 301 | bndi_[2].buffer_type = MYSQL_TYPE_DATETIME; 302 | bndi_[2].buffer = (char*)&t_created_; 303 | 304 | bndi_[3].buffer_type = MYSQL_TYPE_DATETIME; 305 | bndi_[3].buffer = (char*)&t_activated_; 306 | 307 | if ( withKey ) /* after WHERE */ 308 | { 309 | strncpy(k_linkkey_, arg_linkkey.c_str(), 20); 310 | k_linkkey_[20] = EOS; 311 | 312 | k_linkkey_len_ = strlen(k_linkkey_); 313 | 314 | bndi_[4].buffer_type = MYSQL_TYPE_STRING; 315 | bndi_[4].buffer = (char*)k_linkkey_; 316 | bndi_[4].length = &k_linkkey_len_; 317 | 318 | } 319 | 320 | if ( mysql_stmt_bind_param(s, bndi_) ) 321 | Cdb::ThrowSQL("Cusers_activations::bindInput | mysql_stmt_bind_param"); 322 | } 323 | 324 | 325 | /* --------------------------------------------------------------------------- 326 | Bind output values 327 | --------------------------------------------------------------------------- */ 328 | void Cusers_activations::bindOutput(MYSQL_STMT *s) 329 | { 330 | memset(&bndo_, 0, sizeof(bndo_)); 331 | 332 | bndo_[0].buffer_type = MYSQL_TYPE_STRING; 333 | bndo_[0].buffer = (char*)linkkey; 334 | bndo_[0].buffer_length = 21; 335 | bndo_[0].is_null = &linkkey_is_null_; 336 | 337 | bndo_[1].buffer_type = MYSQL_TYPE_LONG; 338 | bndo_[1].buffer = (char*)&user_id; 339 | bndo_[1].is_null = &user_id_is_null_; 340 | 341 | bndo_[2].buffer_type = MYSQL_TYPE_DATETIME; 342 | bndo_[2].buffer = (char*)&t_created_; 343 | bndo_[2].is_null = &created_is_null_; 344 | 345 | bndo_[3].buffer_type = MYSQL_TYPE_DATETIME; 346 | bndo_[3].buffer = (char*)&t_activated_; 347 | bndo_[3].is_null = &activated_is_null_; 348 | 349 | if ( mysql_stmt_bind_result(s, bndo_) ) 350 | Cdb::ThrowSQL("Cusers_activations::bindOutput | mysql_stmt_bind_result"); 351 | } 352 | 353 | 354 | /* --------------------------------------------------------------------------- 355 | Bind output value for Set 356 | --------------------------------------------------------------------------- */ 357 | void Cusers_activations::bindSetOutput() 358 | { 359 | static USERS_ACTIVATIONS_LINKKEY linkkey; /* to be scrapped anyway */ 360 | 361 | memset(&bndso_, 0, sizeof(bndso_)); 362 | 363 | bndso_[0].buffer_type = MYSQL_TYPE_STRING; 364 | bndso_[0].buffer = (char*)linkkey; 365 | bndso_[0].buffer_length = 21; 366 | 367 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 368 | Cdb::ThrowSQL("Cusers_activations::bindSetOutput | mysql_stmt_bind_result"); 369 | } 370 | 371 | 372 | /* --------------------------------------------------------------------------- 373 | Generate date-time strings 374 | --------------------------------------------------------------------------- */ 375 | void Cusers_activations::genDTStrings() 376 | { 377 | if ( created_is_null_ ) 378 | created[0] = EOS; 379 | else 380 | sprintf(created, "%04d-%02d-%02d %02d:%02d:%02d", t_created_.year, t_created_.month, t_created_.day, t_created_.hour, t_created_.minute, t_created_.second); 381 | 382 | if ( activated_is_null_ ) 383 | activated[0] = EOS; 384 | else 385 | sprintf(activated, "%04d-%02d-%02d %02d:%02d:%02d", t_activated_.year, t_activated_.month, t_activated_.day, t_activated_.hour, t_activated_.minute, t_activated_.second); 386 | } 387 | 388 | 389 | /* --------------------------------------------------------------------------- 390 | Reset (zero) public variables 391 | --------------------------------------------------------------------------- */ 392 | void Cusers_activations::Reset() 393 | { 394 | linkkey[0] = EOS; 395 | user_id = 0; 396 | created[0] = EOS; 397 | activated[0] = EOS; 398 | } 399 | -------------------------------------------------------------------------------- /lib/Cusers_logins.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-28 14:28:27, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers_logins.h" 9 | 10 | 11 | bool Cusers_logins::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers_logins::Cusers_logins() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users_logins"; 22 | 23 | columnList_ = "sessid," 24 | "uagent," 25 | "ip," 26 | "user_id," 27 | "csrft," 28 | "created," 29 | "last_used"; 30 | 31 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 32 | ThrowSQL("mysql_stmt_init"); 33 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 34 | ThrowSQL("mysql_stmt_init"); 35 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 36 | ThrowSQL("mysql_stmt_init"); 37 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 38 | ThrowSQL("mysql_stmt_init"); 39 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 40 | ThrowSQL("mysql_stmt_init"); 41 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 42 | ThrowSQL("mysql_stmt_init"); 43 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 44 | ThrowSQL("mysql_stmt_init"); 45 | 46 | Reset(); 47 | } 48 | 49 | 50 | /* --------------------------------------------------------------------------- 51 | Destructor 52 | --------------------------------------------------------------------------- */ 53 | Cusers_logins::~Cusers_logins() 54 | { 55 | mysql_stmt_close(s_); 56 | mysql_stmt_close(sGet_); 57 | mysql_stmt_close(sUpdate_); 58 | mysql_stmt_close(sInsert_); 59 | mysql_stmt_close(sDelete_); 60 | mysql_stmt_close(sSet_); 61 | 62 | slots_[instance_] = false; 63 | } 64 | 65 | 66 | /* --------------------------------------------------------------------------- 67 | Get the next record 68 | Return false if end of record set 69 | --------------------------------------------------------------------------- */ 70 | bool Cusers_logins::Fetch() 71 | { 72 | int ret; 73 | 74 | ret = mysql_stmt_fetch(s_); 75 | 76 | if ( ret != 0 ) 77 | { 78 | Reset(); 79 | 80 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 81 | return false; 82 | else 83 | { 84 | Cdb::ThrowSQL("Cusers_logins::Fetch | mysql_stmt_fetch"); 85 | return false; 86 | } 87 | } 88 | 89 | genDTStrings(); 90 | 91 | return true; 92 | } 93 | 94 | 95 | /* --------------------------------------------------------------------------- 96 | Get record by PK 97 | Not Found will return false 98 | --------------------------------------------------------------------------- */ 99 | bool Cusers_logins::Get(const std::string& arg_sessid) 100 | { 101 | int ret; 102 | 103 | if ( firstGet_ ) 104 | { 105 | char q[CDB_SQLBUF]; 106 | sprintf(q, "SELECT sessid,uagent,ip,user_id,csrft,created,last_used FROM users_logins WHERE sessid=BINARY ?"); 107 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 108 | if ( ret != 0 ) 109 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_prepare"); 110 | firstGet_ = false; 111 | } 112 | 113 | bindKey(sGet_, arg_sessid); 114 | 115 | if ( mysql_stmt_execute(sGet_) ) 116 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_execute"); 117 | 118 | bindOutput(sGet_); 119 | 120 | if ( mysql_stmt_store_result(sGet_) ) 121 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_store_result"); 122 | 123 | ret = mysql_stmt_fetch(sGet_); 124 | 125 | if ( ret != 0 ) 126 | { 127 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 128 | return false; 129 | else 130 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_fetch"); 131 | } 132 | 133 | genDTStrings(); 134 | 135 | return true; 136 | } 137 | 138 | 139 | /* --------------------------------------------------------------------------- 140 | Insert record 141 | --------------------------------------------------------------------------- */ 142 | unsigned Cusers_logins::Insert() 143 | { 144 | int ret; 145 | 146 | if ( firstInsert_ ) 147 | { 148 | char q[CDB_SQLBUF]; 149 | sprintf(q, "INSERT INTO users_logins (sessid,uagent,ip,user_id,csrft,created,last_used) VALUES (?,?,?,?,?,?,?)"); 150 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 151 | if ( ret != 0 ) 152 | Cdb::ThrowSQL("Cusers_logins::Insert | mysql_stmt_prepare"); 153 | firstInsert_ = false; 154 | } 155 | 156 | bindInput(sInsert_); 157 | 158 | ret = mysql_stmt_execute(sInsert_); 159 | 160 | if ( ret != 0 ) 161 | Cdb::ThrowSQL("Cusers_logins::Insert | mysql_stmt_execute"); 162 | 163 | return mysql_insert_id(dbConn_); 164 | } 165 | 166 | 167 | /* --------------------------------------------------------------------------- 168 | Update record by PK 169 | --------------------------------------------------------------------------- */ 170 | void Cusers_logins::Update(const std::string& arg_sessid) 171 | { 172 | int ret; 173 | 174 | if ( firstUpdate_ ) 175 | { 176 | char q[CDB_SQLBUF]; 177 | sprintf(q, "UPDATE users_logins SET sessid=?,uagent=?,ip=?,user_id=?,csrft=?,created=?,last_used=? WHERE sessid=BINARY ?"); 178 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 179 | if ( ret != 0 ) 180 | Cdb::ThrowSQL("Cusers_logins::Update | mysql_stmt_prepare"); 181 | firstUpdate_ = false; 182 | } 183 | 184 | bindInput(sUpdate_, true, arg_sessid); 185 | 186 | ret = mysql_stmt_execute(sUpdate_); 187 | 188 | if ( ret != 0 ) 189 | Cdb::ThrowSQL("Cusers_logins::Update | mysql_stmt_execute"); 190 | } 191 | 192 | 193 | /* --------------------------------------------------------------------------- 194 | Delete record by PK 195 | --------------------------------------------------------------------------- */ 196 | void Cusers_logins::Delete(const std::string& arg_sessid) 197 | { 198 | int ret; 199 | 200 | if ( firstDelete_ ) 201 | { 202 | char q[CDB_SQLBUF]; 203 | sprintf(q, "DELETE FROM users_logins WHERE sessid=BINARY ?"); 204 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 205 | if ( ret != 0 ) 206 | Cdb::ThrowSQL("Cusers_logins::Delete | mysql_stmt_prepare"); 207 | firstDelete_ = false; 208 | } 209 | 210 | bindKey(sDelete_, arg_sessid); 211 | 212 | ret = mysql_stmt_execute(sDelete_); 213 | 214 | if ( ret != 0 ) 215 | Cdb::ThrowSQL("Cusers_logins::Delete | mysql_stmt_execute"); 216 | } 217 | 218 | 219 | /* --------------------------------------------------------------------------- 220 | Insert or update record by PK 221 | --------------------------------------------------------------------------- */ 222 | void Cusers_logins::Set(const std::string& arg_sessid) 223 | { 224 | int ret; 225 | 226 | if ( firstSet_ ) 227 | { 228 | char q[CDB_SQLBUF]; 229 | sprintf(q, "SELECT sessid FROM users_logins WHERE sessid=BINARY ?"); 230 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 231 | if ( ret != 0 ) 232 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_prepare"); 233 | firstSet_ = false; 234 | } 235 | 236 | bindKey(sSet_, arg_sessid); 237 | 238 | if ( mysql_stmt_execute(sSet_) ) 239 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_execute"); 240 | 241 | bindSetOutput(); 242 | 243 | if ( mysql_stmt_store_result(sSet_) ) 244 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_store_result"); 245 | 246 | ret = mysql_stmt_fetch(sSet_); 247 | 248 | if ( ret == 0 ) /* record existed */ 249 | { 250 | Update(arg_sessid); 251 | } 252 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 253 | { 254 | strncpy(sessid, arg_sessid.c_str(), 15); 255 | sessid[15] = EOS; 256 | 257 | Insert(); 258 | } 259 | else 260 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_fetch"); 261 | } 262 | 263 | 264 | /* --------------------------------------------------------------------------- 265 | Bind key values 266 | --------------------------------------------------------------------------- */ 267 | void Cusers_logins::bindKey(MYSQL_STMT *s, const std::string& arg_sessid) 268 | { 269 | strncpy(k_sessid_, arg_sessid.c_str(), 15); 270 | k_sessid_[15] = EOS; 271 | 272 | k_sessid_len_ = strlen(k_sessid_); 273 | 274 | memset(&bndk_, 0, sizeof(bndk_)); 275 | 276 | bndk_[0].buffer_type = MYSQL_TYPE_STRING; 277 | bndk_[0].buffer = (char*)k_sessid_; 278 | bndk_[0].length = &k_sessid_len_; 279 | 280 | if ( mysql_stmt_bind_param(s, bndk_) ) 281 | Cdb::ThrowSQL("Cusers_logins::bindKey | mysql_stmt_bind_param"); 282 | } 283 | 284 | 285 | /* --------------------------------------------------------------------------- 286 | Bind input values 287 | --------------------------------------------------------------------------- */ 288 | void Cusers_logins::bindInput(MYSQL_STMT *s, bool withKey, const std::string& arg_sessid) 289 | { 290 | sessid_len_ = strlen(sessid); 291 | uagent_len_ = strlen(uagent); 292 | ip_len_ = strlen(ip); 293 | csrft_len_ = strlen(csrft); 294 | 295 | set_datetime(&t_created_, created); 296 | set_datetime(&t_last_used_, last_used); 297 | 298 | memset(&bndi_, 0, sizeof(bndi_)); 299 | 300 | bndi_[0].buffer_type = MYSQL_TYPE_STRING; 301 | bndi_[0].buffer = (char*)sessid; 302 | bndi_[0].length = &sessid_len_; 303 | 304 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 305 | bndi_[1].buffer = (char*)uagent; 306 | bndi_[1].length = &uagent_len_; 307 | 308 | bndi_[2].buffer_type = MYSQL_TYPE_STRING; 309 | bndi_[2].buffer = (char*)ip; 310 | bndi_[2].length = &ip_len_; 311 | 312 | bndi_[3].buffer_type = MYSQL_TYPE_LONG; 313 | bndi_[3].buffer = (char*)&user_id; 314 | 315 | bndi_[4].buffer_type = MYSQL_TYPE_STRING; 316 | bndi_[4].buffer = (char*)csrft; 317 | bndi_[4].length = &csrft_len_; 318 | 319 | bndi_[5].buffer_type = MYSQL_TYPE_DATETIME; 320 | bndi_[5].buffer = (char*)&t_created_; 321 | 322 | bndi_[6].buffer_type = MYSQL_TYPE_DATETIME; 323 | bndi_[6].buffer = (char*)&t_last_used_; 324 | 325 | if ( withKey ) /* after WHERE */ 326 | { 327 | strncpy(k_sessid_, arg_sessid.c_str(), 15); 328 | k_sessid_[15] = EOS; 329 | 330 | k_sessid_len_ = strlen(k_sessid_); 331 | 332 | bndi_[7].buffer_type = MYSQL_TYPE_STRING; 333 | bndi_[7].buffer = (char*)k_sessid_; 334 | bndi_[7].length = &k_sessid_len_; 335 | 336 | } 337 | 338 | if ( mysql_stmt_bind_param(s, bndi_) ) 339 | Cdb::ThrowSQL("Cusers_logins::bindInput | mysql_stmt_bind_param"); 340 | } 341 | 342 | 343 | /* --------------------------------------------------------------------------- 344 | Bind output values 345 | --------------------------------------------------------------------------- */ 346 | void Cusers_logins::bindOutput(MYSQL_STMT *s) 347 | { 348 | memset(&bndo_, 0, sizeof(bndo_)); 349 | 350 | bndo_[0].buffer_type = MYSQL_TYPE_STRING; 351 | bndo_[0].buffer = (char*)sessid; 352 | bndo_[0].buffer_length = 16; 353 | bndo_[0].is_null = &sessid_is_null_; 354 | 355 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 356 | bndo_[1].buffer = (char*)uagent; 357 | bndo_[1].buffer_length = 251; 358 | bndo_[1].is_null = &uagent_is_null_; 359 | 360 | bndo_[2].buffer_type = MYSQL_TYPE_STRING; 361 | bndo_[2].buffer = (char*)ip; 362 | bndo_[2].buffer_length = 46; 363 | bndo_[2].is_null = &ip_is_null_; 364 | 365 | bndo_[3].buffer_type = MYSQL_TYPE_LONG; 366 | bndo_[3].buffer = (char*)&user_id; 367 | bndo_[3].is_null = &user_id_is_null_; 368 | 369 | bndo_[4].buffer_type = MYSQL_TYPE_STRING; 370 | bndo_[4].buffer = (char*)csrft; 371 | bndo_[4].buffer_length = 8; 372 | bndo_[4].is_null = &csrft_is_null_; 373 | 374 | bndo_[5].buffer_type = MYSQL_TYPE_DATETIME; 375 | bndo_[5].buffer = (char*)&t_created_; 376 | bndo_[5].is_null = &created_is_null_; 377 | 378 | bndo_[6].buffer_type = MYSQL_TYPE_DATETIME; 379 | bndo_[6].buffer = (char*)&t_last_used_; 380 | bndo_[6].is_null = &last_used_is_null_; 381 | 382 | if ( mysql_stmt_bind_result(s, bndo_) ) 383 | Cdb::ThrowSQL("Cusers_logins::bindOutput | mysql_stmt_bind_result"); 384 | } 385 | 386 | 387 | /* --------------------------------------------------------------------------- 388 | Bind output value for Set 389 | --------------------------------------------------------------------------- */ 390 | void Cusers_logins::bindSetOutput() 391 | { 392 | static USERS_LOGINS_SESSID sessid; /* to be scrapped anyway */ 393 | 394 | memset(&bndso_, 0, sizeof(bndso_)); 395 | 396 | bndso_[0].buffer_type = MYSQL_TYPE_STRING; 397 | bndso_[0].buffer = (char*)sessid; 398 | bndso_[0].buffer_length = 16; 399 | 400 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 401 | Cdb::ThrowSQL("Cusers_logins::bindSetOutput | mysql_stmt_bind_result"); 402 | } 403 | 404 | 405 | /* --------------------------------------------------------------------------- 406 | Generate date-time strings 407 | --------------------------------------------------------------------------- */ 408 | void Cusers_logins::genDTStrings() 409 | { 410 | if ( created_is_null_ ) 411 | created[0] = EOS; 412 | else 413 | sprintf(created, "%04d-%02d-%02d %02d:%02d:%02d", t_created_.year, t_created_.month, t_created_.day, t_created_.hour, t_created_.minute, t_created_.second); 414 | 415 | if ( last_used_is_null_ ) 416 | last_used[0] = EOS; 417 | else 418 | sprintf(last_used, "%04d-%02d-%02d %02d:%02d:%02d", t_last_used_.year, t_last_used_.month, t_last_used_.day, t_last_used_.hour, t_last_used_.minute, t_last_used_.second); 419 | } 420 | 421 | 422 | /* --------------------------------------------------------------------------- 423 | Reset (zero) public variables 424 | --------------------------------------------------------------------------- */ 425 | void Cusers_logins::Reset() 426 | { 427 | sessid[0] = EOS; 428 | uagent[0] = EOS; 429 | ip[0] = EOS; 430 | user_id = 0; 431 | csrft[0] = EOS; 432 | created[0] = EOS; 433 | last_used[0] = EOS; 434 | } 435 | -------------------------------------------------------------------------------- /lib/npp_usr.h: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | ----------------------------------------------------------------------------- 26 | 27 | Node++ Web App Engine 28 | Logged in users' functions 29 | nodepp.org 30 | 31 | -------------------------------------------------------------------------- */ 32 | 33 | #ifndef NPP_USR_H 34 | #define NPP_USR_H 35 | 36 | 37 | /* -------------------------------------------------------------------------- 38 | macros 39 | -------------------------------------------------------------------------- */ 40 | 41 | #define NPP_PASSWD_HASH_BUFLEN 45 /* SHA256 digest in base64 + EOS */ 42 | 43 | 44 | #define NPP_DB_UAGENT_LEN 250 /* User-Agent length stored in ulogins table */ 45 | #define NPP_PASSWD_RESET_KEY_LEN 20 /* password reset key length */ 46 | 47 | 48 | /* user status */ 49 | 50 | #define USER_STATUS_INACTIVE (char)0 51 | #define USER_STATUS_ACTIVE (char)1 52 | #define USER_STATUS_LOCKED (char)2 53 | #define USER_STATUS_PASSWORD_CHANGE (char)3 54 | #define USER_STATUS_DELETED (char)9 55 | 56 | 57 | #define NPP_COMMON_PASSWORDS_FILE "passwords.txt" 58 | 59 | 60 | 61 | /* APP-configurable */ 62 | 63 | #ifndef NPP_MIN_USERNAME_LEN 64 | #define NPP_MIN_USERNAME_LEN 2 /* minimum user name length */ 65 | #endif 66 | 67 | #ifndef NPP_MIN_PASSWORD_LEN 68 | #define NPP_MIN_PASSWORD_LEN 5 /* minimum password length */ 69 | #endif 70 | 71 | #ifndef MAX_ULA_BEFORE_FIRST_SLOW /* maximum unsuccessful login attempts before slowing down to 1 per minute */ 72 | #define MAX_ULA_BEFORE_FIRST_SLOW 10 73 | #endif 74 | 75 | #ifndef MAX_ULA_BEFORE_SECOND_SLOW /* maximum unsuccessful login attempts before slowing down to 1 per hour */ 76 | #define MAX_ULA_BEFORE_SECOND_SLOW 25 77 | #endif 78 | 79 | #ifndef MAX_ULA_BEFORE_THIRD_SLOW /* maximum unsuccessful login attempts before slowing down to 1 per day */ 80 | #define MAX_ULA_BEFORE_THIRD_SLOW 100 81 | #endif 82 | 83 | #ifndef MAX_ULA_BEFORE_LOCK /* maximum unsuccessful login attempts before user lockout */ 84 | #define MAX_ULA_BEFORE_LOCK 1000 85 | #endif 86 | 87 | #ifndef NPP_DEFAULT_USER_AUTH_LEVEL 88 | #define NPP_DEFAULT_USER_AUTH_LEVEL AUTH_LEVEL_USER /* default new user authorization level */ 89 | #endif 90 | 91 | #ifndef NPP_USER_ACTIVATION_HOURS 92 | #define NPP_USER_ACTIVATION_HOURS 48 /* activate user account within */ 93 | #endif 94 | 95 | #ifndef NPP_USER_KEEP_LOGGED_DAYS 96 | #define NPP_USER_KEEP_LOGGED_DAYS 30 /* ls cookie validity period */ 97 | #endif 98 | 99 | #ifndef NPP_AUTH_SESSION_TIMEOUT 100 | #define NPP_AUTH_SESSION_TIMEOUT 1800 /* authenticated session timeout in seconds (120 for tests / 1800 live) */ 101 | #endif /* (it's really how long it stays in cache) */ 102 | 103 | 104 | #ifndef REFUSE_10_COMMON_PASSWORDS 105 | #ifndef REFUSE_100_COMMON_PASSWORDS 106 | #ifndef REFUSE_1000_COMMON_PASSWORDS 107 | #ifndef REFUSE_10000_COMMON_PASSWORDS 108 | #ifndef DONT_REFUSE_COMMON_PASSWORDS 109 | #define DONT_REFUSE_COMMON_PASSWORDS 110 | #endif 111 | #endif 112 | #endif 113 | #endif 114 | #endif 115 | 116 | /* passwords' peppers */ 117 | 118 | #ifndef NPP_PEPPER_01 119 | #define NPP_PEPPER_01 "abcde" 120 | #endif 121 | #ifndef NPP_PEPPER_02 122 | #define NPP_PEPPER_02 "fghij" 123 | #endif 124 | #ifndef NPP_PEPPER_03 125 | #define NPP_PEPPER_03 "klmno" 126 | #endif 127 | #ifndef NPP_PEPPER_04 128 | #define NPP_PEPPER_04 "pqrst" 129 | #endif 130 | #ifndef NPP_PEPPER_05 131 | #define NPP_PEPPER_05 "uvwxy" 132 | #endif 133 | 134 | 135 | /* Node++ engine errors are 0 ... 99 */ 136 | 137 | /* ------------------------------------- */ 138 | /* errors -- red */ 139 | 140 | /* login */ 141 | #define ERR_INVALID_LOGIN 101 142 | #define ERR_USERNAME_TOO_SHORT 102 143 | #define ERR_USERNAME_CHARS 103 144 | #define ERR_USERNAME_TAKEN 104 145 | /* ------------------------------------- */ 146 | #define ERR_MAX_USR_LOGIN_ERROR 110 147 | /* ------------------------------------- */ 148 | /* email */ 149 | #define ERR_EMAIL_EMPTY 111 150 | #define ERR_EMAIL_FORMAT 112 151 | #define ERR_EMAIL_FORMAT_OR_EMPTY 113 152 | #define ERR_EMAIL_TAKEN 114 153 | /* ------------------------------------- */ 154 | #define ERR_MAX_USR_EMAIL_ERROR 120 155 | /* ------------------------------------- */ 156 | /* password */ 157 | #define ERR_INVALID_PASSWORD 121 158 | #define ERR_PASSWORD_TOO_SHORT 122 159 | #define ERR_IN_10_COMMON_PASSWORDS 123 160 | #define ERR_IN_100_COMMON_PASSWORDS 124 161 | #define ERR_IN_1000_COMMON_PASSWORDS 125 162 | #define ERR_IN_10000_COMMON_PASSWORDS 126 163 | /* ------------------------------------- */ 164 | #define ERR_MAX_USR_PASSWORD_ERROR 130 165 | /* ------------------------------------- */ 166 | /* repeat password */ 167 | #define ERR_PASSWORD_DIFFERENT 131 168 | /* ------------------------------------- */ 169 | #define ERR_MAX_USR_REPEAT_PASSWORD_ERROR 140 170 | /* ------------------------------------- */ 171 | /* old password */ 172 | #define ERR_OLD_PASSWORD 141 173 | /* ------------------------------------- */ 174 | #define ERR_MAX_USR_OLD_PASSWORD_ERROR 150 175 | /* ------------------------------------- */ 176 | /* session / link / other */ 177 | #define ERR_SESSION_EXPIRED 151 178 | #define ERR_LINK_BROKEN 152 179 | #define ERR_LINK_MAY_BE_EXPIRED 153 180 | #define ERR_LINK_EXPIRED 154 181 | #define ERR_LINK_TOO_MANY_TRIES 155 182 | #define ERR_ROBOT 156 183 | #define ERR_WEBSITE_FIRST_LETTER 157 184 | #define ERR_NOT_ACTIVATED 158 185 | /* ------------------------------------- */ 186 | #define ERR_MAX_USR_ERROR 199 187 | /* ------------------------------------- */ 188 | 189 | /* ------------------------------------- */ 190 | /* warnings -- yellow */ 191 | 192 | #define WAR_NO_EMAIL 201 193 | #define WAR_BEFORE_DELETE 202 194 | #define WAR_ULA_FIRST 203 195 | #define WAR_ULA_SECOND 204 196 | #define WAR_ULA_THIRD 205 197 | #define WAR_PASSWORD_CHANGE 206 198 | /* ------------------------------------- */ 199 | #define WAR_MAX_USR_WARNING 299 200 | /* ------------------------------------- */ 201 | 202 | /* ------------------------------------- */ 203 | /* messages -- green */ 204 | 205 | #define MSG_WELCOME_NO_ACTIVATION 301 206 | #define MSG_WELCOME_NEED_ACTIVATION 302 207 | #define MSG_WELCOME_AFTER_ACTIVATION 303 208 | #define MSG_USER_LOGGED_OUT 304 209 | #define MSG_CHANGES_SAVED 305 210 | #define MSG_REQUEST_SENT 306 211 | #define MSG_PASSWORD_CHANGED 307 212 | #define MSG_MESSAGE_SENT 308 213 | #define MSG_PROVIDE_FEEDBACK 309 214 | #define MSG_FEEDBACK_SENT 310 215 | #define MSG_USER_ALREADY_ACTIVATED 311 216 | #define MSG_ACCOUNT_DELETED 312 217 | /* ------------------------------------- */ 218 | #define MSG_MAX_USR_MESSAGE 399 219 | /* ------------------------------------- */ 220 | 221 | 222 | #define MSG_CAT_USR_LOGIN "msgLogin" 223 | #define MSG_CAT_USR_EMAIL "msgEmail" 224 | #define MSG_CAT_USR_PASSWORD "msgPassword" 225 | #define MSG_CAT_USR_REPEAT_PASSWORD "msgPasswordRepeat" 226 | #define MSG_CAT_USR_OLD_PASSWORD "msgPasswordOld" 227 | 228 | 229 | /* user authentication */ 230 | 231 | #ifndef NPP_USERS_BY_EMAIL 232 | #ifndef NPP_USERS_BY_LOGIN 233 | #define NPP_USERS_BY_LOGIN 234 | #endif 235 | #endif 236 | 237 | 238 | #define NPP_MAX_AVATAR_SIZE 65536 /* MySQL's BLOB size */ 239 | 240 | 241 | #define SET_USER_STR(key, val) npp_usr_set_str(ci, key, val) 242 | #define SET_USR_STR(key, val) npp_usr_set_str(ci, key, val) 243 | 244 | #define GET_USER_STR(key, val) npp_usr_get_str(ci, key, val) 245 | #define GET_USR_STR(key, val) npp_usr_get_str(ci, key, val) 246 | 247 | #define SET_USER_INT(key, val) npp_usr_set_int(ci, key, val) 248 | #define SET_USR_INT(key, val) npp_usr_set_int(ci, key, val) 249 | 250 | #define GET_USER_INT(key, val) npp_usr_get_int(ci, key, val) 251 | #define GET_USR_INT(key, val) npp_usr_get_int(ci, key, val) 252 | 253 | 254 | /* 255 | Brute-force ls cookie attack protection. 256 | It essentially defines how many different IPs can take part in a botnet attack. 257 | */ 258 | 259 | #ifdef NPP_MEM_TINY 260 | #define FAILED_LOGIN_CNT_SIZE 100 261 | #elif defined NPP_MEM_MEDIUM 262 | #define FAILED_LOGIN_CNT_SIZE 1000 263 | #elif defined NPP_MEM_LARGE 264 | #define FAILED_LOGIN_CNT_SIZE 10000 265 | #elif defined NPP_MEM_XLARGE 266 | #define FAILED_LOGIN_CNT_SIZE 10000 267 | #elif defined NPP_MEM_XXLARGE 268 | #define FAILED_LOGIN_CNT_SIZE 100000 269 | #elif defined NPP_MEM_XXXLARGE 270 | #define FAILED_LOGIN_CNT_SIZE 100000 271 | #elif defined NPP_MEM_XXXXLARGE 272 | #define FAILED_LOGIN_CNT_SIZE 100000 273 | #else /* NPP_MEM_SMALL -- default */ 274 | #define FAILED_LOGIN_CNT_SIZE 1000 275 | #endif 276 | 277 | 278 | 279 | /* -------------------------------------------------------------------------- 280 | structures 281 | -------------------------------------------------------------------------- */ 282 | 283 | typedef struct { 284 | char ip[INET_ADDRSTRLEN]; 285 | int cnt; 286 | time_t when; 287 | } failed_login_cnt_t; 288 | 289 | 290 | 291 | /* -------------------------------------------------------------------------- 292 | prototypes 293 | -------------------------------------------------------------------------- */ 294 | 295 | #ifdef NPP_CPP_STRINGS 296 | char *npp_usr_name(const char *login, const char *email, const char *name, int user_id); 297 | char *npp_usr_name(const std::string& login, const std::string& email, const std::string& name, int user_id); 298 | 299 | int npp_usr_get_str(int ci, const std::string& us_key, char *us_val); 300 | int npp_usr_get_str(int ci, const std::string& us_key, std::string& us_val); 301 | #endif 302 | 303 | 304 | #ifdef __cplusplus 305 | extern "C" { 306 | #endif 307 | 308 | int npp_usr_login(int ci); 309 | 310 | #ifdef NPP_CPP_STRINGS 311 | int npp_usr_password_quality(const std::string& passwd); 312 | #else 313 | int npp_usr_password_quality(const char *passwd); 314 | #endif 315 | 316 | int npp_usr_create_account(int ci); 317 | 318 | #ifdef NPP_CPP_STRINGS 319 | int npp_usr_add_user(int ci, bool use_qs, const std::string& login, const std::string& email, const std::string& name, const std::string& passwd, const std::string& phone, const std::string& lang, const std::string& about, char group_id, char auth_level, char status); 320 | #else 321 | int npp_usr_add_user(int ci, bool use_qs, const char *login, const char *email, const char *name, const char *passwd, const char *phone, const char *lang, const char *about, char group_id, char auth_level, char status); 322 | #endif 323 | 324 | int npp_usr_send_message(int ci); 325 | int npp_usr_save_account(int ci); 326 | int npp_usr_email_registered(int ci); 327 | 328 | #ifndef NPP_CPP_STRINGS 329 | char *npp_usr_name(const char *login, const char *email, const char *name, int user_id); 330 | #endif 331 | 332 | int npp_usr_send_passwd_reset_email(int ci); 333 | 334 | #ifdef NPP_CPP_STRINGS 335 | int npp_usr_verify_passwd_reset_key(int ci, const std::string& linkkey, int *user_id); 336 | #else 337 | int npp_usr_verify_passwd_reset_key(int ci, const char *linkkey, int *user_id); 338 | #endif 339 | 340 | int npp_usr_activate(int ci); 341 | int npp_usr_save_avatar(int ci, int user_id); 342 | int npp_usr_get_avatar(int ci, int user_id); 343 | int npp_usr_change_password(int ci); 344 | int npp_usr_reset_password(int ci); 345 | void npp_usr_logout(int ci); 346 | 347 | #ifdef NPP_CPP_STRINGS 348 | int npp_usr_set_str(int ci, const std::string& us_key, const std::string& us_val); 349 | #else 350 | int npp_usr_set_str(int ci, const char *us_key, const char *us_val); 351 | #endif 352 | 353 | #ifndef NPP_CPP_STRINGS 354 | int npp_usr_get_str(int ci, const char *us_key, char *us_val); 355 | #endif 356 | 357 | #ifdef NPP_CPP_STRINGS 358 | int npp_usr_set_int(int ci, const std::string& us_key, int us_val); 359 | #else 360 | int npp_usr_set_int(int ci, const char *us_key, int us_val); 361 | #endif 362 | 363 | #ifdef NPP_CPP_STRINGS 364 | int npp_usr_get_int(int ci, const std::string& us_key, int *us_val); 365 | #else 366 | int npp_usr_get_int(int ci, const char *us_key, int *us_val); 367 | #endif 368 | 369 | /* for the engine */ 370 | 371 | void libusr_init(void); 372 | int libusr_luses_ok(int ci); 373 | void libusr_luses_close_timeouted(void); 374 | void libusr_luses_save_csrft(void); 375 | void libusr_luses_downgrade(int si, int ci, bool usr_logout); 376 | 377 | #ifdef __cplusplus 378 | } // extern "C" 379 | #endif 380 | 381 | 382 | #endif /* NPP_USR_H */ 383 | -------------------------------------------------------------------------------- /lib/Cusers.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-03-29 20:05:41, generator v.2.0.1 4 | Using C-style strings 5 | Using exceptions 6 | --------------------------------------------------------------------------- */ 7 | 8 | #include "Cusers.h" 9 | 10 | 11 | bool Cusers::slots_[CDB_MAX_INSTANCES]={0}; 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | Constructor 16 | --------------------------------------------------------------------------- */ 17 | Cusers::Cusers() 18 | { 19 | setInstance(slots_); 20 | 21 | table_ = "users"; 22 | 23 | columnList_ = "id," 24 | "login," 25 | "login_u," 26 | "email," 27 | "email_u," 28 | "name," 29 | "phone," 30 | "passwd1," 31 | "passwd2," 32 | "lang," 33 | "about," 34 | "group_id," 35 | "auth_level," 36 | "status," 37 | "created," 38 | "last_login," 39 | "visits," 40 | "ula_cnt," 41 | "ula_time"; 42 | 43 | if ( !(s_=mysql_stmt_init(dbConn_)) ) 44 | ThrowSQL("mysql_stmt_init"); 45 | if ( !(sc_=mysql_stmt_init(dbConn_)) ) 46 | ThrowSQL("mysql_stmt_init"); 47 | if ( !(sGet_=mysql_stmt_init(dbConn_)) ) 48 | ThrowSQL("mysql_stmt_init"); 49 | if ( !(sUpdate_=mysql_stmt_init(dbConn_)) ) 50 | ThrowSQL("mysql_stmt_init"); 51 | if ( !(sInsert_=mysql_stmt_init(dbConn_)) ) 52 | ThrowSQL("mysql_stmt_init"); 53 | if ( !(sDelete_=mysql_stmt_init(dbConn_)) ) 54 | ThrowSQL("mysql_stmt_init"); 55 | if ( !(sSet_=mysql_stmt_init(dbConn_)) ) 56 | ThrowSQL("mysql_stmt_init"); 57 | 58 | Reset(); 59 | } 60 | 61 | 62 | /* --------------------------------------------------------------------------- 63 | Destructor 64 | --------------------------------------------------------------------------- */ 65 | Cusers::~Cusers() 66 | { 67 | mysql_stmt_close(s_); 68 | mysql_stmt_close(sGet_); 69 | mysql_stmt_close(sUpdate_); 70 | mysql_stmt_close(sInsert_); 71 | mysql_stmt_close(sDelete_); 72 | mysql_stmt_close(sSet_); 73 | 74 | slots_[instance_] = false; 75 | } 76 | 77 | 78 | /* --------------------------------------------------------------------------- 79 | Get the next record 80 | Return false if end of record set 81 | --------------------------------------------------------------------------- */ 82 | bool Cusers::Fetch() 83 | { 84 | int ret; 85 | 86 | ret = mysql_stmt_fetch(s_); 87 | 88 | if ( ret != 0 ) 89 | { 90 | Reset(); 91 | 92 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 93 | return false; 94 | else 95 | { 96 | Cdb::ThrowSQL("Cusers::Fetch | mysql_stmt_fetch"); 97 | return false; 98 | } 99 | } 100 | 101 | genDTStrings(); 102 | 103 | return true; 104 | } 105 | 106 | 107 | /* --------------------------------------------------------------------------- 108 | Get record by PK 109 | Not Found will return false 110 | --------------------------------------------------------------------------- */ 111 | bool Cusers::Get(int arg_id) 112 | { 113 | int ret; 114 | 115 | if ( firstGet_ ) 116 | { 117 | char q[CDB_SQLBUF]; 118 | sprintf(q, "SELECT id,login,login_u,email,email_u,name,phone,passwd1,passwd2,lang,about,group_id,auth_level,status,created,last_login,visits,ula_cnt,ula_time FROM users WHERE id=?"); 119 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 120 | if ( ret != 0 ) 121 | Cdb::ThrowSQL("Cusers::Get | mysql_stmt_prepare"); 122 | firstGet_ = false; 123 | } 124 | 125 | bindKey(sGet_, arg_id); 126 | 127 | if ( mysql_stmt_execute(sGet_) ) 128 | Cdb::ThrowSQL("Cusers::Get | mysql_stmt_execute"); 129 | 130 | bindOutput(sGet_); 131 | 132 | if ( mysql_stmt_store_result(sGet_) ) 133 | Cdb::ThrowSQL("Cusers::Get | mysql_stmt_store_result"); 134 | 135 | ret = mysql_stmt_fetch(sGet_); 136 | 137 | if ( ret != 0 ) 138 | { 139 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 140 | return false; 141 | else 142 | Cdb::ThrowSQL("Cusers::Get | mysql_stmt_fetch"); 143 | } 144 | 145 | genDTStrings(); 146 | 147 | return true; 148 | } 149 | 150 | 151 | /* --------------------------------------------------------------------------- 152 | Insert record 153 | --------------------------------------------------------------------------- */ 154 | unsigned Cusers::Insert() 155 | { 156 | int ret; 157 | 158 | if ( firstInsert_ ) 159 | { 160 | char q[CDB_SQLBUF]; 161 | sprintf(q, "INSERT INTO users (login,login_u,email,email_u,name,phone,passwd1,passwd2,lang,about,group_id,auth_level,status,created,last_login,visits,ula_cnt,ula_time) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); 162 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 163 | if ( ret != 0 ) 164 | Cdb::ThrowSQL("Cusers::Insert | mysql_stmt_prepare"); 165 | firstInsert_ = false; 166 | } 167 | 168 | bindInput(sInsert_); 169 | 170 | ret = mysql_stmt_execute(sInsert_); 171 | 172 | if ( ret != 0 ) 173 | Cdb::ThrowSQL("Cusers::Insert | mysql_stmt_execute"); 174 | 175 | id = mysql_insert_id(dbConn_); 176 | 177 | return id; 178 | } 179 | 180 | 181 | /* --------------------------------------------------------------------------- 182 | Update record by PK 183 | --------------------------------------------------------------------------- */ 184 | void Cusers::Update(int arg_id) 185 | { 186 | int ret; 187 | 188 | if ( firstUpdate_ ) 189 | { 190 | char q[CDB_SQLBUF]; 191 | sprintf(q, "UPDATE users SET login=?,login_u=?,email=?,email_u=?,name=?,phone=?,passwd1=?,passwd2=?,lang=?,about=?,group_id=?,auth_level=?,status=?,created=?,last_login=?,visits=?,ula_cnt=?,ula_time=? WHERE id=?"); 192 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 193 | if ( ret != 0 ) 194 | Cdb::ThrowSQL("Cusers::Update | mysql_stmt_prepare"); 195 | firstUpdate_ = false; 196 | } 197 | 198 | bindInput(sUpdate_, true, arg_id); 199 | 200 | ret = mysql_stmt_execute(sUpdate_); 201 | 202 | if ( ret != 0 ) 203 | Cdb::ThrowSQL("Cusers::Update | mysql_stmt_execute"); 204 | } 205 | 206 | 207 | /* --------------------------------------------------------------------------- 208 | Delete record by PK 209 | --------------------------------------------------------------------------- */ 210 | void Cusers::Delete(int arg_id) 211 | { 212 | int ret; 213 | 214 | if ( firstDelete_ ) 215 | { 216 | char q[CDB_SQLBUF]; 217 | sprintf(q, "DELETE FROM users WHERE id=?"); 218 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 219 | if ( ret != 0 ) 220 | Cdb::ThrowSQL("Cusers::Delete | mysql_stmt_prepare"); 221 | firstDelete_ = false; 222 | } 223 | 224 | bindKey(sDelete_, arg_id); 225 | 226 | ret = mysql_stmt_execute(sDelete_); 227 | 228 | if ( ret != 0 ) 229 | Cdb::ThrowSQL("Cusers::Delete | mysql_stmt_execute"); 230 | } 231 | 232 | 233 | /* --------------------------------------------------------------------------- 234 | Insert or update record by PK 235 | --------------------------------------------------------------------------- */ 236 | void Cusers::Set(int arg_id) 237 | { 238 | int ret; 239 | 240 | if ( firstSet_ ) 241 | { 242 | char q[CDB_SQLBUF]; 243 | sprintf(q, "SELECT id FROM users WHERE id=?"); 244 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 245 | if ( ret != 0 ) 246 | Cdb::ThrowSQL("Cusers::Set | mysql_stmt_prepare"); 247 | firstSet_ = false; 248 | } 249 | 250 | bindKey(sSet_, arg_id); 251 | 252 | if ( mysql_stmt_execute(sSet_) ) 253 | Cdb::ThrowSQL("Cusers::Set | mysql_stmt_execute"); 254 | 255 | bindSetOutput(); 256 | 257 | if ( mysql_stmt_store_result(sSet_) ) 258 | Cdb::ThrowSQL("Cusers::Set | mysql_stmt_store_result"); 259 | 260 | ret = mysql_stmt_fetch(sSet_); 261 | 262 | if ( ret == 0 ) /* record existed */ 263 | { 264 | Update(arg_id); 265 | } 266 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 267 | { 268 | id = arg_id; 269 | 270 | Insert(); 271 | } 272 | else 273 | Cdb::ThrowSQL("Cusers::Set | mysql_stmt_fetch"); 274 | } 275 | 276 | 277 | /* --------------------------------------------------------------------------- 278 | Bind key values 279 | --------------------------------------------------------------------------- */ 280 | void Cusers::bindKey(MYSQL_STMT *s, int arg_id) 281 | { 282 | k_id_ = arg_id; 283 | 284 | memset(&bndk_, 0, sizeof(bndk_)); 285 | 286 | bndk_[0].buffer_type = MYSQL_TYPE_LONG; 287 | bndk_[0].buffer = (char*)&k_id_; 288 | 289 | if ( mysql_stmt_bind_param(s, bndk_) ) 290 | Cdb::ThrowSQL("Cusers::bindKey | mysql_stmt_bind_param"); 291 | } 292 | 293 | 294 | /* --------------------------------------------------------------------------- 295 | Bind input values 296 | --------------------------------------------------------------------------- */ 297 | void Cusers::bindInput(MYSQL_STMT *s, bool withKey, int arg_id) 298 | { 299 | login_len_ = strlen(login); 300 | login_u_len_ = strlen(login_u); 301 | email_len_ = strlen(email); 302 | email_u_len_ = strlen(email_u); 303 | name_len_ = strlen(name); 304 | phone_len_ = strlen(phone); 305 | passwd1_len_ = strlen(passwd1); 306 | passwd2_len_ = strlen(passwd2); 307 | lang_len_ = strlen(lang); 308 | about_len_ = strlen(about); 309 | 310 | set_datetime(&t_created_, created); 311 | set_datetime(&t_last_login_, last_login); 312 | set_datetime(&t_ula_time_, ula_time); 313 | 314 | memset(&bndi_, 0, sizeof(bndi_)); 315 | 316 | bndi_[0].buffer_type = MYSQL_TYPE_STRING; 317 | bndi_[0].buffer = (char*)login; 318 | bndi_[0].length = &login_len_; 319 | 320 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 321 | bndi_[1].buffer = (char*)login_u; 322 | bndi_[1].length = &login_u_len_; 323 | 324 | bndi_[2].buffer_type = MYSQL_TYPE_STRING; 325 | bndi_[2].buffer = (char*)email; 326 | bndi_[2].length = &email_len_; 327 | 328 | bndi_[3].buffer_type = MYSQL_TYPE_STRING; 329 | bndi_[3].buffer = (char*)email_u; 330 | bndi_[3].length = &email_u_len_; 331 | 332 | bndi_[4].buffer_type = MYSQL_TYPE_STRING; 333 | bndi_[4].buffer = (char*)name; 334 | bndi_[4].length = &name_len_; 335 | 336 | bndi_[5].buffer_type = MYSQL_TYPE_STRING; 337 | bndi_[5].buffer = (char*)phone; 338 | bndi_[5].length = &phone_len_; 339 | 340 | bndi_[6].buffer_type = MYSQL_TYPE_STRING; 341 | bndi_[6].buffer = (char*)passwd1; 342 | bndi_[6].length = &passwd1_len_; 343 | 344 | bndi_[7].buffer_type = MYSQL_TYPE_STRING; 345 | bndi_[7].buffer = (char*)passwd2; 346 | bndi_[7].length = &passwd2_len_; 347 | 348 | bndi_[8].buffer_type = MYSQL_TYPE_STRING; 349 | bndi_[8].buffer = (char*)lang; 350 | bndi_[8].length = &lang_len_; 351 | 352 | bndi_[9].buffer_type = MYSQL_TYPE_STRING; 353 | bndi_[9].buffer = (char*)about; 354 | bndi_[9].length = &about_len_; 355 | 356 | bndi_[10].buffer_type = MYSQL_TYPE_LONG; 357 | bndi_[10].buffer = (char*)&group_id; 358 | 359 | bndi_[11].buffer_type = MYSQL_TYPE_TINY; 360 | bndi_[11].buffer = (char*)&auth_level; 361 | 362 | bndi_[12].buffer_type = MYSQL_TYPE_TINY; 363 | bndi_[12].buffer = (char*)&status; 364 | 365 | bndi_[13].buffer_type = MYSQL_TYPE_DATETIME; 366 | bndi_[13].buffer = (char*)&t_created_; 367 | 368 | bndi_[14].buffer_type = MYSQL_TYPE_DATETIME; 369 | bndi_[14].buffer = (char*)&t_last_login_; 370 | 371 | bndi_[15].buffer_type = MYSQL_TYPE_LONG; 372 | bndi_[15].buffer = (char*)&visits; 373 | 374 | bndi_[16].buffer_type = MYSQL_TYPE_LONG; 375 | bndi_[16].buffer = (char*)&ula_cnt; 376 | 377 | bndi_[17].buffer_type = MYSQL_TYPE_DATETIME; 378 | bndi_[17].buffer = (char*)&t_ula_time_; 379 | 380 | if ( withKey ) /* after WHERE */ 381 | { 382 | k_id_ = arg_id; 383 | 384 | bndi_[18].buffer_type = MYSQL_TYPE_LONG; 385 | bndi_[18].buffer = (char*)&k_id_; 386 | 387 | } 388 | 389 | if ( mysql_stmt_bind_param(s, bndi_) ) 390 | Cdb::ThrowSQL("Cusers::bindInput | mysql_stmt_bind_param"); 391 | } 392 | 393 | 394 | /* --------------------------------------------------------------------------- 395 | Bind output values 396 | --------------------------------------------------------------------------- */ 397 | void Cusers::bindOutput(MYSQL_STMT *s) 398 | { 399 | memset(&bndo_, 0, sizeof(bndo_)); 400 | 401 | bndo_[0].buffer_type = MYSQL_TYPE_LONG; 402 | bndo_[0].buffer = (char*)&id; 403 | bndo_[0].is_null = &id_is_null_; 404 | 405 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 406 | bndo_[1].buffer = (char*)login; 407 | bndo_[1].buffer_length = 31; 408 | bndo_[1].is_null = &login_is_null_; 409 | 410 | bndo_[2].buffer_type = MYSQL_TYPE_STRING; 411 | bndo_[2].buffer = (char*)login_u; 412 | bndo_[2].buffer_length = 31; 413 | bndo_[2].is_null = &login_u_is_null_; 414 | 415 | bndo_[3].buffer_type = MYSQL_TYPE_STRING; 416 | bndo_[3].buffer = (char*)email; 417 | bndo_[3].buffer_length = 121; 418 | bndo_[3].is_null = &email_is_null_; 419 | 420 | bndo_[4].buffer_type = MYSQL_TYPE_STRING; 421 | bndo_[4].buffer = (char*)email_u; 422 | bndo_[4].buffer_length = 121; 423 | bndo_[4].is_null = &email_u_is_null_; 424 | 425 | bndo_[5].buffer_type = MYSQL_TYPE_STRING; 426 | bndo_[5].buffer = (char*)name; 427 | bndo_[5].buffer_length = 121; 428 | bndo_[5].is_null = &name_is_null_; 429 | 430 | bndo_[6].buffer_type = MYSQL_TYPE_STRING; 431 | bndo_[6].buffer = (char*)phone; 432 | bndo_[6].buffer_length = 31; 433 | bndo_[6].is_null = &phone_is_null_; 434 | 435 | bndo_[7].buffer_type = MYSQL_TYPE_STRING; 436 | bndo_[7].buffer = (char*)passwd1; 437 | bndo_[7].buffer_length = 45; 438 | bndo_[7].is_null = &passwd1_is_null_; 439 | 440 | bndo_[8].buffer_type = MYSQL_TYPE_STRING; 441 | bndo_[8].buffer = (char*)passwd2; 442 | bndo_[8].buffer_length = 45; 443 | bndo_[8].is_null = &passwd2_is_null_; 444 | 445 | bndo_[9].buffer_type = MYSQL_TYPE_STRING; 446 | bndo_[9].buffer = (char*)lang; 447 | bndo_[9].buffer_length = 6; 448 | bndo_[9].is_null = &lang_is_null_; 449 | 450 | bndo_[10].buffer_type = MYSQL_TYPE_STRING; 451 | bndo_[10].buffer = (char*)about; 452 | bndo_[10].buffer_length = 251; 453 | bndo_[10].is_null = &about_is_null_; 454 | 455 | bndo_[11].buffer_type = MYSQL_TYPE_LONG; 456 | bndo_[11].buffer = (char*)&group_id; 457 | bndo_[11].is_null = &group_id_is_null_; 458 | 459 | bndo_[12].buffer_type = MYSQL_TYPE_TINY; 460 | bndo_[12].buffer = (char*)&auth_level; 461 | bndo_[12].is_null = &auth_level_is_null_; 462 | 463 | bndo_[13].buffer_type = MYSQL_TYPE_TINY; 464 | bndo_[13].buffer = (char*)&status; 465 | bndo_[13].is_null = &status_is_null_; 466 | 467 | bndo_[14].buffer_type = MYSQL_TYPE_DATETIME; 468 | bndo_[14].buffer = (char*)&t_created_; 469 | bndo_[14].is_null = &created_is_null_; 470 | 471 | bndo_[15].buffer_type = MYSQL_TYPE_DATETIME; 472 | bndo_[15].buffer = (char*)&t_last_login_; 473 | bndo_[15].is_null = &last_login_is_null_; 474 | 475 | bndo_[16].buffer_type = MYSQL_TYPE_LONG; 476 | bndo_[16].buffer = (char*)&visits; 477 | bndo_[16].is_null = &visits_is_null_; 478 | 479 | bndo_[17].buffer_type = MYSQL_TYPE_LONG; 480 | bndo_[17].buffer = (char*)&ula_cnt; 481 | bndo_[17].is_null = &ula_cnt_is_null_; 482 | 483 | bndo_[18].buffer_type = MYSQL_TYPE_DATETIME; 484 | bndo_[18].buffer = (char*)&t_ula_time_; 485 | bndo_[18].is_null = &ula_time_is_null_; 486 | 487 | if ( mysql_stmt_bind_result(s, bndo_) ) 488 | Cdb::ThrowSQL("Cusers::bindOutput | mysql_stmt_bind_result"); 489 | } 490 | 491 | 492 | /* --------------------------------------------------------------------------- 493 | Bind output value for Set 494 | --------------------------------------------------------------------------- */ 495 | void Cusers::bindSetOutput() 496 | { 497 | static int id; /* to be scrapped anyway */ 498 | 499 | memset(&bndso_, 0, sizeof(bndso_)); 500 | 501 | bndso_[0].buffer_type = MYSQL_TYPE_LONG; 502 | bndso_[0].buffer = (char*)&id; 503 | 504 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 505 | Cdb::ThrowSQL("Cusers::bindSetOutput | mysql_stmt_bind_result"); 506 | } 507 | 508 | 509 | /* --------------------------------------------------------------------------- 510 | Generate date-time strings 511 | --------------------------------------------------------------------------- */ 512 | void Cusers::genDTStrings() 513 | { 514 | if ( created_is_null_ ) 515 | created[0] = EOS; 516 | else 517 | sprintf(created, "%04d-%02d-%02d %02d:%02d:%02d", t_created_.year, t_created_.month, t_created_.day, t_created_.hour, t_created_.minute, t_created_.second); 518 | 519 | if ( last_login_is_null_ ) 520 | last_login[0] = EOS; 521 | else 522 | sprintf(last_login, "%04d-%02d-%02d %02d:%02d:%02d", t_last_login_.year, t_last_login_.month, t_last_login_.day, t_last_login_.hour, t_last_login_.minute, t_last_login_.second); 523 | 524 | if ( ula_time_is_null_ ) 525 | ula_time[0] = EOS; 526 | else 527 | sprintf(ula_time, "%04d-%02d-%02d %02d:%02d:%02d", t_ula_time_.year, t_ula_time_.month, t_ula_time_.day, t_ula_time_.hour, t_ula_time_.minute, t_ula_time_.second); 528 | 529 | } 530 | 531 | 532 | /* --------------------------------------------------------------------------- 533 | Reset (zero) public variables 534 | --------------------------------------------------------------------------- */ 535 | void Cusers::Reset() 536 | { 537 | id = 0; 538 | login[0] = EOS; 539 | login_u[0] = EOS; 540 | email[0] = EOS; 541 | email_u[0] = EOS; 542 | name[0] = EOS; 543 | phone[0] = EOS; 544 | passwd1[0] = EOS; 545 | passwd2[0] = EOS; 546 | lang[0] = EOS; 547 | about[0] = EOS; 548 | group_id = 0; 549 | auth_level = 0; 550 | status = 0; 551 | created[0] = EOS; 552 | last_login[0] = EOS; 553 | visits = 0; 554 | ula_cnt = 0; 555 | ula_time[0] = EOS; 556 | } 557 | -------------------------------------------------------------------------------- /lib/npp_update.c: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020-2022 Jurek Muszynski (rekmus) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | ----------------------------------------------------------------------------- 26 | 27 | Node++ Web App Engine 28 | Update Node++ lib 29 | nodepp.org 30 | 31 | -------------------------------------------------------------------------- */ 32 | 33 | 34 | #include "npp.h" 35 | #include 36 | 37 | 38 | static bool M_force_update=FALSE; 39 | static bool M_test=FALSE; 40 | static bool M_update=FALSE; 41 | 42 | static int M_local_major=0; 43 | static int M_local_minor=0; 44 | static int M_local_patch=0; 45 | 46 | static int M_latest_major=0; 47 | static int M_latest_minor=0; 48 | static int M_latest_patch=0; 49 | 50 | static JSON M_j={0}; 51 | 52 | 53 | /* -------------------------------------------------------------------------- 54 | Parse command line 55 | -------------------------------------------------------------------------- */ 56 | static int parse_command_line(int argc, char *argv[]) 57 | { 58 | int c; 59 | 60 | while ( (c=getopt(argc, argv, "ftu")) != -1 ) 61 | switch (c) 62 | { 63 | case 'f': 64 | M_force_update = TRUE; 65 | break; 66 | case 't': 67 | // M_test = TRUE; 68 | break; 69 | case 'u': 70 | M_update = TRUE; 71 | break; 72 | case '?': 73 | if ( optopt == 'c' ) 74 | fprintf(stderr, "Option -%c requires an argument.\n", optopt); 75 | else if ( isprint(optopt) ) 76 | fprintf(stderr, "Unknown option `-%c'.\n", optopt); 77 | else 78 | fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); 79 | return FAIL; 80 | default: 81 | return FAIL; 82 | } 83 | 84 | return OK; 85 | } 86 | 87 | 88 | /* -------------------------------------------------------------------------- 89 | Parse version string 90 | -------------------------------------------------------------------------- */ 91 | static int parse_verstr(const char *str, int *major, int *minor, int *patch) 92 | { 93 | sscanf(str, "%d.%d.%d", major, minor, patch); 94 | DDBG("%d %d %d", *major, *minor, *patch); 95 | return OK; 96 | } 97 | 98 | 99 | /* -------------------------------------------------------------------------- 100 | Check local Node++ version 101 | -------------------------------------------------------------------------- */ 102 | static int check_local_version() 103 | { 104 | int ret=OK; 105 | 106 | DDBG("Opening npp.h..."); 107 | 108 | char npp_h[512]; 109 | 110 | #ifdef _WIN32 111 | sprintf(npp_h, "%s\\lib\\npp.h", G_appdir); 112 | HANDLE fd; 113 | #else /* Linux */ 114 | sprintf(npp_h, "%s/lib/npp.h", G_appdir); 115 | FILE *fd; 116 | #endif 117 | int fsize; 118 | 119 | #ifdef _WIN32 120 | 121 | fd = CreateFile(TEXT(npp_h), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 122 | 123 | if ( fd == INVALID_HANDLE_VALUE ) 124 | { 125 | ERR("Couldn't open npp.h"); 126 | return FAIL; 127 | } 128 | 129 | /* 64-bit integers complicated by Microsoft... */ 130 | 131 | LARGE_INTEGER li_fsize; 132 | 133 | if ( !GetFileSizeEx(fd, &li_fsize) ) 134 | { 135 | ERR("Couldn't read npp.h's size"); 136 | CloseHandle(fd); 137 | return FAIL; 138 | } 139 | 140 | fsize = li_fsize.QuadPart; 141 | 142 | #else /* Linux */ 143 | 144 | if ( NULL == (fd=fopen(npp_h, "r")) ) 145 | { 146 | ERR("Couldn't open npp.h"); 147 | return FAIL; 148 | } 149 | 150 | fseek(fd, 0, SEEK_END); /* determine the file size */ 151 | 152 | fsize = ftell(fd); 153 | 154 | rewind(fd); 155 | 156 | #endif 157 | 158 | /* read file into the buffer */ 159 | 160 | char *data; 161 | 162 | if ( !(data=(char*)malloc(fsize+1)) ) 163 | { 164 | ERR("Couldn't allocate %lld bytes for buffer", fsize+1); 165 | #ifdef _WIN32 166 | CloseHandle(fd); 167 | #else /* Linux */ 168 | fclose(fd); 169 | #endif 170 | return FAIL; 171 | } 172 | 173 | #ifdef _WIN32 174 | DWORD bytes; 175 | if ( !ReadFile(fd, data, fsize, &bytes, NULL) ) 176 | #else /* Linux */ 177 | if ( fread(data, fsize, 1, fd) != 1 ) 178 | #endif 179 | { 180 | ERR("Couldn't read from npp.h"); 181 | free(data); 182 | #ifdef _WIN32 183 | CloseHandle(fd); 184 | #else /* Linux */ 185 | fclose(fd); 186 | #endif 187 | return FAIL; 188 | } 189 | 190 | #ifdef _WIN32 191 | CloseHandle(fd); 192 | #else /* Linux */ 193 | fclose(fd); 194 | #endif 195 | 196 | /* ---------------------------------------------- */ 197 | 198 | data[fsize] = EOS; 199 | 200 | /* ---------------------------------------------- */ 201 | 202 | char *p_verstr = strstr(data, "NPP_VERSION"); 203 | 204 | if ( !p_verstr ) 205 | { 206 | ERR("Couldn't find NPP_VERSION in npp.h"); 207 | free(data); 208 | return FAIL; 209 | } 210 | 211 | p_verstr += 12; 212 | 213 | int count = p_verstr - data; 214 | char *c=p_verstr; 215 | 216 | while ( *c != '"' && count < fsize ) 217 | { 218 | ++c; 219 | ++count; 220 | } 221 | 222 | ++c; /* skip '"' */ 223 | 224 | char verstr[32]; 225 | int i=0; 226 | 227 | while ( *c != '"' && i < 31 && count < fsize ) 228 | { 229 | verstr[i++] = *c++; 230 | ++count; 231 | } 232 | 233 | verstr[i] = EOS; 234 | 235 | DDBG("verstr [%s]", verstr); 236 | 237 | /* ---------------------------------------------- */ 238 | 239 | free(data); 240 | 241 | /* ---------------------------------------------- */ 242 | 243 | ret = parse_verstr(verstr, &M_local_major, &M_local_minor, &M_local_patch); 244 | 245 | /* ---------------------------------------------- */ 246 | 247 | return ret; 248 | } 249 | 250 | 251 | /* -------------------------------------------------------------------------- 252 | Check latest Node++ version 253 | -------------------------------------------------------------------------- */ 254 | static int check_latest_version() 255 | { 256 | int ret=OK; 257 | char url[1024]; 258 | char data[NPP_JSON_BUFSIZE]; 259 | 260 | #ifdef NPP_HTTPS 261 | sprintf(url, "https://nodepp.org/api/v2/update_info"); 262 | #else 263 | sprintf(url, "http://nodepp.org/api/v2/update_info"); 264 | #endif 265 | 266 | if ( !CALL_HTTP(NULL, &data, "GET", url, FALSE) ) 267 | { 268 | ERR("Couldn't connect to nodepp.org"); 269 | return FAIL; 270 | } 271 | else if ( CALL_HTTP_STATUS != 200 ) 272 | { 273 | ERR("Couldn't get update_info from nodepp.org, status = %d", CALL_HTTP_STATUS); 274 | return FAIL; 275 | } 276 | 277 | data[CALL_HTTP_RESPONSE_LEN] = EOS; 278 | 279 | DDBG("data [%s]", data); 280 | 281 | if ( !JSON_FROM_STRING(&M_j, data) ) 282 | { 283 | ERR("Couldn't parse response as JSON"); 284 | return FAIL; 285 | } 286 | 287 | DBG("parsed pretty: [%s]", JSON_TO_STRING_PRETTY(&M_j)); 288 | 289 | char verstr[32]; 290 | 291 | #ifdef NPP_JSON_V1 292 | COPY(verstr, JSON_GET_STR(&M_j, "version"), 31); 293 | #else 294 | if ( !JSON_GET_STR(&M_j, "version", verstr, 31) ) 295 | { 296 | ERR("Couldn't find version in response"); 297 | return FAIL; 298 | } 299 | #endif 300 | ret = parse_verstr(verstr, &M_latest_major, &M_latest_minor, &M_latest_patch); 301 | 302 | return ret; 303 | } 304 | 305 | 306 | /* -------------------------------------------------------------------------- 307 | Update 308 | -------------------------------------------------------------------------- */ 309 | static int update_lib() 310 | { 311 | ALWAYS("Updating Node++ lib..."); 312 | 313 | JSON j_files={0}; 314 | 315 | if ( !JSON_GET_ARRAY(&M_j, "files", &j_files) ) 316 | { 317 | ERR("Couldn't get file list from the response"); 318 | return FAIL; 319 | } 320 | 321 | int cnt=JSON_COUNT(&j_files); 322 | 323 | INF("%d files to update", cnt); 324 | 325 | int i; 326 | char path[NPP_JSON_STR_LEN+1]; 327 | char fname[128]; 328 | char url[512]; 329 | static char data[CALL_HTTP_MAX_RESPONSE_LEN]; 330 | FILE *fd; 331 | 332 | for ( i=0; i M_local_major 571 | || (M_latest_major == M_local_major && M_latest_minor > M_local_minor) 572 | || (M_latest_major == M_local_major && M_latest_minor == M_local_minor && M_latest_patch > M_local_patch)) ) 573 | { 574 | if ( M_update ) 575 | { 576 | if ( M_latest_major > M_local_major && !M_force_update ) /* confirmation required */ 577 | { 578 | printf("Major version has changed. It may be incompatible with your app code. Are you sure you want to proceed [y/N]? "); 579 | 580 | int answer = getchar(); 581 | 582 | if ( answer != '\n' ) 583 | { 584 | int c; 585 | while ( (c=getchar()) != '\n') continue; 586 | DDBG("c = '%c'", c); 587 | } 588 | 589 | DDBG("answer = '%c'", answer); 590 | 591 | if ( answer == 'y' || answer == 'Y' ) 592 | ret = update_lib(); 593 | 594 | ALWAYS("To remove prompt add -f option to force update"); 595 | } 596 | else 597 | ret = update_lib(); 598 | } 599 | else /* info only */ 600 | { 601 | ALWAYS("Add -u option to update"); 602 | } 603 | } 604 | else /* same version */ 605 | { 606 | ALWAYS(""); 607 | ALWAYS("Nothing to update."); 608 | } 609 | } 610 | 611 | ALWAYS(""); 612 | ALWAYS("More info: nodepp.org"); 613 | #ifndef _WIN32 614 | ALWAYS(""); 615 | #endif 616 | 617 | npp_lib_done(); 618 | 619 | if ( ret != OK ) 620 | return EXIT_FAILURE; 621 | 622 | return EXIT_SUCCESS; 623 | } 624 | --------------------------------------------------------------------------------