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, "Yes No
", 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[]="
";
52 |
53 | if ( REQ("") )
54 | OUT("
%s ", logo);
55 | else
56 | OUT("
", 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("");
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 |
--------------------------------------------------------------------------------