├── LICENSE ├── README.md ├── bin ├── npp.conf ├── nppmake ├── nppmake.bat ├── nppstart ├── nppstop └── passwords.txt ├── lib ├── Cusers.cpp ├── Cusers.h ├── Cusers_activations.cpp ├── Cusers_activations.h ├── Cusers_avatars.cpp ├── Cusers_avatars.h ├── Cusers_groups.cpp ├── Cusers_groups.h ├── Cusers_logins.cpp ├── Cusers_logins.h ├── Cusers_messages.cpp ├── Cusers_messages.h ├── Cusers_p_resets.cpp ├── Cusers_p_resets.h ├── Cusers_settings.cpp ├── Cusers_settings.h ├── npp.h ├── npp_eng_app.c ├── npp_eng_svc.c ├── npp_lib.c ├── npp_lib.h ├── npp_mysql.cpp ├── npp_mysql.h ├── npp_update.c ├── npp_usr.cpp ├── npp_usr.h ├── npp_watcher.c └── users.sql ├── logs └── .logs_here ├── res ├── favicon.ico ├── nodepp.jpg └── wait.gif ├── resmin ├── npp.css └── npp.js ├── snippets ├── sample_snippet.html └── sample_snippet.md └── src ├── m ├── m.bat ├── npp_app.cpp ├── npp_app.h ├── npp_svc.cpp ├── t └── t.bat /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jurek Muszyński 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node++ 2 | 3 | Node++ is an asynchronous HTTP(S) engine and backend framework for low-latency C/C++ web applications and RESTful APIs. 4 | 5 | It's more than [twice as fast as Spring Boot](https://nodepp.org/docs/performance) and [five times faster than Node.js](https://nodepp.org/docs/performance). 6 | 7 | C++ backend can render pages in **microseconds**, even with a database, when used with our efficient [DAO/ORM class](https://nodepp.org/generators/mysqldao) (see [live demo](https://nodepp.org/products)). 8 | 9 | It can act as: 10 | 11 | * a static web server; 12 | * a standalone, self-contained, single-process web application; 13 | * a standalone, multi-process web application, connected and load-balanced via standard POSIX queues; 14 | * an HTTP servlet/microservice that makes up a building block of the more complex, distributed architecture. 15 | 16 | Node++ library (paired with OpenSSL and optionally MySQL) contains everything that is necessary to build a complete, production-grade solution, including **session management**, **users accounts**, **REST calls** and **multi-language support**. 17 | 18 | There is a [RESTful API generator](https://nodepp.org/generators) to generate almost the whole backend code in a few clicks, requiring only an SQL table definition. 19 | 20 | 21 | ## Framework 22 | 23 | The *backend framework* means that there are **7 server-side events** you can react to: 24 | 25 | Event|Function called 26 | -----|---- 27 | application start|`npp_app_init()` 28 | **HTTP request**|**`npp_app_main()`** 29 | session start|`npp_app_session_init()` 30 | session authentication (login)|`npp_app_user_login()` 31 | session logout|`npp_app_user_logout()` 32 | session stop|`npp_app_session_done()` 33 | application stop|`npp_app_done()` 34 | 35 | [npp_app.cpp](https://github.com/rekmus/nodepp/blob/master/src/npp_app.cpp) has to contain these definitions (even if empty). 36 | 37 | As Node++ is single-threaded, the application code does not need to be thread-safe. Horizontal scaling is done through [adding processes](https://github.com/rekmus/nodepp/wiki/Node++-ASYNC), not threads. 38 | 39 | The whole user session and sessid cookie management is handled by the engine. 40 | 41 | By default sessions are not started. To change this [add one line to npp_app.h](https://github.com/rekmus/nodepp/wiki/Sessions-in-Node++). 42 | 43 | 44 | ## Performance 45 | 46 | Node++'s efficiency makes single CPU, 1 GB AWS EC2 t2.micro free instance sufficient to host a fully-fledged web application with a database for thousands of users. 47 | 48 | On a typical server it handles [50,000 requests per second](https://nodepp.org/docs/performance). 49 | 50 | Low latency gets Node++ applications "Faster than 100% of tested sites" badge from [Pingdom](https://tools.pingdom.com) or – as they now don't publish the percentage – it shows the **complete page load in 67 ms**: 51 | 52 |
53 | 54 |
55 | 56 | [Why is Node++ faster than other engines?](https://nodepp.org/docs/design) 57 | 58 | 59 | ## Security 60 | 61 | Node++ has built-in (and enabled by default) protection against most popular attacks, including BEAST, SQL-injection, XSS, and password and cookie brute-force. It does not directly expose the filesystem nor allows any scripting. Its random string generator is FIPS-compliant. CSRF protection is as easy as adding [3 lines to the code](https://github.com/rekmus/nodepp/wiki/CSRFT_OK). 62 | 63 | Default SSL settings give **A+ result**: 64 | 65 |
66 | 67 |
68 | 69 | 70 | ## Programming 71 | 72 | ### Basic convention 73 | 74 |
75 | 76 |
77 | 78 | If `resource` is a file present in `res` or `resmin` (i.e. an image or css), it will be served and `npp_app_main()` will not be called. 79 | 80 | 81 | ### Simplest Hello World 82 | 83 | Return static file if present, otherwise "Hello World!". 84 | 85 | ```source.c++ 86 | void npp_app_main() 87 | { 88 | OUT("Hello World!"); 89 | } 90 | ``` 91 | 92 | ### Simple HTML with 2 pages 93 | 94 | Application, yet without moving parts. 95 | 96 | ```source.c++ 97 | void npp_app_main() 98 | { 99 | if ( REQ("") ) // landing page 100 | { 101 | OUT_HTML_HEADER; 102 | OUT("

%s

", NPP_APP_NAME); 103 | OUT("

Welcome to my web app!

"); 104 | OUT("

About

"); 105 | OUT_HTML_FOOTER; 106 | } 107 | else if ( REQ("about") ) 108 | { 109 | OUT_HTML_HEADER; 110 | OUT("

%s

", NPP_APP_NAME); 111 | OUT("

About

"); 112 | OUT("

Hello World Sample Node++ Web Application

"); 113 | OUT("

Back to landing page

"); 114 | OUT_HTML_FOOTER; 115 | } 116 | else // page not found 117 | { 118 | RES_STATUS(404); 119 | } 120 | } 121 | ``` 122 | 123 | ### Using query string value 124 | 125 | This is a simple 2-pages application demonstrating [QS()](https://github.com/rekmus/nodepp/wiki/QS) macro usage to get a value provided by client in the query string. 126 | 127 | `QS` works with all popular HTTP methods and payload types. 128 | 129 | ```source.c++ 130 | void npp_app_main() 131 | { 132 | if ( REQ("") ) // landing page 133 | { 134 | OUT_HTML_HEADER; // generic HTML header with opening body tag 135 | 136 | OUT("

%s

", NPP_APP_NAME); 137 | 138 | OUT("

Welcome to my web app!

"); 139 | 140 | /* show client type */ 141 | 142 | if ( REQ_DSK ) 143 | OUT("

You're on desktop, right?

"); 144 | else if ( REQ_TAB ) 145 | OUT("

You're on tablet, right?

"); 146 | else /* REQ_MOB */ 147 | OUT("

You're on the phone, right?

"); 148 | 149 | /* link to welcome */ 150 | 151 | OUT("

Click here to try my welcoming bot.

"); 152 | 153 | OUT_HTML_FOOTER; // body and html closing tags 154 | } 155 | else if ( REQ("welcome") ) // welcoming bot 156 | { 157 | OUT_HTML_HEADER; 158 | OUT("

%s

", NPP_APP_NAME); 159 | 160 | /* display form */ 161 | 162 | OUT("

Please enter your name:

"); 163 | OUT("
"); 164 | 165 | /* try to get the query string value */ 166 | 167 | QSVAL qs_name; // query string value 168 | 169 | if ( QS("name", qs_name) ) // if present, bid welcome 170 | OUT("

Welcome %s, my dear friend!

", qs_name); 171 | 172 | OUT("

Back to landing page

"); 173 | 174 | OUT_HTML_FOOTER; 175 | } 176 | else // page not found 177 | { 178 | RES_STATUS(404); 179 | } 180 | } 181 | ``` 182 | 183 | Complete 4-page application example is included in the package (see [npp_app.cpp](https://github.com/rekmus/nodepp/blob/master/src/npp_app.cpp)). 184 | 185 | More examples are available here: [Node++ examples](https://nodepp.org/docs/examples). 186 | 187 | 188 | ## Configuration 189 | 190 | Configuration file ([bin/npp.conf](https://github.com/rekmus/nodepp/blob/master/bin/npp.conf)) contains a handful of settings, starting with logLevel, httpPort, httpsPort, SSL certificate paths, database credentials and so on. 191 | 192 | You can also add your own and read them in `npp_app_init()` with [npp_read_param_str()](https://github.com/rekmus/nodepp/wiki/npp_read_param_str) or [npp_read_param_int()](https://github.com/rekmus/nodepp/wiki/npp_read_param_int). 193 | 194 | 195 | ## Documentation 196 | 197 | ### [Step-by-step tutorial how to set up complete system on AWS EC2 Linux instance](https://nodepp.org/docs/tutorials) 198 | 199 | ### [Getting Started on Linux](https://github.com/rekmus/nodepp/wiki/Node++-Hello-World-%E2%80%93-Getting-Started-on-Linux) 200 | 201 | ### [Getting Started on Windows](https://github.com/rekmus/nodepp/wiki/Node++-Hello-World-%E2%80%93-Getting-Started-on-Windows) 202 | 203 | ### [Switches and constants](https://github.com/rekmus/nodepp/wiki/Node++-switches-and-constants) 204 | 205 | ### [Functions and macros](https://github.com/rekmus/nodepp/wiki/Node++-functions-and-macros) 206 | 207 | ### [Configuration parameters](https://github.com/rekmus/nodepp/wiki/Node++-configuration-parameters) 208 | 209 | ### [How to enable HTTPS](https://github.com/rekmus/nodepp/wiki/How-to-enable-HTTPS-in-Node++) 210 | 211 | ### [Sessions in Node++](https://github.com/rekmus/nodepp/wiki/Sessions-in-Node++) 212 | 213 | ### [ASYNC (multi-process mode)](https://github.com/rekmus/nodepp/wiki/Node++-ASYNC) 214 | 215 | ### [Memory models](https://github.com/rekmus/nodepp/wiki/Node++-memory-models) 216 | 217 | ### [Multi-language support](https://github.com/rekmus/nodepp/wiki/Node++-multi-language-support) 218 | 219 | ### [USERS Module](https://github.com/rekmus/nodepp/wiki/USERS-Module) 220 | 221 | ### [Error codes](https://github.com/rekmus/nodepp/wiki/Node++-error-codes) 222 | 223 | ### [RESTful calls from Node++](https://github.com/rekmus/nodepp/wiki/RESTful-calls-from-Node++) 224 | 225 | ### [What is npp_watcher](https://github.com/rekmus/nodepp/wiki/What-is-npp_watcher) 226 | 227 | 228 | 229 | 230 | ## Directory structure 231 | 232 | Although not necessary, it's good to have **$NPP_DIR** set in the environment, pointing to the project directory. Node++ engine always first looks in `$NPP_DIR/` for the particular file, with `` being one of the below: 233 | 234 | ### `src` 235 | 236 | *(Required only for development)* 237 | 238 | * Application sources. It has to contain at least `npp_app.h` and `npp_app.cpp` with `npp_app_main()` inside. 239 | * Customizable compilation script: `m` 240 | 241 | ### `lib` 242 | 243 | *(Required only for development)* 244 | 245 | * Node++ engine & library source 246 | * `users.sql` 247 | 248 | ### `bin` 249 | 250 | * Main compilation script: `nppmake` 251 | * Executables, i.e. `npp_app`, `npp_svc`, `npp_watcher`, `npp_update` 252 | * Runtime scripts, i.e. `nppstart`, `nppstop` 253 | * Configuration: `npp.conf` 254 | * Strings in additional languages: `strings.LL-CC` 255 | * Blacklist, i.e. `blacklist.txt` 256 | * Whitelist, i.e. `whitelist.txt` 257 | * 10,000 most common passwords: `passwords.txt` 258 | 259 | ### `res` 260 | 261 | Static resources. The whole tree under `res` is publicly available. All the files are read on startup and served straight from the memory. File list is updated once a minute. 262 | 263 | * images 264 | * static HTML files 265 | * text files 266 | * fonts 267 | * ... 268 | 269 | ### `resmin` 270 | 271 | Static resources to be minified. The whole tree under `resmin` is publicly available. All the files are read on startup, minified and served straight from the memory. File list is updated once a minute. 272 | 273 | * CSS 274 | * JS 275 | 276 | ### `snippets` 277 | 278 | Static parts of rendered content, i.e. HTML or markdown snippets. 279 | 280 | ### `logs` 281 | 282 | * Log files 283 | -------------------------------------------------------------------------------- /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=3 # 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=/etc/letsencrypt/live/example.com/fullchain.pem 32 | keyFile=/etc/letsencrypt/live/example.com/privkey.pem 33 | certChainFile=/etc/letsencrypt/live/example.com/fullchain.pem 34 | 35 | 36 | # ---------------------------------------------------------------------------- 37 | # Database connection details 38 | 39 | dbName=nodepp 40 | dbUser=nodepp 41 | dbPassword=nodepp 42 | 43 | 44 | # ---------------------------------------------------------------------------- 45 | # Number of ASYNC (npp_svc) processes 46 | 47 | ASYNCSvcProcesses=0 48 | 49 | 50 | # ---------------------------------------------------------------------------- 51 | # Setting this to 1 will add _t to the log file name and will cause 52 | # engine to ignore security redirections (NPP_DOMAIN_ONLY and HSTS) 53 | # to allow testing from localhost and without SSL. 54 | # For details search for "redirections table" in npp_eng_app.c. 55 | 56 | test=1 57 | -------------------------------------------------------------------------------- /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_UNAME=`uname -s` 70 | 71 | if [ "$NPP_UNAME" = "Darwin" ] 72 | then 73 | NPP_OS="mac" 74 | else 75 | NPP_OS=`grep ID_LIKE /etc/os-release | head -1 | cut -d '=' -f 2` 76 | fi 77 | 78 | if [ $NPP_VERBOSE -eq 1 ] 79 | then 80 | echo "NPP_OS=${NPP_OS}" 81 | fi 82 | 83 | 84 | # ---------------------------------------------------------------------------- 85 | # Determine Node++ modules that are enabled in npp_app.h 86 | 87 | NPP_HTTPS=$(get_presence "NPP_HTTPS") 88 | 89 | NPP_MYSQL=$(get_presence "NPP_MYSQL") 90 | 91 | NPP_USERS=$(get_presence "NPP_USERS") 92 | 93 | NPP_ASYNC=$(get_presence "NPP_ASYNC") 94 | 95 | 96 | # ---------------------------------------------------------------------------- 97 | # APP & SVC modules to compile 98 | 99 | NPP_M_MODULES_APP="npp_app.cpp ../lib/npp_eng_app.c ../lib/npp_lib.c" 100 | NPP_M_MODULES_SVC="npp_svc.cpp ../lib/npp_eng_svc.c ../lib/npp_lib.c" 101 | 102 | NPP_APP_MODULES=$(get_quoted_value "NPP_APP_MODULES") 103 | 104 | if [ ! -z "$NPP_APP_MODULES" ] 105 | then 106 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} ${NPP_APP_MODULES}" 107 | fi 108 | 109 | NPP_SVC_MODULES_SAME=$(get_value "NPP_SVC_MODULES") 110 | 111 | if [ "$NPP_SVC_MODULES_SAME" = "NPP_APP_MODULES" ] 112 | then 113 | NPP_SVC_MODULES=$NPP_APP_MODULES 114 | else 115 | NPP_SVC_MODULES=$(get_quoted_value "NPP_SVC_MODULES") 116 | fi 117 | 118 | if [ ! -z "$NPP_SVC_MODULES" ] 119 | then 120 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} ${NPP_SVC_MODULES}" 121 | fi 122 | 123 | if [ $NPP_MYSQL -eq 1 ] 124 | then 125 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} ../lib/npp_mysql.cpp" 126 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} ../lib/npp_mysql.cpp" 127 | fi 128 | 129 | if [ $NPP_USERS -eq 1 ] 130 | then 131 | 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" 132 | 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" 133 | fi 134 | 135 | if [ $NPP_VERBOSE -eq 1 ] 136 | then 137 | echo "NPP_M_MODULES_APP=${NPP_M_MODULES_APP}" 138 | echo "NPP_M_MODULES_SVC=${NPP_M_MODULES_SVC}" 139 | fi 140 | 141 | 142 | # ---------------------------------------------------------------------------- 143 | # NPP_CPP_STRINGS 144 | 145 | NPP_CPP_STRINGS=$(get_presence "NPP_CPP_STRINGS") 146 | 147 | if [ $NPP_CPP_STRINGS -eq 1 ] 148 | then 149 | NPP_M_MODULES_APP="${NPP_M_MODULES_APP} -std=c++17" 150 | NPP_M_MODULES_SVC="${NPP_M_MODULES_SVC} -std=c++17" 151 | fi 152 | 153 | 154 | # ---------------------------------------------------------------------------- 155 | # Include paths 156 | 157 | NPP_INCLUDE="-I. -I../lib" 158 | 159 | if [ $NPP_VERBOSE -eq 1 ] 160 | then 161 | echo "NPP_INCLUDE=${NPP_INCLUDE}" 162 | fi 163 | 164 | 165 | # ---------------------------------------------------------------------------- 166 | # System and third-party libraries 167 | 168 | NPP_LIBS_APP="" 169 | NPP_LIBS_SVC="" 170 | 171 | if [ $NPP_ASYNC -eq 1 ] 172 | then 173 | if [ "$NPP_OS" = "debian" ] || [ -z "${NPP_OS##*rhel*}" ] || [ -z "${NPP_OS##*fedora*}" ] 174 | then 175 | NPP_LIBS_APP="-lrt" 176 | NPP_LIBS_SVC="-lrt" 177 | fi 178 | fi 179 | 180 | NPP_LIBS_UPDATE="" 181 | 182 | if [ $NPP_HTTPS -eq 1 ] 183 | then 184 | NPP_LIBS_APP="${NPP_LIBS_APP} -lssl -lcrypto" 185 | NPP_LIBS_SVC="${NPP_LIBS_SVC} -lssl -lcrypto" 186 | NPP_LIBS_UPDATE="${NPP_LIBS_UPDATE} -lssl -lcrypto" 187 | fi 188 | 189 | if [ $NPP_MYSQL -eq 1 ] 190 | then 191 | NPP_LIBS_APP="${NPP_LIBS_APP} -lmysqlclient" 192 | NPP_LIBS_SVC="${NPP_LIBS_SVC} -lmysqlclient" 193 | fi 194 | 195 | NPP_LIBS_APP="${NPP_LIBS_APP} -lz" 196 | 197 | if [ $NPP_VERBOSE -eq 1 ] 198 | then 199 | echo "NPP_LIBS_APP=${NPP_LIBS_APP}" 200 | echo "NPP_LIBS_SVC=${NPP_LIBS_SVC}" 201 | echo "NPP_LIBS_UPDATE=${NPP_LIBS_UPDATE}" 202 | fi 203 | 204 | 205 | # ---------------------------------------------------------------------------- 206 | # Compile 207 | 208 | NPP_APP_NAME=$(get_quoted_value "NPP_APP_NAME") 209 | 210 | if [ ! -z "$NPP_APP_NAME" ] 211 | then 212 | echo Building ${NPP_APP_NAME}... 213 | else 214 | echo Building application... 215 | fi 216 | 217 | echo Making npp_app... 218 | 219 | g++ $NPP_M_MODULES_APP \ 220 | -D NPP_APP \ 221 | $NPP_INCLUDE \ 222 | $NPP_LIBS_APP \ 223 | -O3 \ 224 | -o ../bin/npp_app 225 | 226 | 227 | if [ $? -ne 0 ] # error 228 | then 229 | exit 1 230 | fi 231 | 232 | 233 | if [ $NPP_ASYNC -eq 1 ] 234 | then 235 | echo Making npp_svc... 236 | 237 | g++ $NPP_M_MODULES_SVC \ 238 | -D NPP_SVC \ 239 | $NPP_INCLUDE \ 240 | $NPP_LIBS_SVC \ 241 | -O3 \ 242 | -o ../bin/npp_svc 243 | fi 244 | 245 | 246 | if [ "$1" = "all" ] 247 | then 248 | echo Making npp_watcher... 249 | 250 | gcc ../lib/npp_watcher.c \ 251 | ../lib/npp_lib.c \ 252 | -D NPP_WATCHER \ 253 | $NPP_INCLUDE \ 254 | -O3 \ 255 | -o ../bin/npp_watcher 256 | 257 | 258 | echo Making npp_update... 259 | 260 | gcc ../lib/npp_update.c \ 261 | ../lib/npp_lib.c \ 262 | -D NPP_UPDATE \ 263 | $NPP_INCLUDE \ 264 | $NPP_LIBS_UPDATE \ 265 | -O3 \ 266 | -o ../bin/npp_update 267 | fi 268 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/Cusers.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2024-01-06 12:44:01, 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_OTP[44+1]; 24 | typedef char USERS_OTP_EXPIRES[19+1]; 25 | typedef char USERS_LANG[5+1]; 26 | typedef char USERS_ABOUT[250+1]; 27 | typedef char USERS_CREATED[19+1]; 28 | typedef char USERS_LAST_LOGIN[19+1]; 29 | typedef char USERS_ULA_TIME[19+1]; 30 | 31 | 32 | typedef struct 33 | { 34 | int id; 35 | USERS_LOGIN login; 36 | USERS_LOGIN_U login_u; 37 | USERS_EMAIL email; 38 | USERS_EMAIL_U email_u; 39 | USERS_NAME name; 40 | USERS_PHONE phone; 41 | USERS_PASSWD1 passwd1; 42 | USERS_PASSWD2 passwd2; 43 | USERS_OTP otp; 44 | USERS_OTP_EXPIRES otp_expires; 45 | USERS_LANG lang; 46 | USERS_ABOUT about; 47 | int group_id; 48 | char auth_level; 49 | char status; 50 | USERS_CREATED created; 51 | USERS_LAST_LOGIN last_login; 52 | int visits; 53 | int ula_cnt; 54 | USERS_ULA_TIME ula_time; 55 | } USERS_REC; 56 | 57 | 58 | class Cusers : public USERS_REC, public Cdb 59 | { 60 | public: 61 | Cusers(); 62 | ~Cusers(); 63 | 64 | // Get the next record 65 | // Return false if end of record set 66 | bool Fetch(); 67 | 68 | // Get one record by PK 69 | // Not Found will return false 70 | bool Get(int arg_id); 71 | 72 | // Insert record 73 | unsigned Insert(); 74 | 75 | // Update record by PK 76 | void Update(int arg_id); 77 | 78 | // Delete record by PK 79 | void Delete(int arg_id); 80 | 81 | // Insert or update record by PK 82 | void Set(int arg_id); 83 | 84 | // Reset all values 85 | void Reset(); 86 | 87 | 88 | private: 89 | static bool slots_[CDB_MAX_INSTANCES]; 90 | 91 | int k_id_; 92 | 93 | unsigned long login_len_; 94 | unsigned long login_u_len_; 95 | unsigned long email_len_; 96 | unsigned long email_u_len_; 97 | unsigned long name_len_; 98 | unsigned long phone_len_; 99 | unsigned long passwd1_len_; 100 | unsigned long passwd2_len_; 101 | unsigned long otp_len_; 102 | MYSQL_TIME t_otp_expires_; 103 | unsigned long lang_len_; 104 | unsigned long about_len_; 105 | MYSQL_TIME t_created_; 106 | MYSQL_TIME t_last_login_; 107 | MYSQL_TIME t_ula_time_; 108 | 109 | 110 | my_bool id_is_null_; 111 | my_bool login_is_null_; 112 | my_bool login_u_is_null_; 113 | my_bool email_is_null_; 114 | my_bool email_u_is_null_; 115 | my_bool name_is_null_; 116 | my_bool phone_is_null_; 117 | my_bool passwd1_is_null_; 118 | my_bool passwd2_is_null_; 119 | my_bool otp_is_null_; 120 | my_bool otp_expires_is_null_; 121 | my_bool lang_is_null_; 122 | my_bool about_is_null_; 123 | my_bool group_id_is_null_; 124 | my_bool auth_level_is_null_; 125 | my_bool status_is_null_; 126 | my_bool created_is_null_; 127 | my_bool last_login_is_null_; 128 | my_bool visits_is_null_; 129 | my_bool ula_cnt_is_null_; 130 | my_bool ula_time_is_null_; 131 | 132 | MYSQL_BIND bndk_[1]; 133 | MYSQL_BIND bndi_[22]; 134 | MYSQL_BIND bndo_[21]; 135 | 136 | void bindKey(MYSQL_STMT *s, int arg_id); 137 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_id=0); 138 | void bindOutput(MYSQL_STMT *s); 139 | void bindSetOutput(); 140 | 141 | void genDTStrings(); 142 | void convDecStrings(); 143 | }; 144 | 145 | 146 | #endif /* CUSERS_H */ 147 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /lib/Cusers_avatars.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-05-29 10:02:34, 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 | 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 | avatar_data_len = 0; 43 | 44 | Reset(); 45 | } 46 | 47 | 48 | /* --------------------------------------------------------------------------- 49 | Destructor 50 | --------------------------------------------------------------------------- */ 51 | Cusers_avatars::~Cusers_avatars() 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_avatars::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_avatars::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_avatars::Get(int arg_user_id) 98 | { 99 | int ret; 100 | 101 | if ( firstGet_ ) 102 | { 103 | char q[CDB_SQLBUF]; 104 | sprintf(q, "SELECT user_id,avatar_name,avatar_data FROM users_avatars WHERE user_id=?"); 105 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 106 | if ( ret != 0 ) 107 | Cdb::ThrowSQL("Cusers_avatars::Get | mysql_stmt_prepare"); 108 | firstGet_ = false; 109 | } 110 | 111 | bindKey(sGet_, arg_user_id); 112 | 113 | if ( mysql_stmt_execute(sGet_) ) 114 | Cdb::ThrowSQL("Cusers_avatars::Get | mysql_stmt_execute"); 115 | 116 | bindOutput(sGet_); 117 | 118 | if ( mysql_stmt_store_result(sGet_) ) 119 | Cdb::ThrowSQL("Cusers_avatars::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_avatars::Get | mysql_stmt_fetch"); 129 | } 130 | 131 | genDTStrings(); 132 | 133 | return true; 134 | } 135 | 136 | 137 | /* --------------------------------------------------------------------------- 138 | Insert record 139 | --------------------------------------------------------------------------- */ 140 | unsigned Cusers_avatars::Insert() 141 | { 142 | int ret; 143 | 144 | if ( firstInsert_ ) 145 | { 146 | char q[CDB_SQLBUF]; 147 | sprintf(q, "INSERT INTO users_avatars (user_id,avatar_name,avatar_data) VALUES (?,?,?)"); 148 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 149 | if ( ret != 0 ) 150 | Cdb::ThrowSQL("Cusers_avatars::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_avatars::Insert | mysql_stmt_execute"); 160 | 161 | return mysql_insert_id(dbConn_); 162 | } 163 | 164 | 165 | /* --------------------------------------------------------------------------- 166 | Update record by PK 167 | --------------------------------------------------------------------------- */ 168 | void Cusers_avatars::Update(int arg_user_id) 169 | { 170 | int ret; 171 | 172 | if ( firstUpdate_ ) 173 | { 174 | char q[CDB_SQLBUF]; 175 | sprintf(q, "UPDATE users_avatars SET user_id=?,avatar_name=?,avatar_data=? WHERE user_id=?"); 176 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 177 | if ( ret != 0 ) 178 | Cdb::ThrowSQL("Cusers_avatars::Update | mysql_stmt_prepare"); 179 | firstUpdate_ = false; 180 | } 181 | 182 | bindInput(sUpdate_, true, arg_user_id); 183 | 184 | ret = mysql_stmt_execute(sUpdate_); 185 | 186 | if ( ret != 0 ) 187 | Cdb::ThrowSQL("Cusers_avatars::Update | mysql_stmt_execute"); 188 | } 189 | 190 | 191 | /* --------------------------------------------------------------------------- 192 | Delete record by PK 193 | --------------------------------------------------------------------------- */ 194 | void Cusers_avatars::Delete(int arg_user_id) 195 | { 196 | int ret; 197 | 198 | if ( firstDelete_ ) 199 | { 200 | char q[CDB_SQLBUF]; 201 | sprintf(q, "DELETE FROM users_avatars WHERE user_id=?"); 202 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 203 | if ( ret != 0 ) 204 | Cdb::ThrowSQL("Cusers_avatars::Delete | mysql_stmt_prepare"); 205 | firstDelete_ = false; 206 | } 207 | 208 | bindKey(sDelete_, arg_user_id); 209 | 210 | ret = mysql_stmt_execute(sDelete_); 211 | 212 | if ( ret != 0 ) 213 | Cdb::ThrowSQL("Cusers_avatars::Delete | mysql_stmt_execute"); 214 | } 215 | 216 | 217 | /* --------------------------------------------------------------------------- 218 | Insert or update record by PK 219 | --------------------------------------------------------------------------- */ 220 | void Cusers_avatars::Set(int arg_user_id) 221 | { 222 | int ret; 223 | 224 | if ( firstSet_ ) 225 | { 226 | char q[CDB_SQLBUF]; 227 | sprintf(q, "SELECT user_id FROM users_avatars WHERE user_id=?"); 228 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 229 | if ( ret != 0 ) 230 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_prepare"); 231 | firstSet_ = false; 232 | } 233 | 234 | bindKey(sSet_, arg_user_id); 235 | 236 | if ( mysql_stmt_execute(sSet_) ) 237 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_execute"); 238 | 239 | bindSetOutput(); 240 | 241 | if ( mysql_stmt_store_result(sSet_) ) 242 | Cdb::ThrowSQL("Cusers_avatars::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); 249 | } 250 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 251 | { 252 | user_id = arg_user_id; 253 | 254 | Insert(); 255 | } 256 | else 257 | Cdb::ThrowSQL("Cusers_avatars::Set | mysql_stmt_fetch"); 258 | } 259 | 260 | 261 | /* --------------------------------------------------------------------------- 262 | Bind key values 263 | --------------------------------------------------------------------------- */ 264 | void Cusers_avatars::bindKey(MYSQL_STMT *s, int arg_user_id) 265 | { 266 | k_user_id_ = arg_user_id; 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 | if ( mysql_stmt_bind_param(s, bndk_) ) 274 | Cdb::ThrowSQL("Cusers_avatars::bindKey | mysql_stmt_bind_param"); 275 | } 276 | 277 | 278 | /* --------------------------------------------------------------------------- 279 | Bind input values 280 | --------------------------------------------------------------------------- */ 281 | void Cusers_avatars::bindInput(MYSQL_STMT *s, bool withKey, int arg_user_id) 282 | { 283 | avatar_name_len_ = strlen(avatar_name); 284 | 285 | 286 | memset(&bndi_, 0, sizeof(bndi_)); 287 | 288 | bndi_[0].buffer_type = MYSQL_TYPE_LONG; 289 | bndi_[0].buffer = (char*)&user_id; 290 | 291 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 292 | bndi_[1].buffer = (char*)avatar_name; 293 | bndi_[1].length = &avatar_name_len_; 294 | 295 | bndi_[2].buffer_type = MYSQL_TYPE_BLOB; 296 | bndi_[2].buffer = (char*)avatar_data; 297 | bndi_[2].length = &avatar_data_len; 298 | 299 | if ( withKey ) /* after WHERE */ 300 | { 301 | k_user_id_ = arg_user_id; 302 | 303 | bndi_[3].buffer_type = MYSQL_TYPE_LONG; 304 | bndi_[3].buffer = (char*)&k_user_id_; 305 | 306 | } 307 | 308 | if ( mysql_stmt_bind_param(s, bndi_) ) 309 | Cdb::ThrowSQL("Cusers_avatars::bindInput | mysql_stmt_bind_param"); 310 | } 311 | 312 | 313 | /* --------------------------------------------------------------------------- 314 | Bind output values 315 | --------------------------------------------------------------------------- */ 316 | void Cusers_avatars::bindOutput(MYSQL_STMT *s) 317 | { 318 | memset(&bndo_, 0, sizeof(bndo_)); 319 | 320 | bndo_[0].buffer_type = MYSQL_TYPE_LONG; 321 | bndo_[0].buffer = (char*)&user_id; 322 | bndo_[0].is_null = &user_id_is_null_; 323 | 324 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 325 | bndo_[1].buffer = (char*)avatar_name; 326 | bndo_[1].buffer_length = 121; 327 | bndo_[1].is_null = &avatar_name_is_null_; 328 | 329 | bndo_[2].buffer_type = MYSQL_TYPE_BLOB; 330 | bndo_[2].buffer = (char*)avatar_data; 331 | bndo_[2].buffer_length = 65536; 332 | bndo_[2].length = &avatar_data_len; 333 | bndo_[2].is_null = &avatar_data_is_null_; 334 | 335 | if ( mysql_stmt_bind_result(s, bndo_) ) 336 | Cdb::ThrowSQL("Cusers_avatars::bindOutput | mysql_stmt_bind_result"); 337 | } 338 | 339 | 340 | /* --------------------------------------------------------------------------- 341 | Bind output value for Set 342 | --------------------------------------------------------------------------- */ 343 | void Cusers_avatars::bindSetOutput() 344 | { 345 | static int user_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*)&user_id; 351 | 352 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 353 | Cdb::ThrowSQL("Cusers_avatars::bindSetOutput | mysql_stmt_bind_result"); 354 | } 355 | 356 | 357 | /* --------------------------------------------------------------------------- 358 | Generate date-time strings 359 | --------------------------------------------------------------------------- */ 360 | void Cusers_avatars::genDTStrings() 361 | { 362 | } 363 | 364 | 365 | /* --------------------------------------------------------------------------- 366 | Reset (zero) public variables 367 | --------------------------------------------------------------------------- */ 368 | void Cusers_avatars::Reset() 369 | { 370 | user_id = 0; 371 | avatar_name[0] = EOS; 372 | avatar_data[0] = EOS; 373 | } 374 | -------------------------------------------------------------------------------- /lib/Cusers_avatars.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2022-05-29 10:02:34, 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 | } USERS_AVATARS_REC; 25 | 26 | 27 | class Cusers_avatars : public USERS_AVATARS_REC, public Cdb 28 | { 29 | public: 30 | unsigned long avatar_data_len; 31 | 32 | Cusers_avatars(); 33 | ~Cusers_avatars(); 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(int arg_user_id); 42 | 43 | // Insert record 44 | unsigned Insert(); 45 | 46 | // Update record by PK 47 | void Update(int arg_user_id); 48 | 49 | // Delete record by PK 50 | void Delete(int arg_user_id); 51 | 52 | // Insert or update record by PK 53 | void Set(int arg_user_id); 54 | 55 | // Reset all values 56 | void Reset(); 57 | 58 | 59 | private: 60 | static bool slots_[CDB_MAX_INSTANCES]; 61 | 62 | int k_user_id_; 63 | 64 | unsigned long avatar_name_len_; 65 | 66 | 67 | my_bool user_id_is_null_; 68 | my_bool avatar_name_is_null_; 69 | my_bool avatar_data_is_null_; 70 | 71 | MYSQL_BIND bndk_[1]; 72 | MYSQL_BIND bndi_[4]; 73 | MYSQL_BIND bndo_[3]; 74 | 75 | void bindKey(MYSQL_STMT *s, int arg_user_id); 76 | void bindInput(MYSQL_STMT *s, bool withKey=false, int arg_user_id=0); 77 | void bindOutput(MYSQL_STMT *s); 78 | void bindSetOutput(); 79 | 80 | void genDTStrings(); 81 | }; 82 | 83 | 84 | #endif /* CUSERS_AVATARS_H */ 85 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /lib/Cusers_logins.cpp: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2024-03-24 00:13:16, generator v.2.1.0 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 | 47 | Reset(); 48 | } 49 | 50 | 51 | /* --------------------------------------------------------------------------- 52 | Destructor 53 | --------------------------------------------------------------------------- */ 54 | Cusers_logins::~Cusers_logins() 55 | { 56 | mysql_stmt_close(s_); 57 | mysql_stmt_close(sGet_); 58 | mysql_stmt_close(sUpdate_); 59 | mysql_stmt_close(sInsert_); 60 | mysql_stmt_close(sDelete_); 61 | mysql_stmt_close(sSet_); 62 | 63 | slots_[instance_] = false; 64 | } 65 | 66 | 67 | /* --------------------------------------------------------------------------- 68 | Get the next record 69 | Return false if end of record set 70 | --------------------------------------------------------------------------- */ 71 | bool Cusers_logins::Fetch() 72 | { 73 | int ret; 74 | 75 | ret = mysql_stmt_fetch(s_); 76 | 77 | if ( ret != 0 ) 78 | { 79 | Reset(); 80 | 81 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 82 | return false; 83 | else 84 | { 85 | Cdb::ThrowSQL("Cusers_logins::Fetch | mysql_stmt_fetch"); 86 | return false; 87 | } 88 | } 89 | 90 | genDTStrings(); 91 | 92 | return true; 93 | } 94 | 95 | 96 | /* --------------------------------------------------------------------------- 97 | Get record by PK 98 | Not Found will return false 99 | --------------------------------------------------------------------------- */ 100 | bool Cusers_logins::Get(const std::string& arg_sessid) 101 | { 102 | int ret; 103 | 104 | if ( firstGet_ ) 105 | { 106 | char q[CDB_SQLBUF]; 107 | sprintf(q, "SELECT sessid,uagent,ip,user_id,csrft,created,last_used FROM users_logins WHERE sessid=?"); 108 | ret = mysql_stmt_prepare(sGet_, q, strlen(q)); 109 | if ( ret != 0 ) 110 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_prepare"); 111 | firstGet_ = false; 112 | } 113 | 114 | bindKey(sGet_, arg_sessid); 115 | 116 | if ( mysql_stmt_execute(sGet_) ) 117 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_execute"); 118 | 119 | bindOutput(sGet_); 120 | 121 | if ( mysql_stmt_store_result(sGet_) ) 122 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_store_result"); 123 | 124 | ret = mysql_stmt_fetch(sGet_); 125 | 126 | if ( ret != 0 ) 127 | { 128 | if ( ret == 1 || ret == MYSQL_NO_DATA ) 129 | return false; 130 | else 131 | Cdb::ThrowSQL("Cusers_logins::Get | mysql_stmt_fetch"); 132 | } 133 | 134 | genDTStrings(); 135 | 136 | return true; 137 | } 138 | 139 | 140 | /* --------------------------------------------------------------------------- 141 | Insert record 142 | --------------------------------------------------------------------------- */ 143 | unsigned Cusers_logins::Insert() 144 | { 145 | int ret; 146 | 147 | if ( firstInsert_ ) 148 | { 149 | char q[CDB_SQLBUF]; 150 | sprintf(q, "INSERT INTO users_logins (sessid,uagent,ip,user_id,csrft,created,last_used) VALUES (?,?,?,?,?,?,?)"); 151 | ret = mysql_stmt_prepare(sInsert_, q, strlen(q)); 152 | if ( ret != 0 ) 153 | Cdb::ThrowSQL("Cusers_logins::Insert | mysql_stmt_prepare"); 154 | firstInsert_ = false; 155 | } 156 | 157 | bindInput(sInsert_); 158 | 159 | ret = mysql_stmt_execute(sInsert_); 160 | 161 | if ( ret != 0 ) 162 | Cdb::ThrowSQL("Cusers_logins::Insert | mysql_stmt_execute"); 163 | 164 | return mysql_insert_id(dbConn_); 165 | } 166 | 167 | 168 | /* --------------------------------------------------------------------------- 169 | Update record by PK 170 | --------------------------------------------------------------------------- */ 171 | void Cusers_logins::Update(const std::string& arg_sessid) 172 | { 173 | int ret; 174 | 175 | if ( firstUpdate_ ) 176 | { 177 | char q[CDB_SQLBUF]; 178 | sprintf(q, "UPDATE users_logins SET sessid=?,uagent=?,ip=?,user_id=?,csrft=?,created=?,last_used=? WHERE sessid=?"); 179 | ret = mysql_stmt_prepare(sUpdate_, q, strlen(q)); 180 | if ( ret != 0 ) 181 | Cdb::ThrowSQL("Cusers_logins::Update | mysql_stmt_prepare"); 182 | firstUpdate_ = false; 183 | } 184 | 185 | bindInput(sUpdate_, true, arg_sessid); 186 | 187 | ret = mysql_stmt_execute(sUpdate_); 188 | 189 | if ( ret != 0 ) 190 | Cdb::ThrowSQL("Cusers_logins::Update | mysql_stmt_execute"); 191 | } 192 | 193 | 194 | /* --------------------------------------------------------------------------- 195 | Delete record by PK 196 | --------------------------------------------------------------------------- */ 197 | void Cusers_logins::Delete(const std::string& arg_sessid) 198 | { 199 | int ret; 200 | 201 | if ( firstDelete_ ) 202 | { 203 | char q[CDB_SQLBUF]; 204 | sprintf(q, "DELETE FROM users_logins WHERE sessid=?"); 205 | ret = mysql_stmt_prepare(sDelete_, q, strlen(q)); 206 | if ( ret != 0 ) 207 | Cdb::ThrowSQL("Cusers_logins::Delete | mysql_stmt_prepare"); 208 | firstDelete_ = false; 209 | } 210 | 211 | bindKey(sDelete_, arg_sessid); 212 | 213 | ret = mysql_stmt_execute(sDelete_); 214 | 215 | if ( ret != 0 ) 216 | Cdb::ThrowSQL("Cusers_logins::Delete | mysql_stmt_execute"); 217 | } 218 | 219 | 220 | /* --------------------------------------------------------------------------- 221 | Insert or update record by PK 222 | --------------------------------------------------------------------------- */ 223 | void Cusers_logins::Set(const std::string& arg_sessid) 224 | { 225 | int ret; 226 | 227 | if ( firstSet_ ) 228 | { 229 | char q[CDB_SQLBUF]; 230 | sprintf(q, "SELECT sessid FROM users_logins WHERE sessid=?"); 231 | ret = mysql_stmt_prepare(sSet_, q, strlen(q)); 232 | if ( ret != 0 ) 233 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_prepare"); 234 | firstSet_ = false; 235 | } 236 | 237 | bindKey(sSet_, arg_sessid); 238 | 239 | if ( mysql_stmt_execute(sSet_) ) 240 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_execute"); 241 | 242 | bindSetOutput(); 243 | 244 | if ( mysql_stmt_store_result(sSet_) ) 245 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_store_result"); 246 | 247 | ret = mysql_stmt_fetch(sSet_); 248 | 249 | if ( ret == 0 ) /* record existed */ 250 | { 251 | Update(arg_sessid); 252 | } 253 | else if ( ret == 1 || ret == MYSQL_NO_DATA ) /* not found ==> insert new */ 254 | { 255 | strncpy(sessid, arg_sessid.c_str(), 20); 256 | sessid[20] = EOS; 257 | 258 | Insert(); 259 | } 260 | else 261 | Cdb::ThrowSQL("Cusers_logins::Set | mysql_stmt_fetch"); 262 | } 263 | 264 | 265 | /* --------------------------------------------------------------------------- 266 | Bind key values 267 | --------------------------------------------------------------------------- */ 268 | void Cusers_logins::bindKey(MYSQL_STMT *s, const std::string& arg_sessid) 269 | { 270 | strncpy(k_sessid_, arg_sessid.c_str(), 20); 271 | k_sessid_[20] = EOS; 272 | 273 | k_sessid_len_ = strlen(k_sessid_); 274 | 275 | memset(&bndk_, 0, sizeof(bndk_)); 276 | 277 | bndk_[0].buffer_type = MYSQL_TYPE_STRING; 278 | bndk_[0].buffer = (char*)k_sessid_; 279 | bndk_[0].length = &k_sessid_len_; 280 | 281 | if ( mysql_stmt_bind_param(s, bndk_) ) 282 | Cdb::ThrowSQL("Cusers_logins::bindKey | mysql_stmt_bind_param"); 283 | } 284 | 285 | 286 | /* --------------------------------------------------------------------------- 287 | Bind input values 288 | --------------------------------------------------------------------------- */ 289 | void Cusers_logins::bindInput(MYSQL_STMT *s, bool withKey, const std::string& arg_sessid) 290 | { 291 | sessid_len_ = strlen(sessid); 292 | uagent_len_ = strlen(uagent); 293 | ip_len_ = strlen(ip); 294 | csrft_len_ = strlen(csrft); 295 | 296 | set_datetime(&t_created_, created); 297 | set_datetime(&t_last_used_, last_used); 298 | 299 | memset(&bndi_, 0, sizeof(bndi_)); 300 | 301 | bndi_[0].buffer_type = MYSQL_TYPE_STRING; 302 | bndi_[0].buffer = (char*)sessid; 303 | bndi_[0].length = &sessid_len_; 304 | 305 | bndi_[1].buffer_type = MYSQL_TYPE_STRING; 306 | bndi_[1].buffer = (char*)uagent; 307 | bndi_[1].length = &uagent_len_; 308 | 309 | bndi_[2].buffer_type = MYSQL_TYPE_STRING; 310 | bndi_[2].buffer = (char*)ip; 311 | bndi_[2].length = &ip_len_; 312 | 313 | bndi_[3].buffer_type = MYSQL_TYPE_LONG; 314 | bndi_[3].buffer = (char*)&user_id; 315 | 316 | bndi_[4].buffer_type = MYSQL_TYPE_STRING; 317 | bndi_[4].buffer = (char*)csrft; 318 | bndi_[4].length = &csrft_len_; 319 | 320 | bndi_[5].buffer_type = MYSQL_TYPE_DATETIME; 321 | bndi_[5].buffer = (char*)&t_created_; 322 | 323 | bndi_[6].buffer_type = MYSQL_TYPE_DATETIME; 324 | bndi_[6].buffer = (char*)&t_last_used_; 325 | 326 | if ( withKey ) /* after WHERE */ 327 | { 328 | strncpy(k_sessid_, arg_sessid.c_str(), 20); 329 | k_sessid_[20] = EOS; 330 | 331 | k_sessid_len_ = strlen(k_sessid_); 332 | 333 | bndi_[7].buffer_type = MYSQL_TYPE_STRING; 334 | bndi_[7].buffer = (char*)k_sessid_; 335 | bndi_[7].length = &k_sessid_len_; 336 | 337 | } 338 | 339 | if ( mysql_stmt_bind_param(s, bndi_) ) 340 | Cdb::ThrowSQL("Cusers_logins::bindInput | mysql_stmt_bind_param"); 341 | } 342 | 343 | 344 | /* --------------------------------------------------------------------------- 345 | Bind output values 346 | --------------------------------------------------------------------------- */ 347 | void Cusers_logins::bindOutput(MYSQL_STMT *s) 348 | { 349 | memset(&bndo_, 0, sizeof(bndo_)); 350 | 351 | bndo_[0].buffer_type = MYSQL_TYPE_STRING; 352 | bndo_[0].buffer = (char*)sessid; 353 | bndo_[0].buffer_length = 21; 354 | bndo_[0].is_null = &sessid_is_null_; 355 | 356 | bndo_[1].buffer_type = MYSQL_TYPE_STRING; 357 | bndo_[1].buffer = (char*)uagent; 358 | bndo_[1].buffer_length = 251; 359 | bndo_[1].is_null = &uagent_is_null_; 360 | 361 | bndo_[2].buffer_type = MYSQL_TYPE_STRING; 362 | bndo_[2].buffer = (char*)ip; 363 | bndo_[2].buffer_length = 46; 364 | bndo_[2].is_null = &ip_is_null_; 365 | 366 | bndo_[3].buffer_type = MYSQL_TYPE_LONG; 367 | bndo_[3].buffer = (char*)&user_id; 368 | bndo_[3].is_null = &user_id_is_null_; 369 | 370 | bndo_[4].buffer_type = MYSQL_TYPE_STRING; 371 | bndo_[4].buffer = (char*)csrft; 372 | bndo_[4].buffer_length = 16; 373 | bndo_[4].is_null = &csrft_is_null_; 374 | 375 | bndo_[5].buffer_type = MYSQL_TYPE_DATETIME; 376 | bndo_[5].buffer = (char*)&t_created_; 377 | bndo_[5].is_null = &created_is_null_; 378 | 379 | bndo_[6].buffer_type = MYSQL_TYPE_DATETIME; 380 | bndo_[6].buffer = (char*)&t_last_used_; 381 | bndo_[6].is_null = &last_used_is_null_; 382 | 383 | if ( mysql_stmt_bind_result(s, bndo_) ) 384 | Cdb::ThrowSQL("Cusers_logins::bindOutput | mysql_stmt_bind_result"); 385 | } 386 | 387 | 388 | /* --------------------------------------------------------------------------- 389 | Bind output value for Set 390 | --------------------------------------------------------------------------- */ 391 | void Cusers_logins::bindSetOutput() 392 | { 393 | static USERS_LOGINS_SESSID sessid; /* to be scrapped anyway */ 394 | 395 | memset(&bndso_, 0, sizeof(bndso_)); 396 | 397 | bndso_[0].buffer_type = MYSQL_TYPE_STRING; 398 | bndso_[0].buffer = (char*)sessid; 399 | bndso_[0].buffer_length = 21; 400 | 401 | if ( mysql_stmt_bind_result(sSet_, bndso_) ) 402 | Cdb::ThrowSQL("Cusers_logins::bindSetOutput | mysql_stmt_bind_result"); 403 | } 404 | 405 | 406 | /* --------------------------------------------------------------------------- 407 | Generate date-time strings 408 | --------------------------------------------------------------------------- */ 409 | void Cusers_logins::genDTStrings() 410 | { 411 | if ( created_is_null_ ) 412 | created[0] = EOS; 413 | else 414 | 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); 415 | 416 | if ( last_used_is_null_ ) 417 | last_used[0] = EOS; 418 | else 419 | 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); 420 | 421 | } 422 | 423 | 424 | /* --------------------------------------------------------------------------- 425 | Reset (zero) public variables 426 | --------------------------------------------------------------------------- */ 427 | void Cusers_logins::Reset() 428 | { 429 | sessid[0] = EOS; 430 | uagent[0] = EOS; 431 | ip[0] = EOS; 432 | user_id = 0; 433 | csrft[0] = EOS; 434 | created[0] = EOS; 435 | last_used[0] = EOS; 436 | } 437 | -------------------------------------------------------------------------------- /lib/Cusers_logins.h: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------- 2 | Table access class 3 | Generated on nodepp.org on 2024-03-24 00:13:16, generator v.2.1.0 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[20+1]; 16 | typedef char USERS_LOGINS_UAGENT[250+1]; 17 | typedef char USERS_LOGINS_IP[45+1]; 18 | typedef char USERS_LOGINS_CSRFT[15+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 | 39 | Cusers_logins(); 40 | ~Cusers_logins(); 41 | 42 | // Get the next record 43 | // Return false if end of record set 44 | bool Fetch(); 45 | 46 | // Get one record by PK 47 | // Not Found will return false 48 | bool Get(const std::string& arg_sessid); 49 | 50 | // Insert record 51 | unsigned Insert(); 52 | 53 | // Update record by PK 54 | void Update(const std::string& arg_sessid); 55 | 56 | // Delete record by PK 57 | void Delete(const std::string& arg_sessid); 58 | 59 | // Insert or update record by PK 60 | void Set(const std::string& arg_sessid); 61 | 62 | // Reset all values 63 | void Reset(); 64 | 65 | 66 | private: 67 | static bool slots_[CDB_MAX_INSTANCES]; 68 | 69 | USERS_LOGINS_SESSID k_sessid_; 70 | 71 | unsigned long sessid_len_; 72 | unsigned long uagent_len_; 73 | unsigned long ip_len_; 74 | unsigned long csrft_len_; 75 | MYSQL_TIME t_created_; 76 | MYSQL_TIME t_last_used_; 77 | 78 | unsigned long k_sessid_len_; 79 | 80 | my_bool sessid_is_null_; 81 | my_bool uagent_is_null_; 82 | my_bool ip_is_null_; 83 | my_bool user_id_is_null_; 84 | my_bool csrft_is_null_; 85 | my_bool created_is_null_; 86 | my_bool last_used_is_null_; 87 | 88 | MYSQL_BIND bndk_[1]; 89 | MYSQL_BIND bndi_[8]; 90 | MYSQL_BIND bndo_[7]; 91 | 92 | void bindKey(MYSQL_STMT *s, const std::string& arg_sessid); 93 | void bindInput(MYSQL_STMT *s, bool withKey=false, const std::string& arg_sessid=""); 94 | void bindOutput(MYSQL_STMT *s); 95 | void bindSetOutput(); 96 | 97 | void genDTStrings(); 98 | }; 99 | 100 | 101 | #endif /* CUSERS_LOGINS_H */ 102 | -------------------------------------------------------------------------------- /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_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_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_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.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_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/npp_update.c: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020-2024 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 | -------------------------------------------------------------------------------- /lib/npp_usr.h: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020-2024 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 users_logins 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 | #ifndef NPP_OTP_LEN 104 | #define NPP_OTP_LEN 7 105 | #endif 106 | 107 | #ifndef NPP_OTP_EXPIRATION_MINUTES 108 | #define NPP_OTP_EXPIRATION_MINUTES 15 109 | #endif 110 | 111 | 112 | #ifndef REFUSE_10_COMMON_PASSWORDS 113 | #ifndef REFUSE_100_COMMON_PASSWORDS 114 | #ifndef REFUSE_1000_COMMON_PASSWORDS 115 | #ifndef REFUSE_10000_COMMON_PASSWORDS 116 | #ifndef DONT_REFUSE_COMMON_PASSWORDS 117 | #define DONT_REFUSE_COMMON_PASSWORDS 118 | #endif 119 | #endif 120 | #endif 121 | #endif 122 | #endif 123 | 124 | /* passwords' peppers */ 125 | 126 | #ifndef NPP_PEPPER_01 127 | #define NPP_PEPPER_01 "abcde" 128 | #endif 129 | #ifndef NPP_PEPPER_02 130 | #define NPP_PEPPER_02 "fghij" 131 | #endif 132 | #ifndef NPP_PEPPER_03 133 | #define NPP_PEPPER_03 "klmno" 134 | #endif 135 | #ifndef NPP_PEPPER_04 136 | #define NPP_PEPPER_04 "pqrst" 137 | #endif 138 | #ifndef NPP_PEPPER_05 139 | #define NPP_PEPPER_05 "uvwxy" 140 | #endif 141 | 142 | 143 | /* Node++ engine errors are 0 ... 99 */ 144 | 145 | /* ------------------------------------- */ 146 | /* errors -- red */ 147 | 148 | /* login */ 149 | #define ERR_INVALID_LOGIN 101 150 | #define ERR_USERNAME_TOO_SHORT 102 151 | #define ERR_USERNAME_CHARS 103 152 | #define ERR_USERNAME_TAKEN 104 153 | /* ------------------------------------- */ 154 | #define ERR_MAX_USR_LOGIN_ERROR 110 155 | /* ------------------------------------- */ 156 | /* email */ 157 | #define ERR_EMAIL_EMPTY 111 158 | #define ERR_EMAIL_FORMAT 112 159 | #define ERR_EMAIL_FORMAT_OR_EMPTY 113 160 | #define ERR_EMAIL_TAKEN 114 161 | #define ERR_EMAIL_NOT_REGISTERED 115 162 | /* ------------------------------------- */ 163 | #define ERR_MAX_USR_EMAIL_ERROR 120 164 | /* ------------------------------------- */ 165 | /* password */ 166 | #define ERR_INVALID_PASSWORD 121 167 | #define ERR_PASSWORD_TOO_SHORT 122 168 | #define ERR_IN_10_COMMON_PASSWORDS 123 169 | #define ERR_IN_100_COMMON_PASSWORDS 124 170 | #define ERR_IN_1000_COMMON_PASSWORDS 125 171 | #define ERR_IN_10000_COMMON_PASSWORDS 126 172 | #define ERR_OTP_EXPIRED 127 173 | /* ------------------------------------- */ 174 | #define ERR_MAX_USR_PASSWORD_ERROR 130 175 | /* ------------------------------------- */ 176 | /* repeat password */ 177 | #define ERR_PASSWORD_DIFFERENT 131 178 | /* ------------------------------------- */ 179 | #define ERR_MAX_USR_REPEAT_PASSWORD_ERROR 140 180 | /* ------------------------------------- */ 181 | /* old password */ 182 | #define ERR_OLD_PASSWORD 141 183 | /* ------------------------------------- */ 184 | #define ERR_MAX_USR_OLD_PASSWORD_ERROR 150 185 | /* ------------------------------------- */ 186 | /* session / link / other */ 187 | #define ERR_SESSION_EXPIRED 151 188 | #define ERR_LINK_BROKEN 152 189 | #define ERR_LINK_MAY_BE_EXPIRED 153 190 | #define ERR_LINK_EXPIRED 154 191 | #define ERR_LINK_TOO_MANY_TRIES 155 192 | #define ERR_ROBOT 156 193 | #define ERR_WEBSITE_FIRST_LETTER 157 194 | #define ERR_NOT_ACTIVATED 158 195 | /* ------------------------------------- */ 196 | #define ERR_MAX_USR_ERROR 199 197 | /* ------------------------------------- */ 198 | 199 | /* ------------------------------------- */ 200 | /* warnings -- yellow */ 201 | 202 | #define WAR_NO_EMAIL 201 203 | #define WAR_BEFORE_DELETE 202 204 | #define WAR_ULA_FIRST 203 205 | #define WAR_ULA_SECOND 204 206 | #define WAR_ULA_THIRD 205 207 | #define WAR_PASSWORD_CHANGE 206 208 | /* ------------------------------------- */ 209 | #define WAR_MAX_USR_WARNING 299 210 | /* ------------------------------------- */ 211 | 212 | /* ------------------------------------- */ 213 | /* messages -- green */ 214 | 215 | #define MSG_WELCOME_NO_ACTIVATION 301 216 | #define MSG_WELCOME_NEED_ACTIVATION 302 217 | #define MSG_WELCOME_AFTER_ACTIVATION 303 218 | #define MSG_USER_LOGGED_OUT 304 219 | #define MSG_CHANGES_SAVED 305 220 | #define MSG_REQUEST_SENT 306 221 | #define MSG_PASSWORD_CHANGED 307 222 | #define MSG_MESSAGE_SENT 308 223 | #define MSG_PROVIDE_FEEDBACK 309 224 | #define MSG_FEEDBACK_SENT 310 225 | #define MSG_USER_ALREADY_ACTIVATED 311 226 | #define MSG_ACCOUNT_DELETED 312 227 | #define MSG_OTP_PASSWORD_SENT 313 228 | /* ------------------------------------- */ 229 | #define MSG_MAX_USR_MESSAGE 399 230 | /* ------------------------------------- */ 231 | 232 | 233 | #define MSG_CAT_USR_LOGIN "msgLogin" 234 | #define MSG_CAT_USR_EMAIL "msgEmail" 235 | #define MSG_CAT_USR_PASSWORD "msgPassword" 236 | #define MSG_CAT_USR_REPEAT_PASSWORD "msgPasswordRepeat" 237 | #define MSG_CAT_USR_OLD_PASSWORD "msgPasswordOld" 238 | 239 | 240 | /* user authentication */ 241 | 242 | #ifndef NPP_USERS_BY_EMAIL 243 | #ifndef NPP_USERS_BY_LOGIN 244 | #define NPP_USERS_BY_LOGIN 245 | #endif 246 | #endif 247 | 248 | 249 | #define NPP_MAX_AVATAR_SIZE 65536 /* MySQL's BLOB size */ 250 | 251 | 252 | #define SET_USER_STR(key, val) npp_usr_set_str(key, val) 253 | #define SET_USR_STR(key, val) npp_usr_set_str(key, val) 254 | 255 | #define GET_USER_STR(key, val) npp_usr_get_str(key, val) 256 | #define GET_USR_STR(key, val) npp_usr_get_str(key, val) 257 | 258 | #define SET_USER_INT(key, val) npp_usr_set_int(key, val) 259 | #define SET_USR_INT(key, val) npp_usr_set_int(key, val) 260 | 261 | #define GET_USER_INT(key, val) npp_usr_get_int(key, val) 262 | #define GET_USR_INT(key, val) npp_usr_get_int(key, val) 263 | 264 | 265 | /* 266 | Brute-force ls cookie attack protection. 267 | It essentially defines how many different IPs can take part in a botnet attack. 268 | */ 269 | 270 | #ifdef NPP_MEM_TINY 271 | #define FAILED_LOGIN_CNT_SIZE 100 272 | #elif defined NPP_MEM_MEDIUM 273 | #define FAILED_LOGIN_CNT_SIZE 1000 274 | #elif defined NPP_MEM_LARGE 275 | #define FAILED_LOGIN_CNT_SIZE 10000 276 | #elif defined NPP_MEM_XLARGE 277 | #define FAILED_LOGIN_CNT_SIZE 10000 278 | #elif defined NPP_MEM_XXLARGE 279 | #define FAILED_LOGIN_CNT_SIZE 100000 280 | #elif defined NPP_MEM_XXXLARGE 281 | #define FAILED_LOGIN_CNT_SIZE 100000 282 | #elif defined NPP_MEM_XXXXLARGE 283 | #define FAILED_LOGIN_CNT_SIZE 100000 284 | #else /* NPP_MEM_SMALL -- default */ 285 | #define FAILED_LOGIN_CNT_SIZE 1000 286 | #endif 287 | 288 | 289 | /* One-time passwords require emails as the keys */ 290 | 291 | #ifdef NPP_USER_ONE_TIME_PASSWORD_ONLY 292 | #ifndef NPP_USERS_BY_EMAIL 293 | #undef NPP_USERS_BY_LOGIN 294 | #define NPP_USERS_BY_EMAIL 295 | #endif 296 | #endif /* NPP_USER_ONE_TIME_PASSWORD_ONLY */ 297 | 298 | 299 | 300 | /* -------------------------------------------------------------------------- 301 | structures 302 | -------------------------------------------------------------------------- */ 303 | 304 | typedef struct { 305 | char ip[INET_ADDRSTRLEN]; 306 | int cnt; 307 | time_t when; 308 | } failed_login_cnt_t; 309 | 310 | 311 | 312 | /* -------------------------------------------------------------------------- 313 | prototypes 314 | -------------------------------------------------------------------------- */ 315 | 316 | #ifdef NPP_CPP_STRINGS 317 | char *npp_usr_name(const char *login, const char *email, const char *name, int user_id); 318 | char *npp_usr_name(const std::string& login, const std::string& email, const std::string& name, int user_id); 319 | 320 | int npp_usr_get_str(const std::string& us_key, char *us_val); 321 | int npp_usr_get_str(const std::string& us_key, std::string& us_val); 322 | #endif 323 | 324 | 325 | #ifdef __cplusplus 326 | extern "C" { 327 | #endif 328 | 329 | int npp_usr_login(); 330 | 331 | #ifdef NPP_CPP_STRINGS 332 | int npp_usr_password_quality(const std::string& passwd); 333 | #else 334 | int npp_usr_password_quality(const char *passwd); 335 | #endif 336 | 337 | int npp_usr_create_account(); 338 | 339 | #ifdef NPP_CPP_STRINGS 340 | int npp_usr_add_user(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); 341 | #else 342 | int npp_usr_add_user(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); 343 | #endif 344 | 345 | int npp_usr_send_message(); 346 | int npp_usr_save_account(); 347 | int npp_usr_email_registered(); 348 | 349 | #ifndef NPP_CPP_STRINGS 350 | char *npp_usr_name(const char *login, const char *email, const char *name, int user_id); 351 | #endif 352 | 353 | int npp_usr_send_passwd_reset_email(); 354 | 355 | #ifdef NPP_CPP_STRINGS 356 | int npp_usr_verify_passwd_reset_key(const std::string& linkkey, int *user_id); 357 | #else 358 | int npp_usr_verify_passwd_reset_key(const char *linkkey, int *user_id); 359 | #endif 360 | 361 | int npp_usr_activate(); 362 | int npp_usr_save_avatar(int user_id); 363 | int npp_usr_get_avatar(int user_id); 364 | int npp_usr_change_password(); 365 | int npp_usr_reset_password(); 366 | void npp_usr_logout(); 367 | 368 | #ifdef NPP_CPP_STRINGS 369 | int npp_usr_set_str(const std::string& us_key, const std::string& us_val); 370 | #else 371 | int npp_usr_set_str(const char *us_key, const char *us_val); 372 | #endif 373 | 374 | #ifndef NPP_CPP_STRINGS 375 | int npp_usr_get_str(const char *us_key, char *us_val); 376 | #endif 377 | 378 | #ifdef NPP_CPP_STRINGS 379 | int npp_usr_set_int(const std::string& us_key, int us_val); 380 | #else 381 | int npp_usr_set_int(const char *us_key, int us_val); 382 | #endif 383 | 384 | #ifdef NPP_CPP_STRINGS 385 | int npp_usr_get_int(const std::string& us_key, int *us_val); 386 | #else 387 | int npp_usr_get_int(const char *us_key, int *us_val); 388 | #endif 389 | 390 | /* for the engine */ 391 | 392 | void libusr_init(void); 393 | int libusr_luses_ok(); 394 | void libusr_luses_close_timeouted(void); 395 | void libusr_luses_save_csrft(void); 396 | void libusr_luses_downgrade(int si, int ci, bool usr_logout); 397 | 398 | #ifdef __cplusplus 399 | } // extern "C" 400 | #endif 401 | 402 | 403 | #endif /* NPP_USR_H */ 404 | -------------------------------------------------------------------------------- /lib/npp_watcher.c: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020-2024 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 | -------------------------------------------------------------------------------- /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 | otp CHAR(44), -- SHA256 hash in base64 (one-time password) 20 | otp_expires DATETIME, -- one-time password expiration time 21 | lang CHAR(5), 22 | about VARCHAR(250), 23 | group_id INT, 24 | auth_level TINYINT, -- 10 = user, 20 = customer, 30 = staff, 40 = moderator, 50 = admin, 100 = root 25 | status TINYINT, -- 0 = inactive, 1 = active, 2 = locked, 3 = requires password change, 9 = deleted 26 | created DATETIME, 27 | last_login DATETIME, 28 | visits INT, 29 | ula_cnt INT, -- unsuccessful login attempt count 30 | ula_time DATETIME -- and time 31 | ); 32 | 33 | CREATE INDEX users_login ON users (login_u); 34 | CREATE INDEX users_email ON users (email_u); 35 | CREATE INDEX users_last_login ON users (last_login); 36 | 37 | 38 | -- avatars 39 | 40 | CREATE TABLE users_avatars 41 | ( 42 | user_id INT PRIMARY KEY, 43 | avatar_name VARCHAR(120), 44 | avatar_data BLOB -- 64 KiB 45 | ); 46 | 47 | 48 | -- groups 49 | 50 | CREATE TABLE users_groups 51 | ( 52 | id INT auto_increment PRIMARY KEY, 53 | name VARCHAR(120), 54 | about VARCHAR(250), 55 | auth_level TINYINT 56 | ); 57 | 58 | 59 | -- user settings 60 | 61 | CREATE TABLE users_settings 62 | ( 63 | user_id INT, 64 | us_key CHAR(30), 65 | us_val VARCHAR(250), 66 | PRIMARY KEY (user_id, us_key) 67 | ); 68 | 69 | 70 | -- user logins 71 | 72 | CREATE TABLE users_logins 73 | ( 74 | sessid CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin PRIMARY KEY, 75 | uagent VARCHAR(250), 76 | ip CHAR(45), 77 | user_id INT, 78 | csrft CHAR(15), 79 | created DATETIME, 80 | last_used DATETIME 81 | ); 82 | 83 | CREATE INDEX users_logins_uid ON users_logins (user_id); 84 | 85 | 86 | -- account activations 87 | 88 | CREATE TABLE users_activations 89 | ( 90 | linkkey CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin PRIMARY KEY, 91 | user_id INT, 92 | created DATETIME, 93 | activated DATETIME 94 | ); 95 | 96 | 97 | -- password resets 98 | 99 | CREATE TABLE users_p_resets 100 | ( 101 | linkkey CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin PRIMARY KEY, 102 | user_id INT, 103 | created DATETIME, 104 | tries SMALLINT 105 | ); 106 | 107 | CREATE INDEX users_p_resets_uid ON users_p_resets (user_id); 108 | 109 | 110 | -- messages 111 | 112 | CREATE TABLE users_messages 113 | ( 114 | user_id INT, 115 | msg_id INT, 116 | email VARCHAR(120), 117 | message TEXT, -- 64 KiB limit 118 | created DATETIME, 119 | PRIMARY KEY (user_id, msg_id) 120 | ); 121 | 122 | CREATE INDEX users_messages_uid ON users_messages (user_id); 123 | -------------------------------------------------------------------------------- /logs/.logs_here: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /res/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekmus/nodepp/8c9fe0566069a78753d7dfcbddde6cb6430b32c4/res/favicon.ico -------------------------------------------------------------------------------- /res/nodepp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekmus/nodepp/8c9fe0566069a78753d7dfcbddde6cb6430b32c4/res/nodepp.jpg -------------------------------------------------------------------------------- /res/wait.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rekmus/nodepp/8c9fe0566069a78753d7dfcbddde6cb6430b32c4/res/wait.gif -------------------------------------------------------------------------------- /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: 6px 14px 14px 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 | -------------------------------------------------------------------------------- /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), optional, default = 23 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 = "23em"; 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 | -------------------------------------------------------------------------------- /snippets/sample_snippet.html: -------------------------------------------------------------------------------- 1 |

HTML

2 |

This section has been rendered from sample_snippet.html file.

3 |

You can put the static parts into html or md files in snippets directory.

4 |

Then you can simply use OUT_SNIPPET("file.html") and OUT_SNIPPET_MD("file.md") macros.

5 | -------------------------------------------------------------------------------- /snippets/sample_snippet.md: -------------------------------------------------------------------------------- 1 | # Markdown 2 | 3 | This section has been rendered from `sample_snippet.md` file. 4 | 5 | ## Emphasis 6 | 7 | **This is bold text** 8 | 9 | *This is italic text* 10 | 11 | _This is underline text_ 12 | 13 | ## Lists 14 | 15 | ### Ordered 16 | 17 | 1. First item 18 | 1. Second item 19 | 1. Third item 20 | 21 | ### Unordered 22 | 23 | * first item 24 | * second item 25 | * third item with **bold** 26 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/npp_app.cpp: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Node++ Web App 3 | Jurek Muszynski 4 | nodepp.org 5 | ----------------------------------------------------------------------------- 6 | Hello World Sample Node++ Web Application 7 | -------------------------------------------------------------------------- */ 8 | 9 | 10 | #include "npp.h" 11 | 12 | 13 | /* -------------------------------------------------------------------------- 14 | Output HTML & page header 15 | -------------------------------------------------------------------------- */ 16 | static void header() 17 | { 18 | OUT(""); 19 | OUT(""); 20 | OUT(""); 21 | OUT(""); 22 | OUT("%s", NPP_APP_NAME); 23 | #ifdef NPP_APP_DESCRIPTION 24 | OUT("", NPP_APP_DESCRIPTION); 25 | #endif 26 | if ( REQ_MOB ) 27 | OUT(""); 28 | OUT(""); 29 | 30 | OUT(""); 31 | 32 | /* -------------------------------------------------------------------------- */ 33 | /* style */ 34 | 35 | OUT(""); 45 | 46 | /* -------------------------------------------------------------------------- */ 47 | /* first row -- logo */ 48 | 49 | OUT("
"); 50 | 51 | static char logo[]="\"Logo\""; 52 | 53 | if ( REQ("") ) 54 | OUT("

%s

", logo); 55 | else 56 | OUT("

%s

", logo); 57 | 58 | OUT("
"); /* end of first row */ 59 | 60 | /* -------------------------------------------------------------------------- */ 61 | /* second row -- main menu */ 62 | 63 | OUT("
"); 64 | 65 | char lnk_home[256]="Home"; 66 | char lnk_welcome[256]="Welcome"; 67 | char lnk_snippets[256]="Snippets"; 68 | char lnk_performance[256]="Performance"; 69 | 70 | if ( REQ("") ) 71 | strcpy(lnk_home, "Home"); 72 | else if ( REQ("welcome") ) 73 | strcpy(lnk_welcome, "Welcome"); 74 | else if ( REQ("snippets") ) 75 | strcpy(lnk_snippets, "Snippets"); 76 | else if ( REQ("performance") ) 77 | strcpy(lnk_performance, "Performance"); 78 | 79 | /* display menu */ 80 | 81 | OUT(lnk_home); 82 | OUT(" | "); 83 | OUT(lnk_welcome); 84 | OUT(" | "); 85 | OUT(lnk_snippets); 86 | OUT(" | "); 87 | OUT(lnk_performance); 88 | 89 | OUT("
"); /* end of second row */ 90 | 91 | OUT("
"); 92 | } 93 | 94 | 95 | /* -------------------------------------------------------------------------- 96 | Output footer; body & html tags close here 97 | -------------------------------------------------------------------------- */ 98 | static void footer() 99 | { 100 | OUT(""); 101 | } 102 | 103 | 104 | /* -------------------------------------------------------------------------- 105 | Render landing page 106 | -------------------------------------------------------------------------- */ 107 | void render_landing() 108 | { 109 | header(); 110 | 111 | OUT("

Congratulations!

"); 112 | 113 | OUT("

You've managed to compile and run Node++ web application! I hope you will like the performance of the compiled code.

"); 114 | 115 | /* show client type */ 116 | 117 | if ( REQ_DSK ) 118 | OUT("

You're on desktop, right?

"); 119 | else if ( REQ_TAB ) 120 | OUT("

You're on tablet, right?

"); 121 | else /* REQ_MOB */ 122 | OUT("

You're on the phone, right?

"); 123 | 124 | /* show some info */ 125 | 126 | OUT("

You can see how a simple form works.

"); 127 | 128 | OUT("

You can use HTML and Markdown snippets for static content.

"); 129 | 130 | OUT("

You can also estimate your server's performance.

"); 131 | 132 | OUT("

You can modify this app in src/npp_app.cpp. The entry point is npp_app_main(). Have fun!

"); 133 | 134 | /* --------------------------------------------------- */ 135 | 136 | OUT("

To see the source code look at render_landing().

"); 137 | 138 | footer(); 139 | } 140 | 141 | 142 | /* -------------------------------------------------------------------------- 143 | Render page 144 | -------------------------------------------------------------------------- */ 145 | void render_welcome() 146 | { 147 | header(); 148 | 149 | /* display form */ 150 | 151 | OUT("

Say something about yourself:

"); 152 | 153 | OUT("
"); 154 | OUT("

Name:

"); 155 | OUT("

Age:

"); 156 | OUT("

"); 157 | OUT("
"); 158 | 159 | /* try to retrieve query string values */ 160 | 161 | QSVAL name; /* string value */ 162 | int age; /* integer */ 163 | 164 | if ( QS("name", name) ) /* if present, bid welcome */ 165 | OUT("

Welcome %s, my dear friend!

", name); /* QS sanitizes strings by default */ 166 | 167 | if ( QSI("age", &age) ) /* if present, say something nice */ 168 | OUT("

It's good to see you in a good health, despite being already %d years old!

", age); 169 | 170 | /* --------------------------------------------------- */ 171 | 172 | if ( QS("name", NULL) ) /* show this only if there's a name in query string */ 173 | OUT("

To see the source code look at render_welcome().

"); 174 | 175 | footer(); 176 | } 177 | 178 | 179 | /* -------------------------------------------------------------------------- 180 | Render page 181 | -------------------------------------------------------------------------- */ 182 | void render_snippets() 183 | { 184 | header(); 185 | 186 | OUT("

You don't have to wrap all the output in OUT macros.

"); 187 | 188 | OUT_SNIPPET("sample_snippet.html"); 189 | 190 | OUT("
"); 191 | 192 | OUT_SNIPPET_MD("sample_snippet.md"); 193 | 194 | /* --------------------------------------------------- */ 195 | 196 | OUT("

To see the source code look at render_snippets().

"); 197 | 198 | footer(); 199 | } 200 | 201 | 202 | /* -------------------------------------------------------------------------- 203 | Render page 204 | -------------------------------------------------------------------------- */ 205 | void render_performance() 206 | { 207 | header(); 208 | 209 | if ( G_cnts_today.req < 2 ) 210 | { 211 | OUT("

Refresh this page to let the server measure the average processing time.

"); 212 | } 213 | else /* server average is available only after the first request has finished */ 214 | { 215 | long long requests_daily = 86400000 / G_cnts_today.average; 216 | 217 | OUT("

Based on %s requests, the average rendering time is %0.3lf ms.

", INT(G_cnts_today.req), G_cnts_today.average); 218 | 219 | OUT("

It seems that this Node++ application could handle up to %s requests per day on your server.

", INT(requests_daily)); 220 | 221 | OUT("

Refresh this page a couple of times to obtain more accurate estimation.

"); 222 | } 223 | 224 | /* --------------------------------------------------- */ 225 | 226 | OUT("

To see the source code look at render_performance().

"); 227 | 228 | RES_DONT_CACHE; 229 | 230 | footer(); 231 | } 232 | 233 | 234 | 235 | 236 | /* -------------------------------------------------------------------------------- 237 | This is the main entry point for a request 238 | ------------------------------ 239 | Called after parsing HTTP request headers 240 | ------------------------------ 241 | If required (NPP_REQUIRED_AUTH_LEVEL >= AUTH_LEVEL_ANONYMOUS), 242 | the session is already created 243 | 244 | If valid ls cookie is present in the request or 245 | it's over existing connection that has already been authenticated, 246 | the session is already authenticated 247 | ------------------------------ 248 | Response status is 200 by default 249 | Use RES_STATUS() if you want to change it 250 | 251 | Response content type is text/html by default 252 | Use RES_CONTENT_TYPE() if you want to change it 253 | -------------------------------------------------------------------------------- */ 254 | void npp_app_main() 255 | { 256 | if ( REQ("") ) // landing page 257 | { 258 | render_landing(); 259 | } 260 | else if ( REQ("welcome") ) 261 | { 262 | render_welcome(); 263 | } 264 | else if ( REQ("snippets") ) 265 | { 266 | render_snippets(); 267 | } 268 | else if ( REQ("performance") ) 269 | { 270 | render_performance(); 271 | } 272 | else // page not found 273 | { 274 | RES_STATUS(404); 275 | } 276 | } 277 | 278 | 279 | /* -------------------------------------------------------------------------------- 280 | Called when application starts 281 | ------------------------------ 282 | Return true if everything OK 283 | ------------------------------ 284 | Returning false will stop booting process, 285 | npp_app_done() will be called and application will be terminated 286 | -------------------------------------------------------------------------------- */ 287 | bool npp_app_init(int argc, char *argv[]) 288 | { 289 | return true; 290 | } 291 | 292 | 293 | /* -------------------------------------------------------------------------------- 294 | Called when new anonymous session is starting 295 | ------------------------------ 296 | Return true if everything OK 297 | ------------------------------ 298 | Returning false will cause the session to be closed 299 | and npp_app_session_done() will be called 300 | Response status will be set to 500 301 | -------------------------------------------------------------------------------- */ 302 | bool npp_app_session_init() 303 | { 304 | return true; 305 | } 306 | 307 | 308 | #ifdef NPP_USERS 309 | /* -------------------------------------------------------------------------------- 310 | ******* Only for USERS ******* 311 | ------------------------------ 312 | Called after successful authentication (using password or cookie) 313 | when user session is upgraded from anonymous to logged in 314 | ------------------------------ 315 | Return true if everything OK 316 | ------------------------------ 317 | Returning false will cause the session to be downgraded back to anonymous 318 | and npp_app_user_logout() will be called 319 | -------------------------------------------------------------------------------- */ 320 | bool npp_app_user_login() 321 | { 322 | return true; 323 | } 324 | 325 | 326 | /* -------------------------------------------------------------------------------- 327 | ******* Only for USERS ******* 328 | ------------------------------ 329 | Called when downgrading logged in user session to anonymous 330 | Application session data (SESSION_DATA) will be zero-ed as well, 331 | unless NPP_KEEP_SESSION_DATA_ON_LOGOUT is defined 332 | -------------------------------------------------------------------------------- */ 333 | void npp_app_user_logout() 334 | { 335 | } 336 | #endif /* NPP_USERS */ 337 | 338 | 339 | /* -------------------------------------------------------------------------------- 340 | Called when closing anonymous session 341 | After calling this the session memory will be zero-ed 342 | -------------------------------------------------------------------------------- */ 343 | void npp_app_session_done() 344 | { 345 | } 346 | 347 | 348 | /* -------------------------------------------------------------------------------- 349 | Called when application shuts down 350 | -------------------------------------------------------------------------------- */ 351 | void npp_app_done() 352 | { 353 | } 354 | -------------------------------------------------------------------------------- /src/npp_app.h: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Node++ Web App 3 | Jurek Muszynski 4 | nodepp.org 5 | ----------------------------------------------------------------------------- 6 | Hello World Sample Node++ Web Application 7 | -------------------------------------------------------------------------- */ 8 | 9 | #ifndef NPP_APP_H 10 | #define NPP_APP_H 11 | 12 | 13 | #define NPP_APP_NAME "Sample Node++ App" 14 | #define NPP_APP_DOMAIN "example.com" 15 | #define NPP_APP_DESCRIPTION "Sample Node++ Web Application" 16 | 17 | 18 | /* List of additional C/C++ modules to compile. They have to be one-liners */ 19 | 20 | #define NPP_APP_MODULES "" 21 | #define NPP_SVC_MODULES NPP_APP_MODULES 22 | 23 | 24 | /* These are the most common switches */ 25 | /* The full list is at https://github.com/rekmus/nodepp/wiki/Node++-switches-and-constants */ 26 | 27 | /* uncomment to enable HTTPS */ 28 | //#define NPP_HTTPS 29 | 30 | /* uncomment to enable sessions */ 31 | //#define NPP_REQUIRED_AUTH_LEVEL AUTH_LEVEL_ANONYMOUS 32 | 33 | /* uncomment to enable MySQL connection */ 34 | //#define NPP_MYSQL 35 | 36 | /* uncomment to enable USERS module */ 37 | //#define NPP_USERS 38 | 39 | /* uncomment to enable CALL_ASYNC (multi-process) */ 40 | //#define NPP_ASYNC 41 | 42 | 43 | //#define NPP_DEBUG 44 | 45 | 46 | /* app session data */ 47 | /* accessible via SESSION_DATA macro */ 48 | 49 | typedef struct { 50 | char dummy; // replace with your own struct members 51 | } app_session_data_t; 52 | 53 | 54 | #endif /* NPP_APP_H */ 55 | -------------------------------------------------------------------------------- /src/npp_svc.cpp: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Node++ Web App 3 | Jurek Muszynski 4 | nodepp.org 5 | ----------------------------------------------------------------------------- 6 | Sample service module 7 | -------------------------------------------------------------------------- */ 8 | 9 | 10 | #include "npp.h" 11 | 12 | 13 | /* ======================================================================= */ 14 | /* =============================== SERVICES ============================== */ 15 | /* ======================================================================= */ 16 | 17 | 18 | /* -------------------------------------------------------------------------- 19 | Service 20 | -------------------------------------------------------------------------- */ 21 | void getCustomer() 22 | { 23 | OUT_HTML_HEADER; 24 | OUT("

%s

", NPP_APP_NAME); 25 | OUT("

Hello from getCustomer service!

"); 26 | OUT_HTML_FOOTER; 27 | } 28 | 29 | 30 | /* -------------------------------------------------------------------------- 31 | Service 32 | -------------------------------------------------------------------------- */ 33 | void getAccounts() 34 | { 35 | OUT_HTML_HEADER; 36 | OUT("

%s

", NPP_APP_NAME); 37 | OUT("

Hello from getAccounts service!

"); 38 | OUT_HTML_FOOTER; 39 | } 40 | 41 | 42 | /* ======================================================================= */ 43 | /* ========================== END OF SERVICES ============================ */ 44 | /* ======================================================================= */ 45 | 46 | 47 | 48 | /* -------------------------------------------------------------------------- 49 | Entry point 50 | -------------------------------------------------------------------------- */ 51 | void npp_svc_main() 52 | { 53 | if ( SVC("getCustomer") ) 54 | getCustomer(); 55 | else if ( SVC("getAccounts") ) 56 | getAccounts(); 57 | } 58 | 59 | 60 | /* -------------------------------------------------------------------------- 61 | Server start 62 | Return true if successful 63 | -------------------------------------------------------------------------- */ 64 | bool npp_svc_init() 65 | { 66 | return true; 67 | } 68 | 69 | 70 | /* -------------------------------------------------------------------------- 71 | Server stop 72 | -------------------------------------------------------------------------- */ 73 | void npp_svc_done() 74 | { 75 | } 76 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------