Compare commits

..

456 Commits

Author SHA1 Message Date
tomasz.sowa c32ed6ce28 update htmx to 2.0.9 2026-05-27 23:51:44 +02:00
tomasz.sowa 6631ba0641 update uikit to 3.23.10 2025-06-16 23:30:31 +02:00
tomasz.sowa 98320fe174 update uikit to 3.23.6 2025-04-29 09:22:41 +02:00
tomasz.sowa b8105cf9cc update uikit to 3.23.2 2025-03-05 12:44:15 +01:00
tomasz.sowa d7a93916e3 update uikit to 3.22.0 2025-01-13 18:47:59 +01:00
tomasz.sowa cec9dfc0e1 update htmx to 2.0.4 2024-12-21 01:28:39 +01:00
tomasz.sowa 893b3d9fff put a log about generated main content and frames 2024-12-03 10:57:41 +01:00
tomasz.sowa 7de9d1a819 put a log when a request job was not found 2024-12-03 10:34:17 +01:00
tomasz.sowa 8748a63532 update uikit to 3.21.16 2024-11-28 00:33:38 +01:00
tomasz.sowa 5eed025419 add trigger_htmx_event(...) methods to FunctionBase 2024-11-08 13:35:54 +01:00
tomasz.sowa f2e416b0f8 update htmx to 2.0.3 2024-10-09 19:50:27 +02:00
tomasz.sowa 1c7043fa3e update uikit to 3.21.13 2024-09-26 22:13:33 +02:00
tomasz.sowa 2bd4c5b35e print qt environment ids only when .qtcreator directory was created 2024-09-25 09:50:37 +02:00
tomasz.sowa f4481a84f4 fix: set a correct global working dir when generating a .clangd file 2024-09-24 23:41:35 +02:00
tomasz.sowa 4c740690e0 use a QTCreator environmentid and a profileid from a local installation
When creating QTCreator project files use local EnvironmentId
and default profile id. By default the environment id is stored
in ~/.config/QtProject/QtCreator.ini and the profile id in
~/.config/QtProject/qtcreator/profiles.xml.
2024-09-24 16:45:26 +02:00
tomasz.sowa 128c79cdc4 sort a makedepend output
Makefile.dep is sorted now - it's better when making a diff to a previous version.
2024-09-22 15:26:35 +02:00
tomasz.sowa 7082677b2f add a clangd/clangdall and qtcreator/qtcreatorall make targets
Add a clangd make target:
$ make clangd
This installs a .clangd file with configuration (includes/macros/compiler flags)
for the clandg language server.

Add a clangdall make target:
$ make clangdall
This installs a .clangd also in pikotools/ezc/morm and tito libraries.

Add a qtcreator make target:
$ make qtcreator
This installs a .qtcreator directory with QTCreator IDE project files.
In the QTCreator you can open a project by selecting the .qtcreator/winix.creator
file.

You can use 'make qtcreator' again to refresh .qtcreator/winix.files,
the rest of the project files will not be modified.

Add a qtcreatorall make target:
$ make qtcreatorall
This installs a .qtcreator directory also in pikotools/ezc/morm and tito libraries.
2024-09-22 11:43:26 +02:00
tomasz.sowa 257d8bbade change a database type to character varying(320) for a user.email field 2024-09-08 02:29:19 +02:00
tomasz.sowa a6ca71b131 check a length when validating an email
An email address has two parts:
 - the local part (before the "@") = max 64 characters
 - the domain part (after the "@") = max 255 characters
So maximum length is 64 + @ + 255 = 320 characters

https://www.rfc-editor.org/rfc/rfc5321.html#section-4.5.3.1
2024-09-08 02:05:43 +02:00
tomasz.sowa 8634716aa7 add FunctionBase::push_url_to(...) methods 2024-09-08 02:05:05 +02:00
tomasz.sowa 8a12629740 update htmx to 2.0.2 2024-08-19 15:32:56 +02:00
tomasz.sowa b07f2f7a59 remove unnecessary [end] tag 2024-08-12 02:25:47 +02:00
tomasz.sowa da90ef8e40 update uikit to 3.21.7 2024-07-20 15:20:09 +02:00
tomasz.sowa 197f684488 update htmx to 2.0.1 2024-07-20 15:15:03 +02:00
tomasz.sowa e63838faeb improve frontend of emacs, ckeditor, tinymce, nicedit, meta and env functions
Improves in emacs:
- use htmx to send content to the controller
- show txt and formatted_txt content in the second panel
- show two tabs if "tabs" winix parameter is used
- add an option to show either one or two panels
- correctly resize the editor window (F11) when two panels are shown

Improves in ckeditor:
- use htmx to send content to the controller
- do not check automatically for ckeditor update

Improves in tinymce/nicedit/meta/env:
- use htmx to send content to the controller

while here:
- change PascalCase to snake_case in meta/env controllers
- update CodeMirror editor to 5.65.16
- udpate Showdown (markdown to html converter) to 2.1.0
2024-07-20 15:13:27 +02:00
tomasz.sowa 89b37db48e update uikit to 3.21.6 2024-07-11 22:10:44 +02:00
tomasz.sowa 68e7f44a76 do not send content when there is a htmx redirect 2024-07-11 21:58:52 +02:00
tomasz.sowa 2490e2cc68 (ezc): generate only requested frames 2024-07-07 22:10:29 +02:00
tomasz.sowa b2f4c065ea remove a code to finish job requests when winix exits
Actually there was a bug and the code was not correctly waiting for the job requests.
2024-07-02 17:30:35 +02:00
tomasz.sowa 20b40597fd try harder to find the main template and a function's template
If there is no a template (main template and function template) for the current
language then try to find a template for a default language or for a first
available language.
2024-06-29 22:28:39 +02:00
tomasz.sowa 7df78838aa add assign_methods(...) functionality to the FunctionBase
in make_*() methods you can assing your controller methods in such a way:
  assign_methods(this,
    by_param(L"paramoption",                     &MyController::MyMethod3),
    by_param(L"paramoption1", L"paramoption2",   &MyController::MyMethod2),
    by_param_post(L"paramoption", L"postoption", &MyController::MyMethod1)
  );
2024-06-29 17:23:03 +02:00
tomasz.sowa b3bd9c6cf0 update htmx to 2.0.0 2024-06-27 16:37:05 +02:00
tomasz.sowa dadff8329e update uikit to 3.21.5 2024-06-27 11:46:45 +02:00
tomasz.sowa c30b7db041 add closing dialogs, redirecting and removing content functionality to the winix framework
add such new methods to FunctionBase:
- bool can_push_url_to_browser_history();
- void add_standard_models();
- void close_modal_dialogs();

- void prepare_doc_url(const wchar_t * local_url, pt::WTextStream & url);
- void prepare_doc_url(const wchar_t * local_url, std::wstring & url);
- std::wstring prepare_doc_url(const wchar_t * local_url = nullptr);
- std::wstring prepare_doc_url(const std::wstring & local_url);

- void redirect_to(const wchar_t * url, bool append_domain = true);
- void redirect_to(const std::wstring & url, bool append_domain = true);
- void redirect_to(const pt::WTextStream & url, bool append_domain = true);

- void redirect_to(const wchar_t * url, const wchar_t * frame_url, const wchar_t * dom_target);
- void redirect_to(const std::wstring & url, const std::wstring & frame_url, const std::wstring & dom_target);
- void redirect_to(pt::WTextStream & url, pt::WTextStream & frame_url, pt::WTextStream & dom_target);
- void redirect_to(pt::WTextStream & url, pt::WTextStream & frame_url, const wchar_t * dom_target);
- void redirect_to(const wchar_t * url, const wchar_t * frame_url, pt::WTextStream & dom_target);

- void retarged(const wchar_t * frame, const wchar_t * dom_target, const wchar_t * push_url = nullptr, const wchar_t * swap_algorithm = nullptr);
- void retarged(const std::wstring & frame, const std::wstring & dom_target, const std::wstring & push_url, const wchar_t * swap_algorithm = nullptr);
- void retarged(const wchar_t * frame, pt::WTextStream & dom_target, const wchar_t * push_url = nullptr, const wchar_t * swap_algorithm = nullptr);

- void remove_content(pt::WTextStream & dom_target, bool close_dialogs = false);
- void remove_content(const wchar_t * dom_target, bool has_postfix, long dom_target_postfix, bool close_dialogs = false);
- void remove_content(const wchar_t * dom_target, long dom_target_postfix, bool close_dialogs = false);
- void remove_content(const wchar_t * dom_target, bool close_dialogs = false);

- void update_content(const wchar_t * frame, pt::WTextStream & dom_target, bool close_dialogs = false);
- void update_content(const wchar_t * frame, const wchar_t * dom_target, bool has_postfix, long dom_target_postfix, bool close_dialogs = false);
- void update_content(const wchar_t * frame, const wchar_t * dom_target, long dom_target_postfix, bool close_dialogs = false);
- void update_content(const wchar_t * frame, const wchar_t * dom_target, bool close_dialogs = false);

while here:
- refactor PascalCase to snake_case in FunctionBase
- add start_request() and finish_request() methods to FunctionBase
- add has_*_access() methods to FunctionBase
- fix: FunctionBase::clear() method was not called if a request was assigned to a job
- add a WinixEzcHelper model
- allow to serialize a header if the header value is neither a string nor an integer
- refactor PascalCase to snake_case in functions: Emacs, Mkdir, Upload
2024-06-27 10:57:08 +02:00
tomasz.sowa 6aa100f12c WIP: remove the old database abstraction layer
remove such classes:
- DbBase
- DbConn
- DbTextStream
- Db

while here:
- remove: TextStream, SLog, TexTextStream
2024-06-22 18:03:54 +02:00
tomasz.sowa 5d457f3d4b (update to the new pikotools api): use a char32_t character as a main character when converting strings
Use a char32_t instead of a wchar_t type. This is needed on systems
where sizeof(wchar_t) is equal to 2.

This affects classes based on the pt::Stream such as Log and HtmlTextStream.
2024-06-01 00:33:15 +02:00
tomasz.sowa af0d34beb9 make depend 2024-05-31 00:32:56 +02:00
tomasz.sowa d122917f83 fix: correctly activate a user account 2024-05-27 18:22:47 +02:00
tomasz.sowa 612501217c update uikit to 3.20.9 2024-05-12 16:16:56 +02:00
tomasz.sowa d86ab8f9c0 update uikit to 3.20.8 2024-04-29 23:59:30 +02:00
tomasz.sowa 5a33563722 update htmx to 1.9.12 2024-04-28 19:45:16 +02:00
tomasz.sowa 1c850b12ec add a q_encode(...) method to misc 2024-04-28 16:14:57 +02:00
tomasz.sowa 140b4495df update jquery-file-upload to 10.32.0 2024-04-15 08:20:02 +02:00
tomasz.sowa 8b0b25ed0a fix: correctly flush logs when there was a db migration error 2024-04-15 06:38:23 +02:00
tomasz.sowa eacdcfb980 update htmx to 3.19.4 2024-04-11 05:52:09 +02:00
tomasz.sowa 132e7aa937 update htmx to 1.9.11 2024-03-20 03:15:05 +01:00
tomasz.sowa d9f3b69dde update uikit to 3.19.2 2024-03-20 03:07:17 +01:00
tomasz.sowa de753070a8 do not overwrite WINIX_INSTALL_DIR if already set 2024-03-11 16:59:45 +01:00
tomasz.sowa c1c6e6a588 install winix.so to a lib subdirectory 2024-03-11 16:12:13 +01:00
tomasz.sowa 291147503f update uikit to 3.19.1 2024-03-08 22:34:42 +01:00
tomasz.sowa dbf7dfab82 improve the startup help messages 2024-03-08 22:01:33 +01:00
tomasz.sowa b753464608 add some operators to the Log class
add:
virtual Log & operator<<(long double);
virtual Log & operator<<(float);
virtual Log & operator<<(long long unsigned int);
virtual Log & operator<<(unsigned int);
virtual Log & operator<<(short unsigned int);
virtual Log & operator<<(long long int);
virtual Log & operator<<(short int);
virtual Log & operator<<(bool);
virtual Log & operator<<(unsigned char);
virtual Log & operator<<(const pt::Stream &);
2024-02-13 22:29:22 +01:00
tomasz.sowa 544ef298aa update uikit to 3.18.3 2024-02-13 18:54:41 +01:00
tomasz.sowa 065a2d182f update htmx to 1.9.10 2024-01-16 23:17:14 +01:00
tomasz.sowa f4470ccbe7 allow to not set the res value from a plugin function
Add PluginInfo::has_res (bool, default true). If set to false by a plugin function
then the PluginInfo::res value is not taken into account when calculating how many plugins
have returned true or false.
2024-01-04 15:57:29 +01:00
tomasz.sowa 71ad4869ce fix: take into account hours when calculating a relative timezone dst 2023-12-27 16:25:54 +01:00
tomasz.sowa 09dc6782c8 fix: remember the first/last weekday flags from a timezone DST
If a date is given in a relative form with first/last parameters,
we must remember them in order to select the appropriate day
of the week from the appropriate year.
2023-12-24 14:55:39 +01:00
tomasz.sowa 0cebb2dc52 allow to use a first|last weekday name when defining a timezone dst
the format of a 'start' or 'end' field in a dst is:
MM-[first|last]:[monday|tuesday|wednesday|thursday|friday|saturday|sunday] HH:MM:SS
or just as beforehand: MM-DD HH:MM:SS

a sample timezone:
{
name = "tz_+01:00d"
id = "40"
offset_str = "+01:00"

dst = (

{
year = "2001"
has_dst = true
offset_str = "+01:00"
start  	   = "03-last-sunday 01:00"
end    	   = "10-last-sunday 01:00"
}

) # end of dst
}
2023-12-20 03:58:21 +01:00
tomasz.sowa 0724ca8eb3 update htmx to 1.9.9 2023-12-02 10:45:44 +01:00
tomasz.sowa 53991e54e1 update uikit to 3.17.11 2023-11-21 18:59:51 +01:00
tomasz.sowa df7ae1c6ea update uikit to 3.17.9 2023-11-16 23:10:51 +01:00
tomasz.sowa d1f5d9aa88 (winixcli): add a --sort-tables option
while here:
- add a fil_max_size filter for putting a space if the inner stream is greater than x characters
2023-11-09 10:57:11 +01:00
tomasz.sowa a54d70bed4 add a 422 Header status - Unprocessable Entity 2023-11-08 17:59:40 +01:00
tomasz.sowa bcde5c628a update uikit to 3.17.8 2023-11-07 03:56:45 +01:00
tomasz.sowa f241eb0a18 update htmx to 1.9.7 2023-11-06 04:43:20 +01:00
tomasz.sowa 74c0c936f6 make depend 2023-11-02 05:15:30 +01:00
tomasz.sowa 79babc916a add a Request::raw_post buffer
This buffer is used when a Function::NeedToCopyRawPost() method returned true.

while here:
- remove WINIX_POST_PARAMS and WINIX_RAW_POST_STRING plugin messages
2023-11-02 05:14:48 +01:00
tomasz.sowa a08bf9f804 update uikit to 3.17.5 2023-10-24 21:36:25 +02:00
tomasz.sowa 966577cd58 add QT Creator files to .gitignore 2023-10-22 23:38:38 +02:00
tomasz.sowa 8f20c8f67c update uikit to 3.17.1 2023-10-10 13:42:49 +02:00
tomasz.sowa f6c04b2d00 downgrade ckeditor to 4.22.1 as 4.23.0 requires a license key 2023-09-30 01:03:54 +02:00
tomasz.sowa 0474c76a3d update ckeditor to 4.23.0 2023-09-30 00:27:59 +02:00
tomasz.sowa 7a29a072be update jquery to 3.7.1 2023-09-30 00:13:28 +02:00
tomasz.sowa 24c2ecb8dd update htmx to 1.9.6 2023-09-30 00:06:57 +02:00
tomasz.sowa 7a1cea63bf update uikit to 3.17.0 2023-09-30 00:02:00 +02:00
tomasz.sowa e600aebaae add a RequestJobBase base class for requests jobs 2023-09-28 07:47:06 +02:00
tomasz.sowa 5e45ad3417 fix(Http): send body content for PATCH, DELETE and OPTIONS methods if exists
while here:
- use CURLOPT_UPLOAD instead of CURLOPT_PUT as the latter is depracated
2023-09-26 23:02:34 +02:00
tomasz.sowa 79e971cb76 parse the input body for the PUT and PATCH methods too 2023-09-15 10:04:25 +02:00
tomasz.sowa edee581ecf update uikit to 3.16.26 2023-08-31 02:01:47 +02:00
tomasz.sowa f7e077a7c5 add a TimeZone::PrintOffset(...) method 2023-08-29 15:02:37 +02:00
tomasz.sowa 6a9504fd5f update htmx to 1.9.5 2023-08-26 00:16:06 +02:00
tomasz.sowa 6d256e6512 fix: correctly set a Request::RunState::job_run flag to the background request
The flag should be set to the task.request and not to the cur->request.
The cur->request could have been already changed by the main thread.
2023-08-25 16:24:27 +02:00
tomasz.sowa cf383fa026 update easepick to 1.2.1 2023-08-21 13:31:02 +02:00
tomasz.sowa c86536d660 update htmx to 1.9.4 2023-08-09 22:45:59 +02:00
tomasz.sowa dba87d6213 update uikit to 3.16.24 2023-08-06 18:00:25 +02:00
tomasz.sowa 52f9d399ca add a Header::text_xml and text_xml_utf8 types 2023-07-31 17:31:22 +02:00
tomasz.sowa 7b7a962f19 update uikit to 3.16.23 2023-07-30 22:47:36 +02:00
tomasz.sowa c37722c29a update ckeditor to 4.22.1 and jquery to 3.7.0 2023-07-23 14:40:13 +02:00
tomasz.sowa ca509d3a86 update htmx to 1.9.3 2023-07-16 21:37:04 +02:00
tomasz.sowa bf79e46411 add a GetUTF8File(...) method with a pt::WTextStream & content to the misc 2023-07-04 22:59:57 +02:00
tomasz.sowa 08821eb440 update uikit to 3.16.22 2023-06-23 01:47:51 +02:00
tomasz.sowa d7878b5564 update uikit to 3.16.21 2023-06-14 03:13:44 +02:00
tomasz.sowa 0b52ae80dd update uikit to 3.16.19 2023-05-27 17:27:42 +02:00
tomasz.sowa 3e46d8b4b4 update uikit to 3.16.18 2023-05-23 14:48:28 +02:00
tomasz.sowa 1655ae3562 fix: correctly clear after a request when an exception has been thrown 2023-05-16 15:31:13 +02:00
tomasz.sowa dda325bbbf allow to compile with gcc 12 2023-05-13 16:12:02 +02:00
tomasz.sowa c326c2a095 update uikit to 3.16.17 2023-05-11 08:22:12 +02:00
tomasz.sowa bf386e2286 add a Http::set_smtp_ssl_mode(long mode) method for selecting the ssl mode 2023-05-10 14:00:33 +02:00
tomasz.sowa e822e13dc8 add support for sending emails in Http class 2023-05-10 09:01:30 +02:00
tomasz.sowa cc2c008bfd update htmx to 1.9.2 2023-05-08 06:01:20 +02:00
tomasz.sowa b8a8013d4c update uikit to 3.16.15 2023-04-15 23:50:18 +02:00
tomasz.sowa 12ed77aeb1 update htmx to 1.9.0 2023-04-13 21:45:39 +02:00
tomasz.sowa 7476048da6 make depend 2023-04-12 17:21:42 +02:00
tomasz.sowa 8a307790c0 update jquery to 3.6.4 2023-04-09 14:25:11 +02:00
tomasz.sowa a49b10ed2d allow to upload files from the ckeditor
while here:
- update ckeditor to 4.21.0
- add a Sourcedialog plugin to the ckeditor
2023-04-09 14:10:21 +02:00
tomasz.sowa 6a2da642b0 update uikit to 3.16.14 2023-04-08 09:48:12 +02:00
tomasz.sowa b836c77950 update uikit to 3.16.13 2023-04-06 07:52:03 +02:00
tomasz.sowa 2aa4eee20d update uikit to 3.16.12 2023-03-28 07:37:15 +02:00
tomasz.sowa 9ada82c4aa update uikit to 3.16.6 2023-03-12 13:50:50 +01:00
tomasz.sowa aa9b83f740 update uikit to 3.16.5 2023-03-10 19:26:26 +01:00
tomasz.sowa 4ddfd2cd3a update uikit to 3.16.3 2023-02-27 22:14:36 +01:00
tomasz.sowa d15f5e4fa4 update uikit to 3.16.1 2023-02-27 01:57:39 +01:00
tomasz.sowa 2e455f97ac add support for serializing to xml 2023-02-27 00:34:29 +01:00
tomasz.sowa f664cc1a53 update flatpickr to 4.6.13 2023-02-15 23:03:56 +01:00
tomasz.sowa ae505f3201 remove white characters from flatpickr js script 2023-02-15 22:57:41 +01:00
tomasz.sowa d5433cddf1 update jquery to 3.6.3 2023-02-14 13:05:45 +01:00
tomasz.sowa 52773a271c update ckeditor to 4.20.1 2023-02-14 12:26:36 +01:00
tomasz.sowa e9311989ab update uikit to 3.15.24 2023-02-14 00:21:16 +01:00
tomasz.sowa 7b63c01033 update uikit to 3.15.23 2023-02-02 10:43:32 +01:00
tomasz.sowa 5972b2bb39 update uikit to 3.15.22 2023-01-19 23:42:48 +01:00
tomasz.sowa f182978ea5 update htmx to 1.8.5 2023-01-19 12:49:03 +01:00
tomasz.sowa ebb8132808 update uikit to 3.15.21 2023-01-12 17:27:09 +01:00
tomasz.sowa 1bd1762258 update uikit to 3.15.20 2023-01-05 20:29:44 +01:00
tomasz.sowa 00b0e251f4 update uikit to 3.15.19 2022-12-28 10:05:03 +01:00
tomasz.sowa 14e32df8c9 fix(Http): use uninitialize_curl() in begin() method 2022-12-23 04:23:38 +01:00
tomasz.sowa aa938f05ca add methods to set a client certificate/key and the CA in the Http class 2022-12-21 14:09:31 +01:00
tomasz.sowa 4583ab28ed add primary keys definition to migration rules 2022-12-19 19:13:45 +01:00
tomasz.sowa 9c0cd6eb5e add Http::set_ssl_version() to set the available TLS version to use 2022-12-19 14:17:30 +01:00
tomasz.sowa 32c30cf536 update uikit to 3.15.18 2022-12-13 15:10:18 +01:00
tomasz.sowa a8b7a9e122 update uikit to 3.15.17 2022-12-08 12:26:50 +01:00
tomasz.sowa d07ff5b881 update uikit to 3.15.15 2022-12-05 06:57:51 +01:00
tomasz.sowa 66fae598c2 parse winixjson_* environment variables as json config options 2022-11-25 13:30:51 +01:00
tomasz.sowa 589e889822 update uikit to 3.15.14 2022-11-24 22:14:55 +01:00
tomasz.sowa 89249f1297 add Http::fetch(...) methods 2022-11-18 16:38:03 +01:00
tomasz.sowa 2bd56c87e4 update uikit to 3.15.13 2022-11-17 23:07:40 +01:00
tomasz.sowa 204688464e rename Http:put() to Http:post() and add a separate Http:put() 2022-11-17 02:47:00 +01:00
tomasz.sowa 1d0956abab update to the new pikotools api: change converting functions to the snake case 2022-11-14 03:22:48 +01:00
tomasz.sowa c2013ff47f do not use the ezc engine when sending a static file
while here:
- in send_file_mode=0 return a 404 if a static file was not correctly read
2022-11-14 00:54:50 +01:00
tomasz.sowa 624bf47c8d update htmx to 1.8.4 2022-11-07 21:01:18 +01:00
tomasz.sowa cdd395efa5 update uikit to 3.15.12 2022-11-07 20:54:41 +01:00
tomasz.sowa 47f6e2234c update htmx to 1.8.2 2022-10-26 12:44:48 +02:00
tomasz.sowa 1648092cd5 update uikit to 3.15.11 2022-10-26 12:33:11 +02:00
tomasz.sowa 99fbf6ca27 add WINIX_STARTED plugin message 2022-10-19 14:26:34 +02:00
tomasz.sowa f050fc2316 make more virtual functions is BaseThread 2022-10-19 14:26:18 +02:00
tomasz.sowa 1015baf111 make depend 2022-10-17 08:16:45 +02:00
tomasz.sowa 04f0a2f808 add MoveHelper for moving winix files - copied from Mv function 2022-10-17 08:16:28 +02:00
tomasz.sowa 1da240afb9 check notitle parameter in upload winix function 2022-10-17 08:15:27 +02:00
tomasz.sowa 77a00f5989 fix: return a correct status from Dirs::AddDirectory() 2022-10-17 08:13:20 +02:00
tomasz.sowa f3d6494ae5 add the easepick - a date and time picker 2022-10-14 01:56:44 +02:00
tomasz.sowa 8edd0ef07a fix: use the base_url as a domain when creating a session cookie if a cookie domain is empty 2022-09-28 19:28:17 +02:00
tomasz.sowa 3855ea9fa7 add /usr/include/postgresql to includes paths 2022-09-23 19:53:26 +02:00
tomasz.sowa a81839fd9c make depend 2022-09-23 18:34:08 +02:00
tomasz.sowa 03035f038f use PT_HAS_MORM_LIBRARY macro when building too
while here:
- use some conditionals in the Makefile
2022-09-23 18:34:08 +02:00
tomasz.sowa baa870edbd update to uikit 3.15.10 2022-09-22 10:38:31 +02:00
tomasz.sowa c8bc23312b update uikit to 3.15.8 2022-09-16 13:29:25 +02:00
tomasz.sowa d5e6fb7c54 add Access-Control-Expose-Headers to normal cors requests too 2022-09-14 12:48:20 +02:00
tomasz.sowa 6138497fe0 change how origin header is treated
Now check whether the origin is in allowed_origins table,
and if not check allow_all_origins config parameter.

While here:
- add are_cors_preflight_requests_available - if true then preflight
  requests are available (default false)
2022-09-09 01:01:39 +02:00
tomasz.sowa 05ecac8426 add support for more cookie flags in Request::AddCookie() method
changed in config options:
- renamed: http_session_id_name to session_cookie_name
- add config options: session_cookie_path, session_cookie_domain, session_cookie_same_site,
  session_cookie_http_only, session_cookie_secure
2022-09-08 05:40:44 +02:00
tomasz.sowa 222a1c8a1f refactor the algorithm for testing the cors
while here:
- send cors headers even if the status is 404
- add: access_control_expose_headers config option - list of additional headers sent in Access-Control-Expose-Headers
- add: access_control_allow_credentials config option - if true return Access-Control-Allow-Credentials header equal "true"
2022-09-08 03:12:44 +02:00
tomasz.sowa 04164ff967 add Access-Control-Allow-Credentials for simple requests too 2022-09-07 15:25:48 +02:00
tomasz.sowa 9f64692ede set Access-Control-Allow-Credentials if available 2022-09-07 14:46:29 +02:00
tomasz.sowa 8b9ad5d079 make depend 2022-09-01 07:34:39 +02:00
tomasz.sowa bff435db9a add WINIX_SAVE_FILELOG plugin message 2022-09-01 07:34:10 +02:00
tomasz.sowa e09a93bd72 update uikit to 3.15.6 2022-09-01 03:39:02 +02:00
tomasz.sowa e378fcfe3b remove not used variables from Request 2022-08-31 21:33:54 +02:00
tomasz.sowa a7a338f28e fix(Request): allow to prepare integer headers 2022-08-31 21:25:14 +02:00
tomasz.sowa a19158cb62 add config options for testing the Origin header in cors requests
- allow_all_cors_origins - whether or not to allow all origins
- allowed_cors_origins - a list of allowed origins (used if allow_all_cors_origins is false)
2022-08-31 20:42:42 +02:00
tomasz.sowa 778ed01a55 make depend 2022-08-30 01:52:20 +02:00
tomasz.sowa 217f42b7c6 add support for preflight requ (cors) 2022-08-30 01:52:02 +02:00
tomasz.sowa a34db6505d move some methods from App to Request
methods moved: SetEnv(), ReadEnvVariables(), ReadEnvRemoteIP(), CheckSSL(), SetSubdomain()

while here:
- add the rest of http methods: put, connect, trace, patch
2022-08-29 19:20:41 +02:00
tomasz.sowa 7dc117da5e update UIkit to 3.15.5 2022-08-28 16:09:43 +02:00
tomasz.sowa b1441366f4 add Http::verify_ssl(bool verify) method 2022-08-25 05:16:23 +02:00
tomasz.sowa c730b85629 make depend 2022-08-22 16:04:10 +02:00
tomasz.sowa d3a440fa0a add Request::AddPostVar(pt::Space & space, const wchar_t * name) 2022-08-22 16:03:07 +02:00
tomasz.sowa 5f77ce619e make depend 2022-08-20 00:31:30 +02:00
tomasz.sowa 5dd34c802e add Request::job_second_id 2022-08-20 00:31:10 +02:00
tomasz.sowa 3609d94c09 update uikit to 3.15.3 2022-08-15 12:36:54 +02:00
tomasz.sowa 5dc00e95e7 make depend 2022-08-14 12:55:03 +02:00
tomasz.sowa e88615226b add Http::allow_redirects(bool allow_redirects) method 2022-08-13 20:00:15 +02:00
tomasz.sowa ca1a854fd1 fix: use CURLOPT_POSTFIELDSIZE_LARGE to tell libcurl of the post content size 2022-08-13 17:15:48 +02:00
tomasz.sowa ceb5336ca1 add support for OPTIONS http method 2022-08-11 08:04:40 +02:00
tomasz.sowa f651df6e1f update htmx to 1.8.0 2022-08-10 12:42:24 +02:00
tomasz.sowa 6266eac729 use std::wstring_view in SessionIdManager::DecodeToken(...) method 2022-08-10 12:42:16 +02:00
tomasz.sowa de972de948 fix: remove sourcedialog plugin from ckeditor 2022-08-06 04:21:53 +02:00
tomasz.sowa 55f48e4f3a update jquery to 3.6.0
while here do a check: [if not winix_has_jquery]...[end]
2022-07-31 02:03:39 +02:00
tomasz.sowa 39ab07508f update translations 2022-07-30 18:41:59 +02:00
tomasz.sowa 968660e8ca fix: set correctly request->session
The session cookie was not created because request->session pointed at
a temporary session.

While here:
- do some cleaning in App
- set request->mount too
- add fcgi_cannot_create_request_delay to the config
- fix: in mailregister plugin get model_connector from env (and not from the request)
2022-07-30 18:37:50 +02:00
tomasz.sowa 4b46ba1fe3 update uikit to 3.15.1 2022-07-30 15:37:52 +02:00
tomasz.sowa a164e6e21e fix: remove not needed Http::clear() 2022-07-30 04:14:04 +02:00
tomasz.sowa 82281b4363 add a debug mode - fill a Space structure with some info from CURLOPT_DEBUGFUNCTION
while here:
- allow to set headers from a string
- add a seek function (CURLOPT_SEEKFUNCTION)
2022-07-30 04:00:35 +02:00
tomasz.sowa 9d8d35b64f save logs after a job has finished 2022-07-30 03:35:00 +02:00
tomasz.sowa 33f6a9a213 make depend 2022-07-30 03:33:45 +02:00
tomasz.sowa e5ed1d6ae8 fix: do not use cur if login winix function if config.use_internal_loggin_mechanism is false
In the login winix function cur pointer will be null if config.use_internal_loggin_mechanism
is false, in such a case those objects are not registered as winix functions
but we have a public api
(the public api should be moved somewhere e.g. make a service layer)
2022-07-27 01:25:49 +02:00
tomasz.sowa 9e6a5b2d37 add use_internal_session_mechanism and use_internal_loggin_mechanism config options 2022-07-26 21:54:33 +02:00
tomasz.sowa c85a724fec fix(SessionIdManager): take a correct algorithm when decoding a token 2022-07-26 21:09:44 +02:00
tomasz.sowa 2e8f4d1a26 allow the SessionIdManager to use only two keys 2022-07-26 05:18:42 +02:00
tomasz.sowa 522b57ade4 fix(Jobs): change request state to prepare_to_finish in case of an error 2022-07-25 18:37:39 +02:00
tomasz.sowa d4da6aa518 let System::PutUrlProto takes a stream by a reference to pt::Stream 2022-07-25 18:36:28 +02:00
tomasz.sowa 979ef907fe allow a request to be processed in a job
Now we allow a request to be passed into a job queue,
and after the job finishes the request is passed into
a controller again. In order to achieve this we have
a requests queue in System, when we put a request
to the job this Request structure is preserved in the
queue and for a new request a new Request is added to
the queue.

while here:
- remove App::Lock()/Unlock(), use scoped locking
- fix: Plugin now has a Call method which takes ModelConnector
  and a logger (used in multithreaded environment)
- BaseThread has a main_model_connector pointer
  to the main (from the main thread) model connector
- the FastCGI structure fcgi_request moved from App to Request
- some methods for handling requests moved from App to Request
- small refactoring in main.cpp
- add Http class (a http client)
2022-07-25 14:21:21 +02:00
tomasz.sowa b2d92b85a0 make depend 2022-07-11 17:52:05 +02:00
tomasz.sowa 8d6d0ddbf8 update to the new morm::Finder interface 2022-07-11 17:51:50 +02:00
tomasz.sowa 8da76134ce make depend 2022-07-05 19:52:40 +02:00
tomasz.sowa 179daf743e make depend 2022-07-03 14:25:53 +02:00
tomasz.sowa bcb009b606 print version information if running with -v parameter 2022-07-03 14:25:23 +02:00
tomasz.sowa 327c215e5d add LICENSE file 2022-07-03 12:17:26 +02:00
tomasz.sowa b484071818 print components versions in uname winix function 2022-07-03 12:17:14 +02:00
tomasz.sowa 31e826d893 put a log message before opening the FastCGI connection socket
FCGX_OpenSocket will call exit() if there was a problem with creating the socket.
2022-06-27 20:52:09 +02:00
tomasz.sowa e29f912358 add core/postparser.cpp with implementation from core/postparser.h
now we can remove -lfcgi from winix in winixd/Makefile
2022-06-26 06:45:53 +02:00
tomasz.sowa 26226de865 global winixd/Makefile uses now 'find' for looking for *.cpp files
and we don't need Makefiles in subdirectories anymore (except plugins)
2022-06-26 06:22:27 +02:00
tomasz.sowa 56d87c4410 update uikit to 3.14.3 2022-06-19 16:06:16 +02:00
tomasz.sowa ebfa5f7405 do not try to load sessions if session_file config parameter is empty 2022-05-31 07:49:51 +02:00
tomasz.sowa ba16cf41fe move the javascript for autodeleting to a separate winix.js file 2022-05-30 05:35:49 +02:00
tomasz.sowa 01c10bad0e add use_antispam_mechanism_for_not_logged_users config option 2022-05-30 05:35:05 +02:00
tomasz.sowa 7d1fb3c04e remove Request::post_tab and add Request::http_status
Instead of Reqest::post_tab we use now Request::post_in (pt::Space).

Request::http_status will be used instead Request::status,
but at the moment is not changed in all places.
Request::status has been marked as depracated.

While here:
- Check for root dir in App and not in FunctionParser,
let FunctionParser only log the root dir.
- Read post variables after parsing url parameters,
this allows winix functions to set limits
for post input.
- Set limits when parsing input json format, new
options added to config: post_max_object_items, post_max_table_items,
post_max_all_items, post_max_nested_objects.
There are similar options in each winix function (they are in
FunctionBase).
- Some refactoring in App.
- Add config option: log_whole_http_post if true
then the whole parsed post input is logged.
- Add config option: post_json_max - max length of input stream
for parsing json.
- Add config option: templates_request_status, default request_status.html
this is an ezc template used as [content] when the request status
is not 200_ok.
- Fix: Sort winix function didn't show items to sort (fix and do some
refactoring as well)
- Properly sort items in: ImgCrop, Ls, Sort, Upload
- Remove ezc templates: err_404.html, err_per_denied.html - now
request_status.html is used.
2022-05-30 01:29:18 +02:00
tomasz.sowa 9e222f5b80 do not print white characters in log for the first migration 2022-05-28 06:10:39 +02:00
tomasz.sowa 3b5658ff8f fix: correctly sort post variables when they have the same name
In PostParser we add some prefix with a number if the name of a variable is the same,
we should use zero padding for the number to be correctly sorted.
2022-05-28 06:07:38 +02:00
tomasz.sowa 5e89c4004a make depend 2022-05-26 00:35:24 +02:00
tomasz.sowa 9602c28d96 allow lang ezc function get more than one parameter 2022-05-11 14:22:46 +02:00
tomasz.sowa 0fd680b496 update uikit to 3.14.1 2022-05-08 17:00:26 +02:00
tomasz.sowa 37d3a44b24 update uikit to 3.14.0 2022-04-30 20:23:37 +02:00
tomasz.sowa da2dec447b allow to specify how many times we can try to connect to the database at startup
add config options:
db_startup_connection_max_attempts - default 0 (infinite)
db_startup_connection_attempt_delay - delay in seconds between attempts (default 5)

BREAKING CHANGE: WINIX_PLUGIN_INIT plugin message requires to set result status,
you have to set the result status to true (env.res) if your
plugin was initialized correctly, otherwise winix will not start
2022-04-29 06:17:16 +02:00
tomasz.sowa c6c50a5d23 allow to use host database connection parameter
Add config option:
db_host (default empty) - name of host to connect to
2022-04-28 06:12:44 +02:00
tomasz.sowa 98c1e8daad allow to not change fast cgi socket permissions
New config options:
fcgi_set_socket_chmod (bool) - default true
fcgi_set_socket_owner (bool) - default true
2022-04-27 23:31:50 +02:00
tomasz.sowa f99191aa6f make depend 2022-04-26 23:46:57 +02:00
tomasz.sowa df04075f1c add methods to Request for adding and removing parameters
Added methods:
void AddParam(const std::wstring & param_name, const std::wstring & param_value);
void AddParam(const wchar_t * param_name, const wchar_t * param_value);
void RemoveParam(const wchar_t * param_name);
void RemoveParam(const std::wstring & param_name);

This is only temporarily, we will be using the pt::Space structure in the future.
2022-04-26 23:41:56 +02:00
tomasz.sowa 3d2a635e34 fix: use TextStreamBase::to_str() instead of to_string() 2022-04-25 22:05:34 +02:00
tomasz.sowa aad5db9a6a let Functions::Add() returns info whether the functions/controller has been added 2022-04-25 16:35:14 +02:00
tomasz.sowa 43ebbdaa33 add WINIX_PLUGIN_QUIT and WINIX_QUIT plugins messages
While here:
- rename WINIX_CLOSE to WINIX_PREPARE_TO_CLOSE
2022-04-25 16:34:26 +02:00
tomasz.sowa 92c7f90b95 fix: correctly propagate a migration status when the migration failed 2022-04-25 15:19:02 +02:00
tomasz.sowa aae93d018b allow to use db_hostaddr, db_port or db_conn_string config parameters to connect to PostgreSQL 2022-04-20 18:37:52 +02:00
tomasz.sowa 7a115a3970 fix(Log): treat pt::Log::Manipulators as enum and not as int 2022-04-16 21:52:53 +02:00
tomasz.sowa 64e5114947 allow to read environment variables as config parameters
Environment variables must be prefixed with winix_ to be loaded by winix.
The winix_ prefix is then removed and the key value converted to lowercase.

Sample:
evn WINIX_MY_OPTION=TEST123test winix -c config_file

This will add my_option to the config with value TEST123test.
Environment variables are read last so they will overwrite the values
from the configuration files.
2022-04-16 21:50:23 +02:00
tomasz.sowa 4f8b5e649a recognize startup parameters
Usage: winix [options]
  -c             : a path to the config file
  --config       : a path to the config file
  -h             : print usage information
  --help         : print usage information
  -?             : print usage information

While here:
- let it be possible to parse multiple configs,
- fix: some error messages were not printed at startup.
2022-04-16 18:38:30 +02:00
tomasz.sowa e0d9989d74 fix(Item): id should be of type serial 2022-04-11 23:27:49 +02:00
tomasz.sowa 0fe680ef4a fix: migration to version 2 in User model 2022-04-11 23:19:30 +02:00
tomasz.sowa e182c0a21b fix: create core schema before making a first select request
Migration uses Finder to get the current table version.
2022-04-11 23:11:00 +02:00
tomasz.sowa c8edd241d5 create core schema as a first migration 2022-04-11 20:57:49 +02:00
tomasz.sowa a544ccd1a7 fix: User model initial column name: aenv 2022-04-11 20:44:58 +02:00
tomasz.sowa 7df2205b40 update flatpickr to 4.6.11 2022-04-05 17:37:24 +02:00
tomasz.sowa 265e843d02 update uikit to 3.13.7 2022-04-05 16:59:57 +02:00
tomasz.sowa 22a8a97389 update htmx to 1.7.0 2022-04-05 16:53:46 +02:00
tomasz.sowa bb74f2a423 update uikit to 3.11.1 2022-02-08 14:13:33 +01:00
tomasz.sowa 2033168db2 Merge branch 'cli' into ajax 2022-02-08 14:01:50 +01:00
tomasz.sowa e377f144fd fix: do not send headers again after binary content 2022-02-04 18:46:46 +01:00
tomasz.sowa 234ebf8ce8 change HtmlTextStream iterators type to pt::WTextStream::iterator 2022-02-03 20:57:38 +01:00
tomasz.sowa 09cf3c9fa9 add some comments in AcceptBaseParser 2022-02-02 18:34:56 +01:00
tomasz.sowa df32899581 move AcceptEncodingParser to utils 2022-02-02 18:34:22 +01:00
tomasz.sowa 33e8df11c5 parse Accept-Language header to Request::accept_languages table 2022-02-02 18:20:32 +01:00
tomasz.sowa 75daf37bbd improve AcceptBaseParser parsing algorithm
remove AcceptParser - not needed now, AcceptBaseParser can prepare a table now
2022-02-02 17:58:27 +01:00
tomasz.sowa d0d2cfb22c move AcceptBaseParser to utils directory 2022-02-02 17:11:46 +01:00
tomasz.sowa f7b5ac0dc8 change the way how winix answer is created
Now we can return ezc content and models serialized in the same json structure,
Xml and Csv are not implemented yet.
Ezc frames are returned in 'ezc_frames' field.
Main ezc stream is returned in 'main_stream' field.
Frame url parameter can take more than one frame (names separated by commas).
Honor Accept http header (AcceptParser).

Samples:
--------
http://domain.tld/dir/controller
returns html answer from the main ezc stream

http://domain.tld/dir/controller/container:raw
returns html answer from the main ezc stream (the same as above)

http://domain.tld/dir/controller/frame:abc
returns "abc" frame as html

http://domain.tld/dir/controller/container:json
returns all serialized models to json and no ezc streams

http://domain.tld/dir/controller/container:xml
returns all serialized models to xml and no ezc streams (not implemented yet)

http://domain.tld/dir/controller/container:json/frame:abc,xyz
returns all serialized models to json and two frames in 'ezc_frames' object

http://domain.tld/dir/controller/container:json/all_frames
returns all serialized models to json and all frames in 'ezc_frames' object

http://domain.tld/dir/controller/container:json/main_stream
returns all serialized models and the main ezc stream in 'main_stream' field

http://domain.tld/dir/controller/container:json/main_stream/all_frames
returns all serialized models to json, all frames and the main stream
2022-02-01 18:44:23 +01:00
tomasz.sowa 227dd923d6 fix: correctly escape ezc stream to json/xml/csv 2022-01-28 15:54:11 +01:00
tomasz.sowa f6cb9a8aed set correct timetable dst for 'Sarajevo, Skopje, Warsaw, Zagreb'
year: 2022 and 2023
2022-01-26 22:34:13 +01:00
tomasz.sowa b615dc7e6e add cmp ezc function 2022-01-22 04:35:42 +01:00
tomasz.sowa 944560dd2b update uikit to 3.10.1 2022-01-19 15:47:11 +01:00
tomasz.sowa 1d6d29e24d add winixcli/src/winix to .gitignore 2022-01-18 19:46:12 +01:00
tomasz.sowa ff8e9e6b32 start working on winixcli
winixcli can now read a PGModeler file
and is able to generate a template through ezc

winixcli parameters:
--input-mode pgmodeler (only one parameter at the moment)
--input-file file (pgmodeler file)
--templates-dir dir_path (a path to templates directory)
--template file (template file)
2022-01-18 19:40:57 +01:00
tomasz.sowa 557555c4b3 htmx updated to 1.6.1 2021-12-08 15:19:35 +01:00
tomasz.sowa f8e1037476 uikit updated to 3.9.4 2021-11-26 21:51:01 +01:00
tomasz.sowa 35cb54324f added a new item content type: markdown
- emacs editor has an option to select markdown, now it has two planes: one for content editing and the other to show preview
- CodeMirror editor updated to 5.64.0
- to convert markdown to html we use showdown https://github.com/showdownjs/showdown (conversion is done on the client side)
2021-11-26 21:49:21 +01:00
tomasz.sowa 119497bb01 added winix_frame_is ezc winix function 2021-10-24 22:27:52 +02:00
tomasz.sowa dfd6475a81 uikit updated to 3.7.6 2021-10-24 22:27:35 +02:00
tomasz.sowa d6d5236a03 added fil_json_escape filter 2021-10-21 13:42:41 +02:00
tomasz.sowa a327a26bd5 added winix_uikit_version parameter to index_head_adder.html 2021-10-13 23:48:30 +02:00
tomasz.sowa d5ebb7ca12 changed the way how the request's answer is created,
now winix can return json, xml, csv from out_main_stream or from frames and json from models

removed from Request:
  bool send_bin_stream
  bool return_json
  bool return_info_only
  pt::Space info
  bool page_generated
  bool out_main_stream_use_html_filter
  bool out_streams_use_html_filter

added to Request:
  enum AnswerSource
  enum AnswerContainer
  AnswerSource answer_source
  AnswerContainer answer_container
  bool use_ezc_engine
  std::wstring frame
  bool send_all_frames
  bool use_html_filter

added to Config:
 // the name of the url parameter for returning all frames, e.g. https://domain.tld/mydir/myfunction/allframes
 // default: allframes
 std::wstring request_all_frames_parameter;

 // the name of the root element when serializing request answer to xml
 // default: winix
 std::wstring xml_root;

algorithm (the whole algorithm is described in core/request.h):
at the beginning of a request winix sets
   answer_source to models
   answer_container to text
   use_ezc_engine to true

next answer_container and use_ezc_engine can be changed in the following way:

1. winix will look for 'Accept' http header and depending on the header winix will set:
   (not implemented yet)

             Accept | answer_container | use_ezc_engine
	     ------------------------------------|-----------------
	     application/json | json             | false
	      application/xml | xml              | false
	              text/csv | csv              | false

2. next answer_container is set depending on 'container' url parameter
       container | answer_container
 ---------------------------------------------------------
     not present | don't change the value
            text | text
            json | json
             xml | xml
             csv | csv

use_ezc_engine is set depending on 'answer' url parameter:
          answer | use_ezc_engine
 ---------------------------------
     not present | don't change the value
            html | true
            data | false

if 'answer' is html then we take into account two more parameters:
 frame: frame_name (empty default) - if set then winix returns this specific frame
 allframes: (if present then winix returns all frames)
2021-10-13 01:27:14 +02:00
tomasz.sowa 3e46c5674c htmx updated to 1.6.0 2021-10-08 17:44:34 +02:00
tomasz.sowa c4b5565995 don't check for request->is_htmx_request for sending frames, check only "frame" url paremeter
added config parameter: request_frame_parameter, default: "frame"
2021-10-08 03:08:11 +02:00
tomasz.sowa 3f5eabeaa1 uikit updated to 3.7.5 2021-10-07 05:02:24 +02:00
tomasz.sowa 9b8e48e7b2 added static libraries: clocklet (timepicker), flatpickr and litepicker (data pickers) 2021-10-07 04:42:46 +02:00
tomasz.sowa c3122fb82f added [lang] ezc function for returning a localized string 2021-10-07 04:41:06 +02:00
tomasz.sowa 1741597d52 uikit updated to 3.7.4 2021-09-27 02:53:16 +02:00
tomasz.sowa 9c5c74ba84 added: setting a correct mime type for static files - using magic library
added: std::wstring file_mime_type to ItemContent - a mime type for static file
added: Header (core/header.h) - there will be header names defined, at the moment only content_type
added: FuncionsBase::Finish() - it is called at the end when the winix finishes
2021-09-22 00:23:25 +02:00
tomasz.sowa 26ed7b80be changed values for send_file_mode config parameter:
0 - winix will read the content of the file and send it back to the webserver
  1 - winix will use send_file_header header with a full path to the file
  2 - winix will use send_file_header header with a relative path to the file
2021-09-17 03:35:56 +02:00
tomasz.sowa 55ac9a61ed added possibility to send static files to nginx via X-Accel-Redirect header
added to config:
int send_file_mode;
    // 0 - full path to a file in send_file_header header
    // 1 - relative path to a file in send_file_header (need http_send_file_relative_prefix set) (used for nginx)
std::wstring send_file_header;
    // default: X-SENDFILE
    // for Apache set: X-SENDFILE
    // for Lighttpd set: X-LIGHTTPD-send-file
    // for Nginx set: X-Accel-Redirect
std::wstring send_file_relative_prefix;
    // relative prefix used for sending static files if send_file_mode is 1
    // default: "upload-files-internal"
2021-09-15 20:28:34 +02:00
tomasz.sowa 7673264fe1 make depend 2021-08-12 21:57:03 +02:00
tomasz.sowa 42dc43b036 added WINIX_MAKE_DATABASE_MIGRATION plugin message for making migrations from plugins 2021-08-11 22:18:14 +02:00
tomasz.sowa ef22d951a0 fixed: base class of System should be derived as public 2021-08-10 22:06:53 +02:00
tomasz.sowa e95dc834a3 uikit updated to 3.7.2 2021-08-07 21:23:47 +02:00
tomasz.sowa b424988d1b updated to the new pikotools api (api2021): HTMLFilter renamed to HTMLParser
added to config: int html_filter_white_char_mode;
  how white characters between html tags are treated
  0 - WHITE_MODE_ORIGIN - they are copied from input to output
  1 - WHITE_MODE_SINGLE_LINE - new line characters are removed
  2 - WHITE_MODE_TREE - try to create a tree (some kind of pretty printing)
  default: 2
2021-08-07 02:16:48 +02:00
tomasz.sowa 22134b6cc0 commented some method calls to html_filter 2021-07-26 03:54:02 +02:00
tomasz.sowa f861c0761e make depend 2021-07-17 13:57:39 +02:00
tomasz.sowa 1899d5ee17 BBCODEParser has been moved to pikotools library 2021-07-17 13:56:37 +02:00
tomasz.sowa 17bd48ece3 HTMLFilter has been moved to pikotools library 2021-07-17 13:42:04 +02:00
tomasz.sowa c5c02d7f44 HtmlTextStream has now pt::Stream as a based class and uses pt::WTextStream as a buffer 2021-07-16 18:17:57 +02:00
tomasz.sowa ba6159964b htmx updated to 1.5.0 2021-07-16 13:16:02 +02:00
tomasz.sowa b834971f5e uikit updated to 3.7.1 2021-07-16 12:28:38 +02:00
tomasz.sowa 9dc15d536c Makefile: removed macros: EZC_GENERATOR_HAS_PT_STREAM and EZC_GENERATOR_HAS_WINIX_STREAM 2021-07-13 01:49:58 +02:00
tomasz.sowa 2e45cb6ac9 updated to the new ezc api (Generator has three additional parameters now) 2021-07-13 01:46:07 +02:00
tomasz.sowa 2dcfeaa688 fixed: in Item do_migration_to_3(...) admin meta was called admin_meta (not meta_admin) 2021-07-07 01:04:48 +02:00
tomasz.sowa 9d65d931d0 moved some ezc functions from templates/item.cpp to Item and ItemContent
removed: templates/item.cpp
updated: some html templates which use [item] or [item_tab]
removed some old html templates: item_info.html and itam_tab_info.html
2021-07-06 21:52:29 +02:00
tomasz.sowa 746aa41111 renamed: ItemContent::meta_admin -> ItemContent::admin_meta 2021-07-03 01:18:28 +02:00
tomasz.sowa 175dd17416 added request.last_item ezc function 2021-07-03 01:14:53 +02:00
tomasz.sowa 619936c12e make depend 2021-07-01 23:35:08 +02:00
tomasz.sowa 732144df01 updated to the new morm api - models methods which take 'morm::ModelWrapper ** model_wrapper' now take 'morm::Wrapper & wrapper' 2021-07-01 23:34:49 +02:00
tomasz.sowa df3f04a951 added to misc: timespec_to_stream_with_unit() for printing times either is seconds or miliseconds 2021-06-30 16:30:11 +02:00
tomasz.sowa 0f78968579 updated ticket plugin to the new ezc api (child spaces were removed) 2021-06-29 23:42:57 +02:00
tomasz.sowa 66173c7a31 removed old meta ezc functions from gallery plugin 2021-06-28 21:34:41 +02:00
tomasz.sowa 3f934d9aec removed old meta ezc functions from menu plugin 2021-06-28 21:34:22 +02:00
tomasz.sowa df0cc131fe fixed in thread winix function: answers were not sorted correctly 2021-06-28 21:33:33 +02:00
tomasz.sowa ba60f9da8a updated group plugin to the new pikotools api (child spaces were removed) 2021-06-28 20:58:39 +02:00
tomasz.sowa 4569198b9d fixed in index_head_adder.html: winix_function_is "emacs" should be in parentheses 2021-06-27 23:43:01 +02:00
tomasz.sowa ccbbb59af7 make depend 2021-06-27 23:34:06 +02:00
tomasz.sowa 3a5af25eaf updated some html templates 2021-06-27 23:33:10 +02:00
tomasz.sowa 1d18b7fa12 - updated to the new pikotools api (child spaces were removed)
some plugins need to be fixed yet: ticket, gallery, group, menu
- added current user to default models as "user"
- renamed in User: super_user -> is_super_user, env -> admin_env, pass_hash_salted -> is_pass_hash_salted
- now Users class has a WinixModel as a base class
  some plugin calls have to be fixed yet
- added UserWrapper model with a pointer to User class
- removed from ItemContent: methods for accessing 'meta' and 'admin_meta', now ezc can iterate through Space classes
- fixed in env winix function: if there is "changeuser" parameter then we should only switch the user (not save anything)
2021-06-27 23:31:50 +02:00
tomasz.sowa 472490c239 make depend 2021-06-24 21:17:11 +02:00
tomasz.sowa b6340a30d2 updated to the new pikotools api (changes in Log) 2021-06-24 21:17:03 +02:00
tomasz.sowa bf1f0954b9 fixed: changed "%g" to "%f" when printing request/ezc times
SetNonZeroDigitsAfterComma() incorrectly terminated the string if the format was "%g" (in the case where it was used as %e)
2021-06-24 16:11:02 +02:00
tomasz.sowa 2f1cdcf379 added printing info how much time winix spent in the ezc engine
added to Request:
timespec timespec_req_stop;
timespec timespec_req_diff;
timespec timespec_ezc_engine_start;
timespec timespec_ezc_engine_stop;
2021-06-24 15:33:44 +02:00
tomasz.sowa 443c2023d9 make depend 2021-06-23 17:04:21 +02:00
tomasz.sowa 2c5062ba22 UrlEncode() methods from core/misc.h are now thread safe 2021-06-23 17:04:07 +02:00
Tomasz Sowa 99df807095 Makefile: added new macros to CFLAGS 2021-06-21 20:22:15 +02:00
tomasz.sowa 8ab07d11b1 fixed: cur.request->function->fun didn't have a model connector set when a request started 2021-06-21 16:51:35 +02:00
tomasz.sowa a1c0f6f7f0 added config option: add_header_cache_no_store_in_htmx_request
send "Cache-Control: no-store, max-age=0" http header if a request is made by htmx library (ajax)
if a webbrowser get a page from the cache then it will render just the last request without the whole html page (css, js, etc)
https://github.com/bigskysoftware/htmx/issues/497
2021-06-21 11:43:59 +02:00
tomasz.sowa 672737a0d8 added a comment in ItemContent 2021-06-20 22:27:06 +02:00
tomasz.sowa ade96bf6d3 some methods from templates/item.cpp moved to ItemContent 2021-06-20 21:22:08 +02:00
tomasz.sowa 801fc062ef added FunctionBase::Clear() which is called at the end of a request 2021-06-20 20:47:59 +02:00
tomasz.sowa f35840e7de some work in html templates: changed some functions from item_* to item.* 2021-06-20 18:12:43 +02:00
tomasz.sowa 79eda7abb0 - added to FunctionBase: bool register_default_models (default true)
if true then winix will add default models for ezc templates such as "request", "item", etc.
- some methods from templates/item.cpp moved to Item
2021-06-20 18:04:50 +02:00
tomasz.sowa e7c7324058 ItemContent::user_name(EzcEnv & env) changed to ItemContent::user(morm::ModelWrapper ** model_wrapper) and we return a User class
ItemContent::group_name(EzcEnv & env) changed to ItemContent::group(morm::ModelWrapper ** model_wrapper) and we return a Group class
added ItemContent::display_user_name(EzcEnv & env)
some functions in templates/item.cpp moved to Item
2021-06-19 23:48:12 +02:00
tomasz.sowa d8c1a81bcb removed config options: ezc_error_prefix and ezc_error_postfix
Ezc::PatternParser and Ezc::Generator use only pt::Log as a logger now
2021-06-19 20:33:35 +02:00
tomasz.sowa 94f96c11cb make depend 2021-06-18 19:18:46 +02:00
tomasz.sowa ec94dff7d7 some ezc functions from templates/item.cpp moved to Item and ItemContent
methods HasAccess() HasReadAccess() and similar moved from System to Item and ItemContent
2021-06-18 19:18:13 +02:00
tomasz.sowa ebd791a256 changed: now Request class is a model class - we have fields() method there to map fields for ezc templates (currently only dir_tab)
removed: [dir_tab] ezc statement
changed: Ls winix function loads its own dir_tab container (beforehand it was loaded by [dir_tab] ezc statement)
         it's available by [child_dirs] name
2021-06-17 21:44:29 +02:00
tomasz.sowa 4db421d6c3 make depend 2021-06-16 23:43:57 +02:00
tomasz.sowa ab89ffe096 fixed in Item: void Item::link(Ezc::FunInfo<HtmlTextStream> & env) now returns a correct directory for the item (before the current directory was returned)
added to Item: void Item::dir_link(Ezc::FunInfo<HtmlTextStream> & env)
added to WinixModel:
  Dirs * get_dirs();
  Mounts * get_mounts();
  Users * get_users();
  Groups * get_groups();
  SLog * get_session_logger(); // not finished yet
2021-06-16 23:42:23 +02:00
tomasz.sowa 53fe5c35b9 added .editorconfig file 2021-06-16 18:09:18 +02:00
tomasz.sowa f2f2c851df make depend 2021-06-16 18:09:01 +02:00
tomasz.sowa 6dddc5e948 renamed: WinixModel -> WinixModelDeprecated (this class will be removed)
added: WinixModel (models/winixmodel.h|cpp) - a class inheriting from morm::WinixModel, we have methods such as: get_config(), get_logger(), get_request()
       and this class will be a base class for our models
added: WinixModelConnector (models/winixmodelconnector.h|cpp) - a class inheriting from morm::WinixModelConnector
       this connector we are using instead of morm::ModelConnector - there are pointers to winix objects there (config, request, log)
added to Request: Ezc::Models models
removed from TemplatesFunctions: Ezc::Models ezc_models;
changed: ImgCrop winix functions is using its own item_tab vector now (not finished yet)
added: Item::is(), Item::link(), ItemContent::print_content()
2021-06-16 18:07:44 +02:00
tomasz.sowa 9688b1a26a htmx updated to 1.4.1 2021-06-09 01:56:47 +02:00
tomasz.sowa 81df52f6ca make depend 2021-05-31 18:59:49 +02:00
tomasz.sowa 6e4f8f5191 start adding support for Models objects from Ezc 2021-05-31 18:59:20 +02:00
tomasz.sowa 22de3322ae - added to Request: is_htmx_request (bool) - true if the request is made by htmx library (ajax)
- commented out using mount_page_arg_is "subject" and "info" from fun_cat.html and fun_run.html - they will be removed soon
- some improvements in fun_reply.html, fun_showthreads.html and fun_thread.html (scrolling)
2021-05-31 10:58:34 +02:00
tomasz.sowa e6fae4598c updated to the new pikotools api: [ezc out] and [out] changed to [ezc frame] or just [frame]
- when returning json streams changed "out" field to "frames"
- renamed config parameter: allow_ezc_out_in_executable_items -> allow_ezc_frames_in_executable_items
- added basic support for ajax requests in thread plugin
2021-05-28 18:36:19 +02:00
tomasz.sowa ba331dea4a added basic support for htmx (ajax)
- if there is HX-Request header present we sent only a part of the whole html
- we return only specific stream defined by [out ...] ezc statement
- the name of the stream is passed in the 'frame' parameter
  (if not present then 'content' is assumed)
- added ezc function: winix_is_htmx_request
2021-05-27 19:36:04 +02:00
tomasz.sowa 1292a56d1b added htmx 1.4.0 loaded by default in html/index_head_adder.html 2021-05-27 13:41:29 +02:00
tomasz.sowa 6a452ffed0 version changed to 0.7.3 2021-05-27 12:21:59 +02:00
Tomek fc24570062 fixed compilation: pikotools is in src subdirectory now 2021-05-27 12:04:41 +02:00
tomasz.sowa aa71abd725 some workarounds in Thread plugin (don't show stale info in html forms) 2021-05-27 10:29:26 +02:00
tomasz.sowa fb64f5e456 fixed: reply winix function (from thread plugin) didn't add a reply - system->Add() didn't set the model_connector to the item 2021-05-26 19:55:50 +02:00
tomasz.sowa 61fe6ea219 updated to the new api from ezc: changed semantic of [def] and Vars moved outside of Generator 2021-05-23 10:14:08 +02:00
tomasz.sowa d30c7254eb updated uikit to 3.6.22 2021-05-22 13:03:15 +02:00
tomasz.sowa 06be33ba5f make depend 2021-05-21 23:06:57 +02:00
tomasz.sowa b2cffa39e1 added models Thread and ThreadFiles in thread plugin 2021-05-21 23:06:48 +02:00
tomasz.sowa 86ef2529b1 fixed in some places: system->AddFile() returns bool now instead of Error 2021-05-21 17:41:16 +02:00
tomasz.sowa f1b9d1b870 updated to the new pikotools api: changed the way how child_spaces are created in Space class 2021-05-21 17:17:17 +02:00
tomasz.sowa fe67b5d72a updated to the new pikotools api: snake_case names of methods from SpaceParser 2021-05-21 04:51:58 +02:00
tomasz.sowa 27720afaf2 updated to the new pikotools api: SpaceParser::SetSpace(...) methods have been removed 2021-05-21 01:37:42 +02:00
tomasz.sowa 8bb585d97d updated to the new pikotools api: changed utf8 functions PascalCase to snake_case 2021-05-21 00:41:27 +02:00
tomasz.sowa 8c523ce8b9 make depend 2021-05-21 00:32:58 +02:00
tomasz.sowa e48a28a5c8 namespace PT renamed to pt 2021-05-20 20:59:12 +02:00
tomasz.sowa d66a36cf21 make depend 2021-05-14 03:32:03 +02:00
tomasz.sowa a94e09f0aa added support for Model migrations
now we have a table core.migration and each model (User, Group, Item, ItemContent and a new Migration) have its own
row in the table with a version number

added to config:
db_make_migration_if_needed and db_stop_if_migration_fails (need description yet)
2021-05-14 03:31:29 +02:00
tomasz.sowa 4df10de6b7 methods eq() from finder can have now a table name 2021-05-13 19:33:19 +02:00
tomasz.sowa 6d07535dad updated uikit to 3.6.21 version 2021-05-13 06:24:44 +02:00
tomasz.sowa ee354d2ded renamed in Models: map_fields() to fields(), prepare_table() to table() 2021-05-13 03:29:41 +02:00
tomasz.sowa e64bd1fba8 added more html tags to extraAllowedContent (ckeditor) 2021-05-13 03:24:37 +02:00
tomasz.sowa 031e673c51 fixed: passwd winix function: pass_encrypted was not cleared if we are not using rsa for encrypting passwords anymore 2021-05-13 02:02:15 +02:00
tomasz.sowa 801c9a2cda make depend 2021-05-11 22:22:10 +02:00
tomasz.sowa 685b3ca5ee Makefile: source files from pikotools are now in pikotools/src 2021-05-11 22:22:03 +02:00
tomasz.sowa f1af7e2eeb updated to the current pikotools api from branch api2021 2021-05-11 22:20:46 +02:00
tomasz.sowa 85f9fda984 fixed: in passwd winix function: clear password hash when using rsa encoding 2021-05-11 22:15:52 +02:00
tomasz.sowa bb513b0187 make depend 2021-04-30 01:35:40 +02:00
tomasz.sowa 4277f90bad start working on User and Group classes
- User and Group has been moved to 'models' directory
- removed UserPass struct (passwords fields were put to User struct)
not working yet, we need support for binary blobs in morm
2021-04-30 01:34:48 +02:00
tomasz.sowa ccda2bc2fd added option do_migration_to_winix_fullmorm do the config (only temporarily)
if true then we make Item::do_migration() and exit
2021-04-14 14:13:47 +02:00
tomasz.sowa 4b71530f4c added to Config:
bool Config::HasValue(const wchar_t * name, const wchar_t * value)
2021-04-12 18:55:04 +02:00
tomasz.sowa a8a9db53be remove some Lock() and Unlock() from Plugin 2021-04-11 12:09:42 +02:00
tomasz.sowa 634cf07d44 using Winix::Lock object instead of Lock() method in ThreadManager 2021-04-10 21:12:28 +02:00
tomasz.sowa 0e0c006d5a fixed: thread locking problem in Image: method Lock() was used instead of Winix::Lock object 2021-04-10 19:46:50 +02:00
tomasz.sowa 486067a4b2 clang thread sanitizer reported a data race in App::Start()
synchro.was_stop_signal was read without locking

==================
WARNING: ThreadSanitizer: data race (pid=13831)
  Write of size 1 at 0x000000dc4d18 by thread T1 (mutexes: write M44):
    #0 Winix::App::SpecialThreadForSignals(void*) /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:2226:31 (winix.so+0x1f7465)

  Previous read of size 1 at 0x000000dc4d18 by main thread:
    #0 Winix::App::Start() /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:651:18 (winix.so+0x1ee9af)
    #1 main /disk2Tc/home/tomek/roboczy/prog/winix/winixd/main/main.cpp:222:6 (winix+0x2d74c1)

  Location is global 'Winix::app' of size 65840 at 0x000000db5908 (winix+0x000000dc4d18)

  Mutex M44 (0x000000dc4d10) created at:
    #0 pthread_mutex_lock /disk2Tb/usr/src/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc:4153:3 (winix+0x2ac204)
    #1 Winix::Synchro::Lock() /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/synchro.cpp:68:12 (winix.so+0x2e5822)
    #2 Winix::Lock::Lock(Winix::Synchro*) /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/lock.cpp:53:11 (winix.so+0x295522)
    #3 Winix::FileLog::get_local_date(PT::Date const&) /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/filelog.cpp:98:8 (winix.so+0x261183)
    #4 Winix::Log::PrintDate(PT::Date const&) /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/log.cpp:80:30 (winix.so+0x295a21)
    #5 Winix::LogInfo(Winix::Log&, Winix::LogManipulators, char const*, bool, char const*) /disk2Tc/home/tomek/roboczy/prog/winix/winixd/main/main.cpp:104:6 (winix+0x2d69ec)
    #6 main /disk2Tc/home/tomek/roboczy/prog/winix/winixd/main/main.cpp:190:2 (winix+0x2d7363)

  Thread T1 (tid=100187, running) created by main thread at:
    #0 pthread_create /disk2Tb/usr/src/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:962:3 (winix+0x295bb3)
    #1 Winix::App::StartThreads() /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:2246:2 (winix.so+0x1f7549)
    #2 main /disk2Tc/home/tomek/roboczy/prog/winix/winixd/main/main.cpp:212:6 (winix+0x2d743e)

SUMMARY: ThreadSanitizer: data race /disk2Tc/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:2226:31 in Winix::App::SpecialThreadForSignals(void*)
==================
2021-04-10 17:14:51 +02:00
tomasz.sowa 35e10ed469 updated to the new Pikotools api (new Space struct) 2021-04-09 17:50:58 +02:00
tomasz.sowa 00b980e74b make depend 2021-04-09 16:02:54 +02:00
tomasz.sowa efdc0e7c97 etc/time_zones.conf changed values: "true" -> true, "false" -> false 2021-04-09 10:25:10 +02:00
tomasz.sowa 8b64d2066f changed: new space characters in etc/time_zones.conf:
( -> {
 ) -> }
2021-03-31 20:26:30 +02:00
tomasz.sowa 8d87d9a875 changed in Makefile: we have now one lib pikotools/pikotools.a
make depend
2021-03-31 20:25:09 +02:00
tomasz.sowa 8fc1848ecc uikit updated to 3.6.18 2021-03-31 20:21:24 +02:00
tomasz.sowa bbc0a67153 added support for new morm api
- field(...) methods from Model take now FT structure instead of insertable/updatable/primary_key boolean flags
- table name is set in a prepare_table() method now
- added meta and admin_meta from ItemContent (morm has a field() method with PT::Space argument now)
2021-03-11 18:48:18 +01:00
tomasz.sowa e8ba2a7bd1 fixed: incorrect status was set when editing a file
now System::EditFile() returns boolean
2021-03-11 18:42:26 +01:00
tomasz.sowa 23f1c112a4 make depend 2021-03-10 16:40:22 +01:00
tomasz.sowa 4d76e53554 in after_insert() methods: changed get_last_sequence -> get_last_sequence_for_primary_key 2021-03-09 18:16:29 +01:00
tomasz.sowa 73352e680e Make depend 2021-03-08 21:10:33 +01:00
tomasz.sowa 57aad8b454 removed from Item: update() and save() methods which take the 'url_was_changed' argument
and added ItemModelData (based on morm::ModelData) class which has 'prepare_unique_url' field,
an object of this class is passed to update(), insert() and save() methods

fixed: Dirs::CheckRootDir(): update should update childs too (privileges)

WIP: #4
2021-03-08 21:06:50 +01:00
tomasz.sowa ab5c44a2cb removed some old methods for adding/editing Item from Db 2021-02-25 00:17:07 +01:00
tomasz.sowa 3e84eb9dbf Makefile deps 2021-02-25 00:15:03 +01:00
tomasz.sowa afbe82e9f4 changed the way how prefixes are added to urls
instead at the end we adding a prefix before an extension, e.g: filename_(2).jpg
2021-02-25 00:12:45 +01:00
tomasz.sowa 51b1aed483 removed DbItemQuery and DbItemColumns which were used for database accessing for Item class 2021-02-24 22:54:36 +01:00
tomasz.sowa 32e93a04c5 Item class has been moved to a new directory 'models', a new class has been added: ItemContent
and same fields from Item were moved to ItemContent

Item
- id
- parent_id
- type (file, dir, symlink)
- url
- subject
- template (html template)
- sort_index
- content_id

ItemContent
- id
- ref -> references (renamed)
- user_id
- modification_user_id
- group_id
- privileges
- date_creation
- date_modification
- guest_name
- link_to
- link_redirect
- file_path
- file_fs
- file_type
- file_size
- has_thumb -> file_has_thumb (renamed)
- hash -> file_hash (renamed)
- hash_type -> file_hash_type (renamed)
- content -> content_raw (renamed)
- content_type -> content_raw_type (renamed)
- content_parsed
- content_parsed_type
- meta
- ameta -> meta_admin (renamed)
- modify_index (removed)

WIP: #4
2021-02-24 01:19:47 +01:00
tomasz.sowa 3d7ece15f8 changed version to 0.7.2 2021-02-18 21:07:05 +01:00
tomasz.sowa 541597f355 fixed: in TimeZone::SetTzDst() was used operator && instead of || 2021-02-17 18:36:50 +01:00
tomasz.sowa 5fe843d76b set -std=c++20 in Makefile 2021-02-17 18:07:05 +01:00
tomasz.sowa 3191369ece added 'using PT::FileLog::init' to FileLog to suppress clang warning:
warning: 'Winix::FileLog::init' hides overloaded virtual function [-Woverloaded-virtual]
2021-02-17 18:06:00 +01:00
tomasz.sowa a4de11d69c fixed: Image did not use 'savelog' when creating logs
before commit 4832c7db4b the logs were lost, but after 4832c7db4b
the logs were printed when winix shuts down

in 4832c7db4b at the end of BaseThread::StartRoutine()
has been added a call to save_log()
2021-02-17 16:17:36 +01:00
tomasz.sowa 4832c7db4b fixed: clang address sanitizer reports that there is an use after free bug at the end when winix shuts down:
==3859==ERROR: AddressSanitizer: heap-use-after-free on address 0x61b0000053e0 at pc 0x000800697160 bp 0x7fffffffcfb0 sp 0x7fffffffcfa8
READ of size 8 at 0x61b0000053e0 thread T0
    #0 0x80069715f in PT::MemBuffer<wchar_t, 256ul, 4096ul>::empty() const /usr/home/tomek/roboczy/prog/web.ttmath.org/../pikotools/membuffer/membuffer.h:675:9
    #1 0x80069700d in PT::TextStreamBase<wchar_t, 256ul, 4096ul>::empty() const /usr/home/tomek/roboczy/prog/web.ttmath.org/../pikotools/textstream/textstream.h:161:16
    #2 0x8009af0e3 in PT::FileLog::save_log(PT::TextStreamBase<wchar_t, 256ul, 4096ul>*) /usr/home/tomek/roboczy/prog/pikotools/log/filelog.cpp:105:14
    #3 0x8009b3f8a in PT::Log::save_log() /usr/home/tomek/roboczy/prog/pikotools/log/log.cpp:461:13
    #4 0x8009b3d72 in PT::Log::save_log_and_clear() /usr/home/tomek/roboczy/prog/pikotools/log/log.cpp:448:2
    #5 0x8009b0627 in PT::Log::~Log() /usr/home/tomek/roboczy/prog/pikotools/log/log.cpp:62:2
    #6 0x8007288e7 in Winix::Log::~Log() /usr/home/tomek/roboczy/prog/winix/winixd/core/log.cpp:56:1
    #7 0x8007eac96 in Winix::WinixBase::~WinixBase() /usr/home/tomek/roboczy/prog/winix/winixd/core/winixbase.cpp:51:1
    #8 0x8007eb097 in Winix::WinixModel::~WinixModel() /usr/home/tomek/roboczy/prog/winix/winixd/core/winixmodel.cpp:52:1
    #9 0x80069e552 in Winix::BaseThread::~BaseThread() /usr/home/tomek/roboczy/prog/winix/winixd/core/basethread.cpp:54:1
    #10 0x2f8132 in Winix::Job::~Job() /usr/home/tomek/roboczy/prog/web.ttmath.org/../winix/winixd/core/job.h:54:7
    #11 0x2e0c8a in Winix::System::~System() /usr/home/tomek/roboczy/prog/web.ttmath.org/../winix/winixd/core/system.h:67:7
    #12 0x2df017 in Winix::App::~App() /usr/home/tomek/roboczy/prog/web.ttmath.org/../winix/winixd/core/app.h:70:7
    #13 0x800cc9f50 in __cxa_finalize /hddraidzfs/usr/src/lib/libc/stdlib/atexit.c:238:5
    #14 0x800c5ef10 in exit /hddraidzfs/usr/src/lib/libc/stdlib/exit.c:74:2
    #15 0x25c935 in _start /hddraidzfs/usr/src/lib/csu/amd64/crt1.c:76:2

0x61b0000053e0 is located 1632 bytes inside of 1656-byte region [0x61b000004d80,0x61b0000053f8)
freed by thread T0 here:
    #0 0x2dc07d in operator delete(void*) /hddraidzfs/usr/src/contrib/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:160:3
    #1 0x8007c3b2c in Winix::ThreadManager::StopAll() /usr/home/tomek/roboczy/prog/winix/winixd/core/threadmanager.cpp:189:3
    #2 0x800647474 in Winix::App::WaitForThreads() /usr/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:2122:24
    #3 0x800647311 in Winix::App::Close() /usr/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:340:2
    #4 0x2dec7c in main /usr/home/tomek/roboczy/prog/winix/winixd/main/main.cpp:224:6
    #5 0x25c92e in _start /hddraidzfs/usr/src/lib/csu/amd64/crt1.c:76:7
    #6 0x80033efff  (<unknown module>)

previously allocated by thread T0 here:
    #0 0x2db81d in operator new(unsigned long) /hddraidzfs/usr/src/contrib/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:99:3
    #1 0x8007c17c3 in Winix::ThreadManager::Add(Winix::BaseThread*, wchar_t const*) /usr/home/tomek/roboczy/prog/winix/winixd/core/threadmanager.cpp:77:26
    #2 0x8007b0b81 in Winix::System::Init() /usr/home/tomek/roboczy/prog/winix/winixd/core/system.cpp:170:17
    #3 0x8006468d4 in Winix::App::Init() /usr/home/tomek/roboczy/prog/winix/winixd/core/app.cpp:295:9
    #4 0x2deb7e in main /usr/home/tomek/roboczy/prog/winix/winixd/main/main.cpp:206:11
    #5 0x25c92e in _start /hddraidzfs/usr/src/lib/csu/amd64/crt1.c:76:7
    #6 0x80033efff  (<unknown module>)

in ThreadManager::StopAll() there is item.thread_item_data pointer which was freed (the pointer was pointing to an object with a log_buffer)
but internal Log buffer from item.object was pointing to that object and when thread_tab.clear() was called then the d-ctor was called
and then save_log_and_clear() method was called and tried to use the freed object.
2021-02-17 15:58:05 +01:00
tomasz.sowa be83d62f96 changed html in index templates: [include "index_head_functions_add.html"] -> [include "index_head_adder.html"] 2021-02-16 20:10:29 +01:00
tomasz.sowa 3fd2ef1da4 renamed: html/index_head_functions_add.html -> html/index_head_adder.html 2021-02-16 20:01:38 +01:00
tomasz.sowa d861384889 Merge pull request 'uikit' (#3) from uikit into master
Reviewed-on: #3
2021-02-16 19:52:36 +01:00
tomasz.sowa cfd8e88e57 changed markup in fun_thread.html, removed item_options.html (was not used by winix)
WIP: #2
2021-02-16 19:44:57 +01:00
tomasz.sowa 8169cb5a7e added uikit markup for uname winix function
WIP: #2
2021-02-16 19:28:42 +01:00
tomasz.sowa 8c85cd7346 added uikit markup for stat winix function
WIP: #2
2021-02-16 19:25:36 +01:00
tomasz.sowa 4e202833b2 added uikit markup for rmuser winix function
WIP: #2
2021-02-16 19:21:53 +01:00
tomasz.sowa 4a163bd170 added uikit markup for pw winix function
WIP: #2
2021-02-16 19:12:15 +01:00
tomasz.sowa 85fbc1b882 added uikit markup for man winix function
WIP: #2
2021-02-16 19:03:01 +01:00
tomasz.sowa 61810ff6f9 added uikit markup for last winix function
WIP: #2
2021-02-16 18:56:18 +01:00
tomasz.sowa 3a4a29f56d added uikit markup for ipban winix function
WIP: #2
2021-02-16 18:53:12 +01:00
tomasz.sowa 1fb7ece1b3 fixed: in imgcrop: data-uk-lightbox interfere with menu buttons
WIP: #2
2021-02-16 18:46:39 +01:00
tomasz.sowa f3879dd3a4 added lightbox effect on images in imgcrop winix function
WIP: #2
2021-02-16 18:40:48 +01:00
tomasz.sowa 561014886f added uikit markup for imgcrop winix function
WIP: #2
2021-02-16 18:35:55 +01:00
tomasz.sowa a2b19547a3 fixed: in Functions::CheckSpecialFile() after parsing new mount points
the cur->mount pointer was pointing at the old mount object
(which may no longer exists)
2021-02-16 17:23:36 +01:00
tomasz.sowa 93477091d1 added uikit markup for gallery winix funcion (gallery plugin)
- the main gallery is now 'uikit'
- lightbox updated to version 2.11.3 (now it is using jQuery, beforehand prototype.js was used)
- aino-gallery is called galleriajs now (and updated to 1.6.1)
- themes from galleriajs were removed and some new themes has been added (azur, twelve, folio, fullscreen)
- removed some old mount types for galleries (galleriathumb, galleria1.2.9, galleriathumb1.2.9)

WIP: #2
2021-02-16 16:31:52 +01:00
tomasz.sowa 64d3c62945 added uikit markup for export winix function (plugin export)
WIP: #2
2021-02-16 13:11:39 +01:00
tomasz.sowa 134e27f70a modified login template - removed uk-border-pill class
WIP: #2
2021-02-16 12:56:15 +01:00
tomasz.sowa 5205aa089b modified index templates
some meta information moved to index_head_functions_add.html

WIP: #2
2021-02-16 12:55:35 +01:00
tomasz.sowa b5b9655c1e modified buttons in thread winix function
WIP: #2
2021-02-16 12:54:05 +01:00
tomasz.sowa 173d0894fa modified buttons in showthreads winix function
WIP: #2
2021-02-16 12:52:49 +01:00
tomasz.sowa de6b050fb5 fixed comment in ls html template 2021-02-16 12:51:06 +01:00
tomasz.sowa 37da5e81c5 added uikit markup for createticket, showtickets, ticket winix functions (plugin ticket)
WIP: #2
2021-02-15 19:52:03 +01:00
tomasz.sowa ae8637d455 added uikit markup for: createthread, reply, showthreads and thread winix functions 2021-02-12 18:57:14 +01:00
tomasz.sowa 22a45697fa added uikit markup for subject winix function 2021-02-09 18:48:48 +01:00
tomasz.sowa 55462fca9f added uikit markup for uptime winix function 2021-02-09 18:26:30 +01:00
tomasz.sowa 2799a66c16 added uikit markup for who winix function 2021-02-09 18:11:37 +01:00
tomasz.sowa 9832b17fc2 updated uikit to 3.6.16 2021-02-09 18:10:01 +01:00
tomasz.sowa 8146f42492 added uikit markup for seo winix function 2021-02-08 02:01:37 +01:00
tomasz.sowa 9df146af3b added: to 'sort' winix function: 'renumerate' button if 'index' param is present
WIP: #2
2021-01-29 08:35:17 +01:00
tomasz.sowa a7629f638f added uikit markup for sort winix function
WIP: #2
2021-01-28 20:16:44 +01:00
tomasz.sowa e75918f5ed added uikit markup for rm winix function
WIP: #2
2021-01-28 15:36:39 +01:00
tomasz.sowa 9698c25bc4 added uikit markup for ln winix function
WIP: #2
2021-01-28 12:41:43 +01:00
tomasz.sowa bbe2bd48d8 added uikit markup for meta winix function
WIP: #2
2021-01-28 11:49:10 +01:00
tomasz.sowa 0cc565ae80 added uikit markup for env winix function
WIP: #2
2021-01-28 11:11:34 +01:00
tomasz.sowa aa74d96fed included index_bottom_adder.html in index.html and index_generic.html 2021-01-27 18:50:03 +01:00
tomasz.sowa ac6ede6aef added uikit markup for template winix function
WIP: #2
2021-01-27 18:44:58 +01:00
tomasz.sowa 10e291bb39 added: generic html template: index_generic.html
(config option: templates_index_generic)
this is a generic template without additional site-css (only uikit),
at the moment used only in ckeditor file browser

added: to Request class: index_template (std::wstring) - a name of an index html template
2021-01-27 18:31:48 +01:00
tomasz.sowa 7a25e333db added uikit markup for ls winix function
WIP: #2
2021-01-27 17:55:48 +01:00
tomasz.sowa a9b9d0badf fixed: mv winix function didn't move a file correctly
- if a file was moved (renamed) into the same directory and a file with the new name
already existed then nothing was done (now a message is shown that such a file already exists)
- if a file was moved to another directory and there was a file wich such a name there
then the moved file had its original name (now a message is shown that such a file already exists)
2021-01-27 17:30:55 +01:00
tomasz.sowa a69e160f85 added uikit markup for nicedit winix function and nicedit updated to 0.9_r25 version
WIP: #2
2021-01-26 17:24:48 +01:00
tomasz.sowa 56d53a455d added uikit markup for cp winix function
WIP: #2
2021-01-26 16:52:11 +01:00
tomasz.sowa 572afd360a added uikit markup for mv winix function
WIP: #2
2021-01-26 16:37:11 +01:00
tomasz.sowa ec6f946b97 added uikit markup for mkdir winix function
WIP: #2
2021-01-26 16:26:34 +01:00
tomasz.sowa acfd87e548 added uikit markup for 'default' winix function
WIP: #2
2021-01-26 16:19:20 +01:00
tomasz.sowa aa228732e3 added uk-table-responsive attribute to mount winix function markup
WIP: #2
2021-01-26 16:11:09 +01:00
tomasz.sowa 840c222190 added uikit markup for mount winix function
WIP: #2
2021-01-26 16:05:15 +01:00
tomasz.sowa 4408957770 changed form width for locale template
WIP: #2
2021-01-26 15:57:55 +01:00
tomasz.sowa 89814cbc2e updated uikit to 3.6.14 version
WIP: #2
2021-01-26 15:51:57 +01:00
tomasz.sowa fdcefae264 added uikit markup for priv, chmod, chown winix functions
WIP: #2
2021-01-26 15:46:47 +01:00
tomasz.sowa 0139919d14 added uikit markup for passwd winix function 2021-01-25 19:19:45 +01:00
tomasz.sowa 9476bcc7b6 Merge branch 'master' into uikit 2021-01-25 18:45:07 +01:00
tomasz.sowa 4625451c85 fixed: messages about password validity in adduser function were not shown,
slog and locale for functions->fun_passwd were not set
2021-01-25 18:41:28 +01:00
tomasz.sowa 1e345f5010 changed: locale files 2021-01-25 18:19:30 +01:00
tomasz.sowa 31befcba44 added uikit markup for slog.html 2021-01-25 18:15:26 +01:00
tomasz.sowa f6077da614 Merge branch 'master' into uikit 2021-01-25 17:59:14 +01:00
tomasz.sowa 499db7e3eb fixed: session logger didn't have 'cur' and 'locale' pointers set
but this is a temporary fix, the session logger will be moved to Session class
2021-01-25 17:55:07 +01:00
tomasz.sowa 50da49a3ed added uikit markup for adduser winix function 2021-01-25 17:17:54 +01:00
tomasz.sowa 6afd5c637e added: in account winix function: links to locale and timezone 2021-01-25 16:23:13 +01:00
tomasz.sowa 31a6aac9d3 added uikit markup for locale winix function 2021-01-25 16:15:55 +01:00
tomasz.sowa 3c3660914f added uikit markup for timezone winix function 2021-01-25 16:10:42 +01:00
tomasz.sowa cd0ae231dc added uikit markup for account winix function 2021-01-25 15:57:37 +01:00
tomasz.sowa a8bc741883 added uikit markup for vim editor (wymeditor) 2021-01-25 14:34:35 +01:00
tomasz.sowa 05b3525863 changed: version to 0.7.1 2021-01-25 13:14:16 +01:00
473 changed files with 52312 additions and 39214 deletions
+21
View File
@@ -0,0 +1,21 @@
# EditorConfig
# https://editorconfig.org/
# https://editorconfig-specification.readthedocs.io/
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# 4 space indentation
[*.{h,cpp,html,css,js,conf,txt}]
indent_style = tab
indent_size = 4
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
indent_size = 4
+6 -1
View File
@@ -3,4 +3,9 @@
.settings/
*.o
*.so
winixd/winix
/winixd/winix
/winixcli/src/winix
/winixcli/m
/.clangd
/.qtcreator/
/.qtc_clangd/
+2
View File
@@ -0,0 +1,2 @@
CompileFlags:
Add: [-pthread, -std=c++20, -I%%%CURRENT_DIR%%%/winixd, -I%%%GLOBAL_WORKING_DIR%%%/pikotools/src, -I%%%GLOBAL_WORKING_DIR%%%/ezc/src, -I%%%GLOBAL_WORKING_DIR%%%/morm/src, -I%%%GLOBAL_WORKING_DIR%%%/tito/src, -I/usr/include, -I/usr/local/include, -I/usr/local/include/postgresql, -DPT_HAS_MORM_LIBRARY, -DEZC_HAS_MORM_LIBRARY, -DMORM_HAS_EZC_LIBRARY]
+1
View File
@@ -0,0 +1 @@
-std=c20
+4
View File
@@ -0,0 +1,4 @@
#define PT_HAS_MORM_LIBRARY 1
#define EZC_HAS_MORM_LIBRARY 1
#define MORM_HAS_EZC_LIBRARY 1
+1
View File
@@ -0,0 +1 @@
[General]
+184
View File
@@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 14.0.1, 2024-09-20T16:21:10. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">%%%QT_ENVIRONMENT_ID%%%</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="qlonglong">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">2</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
<value type="bool" key="AutoTest.Framework.Boost">true</value>
<value type="bool" key="AutoTest.Framework.CTest">false</value>
<value type="bool" key="AutoTest.Framework.Catch">true</value>
<value type="bool" key="AutoTest.Framework.GTest">true</value>
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
</valuemap>
<value type="bool" key="AutoTest.ApplyFilter">false</value>
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
<value type="int" key="AutoTest.RunAfterBuild">0</value>
<value type="bool" key="AutoTest.UseGlobal">true</value>
<valuemap type="QVariantMap" key="ClangTools">
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">3</value>
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
</valuemap>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">%%%QT_DEFAULT_PROFILE_ID%%%</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">%%%CURRENT_DIR%%%</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand">/usr/local/bin/gmake</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand">/usr/local/bin/gmake</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="qlonglong">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>
+1
View File
@@ -0,0 +1 @@
-std=c++20
+1
View File
@@ -0,0 +1 @@
+30
View File
@@ -0,0 +1,30 @@
#!/bin/sh
CURRENT_DIR=$(pwd)
GLOBAL_WORKING_DIR=$(realpath ${CURRENT_DIR}/..)
# ----------
# make sure the current directory is correct
if [ ! -d ${CURRENT_DIR}/.templates ] ; then
echo "this script should be called by make: make clangd (one level up)"
exit 1
fi
# change / to \/ in paths
CURRENT_DIR_FOR_SED=$(echo ${CURRENT_DIR} | sed 's/\//\\\//g')
GLOBAL_WORKING_DIR_FOR_SED=$(echo ${GLOBAL_WORKING_DIR} | sed 's/\//\\\//g')
if [ -f "${CURRENT_DIR}/.templates/.clangd" ] ; then
if [ ! -f "${CURRENT_DIR}/.clangd" ] ; then
cat "${CURRENT_DIR}/.templates/.clangd" | \
sed -e "s/%%%CURRENT_DIR%%%/${CURRENT_DIR_FOR_SED}/g" \
-e "s/%%%GLOBAL_WORKING_DIR%%%/${GLOBAL_WORKING_DIR_FOR_SED}/g" > \
${CURRENT_DIR}/.clangd
echo "added a ${CURRENT_DIR}/.clangd file"
fi
fi
+105
View File
@@ -0,0 +1,105 @@
#!/bin/sh
CURRENT_DIR=$(pwd)
GLOBAL_WORKING_DIR=$(realpath ${CURRENT_DIR}/..)
QTCREATOR_DIR=${CURRENT_DIR}/.qtcreator
# ----------
# make sure the current directory is correct
if [ ! -d ${CURRENT_DIR}/.templates ] ; then
echo "this script should be called by make: make qtcreator (one level up)"
exit 1
fi
qtcreatorini=~/.config/QtProject/QtCreator.ini
qtprofiles=~/.config/QtProject/qtcreator/profiles.xml
if [ ! -f "$qtcreatorini" ] ; then
echo "I cannot find a $qtcreatorini file"
echo "this file is needed to take an EnvironmentId parameter"
echo "if QTCreator was recently installed make sure you have opened it at least once"
exit 2
fi
if [ ! -f "$qtprofiles" ] ; then
echo "I cannot find a $qtprofiles file"
echo "this file is needed to take a default profile id parameter"
echo "if QTCreator was recently installed make sure you have opened it at least once"
exit 3
fi
qtenvironmentid=`grep -F 'Settings\EnvironmentId' "$qtcreatorini" | grep -Eo '\{[a-zA-Z0-9-]+\}'`
qtdefaultprofileid=`grep -A 1 -F '<variable>Profile.Default</variable>' "$qtprofiles" | tail -n 1 | grep -Eo '\{[a-zA-Z0-9-]+\}'`
if [ -z "$qtenvironmentid" ] ; then
echo "I cannot read a Settings\EnvironmentId parameter from $qtcreatorini file"
exit 4
fi
if [ -z "$qtdefaultprofileid" ] ; then
echo "I cannot read a Profile.Default parameter from $qtprofiles file"
exit 5
fi
# change / to \/ in paths
CURRENT_DIR_FOR_SED=$(echo ${CURRENT_DIR} | sed 's/\//\\\//g')
GLOBAL_WORKING_DIR_FOR_SED=$(echo ${GLOBAL_WORKING_DIR} | sed 's/\//\\\//g')
was_qtcreator_dir=0
if [ -d "${QTCREATOR_DIR}" ] ; then
was_qtcreator_dir=1
else
echo "Your QTCreator EnvironmentId is: $qtenvironmentid"
echo "Your QTCreator default profile id is: $qtdefaultprofileid"
mkdir -p "${QTCREATOR_DIR}"
fi
if [ -d "${QTCREATOR_DIR}" ] ; then
if [ -d ${CURRENT_DIR}/.templates/.qtcreator ] ; then
cd ${CURRENT_DIR}/.templates/.qtcreator
if [ $? -eq 0 ] ; then
for i in * ; do
if [ ! -f "${QTCREATOR_DIR}/$i" ] ; then
cat "$i" | \
sed -e "s/%%%CURRENT_DIR%%%/${CURRENT_DIR_FOR_SED}/g" \
-e "s/%%%GLOBAL_WORKING_DIR%%%/${GLOBAL_WORKING_DIR_FOR_SED}/g" \
-e "s/%%%QT_ENVIRONMENT_ID%%%/${qtenvironmentid}/g" \
-e "s/%%%QT_DEFAULT_PROFILE_ID%%%/${qtdefaultprofileid}/g" > \
"${QTCREATOR_DIR}/$i"
fi
done
if [ $was_qtcreator_dir -eq 0 ] ; then
echo "QTCreator files generated to ${QTCREATOR_DIR} directory"
echo "select an 'open project...' option and find a ${QTCREATOR_DIR}/*.creator file"
fi
fi
fi
find ${QTCREATOR_DIR} -name "*.files" | while read projectfiles ; do
cd ${CURRENT_DIR}/winixd
if [ $? -eq 0 ] ; then
find ../winixd -type f \( -iname "*.cpp" -o -iname "*.h" \) | sort > ${projectfiles}
echo "file ${projectfiles} has been updated"
fi
cd ${CURRENT_DIR}/winixcli
if [ $? -eq 0 ] ; then
find ../winixcli -type f \( -iname "*.cpp" -o -iname "*.h" \) | sort >> ${projectfiles}
fi
done
fi
+24
View File
@@ -0,0 +1,24 @@
Copyright (c) 2012-2022, Tomasz Sowa
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
+62
View File
@@ -0,0 +1,62 @@
export CXX
export CXXFLAGS
export LDFLAGS
all: winixd winixcli
winixd: FORCE
$(MAKE) -C winixd
winixcli: FORCE
$(MAKE) -C winixcli
clean: FORCE
$(MAKE) -C winixd clean
$(MAKE) -C winixcli clean
cleanall: FORCE
$(MAKE) -C winixd cleanall
$(MAKE) -C winixcli clean
depend: FORCE
$(MAKE) -C winixd depend
$(MAKE) -C winixcli depend
install: FORCE
$(MAKE) -C winixd install
#$(MAKE) -C winixcli depend
clangd: FORCE
@.templates/install_clangd.sh
clangdall: clangd
@$(MAKE) -C ../pikotools clangd
@$(MAKE) -C ../morm clangd
@$(MAKE) -C ../ezc clangd
@$(MAKE) -C ../tito clangd
qtcreator: clangd
@.templates/install_qtcreator.sh
qtcreatorall: qtcreator
@$(MAKE) -C ../pikotools qtcreator
@$(MAKE) -C ../morm qtcreator
@$(MAKE) -C ../ezc qtcreator
@$(MAKE) -C ../tito qtcreator
FORCE:
+25
View File
@@ -0,0 +1,25 @@
export CXX
export CXXFLAGS
export LDFLAGS
all: src
src: FORCE
$(MAKE) -C src
clean: FORCE
$(MAKE) -C src clean
depend: FORCE
$(MAKE) -C src depend
FORCE:
+91
View File
@@ -0,0 +1,91 @@
sourcefiles:=$(shell find . -name "*.cpp")
objfiles:=$(patsubst %.cpp,%.o,$(sourcefiles))
GLOBAL_WORKING_DIR := $(shell pwd)/../../..
WINIX_NEEDED_MACROS = -DPT_HAS_MORM_LIBRARY \
-DEZC_HAS_MORM_LIBRARY \
-DMORM_HAS_EZC_LIBRARY
ifndef CXX
CXX = g++
endif
ifndef ADDITIONAL_CXXFLAGS
ADDITIONAL_CXXFLAGS=-O2
endif
ifndef ADDITIONAL_LDFLAGS
ADDITIONAL_LDFLAGS=-s
endif
ifndef CXXFLAGS
# /usr/include/postgresql is in Linux distros (Alpine)
CXXFLAGS = -Wall -pedantic -std=c++20 $(ADDITIONAL_CXXFLAGS) \
-I/usr/local/include \
-I/usr/include/postgresql \
-I$(GLOBAL_WORKING_DIR)/winix/winixcli \
-I$(GLOBAL_WORKING_DIR)/pikotools/src \
-I$(GLOBAL_WORKING_DIR)/morm/src \
-I$(GLOBAL_WORKING_DIR)/ezc/src \
-I$(GLOBAL_WORKING_DIR)/tito/src \
$(WINIX_NEEDED_MACROS)
endif
LDFLAGS = -L/usr/local/lib $(ADDITIONAL_LDFLAGS)
export CXX
export CXXFLAGS
export LDFLAGS
export GLOBAL_WORKING_DIR
export WINIX_NEEDED_MACROS
progname = winix
all: $(progname)
$(progname): $(objfiles) pikotools morm ezc
$(CXX) -o $(progname) $(CXXFLAGS) $(LDFLAGS) $(objfiles) $(GLOBAL_WORKING_DIR)/ezc/src/ezc.a $(GLOBAL_WORKING_DIR)/morm/src/morm.a $(GLOBAL_WORKING_DIR)/pikotools/src/pikotools.a
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) -o $@ $<
.PHONY: pikotools
.PHONY: morm
.PHONY: ezc
pikotools:
$(MAKE) -C ../../../pikotools
morm:
$(MAKE) -C ../../../morm/src
ezc:
$(MAKE) -C ../../../ezc/src
clean: FORCE
rm -f $(objfiles)
rm -f $(progname)
depend:
makedepend -w 10 -Y. -I../../../pikotools/src -I../../../morm/src -I../../../ezc/src -I../../../tito/src $(WINIX_NEEDED_MACROS) -f- $(sourcefiles) | sort -u > Makefile.dep
FORCE:
-include Makefile.dep
+75
View File
@@ -0,0 +1,75 @@
./main.o: ../../../ezc/src/blocks.h
./main.o: ../../../ezc/src/cache.h
./main.o: ../../../ezc/src/expressionparser.h
./main.o: ../../../ezc/src/ezc.h
./main.o: ../../../ezc/src/functions.h
./main.o: ../../../ezc/src/funinfo.h
./main.o: ../../../ezc/src/generator.h
./main.o: ../../../ezc/src/item.h
./main.o: ../../../ezc/src/models.h
./main.o: ../../../ezc/src/objects.h
./main.o: ../../../ezc/src/outstreams.h
./main.o: ../../../ezc/src/pattern.h
./main.o: ../../../ezc/src/patternparser.h
./main.o: ../../../ezc/src/version.h
./main.o: ../../../morm/src/baseexpression.h
./main.o: ../../../morm/src/baseobjectwrapper.h
./main.o: ../../../morm/src/clearer.h
./main.o: ../../../morm/src/cursorhelper.h
./main.o: ../../../morm/src/dbconnector.h
./main.o: ../../../morm/src/dbexpression.h
./main.o: ../../../morm/src/export.h
./main.o: ../../../morm/src/fieldvaluehelper.h
./main.o: ../../../morm/src/finderhelper.h
./main.o: ../../../morm/src/flatconnector.h
./main.o: ../../../morm/src/flatexpression.h
./main.o: ../../../morm/src/ft.h
./main.o: ../../../morm/src/model.h
./main.o: ../../../morm/src/modelconnector.h
./main.o: ../../../morm/src/modelcontainerwrapper.h
./main.o: ../../../morm/src/modeldata.h
./main.o: ../../../morm/src/modelenv.h
./main.o: ../../../morm/src/morm_types.h
./main.o: ../../../morm/src/queryresult.h
./main.o: ../../../morm/src/select.h
./main.o: ../../../morm/src/spacewrapper.h
./main.o: ../../../morm/src/wrapper.h
./main.o: ../../../pikotools/src/convert/inttostr.h
./main.o: ../../../pikotools/src/convert/misc.h
./main.o: ../../../pikotools/src/convert/strtoint.h
./main.o: ../../../pikotools/src/convert/text.h
./main.o: ../../../pikotools/src/date/date.h
./main.o: ../../../pikotools/src/log/filelog.h
./main.o: ../../../pikotools/src/log/log.h
./main.o: ../../../pikotools/src/mainoptions/mainoptionsparser.h
./main.o: ../../../pikotools/src/membuffer/membuffer.h
./main.o: ../../../pikotools/src/space/space.h
./main.o: ../../../pikotools/src/textstream/stream_private.h
./main.o: ../../../pikotools/src/textstream/stream.h
./main.o: ../../../pikotools/src/textstream/textstream.h
./main.o: ../../../pikotools/src/textstream/types.h
./main.o: ../../../pikotools/src/utf8/utf8.h
./main.o: misc.h
./main.o: pgmodeler.h
./misc.o: ../../../pikotools/src/convert/inttostr.h
./misc.o: ../../../pikotools/src/convert/misc.h
./misc.o: ../../../pikotools/src/space/space.h
./misc.o: ../../../pikotools/src/textstream/stream.h
./misc.o: ../../../pikotools/src/utf8/utf8.h
./misc.o: misc.h
./pgmodeler.o: ../../../pikotools/src/convert/baseparser.h
./pgmodeler.o: ../../../pikotools/src/convert/inttostr.h
./pgmodeler.o: ../../../pikotools/src/convert/misc.h
./pgmodeler.o: ../../../pikotools/src/date/date.h
./pgmodeler.o: ../../../pikotools/src/html/htmlparser.h
./pgmodeler.o: ../../../pikotools/src/membuffer/membuffer.h
./pgmodeler.o: ../../../pikotools/src/space/space.h
./pgmodeler.o: ../../../pikotools/src/textstream/stream_private.h
./pgmodeler.o: ../../../pikotools/src/textstream/stream.h
./pgmodeler.o: ../../../pikotools/src/textstream/textstream.h
./pgmodeler.o: ../../../pikotools/src/textstream/types.h
./pgmodeler.o: ../../../pikotools/src/utf8/utf8.h
./pgmodeler.o: misc.h
./pgmodeler.o: pgmodeler.h
# DO NOT DELETE
+295
View File
@@ -0,0 +1,295 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include "convert/strtoint.h"
#include "mainoptions/mainoptionsparser.h"
#include "pgmodeler.h"
#include "misc.h"
#include "ezc.h"
namespace Winix
{
// make a static method in MainOptionsParser?
std::wstring get_param(const pt::Space::TableType * input_mode)
{
if( input_mode && input_mode->size() > 0 )
{
pt::Space * first_par = (*input_mode)[0];
if( first_par->is_table() && first_par->table_size() > 0 )
{
return first_par->value.value_table.front()->to_wstr();
}
}
return std::wstring();
}
bool use_pgmodeler(const std::wstring & input_file, const pt::Space & input_options, pt::Space & schema, bool sort_tables)
{
PGModeler pgmodeler;
return pgmodeler.parse(input_file, schema, sort_tables);
}
typedef pt::WTextStream MyStream;
// move me to a better place
void esc_tex(wchar_t c, pt::WTextStream & str)
{
if( c == '$' )
str << L"\\$";
else
if( c == '#' )
str << L"\\#";
else
if( c == '%' )
str << L"\\%";
else
if( c == '&' )
str << L"\\&";
else
if( c == '\\' )
str << L"$\\backslash$";
else
if( c == '{' )
str << L"$\\{$";
else
if( c == '}' )
str << L"$\\}$";
else
if( c == '^' )
str << L""; // !! IMPROVE ME add \char with specific code
else
if( c == '_' )
str << L"\\_";
else
if( c == '~' )
str << L""; // !! IMPROVE ME add \char with specific code
else
if( c == '-' )
str << L"{-}";
else
if( c != 0 )
str << c;
}
void fil_tex(Ezc::FunInfo<MyStream> & env)
{
auto i = env.in.begin();
for( ; i != env.in.end() ; ++i)
{
esc_tex(*i, env.out);
}
}
void fil_max_size(Ezc::FunInfo<MyStream> & env)
{
auto i = env.in.begin();
size_t max_len = pt::to_ul(env.par);
size_t len = 0;
for( ; i != env.in.end() ; ++i)
{
if( len >= max_len )
{
env.out << ' ';
len = 0;
}
if( pt::is_white(*i) )
{
len = 0;
}
else
{
len += 1;
}
env.out << *i;
}
}
void cmp(Ezc::FunInfo<MyStream> & env)
{
if( env.params.size() >= 2 )
{
env.res = true;
for(size_t a=0 ; a < env.params.size() - 1 ; ++a)
{
if( env.params[a].str != env.params[a+1].str )
{
env.res = false;
break;
}
}
}
}
bool generate(const pt::Space & input_options, pt::Space & schema)
{
pt::WTextStream log_buffer;
pt::FileLog file_log;
pt::Log log;
file_log.init(L"log.txt", true, 4, true);
log.set_file_log(&file_log);
log.set_log_buffer(&log_buffer);
Ezc::Pattern pattern;
Ezc::PatternParser parser;
Ezc::Functions<MyStream> functions;
Ezc::Blocks blocks;
Ezc::Models models;
std::wstring dir = get_param(input_options.get_table(L"templates-dir"));
std::wstring template_file = get_param(input_options.get_table(L"template"));
if( dir.empty() )
{
std::cerr << "you have to set the templates directory with --templates-dir parameter" << std::endl;
return false;
}
if( template_file.empty() )
{
std::cerr << "you have to set the template file name with --template_file parameter" << std::endl;
return false;
}
functions.Insert("fil_tex", fil_tex);
functions.Insert("cmp", cmp);
functions.Insert("fil_max_size", fil_max_size);
parser.Directory(dir);
parser.SetBlocks(blocks);
parser.SetLogger(&log);
parser.ParseFile(template_file, pattern);
models.Add(L"schema", schema);
Ezc::Generator<MyStream, true, false> generator;
generator.SetPattern(pattern);
generator.SetFunctions(functions);
generator.SetModels(models);
MyStream str;
generator.SetLogger(log);
generator.Generate(str);
std::string tmp;
str.to_str(tmp);
std::cout << tmp << std::endl;
log << pt::Log::logsave;
return true;
}
} // namespace Winix
int main(int argc, const char ** argv)
{
using namespace Winix;
pt::MainOptionsParser parser;
pt::Space input_options, args, schema;
args.add(L"input-mode", 1);
args.add(L"input-file", 1);
args.add(L"templates-dir", 1);
args.add(L"template", 1);
pt::MainOptionsParser::Status status = parser.parse(argc, argv, input_options, args);
std::wstring input_mode = get_param(input_options.get_table(L"input-mode"));
std::wstring input_file = get_param(input_options.get_table(L"input-file"));
if( input_mode.empty() )
{
std::cout << "you have to use --input-mode parameter" << std::endl;
return 1;
}
print("input-mode", input_mode);
print("input-file", input_file);
bool sort_tables = input_options.has_key(L"sort-tables");
if( input_mode == L"pgmodeler" )
{
if( !use_pgmodeler(input_file, input_options, schema, sort_tables) )
return 3;
}
else
{
std::cerr << "unknown --input-mode parameter, available are: pgmodeler" << std::endl;
return 2;
}
generate(input_options, schema);
// for debug purposes
// std::string tmp;
// tmp = input_options.serialize_to_json_str(true);
// std::cout << tmp << std::endl;
}
+65
View File
@@ -0,0 +1,65 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include "misc.h"
namespace Winix
{
void print_nonl(const char * msg, const std::wstring & str)
{
std::string str_utf8;
pt::wide_to_utf8(str, str_utf8);
std::cerr << msg << ": " << str_utf8;
}
void print(const char * msg, const std::wstring & str)
{
print_nonl(msg, str);
std::cerr << std::endl;
}
void print(const char * msg, const std::wstring & str, int val)
{
print_nonl(msg, str);
std::cerr << ":" << val << std::endl;
}
}
+54
View File
@@ -0,0 +1,54 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winixcli_src_misc
#define headerfile_winixcli_src_misc
#include "space/space.h"
namespace Winix
{
void print_nonl(const char * msg, const std::wstring & str);
void print(const char * msg, const std::wstring & str);
void print(const char * msg, const std::wstring & str, int val);
}
#endif
+150
View File
@@ -0,0 +1,150 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "pgmodeler.h"
#include "html/htmlparser.h"
#include "misc.h"
namespace Winix
{
PGModeler::PGModeler()
{
}
PGModeler::~PGModeler()
{
}
bool PGModeler::parse(const std::wstring & input_file, pt::Space & schema, bool sort_tables)
{
schema.clear();
pt::HTMLParser parser;
pt::HTMLParser::Status status = parser.parse_xml_file(input_file, schema, true, true);
if( status == pt::HTMLParser::Status::cant_open_file )
{
print("cannot open the input file", input_file);
return false;
}
else
if( status == pt::HTMLParser::Status::syntax_error )
{
print("syntax error", input_file, parser.get_last_parsed_line());
schema.clear();
return false;
}
else
{
if( sort_tables )
make_sort_tables(schema);
}
return true;
}
std::pair<const std::wstring*, const std::wstring*> PGModeler::get_schema_table_names(const pt::Space & table)
{
const pt::Space * schema = table.get_space(L"schema");
const std::wstring * schema_name = nullptr;
const std::wstring * table_name = nullptr;
if( schema )
{
const pt::Space * attr = schema->get_space(L"attr");
if( attr )
{
schema_name = attr->get_wstr(L"name");
}
}
const pt::Space * attr = table.get_space(L"attr");
if( attr )
{
table_name = attr->get_wstr(L"name");
}
return std::make_pair(schema_name, table_name);
}
void PGModeler::make_sort_tables(pt::Space & schema)
{
pt::Space * dbmodel = schema.get_space(L"dbmodel");
if( dbmodel )
{
pt::Space::TableType * table = dbmodel->get_table(L"table");
if( table )
{
std::sort(table->begin(), table->end(), [](const pt::Space * t1, const pt::Space * t2) -> bool {
auto t1_names = get_schema_table_names(*t1);
auto t2_names = get_schema_table_names(*t2);
if( t1_names.first && t2_names.second && t2_names.first && t2_names.second )
{
if( *t1_names.first != *t2_names.first )
{
return *t1_names.first < *t2_names.first;
}
else
{
return *t1_names.second < *t2_names.second;
}
}
else
{
return false;
}
});
}
}
}
}
+66
View File
@@ -0,0 +1,66 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winixcli_src_pgmodeler
#define headerfile_winixcli_src_pgmodeler
#include "space/space.h"
namespace Winix
{
class PGModeler
{
public:
PGModeler();
~PGModeler();
bool parse(const std::wstring & input_file, pt::Space & schema, bool sort_tables);
private:
void make_sort_tables(pt::Space & schema);
static std::pair<const std::wstring *, const std::wstring *> get_schema_table_names(const pt::Space & table);
};
}
#endif
+108 -110
View File
@@ -1,81 +1,86 @@
# Makefile for GNU make
# GNU Makefile
include Makefile.dep
# sourcefiles: all *.cpp files except ./plugins subdirectory
# objfiles: corresponding *.o files
sourcefiles:=$(shell find . -name "*.cpp" -not \( -path ./plugins/\* \))
objfiles:=$(patsubst %.cpp,%.o,$(sourcefiles))
# sourcefiles_no_main: all *.cpp files except ./plugins and ./main subdirectories
sourcefiles_no_main:=$(shell find . -name "*.cpp" -not \( -path ./plugins/\* \) -not \( -path ./main/\* \))
objfiles_no_main:=$(patsubst %.cpp,%.o,$(sourcefiles_no_main))
# https://www.gnu.org/software/make/manual/html_node/Flavors.html#Flavors
GLOBAL_WORKING_DIR := $(shell pwd)/../..
current_path := $(shell pwd)
global_relative_working_dir := $(shell relative_path $(current_path) $(GLOBAL_WORKING_DIR))
# sourcefiles_main: all *.cpp files from ./main subdirectory
sourcefiles_main:=$(shell find main -name "*.cpp")
objfiles_main:=$(patsubst %.cpp,%.o,$(sourcefiles_main))
ifeq ($(CXX), g++)
CXX = g++6
endif
WINIX_PLUGINS_MAKEDEPEND_INCLUDES = -I../../../../winix/winixd \
-I../../../../pikotools/src \
-I../../../../morm/src \
-I../../../../ezc/src \
-I../../../../tito/src
WINIX_NEEDED_MACROS = -DPT_HAS_MORM_LIBRARY \
-DEZC_HAS_MORM_LIBRARY \
-DMORM_HAS_EZC_LIBRARY
ifndef CXX
ifeq ($(OSTYPE), FreeBSD)
CXX = clang++
else
CXX = g++6
CXX = g++
endif
endif
# CXX = g++-4.8
ifndef CXXFLAGS
CXXFLAGS = -Wall -O0 -g -fPIC -pthread -std=c++17 -I/usr/local/include -I/usr/include/postgresql -DEZC_HAS_SPECIAL_STREAM
# /usr/include/postgresql is in Linux distros (Alpine)
CXXFLAGS = -Wall -pedantic -O2 -std=c++20 -fPIC -pthread \
-I/usr/local/include \
-I/usr/include/postgresql \
-I../../winix/winixd \
-I../../pikotools/src \
-I../../morm/src \
-I../../ezc/src \
-I../../tito/src \
$(WINIX_PLUGINS_MAKEDEPEND_INCLUDES) \
$(WINIX_NEEDED_MACROS)
endif
ifndef AR
AR = ar
endif
winix_include_paths = -I$(global_relative_working_dir)/winix/winixd -I$(global_relative_working_dir)/ezc/src -I$(global_relative_working_dir)/tito/src -I$(global_relative_working_dir)/morm/src -I$(global_relative_working_dir)/pikotools
ifndef LDFLAGS
LDFLAGS = -L/usr/local/lib
LDFLAGS = -L/usr/local/lib -s
endif
# for make install
winix_install_dir = /usr/local/winix
ifndef WINIX_INSTALL_DIR
WINIX_INSTALL_DIR=/usr/local/winix
endif
ifeq ($(WINIX_INSTALL_DIR),)
$(error WINIX_INSTALL_DIR env variable cannot be empty)
endif
export CXX
export CXXFLAGS
export LDFLAGS
export GLOBAL_WORKING_DIR
export WINIX_PLUGINS_MAKEDEPEND_INCLUDES
export WINIX_NEEDED_MACROS
all: winix winix.so plugins
all: winix.so plugins winix
winix: $(objfiles_main) winix.so
$(CXX) -o winix $(CXXFLAGS) $(LDFLAGS) $(objfiles_main) winix.so -lcurl
winix.so: $(winix.src.files)
@cd core ; $(MAKE) -e
@cd db ; $(MAKE) -e
@cd functions ; $(MAKE) -e
@cd notify ; $(MAKE) -e
@cd templates ; $(MAKE) -e
@cd $(GLOBAL_WORKING_DIR)/ezc/src ; $(MAKE) -e
@cd $(GLOBAL_WORKING_DIR)/tito/src ; $(MAKE) -e
@cd $(GLOBAL_WORKING_DIR)/pikotools ; $(MAKE) -e
@cd $(GLOBAL_WORKING_DIR)/morm/src ; $(MAKE) -e
$(CXX) -shared -rdynamic -Wl,-whole-archive -o winix.so $(CXXFLAGS) $(winix_include_paths) core/*.o db/*.o functions/*.o templates/*.o notify/*.o $(GLOBAL_WORKING_DIR)/ezc/src/ezc.a $(GLOBAL_WORKING_DIR)/tito/src/tito.a $(GLOBAL_WORKING_DIR)/pikotools/convert/convert.a $(GLOBAL_WORKING_DIR)/pikotools/utf8/utf8.a $(GLOBAL_WORKING_DIR)/pikotools/space/space.a $(GLOBAL_WORKING_DIR)/pikotools/mainparser/mainparser.a $(GLOBAL_WORKING_DIR)/pikotools/date/date.a $(GLOBAL_WORKING_DIR)/pikotools/log/log.a $(GLOBAL_WORKING_DIR)/morm/src/morm.a $(LDFLAGS) -lfcgi -lpq -lz -lpthread -lcurl -Wl,-no-whole-archive
winix: winix.so $(winix.src.files)
@cd main ; $(MAKE) -e
$(CXX) -o winix $(CXXFLAGS) $(LDFLAGS) main/*.o winix.so -lfcgi
winix.so: $(objfiles_no_main)
@cd ../../pikotools ; $(MAKE) -e
@cd ../../morm ; $(MAKE) -e
@cd ../../ezc ; $(MAKE) -e
@cd ../../tito ; $(MAKE) -e
$(CXX) -shared -rdynamic -Wl,-whole-archive -o winix.so $(CXXFLAGS) $(objfiles_no_main) ../../pikotools/src/pikotools.a ../../morm/src/morm.a ../../ezc/src/ezc.a ../../tito/src/tito.a $(LDFLAGS) -lfcgi -lpq -lz -lpthread -lmagic -Wl,-no-whole-archive
plugins: FORCE
@@ -90,15 +95,17 @@ plugins: FORCE
@cd plugins/seo ; $(MAKE) -e
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) -o $@ $<
FORCE:
clean:
@cd core ; $(MAKE) -e clean
@cd db ; $(MAKE) -e clean
@cd functions ; $(MAKE) -e clean
@cd templates ; $(MAKE) -e clean
@cd notify ; $(MAKE) -e clean
clean: FORCE
rm -f $(objfiles)
rm -f winix.so
rm -f winix
@cd plugins/stats ; $(MAKE) -e clean
@cd plugins/thread ; $(MAKE) -e clean
@cd plugins/ticket ; $(MAKE) -e clean
@@ -108,75 +115,66 @@ clean:
@cd plugins/export ; $(MAKE) -e clean
@cd plugins/mailregister ; $(MAKE) -e clean
@cd plugins/seo ; $(MAKE) -e clean
@cd $(GLOBAL_WORKING_DIR)/ezc/src ; $(MAKE) -e clean
@cd $(GLOBAL_WORKING_DIR)/tito/src ; $(MAKE) -e clean
@cd $(GLOBAL_WORKING_DIR)/pikotools ; $(MAKE) -e clean
@cd $(GLOBAL_WORKING_DIR)/morm/src ; $(MAKE) -e clean
@cd main ; $(MAKE) -e clean
rm -f winix.so
rm -f winix
cleanall: clean
@cd ../../pikotools ; $(MAKE) -e clean
@cd ../../morm ; $(MAKE) -e clean
@cd ../../ezc ; $(MAKE) -e clean
@cd ../../tito ; $(MAKE) -e clean
depend:
@cd core ; $(MAKE) -e depend
@cd db ; $(MAKE) -e depend
@cd functions ; $(MAKE) -e depend
@cd templates ; $(MAKE) -e depend
@cd notify ; $(MAKE) -e depend
@cd plugins/stats ; $(MAKE) -e depend
@cd plugins/thread ; $(MAKE) -e depend
@cd plugins/ticket ; $(MAKE) -e depend
@cd plugins/gallery ; $(MAKE) -e depend
@cd plugins/group ; $(MAKE) -e depend
@cd plugins/menu ; $(MAKE) -e depend
@cd plugins/export ; $(MAKE) -e depend
@cd plugins/mailregister ; $(MAKE) -e depend
@cd plugins/seo ; $(MAKE) -e depend
@cd $(GLOBAL_WORKING_DIR)/ezc/src ; $(MAKE) -e depend
@cd $(GLOBAL_WORKING_DIR)/tito/src ; $(MAKE) -e depend
@cd $(GLOBAL_WORKING_DIR)/pikotools ; $(MAKE) -e depend
@cd main ; $(MAKE) -e depend
echo -n "winix.src.files = " > Makefile.dep
find -E . -type f -regex ".*\.h|.*\.cpp" | xargs -I foo echo -n foo " " >> Makefile.dep
# use $(global_relative_working_dir) here to put relative paths to Makefile.dep
find -E $(global_relative_working_dir)/ezc/src -type f -regex ".*\.h|.*\.cpp" | xargs -I foo echo -n foo " " >> Makefile.dep
find -E $(global_relative_working_dir)/tito/src -type f -regex ".*\.h|.*\.cpp" | xargs -I foo echo -n foo " " >> Makefile.dep
find -E $(global_relative_working_dir)/pikotools -type f -regex ".*\.h|.*\.cpp" | xargs -I foo echo -n foo " " >> Makefile.dep
find -E $(global_relative_working_dir)/morm/src -type f -regex ".*\.h|.*\.cpp" | xargs -I foo echo -n foo " " >> Makefile.dep
makedepend -w 10 -Y. -I../../pikotools/src -I../../morm/src -I../../ezc/src -I../../tito/src $(WINIX_NEEDED_MACROS) -f- $(sourcefiles) | sort -u > Makefile.dep
@cd plugins/stats ; $(MAKE) -e depend
@cd plugins/thread ; $(MAKE) -e depend
@cd plugins/ticket ; $(MAKE) -e depend
@cd plugins/gallery ; $(MAKE) -e depend
@cd plugins/group ; $(MAKE) -e depend
@cd plugins/menu ; $(MAKE) -e depend
@cd plugins/export ; $(MAKE) -e depend
@cd plugins/mailregister ; $(MAKE) -e depend
@cd plugins/seo ; $(MAKE) -e depend
@cd ../../pikotools ; $(MAKE) -e depend
@cd ../../morm ; $(MAKE) -e depend
@cd ../../ezc ; $(MAKE) -e depend
@cd ../../tito ; $(MAKE) -e depend
install: all
# installing binaries
rm -Rf $(winix_install_dir)/bin
mkdir -p $(winix_install_dir)/bin
cp winix $(winix_install_dir)/bin
cp winix.so $(winix_install_dir)/bin
# installing the main binary
rm -Rf $(WINIX_INSTALL_DIR)/bin
mkdir -p $(WINIX_INSTALL_DIR)/bin
cp winix $(WINIX_INSTALL_DIR)/bin
# installing the winix.so library
rm -Rf $(WINIX_INSTALL_DIR)/lib
mkdir -p $(WINIX_INSTALL_DIR)/lib
cp winix.so $(WINIX_INSTALL_DIR)/lib
# etc configs
rm -Rf $(winix_install_dir)/etc
mkdir -p $(winix_install_dir)/etc
cp -rf etc/* $(winix_install_dir)/etc/
rm -Rf $(WINIX_INSTALL_DIR)/etc
mkdir -p $(WINIX_INSTALL_DIR)/etc
cp -rf etc/* $(WINIX_INSTALL_DIR)/etc/
# html templates
rm -Rf $(winix_install_dir)/html
mkdir -p $(winix_install_dir)/html
cp -rf html/* $(winix_install_dir)/html/
rm -Rf $(WINIX_INSTALL_DIR)/html
mkdir -p $(WINIX_INSTALL_DIR)/html
cp -rf html/* $(WINIX_INSTALL_DIR)/html/
# txt templates
rm -Rf $(winix_install_dir)/txt
mkdir -p $(winix_install_dir)/txt
cp -rf txt/* $(winix_install_dir)/txt/
rm -Rf $(WINIX_INSTALL_DIR)/txt
mkdir -p $(WINIX_INSTALL_DIR)/txt
cp -rf txt/* $(WINIX_INSTALL_DIR)/txt/
# locales
rm -Rf $(winix_install_dir)/locale
mkdir -p $(winix_install_dir)/locale
cp -rf locale/* $(winix_install_dir)/locale/
rm -Rf $(WINIX_INSTALL_DIR)/locale
mkdir -p $(WINIX_INSTALL_DIR)/locale
cp -rf locale/* $(WINIX_INSTALL_DIR)/locale/
# plugins
rm -Rf $(winix_install_dir)/plugins
mkdir -p $(winix_install_dir)/plugins
find plugins/ -name "*.so" | xargs -I foo cp foo $(winix_install_dir)/plugins/
# deleting subversion directories
find $(winix_install_dir) -type d -name ".svn" | xargs -I foo rm -fr foo
rm -Rf $(WINIX_INSTALL_DIR)/plugins
mkdir -p $(WINIX_INSTALL_DIR)/plugins
find plugins/ -name "*.so" | xargs -I foo cp foo $(WINIX_INSTALL_DIR)/plugins/
# removing privileges for others
find $(winix_install_dir) -exec chmod o-r,o-x,o-w "{}" "+"
find $(WINIX_INSTALL_DIR) -exec chmod o-r,o-x,o-w "{}" "+"
-include Makefile.dep
+18028 -1
View File
File diff suppressed because one or more lines are too long
-24
View File
@@ -1,24 +0,0 @@
include Makefile.o.dep
current_path := $(shell pwd)
global_relative_working_dir := $(shell relative_path $(current_path) $(GLOBAL_WORKING_DIR))
winix_include_paths = -I$(global_relative_working_dir)/winix/winixd -I$(global_relative_working_dir)/ezc/src -I$(global_relative_working_dir)/tito/src -I$(global_relative_working_dir)/morm/src -I$(global_relative_working_dir)/pikotools
all: $(o)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $(winix_include_paths) $<
depend:
makedepend -Y. $(winix_include_paths) -f- *.cpp > Makefile.dep
echo -n "o = " > Makefile.o.dep
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep
clean:
rm -f *.o
include Makefile.dep
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1 +0,0 @@
o = acceptbaseparser.o app.o basethread.o bbcodeparser.o compress.o config.o crypt.o dircontainer.o dirs.o filelog.o groups.o htmlfilter.o httpsimpleparser.o image.o ipbancontainer.o item.o job.o lastcontainer.o loadavg.o lock.o log.o misc.o mount.o mountparser.o mounts.o plugin.o plugindata.o postmultiparser.o rebus.o request.o run.o session.o sessioncontainer.o sessionidmanager.o sessionmanager.o sessionparser.o slog.o synchro.o system.o threadmanager.o timezone.o timezones.o user.o users.o winixbase.o winixmodel.o winixrequest.o winixsystem.o
+732 -1172
View File
File diff suppressed because it is too large Load Diff
+43 -91
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2018, Tomasz Sowa
* Copyright (c) 2010-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,27 +46,23 @@
#include <fcgiapp.h>
#include "sessionmanager.h"
#include "db/db.h"
#include "functions/functions.h"
#include "templates/templates.h"
#include "compress.h"
#include "postparser.h"
#include "cookieparser.h"
#include "postmultiparser.h"
#include "acceptencodingparser.h"
#include "space/jsontospaceparser.h"
#include "utils/acceptencodingparser.h"
#include "winixrequest.h"
#include "log/log.h"
#include "filelog.h"
#include "models/winixmodelconnector.h"
namespace Winix
{
class App
{
public:
@@ -77,16 +73,19 @@ public:
bool DropPrivileges();
void InitLoggers();
Log & GetMainLog();
void InitPlugins();
bool InitializePlugins();
bool Init();
bool InitializeRequestForFastCGI(Request & request);
void SetRequestDependency(Request & request);
void InitializeNewRequest(Request & request);
void PutRequestToJob();
void Start();
void Close();
void LogUserGroups();
bool Demonize();
void SetStopSignal();
bool WasStopSignal();
bool Lock();
void Unlock();
Synchro * GetSynchro();
void StartThreads();
void WaitForThreads();
@@ -96,22 +95,11 @@ public:
// pointers to the current request and a session
Cur cur;
// temporary one request object
// current request
Request req;
// users sessions
SessionManager session_manager;
// database (DEPRACATED)
Db db;
DbConn db_conn;
/*
model
*/
// an unique id for each request
size_t request_id;
// ...
System system;
@@ -124,9 +112,6 @@ public:
bool stdout_is_closed;
/*
view
*/
Templates templates;
@@ -135,44 +120,32 @@ public:
private:
enum Header
{
h_200,
h_404,
h_403
};
PostParser post_parser;
PostMultiParser post_multi_parser;
PT::JSONToSpaceParser post_json_parser;
std::string post_buffer;
pt::SpaceParser space_parser;
CookieParser cookie_parser;
AcceptBaseParser accept_base_parser;
AcceptEncodingParser accept_encoding_parser;
Compress compress;
FCGX_Request fcgi_request;
int fcgi_socket;
Synchro synchro;
pthread_t signal_thread;
std::string socket_to_send_on_exit;
std::string send_data_buf;
PT::SpaceToJSON json_generic_serializer;
TextStream<std::wstring> json_out_stream;
std::string aheader_name, aheader_value;
std::wstring html_filtered;
std::string output_8bit;
BinaryPage compressed_output;
std::wstring cookie_id_string;
std::wstring http_header;
std::string http_header_8bit;
pt::WTextStream post_log_tmp_buffer;
morm::ModelConnector model_connector; // main thread model connector, each thread has its own connector
std::wstring http_header_name;
std::wstring http_header_value;
pt::WTextStream empty_response;
WinixModelConnector model_connector; // main thread model connector, each thread has its own connector
morm::JSONConnector json_connector;
morm::XMLConnector xml_connector;
morm::PostgreSQLConnector postgresql_connector;
// objects for main thread
WinixBase winix_base;
WinixModel winix_model;
WinixModelDeprecated winix_model;
WinixSystem winix_system;
WinixRequest winix_request;
// ///////////////////////
@@ -182,19 +155,22 @@ private:
//////////////////////////
// log_buffer for the main thread
PT::WTextStream log_buffer;
pt::WTextStream log_buffer;
// logger only for App object
// logger only for the main thread
Log log;
// file logger, one object for every Log objects
// file logger, one object for all Log objects
FileLog file_log;
bool InitFCGI(char * sock, char * sock_user, char * sock_group);
bool InitFCGIChmodChownSocket(char * sock, char * sock_user, char * sock_group);
bool AddSystemThreads();
bool InitFCGIChmodChownSocket(const char * sock);
bool DropPrivileges(char * user, char * group);
bool DropPrivileges(const char * user, uid_t uid, gid_t gid, bool additional_groups);
bool CheckAccessFromPlugins();
void MakeRenameMeToABetterName();
bool AddRootDir();
void ProcessRequestThrow();
void ProcessRequest();
void BaseUrlRedirect(int code, bool add_subdomain);
@@ -202,59 +178,31 @@ private:
void CheckIfNeedSSLredirect();
void SetLocale();
void CheckPostRedirect();
void MakePage();
void Make();
void AddDefaultModels();
void SaveSessionsIfNeeded(); // !! IMPROVE ME wywalic do menagera sesji??
void LogAccess();
void SendData(const BinaryPage & page, FCGX_Stream * out);
void CreateJSONAnswer();
void ReadRequest();
void SendTextAnswer();
void SendBinaryAnswer();
void SendAnswer();
void LogEnvironmentVariables();
void LogEnvironmentHTTPVariables();
void ParseAcceptHeader(const wchar_t * header_name, const std::wstring & env, std::vector<HeaderValue> & container, size_t max_len);
void ParseAcceptHeader();
void ParseAcceptLanguageHeader();
void SetEnv(const char * name, std::wstring & env);
void ReadEnvVariables();
void ReadEnvHTTPVariables();
bool SaveEnvHTTPVariable(const char * env);
void ReadEnvRemoteIP();
void ReadPostJson();
void ReadInputPostToBuffer();
void ParsePostJson();
void ReadPostJson(bool copy_raw_post);
void ReadPostVars();
void CheckIE();
void CheckKonqueror();
void CheckRequestMethod();
void CheckSSL();
void SetSubdomain();
Header GetHTTPStatusCode();
void PrepareSessionCookie();
void FilterContent();
void CheckHtmx();
bool IsRequestedFrame();
void SendHeaders();
void SendCookies();
bool AddHeader(const wchar_t * name, const wchar_t * value);
bool AddHeader(const std::wstring & name, const std::wstring & value);
bool AddHeader(const wchar_t * name, const PT::WTextStream & value);
bool AddHeader(const std::wstring & name, const PT::WTextStream & value);
bool PrepareHeadersStaticCreateResource(PT::WTextStream & out_path);
void PrepareHeadersStatic();
void PrepareHeaderContentType();
void PrepareHeadersForbidden();
void PrepareHeadersRedirect();
void PrepareHeadersSendFile();
void PrepareHeadersCompression(int compress_encoding);
void PrepareHeadersNormal(Header header, size_t output_size);
void PrepareHeaders(bool compressing, int compress_encoding, Header header, size_t output_size);
void PrepareStandardJSONFields();
int SelectDeflateVersion();
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
bool CanSendContent();
void ClearAfterRequest();
void IncrementRequestId();
void LogUser(const char * msg, uid_t id);
void LogGroup(const char * msg, gid_t id, bool put_logend = true);
@@ -267,6 +215,10 @@ private:
void CreateStaticTree();
bool DoDatabaseMigration();
bool TryToMakeDatabaseMigration();
// !! IMPROVE ME
// !! move to the session manager?
time_t last_sessions_save;
+17 -9
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2019, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,10 +42,11 @@ namespace Winix
BaseThread::BaseThread() : thread_signal(PTHREAD_COND_INITIALIZER)
{
synchro = 0;
thread_id = 0;
work_mode = 0;
wake_up_was_called = false;
synchro = nullptr;
thread_id = 0;
work_mode = 0;
wake_up_was_called = false;
main_model_connector = nullptr;
}
@@ -54,15 +55,21 @@ BaseThread::~BaseThread()
}
void BaseThread::set_main_log_buffer(PT::WTextStream * log_buffer)
void BaseThread::set_main_log_buffer(pt::WTextStream * log_buffer)
{
main_log.SetLogBuffer(log_buffer);
main_log.set_log_buffer(log_buffer);
}
void BaseThread::set_main_file_log(PT::FileLog * file_log)
void BaseThread::set_main_file_log(pt::FileLog * file_log)
{
main_log.SetFileLog(file_log);
main_log.set_file_log(file_log);
}
void BaseThread::set_main_model_connector(morm::ModelConnector * main_model_connector)
{
this->main_model_connector = main_model_connector;
}
@@ -254,6 +261,7 @@ void * BaseThread::StartRoutine(void * this_object)
}
}
base->save_log();
pthread_exit(0);
return 0;
}
+16 -13
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2019, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
#include <pthread.h>
#include "synchro.h"
#include "winixmodel.h"
#include "winixmodeldeprecated.h"
@@ -47,16 +47,17 @@ namespace Winix
class BaseThread : public WinixModel
class BaseThread : public WinixModelDeprecated
{
public:
BaseThread();
virtual ~BaseThread();
void set_main_log_buffer(PT::WTextStream * log_buffer);
void set_main_file_log(PT::FileLog * file_log);
void set_main_log_buffer(pt::WTextStream * log_buffer);
void set_main_file_log(pt::FileLog * file_log);
void set_main_model_connector(morm::ModelConnector * main_model_connector);
// work mode
// we have two modes:
@@ -105,11 +106,13 @@ protected:
// logger for the main thread
Log main_log;
// log from WinixBase is meant to be used by the second thread
// log from WinixBase is meant to be used by the other thread
// model connector for the main thread
// model_connector from the based class WinixModelDeprecated is meant to be used by the second thread
morm::ModelConnector * main_model_connector;
protected:
// signal came (work mode = 0 - default)
@@ -141,12 +144,12 @@ protected:
void SignalLoop();
static void * StartRoutine(void *);
bool BaseInit();
void BaseUninit();
bool BaseSignalReceived();
void BaseDo();
bool WaitForSignal();
bool WaitForSignalSleep(time_t second);
virtual bool BaseInit();
virtual void BaseUninit();
virtual bool BaseSignalReceived();
virtual void BaseDo();
virtual bool WaitForSignal();
virtual bool WaitForSignalSleep(time_t second);
bool Lock();
void Unlock();
-636
View File
@@ -1,636 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "bbcodeparser.h"
namespace Winix
{
bool BBCODEParser::Equal(const wchar_t * str1, const wchar_t * str2)
{
while( *str1 == *str2 && *str1 != 0 )
{
str1 += 1;
str2 += 1;
}
return *str1 == *str2;
}
bool BBCODEParser::IsValidCharForName(int c)
{
if( (c>='a' && c<='z') ||
(c>='A' && c<='Z') ||
c=='*' || c=='_')
return true;
return false;
}
bool BBCODEParser::IsOpeningTagMark(wchar_t c)
{
return (c == '[');
}
bool BBCODEParser::IsClosingTagMark(wchar_t c)
{
return (c == ']');
}
bool BBCODEParser::IsClosingXmlSimpleTagMark(wchar_t c)
{
return false;
}
// there are no commentaries in bbcode
bool BBCODEParser::IsOpeningCommentaryTagMark(const wchar_t *)
{
return false;
}
size_t BBCODEParser::OpeningCommentaryTagMarkSize()
{
return 0;
}
bool BBCODEParser::SkipCommentaryTagIfExists()
{
return false;
}
// one enter will generate one <br>
// two enters or more will generate only two br (<br><br>)
void BBCODEParser::PutNormalText(const wchar_t * str, const wchar_t * end)
{
int br_len;
if( *pchar == 0 )
{
// trimming last white characters at end of the user text
while( str<end && (IsWhite(*(end-1)) || *(end-1)==10) )
--end;
}
while( str < end )
{
if( *str == 10 )
{
++str;
br_len = 1;
// skipping white characters without a new line character
while( str < end && IsWhite(*str) )
++str;
if( str < end && *str == 10 )
{
br_len = 2;
// skipping white characters with new line characters
while( str < end && (IsWhite(*str) || *str==10) )
++str;
}
if( !has_open_ol_tag && !has_open_ul_tag && !has_open_li_tag )
{
for(int i=0 ; i < br_len ; ++i)
(*out_string) += L"<br>\n";
}
}
else
{
PrintEscape(*str);
++str;
}
}
}
void BBCODEParser::ReadNormalTextSkipWhite(const wchar_t * & start, const wchar_t * & last_non_white)
{
}
void BBCODEParser::CheckExceptions()
{
if( stack_len >= 2 )
{
if( pstack[stack_len-1].type == Item::opening &&
pstack[stack_len-2].type == Item::opening &&
IsNameEqual(L"*", pstack[stack_len-1].name) &&
IsNameEqual(L"*", pstack[stack_len-2].name) )
{
// removing the last [*] from the stack
// </li> was put automatically
PopStack();
}
}
}
/*
bbcode format:
[bbcodetag=value]some text[/bbcodetag]
the value can be quoted, e.g.
[bbcodetag="value"]some text[/bbcodetag], or
[bbcodetag='value']some text[/bbcodetag]
the third string below (in tags table) is 'html_argument' from Tags,
it can contain a special character % followed by a string which means:
%1 - "value" escaped as for html
%2 - "some text" escaped as for html
%u1 - "value" trimmed and escaped as for url-es
%u2 - "some text" trimmed and escaped as for url-es
%% - one %
if you are using %2 or %u2 then "some text" is not treated as bbcode, e.g.
[bbcodetag=value]some [b]text[/b][/bbcodetag] will produce:
<htmltag arg="value">some [b]text[/b]</htmltag> (the inner tags [b][/b] were not parsed)
also when using %2 or %u2 the closing bbcode tag is skipped
(if you want this tag then you can put it in 'html_argument')
and when using u (%u1 or %u2) the argument is trimmed from whitespaces and new lines
at the beginning and at the end
(because otherwise a space would be changed to %20 and this were probably not what you really wanted)
*/
const BBCODEParser::Tags * BBCODEParser::FindTag(const wchar_t * tag)
{
static Tags tags[] = {
{L"*", L"li", L">", false},
{L"b", L"em", L">", true},
{L"i", L"span", L" class=\"bbitalic\">", true},
{L"u", L"span", L" class=\"bbunderline\">", true},
{L"s", L"span", L" class=\"bbstrike\">", true},
{L"code", L"code", L" class=\"bbcode\">", false},
{L"list", L"ul", L" class=\"bblist\">", false},
{L"color", L"span", L" class=\"bbcol%1\">", true},
{L"url", L"a", L" href=\"%u1\">", true},
{L"img", L"img", L" alt=\"%1\" src=\"%u2\">", true},
{L"quote", L"div", L" class=\"bbquote\">\n<span class=\"bbquotewho\">%1</span><br>\n", false},
};
size_t i;
size_t len = sizeof(tags) / sizeof(Tags);
for(i=0 ; i<len ; ++i)
{
if( Equal(tag, tags[i].bbcode) )
return &tags[i];
}
return 0;
}
const BBCODEParser::Tags * BBCODEParser::FindTag(const std::wstring & tag)
{
return FindTag(tag.c_str());
}
void BBCODEParser::PrintArgumentCheckQuotes(const wchar_t * & start, const wchar_t * & end)
{
// skipping white characters from the argument
while( start<end && IsWhite(*start) )
++start;
// skipping first '=' character if exists
if( start<end && *start == '=' )
++start;
// skipping white characters from the argument
// at the beginning
while( start<end && IsWhite(*start) )
++start;
// and at the end
while( start<end && IsWhite(*(end-1)) )
--end;
if( start<end && (*start=='\'' || *start=='\"') )
{
++start;
if( start<end && *(start-1) == *(end-1) )
--end;
// skipping white characters after a first quote char [url = " ww...."]
while( start<end && IsWhite(*start) )
++start;
}
}
void BBCODEParser::PrintEncode(int c)
{
if( c == '&' )
{
(*out_string) += L"&amp;";
}
else
if( (c>='a' && c<='z') ||
(c>='A' && c<='Z') ||
(c>='0' && c<='9') ||
(c=='_' || c=='?' || c=='.' || c==',' || c=='/' || c=='-' ||
c=='+' || c=='*' || c=='(' || c==')' || c=='=' || c==':')
)
{
(*out_string) += c;
}
else
{
wchar_t buffer[20];
swprintf(buffer, 20, L"%02X", c);
(*out_string) += '%';
(*out_string) += buffer;
}
}
void BBCODEParser::PrintEscape(int c, bool change_quote)
{
if( c == '<' )
{
(*out_string) += L"&lt;";
}
else
if( c == '>' )
{
(*out_string) += L"&gt;";
}
else
if( c == '&' )
{
(*out_string) += L"&amp;";
}
else
if( c == '\"' && change_quote )
{
(*out_string) += L"&quot;";
}
else
{
(*out_string) += c;
}
}
void BBCODEParser::PrintArgumentEncode(const wchar_t * start, const wchar_t * end)
{
PrintArgumentCheckQuotes(start, end);
TrimWhiteWithNewLines(start, end);
for( ; start<end ; ++start )
PrintEncode(*start);
}
void BBCODEParser::PrintArgumentEscape(const wchar_t * start, const wchar_t * end)
{
PrintArgumentCheckQuotes(start, end);
for( ; start<end ; ++start )
PrintEscape(*start, true); // quotes are escaped as well here
}
void BBCODEParser::CheckOpeningTag(const Tags * tag, const wchar_t * tag_name, bool & condition)
{
if( Equal(tag->html_tag, tag_name) )
{
if( condition )
{
PutClosingTag(tag);
(*out_string) += '\n';
}
condition = true;
}
}
void BBCODEParser::CheckOpeningTag(const Tags * tag)
{
bool has_list_tag = has_open_ul_tag || has_open_ol_tag;
CheckOpeningTag(tag, L"li", has_open_li_tag);
CheckOpeningTag(tag, L"ul", has_open_ul_tag);
CheckOpeningTag(tag, L"ol", has_open_ol_tag);
if( has_open_li_tag && !has_list_tag )
{
(*out_string) += L"<ul>\n";
has_open_ul_tag = true;
}
}
void BBCODEParser::PrintEscape(const wchar_t * start, const wchar_t * end, bool change_quote)
{
for( ; start < end ; ++start)
PrintEscape(*start, change_quote);
}
void BBCODEParser::PrintEncode(const wchar_t * start, const wchar_t * end)
{
for( ; start < end ; ++start)
PrintEncode(*start);
}
void BBCODEParser::PutOpeningTagFromEzc()
{
// this can be a tag from Ezc templates system
(*out_string) += '[';
(*out_string) += LastItem().name;
const wchar_t * start = pchar;
while( *pchar && *pchar!=']' )
++pchar;
if( *pchar == ']' )
++pchar;
Put(start, pchar);
}
void BBCODEParser::PutHtmlArgument1(const wchar_t * arg_start, const wchar_t * arg_end, bool has_u)
{
if( has_u )
PrintArgumentEncode(arg_start, arg_end);
else
PrintArgumentEscape(arg_start, arg_end);
}
void BBCODEParser::TrimWhiteWithNewLines(const wchar_t * & start, const wchar_t * & end)
{
while( start < end && (IsWhite(*start) || *start==10) )
++start;
while( start < end && (IsWhite(*(end-1)) || *(end-1)==10) )
--end;
}
void BBCODEParser::PutHtmlArgument2(const Tags * tag, bool has_u)
{
const wchar_t * start = pchar;
const wchar_t * end = pchar;
bool first_tag_removed = false;
while( *pchar != 0 )
{
if( IsOpeningTagMark(*pchar) )
{
if( IsClosingTagForLastItem() )
{
// the last tag is skipped when using patterns with %2 or %u2
PopStack(); // removing opening tag from the stack
first_tag_removed = true;
break;
}
}
else
{
pchar += 1;
end = pchar;
}
}
if( !first_tag_removed )
PopStack(); // user has forgotten to close the tag
if( has_u )
{
TrimWhiteWithNewLines(start, end);
PrintEncode(start, end);
}
else
{
PrintEscape(start, end);
}
}
void BBCODEParser::PutHtmlArgument(const Tags * tag, const wchar_t * arg_start, const wchar_t * arg_end)
{
const wchar_t * pattern = tag->html_argument;
bool has_u;
while( *pattern )
{
if( *pattern == '%' )
{
++pattern;
has_u = false;
if( *pattern == 'u' )
{
++pattern;
has_u = true;
}
if( *pattern == '1' )
{
++pattern;
PutHtmlArgument1(arg_start, arg_end, has_u);
}
else
if( *pattern == '2' )
{
++pattern;
PutHtmlArgument2(tag, has_u);
}
else
if( *pattern == '%' )
{
(*out_string) += '%';
++pattern;
}
// else unrecognized, will be printed next time as a normal character
}
else
{
(*out_string) += *pattern;
++pattern;
}
}
}
void BBCODEParser::PutOpeningTagFromBBCode(const Tags * tag)
{
CheckOpeningTag(tag);
PutOpeningTagMark();
Put(tag->html_tag);
const wchar_t * start = pchar;
while( *pchar && *pchar != ']' )
++pchar;
PutHtmlArgument(tag, start, pchar);
if( *pchar == ']' )
++pchar;
if( !tag->inline_tag )
{
Put(10);
SkipWhiteLines();
}
}
bool BBCODEParser::PutOpeningTag()
{
const Tags * tag = FindTag(LastItem().name);
if( !tag )
PutOpeningTagFromEzc();
else
PutOpeningTagFromBBCode(tag);
return false;
}
void BBCODEParser::PutClosingTag(const Tags * tag)
{
if( !tag )
return; // skipping the tag
PutOpeningTagMark();
(*out_string) += '/';
(*out_string) += tag->html_tag;
PutClosingTagMark();
if( !tag->inline_tag )
{
(*out_string) += L"\n";
SkipWhiteLines();
}
if( Equal(tag->html_tag, L"li") )
has_open_li_tag = false;
if( Equal(tag->html_tag, L"ol") )
has_open_ol_tag = false;
if( Equal(tag->html_tag, L"ul") )
has_open_ul_tag = false;
}
void BBCODEParser::PutClosingTag(const wchar_t * tag_name)
{
const Tags * tag = FindTag(tag_name);
PutClosingTag(tag);
}
void BBCODEParser::Init()
{
has_open_li_tag = false;
has_open_ol_tag = false;
has_open_ul_tag = false;
SkipWhiteLines();
}
void BBCODEParser::Uninit()
{
if( has_open_li_tag )
(*out_string) += L"</li>\n";
if( has_open_ol_tag )
(*out_string) += L"</ol>\n";
if( has_open_ul_tag )
(*out_string) += L"</ul>\n";
}
} // namespace Winix
-127
View File
@@ -1,127 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_bbcodeparser
#define headerfile_winix_core_bbcodeparser
#include "htmlfilter.h"
namespace Winix
{
class BBCODEParser : public HTMLFilter
{
struct Tags
{
const wchar_t * bbcode;
const wchar_t * html_tag;
const wchar_t * html_argument; // with closing '>'
bool inline_tag;
};
/*
virtual methods
(from HTMLFilter class)
*/
virtual void Init();
virtual void Uninit();
virtual bool IsOpeningTagMark(wchar_t c);
virtual bool IsClosingTagMark(wchar_t c);
virtual bool IsClosingXmlSimpleTagMark(wchar_t c);
virtual bool IsOpeningCommentaryTagMark(const wchar_t *);
virtual size_t OpeningCommentaryTagMarkSize();
virtual bool IsValidCharForName(int c);
virtual void CheckExceptions();
virtual bool SkipCommentaryTagIfExists();
virtual bool PutOpeningTag();
virtual void PutClosingTag(const wchar_t * tag);
virtual void PutNormalText(const wchar_t * str, const wchar_t * end);
virtual void ReadNormalTextSkipWhite(const wchar_t * & start, const wchar_t * & last_non_white);
/*
others
*/
bool Equal(const wchar_t * str1, const wchar_t * str2);
void PutHtmlArgument1(const wchar_t * arg_start, const wchar_t * arg_end, bool has_u);
void PutHtmlArgument2(const Tags * tag, bool has_u);
void PutHtmlArgument(const Tags * tag, const wchar_t * arg_start, const wchar_t * arg_end);
void PutOpeningTagFromEzc();
void PutOpeningTagFromBBCode(const Tags * tag);
const Tags * FindTag(const wchar_t * tag);
const Tags * FindTag(const std::wstring & tag);
void PrintArgumentCheckQuotes(const wchar_t * & start, const wchar_t * & end);
void PrintEscape(int c, bool change_quote = false);
void PrintEncode(int c);
void PrintEscape(const wchar_t * start, const wchar_t * end, bool change_quote = false);
void PrintEncode(const wchar_t * start, const wchar_t * end);
void PrintArgumentEncode(const wchar_t * start, const wchar_t * end);
void PrintArgumentEscape(const wchar_t * start, const wchar_t * end);
void PutClosingTag(const Tags * tag);
void CheckOpeningTag(const Tags * tag, const wchar_t * tag_name, bool & condition);
void CheckOpeningTag(const Tags * tag);
void TrimWhiteWithNewLines(const wchar_t * & start, const wchar_t * & end);
bool has_open_ol_tag; // has open html <ol> tag
bool has_open_ul_tag; // has open html <ul> tag
bool has_open_li_tag; // has open html <li> tag
};
} // namespace Winix
#endif
+2
View File
@@ -258,6 +258,8 @@ BinaryPage::const_iterator i = page.begin();
source_len -= strm.avail_in;
flush = (source_len == 0) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = (Bytef*)buffer_in;
// IMPROVE ME we can add an interface to pt::TextStreamBase<> and get all chunks of memory
CopyToInputBuffer(i, strm.avail_in);
do
+111 -95
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,47 +45,39 @@ namespace Winix
Config::Config()
{
errors_to_stdout = true;
}
void Config::SetFileLog(FileLog * file_log)
{
log.SetFileLog(file_log);
log.set_file_log(file_log);
}
void Config::SetLogBuffer(PT::WTextStream * log_buffer)
void Config::SetLogBuffer(pt::WTextStream * log_buffer)
{
log.SetLogBuffer(log_buffer);
log.set_log_buffer(log_buffer);
}
void Config::ShowError()
void Config::ShowError(const std::wstring & config_file)
{
switch( parser.status )
{
case PT::SpaceParser::no_space:
log << log2 << "Config: space not set" << logend;
case pt::SpaceParser::ok:
break;
case PT::SpaceParser::ok:
log << log2 << "Config: syntax ok" << logend;
case pt::SpaceParser::cant_open_file:
log << log1 << "Config: I cannot open a config file: " << config_file << logend;
break;
case PT::SpaceParser::cant_open_file:
if( errors_to_stdout )
std::wcout << L"Config: I cannot open a config file: " << config_file << std::endl;
log << log1 << "Config: cant open a config file: " << config_file << logend;
case pt::SpaceParser::syntax_error:
log << log1 << "Config: syntax error in file: " << config_file << ", line: "
<< parser.get_last_parsed_line() << ":" << parser.get_last_parsed_column() << logend;
break;
case PT::SpaceParser::syntax_error:
if( errors_to_stdout )
std::wcout << "Config: syntax error, line: " << parser.line << std::endl;
log << log1 << "Config: syntax error, line: " << parser.line << logend;
default:
// there are no limits sets when parsing the config file
break;
}
}
@@ -95,38 +87,38 @@ void Config::ShowError()
bool Config::ReadConfig(bool errors_to_stdout_, bool stdout_is_closed)
bool Config::ReadConfig(const std::wstring & config_file)
{
errors_to_stdout = errors_to_stdout_;
if( config_file.empty() )
{
log << log2 << "Config: name of the config file is empty" << logend;
return false;
}
log << log2 << "Config: reading a config file" << logend;
log << log2 << "Config: reading a config file: " << config_file << logend;
pt::SpaceParser::Status status = parser.parse_space_file(config_file, space, false);
parser.SetSpace(space);
PT::SpaceParser::Status status = parser.Parse(config_file);
if( status == PT::SpaceParser::ok )
if( status == pt::SpaceParser::ok )
{
AssignValues(stdout_is_closed);
SetAdditionalVariables();
return true;
}
else
{
ShowError();
ShowError(config_file);
return false;
}
}
void Config::AssignValuesFromSpace()
{
AssignValues();
SetAdditionalVariables();
}
void Config::AssignValues(bool stdout_is_closed)
void Config::AssignValues()
{
server_mode = Text(L"server_mode");
demonize = Bool(L"demonize", true);
@@ -138,10 +130,13 @@ void Config::AssignValues(bool stdout_is_closed)
log_file = Text(L"log_file");
log_delimiter = Text(L"log_delimiter", L"---------------------------------------------------------------------------------");
fcgi_socket = Text(L"fcgi_socket");
fcgi_set_socket_chmod = Bool(L"fcgi_set_socket_chmod", true);
fcgi_set_socket_owner = Bool(L"fcgi_set_socket_owner", true);
fcgi_socket_chmod = Int(L"fcgi_socket_chmod", 0770);
fcgi_socket_user = Text(L"fcgi_socket_user");
fcgi_socket_group = Text(L"fcgi_socket_group");
fcgi_socket_listen = Int(L"fcgi_socket_listen", 100);
fcgi_socket_listen = Int(L"fcgi_socket_listen", 1024);
fcgi_cannot_create_request_delay = Size(L"fcgi_cannot_create_request_delay", 3);
log_level = Int(L"log_level", 1);
log_request = Int(L"log_request", 1);
log_save_each_line = Bool(L"log_save_each_line", false);
@@ -153,9 +148,15 @@ void Config::AssignValues(bool stdout_is_closed)
log_post_value_size = Size(L"log_post_value_size", 80);
log_env_variables = Bool(L"log_env_variables", false);
log_env_http_variables = Bool(L"log_env_http_variables", false);
log_whole_http_post = Bool(L"log_whole_http_post", false);
log_http_answer_headers = Bool(L"log_http_answer_headers", false);
post_file_max = Size(L"post_file_max", 8388608); // 8 MB
post_json_max = Size(L"post_json_max", 8388608); // 8 MB
post_max_object_items = Size(L"post_max_object_items", 1024);
post_max_table_items = Size(L"post_max_table_items", 4096);
post_max_all_items = Size(L"post_max_all_items", 8192);
post_max_nested_objects = Size(L"post_max_nested_objects", 32);
upload_dir = Text(L"upload_dir");
common_dir = Text(L"common_dir");
@@ -186,14 +187,33 @@ void Config::AssignValues(bool stdout_is_closed)
templates_fun_prefix = Text(L"templates_fun_prefix", L"fun_");
templates_fun_postfix = Text(L"templates_fun_postfix", L".html");
templates_index = Text(L"templates_index", L"index.html");
templates_index_generic = Text(L"templates_index_generic", L"index_generic.html");
templates_index_raw = Text(L"templates_index_raw", L"index_raw.html");
templates_request_status = Text(L"templates_request_status", L"request_status.html");
template_only_root_use_template_fun = Bool(L"template_only_root_use_template_fun", false);
http_session_id_name = Text(L"http_session_id_name", L"session_id");
use_internal_session_mechanism = Bool(L"use_internal_session_mechanism", true);
use_internal_loggin_mechanism = Bool(L"use_internal_loggin_mechanism", true);
session_cookie_name = Text(L"session_cookie_name", L"session_id");
session_cookie_path = Text(L"session_cookie_path", L"/");
session_cookie_domain = Text(L"session_cookie_domain", L"");
session_cookie_same_site = Int(L"session_cookie_same_site", 0);
session_cookie_http_only = Bool(L"session_cookie_http_only", false);
session_cookie_secure = Bool(L"session_cookie_secure", false);
db_conn_string = Text(L"db_conn_string");
db_host = Text(L"db_host");
db_hostaddr = Text(L"db_hostaddr");
db_port = Text(L"db_port");
db_database = Text(L"db_database");
db_user = Text(L"db_user");
db_pass = Text(L"db_pass");
db_postgresql_smaller_than_10 = Bool(L"db_postgresql_smaller_than_10", false);
db_startup_connection_max_attempts = Size(L"db_startup_connection_max_attempts", 0);
db_startup_connection_attempt_delay = Size(L"db_startup_connection_attempt_delay", 5);
db_make_migration_if_needed = Bool(L"db_make_migration_if_needed", true);
db_stop_if_migration_fails = Bool(L"db_stop_if_migration_fails", true);
item_url_empty = Text(L"item_url_empty");
@@ -239,9 +259,8 @@ void Config::AssignValues(bool stdout_is_closed)
compression_page_min_size = Size(L"compression_page_min_size", 512);
compression_encoding = Int(L"compression_encoding", 20);
html_filter = Bool(L"html_filter", true);
html_filter_trim_white = Bool(L"html_filter_trim_white", true);
html_filter_break_word = Int(L"html_filter_break_word", 60);
html_filter = Bool(L"html_filter", false);
html_filter_white_char_mode = Int(L"html_filter_white_char_mode", 2);
html_filter_wrap_line = Int(L"html_filter_wrap_line", 110);
html_filter_tabs = Size(L"html_filter_tabs", 2);
html_filter_orphans = Bool(L"html_filter_orphans", true);
@@ -256,7 +275,9 @@ void Config::AssignValues(bool stdout_is_closed)
title_separator = Text(L"title_separator", L" / ");
http_header_send_file = Text(L"http_header_send_file", L"X-LIGHTTPD-send-file");
send_file_mode = Int(L"send_file_mode", 0);
send_file_header = Text(L"send_file_header", L"X-SENDFILE");
send_file_relative_prefix = Text(L"send_file_relative_prefix", L"upload-files-internal");
editors_html_safe_mode = Bool(L"editors_html_safe_mode", true);
editors_html_safe_mode_skip_root = Bool(L"editors_html_safe_mode_skip_root", true);
@@ -287,8 +308,20 @@ void Config::AssignValues(bool stdout_is_closed)
ezc_max_elements = Size(L"ezc_max_elements", 50000);
ezc_max_loop_elements = Size(L"ezc_max_loop_elements", 5000);
ezc_out_streams_size = Size(L"ezc_out_streams_size", 128);
ezc_error_prefix = Text(L"ezc_error_prefix", L"<!-- ");
ezc_error_postfix = Text(L"ezc_error_postfix", L" -->");
request_frame_parameter = Text(L"request_frame_parameter", L"frame");
request_all_frames_parameter = Text(L"request_all_frames_parameter", L"all_frames");
request_main_stream_parameter = Text(L"request_main_stream_parameter", L"main_stream");
request_frame_parameter_max_length = Size(L"request_frame_parameter_max_length", 128);
request_frame_parameter_max_frames = Size(L"request_frame_parameter_max_frames", 16);
xml_root = Text(L"xml_root", L"winix");
bin_stream_field = Text(L"bin_stream_field", L"bin_stream");
main_stream_field = Text(L"main_stream_field", L"main_stream");
ezc_frames_field = Text(L"ezc_frames_field", L"ezc_frames");
request_max_accept_fields = Size(L"request_max_accept_fields", 8);
request_max_accept_language_fields = Size(L"request_max_accept_language_fields", 8);
account_need_email_verification = Bool(L"account_need_email_verification", true);
reset_password_code_expiration_time = Long(L"reset_password_code_expiration_time", 86400);
@@ -313,12 +346,22 @@ void Config::AssignValues(bool stdout_is_closed)
incorrect_login_cannot_login_delay = Size(L"incorrect_login_cannot_login_delay", 1800);
pid_file = Text(L"pid_file", L"");
allow_ezc_out_in_executable_items = Bool(L"allow_ezc_out_in_executable_items", false);
allow_ezc_frames_in_executable_items = Bool(L"allow_ezc_frames_in_executable_items", false);
check_proxy_ip_header = Bool(L"check_proxy_ip_header", false);
proxy_ip_header = Text(L"proxy_ip_header", L"X_Real_IP");
use_antispam_mechanism_for_not_logged_users = Bool(L"use_antispam_mechanism_for_not_logged_users", true);
antispam_list_max_size = Size(L"antispam_list_max_size", 10);
add_header_cache_no_store_in_htmx_request = Bool(L"add_header_cache_no_store_in_htmx_request", true);
request_queue_job_limit = Size(L"request_queue_job_limit", 1024);
ListText(L"allowed_origins", allowed_origins);
allow_all_origins = Bool(L"allow_all_origins", true);
are_cors_preflight_requests_available = Bool(L"are_cors_preflight_requests_available", false);
ListText(L"access_control_expose_headers", access_control_expose_headers);
access_control_allow_credentials = Bool(L"access_control_allow_credentials", false);
}
@@ -381,150 +424,123 @@ void Config::CheckPasswd()
std::wstring Config::Text(const wchar_t * name)
{
return space.Text(name);
return space.to_wstr(name);
}
std::wstring Config::Text(const wchar_t * name, const wchar_t * def)
{
return space.Text(name, def);
return space.to_wstr(name, def);
}
std::wstring Config::Text(const std::wstring & name, const wchar_t * def)
{
return space.Text(name, def);
}
std::wstring & Config::TextRef(const wchar_t * name)
{
return space.TextRef(name);
}
std::wstring & Config::TextRef(const wchar_t * name, const wchar_t * def)
{
return space.TextRef(name, def);
}
std::wstring & Config::TextRef(const std::wstring & name, const wchar_t * def)
{
return space.TextRef(name, def);
return space.to_wstr(name, def);
}
int Config::Int(const wchar_t * name)
{
return space.Int(name);
return space.to_int(name);
}
int Config::Int(const wchar_t * name, int def)
{
return space.Int(name, def);
return space.to_int(name, def);
}
int Config::Int(const std::wstring & name, int def)
{
return space.Int(name, def);
return space.to_int(name, def);
}
long Config::Long(const wchar_t * name)
{
return space.Long(name);
return space.to_long(name);
}
long Config::Long(const wchar_t * name, long def)
{
return space.Long(name, def);
return space.to_long(name, def);
}
long Config::Long(const std::wstring & name, long def)
{
return space.Long(name, def);
return space.to_long(name, def);
}
size_t Config::Size(const wchar_t * name)
{
return space.Size(name);
return space.to_ulong(name);
}
size_t Config::Size(const wchar_t * name, size_t def)
{
return space.Size(name, def);
return space.to_ulong(name, def);
}
size_t Config::Size(const std::wstring & name, size_t def)
{
return space.Size(name, def);
return space.to_ulong(name, def);
}
bool Config::Bool(const wchar_t * name)
{
return space.Bool(name);
return space.to_bool(name);
}
bool Config::Bool(const wchar_t * name, bool def)
{
return space.Bool(name, def);
return space.to_bool(name, def);
}
bool Config::Bool(const std::wstring & name, bool def)
{
return space.Bool(name, def);
return space.to_bool(name, def);
}
bool Config::ListText(const wchar_t * name, std::vector<std::wstring> & list)
{
return space.ListText(name, list);
return space.to_list(name, list);
}
bool Config::ListText(const std::wstring & name, std::vector<std::wstring> & list)
{
return space.ListText(name, list);
return space.to_list(name, list);
}
bool Config::HasValue(const wchar_t * name, const wchar_t * value)
{
return space.HasValue(name, value);
return space.has_value(name, value);
}
bool Config::HasValue(const wchar_t * name, const std::wstring & value)
{
return space.HasValue(name, value);
}
bool Config::HasValue(const std::wstring & name, const wchar_t * value)
{
return space.HasValue(name, value);
}
bool Config::HasValue(const std::wstring & name, const std::wstring & value)
{
return space.HasValue(name, value);
return space.has_value(name.c_str(), value.c_str());
}
void Config::Print(std::wostream & out)
{
space.Serialize(out);
}
//void Config::Print(std::wostream & out)
//{
// space.serialize_to_space_stream(out);
//}
+299 -48
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,10 +53,6 @@ class Config
{
public:
// name of the config file
// this is the parameter passed to winix programm
std::wstring config_file;
// server mode
// you can assign any string to it such as "production" "dev"
// this value is not used by winix itself
@@ -88,7 +84,8 @@ public:
// the log level (how much info should be inserted to logs)
// 1 - minimum
// 2 - (default)
// 3 - maximum - all logs
// 3 - more logs
// 4 - maximum - all logs
int log_level;
// logging to stdout too
@@ -97,7 +94,7 @@ public:
bool log_stdout;
// how many requests should be saved in the same time
// if you have a very busy server you can incrase this value
// if you have a very busy server you can increase this value
// default: 1
int log_request;
@@ -134,11 +131,17 @@ public:
std::wstring log_delimiter;
// log environment variables (fastcgi environment)
// default: false;
bool log_env_variables;
// log environment http variables (only HTTP_* variables from fastcgi environment)
// default: false;
bool log_env_http_variables;
// log the whole http post structure (in json format) after parsing the post input
// default: false;
bool log_whole_http_post;
// log headers (+cookies) which are returned to the client
// this is what winix has generated -- the web server can change or add other headers
// default: false
@@ -147,16 +150,29 @@ public:
// fast cgi: socket (unix domain)
std::wstring fcgi_socket;
// fast cgi: whether to change chmod of the socket
// default: true
// if true then you should set fcgi_socket_chmod as well
bool fcgi_set_socket_chmod;
// fast cgi: whether to change owner/group of the socket
// default: true
// if true then you should set fcgi_socket_user and fcgi_socket_group as well
bool fcgi_set_socket_owner;
// fast cgi: socket permissions
// taken into account if fcgi_set_socket_chmod is true
// chmod and chown of the socket are set before winix drops privileges
int fcgi_socket_chmod;
// fast cgi: owner of the socket
// chmod and chown of the socket are set before winix drops privileges
// taken into account if fcgi_set_socket_owner is true
std::wstring fcgi_socket_user;
// fast cgi: group of the socket
// chmod and chown of the socket are set before winix drops privileges
// taken into account if fcgi_set_socket_owner is true
std::wstring fcgi_socket_group;
// fcgi_socket_listen is the listen queue depth used in the listen() call
@@ -164,6 +180,12 @@ public:
// default: 100
int fcgi_socket_listen;
// in order to read a request we need to properly initialize a FastCGI structure by
// using FCGX_InitRequest function, if FCGX_InitRequest fails then we wait fcgi_cannot_create_request_delay
// seconds and trying again
// default: 3
size_t fcgi_cannot_create_request_delay;
std::wstring templates_dir;
std::wstring templates_dir_default; // html templates from winix
@@ -181,26 +203,117 @@ public:
// default: index.html
std::wstring templates_index;
// html template used to send generic content - without site-css styles and markup (only uikit)
// default: index_generic.html
std::wstring templates_index_generic;
// html template used to send raw content
// default: index_raw.html
std::wstring templates_index_raw;
// html template used to show a http status such as Forbidden or Not Found
// default: request_status.html
std::wstring templates_request_status;
// if true then only root can use 'template' winix function
// default: false
bool template_only_root_use_template_fun;
// the database connection string
// https://www.postgresql.org/docs/14/libpq-connect.html#LIBPQ-CONNSTRING
// default: empty
// if empty then winix uses db_host and db_hostaddr
std::wstring db_conn_string;
// the database host name used if db_conn_string is empty
// default: empty
std::wstring db_host;
// the database host ip address used if db_conn_string is empty
// default: empty
// if db_host is empty and db_hostaddr is empty then winix connects to a Unix-domain socket
// meaning of db_host and db_hostaddr parameters is the same as described in
// https://www.postgresql.org/docs/14/libpq-connect.html#LIBPQ-CONNSTRING
//
// from above documentation:
// Using hostaddr allows the application to avoid a host name look-up, which might be important
// in applications with time constraints. However, a host name is required for GSSAPI or SSPI
// authentication methods, as well as for verify-full SSL certificate verification.
// The following rules are used:
//
// - If host is specified without hostaddr, a host name lookup occurs.
//
// - If hostaddr is specified without host, the value for hostaddr gives the server network address.
// The connection attempt will fail if the authentication method requires a host name.
//
// - If both host and hostaddr are specified, the value for hostaddr gives the server network address.
// The value for host is ignored unless the authentication method requires it, in which case it will
// be used as the host name.
std::wstring db_hostaddr;
// the database port number
std::wstring db_port;
// the database name, user name and a password for the PostgreSQL database
std::wstring db_database;
std::wstring db_user;
std::wstring db_pass;
// is the PostgreSQL later than 10
// default false
// if true then we are not using ROW() statements in sql query
bool db_postgresql_smaller_than_10;
// specify how many times we can try to connect to the database at startup
// default 0 (infinite)
size_t db_startup_connection_max_attempts;
// delay between each connection attempt at startup
// default 5 (seconds)
size_t db_startup_connection_attempt_delay;
// make database migration if needed
bool db_make_migration_if_needed;
// if a migration fails then stop winix
bool db_stop_if_migration_fails;
// use internal session mechanism
// default: true
// if false then we do not load/save and create internal sessions
// but there always be the temporary session object for a request
// also we do not load 'who' winix function
bool use_internal_session_mechanism;
// use internal loggin mechanism
// default: true
// if false then we do not load 'login' and 'logout' winix functions
// and the system will not allow to login through its api
bool use_internal_loggin_mechanism;
// the name of the cookie which has the session identifier
std::wstring http_session_id_name;
std::wstring session_cookie_name;
// session cookie path
// default: /
std::wstring session_cookie_path;
// session cookie domain
// if empty then the domain will be equal base_url
// default: empty
std::wstring session_cookie_domain;
// session cookie samesite attribute
// 0 - dont set the attribute
// 1 - Strict
// 2 - Lax
// 3 - None
// (values the same as values from CookieSameSite enum)
// default: 0
int session_cookie_same_site;
// whether or not set HttpOnly attribute on the session cookie
// default: false
bool session_cookie_http_only;
// whether or not set Secure attribute on the session cookie
// default: false
bool session_cookie_secure;
// string used in a place where is a user (or group) selected
// !! IMPROVE ME should be moved to locales
@@ -303,15 +416,15 @@ public:
std::vector<std::wstring> plugin_file;
// should the html code be cleaned by the html filter
// default: false
bool html_filter;
// should white characters be trimmed
bool html_filter_trim_white;
// when long words should be broken (a space will be inserted)
// default: after 60 non white characters there will be put a space
// set zero to turn off
size_t html_filter_break_word;
// how white characters between html tags are treated
// 0 - WHITE_MODE_ORIGIN - they are copied from input to output
// 1 - WHITE_MODE_SINGLE_LINE - new line characters are removed
// 2 - WHITE_MODE_TREE - try to create a tree (some kind of pretty printing)
// default: 2
int html_filter_white_char_mode;
// when long lines should be broken (a new line character will be inserted)
// default: 110
@@ -346,6 +459,35 @@ public:
// 0 - not used
size_t post_file_max;
// maximum length of the input stream when parsing it as json
// default: 8388608 - 8MB
// set zero to disable checking
size_t post_json_max;
// maximum key/value pairs in one object when parsing post json structure
// default: 1024
// set zero to disable checking
// each winix function can set its own limits
size_t post_max_object_items;
// maximum items in one table when parsing post json structure
// default: 4096
// set zero to disable checking
// each winix function can set its own limits
size_t post_max_table_items;
// maximum items (key/values pairs of objects or table items) througout the whole post input json structure
// default: 8192
// set zero to disable checking
// each winix function can set its own limits
size_t post_max_all_items;
// maximum nested objects/tables when parsing post json structure
// default: 32
// set zero to disable checking
// each winix function can set its own limits
size_t post_max_nested_objects;
// directory for static files
std::wstring upload_dir;
@@ -538,9 +680,39 @@ public:
// separator used in <title> html tag
std::wstring title_separator;
// http header recognized by www server as a file to send back
// default: X-LIGHTTPD-send-file
std::wstring http_header_send_file;
// how to send static files (uploaded by users) to the webserver
// 0 - winix will read the content of the file and send it back to the webserver
// 1 - winix will use send_file_header header with a full path to the file
// 2 - winix will use send_file_header header with a relative path to the file
// default: 0
// 0 can be be used with all webservers but it requires to copy the whole file content
// you can omit copying the content with values 1 or 2:
// for Apache set: 1
// for Lighttpd set: 1
// for Nginx set: 2
int send_file_mode;
// http header recognized by www server as a file to send back, used if send_file_mode is 1 or 2
// default: X-SENDFILE
// for Apache set: X-SENDFILE (Apache needs an external module: https://tn123.org/mod_xsendfile/)
// for Lighttpd set: X-LIGHTTPD-send-file (https://redmine.lighttpd.net/projects/1/wiki/X-LIGHTTPD-send-file)
// for Nginx set: X-Accel-Redirect (https://nginx.org/en/docs/http/ngx_http_core_module.html#internal)
std::wstring send_file_header;
// relative prefix used for sending static files if send_file_mode is 2
// default: "upload-files-internal"
// this prefix is added at the beginning of a relative file path e.g.
// /upload-files-internal/simplefs/normal/some_directories/file.jpg
//
// in Nginx config file use 'location' with the prefix, e.g:
// server {
// .....
// location /upload-files-internal/ {
// alias /path/to/winix/upload/; # trailing slash at the end
// internal;
// }
// }
std::wstring send_file_relative_prefix;
// in editors (emacs, ckeditor,...) the html will be filtered and unsafe tags
// will be dropped (script, frame, etc.)
@@ -615,6 +787,7 @@ public:
// 2 - application/xml - for XHTML 1.0 or for XHTML 1.1
// default: 0
// if utf8 is true then "; charset=UTF-8" will also be appended
// may it would be better to set just the string here instead of integers?
int content_type_header;
// global umask
@@ -632,18 +805,56 @@ public:
// how many output streams do we have in Request class
// those streams used in ajax responses
// you can use no more [ezc out] statements than this limit
// you can use no more [ezc frames] statements than this limit
// default: 128
size_t ezc_out_streams_size;
// prefix and postfix used when there is an error in Ezc patterns
// default:
// prefix: "<!-- "
// postfix: " -->"
std::wstring ezc_error_prefix;
std::wstring ezc_error_postfix;
// the name of the url parameter for returning a frame, e.g. https://domain.tld/mydir/myfunction/frame:foo
// default: frame
std::wstring request_frame_parameter;
// when true then when a user want to create a new account
// the name of the url parameter for returning all frames, e.g. https://domain.tld/mydir/myfunction/all_frames
// default: all_frames
std::wstring request_all_frames_parameter;
// the name of the url parameter for returning the main ezc stream, e.g. https://domain.tld/mydir/myfunction/main_stream
// default: main_stream
std::wstring request_main_stream_parameter;
// max lenght of the url frame parameter
// default: 128
size_t request_frame_parameter_max_length;
// max number of frames in the frame url parameter (they are separated by a comma)
// default: 16
// if you need more frames you can use all_frames url parameter to return all frames
size_t request_frame_parameter_max_frames;
// the name of the root element when serializing request answer to xml
// default: winix
std::wstring xml_root;
// the name of the field of the binary stream when serializing a request
// default: bin_stream
std::wstring bin_stream_field;
// the name of the field of the main ezc stream when serializing a request
// default: main_stream
std::wstring main_stream_field;
// the name of the field (object) of the ezc frames when serializing a request
// default: ezc_frames
std::wstring ezc_frames_field;
// max Accept header mime types to be parsed in a request
// default: 8
size_t request_max_accept_fields;
// max Accept-Language languages to be parsed in a request
// default: 8
size_t request_max_accept_language_fields;
// when true then when a user want to create a new account
// he has to provide his email and a message will be sent back to him
// with a link to activate the account
// default: true
@@ -752,10 +963,10 @@ public:
// pid file is saved after winix has dropped privileges
std::wstring pid_file;
// allow to use [ezc out] statement in executable items (used in 'run' winix function)
// allow to use [ezc frame] statements in executable items (used in 'run' winix function)
// default false
// warning: if you enable this options a user can override a different output stream when using ajax
bool allow_ezc_out_in_executable_items;
bool allow_ezc_frames_in_executable_items;
// check whether there is a 'log_proxy_ip_header' header
@@ -767,7 +978,12 @@ public:
// default: X_Real_IP
std::wstring proxy_ip_header;
// antispam mechanizm
// use an antispam mechanism for not logged users
// when they try to add a new item
// default: true
bool use_antispam_mechanism_for_not_logged_users;
// antispam mechanism
// size of an list for map: form_id to counter_id for anonymous users (each session has such an map)
// this value allowes you to open the same or different html form in the browser more than once
// and each form has its own form_id and counter_id
@@ -775,8 +991,50 @@ public:
size_t antispam_list_max_size;
// send "Cache-Control: no-store, max-age=0" http header if a request is made by htmx library (ajax)
// if a webbrowser get a page from the cache then it will render just the last request without the whole html page (css, js, etc)
// https://github.com/bigskysoftware/htmx/issues/497
bool add_header_cache_no_store_in_htmx_request;
// a limit for the queue for requests
// when a request is scheduled to a job
// default: 1024
// if the limit is reached then the http status 503 Service Unavailable is returned
size_t request_queue_job_limit;
// list of allowed origins in cors requests
// can be set per controller in a method: virtual bool FunctionBase::IsOriginAvailable(const std::wstring & origin_url)
// default: empty
std::vector<std::wstring> allowed_origins;
// whether or not all origins are allowed if allowed_origins is empty
// default: true
// this is true by default because Origin header is sent not only in cors requests
// (you can still allow it in your function/controller by overriding IsOriginAvailable(...) method)
bool allow_all_origins;
// whether or not cors preflight requests are available
// https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
// default: false
bool are_cors_preflight_requests_available;
// list of additional headers sent in Access-Control-Expose-Headers header
// can be set per controller in a method: virtual void FunctionBase::AddAccessControlExposeHeadersHeader()
// default: empty
std::vector<std::wstring> access_control_expose_headers;
// if true return Access-Control-Allow-Credentials header equal "true"
// whethert credentials (e.g. cookies, authorization headers) are available in cors requests
// can be set per controller in a method: virtual bool FunctionBase::AreCorsCredentialsAvailable()
// default: false
bool access_control_allow_credentials;
Config();
bool ReadConfig(bool errors_to_stdout_, bool stdout_is_closed = true);
bool ReadConfig(const std::wstring & config_file);
void AssignValuesFromSpace();
/*
*
@@ -789,10 +1047,6 @@ public:
std::wstring Text(const wchar_t * name, const wchar_t * def);
std::wstring Text(const std::wstring & name, const wchar_t * def);
std::wstring & TextRef(const wchar_t * name);
std::wstring & TextRef(const wchar_t * name, const wchar_t * def);
std::wstring & TextRef(const std::wstring & name, const wchar_t * def);
int Int(const wchar_t *);
int Int(const wchar_t * name, int def);
int Int(const std::wstring & name, int def);
@@ -808,30 +1062,27 @@ public:
bool ListText(const wchar_t * name, std::vector<std::wstring> & list);
bool ListText(const std::wstring & name, std::vector<std::wstring> & list);
bool HasValue(const wchar_t * name, const wchar_t * value);
bool HasValue(const wchar_t * name, const std::wstring & value);
bool HasValue(const std::wstring & name, const wchar_t * value);
bool HasValue(const wchar_t * name, const wchar_t * value);
bool HasValue(const std::wstring & name, const std::wstring & value);
// for debug
void Print(std::wostream & out);
//void Print(std::wostream & out);
// raw access to the config
PT::Space space;
pt::Space space;
void SetFileLog(FileLog * file_log);
void SetLogBuffer(PT::WTextStream * log_buffer);
void SetLogBuffer(pt::WTextStream * log_buffer);
private:
PT::SpaceParser parser;
bool errors_to_stdout;
pt::SpaceParser parser;
Log log;
void ShowError();
void AssignValues(bool stdout_is_closed);
void ShowError(const std::wstring & config_file);
void AssignValues();
void SetAdditionalVariables();
void CheckPasswd();
+32 -28
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2018, Tomasz Sowa
* Copyright (c) 2011-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,7 +78,7 @@ bool Crypt::HashBin(int hash, const char * in, size_t inlen, std::string & out)
run.Clear();
run.set_dependency(this);
PT::WideToUTF8(config->opensll_path, command);
pt::wide_to_utf8(config->opensll_path, command);
run.Cmd(command);
run.Par("dgst");
run.Par("-binary");
@@ -119,7 +119,7 @@ bool Crypt::HashBin(int hash, const std::string & in, std::string & out)
bool Crypt::HashBin(int hash, const wchar_t * in, size_t inlen, std::string & out)
{
PT::WideToUTF8(in, inlen, bufina);
pt::wide_to_utf8(in, inlen, bufina);
int res = HashBin(hash, bufina.c_str(), bufina.size(), out);
bufina.clear();
@@ -211,7 +211,7 @@ bool Crypt::RSA(bool encrypt, const char * keypath, const char * in, size_t inle
return false;
run.Clear();
PT::WideToUTF8(config->opensll_path, command);
pt::wide_to_utf8(config->opensll_path, command);
run.Cmd(command);
run.Par("rsautl");
@@ -243,7 +243,7 @@ bool Crypt::RSA(bool encrypt, const std::string & keypath, const std::string & i
bool Crypt::RSA(bool encrypt, const wchar_t * keypath, const char * in, size_t inlen, std::string & out)
{
PT::WideToUTF8(keypath, keypatha);
pt::wide_to_utf8(keypath, keypatha);
return RSA(encrypt, keypatha.c_str(), in, inlen, out);
}
@@ -267,28 +267,28 @@ bool Crypt::RSA(bool encrypt, const std::wstring & keypath, const std::string &
bool Crypt::PassHash(const std::wstring & salt, UserPass & up)
bool Crypt::PassHash(const std::wstring & salt, User & user)
{
bool result = true;
up.pass_hash_salted = false;
user.is_pass_hash_salted = false;
if( up.pass_type != WINIX_CRYPT_HASH_NONE )
if( user.pass_type != WINIX_CRYPT_HASH_NONE )
{
pass_org = up.pass;
pass_salted = up.pass;
pass_org = user.password;
pass_salted = user.password;
pass_salted += salt;
if( HashHex(up.pass_type, pass_salted, up.pass) )
if( HashHex(user.pass_type, pass_salted, user.password) )
{
if( !salt.empty() )
up.pass_hash_salted = true;
user.is_pass_hash_salted = true;
}
else
{
log << log1 << "Crypt: problem with generating a hash, the password will not be hashed" << logend;
up.pass = pass_org;
up.pass_type = WINIX_CRYPT_HASH_NONE;
user.password = pass_org;
user.pass_type = WINIX_CRYPT_HASH_NONE;
result = false;
}
@@ -301,22 +301,23 @@ return result;
bool Crypt::PassCrypt(const std::wstring & path_to_rsa_private_key, UserPass & up)
bool Crypt::PassCrypt(const std::wstring & path_to_rsa_private_key, User & user)
{
bool result = false;
ClearString(up.pass_encrypted);
ClearString(user.pass_encrypted);
if( !path_to_rsa_private_key.empty() )
{
PT::WideToUTF8(up.pass, passa);
pt::wide_to_utf8(user.password, passa);
if( RSA(true, path_to_rsa_private_key, passa, up.pass_encrypted) )
if( RSA(true, path_to_rsa_private_key, passa, user.pass_encrypted) )
{
ClearString(user.password);
result = true;
}
else
{
ClearString(up.pass_encrypted);
ClearString(user.pass_encrypted);
log << log1 << "AddUser: problem with encrypting, the password will not be encrypted!" << logend;
}
@@ -327,27 +328,30 @@ return result;
}
void Crypt::PassHashCrypt(const std::wstring & salt, const std::wstring & path_to_rsa_private_key, UserPass & up)
void Crypt::PassHashCrypt(const std::wstring & salt, const std::wstring & path_to_rsa_private_key, User & user)
{
PassHash(salt, up);
PassCrypt(path_to_rsa_private_key, up);
PassHash(salt, user);
PassCrypt(path_to_rsa_private_key, user);
}
void Crypt::PassHashCrypt(UserPass & up)
/*
* we hashing user.password, may it would be better to get the password as a seperate argument?
*/
void Crypt::PassHashCrypt(User & user)
{
up.pass_type = config->pass_type;
user.pass_type = config->pass_type;
ClearString(user.pass_encrypted);
empty.clear();
if( config->pass_hash_use_salt && !config->pass_hash_salt.empty() )
PassHash(config->pass_hash_salt, up);
PassHash(config->pass_hash_salt, user);
else
PassHash(empty, up);
PassHash(empty, user);
if( config->pass_use_rsa && !config->pass_rsa_private_key.empty() )
PassCrypt(config->pass_rsa_private_key, up);
PassCrypt(config->pass_rsa_private_key, user);
}
+6 -6
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* Copyright (c) 2011-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
#include <string>
#include "run.h"
#include "config.h"
#include "user.h"
#include "models/user.h"
#include "winixbase.h"
@@ -177,7 +177,7 @@ public:
if there is a problem with generating a hash the method stores a plain text password
and changes up.pass_type to zero (plain text passwords are not salted)
*/
bool PassHash(const std::wstring & salt, UserPass & up);
bool PassHash(const std::wstring & salt, User & user);
/*
@@ -195,7 +195,7 @@ public:
if there is a problem (or the path to the key is empty) then up.pass_encrypted will be empty
and the method returns false
*/
bool PassCrypt(const std::wstring & path_to_rsa_private_key, UserPass & up);
bool PassCrypt(const std::wstring & path_to_rsa_private_key, User & user);
/*
@@ -217,7 +217,7 @@ public:
up.pass_encrypted - encrypted password (if not empty)
*/
void PassHashCrypt(const std::wstring & salt, const std::wstring & path_to_rsa_private_key, UserPass & up);
void PassHashCrypt(const std::wstring & salt, const std::wstring & path_to_rsa_private_key, User & user);
/*
@@ -232,7 +232,7 @@ public:
up.pass_hash_salted - true if the hash is salted (plain text are never salted)
up.pass_encrypted - encrypted password (if not empty)
*/
void PassHashCrypt(UserPass & up);
void PassHashCrypt(User & user);
/*
+9 -1
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,14 @@ struct Cur
// those pointers are never null, if there is no a session for the user
// the 'session' pointer pointers at a special temporary session
Cur()
{
request = nullptr;
session = nullptr;
mount = nullptr;
}
};
+13 -2
View File
@@ -81,13 +81,13 @@ return var_iter;
}
DirContainer::Iterator DirContainer::Begin()
DirContainer::ConstIterator DirContainer::Begin() const
{
return table.begin();
}
DirContainer::Iterator DirContainer::End()
DirContainer::ConstIterator DirContainer::End() const
{
return table.end();
}
@@ -255,6 +255,17 @@ return i->second;
}
DirContainer::ConstIterator DirContainer::FindId(long id) const
{
TableId::const_iterator i = table_id.find(id);
if( i == table_id.end() )
return table.end();
return i->second;
}
DirContainer::ParentIterator DirContainer::ParentBegin()
{
+6 -4
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2014, Tomasz Sowa
* Copyright (c) 2008-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,8 +37,8 @@
#include <list>
#include <map>
#include "item.h"
#include "winixbase.h"
#include "models/item.h"
namespace Winix
@@ -52,6 +52,7 @@ class DirContainer : public WinixBase
public:
typedef std::list<Item> Table;
typedef Table::iterator Iterator;
typedef Table::const_iterator ConstIterator;
typedef Table::size_type SizeType;
typedef std::map<long, Iterator> TableId;
@@ -66,8 +67,8 @@ public:
Iterator GetEtc();
Iterator GetVar();
Iterator Begin();
Iterator End();
ConstIterator Begin() const;
ConstIterator End() const;
SizeType Size();
bool Empty();
Iterator PushBack(const Item & item);
@@ -75,6 +76,7 @@ public:
void Clear();
Iterator FindId(long id);
ConstIterator FindId(long id) const;
bool DelById(long id);
+51 -31
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
*
*/
#include <ctime>
#include "dirs.h"
#include "error.h"
#include "notify/notify.h"
@@ -41,13 +42,6 @@ namespace Winix
{
void Dirs::SetDb(Db * pdb)
{
db = pdb;
}
void Dirs::SetCur(Cur * pcur)
{
cur = pcur;
@@ -60,9 +54,9 @@ void Dirs::SetNotify(Notify * pnotify)
}
void Dirs::set_dependency(WinixModel * winix_model)
void Dirs::set_dependency(WinixModelDeprecated * winix_model)
{
WinixModel::set_dependency(winix_model);
WinixModelDeprecated::set_dependency(winix_model);
dir_tab.set_dependency(winix_model);
}
@@ -76,7 +70,7 @@ void Dirs::Clear()
bool Dirs::HasReadExecAccessForRoot(const Item & item)
{
// there must be at least one 'x' (for the root)
return (item.privileges & 01111) != 0;
return (item.item_content.privileges & 01111) != 0;
}
@@ -88,28 +82,32 @@ void Dirs::CheckRootDir()
{
if( !HasReadExecAccessForRoot(*i) )
{
i->privileges = 07555;
i->item_content.privileges = 07555;
log << log1 << "Dirs: there is no access for a root (admin) to the root dir, setting 07555 for the root directory" << logend;
db->EditPrivById(*i, i->id);
i->item_content.set_connector(model_connector);
i->item_content.date_modification = std::time(nullptr);
i->item_content.save(false);
}
return;
}
log << log1 << "Dirs: there is no a root directory in the database (creating one)" << logend;
Item root;
ItemModelData item_data;
item_data.prepare_unique_url = false;
Item root;
root.set_connector(model_connector);
root.type = Item::dir;
root.parent_id = -1;
root.user_id = -1;
root.group_id = -1;
root.privileges = 07555;
root.item_content.user_id = -1;
root.item_content.group_id = -1;
root.item_content.privileges = 07555;
root.item_content.date_creation = std::time(nullptr);
root.item_content.date_modification = root.item_content.date_creation;
// !! upewnic sie ze baza nie zmieni url (gdyby wczesniej juz byl w bazie pusty url)
// !! zrobic jakis wyjatek do wprowadzania roota?
if( db->AddItem(root) == WINIX_ERR_OK )
if( root.insert(item_data) )
{
dir_tab.PushBack(root);
}
@@ -122,7 +120,15 @@ void Dirs::ReadDirs()
{
Clear();
db->GetDirs(dir_tab);
//db->GetDirs(dir_tab);
morm::Finder<Item> finder(model_connector);
std::list<Item> all_dirs = finder.select().where().eq(L"type", static_cast<int>(Item::Type::dir)).get_list();
for(Item & item : all_dirs)
{
dir_tab.PushBack(item);
}
CheckRootDir();
dir_tab.FindSpecialFolders();
}
@@ -443,9 +449,20 @@ Item * Dirs::GetDir(long id)
DirContainer::Iterator i = dir_tab.FindId(id);
if( i == dir_tab.End() )
return 0;
return nullptr;
return &(*i);
return &(*i);
}
const Item * Dirs::GetDir(long id) const
{
DirContainer::ConstIterator i = dir_tab.FindId(id);
if( i == dir_tab.End() )
return nullptr;
return &(*i);
}
@@ -723,17 +740,19 @@ bool Dirs::DelDir(long dir_id)
}
Error Dirs::AddDirectory(Item & item, bool add_to_dir_tab, Item ** pdir, int notify_code)
bool Dirs::AddDirectory(Item & item, bool add_to_dir_tab, Item ** pdir, int notify_code)
{
if( pdir )
*pdir = 0;
if( item.type != Item::dir )
return WINIX_ERR_DIR_EXPECTED;
return false;
Error status = db->AddItem(item);
//Error status = db->AddItem(item);
//item.set_connector(model_connector);
bool status = item.insert();
if( status == WINIX_ERR_OK )
if( status )
{
Item * d = AddDir(item);
@@ -764,10 +783,11 @@ Item * Dirs::CreateVarDir()
if( root )
{
v.set_connector(root->get_connector());
v.parent_id = root->id;
v.user_id = root->user_id;
v.group_id = root->group_id;
v.privileges = root->privileges;
v.item_content.user_id = root->item_content.user_id;
v.item_content.group_id = root->item_content.group_id;
v.item_content.privileges = root->item_content.privileges;
v.subject = L"var";
v.url = L"var";
v.type = Item::dir;
+8 -10
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,12 +39,10 @@
#include <vector>
#include <map>
#include <string>
#include "item.h"
#include "dircontainer.h"
#include "db/db.h"
#include "request.h"
#include "winixmodel.h"
#include "models/item.h"
#include "winixmodeldeprecated.h"
@@ -58,7 +56,7 @@ class Notify;
// (we will support '..' in the future)
class Dirs : public WinixModel
class Dirs : public WinixModelDeprecated
{
public:
@@ -66,10 +64,9 @@ public:
void ReadDirs();
void SetCur(Cur * pcur);
void SetDb(Db * pdb);
void SetNotify(Notify * pnotify);
void set_dependency(WinixModel * winix_model);
void set_dependency(WinixModelDeprecated * winix_model);
// these methods return false if there is no such a dir
bool IsDir(long dir_id);
@@ -110,12 +107,14 @@ public:
Item * GetDir(long id);
Item * AddDir(const Item & item);
const Item * GetDir(long id) const;
void CheckRootDir();
Item * CreateVarDir();
// !! jak juz wczesniejsze nazwy beda zmienione to tutaj damy AddDir() /AddDir() juz istnieje przeciez?/
Error AddDirectory(Item & item, bool add_to_dir_tab = false, Item ** pdir = 0, int notify_code = 0);
bool AddDirectory(Item & item, bool add_to_dir_tab = false, Item ** pdir = 0, int notify_code = 0);
// returns how many levels of directories there are
// "/" -> 0 (root dir)
@@ -129,7 +128,6 @@ public:
private:
Cur * cur;
Db * db;
Notify * notify;
DirContainer dir_tab;
+25 -14
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2018-2019, Tomasz Sowa
* Copyright (c) 2018-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
#include <string.h>
#include "utf8/utf8.h"
#include "timezones.h"
#include "plugin.h"
namespace Winix
@@ -49,6 +49,7 @@ FileLog::FileLog()
{
time_zones = nullptr;
synchro = nullptr;
plugin = nullptr;
log_time_zone_id = 0;
}
@@ -64,9 +65,15 @@ void FileLog::set_synchro(Synchro * synchro)
}
void FileLog::set_plugin(Plugin * plugin)
{
this->plugin = plugin;
}
void FileLog::init(const std::wstring & log_file, bool log_stdout, int log_level, bool save_each_line, size_t log_time_zone_id)
{
PT::FileLog::init(log_file, log_stdout, log_level, save_each_line);
pt::FileLog::init(log_file, log_stdout, log_level, save_each_line);
this->log_time_zone_id = log_time_zone_id;
}
@@ -91,7 +98,7 @@ bool FileLog::should_save_each_line()
PT::Date FileLog::get_local_date(const PT::Date & date)
pt::Date FileLog::get_local_date(const pt::Date & date)
{
if( time_zones )
{
@@ -100,7 +107,7 @@ PT::Date FileLog::get_local_date(const PT::Date & date)
if( tz )
{
PT::Date local_date = tz->ToLocal(date);
pt::Date local_date = tz->ToLocal(date);
return local_date;
}
else
@@ -116,19 +123,23 @@ PT::Date FileLog::get_local_date(const PT::Date & date)
bool FileLog::synchro_lock()
void FileLog::save_log(pt::WTextStream * buffer)
{
return synchro->Lock();
if( !buffer->empty() )
{
Lock lock(synchro);
pt::FileLog::save_log(buffer);
// at the beginning when winix starts the plugin pointer is null
// this plugin is set after the plugin object is initialized
if( plugin )
{
plugin->Call(WINIX_SAVE_FILELOG, buffer);
}
}
}
void FileLog::synchro_unlock()
{
synchro->Unlock();
}
} // namespace Winix
+12 -9
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2018, Tomasz Sowa
* Copyright (c) 2018-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,9 +47,9 @@
namespace Winix
{
class TimeZones;
class Plugin;
class FileLog : public PT::FileLog
class FileLog : public pt::FileLog
{
public:
@@ -57,15 +57,22 @@ public:
virtual ~FileLog();
void set_synchro(Synchro * synchro);
void set_plugin(Plugin * plugin);
// using pt::FileLog::init to suppress clang warning:
// warning: 'Winix::FileLog::init' hides overloaded virtual function [-Woverloaded-virtual]
using pt::FileLog::init;
void init(const std::wstring & log_file, bool log_stdout, int log_level, bool save_each_line, size_t log_time_zone_id);
void set_time_zones(TimeZones * time_zones);
PT::Date get_local_date(const PT::Date & date);
pt::Date get_local_date(const pt::Date & date);
int get_log_level();
bool should_save_each_line();
void save_log(pt::WTextStream * buffer);
protected:
@@ -73,12 +80,8 @@ protected:
size_t log_time_zone_id;
TimeZones * time_zones;
Synchro * synchro;
virtual bool synchro_lock();
virtual void synchro_unlock();
Plugin * plugin; // can be null (only at the beginning when winix starts)
};
+14 -5
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,9 +46,9 @@ Groups::Groups()
}
void Groups::set_dependency(WinixModel * winix_model)
void Groups::set_dependency(WinixModelDeprecated * winix_model)
{
WinixModel::set_dependency(winix_model);
WinixModelDeprecated::set_dependency(winix_model);
table.set_dependency(winix_model);
}
@@ -59,11 +59,20 @@ void Groups::Clear()
}
void Groups::ReadGroups(Db * db)
void Groups::ReadGroups()
{
Clear();
db->GetGroups(table);
morm::Finder<Group> finder(model_connector);
std::vector<Group> groups_tmp = finder.
select().
get_vector();
for(Group & group : groups_tmp)
{
table.PushBack(group, group.name);
}
}
+6 -7
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,10 +37,9 @@
#include <map>
#include "group.h"
#include "models/group.h"
#include "ugcontainer.h"
#include "db/db.h"
#include "winixmodel.h"
#include "winixmodeldeprecated.h"
@@ -49,7 +48,7 @@ namespace Winix
class Groups : public WinixModel
class Groups : public WinixModelDeprecated
{
typedef UGContainer<Group> Table;
@@ -57,14 +56,14 @@ Table table;
public:
void set_dependency(WinixModel * winix_model);
void set_dependency(WinixModelDeprecated * winix_model);
typedef Table::Iterator Iterator;
typedef Table::SizeType SizeType;
Groups();
void Clear();
void ReadGroups(Db * db);
void ReadGroups();
Group * GetGroup(long group_id);
Group * GetGroup(const std::wstring & name);
long GetGroupId(const std::wstring & name);
+115
View File
@@ -0,0 +1,115 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "header.h"
namespace Winix
{
const wchar_t * Header::find_status_string_value(int http_status)
{
size_t table_len = sizeof(status_int_string_map) / sizeof(StatusIntStringMapHelper);
for(size_t i=0 ; i < table_len ; ++i)
{
if( status_int_string_map[i].status_int == http_status )
{
return status_int_string_map[i].status_str;
}
}
return nullptr;
}
void Header::prepare_status_value(int http_status, pt::WTextStream & value, bool clear_value)
{
if( clear_value )
value.clear();
value << http_status;
const wchar_t * value_str = find_status_string_value(http_status);
if( value_str )
{
value << ' ' << value_str;
}
}
bool Header::is_header_value_char_correct(wchar_t c)
{
/*
* make sure to not allow at least \r or \r
*/
return c > 32 && c < 127;
}
bool Header::is_header_value_correct(const wchar_t * str)
{
for( ; *str ; ++str)
{
if( !is_header_value_char_correct(*str) )
{
return false;
}
}
return true;
}
bool Header::is_header_value_correct(const std::wstring & str)
{
/*
* dont use is_header_value_correct(str.c_str()) as there can be a null character (0) inside the string
*/
for(size_t i=0 ; i < str.size() ; ++i)
{
if( !is_header_value_char_correct(str[i]) )
{
return false;
}
}
return true;
}
}
+225
View File
@@ -0,0 +1,225 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_header
#define headerfile_winix_core_header
#include "log.h"
#include <textstream/textstream.h>
namespace Winix
{
class Header
{
public:
/*
* headers' names
*/
static constexpr const wchar_t * content_type = L"Content-Type";
static constexpr const wchar_t * accept = L"Accept";
static constexpr const wchar_t * accept_language = L"Accept-Language";
static constexpr const wchar_t * authorization = L"Authorization";
static constexpr const wchar_t * allow = L"Allow";
static constexpr const wchar_t * very = L"Very";
static constexpr const wchar_t * origin = L"Origin";
static constexpr const wchar_t * access_control_allow_methods = L"Access-Control-Allow-Methods";
static constexpr const wchar_t * access_control_allow_origin = L"Access-Control-Allow-Origin";
static constexpr const wchar_t * access_control_allow_headers = L"Access-Control-Allow-Headers";
static constexpr const wchar_t * access_control_allow_credentials = L"Access-Control-Allow-Credentials";
static constexpr const wchar_t * access_control_expose_headers = L"Access-Control-Expose-Headers";
static constexpr const wchar_t * access_control_max_age = L"Access-Control-Max-Age";
static constexpr const wchar_t * hx_location = L"HX-Location";
static constexpr const wchar_t * hx_push_url = L"HX-Push-Url";
static constexpr const wchar_t * hx_redirect = L"HX-Redirect";
static constexpr const wchar_t * hx_refresh = L"HX-Refresh";
static constexpr const wchar_t * hx_replace_url = L"HX-Replace-Url";
static constexpr const wchar_t * hx_reswap = L"HX-Reswap";
static constexpr const wchar_t * hx_retarget = L"HX-Retarget";
static constexpr const wchar_t * hx_reselect = L"HX-Reselect";
static constexpr const wchar_t * hx_trigger = L"HX-Trigger";
static constexpr const wchar_t * hx_trigger_after_settle = L"HX-Trigger-After-Settle";
static constexpr const wchar_t * hx_trigger_after_swap = L"HX-Trigger-After-Swap";
/*
* headers' names lower case
*/
static constexpr const wchar_t * content_type_lc = L"content-type";
static constexpr const wchar_t * accept_lc = L"accept";
static constexpr const wchar_t * accept_language_lc = L"accept-language";
/*
* headers' values
*/
static constexpr const wchar_t * application_octet_stream = L"application/octet-stream";
static constexpr const wchar_t * text_html = L"text/html";
static constexpr const wchar_t * application_json = L"application/json";
static constexpr const wchar_t * application_xml = L"application/xml";
static constexpr const wchar_t * application_xhtml_xml = L"application/xhtml+xml";
static constexpr const wchar_t * text_csv = L"text/csv";
static constexpr const wchar_t * text_javascript = L"text/javascript";
static constexpr const wchar_t * text_xml = L"text/xml";
static constexpr const wchar_t * all_all = L"*/*";
static constexpr const wchar_t * text_all = L"text/*";
static constexpr const wchar_t * application_all = L"application/*";
static constexpr const wchar_t * text_html_utf8 = L"text/html; charset=UTF-8";
static constexpr const wchar_t * application_json_utf8 = L"application/json; charset=UTF-8";
static constexpr const wchar_t * application_xml_utf8 = L"application/xml; charset=UTF-8";
static constexpr const wchar_t * application_xhtml_xml_utf8 = L"application/xhtml+xml; charset=UTF-8";
static constexpr const wchar_t * text_csv_utf8 = L"text/csv; charset=UTF-8";
static constexpr const wchar_t * text_javascript_utf8 = L"text/javascript; charset=UTF-8";
static constexpr const wchar_t * text_xml_utf8 = L"text/xml; charset=UTF-8";
static constexpr const wchar_t * application_x_www_form_urlencoded = L"application/x-www-form-urlencoded";
static constexpr const wchar_t * multipart_form_data = L"multipart/form-data";
static constexpr const wchar_t * bearer = L"Bearer";
static constexpr const wchar_t * winix = L"Winix";
static const int status_200_ok = 200;
static const int status_201_created = 201;
static const int status_204_no_content = 204;
static const int status_300_multiple_choices = 300;
static const int status_301_moved_permanently = 301;
static const int status_302_found = 302;
static const int status_303_see_other = 303;
static const int status_307_temporary_redirect = 307;
static const int status_400_bad_request = 400;
static const int status_403_forbidden = 403;
static const int status_404_not_found = 404;
static const int status_414_uri_too_long = 414;
static const int status_422_unprocessable_entity = 422;
static const int status_500_internal_server_error = 500;
static const int status_503_service_unavailable = 503;
static constexpr const wchar_t * str_status_200 = L"OK";
static constexpr const wchar_t * str_status_201 = L"Created";
static constexpr const wchar_t * str_status_204 = L"No Content";
static constexpr const wchar_t * str_status_300 = L"Multiple Choices";
static constexpr const wchar_t * str_status_301 = L"Moved Permanently";
static constexpr const wchar_t * str_status_302 = L"Found";
static constexpr const wchar_t * str_status_303 = L"See Other";
static constexpr const wchar_t * str_status_307 = L"Temporary Redirect";
static constexpr const wchar_t * str_status_400 = L"Bad Request";
static constexpr const wchar_t * str_status_403 = L"Forbidden";
static constexpr const wchar_t * str_status_404 = L"Not Found";
static constexpr const wchar_t * str_status_414 = L"URI Too Long";
static constexpr const wchar_t * str_status_422 = L"Unprocessable Entity";
static constexpr const wchar_t * str_status_500 = L"Internal Server Error";
static constexpr const wchar_t * str_status_503 = L"Service Unavailable";
static const wchar_t * find_status_string_value(int http_status);
static void prepare_status_value(int http_status, pt::WTextStream & value, bool clear_value = true);
static bool is_header_value_char_correct(wchar_t c);
static bool is_header_value_correct(const wchar_t * str);
static bool is_header_value_correct(const std::wstring & str);
protected:
struct StatusIntStringMapHelper
{
int status_int;
const wchar_t * status_str;
};
static constexpr StatusIntStringMapHelper status_int_string_map[] = {
{status_200_ok, str_status_200},
{status_201_created, str_status_201},
{status_204_no_content, str_status_204},
{status_300_multiple_choices, str_status_300},
{status_301_moved_permanently, str_status_301},
{status_302_found, str_status_302},
{status_303_see_other, str_status_303},
{status_307_temporary_redirect, str_status_307},
{status_400_bad_request, str_status_400},
{status_403_forbidden, str_status_403},
{status_404_not_found, str_status_404},
{status_414_uri_too_long, str_status_414},
{status_422_unprocessable_entity, str_status_422},
{status_500_internal_server_error, str_status_500},
{status_503_service_unavailable, str_status_503},
};
};
class HeaderValue
{
public:
std::wstring value;
double weight; // q parameter in some headers
HeaderValue()
{
weight = 0.0;
}
static void log_values(const std::vector<HeaderValue> & header_values, Log & log)
{
char buf[64];
bool is_first = true;
for(const HeaderValue & h: header_values)
{
snprintf(buf, sizeof(buf)/sizeof(char), "%.3f", h.weight);
if( !is_first )
log << ", ";
log << h.value << ";q=" << buf;
is_first = false;
}
}
};
}
#endif
File diff suppressed because it is too large Load Diff
-373
View File
@@ -1,373 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_htmlfilter
#define headerfile_winix_core_htmlfilter
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include "core/winixbase.h"
namespace Winix
{
// max length of a name of a html tag (with terminating null)
#define WINIX_HTMLFILTER_ITEM_NAME_MAXLEN 30
// max length of a html lang attribute (e.g. "en", "pl")
#define WINIX_HTMLFILTER_ITEM_LANG_MAXLEN 10
#define WINIX_HTMLFILTER_ATTR_NAME_MAXLEN 40
#define WINIX_HTMLFILTER_ATTR_VALUE_MAXLEN 500
// depth of the html tree
#define WINIX_HTMLFILTER_STACK_MAXLEN 100
// length of a buffer used for printing
// it should be at least: WINIX_HTMLFILTER_ITEM_NAME_MAXLEN+3
#define WINIX_HTMLFILTER_BUFFER_MAXLEN 2048
/*!
very lightweight filter for html
(without using any dynamic memory - some memory is allocated only at the beginning - in ctors)
this filter has O(n) complexity over the whole html string
such tags as: <script> <pre> <textarea> are treated in a special way
all characters between the opening and closing tag (<script>....</script>) are untouched
if the filter finds that there are not closed tags it will close them,
if the filter finds a closing tag which doesn't have an opening tag - it will skip it
tags which don't need to be closed: meta, input, br, img, link
look at CheckExceptions() method
the filter recognizes xml simple tags (with / at the end) such as: <br />
*/
class HTMLFilter : public WinixBase
{
public:
enum OrphanMode
{
orphan_nbsp, // putting "&nbsp;" string
orphan_160space // putting 160 ascii code
};
HTMLFilter();
HTMLFilter(const HTMLFilter & f);
HTMLFilter & operator=(const HTMLFilter & f);
virtual ~HTMLFilter();
// main methods used for filtering
void Filter(const wchar_t * in, std::wstring & out);
void Filter(const std::wstring & in, std::wstring & out);
// insert a white space into long words
// (only between html tags)
// skipped in such tags: script, pre, textarea
// break_after - after how many characters insert a space (0 - off)
void BreakWord(size_t break_after_);
// insert a new line character into long lines
// (only between html tags)
// skipped in such tags: script, pre, textarea
// wrap_line - after how many characters wrap a line (0 - off)
// lines are wrapped only in 'body' tag (useful for text in 'title' tag which is in 'head' section)
void WrapLine(size_t wrap_line_);
// trimming white characters (with new lines)
// at the beginning, at the end and in the middle of a string
// only between html tags
// at the beginning and at the end only one space is left
// skipped in such tags: script, pre, textarea
// false by default
void TrimWhite(bool trim);
// first tabs in a tree
// default: 2 (spaces)
// set 0 to turn off
void InsertTabs(size_t tabsize);
// set a name of a html tag which will be used as 'nofilter' tag
// elements between such tags are not filtered (similarly as in <pre> and <textarea>)
// these tags (opening and closing) will no be placed in the html output
void SetNoFilterTag(const std::wstring & tag_name);
// orphans are checked only in 'body' tag
void AssignOrphans(const wchar_t * lang_code, const std::vector<std::wstring> & otab);
void AssignOrphans(const std::wstring & lang_code, const std::vector<std::wstring> & otab);
void ClearOrphans();
// check 'orphans' for the specicic language
// if an orphan is detected then the non-break space ("&nbsp;" or ascii 160 code) will be put
// default disable (lang_none)
void OrphansMode(const std::wstring & orphan_mode);
// skipping some unsafe tags
// (script, iframe, frame, frameset, applet, head, meta, html, link, body, ...)
void SafeMode(bool safe_mode_);
// skip all html tags
// gives only text without markup
// but there can be commentaries
void SkipTags(bool skip_tags);
// skip commentaries
void SkipCommentaries(bool skip_commentaries);
// if true then entities such as &nbsp; are skipped
// this automatically turns on AnalyzeEntities
// in such a case FoundEntity callbacks are sent
void SkipEntities(bool skip_entities);
// analyze html entities such as &nbsp;
// virtual method: FoundEntity is called
// entities are analyzed in normal text and in attribute values such as <p class="a&nbsp;">
void AnalyzeEntities(bool analyze_entities);
protected:
// orphans for one language
struct Orphans
{
std::vector<std::wstring> tab;
size_t max_len;
};
// orphans for all languages
// map<language_code, Orphans>
typedef std::map<std::wstring, Orphans> OrphansTab;
OrphansTab orphans_tab;
// html <nofilter> tag name
std::wstring no_filter_tag;
struct Item
{
std::wstring name; // max size: WINIX_HTMLFILTER_ITEM_NAME_MAXLEN
enum Type
{
opening, /* sample: <h1> */
closing, /* sample: </h1> */
simple, /* sample: <br/> */
special, /* sample: <!doctype> */
none
} type;
// is there a new line after this tag
bool new_line;
// current orphans table
// (will be propagated)
Orphans * porphans;
// this item or one from its parents is a 'body' html tag
// (will be propagated)
bool has_body_tag;
void Clear();
Item();
};
/*
virtual methods
*/
virtual void Init();
virtual void Uninit();
virtual bool IsOpeningTagMark(wchar_t c);
virtual bool IsClosingTagMark(wchar_t c);
virtual bool IsClosingXmlSimpleTagMark(wchar_t c);
virtual bool IsStartingEntityMark(wchar_t c);
virtual bool IsEndingEntityMark(wchar_t c);
virtual bool IsOpeningCommentaryTagMark(const wchar_t * str);
virtual size_t OpeningCommentaryTagMarkSize();
virtual bool IsValidCharForName(int c);
virtual bool IsValidCharForAttrName(int c);
virtual bool IsValidCharForEntityName(int c);
virtual void CheckExceptions();
virtual bool SkipCommentaryTagIfExists();
virtual void Put(wchar_t c);
virtual void Put(const wchar_t * str);
virtual void Put(const wchar_t * str, const wchar_t * end);
virtual void Put(const std::wstring & str);
virtual void AnalyzeEntitiesAndPut(const wchar_t * str, const wchar_t * end, std::wstring * out);
virtual void PutOpeningTagMark();
virtual void PutClosingTagMark();
virtual bool PutOpeningTag();
virtual void PutClosingTag(const wchar_t * tag);
virtual void PutNormalText(const wchar_t * str, const wchar_t * end);
virtual void ReadNormalTextSkipWhite(const wchar_t * & start, const wchar_t * & last_non_white);
virtual void ItemFound();
virtual void EntityFound(const wchar_t * str, const wchar_t * end);
/*
others
*/
void SetSomeDefaults();
Item & GetItem(size_t i);
Item & LastItem();
wchar_t ToLower(wchar_t c);
void ToLower(std::wstring & str);
bool IsNameEqual(const wchar_t * name1, const wchar_t * name2);
bool IsNameEqual(const wchar_t * name1, const std::wstring & name2);
bool IsNameEqual(const std::wstring & name1, const wchar_t * name2);
bool IsNameEqual(const std::wstring & name1, const std::wstring & name2);
bool IsNameEqual(const wchar_t * name1, const wchar_t * name2, size_t len);
bool IsNameEqual(const wchar_t * name1, const std::wstring & name2, size_t len);
bool IsNameEqual(const std::wstring & name1, const wchar_t * name2, size_t len);
bool IsNameEqual(const std::wstring & name1, const std::wstring & name2, size_t len);
bool IsLastTag(const wchar_t * name);
bool IsLastTag(const std::wstring & name);
bool IsTagSafe(const wchar_t * tag);
bool IsTagSafe(const std::wstring & tag);
int CheckOrphan(const wchar_t * str, const wchar_t * end, const std::wstring & orphan_str);
bool CheckOrphan(const wchar_t * str, const wchar_t * end, const std::vector<std::wstring> & orphans);
bool CheckOrphan(const wchar_t * str, const wchar_t * end);
bool IsWhite(int c);
void SkipWhite();
void SkipWhiteLines();
void SkipWhiteWithFirstNewLine();
void SkipWhiteLines(const wchar_t * & str, const wchar_t * end);
bool IsClosingTagForLastItem();
void SkipAndCheckClosingTag();
void PopStack();
bool PushStack();
void CheckNewLine();
void CheckStackPrintRest();
void AddForgottenTags();
void CheckClosingTags();
void ReadNormalText();
bool PrintRest();
bool PrintOpeningItem();
void ReadItemName();
void ReadItemAttrName();
void ReadItemAttrValueAdd(const wchar_t * value_start, const wchar_t * value_end);
void ReadItemAttrValue(bool has_quote, wchar_t quote_char);
bool ReadItemAttr();
bool CheckItemAttr();
void PrintItemAttr();
void ReadItemClosing();
void ReadItemSpecial();
void ReadItemOpening();
bool ReadItem();
void ReadLoop();
void Read();
void CheckChar(wchar_t c);
void CheckLineWrap();
bool HasEntityEndAround(const wchar_t * str, const wchar_t * end);
void PutNormalNonWhite(const wchar_t * & str, const wchar_t * end);
void PutNormalWhite(const wchar_t * & str, const wchar_t * end);
void PutEverythingUntilClosingTag(bool put_closing_tag_as_well);
void PutTabs(size_t len);
void PutNonBreakingSpace();
void PutNewLine();
void CalcOrphansMaxLen(Orphans & orphans);
const wchar_t * pchar;
Item empty;
Item * pstack; // stack pointer
size_t stack_len; // length of the stack
wchar_t * buffer; // buffer used when printing
std::wstring * out_string;
bool last_new_line;
size_t break_after; // insert a space into long words after 'break_after' characters
size_t wrap_line; // insert a new line character into long lines
bool trim_white; // trimming white characters
size_t tab_size;
OrphanMode orphan_mode;
std::wstring attr_name;
std::vector<std::wstring> attr_value;
std::wstring attr_value_temp;
std::wstring attr_value_lower;
bool attr_has_value;
std::wstring lang_code_lower;
size_t line_len; //length of the current line (without first spaces which create the html tree)
bool safe_mode; // skipping some unsafe tags
Orphans orphans_temp;
bool skip_tags;
bool skip_commentaries;
bool skip_entities;
bool analyze_entities;
};
} // namespace Winix
#endif
+4 -4
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2014, Tomasz Sowa
* Copyright (c) 2008-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -143,7 +143,7 @@ void HttpSimpleParser::ReadName()
}
if( getchar_returns_utf8_chars )
PT::UTF8ToWide(utf8_token, last_name);
pt::utf8_to_wide(utf8_token, last_name);
if( last_c == '=' )
last_c = GetChar();
@@ -173,7 +173,7 @@ void HttpSimpleParser::ReadQuotedValue()
}
if( getchar_returns_utf8_chars )
PT::UTF8ToWide(utf8_token, last_value);
pt::utf8_to_wide(utf8_token, last_value);
if( last_c == '"' )
last_c = GetChar();
@@ -204,7 +204,7 @@ void HttpSimpleParser::ReadNormalValue()
}
if( getchar_returns_utf8_chars )
PT::UTF8ToWide(utf8_token, last_value);
pt::utf8_to_wide(utf8_token, last_value);
}
+3 -2
View File
@@ -36,7 +36,8 @@
#define headerfile_winix_core_httpsimpleparser
#include <string>
#include "winixmodel.h"
#include "winixmodeldeprecated.h"
namespace Winix
@@ -44,7 +45,7 @@ namespace Winix
class HttpSimpleParser : public WinixModel
class HttpSimpleParser : public WinixModelDeprecated
{
protected:
+56 -49
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
#include <ctime>
#include "image.h"
#include "core/misc.h"
#include "utf8/utf8.h"
#include "system.h"
#include "lock.h"
@@ -44,14 +45,6 @@ namespace Winix
{
void Image::SetDb(Db * pdb)
{
db = pdb;
}
void Image::SetConfig(Config * pconfig)
{
config = pconfig;
@@ -267,7 +260,7 @@ bool end;
do
{
class Lock lock_object(synchro);
Winix::Lock lock_object(synchro);
if( i != image_tab.end() )
{
@@ -292,19 +285,13 @@ bool end;
void Image::Add(const std::wstring & in, TextStream<std::string> & out)
{
PT::WideToUTF8(in, add_tempa);
out << add_tempa;
}
void Image::EscapePath(const std::string & path, TextStream<std::string> & out, bool clear_stream)
void Image::EscapePath(const std::string & path, pt::TextStream & out, bool clear_stream)
{
if( clear_stream )
out.Clear();
out.clear();
out << '"';
@@ -377,7 +364,7 @@ bool Image::CreateInputFileName()
{
bool thumb = (item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB);
if( thumb && !file_work.has_thumb )
if( thumb && !file_work.item_content.file_has_thumb )
{
log << log1 << "Image: file id: " << file_work.id << ", url: " << file_work.url
<< " doesn't have a thumbnail yet (skipping)" << logend;
@@ -387,7 +374,7 @@ bool Image::CreateInputFileName()
if( system->MakeFilePath(file_work, src_path, thumb) )
{
PT::WideToUTF8(src_path, input_file_name);
pt::wide_to_utf8(src_path, input_file_name);
return true;
}
else
@@ -402,9 +389,9 @@ bool Image::CreateInputFileName()
// second thread (objects locked)
void Image::CreateTmpFileName()
{
stream_tmp_path.Clear();
stream_tmp_path.clear();
stream_tmp_path << config->upload_dir << L"/tmp/image_" << std::time(0);
PT::WideToUTF8(stream_tmp_path.Str(), tmp_file_name);
stream_tmp_path.to_str(tmp_file_name);
}
@@ -412,20 +399,23 @@ void Image::CreateTmpFileName()
// second thread (objects are not locked)
bool Image::CreateCommand()
{
class Lock lock_object(synchro);
Winix::Lock lock_object(synchro);
iq.SetAll(true, false);
iq.WhereId(item_work.file_id);
// iq.SetAll(true, false);
// iq.WhereId(item_work.file_id);
morm::Finder<Item> finder(model_connector);
file_work = finder.select().where().eq(L"id", item_work.file_id).get();
// the file could have been changed especially when there is a long queue of files
if( db->GetItem(file_work, iq) != WINIX_ERR_OK )
if( !file_work.found() )
return false;
if( !CreateInputFileName() )
return false;
command.Clear();
Add(config->convert_cmd, command);
command.clear();
command << config->convert_cmd;
command << " ";
EscapePath(input_file_name, command, false);
@@ -469,7 +459,7 @@ bool Image::CreateCommand()
command << " ";
EscapePath(tmp_file_name, command, false);
log << log4 << "Image: running: " << command.Str() << logend;
log << log4 << "Image: running: " << command << logend;
return true;
@@ -483,34 +473,37 @@ void Image::ImageSavedCorrectly()
{
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB )
{
if( !file_work.has_thumb )
if( !file_work.item_content.file_has_thumb )
{
file_work.has_thumb = true;
db->EditHasThumbById(true, file_work.id);
file_work.item_content.file_has_thumb = true;
file_work.propagate_connector();
file_work.item_content.update(false);
//db->EditHasThumbById(true, file_work.id);
}
log << log3 << "Image: generated a thumbnail: " << dst_path << logend;
plugin->Call((Session*)0, WINIX_CREATED_THUMB, &file_work);
plugin->Call(model_connector, &log, nullptr, WINIX_CREATED_THUMB, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_RESIZE )
{
log << log3 << "Image: image resized: " << dst_path << logend;
plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
plugin->Call(model_connector, &log, nullptr, WINIX_IMAGE_RESIZED, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_CROP )
{
log << log3 << "Image: image cropped: " << dst_path << logend;
// !! IMPROVE ME add a correct message
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
//plugin->Call(model_connector, &log, nullptr, WINIX_IMAGE_RESIZED, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB )
{
log << log3 << "Image: image thumbnail cropped: " << dst_path << logend;
// !! IMPROVE ME add a correct message
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
//plugin->Call(model_connector, &log, nullptr, WINIX_IMAGE_RESIZED, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB )
@@ -525,21 +518,32 @@ void Image::ImageSavedCorrectly()
// second thread (objects are not locked)
void Image::SaveImage()
{
class Lock lock_object(synchro);
Winix::Lock lock_object(synchro);
// the file could have been changed especially when creating the image lasted too long
iq.SetAll(true, false);
iq.WhereId(item_work.file_id);
//iq.SetAll(true, false);
//iq.WhereId(item_work.file_id);
if( db->GetItem(file_work, iq) == WINIX_ERR_OK )
{
morm::Finder<Item> finder(model_connector);
file_work = finder.select().where().eq(L"id", item_work.file_id).get();
// the file could have been changed especially when there is a long queue of files
if( !file_work.found() )
return;
//if( db->GetItem(file_work, iq) == WINIX_ERR_OK )
//{
bool thumb = (item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB ||
item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB ||
item_work.type == WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB );
if( system->MakeFilePath(file_work, dst_path, thumb, true, config->upload_dirs_chmod, config->upload_group_int) )
{
if( RenameFile(stream_tmp_path.Str(), dst_path) )
std::wstring from;
stream_tmp_path.to_str(from);
if( RenameFile(from, dst_path) )
{
// it doesn't matter for us if there is an error when chmod/chown on a file
// the admin (root) will correct it
@@ -548,17 +552,17 @@ void Image::SaveImage()
}
else
{
log << log1 << "Image: cannot move a temporary file: " << stream_tmp_path.Str()
log << log1 << "Image: cannot move a temporary file: " << stream_tmp_path
<< ", to: " << dst_path << logend;
Winix::RemoveFile(stream_tmp_path.Str());
Winix::RemoveFile(from);
}
}
else
{
log << log1 << "Image: cannot create a destination path" << logend;
}
}
//}
}
@@ -568,7 +572,9 @@ void Image::CreateImage()
{
if( CreateCommand() )
{
int res = std::system(command.CStr());
std::string command_str;
command.to_str(command_str);
int res = std::system(command_str.c_str());
if( res == 0 )
{
@@ -576,11 +582,12 @@ void Image::CreateImage()
}
else
{
class Lock lock_object(synchro);
log << log3 << "Image: some problems with creating an image"
<< ", 'convert' process returned: " << res << logend;
}
}
log << logsave;
}
@@ -597,8 +604,8 @@ void Image::CreateImage()
void Image::CreateThumbnail()
{
PT::WideToUTF8(item_work.source, sourcea);
PT::WideToUTF8(item_work.dst, dsta);
pt::wide_to_utf8(item_work.source, sourcea);
pt::wide_to_utf8(item_work.dst, dsta);
MagickWandGenesis();
+5 -12
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,10 +38,8 @@
#include <string>
#include <list>
#include "basethread.h"
#include "textstream.h"
#include "db/db.h"
#include "core/item.h"
#include "core/config.h"
#include "models/item.h"
namespace Winix
@@ -116,7 +114,6 @@ public:
};
void SetDb(Db * pdb);
void SetConfig(Config * pconfig);
void SetSystem(System * psystem);
@@ -147,7 +144,6 @@ public:
private:
Db * db;
Config * config;
System * system;
@@ -185,10 +181,8 @@ private:
// only for second thread
ImageItem item_work;
std::wstring src_path, dst_path;
TextStream<std::string> command;
TextStream<std::wstring> stream_tmp_path;
DbItemQuery iq;
std::string add_tempa;
pt::TextStream command;
pt::WTextStream stream_tmp_path;
std::string input_file_name;
std::string tmp_file_name;
Item file_work;
@@ -201,9 +195,8 @@ private:
void SaveImage();
void CreateImage();
void SelectAspect(size_t cx, size_t cy);
void EscapePath(const std::string & path, TextStream<std::string> & out, bool clear_stream = true);
void EscapePath(const std::string & path, pt::TextStream & out, bool clear_stream = true);
void CheckParam(ImageItem & item);
void Add(const std::wstring & in, TextStream<std::string> & out);
void ImageSavedCorrectly();
};
+2 -2
View File
@@ -148,7 +148,7 @@ void IPBanContainer::PrintTab()
{
log << log4 << i << ": ip: " << ipban_tab[i].ip << ", flags: " << ipban_tab[i].flags << ", last_used: ";
PT::Date date(ipban_tab[i].last_used);
pt::Date date(ipban_tab[i].last_used);
log << date << ", expires: ";
date = ipban_tab[i].expires;
@@ -168,7 +168,7 @@ void IPBanContainer::PrintTab2()
log << log4 << i << ": ip: " << ipban.ip << ", flags: " << ipban.flags << ", last_used: ";
PT::Date date(ipban.last_used);
pt::Date date(ipban.last_used);
log << date << ", expires: ";
date = ipban.expires;
+2 -2
View File
@@ -37,7 +37,7 @@
#include <vector>
#include "ipban.h"
#include "winixmodel.h"
#include "winixmodeldeprecated.h"
@@ -46,7 +46,7 @@ namespace Winix
class IPBanContainer : public WinixModel
class IPBanContainer : public WinixModelDeprecated
{
public:
-156
View File
@@ -1,156 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2016, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_item
#define headerfile_winix_core_item
#include <string>
#include "space/space.h"
#include "date/date.h"
namespace Winix
{
#define WINIX_ITEM_FILETYPE_NONE 0
#define WINIX_ITEM_FILETYPE_IMAGE 1
#define WINIX_ITEM_FILETYPE_DOCUMENT 2
#define WINIX_ITEM_FILETYPE_VIDEO 3
#define WINIX_ITEM_FILETYPE_UNKNOWN 10
struct Item
{
long id;
long parent_id;
long user_id;
long group_id;
std::wstring guest_name; // used as a user name when user_id is equal -1
long modification_user_id; // who has modified the item last (not taken into account when checking permissions)
int privileges;
PT::Date date_creation;
PT::Date date_modification;
std::wstring subject;
std::wstring content;
std::wstring url;
int modify_index;
enum ContentType
{
ct_text = 0,
ct_formatted_text,
ct_html,
ct_bbcode,
ct_other, // no auto-formatting is applied
};
ContentType content_type;
enum Type
{
dir = 0,
file = 1,
symlink = 2,
none = 1000
};
Type type;
// used when type is symlink or to a directory too (function 'default')
std::wstring link_to;
int link_redirect; // !! IMPROVE ME should it be 'bool'?
// static file (if exists)
std::wstring file_path; // relative file path
int file_fs; // file system type where the file was saved
int file_type; // file type (none, image, doc, etc)
bool has_thumb; // whether or not we have a thumbnail
std::wstring hash; // file hash (md4, md5, ...)
int hash_type; // hash type WINIX_CRYPT_HASH_* (see crypt.h)
size_t file_size; // size of the file
std::wstring html_template;
// sort index used when displaying a group of items
int sort_index;
// meta information
PT::Space meta;
PT::Space ameta;
// methods
Item();
void SetDateToNow();
void SetDateModifyToNow();
void Clear();
static bool CanContentBeHtmlFiltered(Item::ContentType ct);
bool CanContentBeHtmlFiltered();
private:
// used by the database
long content_id; // content id in 'content' table
int ref; // content references
friend class Db;
friend struct DbItemColumns;
};
} // namespace Winix
#endif
+279 -31
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2012-2019, Tomasz Sowa
* Copyright (c) 2012-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,9 @@
#include "job.h"
#include "plugin.h"
#include "log.h"
#include "functions/functions.h"
#include "lock.h"
namespace Winix
@@ -45,31 +48,115 @@ namespace Winix
Job::Job()
{
jobs_queue_tab.resize(WINIX_JOBS_HOW_MANY_PRIORITIES);
jobs_queue_tab.resize(PRIORITY_HIGHEST + 1);
cur = nullptr;
functions = nullptr;
mounts = nullptr;
load_avg = nullptr;
req_tab = nullptr;
}
void Job::CheckPriority(int & priority) const
void Job::SetCur(Cur * cur)
{
if( priority < 0 )
priority = 0;
this->cur = cur;
}
if( priority >= WINIX_JOBS_HOW_MANY_PRIORITIES )
priority = WINIX_JOBS_HOW_MANY_PRIORITIES - 1;
void Job::SetFunctions(Functions * functions)
{
this->functions = functions;
}
void Job::SetLoadAvg(LoadAvg * load_avg)
{
this->load_avg = load_avg;
}
void Job::SetMounts(Mounts * mounts)
{
this->mounts = mounts;
}
void Job::SetReqTab(std::list<Request> * req_tab)
{
this->req_tab = req_tab;
}
void Job::CheckPriority(size_t & priority) const
{
if( priority > PRIORITY_HIGHEST )
priority = PRIORITY_HIGHEST;
}
// first thread (objects locked)
void Job::Add(PT::Space & job, int priority)
void Job::Add(pt::Space & job, size_t priority)
{
CheckPriority(priority);
jobs_queue_tab[priority].push(job);
JobTask task;
task.job_type = JobTask::JOB_TYPE_DEFAULT;
task.job_id = JobTask::JOB_ID_DEFAULT;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
// first thread (objects locked)
void Job::Add(Request * request, pt::Space & job, size_t priority)
{
CheckPriority(priority);
JobTask task;
task.job_type = JobTask::JOB_TYPE_REQUEST_CONTINUATION;
task.job_id = JobTask::JOB_ID_DEFAULT;
task.request = request;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
size_t Job::Size(int priority) const
// first thread (objects locked)
void Job::Add(long job_id, pt::Space & job, size_t priority)
{
CheckPriority(priority);
JobTask task;
task.job_type = JobTask::JOB_TYPE_DEFAULT;
task.job_id = job_id;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
// first thread (objects locked)
void Job::Add(long job_id, Request * request, pt::Space & job, size_t priority)
{
CheckPriority(priority);
JobTask task;
task.job_type = JobTask::JOB_TYPE_REQUEST_CONTINUATION;
task.job_id = job_id;
task.request = request;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
void Job::RegisterRequestJob(long job_id, RequestJobBase & request_job)
{
request_jobs.insert(std::make_pair(job_id, &request_job));
}
size_t Job::Size(size_t priority) const
{
CheckPriority(priority);
return jobs_queue_tab[priority].size();
@@ -81,14 +168,14 @@ size_t Job::Size() const
{
size_t sum = 0;
for(size_t i=0 ; i<WINIX_JOBS_HOW_MANY_PRIORITIES ; ++i)
for(size_t i=0 ; i <= PRIORITY_HIGHEST ; ++i)
sum += Size(i);
return sum;
}
bool Job::Empty(int priority) const
bool Job::Empty(size_t priority) const
{
CheckPriority(priority);
return jobs_queue_tab[priority].empty();
@@ -97,7 +184,7 @@ bool Job::Empty(int priority) const
bool Job::Empty() const
{
for(size_t i=0 ; i<WINIX_JOBS_HOW_MANY_PRIORITIES ; ++i)
for(size_t i=0 ; i <= PRIORITY_HIGHEST ; ++i)
if( !Empty(i) )
return false;
@@ -111,6 +198,7 @@ return true;
second thread
*/
// second thread (objects locked)
bool Job::SignalReceived()
{
@@ -121,19 +209,20 @@ bool Job::SignalReceived()
// second thread (objects not locked)
void Job::Do()
{
size_t i = WINIX_JOBS_HOW_MANY_PRIORITIES;
size_t i = PRIORITY_HIGHEST + 1;
bool is_empty;
while( i-- > 0 && !IsExitSignal() )
{
do
{
Lock();
is_empty = Empty(i);
Unlock();
{
Winix::Lock lock(synchro);
is_empty = Empty(i);
}
if( !is_empty )
DoQueue(jobs_queue_tab[i]);
DoQueue(jobs_queue_tab[i], i);
}
while( !is_empty && !IsExitSignal() );
}
@@ -141,53 +230,212 @@ bool is_empty;
// second thread (objects not locked, jobs_queue is not empty)
void Job::DoQueue(JobsQueue & jobs_queue)
void Job::DoQueue(JobsQueue & jobs_queue, size_t priority)
{
bool is_empty;
do
{
Lock();
// references will not be invalidated after insertion to jobs_queue
// (jobs_queue is std::queue and it uses std::deque by default)
PT::Space & job = jobs_queue.front();
Unlock();
JobTask * job_task = nullptr;
DoJob(job);
{
Winix::Lock lock(synchro);
Lock();
jobs_queue.pop();
is_empty = jobs_queue.empty();
Unlock();
if( !jobs_queue.empty() )
{
job_task = &jobs_queue.front();
}
}
if( job_task )
{
DoJob(*job_task, priority);
{
Winix::Lock lock(synchro);
jobs_queue.pop();
is_empty = jobs_queue.empty();
}
}
}
while( !is_empty && !IsExitSignal() );
}
// second thread (objects not locked)
void Job::DoJob(PT::Space & job)
void Job::DoJob(JobTask & task, size_t priority)
{
PluginRes res;
try
{
PluginRes res = plugin->Call((Session*)0, WINIX_JOB, &job);
main_log << logsave;
if( task.job_type == JobTask::JOB_TYPE_REQUEST_CONTINUATION )
{
res = DoRequestJobs(task, task.job_id, priority);
}
else
{
res = plugin->Call(model_connector, &log, nullptr, WINIX_JOB, &task.job, nullptr, task.job_type, task.job_id);
}
log << logsave;
if( res.res_true == 0 )
DoWinixJob(job);
{
DoWinixJob(task.job); // probably this will be removed
}
}
catch(...)
{
log << log2 << "Job: an exception was catched when doing a job" << logend;
}
}
// second thread (objects not locked)
void Job::DoWinixJob(PT::Space & job)
PluginRes Job::DoRequestJobs(JobTask & task, long job_id, size_t priority)
{
PluginRes res;
if( task.request )
{
auto jobs_iterator = request_jobs.lower_bound(job_id);
bool has_job = false;
while( jobs_iterator != request_jobs.end() && jobs_iterator->first == job_id )
{
task.request->run_state = Request::RunState::job_run;
jobs_iterator->second->set_dependency(this);
jobs_iterator->second->set_request(task.request);
jobs_iterator->second->do_job();
jobs_iterator++;
has_job = true;
}
if( !has_job )
{
log << log2 << "Job: I could not find a request job with id: " << job_id << logend;
}
Cur local_cur;
local_cur.request = task.request;
local_cur.request->run_state = Request::RunState::job_run;
local_cur.session = task.request->session;
local_cur.mount = task.request->mount;
{
Winix::Lock lock(synchro);
log << logsave;
Cur old_cur = *cur;
*cur = local_cur;
DoRequestContinuationJob(task, priority);
*cur = old_cur;
}
}
else
{
log << log2 << "Job: request continuation task doesn't have a request set, skipping the job and request continuation" << logend;
log << log2 << "Job: this is an internal error, the request if exists in the queue will never be removed" << logend;
}
return res;
}
// second thread (objects locked)
// use main_log (after locking) for the logs to be in the correct order
void Job::DoRequestContinuationJob(JobTask & job_task, size_t priority)
{
if( cur->request->function )
{
main_log << config->log_delimiter << logend;
main_log << log3 << "Job: making a continuation for request " << cur->request << logend;
main_log << log4 << "Job: doing directory analysis again" << logend;
if( functions->ParseOnlyDirs() )
{
cur->mount = mounts->CalcCurMount(cur->request);
cur->request->mount = cur->mount;
cur->request->run_state = Request::RunState::job_continuation_run;
functions->ContinueMakeFunction();
if( cur->request->run_state == Request::RunState::assigned_to_job )
{
log << log3 << "Job: this request (" << cur->request << ") has been moved to the job queue again" << logend;
Add(cur->request->job_id, cur->request, cur->request->job, priority);
}
}
else
{
main_log << log4 << "Job: directories have not been correctly prepared, finishing the request" << logend;
cur->request->http_status = Header::status_500_internal_server_error;
cur->request->run_state = Request::RunState::prepare_to_finish;
}
}
else
{
main_log << log2 << "Job: request continuation task doesn't have a funtion set, return 500 internal error" << logend;
cur->request->http_status = Header::status_500_internal_server_error;
cur->request->run_state = Request::RunState::prepare_to_finish;
}
if( cur->request->run_state != Request::RunState::assigned_to_job )
{
cur->request->FinishRequest(); // if cur->request->function were null then templates functions would not work
load_avg->StopRequest(cur->request);
if( cur->request->function )
cur->request->function->clear();
cur->request->Clear();
cur->request->run_state = Request::RunState::finished;
RemoveOldRequest(cur->request);
}
else
{
if( cur->request->function )
cur->request->function->clear();
}
main_log << logendrequest;
}
// second thread (objects not locked)
void Job::DoWinixJob(pt::Space & job)
{
//log << log1 << "standard winix job: " << job.Text(L"type") << logend;
}
// second thread (objects locked)
// use main_log for the logs to be in the correct order
void Job::RemoveOldRequest(Request * request)
{
std::list<Request>::iterator i = req_tab->begin();
while( i != req_tab->end() )
{
if( &(*i) == request )
{
main_log << log3 << "Job: removing request " << request << logend;
req_tab->erase(i);
break;
}
else
{
++i;
}
}
}
} // namespace Winix
+49 -13
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2012-2014, Tomasz Sowa
* Copyright (c) 2012-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,22 +32,26 @@
*
*/
#ifndef headerfile_winix_core_jobs
#define headerfile_winix_core_jobs
#ifndef headerfile_winix_core_job
#define headerfile_winix_core_job
#include <vector>
#include <queue>
#include "basethread.h"
#include "space/space.h"
#include "jobtask.h"
#include "cur.h"
#include "loadavg.h"
#include "mounts.h"
#include "requestjobs/requestjobbase.h"
namespace Winix
{
class Functions;
#define WINIX_JOBS_HOW_MANY_PRIORITIES 32
@@ -55,19 +59,40 @@ class Job : public BaseThread
{
public:
static const size_t PRIORITY_LOWEST = 0;
static const size_t PRIORITY_HIGHEST = 31;
static const size_t PRIORITY_DEFAULT = 16;
static const size_t PRIORITY_REQUEST_CONTINUATION = 17;
Job();
void SetCur(Cur * cur);
void SetFunctions(Functions * functions);
void SetLoadAvg(LoadAvg * load_avg);
void SetMounts(Mounts * mounts);
void SetReqTab(std::list<Request> * req_tab);
/*
add a new job to the queue
priority: 0-31 (0 - the lowest priority, 31 - the highest priority)
*/
void Add(PT::Space & job, int priority = 0);
void Add(pt::Space & job, size_t priority = PRIORITY_DEFAULT);
void Add(Request * request, pt::Space & job, size_t priority = PRIORITY_DEFAULT);
void Add(long job_id, pt::Space & job, size_t priority = PRIORITY_DEFAULT);
void Add(long job_id, Request * request, pt::Space & job, size_t priority = PRIORITY_DEFAULT);
/*
* register a new request job worker
*/
void RegisterRequestJob(long job_id, RequestJobBase & request_job);
/*
queue size, and size of all jobs in any priority
*/
size_t Size(int priority) const;
size_t Size(size_t priority) const;
size_t Size() const;
@@ -75,17 +100,24 @@ public:
true if specified queue is empty
or if all queues are empty
*/
bool Empty(int priority) const;
bool Empty(size_t priority) const;
bool Empty() const;
private:
typedef std::queue<PT::Space> JobsQueue;
Cur * cur;
Functions * functions;
LoadAvg * load_avg;
Mounts * mounts;
std::list<Request> * req_tab;
typedef std::queue<JobTask> JobsQueue;
typedef std::vector<JobsQueue> JobsQueueTab;
JobsQueueTab jobs_queue_tab;
std::multimap<long, RequestJobBase*> request_jobs;
void CheckPriority(int & priority) const;
void CheckPriority(size_t & priority) const;
void SaveToFile();
void ReadFromFile();
@@ -101,9 +133,13 @@ private:
bool SignalReceived();
void Do();
void DoQueue(JobsQueue & jobs_queue);
void DoJob(PT::Space & job);
void DoWinixJob(PT::Space & job);
void DoQueue(JobsQueue & jobs_queue, size_t priority);
void DoJob(JobTask & task, size_t priority);
void DoRequestContinuationJob(JobTask & job_task, size_t priority);
void DoWinixJob(pt::Space & job);
void RemoveOldRequest(Request * request);
void RemoveAllJobsRequests();
PluginRes DoRequestJobs(JobTask & task, long job_id, size_t priority);
};
+86
View File
@@ -0,0 +1,86 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_jobtask
#define headerfile_winix_core_jobtask
#include "space/space.h"
namespace Winix
{
class Request;
class JobTask
{
public:
static const long JOB_TYPE_DEFAULT = 1;
static const long JOB_TYPE_REQUEST_CONTINUATION = 2;
/*
* the value of job_id will be defined by each controller
* so the default value is better to have -1 instead of for example 1
*/
static const long JOB_ID_DEFAULT = -1;
long job_type;
long job_id;
Request * request;
pt::Space job;
JobTask()
{
clear();
}
void clear()
{
job_type = JOB_TYPE_DEFAULT;
job_id = JOB_ID_DEFAULT;
request = nullptr;
job.clear();
}
};
}
#endif
+2 -2
View File
@@ -69,8 +69,8 @@ struct LastItem
long session_id;
// start logging and end logging
PT::Date start;
PT::Date end;
pt::Date start;
pt::Date end;
LastItem();
+13 -20
View File
@@ -56,7 +56,8 @@ LoadAvg::LoadAvg()
cache_req_per_sec5 = 0.0;
cache_req_per_sec15 = 0.0;
was_stop_request = false;
timespec_old_req_stop.tv_sec = 0;
timespec_old_req_stop.tv_nsec = 0;
CreateTable();
}
@@ -76,7 +77,8 @@ LoadAvg & LoadAvg::operator=(const LoadAvg & l)
cache_req_per_sec5 = l.cache_req_per_sec5;
cache_req_per_sec15 = l.cache_req_per_sec15;
was_stop_request = l.was_stop_request;
timespec_old_req_stop.tv_sec = l.timespec_old_req_stop.tv_sec;
timespec_old_req_stop.tv_nsec = l.timespec_old_req_stop.tv_nsec;
CreateTable();
@@ -182,14 +184,14 @@ void LoadAvg::CheckTimers()
void LoadAvg::StartRequest()
void LoadAvg::StartRequest(Request * req)
{
clock_gettime(CLOCK_REALTIME, &start_req);
if( was_stop_request )
if( timespec_old_req_stop.tv_sec != 0 )
{
double dp = (start_req.tv_sec - stop_req.tv_sec);
dp += double(start_req.tv_nsec - stop_req.tv_nsec) / 1000000000.0; // make sure that tv_nsec has signed type
// we got at least one request in the past
timespec diff;
calculate_timespec_diff(timespec_old_req_stop, req->timespec_req_start, diff);
double dp = timespec_to_double(diff);
current1.dp += dp;
current5.dp += dp;
@@ -203,14 +205,9 @@ void LoadAvg::StartRequest()
void LoadAvg::StopRequest()
void LoadAvg::StopRequest(Request * req)
{
char buf[50];
clock_gettime(CLOCK_REALTIME, &stop_req);
double dr = (stop_req.tv_sec - start_req.tv_sec);
dr += double(stop_req.tv_nsec - start_req.tv_nsec) / 1000000000.0; // make sure that tv_nsec has signed type
double dr = timespec_to_double(req->timespec_req_diff);
current1.dr += dr;
current5.dr += dr;
@@ -220,11 +217,7 @@ char buf[50];
current5.req += 1;
current15.req += 1;
sprintf(buf, "%f", dr);
SetNonZeroDigitsAfterComma(buf, 2);
log << log2 << "LA: request took: " << buf << "s" << logend;
was_stop_request = true;
timespec_old_req_stop = req->timespec_req_stop;
}
+6 -5
View File
@@ -37,6 +37,7 @@
#include <ctime>
#include "winixbase.h"
#include "request.h"
namespace Winix
@@ -60,8 +61,8 @@ public:
LoadAvg & operator=(const LoadAvg & l);
LoadAvg(const LoadAvg & l);
void StartRequest();
void StopRequest();
void StartRequest(Request * req);
void StopRequest(Request * req);
double LoadAvgNow(); // load average withing last WINIX_LOADAVG_GRANULARITY1 seconds
double LoadAvg1();
@@ -78,7 +79,7 @@ private:
struct Times
{
double dr; // time for the request (in seconds)
double dp; // time for the pause between requestes (in seconds)
double dp; // time for the pause between requestes(in seconds)
long req; // how many requests
void Clear()
@@ -98,6 +99,8 @@ private:
}
};
timespec timespec_old_req_stop;
void CheckTimers();
void UpdateTimer1();
void UpdateTimer5();
@@ -117,8 +120,6 @@ private:
void Calculate5();
void Calculate15();
bool was_stop_request;
timespec start_req, stop_req;
Times * tab1;
size_t len1;
+129 -45
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2019, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,7 +72,7 @@ void Log::SetMaxRequests(int max_requests)
void Log::PrintDate(const PT::Date & date)
void Log::PrintDate(const pt::Date & date)
{
FileLog * winix_file_log = dynamic_cast<FileLog*>(file_log);
@@ -86,7 +86,7 @@ void Log::PrintDate(const PT::Date & date)
Log & Log::operator<<(const void * s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
@@ -94,7 +94,7 @@ Log & Log::operator<<(const void * s)
Log & Log::operator<<(const char * s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
@@ -102,7 +102,7 @@ Log & Log::operator<<(const char * s)
Log & Log::operator<<(const std::string & s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
@@ -110,7 +110,7 @@ Log & Log::operator<<(const std::string & s)
Log & Log::operator<<(const std::string * s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
@@ -118,120 +118,197 @@ Log & Log::operator<<(const std::string * s)
Log & Log::operator<<(const wchar_t * s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(const std::wstring & s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(const std::wstring * s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(bool s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(short s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(int s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(long s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(long long s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(char s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(unsigned char s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(wchar_t s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(size_t s)
Log & Log::operator<<(char32_t s)
{
PT::Log::operator<<(s);
return *this;
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(unsigned short s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(unsigned int s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(unsigned long s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(unsigned long long s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(float s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(double s)
{
PT::Log::operator<<(s);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(const PT::Space & s)
Log & Log::operator<<(long double s)
{
PT::Log::operator<<(s);
return *this;
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(const PT::Date & date)
Log & Log::operator<<(const pt::Stream & s)
{
PT::Log::operator<<(date);
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(const pt::Space & s)
{
pt::Log::operator<<(s);
return *this;
}
Log & Log::operator<<(const pt::Date & date)
{
pt::Log::operator<<(date);
return *this;
}
Log & Log::operator<<(morm::Model & model)
{
pt::Log::operator<<(model);
return *this;
}
Log & Log::operator<<(LogManipulators m)
{
switch(m)
{
case LogManipulators::log1:
PT::Log::operator<<(PT::Log::log1);
pt::Log::operator<<(pt::Log::log1);
break;
case LogManipulators::log2:
PT::Log::operator<<(PT::Log::log2);
pt::Log::operator<<(pt::Log::log2);
break;
case LogManipulators::log3:
PT::Log::operator<<(PT::Log::log3);
pt::Log::operator<<(pt::Log::log3);
break;
case LogManipulators::log4:
PT::Log::operator<<(PT::Log::log4);
pt::Log::operator<<(pt::Log::log4);
break;
case LogManipulators::logend:
PT::Log::operator<<(PT::Log::logend);
pt::Log::operator<<(pt::Log::logend);
break;
case LogManipulators::logsave:
PT::Log::operator<<(PT::Log::logsave);
pt::Log::operator<<(pt::Log::logsave);
break;
case LogManipulators::logendrequest:
@@ -246,7 +323,14 @@ Log & Log::operator<<(LogManipulators m)
break;
}
return *this;
return *this;
}
Log & Log::operator<<(pt::Log::Manipulators m)
{
pt::Log::operator<<(m);
return *this;
}
@@ -265,33 +349,33 @@ return *this;
Log & Log::LogString(const std::string & value, size_t max_size)
/*
Log & Log::put_string(const std::string & value, size_t max_size)
{
PT::Log::LogString(value, max_size);
pt::Log::put_string(value, max_size);
return *this;
}
Log & Log::LogString(const std::wstring & value, size_t max_size)
Log & Log::put_string(const std::wstring & value, size_t max_size)
{
PT::Log::LogString(value, max_size);
pt::Log::put_string(value, max_size);
return *this;
}
Log & Log::LogBinary(const char * blob, size_t blob_len)
Log & Log::put_binary_blob(const char * blob, size_t blob_len)
{
PT::Log::LogBinary(blob, blob_len);
pt::Log::put_binary_blob(blob, blob_len);
return *this;
}
Log & Log::LogBinary(const std::string & blob)
Log & Log::put_binary_blob(const std::string & blob)
{
PT::Log::LogBinary(blob);
pt::Log::put_binary_blob(blob);
return *this;
}
*/
+36 -16
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2019, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,8 @@
#include "logmanipulators.h"
#include "filelog.h"
#include "log/log.h"
#include "morm.h"
namespace Winix
@@ -51,7 +53,7 @@ namespace Winix
class Log : public PT::Log
class Log : public pt::Log
{
public:
@@ -69,27 +71,45 @@ public:
virtual Log & operator<<(const wchar_t * s);
virtual Log & operator<<(const std::wstring * s);
virtual Log & operator<<(const std::wstring & s);
virtual Log & operator<<(char s);
virtual Log & operator<<(unsigned char);
virtual Log & operator<<(wchar_t s);
virtual Log & operator<<(char32_t s);
virtual Log & operator<<(bool);
virtual Log & operator<<(short);
virtual Log & operator<<(int s);
virtual Log & operator<<(long s);
virtual Log & operator<<(char s);
virtual Log & operator<<(wchar_t s);
virtual Log & operator<<(size_t s);
virtual Log & operator<<(long long);
virtual Log & operator<<(unsigned short);
virtual Log & operator<<(unsigned int);
virtual Log & operator<<(unsigned long);
virtual Log & operator<<(unsigned long long);
virtual Log & operator<<(float);
virtual Log & operator<<(double s);
virtual Log & operator<<(const PT::Space & space);
virtual Log & operator<<(LogManipulators m);
virtual Log & operator<<(const PT::Date & date);
virtual Log & operator<<(long double);
virtual void PrintDate(const PT::Date & date);
virtual Log & operator<<(const pt::Stream & stream);
virtual Log & operator<<(const pt::Space & space);
virtual Log & operator<<(const pt::Date & date);
virtual Log & operator<<(LogManipulators m);
virtual Log & operator<<(pt::Log::Manipulators m);
virtual Log & operator<<(morm::Model & model);
virtual void PrintDate(const pt::Date & date);
template<typename char_type, size_t stack_size, size_t heap_block_size>
Log & operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf);
Log & operator<<(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & buf);
virtual Log & LogString(const std::string & value, size_t max_size);
virtual Log & LogString(const std::wstring & value, size_t max_size);
/*
virtual Log & put_string(const std::string & value, size_t max_size);
virtual Log & put_string(const std::wstring & value, size_t max_size);
virtual Log & LogBinary(const char * blob, size_t blob_len);
virtual Log & LogBinary(const std::string & blob);
virtual Log & put_binary_blob(const char * blob, size_t blob_len);
virtual Log & put_binary_blob(const std::string & blob);
*/
//virtual Log & SystemErr(int err);
@@ -111,9 +131,9 @@ private:
template<typename char_type, size_t stack_size, size_t heap_block_size>
Log & Log::operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf)
Log & Log::operator<<(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & buf)
{
PT::Log::operator<<(buf);
pt::Log::operator<<(buf);
return *this;
}
+4 -4
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2018, Tomasz Sowa
* Copyright (c) 2011-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,11 +69,11 @@ enum LogManipulators
logend,
logsave,
/*
* it is needed here?
*/
logendrequest,
loginfo,
logerror,
logwarning
};
+431 -106
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@ namespace misc_private
0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028,
0x2029, 0x202F, 0x205F, 0x3000 };
PT::WTextStream tmp_qencode;
pt::WTextStream tmp_qencode;
}
@@ -331,7 +331,7 @@ void CorrectUrlOnlyAllowedChar(std::wstring & url)
{
CorrectUrlDots(url);
CorrectUrlChars(url);
PT::ToLower(url);
pt::to_lower_emplace(url);
Trim(url, '_');
if( url.empty() || url == L"." )
@@ -359,7 +359,7 @@ void CorrectUrlOnlyAllowedChar(std::wstring & url)
// DEPRECATED now pt::Date can print a month in Roman numerals
const wchar_t * DateToStr(int year, int month, int day)
{
static const wchar_t * month_letter[] = { L"I", L"II", L"III", L"IV", L"V", L"VI", L"VII", L"VIII", L"IX", L"X", L"XI", L"XII" };
@@ -383,6 +383,7 @@ static wchar_t buffer[100];
}
// DEPRECATED now pt::Date can print a month in Roman numerals
const wchar_t * DateToStr(int year, int month, int day, int hour, int min, int sec)
{
static const wchar_t * month_letter[] = { L"I", L"II", L"III", L"IV", L"V", L"VI", L"VII", L"VIII", L"IX", L"X", L"XI", L"XII" };
@@ -408,7 +409,7 @@ static wchar_t buffer[100];
const wchar_t * DateToStr(const PT::Date & d)
const wchar_t * DateToStr(const pt::Date & d)
{
return DateToStr(d.year, d.month, d.day, d.hour, d.min, d.sec);
}
@@ -416,14 +417,14 @@ const wchar_t * DateToStr(const PT::Date & d)
const wchar_t * DateToStr(time_t t)
{
PT::Date date = t;
pt::Date date = t;
return DateToStr(date);
}
const wchar_t * DateToStrWithoutHours(const PT::Date & d)
const wchar_t * DateToStrWithoutHours(const pt::Date & d)
{
return DateToStr(d.year, d.month, d.day);
}
@@ -431,7 +432,7 @@ const wchar_t * DateToStrWithoutHours(const PT::Date & d)
const wchar_t * DateToStrWithoutHours(time_t t)
{
PT::Date date = t;
pt::Date date = t;
return DateToStrWithoutHours(date);
}
@@ -460,7 +461,7 @@ return buffer;
const char * DateToStrCookie(const PT::Date & d)
const char * DateToStrCookie(const pt::Date & d)
{
return DateToStrCookie(d.year, d.month, d.day, d.hour, d.min, d.sec);
}
@@ -468,7 +469,7 @@ const char * DateToStrCookie(const PT::Date & d)
const char * DateToStrCookie(time_t t)
{
PT::Date date = t;
pt::Date date = t;
return DateToStrCookie(date);
}
@@ -493,9 +494,9 @@ return buffer;
PT::WTextStream IPToStr(unsigned int ip)
pt::WTextStream IPToStr(unsigned int ip)
{
PT::WTextStream buf;
pt::WTextStream buf;
for(int i=0 ; i<4 ; ++i, ip >>= 8)
{
@@ -509,7 +510,7 @@ return buf;
}
PT::WTextStream IPToStr(int ip)
pt::WTextStream IPToStr(int ip)
{
return IPToStr(static_cast<unsigned int>(ip));
}
@@ -819,8 +820,12 @@ return correct;
bool ValidateEmail(const wchar_t * email)
{
int at = 0; // how many '@'
int dots_after_at = 0; // how many dots in the domain part
int at = 0; // how many '@'
int dots_after_at = 0; // how many dots in the domain part
const size_t address_max_length = 64; // the max length before a '@'
const size_t domain_max_length = 255; // the max length after a '@'
size_t address_length = 0;
size_t domain_length = 0;
for(size_t i=0 ; email[i] != 0 ; ++i)
{
@@ -828,16 +833,22 @@ bool ValidateEmail(const wchar_t * email)
return false;
if( email[i] == '@' )
{
++at;
}
else
{
if( at == 0 )
address_length += 1;
else
domain_length += 1;
if( email[i] == '.' && at > 0 )
++dots_after_at;
if( email[i] == '.' && at > 0 )
++dots_after_at;
}
}
if( at != 1 || dots_after_at == 0 )
return false;
return true;
return at == 1 && dots_after_at > 0 && address_length <= address_max_length && domain_length <= domain_max_length;
}
@@ -854,7 +865,7 @@ bool IsFile(const wchar_t * file)
struct stat sb;
char file_name[WINIX_OS_PATH_SIZE];
if( !WideToUTF8(file, file_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(file, (char*)file_name, WINIX_OS_PATH_SIZE) )
return false;
return (stat(file_name, &sb) == 0);
@@ -876,7 +887,7 @@ char dir_name[WINIX_OS_PATH_SIZE];
if( !IsFile(dir) )
{
if( !WideToUTF8(dir, dir_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(dir, (char*)dir_name, WINIX_OS_PATH_SIZE) )
return false;
if( mkdir(dir_name, 0777) < 0 )
@@ -952,7 +963,7 @@ struct group * result;
char group_name[WINIX_OS_USERNAME_SIZE];
char buffer[512];
if( !WideToUTF8(name, group_name, WINIX_OS_USERNAME_SIZE) )
if( !pt::wide_to_utf8(name, (char*)group_name, WINIX_OS_USERNAME_SIZE) )
return -1;
if( getgrnam_r(group_name, &gr, buffer, sizeof(buffer)/sizeof(char), &result) != 0 )
@@ -988,7 +999,7 @@ bool SetPriv(const wchar_t * name, int priv, int group)
{
char file_name[WINIX_OS_PATH_SIZE];
if( !WideToUTF8(name, file_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(name, (char*)file_name, WINIX_OS_PATH_SIZE) )
return false;
if( chmod(file_name, priv) < 0 )
@@ -1046,10 +1057,10 @@ char src_name[WINIX_OS_PATH_SIZE];
char dst_name[WINIX_OS_PATH_SIZE];
FILE * in, * out;
if( !WideToUTF8(src, src_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(src, (char*)src_name, WINIX_OS_PATH_SIZE) )
return false;
if( !WideToUTF8(dst, dst_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(dst, (char*)dst_name, WINIX_OS_PATH_SIZE) )
return false;
in = fopen(src_name, "rb");
@@ -1091,7 +1102,7 @@ bool RemoveFile(const wchar_t * file)
{
char file_name[WINIX_OS_PATH_SIZE];
if( !WideToUTF8(file, file_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(file, (char*)file_name, WINIX_OS_PATH_SIZE) )
return false;
return unlink(file_name) == 0;
@@ -1110,10 +1121,10 @@ bool RenameFile(const wchar_t * from, const wchar_t * to)
char from_name[WINIX_OS_PATH_SIZE];
char to_name[WINIX_OS_PATH_SIZE];
if( !WideToUTF8(from, from_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(from, (char*)from_name, WINIX_OS_PATH_SIZE) )
return false;
if( !WideToUTF8(to, to_name, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(to, (char*)to_name, WINIX_OS_PATH_SIZE) )
return false;
return rename(from_name, to_name) == 0;
@@ -1137,7 +1148,7 @@ std::ifstream get_file_content;
if( clear_content )
content.clear();
if( !WideToUTF8(file_path, file, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(file_path, (char*)file, WINIX_OS_PATH_SIZE) )
return false;
get_file_content.open(file, std::ios_base::in | std::ios_base::binary);
@@ -1148,7 +1159,7 @@ std::ifstream get_file_content;
/*
* we don't report any errors when converting from UTF8 to wide characters here
*/
PT::UTF8ToWide(get_file_content, content);
pt::utf8_to_wide(get_file_content, content);
get_file_content.close();
return true;
@@ -1161,30 +1172,126 @@ bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool cl
}
// if there is not an extension it returns a pointer to the last '\0' character
bool GetUTF8File(const wchar_t * file_path, pt::WTextStream & content, bool clear_content)
{
char file[WINIX_OS_PATH_SIZE];
std::ifstream get_file_content;
if( clear_content )
content.clear();
if( !pt::wide_to_utf8(file_path, (char*)file, WINIX_OS_PATH_SIZE) )
return false;
get_file_content.open(file, std::ios_base::in | std::ios_base::binary);
if( !get_file_content )
return false;
/*
* we don't report any errors when converting from UTF8 to wide characters here
*/
pt::utf8_to_wide(get_file_content, content);
get_file_content.close();
return true;
}
bool GetUTF8File(const std::wstring & file_path, pt::WTextStream & content, bool clear_content)
{
return GetUTF8File(file_path.c_str(), content, clear_content);
}
bool GetBinaryFile(const wchar_t * file_path, BinaryPage & content, bool clear_content)
{
char file[WINIX_OS_PATH_SIZE];
char buffer[4096];
size_t buffer_len = sizeof(buffer) / sizeof(char);
std::ifstream get_file_content;
if( clear_content )
content.clear();
if( !pt::wide_to_utf8(file_path, (char*)file, WINIX_OS_PATH_SIZE) )
return false;
get_file_content.open(file, std::ios_base::in | std::ios_base::binary);
if( !get_file_content )
return false;
do
{
get_file_content.read(buffer, buffer_len);
content.write(buffer, get_file_content.gcount());
}
while( !get_file_content.eof() && get_file_content.good() );
get_file_content.close();
return true;
}
bool GetBinaryFile(const std::wstring & file_path, BinaryPage & content, bool clear_content)
{
return GetBinaryFile(file_path.c_str(), content, clear_content);
}
// if there is no an extension it returns a pointer to the last '\0' character
const wchar_t * GetFileExt(const wchar_t * name)
{
size_t i, ilast;
const wchar_t * dot_ptr = nullptr;
// looking for the end of the name
for(i=0 ; name[i] != 0 ; ++i);
for( ; *name != 0 ; ++name)
{
if( *name == '.' )
{
dot_ptr = name;
}
}
if( i == 0 )
return name; // ops, the name is empty
return dot_ptr ? dot_ptr + 1 : name;
}
// remember the end of the string
ilast = i;
// looking for the last dot
for(--i ; i>0 && name[i] != '.' ; --i);
void PrepareNewFileName(const wchar_t * src, const wchar_t * postfix, std::wstring & res, bool clear_res)
{
bool has_ext = false;
const wchar_t * ext = GetFileExt(src);
if( name[i] != '.' )
return name + ilast; // ops, there is not a dot
if( clear_res )
res.clear();
// the extensions starts from i+1
// and can be empty (if the last character is a dot)
size_t len = ext - src;
return name + i + 1;
if( len > 0 )
{
if( *(ext-1) == '.' )
{
len -= 1;
has_ext = true;
}
}
res.append(src, len);
res.append(postfix);
if( has_ext )
res.append(1, '.');
res.append(ext);
}
void PrepareNewFileName(const std::wstring & src, const std::wstring & postfix, std::wstring & res, bool clear_res)
{
return PrepareNewFileName(src.c_str(), postfix.c_str(), res, clear_res);
}
@@ -1194,31 +1301,31 @@ int SelectFileType(const wchar_t * file_name)
// as an image we're using only those types which can be rendered
// by a web browser
if( PT::EqualNoCase(ext, L"jpg") ||
PT::EqualNoCase(ext, L"jpeg") ||
PT::EqualNoCase(ext, L"jpe") ||
PT::EqualNoCase(ext, L"pic") ||
PT::EqualNoCase(ext, L"tga") ||
PT::EqualNoCase(ext, L"gif") ||
PT::EqualNoCase(ext, L"bmp") ||
PT::EqualNoCase(ext, L"png") )
if( pt::is_equal_nc(ext, L"jpg") ||
pt::is_equal_nc(ext, L"jpeg") ||
pt::is_equal_nc(ext, L"jpe") ||
pt::is_equal_nc(ext, L"pic") ||
pt::is_equal_nc(ext, L"tga") ||
pt::is_equal_nc(ext, L"gif") ||
pt::is_equal_nc(ext, L"bmp") ||
pt::is_equal_nc(ext, L"png") )
return WINIX_ITEM_FILETYPE_IMAGE;
if( PT::EqualNoCase(ext, L"pdf") ||
PT::EqualNoCase(ext, L"doc") ||
PT::EqualNoCase(ext, L"xls") ||
PT::EqualNoCase(ext, L"txt") ||
PT::EqualNoCase(ext, L"ods") ||
PT::EqualNoCase(ext, L"odt") )
if( pt::is_equal_nc(ext, L"pdf") ||
pt::is_equal_nc(ext, L"doc") ||
pt::is_equal_nc(ext, L"xls") ||
pt::is_equal_nc(ext, L"txt") ||
pt::is_equal_nc(ext, L"ods") ||
pt::is_equal_nc(ext, L"odt") )
return WINIX_ITEM_FILETYPE_DOCUMENT;
if( PT::EqualNoCase(ext, L"avi") ||
PT::EqualNoCase(ext, L"mp4") ||
PT::EqualNoCase(ext, L"flv") ||
PT::EqualNoCase(ext, L"mpg") ||
PT::EqualNoCase(ext, L"mpeg") ||
PT::EqualNoCase(ext, L"mkv") ||
PT::EqualNoCase(ext, L"wmv") )
if( pt::is_equal_nc(ext, L"avi") ||
pt::is_equal_nc(ext, L"mp4") ||
pt::is_equal_nc(ext, L"flv") ||
pt::is_equal_nc(ext, L"mpg") ||
pt::is_equal_nc(ext, L"mpeg") ||
pt::is_equal_nc(ext, L"mkv") ||
pt::is_equal_nc(ext, L"wmv") )
return WINIX_ITEM_FILETYPE_VIDEO;
return WINIX_ITEM_FILETYPE_UNKNOWN;
@@ -1239,8 +1346,15 @@ void UrlEncode(const char * in, std::string & out, bool clear_out)
if( clear_out )
out.clear();
pt::TextStream stream;
for(size_t i=0 ; in[i] != 0 ; ++i)
UrlEncode(in[i], out, false);
{
UrlEncode(in[i], stream, true);
for(size_t s=0 ; s < stream.size() ; ++s)
out += stream[s];
}
}
@@ -1250,39 +1364,44 @@ void UrlEncode(const std::string & in, std::string & out, bool clear_out)
}
void UrlEncode(const wchar_t * in, std::string & out, bool clear_out)
{
static std::string ain;
PT::WideToUTF8(in, ain);
if( clear_out )
out.clear();
for(size_t i=0 ; i < ain.size() ; ++i)
UrlEncode(ain[i], out, false);
}
//void UrlEncode(const wchar_t * in, std::string & out, bool clear_out)
//{
// if( clear_out )
// out.clear();
//
// pt::TextStream stream;
//
// for(size_t i=0 ; in[i] != 0 ; ++i)
// {
// UrlEncode(in[i], stream, true);
//
// for(size_t s=0 ; s < stream.size() ++i)
// out += stream[s];
// }
//}
void UrlEncode(const std::wstring & in, std::string & out, bool clear_out)
{
UrlEncode(in.c_str(), out, clear_out);
}
//void UrlEncode(const std::wstring & in, std::string & out, bool clear_out)
//{
// UrlEncode(in.c_str(), out, clear_out);
//}
void UrlEncode(const wchar_t * in, std::wstring & out, bool clear_out)
{
static std::string ain;
PT::WideToUTF8(in, ain);
if( clear_out )
out.clear();
for(size_t i=0 ; i < ain.size() ; ++i)
UrlEncode(ain[i], out, false);
pt::WTextStream stream;
for(size_t i=0 ; in[i] != 0 ; ++i)
{
UrlEncode(in[i], stream, true);
for(size_t s=0 ; s < stream.size() ; ++s)
out += stream[s];
}
}
@@ -1293,6 +1412,27 @@ void UrlEncode(const std::wstring & in, std::wstring & out, bool clear_out)
void UrlEncode(const pt::TextStream & in, pt::TextStream & out, bool clear_out)
{
if( clear_out )
out.clear();
for(size_t i=0 ; i < in.size() ; ++i)
UrlEncode(in.get_char(i), out, false);
}
void UrlEncode(const pt::WTextStream & in, pt::WTextStream & out, bool clear_out)
{
if( clear_out )
out.clear();
for(size_t i=0 ; i < in.size() ; ++i)
UrlEncode(in.get_wchar(i), out, false);
}
bool UrlDecodeFromHex(int c, int & out)
{
@@ -1347,7 +1487,7 @@ int c1, c2;
url_utf8[index] = 0;
return PT::UTF8ToWide(url_utf8, out, false);
return pt::utf8_to_wide(url_utf8, out, false);
}
@@ -1364,7 +1504,7 @@ using namespace misc_private;
tmp_qencode.clear();
QEncode(in, tmp_qencode);
tmp_qencode.to_string(out, clear);
tmp_qencode.to_str(out, clear);
tmp_qencode.clear();
}
@@ -1391,26 +1531,211 @@ void RemovePostFileTmp(PostFileTab & post_file_tab)
}
bool WideToUTF8(const wchar_t * wide_string, char * utf8, size_t utf8_size)
void JSONescapeStream(const pt::WTextStream & in, pt::WTextStream & out)
{
bool res = PT::WideToUTF8(wide_string, utf8, utf8_size);
pt::WTextStream::const_iterator i = in.begin();
if( !res )
for( ; i != in.end() ; ++i)
{
/*
* either the 'utf8' buffer is too small or there was an error when converting
*/
//log << log1 << "Misc: I cannot convert from a wide string to an UTF-8 string, original string was: "
// << wide_string << logend;
JSONescape(*i, out);
}
return res;
}
bool WideToUTF8(const std::wstring & wide_string, char * utf8, size_t utf8_size)
void JSONescapeStream(const std::wstring & in, pt::WTextStream & out)
{
return WideToUTF8(wide_string.c_str(), utf8, utf8_size);
std::wstring::const_iterator i = in.begin();
for( ; i != in.end() ; ++i)
{
JSONescape(*i, out);
}
}
void calculate_timespec_diff(timespec & start, timespec & stop, timespec & result)
{
/*
* copied from macro timespecsub(tsp, usp, vsp) which is defined in sys/time.h
*/
result.tv_sec = stop.tv_sec - start.tv_sec;
result.tv_nsec = stop.tv_nsec - start.tv_nsec;
if( result.tv_nsec < 0 )
{
result.tv_sec--;
result.tv_nsec += 1000000000L;
}
}
double timespec_to_double(timespec & val)
{
double val_double = val.tv_sec + val.tv_nsec / 1000000000.0;
return val_double;
}
void timespec_to_stream(timespec & val, pt::Stream & stream)
{
char buf[50];
double val_double = timespec_to_double(val);
sprintf(buf, "%f", val_double);
SetNonZeroDigitsAfterComma(buf, 2);
stream << buf;
}
void timespec_to_stream_with_unit(timespec & val, pt::Stream & stream)
{
char buf[50];
bool is_ms = false;
double val_double = timespec_to_double(val);
if( val_double < 0.1 )
{
is_ms = true;
val_double = val_double * 1000;
}
sprintf(buf, "%f", val_double);
SetNonZeroDigitsAfterComma(buf, 2);
stream << buf;
if( is_ms )
{
stream << "ms";
}
else
{
stream << "s";
}
}
void slice_by(const std::wstring & str, wchar_t c, std::vector<std::wstring> & out)
{
std::wstring tmp;
for(size_t i = 0 ; i < str.size() ; ++i)
{
if( str[i] == c )
{
if( !tmp.empty() )
{
out.push_back(tmp);
tmp.clear();
}
}
else
{
tmp += str[i];
}
}
if( !tmp.empty() )
{
out.push_back(tmp);
}
}
bool is_in_list(const std::wstring & item, const std::vector<std::wstring> & list)
{
return is_in_list_generic(item, list);
}
bool is_in_list(const std::wstring & item, const std::list<std::wstring> & list)
{
return is_in_list_generic(item, list);
}
bool is_in_list(const std::wstring & item, const std::set<std::wstring> & list)
{
return is_in_list_generic(item, list);
}
void cookie_same_site_to_stream(CookieSameSite same_site, pt::Stream & stream)
{
switch(same_site)
{
case CookieSameSite::samesite_strict:
stream << L"Strict";
break;
case CookieSameSite::samesite_lax:
stream << L"Lax";
break;
case CookieSameSite::samesite_none:
stream << L"None";
break;
default:
break;
}
}
void prepare_cookie_string(
pt::Stream & cookie,
const std::wstring * value_string,
const pt::Stream * value_stream,
pt::Date * expires,
const std::wstring * path,
const std::wstring * domain,
CookieSameSite cookie_same_site,
bool http_only,
bool secure)
{
if( value_string )
cookie << *value_string;
if( value_stream )
cookie << *value_stream;
if( cookie.empty() )
cookie << L"\"\""; // cookie empty value
if( expires )
cookie << L"; expires=" << DateToStrCookie(*expires) << L" GMT";
if( path && !path->empty() )
{
cookie << L"; path=" << *path;
}
if( domain && !domain->empty() )
cookie << L"; domain=" << *domain;
if( cookie_same_site != CookieSameSite::samesite_notset )
{
cookie << L"; SameSite=";
cookie_same_site_to_stream(cookie_same_site, cookie);
}
if( http_only )
cookie << L"; HttpOnly";
/*
don't use '; secure' flag if you are using both sites (with SSL
and without SSL) -- with secure flag the cookie is sent only through
SSL and if you accidentally open a new window without SSL (http://)
then winix will create a new session for you and the previous session (https://)
will be lost (the session cookie will be overwritten in the client's browser)
*/
if( secure )
cookie << L"; Secure";
}
+179 -79
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,10 +36,11 @@
#define headerfile_winix_core_misc
#include <string>
#include <vector>
#include <set>
#include <sstream>
#include <ctime>
#include <cstdio>
#include "item.h"
#include "requesttypes.h"
#include "date/date.h"
#include "textstream/textstream.h"
@@ -78,6 +79,7 @@ double Tod(const wchar_t * str);
// if the buffer is too small it will be terminated at the beginning (empty string)
// and the function returns false
// IMPROVEME now we can use Toa from Pikotools
template<class CharType>
bool Toa(unsigned long value, CharType * buffer, size_t buf_len, int base = 10)
{
@@ -238,13 +240,13 @@ void CorrectUrlOnlyAllowedChar(std::wstring & url);
const wchar_t * DateToStr(int year, int month, int day);
const wchar_t * DateToStr(int year, int month, int day, int hour, int min, int sec);
const wchar_t * DateToStr(const PT::Date & d);
const wchar_t * DateToStr(const pt::Date & d);
const wchar_t * DateToStr(time_t t);
const wchar_t * DateToStrWithoutHours(const PT::Date & d);
const wchar_t * DateToStrWithoutHours(const pt::Date & d);
const wchar_t * DateToStrWithoutHours(time_t t);
const char * DateToStrCookie(int year, int month, int day, int hour, int min, int sec);
const char * DateToStrCookie(const PT::Date & d);
const char * DateToStrCookie(const pt::Date & d);
const char * DateToStrCookie(time_t t);
// depracated
@@ -253,8 +255,8 @@ const wchar_t * IpToStr(unsigned int ip_);
// in a new code we can use WTextStream in such a way
// DateToStr() etc can use it too
PT::WTextStream IPToStr(unsigned int ip);
PT::WTextStream IPToStr(int ip);
pt::WTextStream IPToStr(unsigned int ip);
pt::WTextStream IPToStr(int ip);
@@ -420,7 +422,7 @@ size_t i = 0;
while( i < buf.size() )
{
if( PT::IsSubString(look_for.c_str(), buf.c_str() + i) )
if( pt::is_substr(look_for.c_str(), buf.c_str() + i) )
{
buf.erase(i, look_for.size());
buf.insert(i, replace);
@@ -662,8 +664,19 @@ bool RenameFile(const std::wstring & from, const std::wstring & to);
bool GetUTF8File(const wchar_t * file_path, std::wstring & content, bool clear_content = true);
bool GetUTF8File(const std::wstring & file_path, std::wstring & content, bool clear_content = true);
bool GetUTF8File(const wchar_t * file_path, pt::WTextStream & content, bool clear_content = true);
bool GetUTF8File(const std::wstring & file_path, pt::WTextStream & content, bool clear_content = true);
bool GetBinaryFile(const wchar_t * file_path, BinaryPage & content, bool clear_content = true);
bool GetBinaryFile(const std::wstring & file_path, BinaryPage & content, bool clear_content = true);
const wchar_t * GetFileExt(const wchar_t * name);
void PrepareNewFileName(const wchar_t * src, const wchar_t * postfix, std::wstring & res, bool clear_res = true);
void PrepareNewFileName(const std::wstring & src, const std::wstring & postfix, std::wstring & res, bool clear_res = true);
int SelectFileType(const wchar_t * file_name);
int SelectFileType(const std::wstring & file_name);
@@ -673,14 +686,11 @@ int SelectFileType(const std::wstring & file_name);
// thread safe
template<typename char_type, size_t stack_size, size_t heap_block_size>
void UrlEncode(char c,
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear_out = true)
template<typename StreamType>
void UrlEncode(char c, StreamType & out, bool clear_out = true)
{
char buffer[10];
size_t buflen = sizeof(buffer)/sizeof(char);
char buffer[10];
size_t buflen = sizeof(buffer)/sizeof(char);
if( clear_out )
out.clear();
@@ -705,11 +715,33 @@ size_t buflen = sizeof(buffer)/sizeof(char);
}
// thread safe
template<typename char_type, size_t stack_size, size_t heap_block_size>
void UrlEncode(const char * in,
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear_out = true)
template<typename StreamType>
void UrlEncode(wchar_t c, StreamType & out, bool clear_out = true)
{
char buffer[10];
size_t buflen = sizeof(buffer)/sizeof(char);
if( clear_out )
out.clear();
// this conversion is not using surrogate pairs if wchar_t is 2 bytes long
size_t utf8_len = pt::int_to_utf8(static_cast<int>(c), buffer, buflen);
if( utf8_len > 0 )
{
for(size_t i=0 ; i < utf8_len ; ++i)
{
UrlEncode(buffer[i], out, false);
}
}
}
template<typename StreamType>
void UrlEncode(const char * in, StreamType & out, bool clear_out = true)
{
if( clear_out )
out.clear();
@@ -719,67 +751,44 @@ void UrlEncode(const char * in,
}
// thread safe
template<typename char_type, size_t stack_size, size_t heap_block_size>
void UrlEncode(const std::string & in,
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear_out = true)
template<typename StreamType>
void UrlEncode(const std::string & in, StreamType & out, bool clear_out = true)
{
UrlEncode(in.c_str(), out, clear_out);
}
// not thread safe
template<typename char_type, size_t stack_size, size_t heap_block_size>
void UrlEncode(const wchar_t * in,
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear_out = true)
template<typename StreamType>
void UrlEncode(const wchar_t * in, StreamType & out, bool clear_out = true)
{
static std::string ain;
PT::WideToUTF8(in, ain);
if( clear_out )
out.clear();
for(size_t i=0 ; i < ain.size() ; ++i)
UrlEncode(ain[i], out, false);
for(size_t i=0 ; in[i] != 0 ; ++i)
UrlEncode(in[i], out, false);
}
// not thread safe
template<typename char_type, size_t stack_size, size_t heap_block_size>
void UrlEncode(const std::wstring & in,
PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear_out = true)
template<typename StreamType>
void UrlEncode(const std::wstring & in, StreamType & out, bool clear_out = true)
{
UrlEncode(in.c_str(), out, clear_out);
}
// no thread safe
template<class StringType>
void UrlEncode(char c, StringType & out, bool clear_out = true)
{
static PT::TextStream tmp;
UrlEncode(c, tmp);
tmp.to_string(out, clear_out);
}
// !! IMROVE ME we need some UrlEncode methods with PT::TextBuffer instead of std::string
void UrlEncode(const char * in, std::string & out, bool clear_out = true);
void UrlEncode(const std::string & in, std::string & out, bool clear_out = true);
void UrlEncode(const wchar_t * in, std::string & out, bool clear_out = true);
void UrlEncode(const std::wstring & in, std::string & out, bool clear_out = true);
//void UrlEncode(const wchar_t * in, std::string & out, bool clear_out = true);
//void UrlEncode(const std::wstring & in, std::string & out, bool clear_out = true);
void UrlEncode(const wchar_t * in, std::wstring & out, bool clear_out = true);
void UrlEncode(const std::wstring & in, std::wstring & out, bool clear_out = true);
void UrlEncode(const pt::TextStream & in, pt::TextStream & out, bool clear_out = true);
void UrlEncode(const pt::WTextStream & in, pt::WTextStream & out, bool clear_out = true);
/*
@@ -797,7 +806,7 @@ bool UrlDecode(const std::string & url, std::wstring & out, bool clear_out = tr
template<typename char_type, size_t stack_size, size_t heap_block_size>
void QEncodeAddChar(char_type c, PT::TextStreamBase<char_type, stack_size, heap_block_size> & out)
void QEncodeAddChar(char_type c, pt::TextStreamBase<char_type, stack_size, heap_block_size> & out)
{
if( (c>='A' && c<='Z') ||
(c>='a' && c<='z') ||
@@ -812,7 +821,7 @@ void QEncodeAddChar(char_type c, PT::TextStreamBase<char_type, stack_size, heap_
size_t len1 = sizeof(buf1) / sizeof(char);
size_t len2 = sizeof(buf2) / sizeof(char);
size_t len = PT::IntToUTF8(int(c), buf1, len1);
size_t len = pt::int_to_utf8(int(c), buf1, len1);
for(size_t i=0 ; i<len ; ++i)
{
@@ -845,7 +854,7 @@ void QEncodeAddChar(char_type c, PT::TextStreamBase<char_type, stack_size, heap_
charset, encoding, encoded-text, and delimiters."
*/
template<typename char_type, size_t stack_size, size_t heap_block_size>
void QEncode(const wchar_t * in, PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
void QEncode(const wchar_t * in, pt::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear = true)
{
if( clear )
@@ -861,7 +870,7 @@ void QEncode(const wchar_t * in, PT::TextStreamBase<char_type, stack_size, heap_
template<typename char_type, size_t stack_size, size_t heap_block_size>
void QEncode(const std::wstring & in, PT::TextStreamBase<char_type, stack_size, heap_block_size> & out,
void QEncode(const std::wstring & in, pt::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear = true)
{
if( clear )
@@ -877,6 +886,7 @@ void QEncode(const std::wstring & in, PT::TextStreamBase<char_type, stack_size,
}
// no thread safe
void QEncode(const std::wstring & in, std::string & out, bool clear = true);
@@ -944,20 +954,11 @@ void SetMinMax(IntType & val, IntType min_val, IntType max_val)
}
template<class Stream, class StringType>
void JSONescape(Stream & out, const StringType & str)
template<class Stream>
void JSONescape(wchar_t c, Stream & out)
{
// !! IMPROVE ME (optimizing)
// it is better to not write one by one character
// but use write method insted
for(size_t i=0 ; i<str.size() ; ++i)
switch( c )
{
switch(str[i])
{
case 0: out << '\\'; out << '0'; break;
case '\r': out << '\\'; out << 'r'; break;
case '\n': out << '\\'; out << 'n'; break;
@@ -968,21 +969,120 @@ void JSONescape(Stream & out, const StringType & str)
//case '/': out << '\\'; out << '/'; break; // slash doesn't have to be escaped
case '"': out << '\\'; out << '\"'; break;
default:
out << str[i];
out << c;
}
}
template<class StringType, class Stream>
void JSONescape(const StringType & str, Stream & out)
{
for(size_t i=0 ; i < str.size() ; ++i)
{
if constexpr(sizeof(char) == sizeof(typename StringType::value_type))
{
JSONescape(static_cast<wchar_t>(static_cast<unsigned char>(str[i])), out);
}
else
{
JSONescape(str[i], out);
}
}
}
void JSONescapeStream(const pt::WTextStream & in, pt::WTextStream & out);
void JSONescapeStream(const std::wstring & in, pt::WTextStream & out);
/*
* converting from a wide string to an UTF-8 string
* and puts a log if the conversion fails
* calculate diff between start and stop timespec
*
* if start is greater than stop then the result is negative:
* - result.tv_sec is less than zero
* - result.tv_nsec is greater than or equal to zero (only if start.tv_nsec and stop.tv_nsec are correct values from zero to 1000000000L)
*
* 'double' value can be calculated in this way:
* double res = result.tv_sec + result.tv_nsec / 1000000000.0;
*
* it uses PT::WideToUTF8()
*/
bool WideToUTF8(const wchar_t * wide_string, char * utf8, size_t utf8_size);
bool WideToUTF8(const std::wstring & wide_string, char * utf8, size_t utf8_size);
void calculate_timespec_diff(timespec & start, timespec & stop, timespec & result);
/*
* converts timespec to double in the following way:
* double val_double = val.tv_sec + val.tv_nsec / 1000000000.0;
*
* val.tv_sec can be negative (less than zero) but tv_nsec should be in the range [0, 1000000000.0)
*
*/
double timespec_to_double(timespec & val);
void timespec_to_stream(timespec & val, pt::Stream & stream);
void timespec_to_stream_with_unit(timespec & val, pt::Stream & stream);
void slice_by(const std::wstring & str, wchar_t c, std::vector<std::wstring> & out);
bool is_in_list(const std::wstring & item, const std::vector<std::wstring> & list);
bool is_in_list(const std::wstring & item, const std::list<std::wstring> & list);
bool is_in_list(const std::wstring & item, const std::set<std::wstring> & list);
template<typename ContainerType>
bool is_in_list_generic(const std::wstring & item, const ContainerType & list)
{
for(const std::wstring & str : list)
{
if( str == item )
{
return true;
}
}
return false;
}
void cookie_same_site_to_stream(CookieSameSite same_site, pt::Stream & stream);
void prepare_cookie_string(
pt::Stream & out_stream,
const std::wstring * value_string = nullptr,
const pt::Stream * value_stream = nullptr,
pt::Date * expires = nullptr,
const std::wstring * path = nullptr,
const std::wstring * domain = nullptr,
CookieSameSite cookie_same_site = CookieSameSite::samesite_notset,
bool http_only = false,
bool secure = false);
template<typename char_type, size_t stack_size, size_t heap_block_size>
void q_encode(
const pt::TextStreamBase<char_type, stack_size, heap_block_size> & in,
pt::TextStreamBase<char_type, stack_size, heap_block_size> & out,
bool clear = true)
{
if( clear )
out.clear();
out << "=?UTF-8?Q?";
// do not use QEncode(in.c_str()) as 'in' can have a null-terminating byte
typename pt::TextStreamBase<char_type, stack_size, heap_block_size>::const_iterator i = in.begin();
for( ; i != in.end() ; ++i)
QEncodeAddChar(*i, out);
out << "?=";
}
+26 -2
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2014, Tomasz Sowa
* Copyright (c) 2009-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,14 +43,38 @@ namespace Winix
Mount::Mount()
{
Clear();
}
Mount::Mount(const Mount & m)
{
operator=(m);
}
Mount & Mount::operator=(const Mount & m)
{
dir_id = m.dir_id;
type = m.type;
fs = m.fs;
param = m.param;
return *this;
}
void Mount::Clear()
{
dir_id = -1;
type = -1;
fs = -1;
ClearParams();
}
void Mount::ClearParams()
{
size_t i;
+5 -1
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2014, Tomasz Sowa
* Copyright (c) 2009-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,10 @@ public:
Mount();
Mount(const Mount & m);
Mount & operator=(const Mount & m);
void Clear();
void ClearParams();
bool IsPar(int code);
+2 -1
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include "mountparser.h"
#include "log.h"
#include "misc.h"
#include "dirs.h"
namespace Winix
+5 -6
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,20 +40,19 @@
#include <vector>
#include <stdlib.h>
#include <limits.h>
#include "mount.h"
#include "item.h"
#include "dirs.h"
#include "winixmodel.h"
#include "models/item.h"
#include "winixmodeldeprecated.h"
namespace Winix
{
class Dirs;
class MountParser : public WinixModel
class MountParser : public WinixModelDeprecated
{
public:
+26 -35
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2018, Tomasz Sowa
* Copyright (c) 2009-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,7 @@
#include "mounts.h"
#include "request.h"
#include "log.h"
#include "db/db.h"
#include "cur.h"
#include "dirs.h"
@@ -49,6 +48,7 @@ Mounts::Mounts()
{
pmount = &empty_mount;
skip_static = false;
dirs = nullptr;
}
@@ -99,7 +99,7 @@ void Mounts::CreateMounts()
CreateMountFs();
CreateMountPar();
plugin->Call((Session*)0, WINIX_ADD_MOUNTS);
plugin->Call(WINIX_ADD_MOUNTS);
empty_mount.param.resize(mount_par_tab.size());
empty_mount.ClearParams();
@@ -113,18 +113,6 @@ void Mounts::SetDirs(Dirs * pdirs)
}
void Mounts::SetDb(Db * pdb)
{
db = pdb;
}
void Mounts::SetCur(Cur * pcur)
{
cur = pcur;
}
int Mounts::AddMountType(const wchar_t * type)
{
mount_type_tab.push_back(type);
@@ -221,14 +209,17 @@ void Mounts::ReadMounts(const std::wstring & mounts)
mount_parser.Parse(mounts, mount_tab);
CalcCurMount();
plugin->Call((Session*)0, WINIX_FSTAB_CHANGED);
// IMPROVE ME
// cur->mount is pointing to the empty mount (it is set in functions.cpp in CheckSpecialFile method)
// may would be better to call WINIX_FSTAB_CHANGED after the cur->mount is set?
// some plugins are using 'cur' object
plugin->Call(WINIX_FSTAB_CHANGED);
}
// reading from /etc/fstab
Error Mounts::ReadMounts()
void Mounts::ReadMounts()
{
static std::wstring file = L"fstab";
@@ -237,27 +228,27 @@ Error Mounts::ReadMounts()
if( !etc )
{
log << log1 << "M: there is no /etc directory" << logend;
return WINIX_ERR_NO_ITEM;
return;
}
Item fstab;
Error err = db->GetItem(etc->id, file, fstab);
morm::Finder<Item> finder(model_connector);
Item fstab = finder.select().where().eq(L"parent_id", etc->id).eq(L"url", file).get();
if( err == WINIX_ERR_NO_ITEM )
// Error err = db->GetItem(etc->id, file, fstab);
if( !fstab.found() )
{
log << log1 << "M: there is no /etc/fstab file" << logend;
return err;
return;
}
if( err != WINIX_ERR_OK )
{
log << log1 << "M: cannot read /etc/fstab" << logend;
return err;
}
// if( err != WINIX_ERR_OK )
// {
// log << log1 << "M: cannot read /etc/fstab" << logend;
// return err;
// }
ReadMounts(fstab.content);
return WINIX_ERR_OK;
ReadMounts(fstab.item_content.content_raw);
}
@@ -287,7 +278,7 @@ void Mounts::MountCmsForRoot()
Mount * Mounts::CalcCurMount()
Mount * Mounts::CalcCurMount(Request * request)
{
std::vector<Item*>::reverse_iterator i;
@@ -295,10 +286,10 @@ std::vector<Item*>::reverse_iterator i;
// when the program starts (when the dir_tab is empty()
// we don't want to call MountCmsForRoot()
if( cur->request->dir_tab.empty() )
if( request->dir_tab.empty() )
return pmount;
for(i = cur->request->dir_tab.rbegin() ; i!=cur->request->dir_tab.rend() ; ++i)
for(i = request->dir_tab.rbegin() ; i!=request->dir_tab.rend() ; ++i)
{
std::map<long, Mount>::iterator m = mount_tab.find( (*i)->id );
+7 -15
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2018, Tomasz Sowa
* Copyright (c) 2009-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,21 +41,17 @@
#include <string>
#include <vector>
#include "mount.h"
#include "error.h"
#include "dirs.h"
#include "db/db.h"
#include "request.h"
#include "mountparser.h"
#include "winixmodel.h"
#include "winixmodeldeprecated.h"
namespace Winix
{
class Dirs;
class Request;
class Mounts : public WinixModel
class Mounts : public WinixModelDeprecated
{
public:
@@ -114,8 +110,6 @@ public:
int MountParLang() { return mount_par_lang; }
void SetDirs(Dirs * pdirs);
void SetDb(Db * pdb);
void SetCur(Cur * pcur);
// dir_id, mount_point
typedef std::map<long, Mount> MountTab;
@@ -124,9 +118,9 @@ public:
void CreateMounts();
void ReadMounts(const std::wstring & mounts);
Error ReadMounts();
void ReadMounts();
Mount * CalcCurMount();
Mount * CalcCurMount(Request * request);
Mount * CalcMount(long dir_id);
// current mount point
@@ -144,9 +138,7 @@ public:
private:
Db * db;
Dirs * dirs;
Cur * cur;
bool skip_static;
+75 -173
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,44 +48,6 @@ namespace Winix
{
/*
*
* PluginInfo
*
*
*/
void PluginInfo::set_dependency_for(WinixBase * winix_base)
{
plugin->SetDependencyFor(winix_base);
}
void PluginInfo::set_dependency_for(WinixBase & winix_base)
{
set_dependency_for(&winix_base);
}
void PluginInfo::set_dependency_for(WinixModel * winix_model)
{
plugin->SetDependencyFor(winix_model);
}
void PluginInfo::set_dependency_for(WinixModel & winix_model)
{
set_dependency_for(&winix_model);
}
/*
*
* Plugin
*
*
*/
void Plugin::UnloadPlugins()
{
size_t i;
@@ -103,13 +65,14 @@ Plugin::Plugin()
{
current_plugin = -1;
db = nullptr;
cur = nullptr;
system = nullptr;
functions = nullptr;
templates = nullptr;
session_manager = nullptr;
winix_request = nullptr;
plugin = this;
}
@@ -119,29 +82,18 @@ Plugin::~Plugin()
}
void Plugin::SetDb(Db * pdb)
{
db = pdb;
}
//void Plugin::SetConfig(Config * pconfig)
//{
// config = pconfig;
//}
void Plugin::SetCur(Cur * pcur)
{
cur = pcur;
}
void Plugin::SetSystem(System * psystem)
{
system = psystem;
}
void Plugin::SetCur(Cur * cur)
{
this->cur = cur;
}
void Plugin::SetFunctions(Functions * pfunctions)
{
functions = pfunctions;
@@ -154,12 +106,6 @@ void Plugin::SetTemplates(Templates * ptemplates)
}
//void Plugin::SetSynchro(Synchro * psynchro)
//{
// synchro = psynchro;
//}
void Plugin::SetSessionManager(SessionManager * psession_manager)
{
session_manager = psession_manager;
@@ -189,45 +135,33 @@ void Plugin::Unlock()
bool Plugin::SetDependency(PluginInfo & info)
bool Plugin::SetDependencyForPluginInfo(morm::ModelConnector * pmodel_connector, Log * plog, Cur * pcur, PluginInfo & info)
{
// for safety we call a plugin function only when all our pointers are not null
bool res = (db && config && cur && system && functions && templates && synchro && session_manager && winix_request);
bool res = (pmodel_connector && plog && pcur && config && system && functions && templates && synchro && session_manager && winix_request);
if( !res )
{
Lock();
log << log1 << "Plugin: cannot call a function - some of the winix pointers are null" << logend;
Unlock();
}
info.db = db;
info.config = config;
info.cur = cur;
info.cur = pcur;
info.system = system;
info.functions = functions;
info.templates = templates;
info.synchro = synchro;
info.session_manager = session_manager;
info.plugin = this;
info.model_connector = pmodel_connector;;
info.log.SetDependency(&log);
info.log.set_log_buffer(plog->get_log_buffer());
info.log.set_file_log(plog->get_file_log());
return res;
return res;
}
void Plugin::SetDependencyFor(WinixBase * winix_base)
{
winix_base->set_dependency(winix_request);
}
void Plugin::SetDependencyFor(WinixModel * winix_model)
{
winix_model->set_dependency(winix_request);
}
void Plugin::LoadPlugins(const std::wstring & plugins_dir, const std::vector<std::wstring> & plugins)
{
@@ -256,8 +190,8 @@ void * Plugin::LoadInitFun(const wchar_t * filename, Fun1 & fun_init)
{
char file[WINIX_OS_PATH_SIZE];
if( !WideToUTF8(filename, file, WINIX_OS_PATH_SIZE) )
return 0;
if( !pt::wide_to_utf8(filename, (char*)file, WINIX_OS_PATH_SIZE) )
return nullptr;
void * p = dlopen(file, RTLD_NOW | RTLD_LOCAL);
@@ -265,7 +199,7 @@ char file[WINIX_OS_PATH_SIZE];
{
log << log1 << "Plugin: cannot load a plugin: \"" << filename << "\"" << logend;
log << log1 << "Plugin: dlerror: " << dlerror() << logend;
return 0;
return nullptr;
}
fun_init = (Fun1)dlsym(p, "Init");
@@ -276,14 +210,14 @@ char file[WINIX_OS_PATH_SIZE];
<< " (there is no Init() function)" << logend;
dlclose(p);
return 0;
return nullptr;
}
log << log2 << "Plugin: plugin loaded"
<< ", file: " << filename
<< ", index: " << plugins.size() << logend;
return p;
return p;
}
@@ -295,7 +229,7 @@ void * plugin_handle;
int old_current_plugin;
PluginInfo info;
if( !SetDependency(info) )
if( !SetDependencyForPluginInfo(model_connector, &log, cur, info) )
return;
if( !(plugin_handle = LoadInitFun(filename, fun_init)) )
@@ -306,6 +240,10 @@ PluginInfo info;
current_plugin = (int)plugins.size();
info.plugin_id = current_plugin;
/*
* WARNING:
* all pointers from Cur are null pointers here
*/
fun_init(info);
PluginsItem item;
@@ -353,27 +291,24 @@ bool Plugin::HasMessage(int message)
}
void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info)
void Plugin::Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, Slots::iterator & slot, PluginInfo & info)
{
if( !SetDependency(info) )
if( !SetDependencyForPluginInfo(model_connector, plog, cur, info) )
return;
current_plugin = slot->second.index;
info.plugin_id = current_plugin;
info.session = ses;
if( current_plugin != -1 && ses )
info.plugin_data_base = ses->plugin_data.Get(current_plugin);
if( current_plugin != -1 && cur->session && !cur->session->is_temporary_session() )
info.plugin_data_base = cur->session->plugin_data.Get(current_plugin);
else
info.plugin_data_base = 0;
info.plugin_data_base = nullptr;
if( !slot->second.is_running )
{
if( config->log_plugin_call )
{
Lock();
log << log1 << "Plugin: calling plugin id: " << slot->second.index << ", message: " << message << logend;
Unlock();
}
slot->second.is_running = true;
@@ -388,156 +323,123 @@ void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo
if( config->log_plugin_call )
{
Lock();
log << log1 << "Plugin: returning from plugin id: " << slot->second.index << ", message: " << message
<< ", result: " << (info.res? "true" : "false") << logend;
Unlock();
}
}
else
{
Lock();
log << log1 << "Plugin: id: " << slot->second.index
<< ", message: " << message
<< ", recurrences are not allowed" << logend;
Unlock();
}
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_)
PluginRes Plugin::Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, void * p1, void * p2, long l1, long l2)
{
PluginRes res;
int old_current_plugin = current_plugin;
PluginInfo info;
PluginRes res;
int old_current_plugin = current_plugin;
PluginInfo info;
Cur local_cur;
if( !cur )
cur = &local_cur;
Slots::iterator i = slots.lower_bound(message);
for( ; i!=slots.end() && i->first==message ; ++i )
{
info.Clear();
info.p1 = p1_;
info.p2 = p2_;
info.l1 = l1_;
info.l2 = l2_;
info.p1 = p1;
info.p2 = p2;
info.l1 = l1;
info.l2 = l2;
Call(ses, message, i, info);
Call(model_connector, plog, cur, message, i, info);
if( info.res )
++res.res_true;
else
++res.res_false;
if( info.has_res )
{
if( info.res )
++res.res_true;
else
++res.res_false;
}
}
current_plugin = old_current_plugin;
return res;
return res;
}
PluginRes Plugin::Call(morm::ModelConnector * model_connector, Log * plog, Session * session, Request * request, Mount * mount, int message, void * p1, void * p2, long l1, long l2)
{
Cur local_cur;
local_cur.session = session;
local_cur.request = request;
local_cur.mount = mount;
return Call(model_connector, plog, &local_cur, message, p1, p2, l1, l2);
}
PluginRes Plugin::Call(int message)
{
return Call(cur->session, message, 0, 0, 0, 0);
return Call(model_connector, &log, cur, message, 0, 0, 0, 0);
}
PluginRes Plugin::Call(int message, void * p1_)
{
return Call(cur->session, message, p1_, 0, 0, 0);
return Call(model_connector, &log, cur, message, p1_, 0, 0, 0);
}
PluginRes Plugin::Call(int message, void * p1_, void * p2_)
{
return Call(cur->session, message, p1_, p2_, 0, 0);
return Call(model_connector, &log, cur, message, p1_, p2_, 0, 0);
}
PluginRes Plugin::Call(int message, long l1_)
{
return Call(cur->session, message, 0, 0, l1_, 0);
return Call(model_connector, &log, cur, message, 0, 0, l1_, 0);
}
PluginRes Plugin::Call(int message, long l1_, long l2_)
{
return Call(cur->session, message, 0, 0, l1_, l2_);
return Call(model_connector, &log, cur, message, 0, 0, l1_, l2_);
}
PluginRes Plugin::Call(int message, void * p1_, long l1_)
{
return Call(cur->session, message, p1_, 0, l1_, 0);
return Call(model_connector, &log, cur, message, p1_, 0, l1_, 0);
}
PluginRes Plugin::Call(int message, void * p1_, long l1_, long l2_)
{
return Call(cur->session, message, p1_, 0, l1_, l2_);
return Call(model_connector, &log, cur, message, p1_, 0, l1_, l2_);
}
PluginRes Plugin::Call(int message, void * p1_, void * p2_, long l1_)
{
return Call(cur->session, message, p1_, p2_, l1_, 0);
return Call(model_connector, &log, cur, message, p1_, p2_, l1_, 0);
}
PluginRes Plugin::Call(Session * ses, int message)
{
return Call(ses, message, 0, 0, 0, 0);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_)
{
return Call(ses, message, p1_, 0, 0, 0);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_)
{
return Call(ses, message, p1_, p2_, 0, 0);
}
PluginRes Plugin::Call(Session * ses, int message, long l1_)
{
return Call(ses, message, 0, 0, l1_, 0);
}
PluginRes Plugin::Call(Session * ses, int message, long l1_, long l2_)
{
return Call(ses, message, 0, 0, l1_, l2_);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, long l1_)
{
return Call(ses, message, p1_, 0, l1_, 0);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, long l1_, long l2_)
{
return Call(ses, message, p1_, 0, l1_, l2_);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_)
{
return Call(ses, message, p1_, p2_, l1_, 0);
}
size_t Plugin::Size()
{
return plugins.size();
+25 -44
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,9 @@
#include <map>
#include "pluginmsg.h"
#include "plugindata.h"
#include "winixbase.h"
#include "winixmodeldeprecated.h"
#include "modelconnector.h"
#include "mount.h"
@@ -54,7 +56,7 @@ class Functions;
class Templates;
class SessionManager;
class WinixModel;
class WinixModelDeprecated;
class WinixRequest;
@@ -77,10 +79,12 @@ class WinixRequest;
class Plugin;
struct Session;
class Session;
class Request;
// move me to a different file
// may it should be based on WinixModelDeprecated?
struct PluginInfo
{
// these variables are used for some purposes
@@ -95,7 +99,6 @@ struct PluginInfo
// objects from winix which are accessible from a plugin
Db * db;
Config * config;
Cur * cur;
System * system;
@@ -108,14 +111,7 @@ struct PluginInfo
Plugin * plugin;
// a session
// some messages are sent in a session's context e.g. logging a user
// this pointer in not always the same as cur->session, it is preferred
// to use this pointer instead of cur->session
// (cur->session can point at a temporary object)
// this pointer can be null
Session * session;
morm::ModelConnector * model_connector;
// pointer to the plugin session (can be null if not set by the plugin or if session is null)
// this is taken from session->plugin_data.Get()
@@ -123,18 +119,17 @@ struct PluginInfo
// to create your plugin's session data
PluginDataBase * plugin_data_base; // !! zmienic nazwe na plugin_session_base ? a moze session_base; a moze plugin_session?
// whether or not there is a res (bool) value set
// default: true
// if set to false then the 'res' is not taken into account when calculating how many plugins
// have returned true or false
bool has_res;
// function return status
// default: false (if not set by the plugin)
bool res;
void set_dependency_for(WinixBase * winix_base);
void set_dependency_for(WinixBase & winix_base);
void set_dependency_for(WinixModel * winix_model);
void set_dependency_for(WinixModel & winix_model);
void Clear()
{
// pointers to winix objects are not cleared here
@@ -145,9 +140,9 @@ struct PluginInfo
l2 = 0;
plugin_id = -1;
session = 0;
plugin_data_base = 0;
has_res = true;
res = false;
}
@@ -171,11 +166,11 @@ struct PluginRes
class Plugin : public WinixBase
class Plugin : public WinixModelDeprecated
{
public:
// index of a plugin which is called by Call() method
// index of a plugin which is called by CallAllRegisteredMessages() method
// normally: -1
int current_plugin;
@@ -212,13 +207,10 @@ public:
Plugin();
~Plugin();
void SetDb(Db * pdb);
//void SetConfig(Config * pconfig);
void SetCur(Cur * pcur);
void SetSystem(System * psystem);
void SetCur(Cur * cur);
void SetFunctions(Functions * pfunctions);
void SetTemplates(Templates * ptemplates);
//void SetSynchro(Synchro * psynchro);
void SetSessionManager(SessionManager * psession_manager);
void SetWinixRequest(WinixRequest * winix_request);
@@ -242,16 +234,9 @@ public:
PluginRes Call(int message, void * p1_, long l1_);
PluginRes Call(int message, void * p1_, long l1_, long l2_);
PluginRes Call(int message, void * p1_, void * p2_, long l1_);
PluginRes Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_);
PluginRes Call(Session * ses, int message);
PluginRes Call(Session * ses, int message, void * p1_);
PluginRes Call(Session * ses, int message, void * p1_, void * p2_);
PluginRes Call(Session * ses, int message, long l1_);
PluginRes Call(Session * ses, int message, long l1_, long l2_);
PluginRes Call(Session * ses, int message, void * p1_, long l1_);
PluginRes Call(Session * ses, int message, void * p1_, long l1_, long l2_);
PluginRes Call(Session * ses, int message, void * p1_, void * p2_, long l1_);
PluginRes Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, void * p1 = nullptr, void * p2 = nullptr, long l1 = 0, long l2 = 0);
PluginRes Call(morm::ModelConnector * model_connector, Log * plog, Session * session, Request * request, Mount * mount, int message, void * p1 = nullptr, void * p2 = nullptr, long l1 = 0, long l2 = 0);
// how many plugins there are
size_t Size();
@@ -266,16 +251,13 @@ public:
private:
Db * db;
//Config * config;
Cur * cur;
System * system;
Functions * functions;
Templates * templates;
//Synchro * synchro;
SessionManager * session_manager;
WinixRequest * winix_request;
WinixRequest * winix_request; // is it needed anymore? !!!!!!!!!!!!!!!!
std::wstring temp_path; // used when loading plugins
@@ -285,11 +267,10 @@ private:
Slots slots;
void * LoadInitFun(const wchar_t * filename, Fun1 & fun_init);
void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info);
void Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, Slots::iterator & slot, PluginInfo & info);
bool SetDependency(PluginInfo & info);
void SetDependencyFor(WinixBase * winix_base);
void SetDependencyFor(WinixModel * winix_model);
bool SetDependencyForPluginInfo(morm::ModelConnector * pmodel_connector, Log * plog, Cur * pcur, PluginInfo & info);
void Lock();
void Unlock();
+28 -19
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2015, Tomasz Sowa
* Copyright (c) 2008-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
namespace Winix
{
// IMPROVEME give some description
#define WINIX_MAKE_DATABASE_MIGRATION 997
@@ -105,10 +107,14 @@ namespace Winix
// in l1 you have the old session id
#define WINIX_SESSION_REMOVED 30029
// the winix is closing
// the winix is being closing
// there is not any sessions available (cur->session is null)
// session pointer is null
#define WINIX_CLOSE 30040
#define WINIX_PREPARE_TO_CLOSE 30040
// winix has been closes, all other threads are stopped now, this is a last message for the main thread
// there is not any sessions available (cur->session is null)
#define WINIX_QUIT 30041
// preparing to remove a file (rm function)
// in p1 you have a pointer to the Item struct (file)
@@ -138,8 +144,15 @@ namespace Winix
// winix is initialized,
// now you can initialize your plugin
// session pointer is null
// you have to set the result status to true (env.res) if your
// plugin was initialized correctly, otherwise winix will not start
#define WINIX_PLUGIN_INIT 30080
// winix is ready to remove a plugin
// you can clear some plugin data here e.g. controllers
// all other threads are stopped now
#define WINIX_PLUGIN_QUIT 30081
// here you can add your own mount point, file systems, mount parameters
// for adding a new mount type call: system->mounts.AddMountType("new_mount_name")
// session pointer is null
@@ -167,6 +180,7 @@ namespace Winix
// the request is being ended
// you can clear some of your objects here
// in p1 you have a pointer to the Request object
#define WINIX_END_REQUEST 30140
// a new file (page) has been added
@@ -268,20 +282,6 @@ namespace Winix
// the session pointer in info is null
#define WINIX_BASE_URL_REDIRECT 31030
// raw POST parameters
// in p1 there is a pointer to std::wstring meaning a parameter's name
// in p2 there is a pointer to std::wstring value
// this is sent only from PostParser
// PostMultiParser (multipart/form-data html forms) doesn't send this messsage
// there is no a session set (session pointer is null)
// this message is sent for each name value pairs
//
#define WINIX_POST_PARAMS 31040
// this is the raw string sent in POST method
// in p1 there is a pointer to std::string object
#define WINIX_RAW_POST_STRING 31050
// this message is sent before calling MakePost() or MakeGet()
// if you return false (which is default) you can prevent the access
// to the resource
@@ -289,14 +289,23 @@ namespace Winix
// http headers (without cookies) were created and are ready to send
// here you can make some changes to them
// in p1 you have a pointer to the PT::Space (Request::out_headers)
// in p1 you have a pointer to the pt::Space (Request::out_headers)
#define WINIX_PREPARE_TO_SEND_HTTP_HEADERS 31070
// http cookies were created and are ready to send
// here you can make some changes to them
// in p1 you have a pointer to the PT::Space (Request::out_cookies)
// in p1 you have a pointer to the pt::Space (Request::out_cookies)
#define WINIX_PREPARE_TO_SEND_HTTP_COOKIES 31080
// a file log was saved
// in p1 you have a pointer to the pt::WTextStream buffer
// this can be called from a different thread but with locking
#define WINIX_SAVE_FILELOG 31090
// this message is sent when winix has been started
// it is called from the main thread (with locking)
#define WINIX_STARTED 31100
/*
messages sent from other threads
+16 -21
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -256,7 +256,7 @@ void PostMultiParser::LogFirst(const std::string & to_log, size_t len)
log << "empty";
log << "): \"";
log.LogString(to_log, len);
log.put_string(to_log, len);
log << "\"" << logend;
}
@@ -382,30 +382,23 @@ void PostMultiParser::ReadContent()
log << log2 << "PMP: content size: " << content_len << " bytes" << logend;
if( !PT::IsSubStringNoCase("pass", name.c_str()) )
if( !pt::is_substr_nc("pass", name.c_str()) )
LogFirst(content, config->log_post_value_size);
}
void PostMultiParser::ConvStr(const std::string & src, std::wstring & dst)
{
PT::UTF8ToWide(src, dst);
pt::utf8_to_wide(src, dst);
}
void PostMultiParser::AddNormalPostVar()
{
if( post_tab->size() >= WINIX_POSTTABLE_MAXSIZE )
{
err = WINIX_ERR_INPUT_TOO_LARGE;
log << log1 << "PMP: more than " << WINIX_POSTTABLE_MAXSIZE << " post variables (skipping)" << logend;
return;
}
ConvStr(name, namew);
ConvStr(content, contentw);
bool added = InsertPostVar(*post_tab, namew, contentw);
bool added = request->AddPostVar(namew, contentw);
log << log2 << "PMP: POST var, name: \"" << namew << "\"";
@@ -418,7 +411,7 @@ void PostMultiParser::AddNormalPostVar()
void PostMultiParser::AddFilePostVar()
{
if( post_file_tab->size() >= WINIX_POSTTABLE_MAXSIZE )
if( request->post_file_tab.size() >= WINIX_POSTTABLE_MAXSIZE )
{
err = WINIX_ERR_INPUT_TOO_LARGE;
log << log1 << "PMP: more than " << WINIX_POSTTABLE_MAXSIZE << " post file variables (skipping)" << logend;
@@ -430,7 +423,7 @@ void PostMultiParser::AddFilePostVar()
post_file_temp.tmp_filename = tmp_filename;
post_file_temp.file_size = content_len;
bool added = InsertPostVar(*post_file_tab, namew, post_file_temp);
bool added = InsertPostVar(request->post_file_tab, namew, post_file_temp);
log << log2 << "PMP: POST FILE var, name: \"" << namew << "\"";
@@ -496,7 +489,7 @@ size_t buf_len = sizeof(buf)/sizeof(wchar_t);
tmp_filename_postfix += 1;
tmp_filename = buf;
PT::WideToUTF8(tmp_filename, atmp_filename);
pt::wide_to_utf8(tmp_filename, atmp_filename);
tmp_file.open(atmp_filename.c_str(), std::ios_base::binary | std::ios_base::out);
// !! IMPROVE ME dodac ustawienie chmod config.upload_files_chmod dla tymczasowego pliku
@@ -565,6 +558,9 @@ void PostMultiParser::ReadChar()
in_buffer_len = FCGX_GetStr((char*)in_buffer, WINIX_POSTMULTI_INPUT_BUFFER, in);
in_buffer_ind = 0;
if( copy_raw_post && in_buffer_len > 0 )
request->raw_post.write((char *)in_buffer, in_buffer_len);
}
if( in_buffer_len == 0 )
@@ -581,7 +577,7 @@ void PostMultiParser::ReadChar()
Error PostMultiParser::Parse(FCGX_Stream * in_, PostTab & post_tab_, PostFileTab & post_file_tab_)
Error PostMultiParser::Parse(FCGX_Stream * in_, Request & request, bool copy_raw_post)
{
in = in_;
last = 0;
@@ -590,8 +586,8 @@ Error PostMultiParser::Parse(FCGX_Stream * in_, PostTab & post_tab_, PostFileTab
line_end_dos = false;
in_buffer_ind = WINIX_POSTMULTI_INPUT_BUFFER;
in_buffer_len = WINIX_POSTMULTI_INPUT_BUFFER;
post_tab = &post_tab_;
post_file_tab = &post_file_tab_;
this->request = &request;
this->copy_raw_post = copy_raw_post;
tmp_filename_postfix = 1;
ReadChar();
@@ -605,9 +601,8 @@ Error PostMultiParser::Parse(FCGX_Stream * in_, PostTab & post_tab_, PostFileTab
if( err != WINIX_ERR_OK )
{
RemovePostFileTmp(*post_file_tab);
post_tab->clear();
post_file_tab->clear();
RemovePostFileTmp(request.post_file_tab);
request.post_in.clear();
if( err != WINIX_ERR_INPUT_TOO_LARGE && err != WINIX_ERR_CANT_CREATE_FILE )
log << log1 << "PMP: syntax error" << logend;
+6 -6
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
#include <fcgiapp.h>
#include <fstream>
#include "error.h"
#include "requesttypes.h"
#include "request.h"
#include "config.h"
#include "misc.h"
#include "winixbase.h"
@@ -66,7 +66,7 @@ public:
~PostMultiParser();
void SetConfig(Config * pconfig);
Error Parse(FCGX_Stream * in_, PostTab & post_tab_, PostFileTab & post_file_tab_);
Error Parse(FCGX_Stream * in_, Request & request, bool copy_raw_post);
private:
@@ -80,9 +80,9 @@ private:
int tmp_filename_postfix;
size_t in_buffer_ind;
size_t in_buffer_len;
bool copy_raw_post;
PostTab * post_tab;
PostFileTab * post_file_tab;
Request * request;
int last; // last read character
int var_index; // used as a postfix to the same name (is auto increment)
@@ -148,7 +148,7 @@ std::pair<typename Container::iterator, bool> res;
if( !added )
{
key += L"_inc";
key += Toa(var_index);
pt::Toa(var_index, key, false, 10, 5);
res = container.insert( std::make_pair(key, value) );
added = res.second;
var_index += 1;
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2022-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,98 +32,83 @@
*
*/
#include "item.h"
#include "misc.h"
#include "crypt.h"
#include <fcgiapp.h>
#include <string>
#include "postparser.h"
#include "httpsimpleparser.h"
#include "convert/text.h"
namespace Winix
{
Item::Item()
PostParser::PostParser()
{
Clear();
log_value_size = 0;
HttpSimpleParser::getchar_returns_utf8_chars = true;
}
// !! IMPROVE ME
// now we have Request::start_time and Request::start_date
// we can somehow get the current time from the request
// may setting the date should be completetly removed from here?
void Item::SetDateToNow()
void PostParser::LogValueSize(size_t s)
{
date_creation = std::time(0);
date_modification = date_creation;
log_value_size = s;
}
void Item::SetDateModifyToNow()
void PostParser::Parse(FCGX_Stream * in, Request & request, bool copy_raw_post)
{
date_modification = std::time(0);
this->in = in;
this->request = &request;
this->copy_raw_post = copy_raw_post;
var_index = 1;
this->request->raw_post.clear();
HttpSimpleParser::Parse();
}
void Item::Clear()
int PostParser::GetChar()
{
id = -1;
int c = FCGX_GetChar(in);
user_id = -1;
group_id = -1;
privileges = 0;
modification_user_id = -1;
if( c != -1 && copy_raw_post )
request->raw_post << static_cast<unsigned char>(c);
guest_name.clear();
subject.clear();
content.clear();
modify_index = 0;
url.clear();
content_type = ct_formatted_text;
type = none;
parent_id = -1;
link_to.clear();
link_redirect = false;
content_id = -1;
ref = 1;
file_path.clear();
file_fs = -1;
file_type = WINIX_ITEM_FILETYPE_NONE;
hash.clear();
hash_type = WINIX_CRYPT_HASH_NONE;
file_size = 0;
has_thumb = false;
html_template.clear();
sort_index = 0;
meta.Clear();
ameta.Clear();
SetDateToNow();
return c;
}
/*
* we're using the HtmlFilter only for those contents
*
*/
bool Item::CanContentBeHtmlFiltered(Item::ContentType ct)
void PostParser::CreateLog(bool param_added, const std::wstring & name, const std::wstring & value)
{
return ct == ct_text || ct == ct_formatted_text || ct == ct_html || ct == ct_bbcode;
log << log2 << "Method POST, name: \"" << name << "\"";
if( log_value_size > 0 && !pt::is_substr_nc(L"pass", name.c_str()) )
{
log << ", value: ";
if( value.size() > log_value_size )
log << "(first " << log_value_size << " characters) ";
log << "\"";
log.put_string(value, log_value_size);
log << "\" (size: " << value.size() << ")";
}
if( param_added == false )
log << log2 << " (skipped)";
log << log2 << logend;
}
bool Item::CanContentBeHtmlFiltered()
void PostParser::Parameter(std::wstring & name, std::wstring & value)
{
return CanContentBeHtmlFiltered(content_type);
bool added = request->AddPostVar(name, value);
CreateLog(added, name, value);
}
} // namespace Winix
+14 -99
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2023, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,13 +35,9 @@
#ifndef headerfile_winix_core_postparser
#define headerfile_winix_core_postparser
#include <fcgiapp.h>
#include <string>
#include "httpsimpleparser.h"
#include "requesttypes.h"
#include "misc.h"
#include "utf8/utf8.h"
#include "convert/text.h"
#include "request.h"
namespace Winix
@@ -51,106 +47,25 @@ namespace Winix
class PostParser : public HttpSimpleParser
{
FCGX_Stream * in;
PostTab * post_tab;
size_t log_value_size;
int var_index;
bool has_winix_post_params_msg;
bool has_winix_raw_post_msg;
std::string raw_post;
protected:
virtual int GetChar()
{
int c = FCGX_GetChar(in);
if( c != -1 && has_winix_raw_post_msg )
raw_post += c;
return c;
}
void CreateLog(bool param_added, const std::wstring & name, const std::wstring & value)
{
log << log2 << "Method POST, name: \"" << name << "\"";
if( log_value_size > 0 && !PT::IsSubStringNoCase(L"pass", name.c_str()) )
{
log << ", value: ";
if( value.size() > log_value_size )
log << "(first " << log_value_size << " characters) ";
log << "\"";
log.LogString(value, log_value_size);
log << "\" (size: " << value.size() << ")";
}
if( param_added == false )
log << log2 << " (skipped)";
log << log2 << logend;
}
virtual void Parameter(std::wstring & name, std::wstring & value)
{
bool added;
std::pair<PostTab::iterator, bool> res;
if( has_winix_post_params_msg )
plugin->Call(0, WINIX_POST_PARAMS, &name, &value);
res = post_tab->insert( std::make_pair(name, value) );
added = res.second;
if( !added )
{
name += L"_inc";
name += Toa(var_index);
res = post_tab->insert( std::make_pair(name, value) );
added = res.second;
var_index += 1;
}
CreateLog(added, name, value);
}
public:
PostParser()
{
log_value_size = 0;
HttpSimpleParser::getchar_returns_utf8_chars = true;
}
PostParser();
void LogValueSize(size_t s);
void Parse(FCGX_Stream * in, Request & request, bool copy_raw_post);
void LogValueSize(size_t s)
{
log_value_size = s;
}
void Parse(FCGX_Stream * in_, PostTab & post_tab_)
{
in = in_;
post_tab = &post_tab_;
var_index = 1;
raw_post.clear();
protected:
has_winix_post_params_msg = plugin->HasMessage(WINIX_POST_PARAMS);
has_winix_raw_post_msg = plugin->HasMessage(WINIX_RAW_POST_STRING);
FCGX_Stream * in;
Request * request;
size_t log_value_size;
int var_index;
bool copy_raw_post;
HttpSimpleParser::Parse();
if( has_winix_raw_post_msg )
plugin->Call(0, WINIX_RAW_POST_STRING, &raw_post);
raw_post.clear();
}
virtual int GetChar();
void CreateLog(bool param_added, const std::wstring & name, const std::wstring & value);
virtual void Parameter(std::wstring & name, std::wstring & value);
};
+2082 -96
View File
File diff suppressed because it is too large Load Diff
+334 -151
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,16 +39,23 @@
#include <sstream>
#include <vector>
#include "requesttypes.h"
#include "item.h"
#include "models/item.h"
#include "error.h"
#include "config.h"
#include "textstream.h"
#include "templates/htmltextstream.h"
#include "date/date.h"
#include "space/space.h"
#include "space/spacetojson.h"
#include "textstream/textstream.h"
#include "outstreams.h"
#include "models.h"
#include "models/winixmodel.h"
#include "header.h"
#include "compress.h"
#include "plugin.h"
#include "mount.h"
#include "mounts.h"
#include "jobtask.h"
namespace Winix
@@ -58,12 +65,15 @@ namespace Winix
class FunctionBase;
class Templates;
struct Request
class Request : public WinixModel
{
public:
// how many input headers can be put to in_headers struct
static const size_t MAX_INPUT_HEADERS = 32;
@@ -82,14 +92,57 @@ struct Request
*/
size_t id;
// the state of the request
// not_assigned - the object is not being used
// normal_run - run in the main thread, this state is set after a new request is made
// assigned_to_job - the request is preserved and a new job will be called
// job_run - run in the job thread (objects are locked)
// finished - the request is finished and the object can be removed
enum RunState { not_assigned = 0, normal_run, assigned_to_job, job_run, job_continuation_run, prepare_to_finish, finished};
RunState run_state;
/*
request start time
Time() methods are very slow so it is better to directly use those two values
they are set when a request starts
* request start time
*
* start_time is the same as timespec_req_start.tv_sec
* start_date is a pt::Date converted from start_time
*
*/
timespec timespec_req_start;
time_t start_time;
PT::Date start_date;
pt::Date start_date;
/*
* request stop time
*
*/
timespec timespec_req_stop;
/*
* request stop time - start time
*
*/
timespec timespec_req_diff;
/*
* start time of the ezc engine (html templates)
*
*/
timespec timespec_ezc_engine_start;
/*
* end time of the ezc engine (html templates)
*
*/
timespec timespec_ezc_engine_stop;
@@ -107,7 +160,7 @@ struct Request
the HTTP method
!! IMPROVE ME add the rest methods here
*/
enum Method { get, post, head, delete_, unknown_method } method;
enum Method { get, head, post, put, delete_, connect, options, trace, patch, unknown_method } method;
/*
@@ -119,14 +172,17 @@ struct Request
/*
raw parameters
!! CHECK ME may post_tab and cookie_tab should be changed to PT::Space now?
!! CHECK ME may post_tab and cookie_tab should be changed to pt::Space now?
or may change the name to cookie_in? or in_cookie?
*/
PostTab post_tab;
PostFileTab post_file_tab;
CookieTab cookie_tab;
PT::Space post_in;
bool is_postin_used;// temporarily, before all post variables will be put to post_in
pt::Space post_in;
/*
* raw post input used if a Function::NeedToCopyRawPost() returned true
*/
pt::TextStream raw_post;
// input headers (without cookies)
// at the moment we are using FastCGI and HTTP headers are prefixed with 'HTTP_' string
@@ -135,7 +191,7 @@ struct Request
// although https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 says that there can be more
// than one http header with the same name we do not support it
// each header has a different name here, cookies we have in a different container (cookie_tab)
PT::Space headers_in;
pt::Space headers_in;
/*
@@ -151,6 +207,8 @@ struct Request
std::wstring env_http_host;
std::wstring env_http_user_agent;
std::wstring env_http_accept_encoding;
std::wstring env_http_accept;
std::wstring env_http_accept_language;
std::wstring env_fcgi_role;
std::wstring env_content_type;
std::wstring env_https;
@@ -171,6 +229,8 @@ struct Request
// true if we are using an encrypted connection (SSL)
bool using_ssl;
// true if the request is being made by ajax by htmx library
bool is_htmx_request;
/*
request input variables representing the winix filesystem
@@ -189,13 +249,23 @@ struct Request
// null if there is no a function
FunctionBase * function;
// current session (if exists, can be null)
Session * session;
// current mount point (can be null, it is treated as cms filesystem then)
Mount * mount;
// parameters (name:value)
ParamTab param_tab;
// this is a pointer either to the item (if exists) or to the last directory
Item * last_item;
// can we use gzip compression algorithm when sending content to the client
bool accept_gzip;
// can we use deflate compression algorithm when sending content to the client
bool accept_deflate;
/*
@@ -208,11 +278,101 @@ struct Request
*
*/
//
// the algorithm how a request's container is selected is shown below:
// (the whole answer's algorightm is implemented in PrepareAnswerType() method)
// ------------------------------------------------------------------------------------------
//
// at the beginning we set container_type to "raw" meaning simple text or html, then
// we check the "Accept" http header, if it is set then we set container_type accordingly:
//
// Accept | container_type
// -----------------------------------------------
// text/html | container_raw
// application/xhtml+xml | container_raw
// application/json | container_json
// application/xml | container_xml
// text/csv | container_csv
//
// next we check "container" url parameter, if it is set then we set container_type accordingly
// ("container" url parameter has higher precedence than "Accept" http header):
//
// container | container_type
// -----------------------------------------------
// raw | container_raw
// json | container_json
// xml | container_xml
// csv | container_csv
//
//
// Samples:
//
// http://domain.tld/dir/controller
// returns html answer from the main ezc stream
//
// http://domain.tld/dir/controller/container:raw
// returns html answer from the main ezc stream (the same as above)
//
// http://domain.tld/dir/controller/frame:abc
// returns "abc" frame as html
//
// http://domain.tld/dir/controller/container:json
// returns all serialized models to json and no ezc streams
//
// http://domain.tld/dir/controller/container:xml
// returns all serialized models to xml and no ezc streams
//
// http://domain.tld/dir/controller/container:json/frame:abc,xyz
// returns all serialized models to json and two frames in 'ezc_frames' object
//
// http://domain.tld/dir/controller/container:json/all_frames
// returns all serialized models to json and all frames in 'ezc_frames' object
//
// http://domain.tld/dir/controller/container:json/main_stream
// returns all serialized models and the main ezc stream in 'main_stream' field
//
// http://domain.tld/dir/controller/container:json/main_stream/all_frames
// returns all serialized models to json, all frames and the main stream
//
bool send_bin_stream;
bool send_main_stream;
bool send_all_frames;
std::vector<std::wstring> send_frames;
bool use_ezc_engine;
bool serialize_models;
// change maybe answer_text -> container_text?
enum ContainerType
{
container_raw,
container_json,
container_xml,
container_csv,
};
ContainerType container_type;
// at the beginning those with higher priority
std::vector<HeaderValue> accept_mime_types;
// at the beginning those with higher priority
std::vector<HeaderValue> accept_languages;
// request status
// !! CHANGE ME it'll be better to use ordinary http result codes
// DEPRECATED, use http_status instead
Error status;
/*
* HTTP result status
* at the moment default is -1 which means it is not used (use status in such a case)
*/
int http_status;
// if not empty means an address for redirecting to
// it should be url-encoded
std::wstring redirect_to;
@@ -233,100 +393,30 @@ struct Request
bool send_as_attachment;
// headers send to the client (without cookies) (may change to headers_out?)
PT::Space out_headers;
pt::Space out_headers;
// cookies send to the client
// a value can be either a cookie value or the whole cookie string (with domain, date etc)
PT::Space out_cookies;
pt::Space out_cookies;
// winix can return either a text answer or a binary answer
// if send_bin_stream is true then the binary answer is sent (out_bin_stream)
// or if send_bin_stream is false then the text answer is sent
// default: false
//
//
// winix answer send to the client's browser
// |
// |
// depending on send_bin_stream
// (if false) ------------------------------------------------- (if true)
// | |
// text answer binary answer
// | |
// depending on return_json sending out_bin_stream
// (if false) ------------------------------------ (if true)
// | |
// normal request ajax request
// | |
// sending out_main_stream |
// |
// |
// depending on return_info_only
// (if false) ------------------------------------------------------------- (if true)
// | |
// generating JSON object from: generating JSON object only from info
// out_streams and info, e.g.: e.g.:
// { { info object serialized here }
// "out": { out_streams serialized here e.g.:
// "stream_name_1": "some html content",
// "stream_name_2": "some other html content"
// },
// "info": { info object serialized here }
// }
//
//
bool send_bin_stream;
// binary page sent to the client if send_bin_stream is true
// binary page sent to the client if answer_source is answer_bin_stream
BinaryPage out_bin_stream;
// when returning the text answer we can either return the whole html page (normal requests)
// or a JSON object (for requests generated from AJAX)
// if return_json is false then we return the whole html page (which is in out_main_stream)
// if return_json is true we are creating an JSON object from out_streams
// and from info space (see above picture)
// (or just only from info if return_info_only is true)
// default: false
// return_json is set to true by App at the beginning of a request
// if reqtype:json parameter is present (in the url)
// note: return_json is only valid if send_bin_stream is false
bool return_json;
// main text output stream where the html otput is generated from ezc templates
// here the whole html page (with doctype, head, body) is generated
HtmlTextStream out_main_stream;
// text output streams used in ajax requests (send in JSON format to the client)
// in ezc templates you can use [ezc out "stream_name"] keyword
// text output streams used in ajax requests
// in ezc templates you can use [ezc frame "stream_name"] or just [frame "stream_name"] keyword
// to switch between streams
Ezc::OutStreams<HtmlTextStream> out_streams;
Ezc::OutStreams<HtmlTextStream, true> out_streams;
// if true the JSON object is generated only from info (out_streams are not used)
// default: false
bool return_info_only;
// additional info added when sending the JSON answer
PT::Space info;
// info serializer
// if not set then the json_generic_serializer from App will be used
// default: null (json_generic_serializer used)
PT::SpaceToJSON * info_serializer;
// if set to true then the standard template system will not be used
// default: false
bool page_generated;
// whether or not the main html stream should be filtered by our html filter
bool out_main_stream_use_html_filter;
// whether or not the ajax streams should be filtered by our html filter
// this filter is only aplied to streams in "out" space, "info" space is not touched
bool out_streams_use_html_filter;
// models to return or to render through ezc library
Ezc::Models models;
// filter html content with HTMLFilter, default the same as config.html_filter
bool use_html_filter;
// if this variable is true then winix always return 200 OK header
// when the status would be 404 (not found) or 403 (permission denied)
@@ -338,32 +428,50 @@ struct Request
bool gen_skip_new_line;
bool gen_use_special_chars;
// index template name
std::wstring html_template;
/*
additional variables used for common uses
*/
// DEPRECATED will be removed
// usually items in the current directory (depends on the function)
std::vector<Item> item_tab;
/*
* FastCGI request structure with pointers to input/output streams
*/
FCGX_Request fcgi_request;
long job_id; // the main id of your job
long job_second_id; // a secondary id of your job
pt::Space job;
Request();
void SetConfig(Config * pconfig);
void SetConfig(Config * config);
void SetTemplates(Templates * templates);
void SetCompress(Compress * compress);
void SetPlugin(Plugin * plugin);
void SetMounts(Mounts * mounts);
void set_json_connector(morm::JSONConnector * json_connector);
void set_xml_connector(morm::XMLConnector * xml_connector);
void fields();
void RequestStarts();
void RequestEnds();
void Clear();
void PrepareAnswerType();
bool IsParam(const wchar_t * param_name);
bool IsParam(const std::wstring & param_name);
@@ -373,6 +481,16 @@ struct Request
std::wstring * ParamValuep(const wchar_t * param_name); // returns nullptr if there is no such a parameter
std::wstring * ParamValuep(const std::wstring & param_name); // returns nullptr if there is no such a parameter
void AddParam(const std::wstring & param_name, const std::wstring & param_value);
void AddParam(const wchar_t * param_name, const wchar_t * param_value);
void RemoveParam(const wchar_t * param_name);
void RemoveParam(const std::wstring & param_name);
pt::Space * AddPostVar(pt::Space & space, const wchar_t * name);
bool AddPostVar(const wchar_t * name, const wchar_t * value);
bool AddPostVar(const std::wstring & name, const std::wstring & value);
bool IsPostVar(const wchar_t * var);
bool IsPostVar(const std::wstring & var);
const std::wstring & PostVar(const wchar_t * var); // returns an empty string if there is no such a parameter
@@ -382,74 +500,139 @@ struct Request
std::wstring * PostVarp(const wchar_t * var);
std::wstring * PostVarp(const std::wstring & var);
bool AllPostVarEmpty(); // returning true if all post vars are empty
void AddCookie(
const std::wstring & name,
const std::wstring * value_string = nullptr,
const pt::Stream * value_stream = nullptr,
pt::Date * expires = nullptr,
const std::wstring * path = nullptr,
const std::wstring * domain = nullptr,
CookieSameSite cookie_same_site = CookieSameSite::samesite_notset,
bool http_only = false,
bool secure = false);
void AddDefaultSessionCookie(const std::wstring & value, pt::Date * expires = nullptr);
bool has_frame(const wchar_t * frame);
bool has_frame(const std::wstring & frame);
void create_job(long job_id = JobTask::JOB_ID_DEFAULT, long job_secondary_id = JobTask::JOB_ID_DEFAULT);
void modify_status_code_if_needed();
// RENAMEME to add_header_if_not_exists
bool AddHeader(const wchar_t * name, const wchar_t * value);
bool AddHeader(const wchar_t * name, long value);
bool AddHeader(const std::wstring & name, const std::wstring & value);
bool AddHeader(const wchar_t * name, const pt::WTextStream & value);
bool AddHeader(const std::wstring & name, const pt::WTextStream & value);
void FinishRequest();
// setting a cookie
// name - cookie name (either const wchar_t, or std::wstring or PT::WTextStream)
// value - cookie value (can be everything which can be put to PT::WTextStream stream)
// the return std::wstring reference is a reference to the cookie inserted value (in out_cookies structure)
template<typename NameType, typename ValueType>
std::wstring & AddCookie(const NameType & name, const ValueType & value, PT::Date * expires = 0);
void SetEnv(const char * name, std::wstring & env);
void ReadEnvVariables();
void ReadEnvRemoteIP();
template<typename NameType, typename ValueType>
std::wstring & AddCookie(const NameType & name, const ValueType & value, PT::Date & expires);
static Method CheckRequestMethod(const wchar_t * name);
void CheckRequestMethod();
void CheckSSL();
void SetSubdomain();
static void PutMethodName(Request::Method method, pt::Stream & stream);
void PutMethodName(pt::Stream & stream);
bool has_htmx_redirect();
private:
Config * config;
Templates * templates;
Compress * compress;
Plugin * plugin;
Mounts * mounts;
morm::JSONConnector * json_connector;
morm::XMLConnector * xml_connector;
BinaryPage output_8bit;
BinaryPage compressed_output;
pt::WTextStream output_tmp_filtered_stream;
pt::TextStream serialized_model;
std::string aheader_name, aheader_value;
std::wstring cookie_id_string;
std::string send_data_buf;
std::wstring http_header_name;
std::string http_header_8bit;
// used in ParamValue() and PostVar() when there is no such a param
const std::wstring str_empty;
void ClearOutputStreams();
void CheckAcceptHeader();
void CheckContainerParameter();
void PrepareFrameNames();
void current_dir(morm::Wrapper & wrapper);
void last_item_wrapper(morm::Wrapper & wrapper);
void http_status_error_title(EzcEnv & env);
void http_status_error_description(EzcEnv & env);
void PrepareAndSendAnswer();
void PrepareRawAnswer();
void PrepareJsonAnswer();
void PrepareXmlAnswer();
void PrepareCsvAnswer();
void PrepareContenerizedAnswer();
void PutSeparatorIfNeeded(bool put_separator);
void SerializeField(const wchar_t * field_name);
void SerializeClosingField(const wchar_t * field_name);
void SerializeFieldJson(const wchar_t * field_name);
void SerializeFieldXml(const wchar_t * field_name);
void SerializeClosingFieldXml(const wchar_t * field_name);
void SerializeFieldCsv(const wchar_t * field_name);
void SerializeStream(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamJson(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamXml(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamCsv(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeAllFrames();
void SerializeSpecificFrames();
void SerializeModels();
void SerializeModel(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelJson(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelXml(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelCsv(morm::Wrapper & wrapper, const wchar_t * field_name);
void FilterHtmlIfNeeded(const pt::WTextStream & input_stream, BinaryPage & output, bool clear_stream = true);
void Send8bitOutput(BinaryPage & output);
void SendData(const BinaryPage & page, FCGX_Stream * out);
void UseEzcGenerator();
int SelectDeflateVersion();
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
void PrepareSessionCookie();
void PrepareHeaders(bool compressing, int compress_encoding, size_t output_size);
void ModifyStatusForRedirect();
void PrepareSendFileHeaderForStaticMountpoint();
void PrepareSendFileHeader();
void PrepareContentEncodingHeader(int compress_encoding);
void PrepareContentLengthHeader(size_t output_size);
void PrepareHeaderContentType();
void PrepareHeaderStatus(int http_status);
void SendHeaders();
void SendCookies();
bool CreateStaticResourcePath(pt::WTextStream & out_path);
bool CanSendContent();
void LogRequestTime();
MORM_MEMBER_FIELD(Request)
};
template<typename NameType, typename ValueType>
std::wstring & Request::AddCookie(const NameType & name, const ValueType & value, PT::Date * expires)
{
PT::WTextStream cookie;
cookie << value;
if( cookie.empty() )
cookie << L"\"\""; // cookie empty value
if( expires )
cookie << L"; expires=" << DateToStrCookie(*expires) << L" GMT";
cookie << L"; path=/; domain=" << config->base_url;
/*
!! IMPROVE ME add an option to the config
don't use '; secure' flag if you are using both sites (with SSL
and without SSL) -- with secure flag the cookie is sent only through
SSL and if you accidentally open a new window without SSL (http://)
then winix will create a new session for you and the previous session (https://)
will be lost (the session cookie will be overwritten in the client's browser)
*/
return out_cookies.Add(name, cookie);
}
template<typename NameType, typename ValueType>
std::wstring & Request::AddCookie(const NameType & name, const ValueType & value, PT::Date & expires)
{
return AddCookie(name, value, &expires);
}
} // namespace Winix
#endif
+8 -8
View File
@@ -45,12 +45,9 @@ namespace Winix
{
// !! IMPROVE ME
// !! narazie uzywane tylko w post multi parserze
// dodac do zwyklego parsera post
#define WINIX_POSTTABLE_MAXSIZE 50
// may move to config?
#define WINIX_POSTTABLE_MAXSIZE 1024
#define WINIX_POSTTABLE_VALUE_TABLE_MAXSIZE 1024
struct PostFile
@@ -69,15 +66,18 @@ struct Param
};
enum CookieSameSite {samesite_notset = 0, samesite_strict = 1, samesite_lax = 2, samesite_none = 3};
// some global types used by Request class
typedef std::map<std::wstring, std::wstring> PostTab;
typedef std::map<std::wstring, PostFile> PostFileTab;
typedef std::vector<Param> ParamTab;
typedef std::map<std::wstring, std::wstring> CookieTab;
typedef PT::TextStreamBase<char, 1, 4096> BinaryPage;
typedef pt::TextStreamBase<char, 1, 4096> BinaryPage;
+7 -2
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -97,6 +97,7 @@ void Session::Clear(bool clear_plugin_data)
new_session = true;
spam_score = 0;
remove_me = false;
allow_to_delete = true;
start_time = 0;
last_time = 0;
@@ -104,7 +105,6 @@ void Session::Clear(bool clear_plugin_data)
start_date.Clear();
last_date.Clear();
log_buffer.Clear();
last_css.clear();
ip_ban = 0;
@@ -121,6 +121,11 @@ void Session::ClearAfterRequest()
}
bool Session::is_temporary_session() const
{
return id == 0;
}
} // namespace Winix
+18 -13
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,12 +39,10 @@
#include <string>
#include <ctime>
#include <map>
#include "item.h"
#include "error.h"
#include "user.h"
#include "models/user.h"
#include "plugindata.h"
#include "rebus.h"
#include "textstream.h"
#include "date/date.h"
#include "ipban.h"
@@ -54,8 +52,9 @@ namespace Winix
struct Session
class Session
{
public:
Session();
Session(const Session & ses);
@@ -66,7 +65,7 @@ struct Session
void ClearAfterRequest();
// 0 - means that there is a temporary session
// 0 - means that this is a temporary session
long id;
// a session index
@@ -82,12 +81,12 @@ struct Session
// when this session was created
// (the same values)
time_t start_time;
PT::Date start_date;
pt::Date start_date;
// when this session was last used
// (the same values)
time_t last_time;
PT::Date last_date;
pt::Date last_date;
// when there was a last get request
// (used to calculate spam or invalid login attempts etc.)
@@ -101,16 +100,20 @@ struct Session
bool remember_me;
// if true then this session will be removed by SessionManager
// without checking the time expiration
// if remove_me is true and if allow_to_delete is true then this session will be
// removed by SessionManager without checking the time expiration
bool remove_me;
// if the session can be removed then this value is true (default)
// if we continue a request from a controller to a job
// then we set this value to false in order for the SessionManager
// to not delete this
bool allow_to_delete;
PluginData plugin_data;
// buffer for the session log
TextStream<std::wstring> log_buffer;
// !! IMPROVE ME it is still needed?
// css cannot be taken directly from the mountpoint?
// table with css files
@@ -133,6 +136,8 @@ struct Session
bool is_temporary_session() const;
};
+3 -3
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,7 +82,7 @@ Table::iterator i = table.begin();
{
if( i->plugin_data.HasAllocatedData() )
{
plugin->Call(&*i, WINIX_PLUGIN_SESSION_DATA_REMOVE); // the session passed here is ok?
plugin->Call(model_connector, &log, &*i, nullptr, nullptr, WINIX_PLUGIN_SESSION_DATA_REMOVE, nullptr, nullptr, 0, 0); // the session passed here is ok?
}
//i->plugin_data.DeleteAll(); // it's better to call it here instead in the destructor
@@ -116,7 +116,7 @@ IndexId::iterator i = index_id.find(id);
if( i->second->plugin_data.HasAllocatedData() )
{
plugin->Call(&*(i->second), WINIX_PLUGIN_SESSION_DATA_REMOVE); // the session passed here is ok?
plugin->Call(model_connector, &log, &*(i->second), nullptr, nullptr, WINIX_PLUGIN_SESSION_DATA_REMOVE, nullptr, nullptr, 0, 0); // the session passed here is ok?
}
//i->second->plugin_data.DeleteAll();
+2 -2
View File
@@ -42,7 +42,7 @@
#include "session.h"
#include "cur.h"
#include "config.h"
#include "winixmodel.h"
#include "winixmodeldeprecated.h"
@@ -52,7 +52,7 @@ namespace Winix
class SessionContainer : public WinixModel
class SessionContainer : public WinixModelDeprecated
{
public:
+129 -30
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2014-2018, Tomasz Sowa
* Copyright (c) 2014-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
#include "utf8/utf8.h"
#include "date/date.h"
#include "misc.h"
#include "convert/text.h"
namespace Winix
@@ -48,8 +49,8 @@ namespace Winix
SessionIdManager::SessionIdManager()
{
algorithm_type = 'a';
key_tab_size = 256;
algorithm_type = ALGORITHM_MULTIPLE_KEYS;
key_tab_size = 0;
key_index = 0;
last_key_generated = 0;
key_renew_time = 60;
@@ -57,9 +58,12 @@ SessionIdManager::SessionIdManager()
}
void SessionIdManager::Init(const std::wstring & keys_file)
void SessionIdManager::InitMultipleKeys(const std::wstring & keys_file)
{
algorithm_type = ALGORITHM_MULTIPLE_KEYS;
was_inited = true;
key_tab_size = 256;
key_tab1.resize(key_tab_size);
key_tab2.resize(key_tab_size);
@@ -72,6 +76,57 @@ void SessionIdManager::Init(const std::wstring & keys_file)
}
bool SessionIdManager::InitSingleKeys(const std::wstring & key1, const std::wstring & key2)
{
algorithm_type = ALGORITHM_SINGLE_KEYS;
key_tab_size = 1;
key_tab1.resize(key_tab_size);
key_tab2.resize(key_tab_size);
aes1.resize(key_tab_size);
aes2.resize(key_tab_size);
was_inited = true;
was_inited = was_inited && InitializeKey(key1, key_tab1);
was_inited = was_inited && InitializeKey(key2, key_tab2);
if( was_inited )
{
InitializeAesKeys();
}
return was_inited;
}
bool SessionIdManager::IsInitialized()
{
return was_inited;
}
bool SessionIdManager::InitializeKey(const std::wstring & key, std::vector<std::string> & key_tab)
{
if( key.size() == 16 * 2 || key.size() == 24 * 2 || key.size() == 32 * 2 )
{
if( !pt::hex_string_to_bytes(key, key_tab[0]) )
{
log << log1 << "SIM: an incorrect character in a key, expected a hex digits in the range 0-9 or a-f" << logend;
}
}
else
{
log << log1 << "SIM: provided key has size: " << key.size()
<< ", expected size is 16, 24 or 32 bytes (written as two hex digits each)" << logend;
return false;
}
return true;
}
void SessionIdManager::SetKeyRenewTime(time_t renew_time)
{
key_renew_time = renew_time;
@@ -86,12 +141,12 @@ void SessionIdManager::SetKeyRenewTime(time_t renew_time)
}
void SessionIdManager::ReadKey(const wchar_t * name, PT::Space & space, std::vector<std::string> & dest_key)
void SessionIdManager::ReadKey(const wchar_t * name, pt::Space & space, std::vector<std::string> & dest_key)
{
std::vector<std::wstring> keys;
std::string key_ascii, key_base64_decoded;
space.ListText(name, keys);
space.to_list(name, keys);
for(size_t i=0 ; i<key_tab_size ; ++i)
dest_key[i].clear();
@@ -100,7 +155,7 @@ std::string key_ascii, key_base64_decoded;
{
dest_key[i].clear();
if( PT::WideToUTF8(keys[i], key_ascii) )
if( pt::wide_to_utf8(keys[i], key_ascii) )
{
if( base64.Decode(key_ascii, key_base64_decoded) )
{
@@ -140,21 +195,20 @@ void SessionIdManager::InitializeAesKeys()
bool SessionIdManager::ReadKeysFromFile(const wchar_t * file)
{
PT::Space space;
PT::SpaceParser parser;
PT::Date date;
pt::Space space;
pt::SpaceParser parser;
pt::Date date;
parser.SetSpace(space);
PT::SpaceParser::Status status = parser.Parse(file);
pt::SpaceParser::Status status = parser.parse_space_file(file, space);
if( status == PT::SpaceParser::ok )
if( status == pt::SpaceParser::ok )
{
key_index = space.Size(L"key_index");
key_index = space.to_ulong(L"key_index");
if( key_index >= 256 )
key_index = 0;
if( date.Parse(space.Text(L"last_key_generated", L"0")) )
if( date.Parse(space.to_wstr(L"last_key_generated", L"0")) )
last_key_generated = date.ToTime();
ReadKey(L"key_tab1", space, key_tab1);
@@ -166,7 +220,7 @@ PT::Date date;
log << log1 << "SIM: I cannot read the session keys from: " << file << logend;
}
return status == PT::SpaceParser::ok;
return status == pt::SpaceParser::ok;
}
@@ -196,8 +250,8 @@ void SessionIdManager::SaveKeysToFile(std::vector<std::string> & keys)
bool SessionIdManager::SaveKeysToFile(const wchar_t * file)
{
PT::Date date = last_key_generated;
PT::WideToUTF8(file, file_name_ascii);
pt::Date date = last_key_generated;
pt::wide_to_utf8(file, file_name_ascii);
out_file.clear();
out_file.open(file_name_ascii, std::ios_base::binary | std::ios_base::out);
@@ -379,6 +433,18 @@ void SessionIdManager::CopyString(const std::wstring & in, std::string & out)
}
void SessionIdManager::CopyString(const std::wstring_view & in, std::string & out)
{
out.clear();
if( out.capacity() < in.size() )
out.reserve(in.size());
for(size_t i=0 ; i<in.size() ; ++i)
out += in[i];
}
bool SessionIdManager::Encode(std::string & str)
{
@@ -401,6 +467,7 @@ return true;
}
bool SessionIdManager::EncodeToken(size_t id, unsigned int index, time_t cur_utc_time, std::wstring & token)
{
size_t pad_top_size;
@@ -414,10 +481,14 @@ char pad_bottom_value;
if( !was_inited )
return false;
CheckKeys(cur_utc_time);
if( algorithm_type == ALGORITHM_MULTIPLE_KEYS )
{
CheckKeys(cur_utc_time);
}
RandPadding(pad_top_size, pad_top_value, pad_bottom_size, pad_bottom_value);
string_token += algorithm_type;
string_token += GetAlgoritmTypeAsString();
string_token += (unsigned char)key_index;
string_token += pad_top_value;
string_token += pad_bottom_value;
@@ -489,17 +560,14 @@ return true;
}
bool SessionIdManager::DecodeTokenA(size_t & id, unsigned int & index)
bool SessionIdManager::DecodeToken(size_t key, size_t & id, unsigned int & index)
{
size_t pad_top_size;
size_t pad_bottom_size;
char pad_top_value;
char pad_bottom_value;
const char * str = string_token.c_str() + 1;
size_t key = (unsigned char)(*str);
str += 1;
const char * str = string_token.c_str() + 2;
if( !DecodeAES(str, key) )
return false;
@@ -533,8 +601,31 @@ return CheckControlSums(str);
}
bool SessionIdManager::DecodeToken(size_t & id, unsigned int & index)
{
size_t key = 0;
bool SessionIdManager::DecodeToken(const std::wstring & token, size_t & id, unsigned int & index)
if( string_token[0] == 'a' )
{
// it is ALGORITHM_MULTIPLE_KEYS
key = (unsigned char)string_token[1];
}
else
if( string_token[0] == 'b' )
{
// it is ALGORITHM_SINGLE_KEYS
key = 0;
}
else
{
return false;
}
return DecodeToken(key, id, index);
}
bool SessionIdManager::DecodeToken(const std::wstring_view & token, size_t & id, unsigned int & index)
{
if( !was_inited )
return false;
@@ -547,13 +638,21 @@ bool SessionIdManager::DecodeToken(const std::wstring & token, size_t & id, unsi
if( string_token.size() != 34 )
return false;
if( string_token[0] == 'a' )
return DecodeTokenA(id, index);
return false;
return DecodeToken(id, index);
}
char SessionIdManager::GetAlgoritmTypeAsString()
{
if( algorithm_type == ALGORITHM_MULTIPLE_KEYS )
return 'a';
if( algorithm_type == ALGORITHM_SINGLE_KEYS )
return 'b';
return 'a';
}
} // namespace Winix
+45 -8
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2014-2018, Tomasz Sowa
* Copyright (c) 2014-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,30 +83,63 @@ public:
SessionIdManager();
/*
* initialization
* we are using keys stored in a file
* those keys are automatically generated
* this is the default algorithm
*/
static const int ALGORITHM_MULTIPLE_KEYS = 1;
/*
* we use only two keys
* those keys you have to provide
*/
static const int ALGORITHM_SINGLE_KEYS = 2;
/*
* initialization for ALGORITHM_MULTIPLE_KEYS algorithm
* this method takes about 1MB memory more (for AES key expansions)
* if you do not need the session cookie to be enrypted then don't call this method
*
*/
void Init(const std::wstring & keys_file);
void InitMultipleKeys(const std::wstring & keys_file);
/*
* initialization for ALGORITHM_SINGLE_KEYS algorithm
* keys should be provided as 16*2 or 24*2 or 32*2 hexadecimal characters
*
*/
bool InitSingleKeys(const std::wstring & key1, const std::wstring & key2);
/*
* true if the object is correctly initialized
*
*/
bool IsInitialized();
/*
* how often a new AES key pairs should be generated
* used with ALGORITHM_MULTIPLE_KEYS algorithm
*/
void SetKeyRenewTime(time_t renew_time);
/*
* encode/decode the session cookie
* make sure the Init() method is called first
* make sure InitMultipleKeys() or InitSingleKeys() method is called first
*
* for ALGORITHM_SINGLE_KEYS algorithm the cur_utc_time parameter is ignored
*
*/
bool EncodeToken(size_t id, unsigned int index, time_t cur_utc_time, std::wstring & token);
bool DecodeToken(const std::wstring & token, size_t & id, unsigned int & index);
bool DecodeToken(const std::wstring_view & token, size_t & id, unsigned int & index);
private:
bool was_inited;
char algorithm_type;
int algorithm_type;
std::string string_token, string_token_base64;
std::vector<std::string> key_tab1, key_tab2;
size_t key_index;
@@ -120,11 +153,12 @@ private:
std::string file_name_ascii;
std::vector<Tito::AES> aes1, aes2;
bool InitializeKey(const std::wstring & key, std::vector<std::string> & key_tab);
bool ReadKeysFromFile(const wchar_t * file);
bool ReadKeysFromFile(const std::wstring & file);
bool SaveKeysToFile(const wchar_t * file);
bool SaveKeysToFile(const std::wstring & file);
void ReadKey(const wchar_t * name, PT::Space & space, std::vector<std::string> & dest_key);
void ReadKey(const wchar_t * name, pt::Space & space, std::vector<std::string> & dest_key);
bool AreKeysCorrect(size_t index);
void GenerateKeys(size_t index, time_t cur_utc_time);
void CheckKeys(time_t cur_utc_time);
@@ -136,12 +170,15 @@ private:
void AppendXor(std::string & str);
void CopyString(const std::string & in, std::wstring & out);
void CopyString(const std::wstring & in, std::string & out);
void CopyString(const std::wstring_view & in, std::string & out);
bool Encode(std::string & str);
bool DecodeTokenA(size_t & id, unsigned int & index);
bool DecodeToken(size_t key, size_t & id, unsigned int & index);
bool DecodeToken(size_t & id, unsigned int & index);
bool IsPaddingCorrect(const char * str, size_t len, char val);
bool CheckControlSums(const char * str);
void InitializeAesKeys(size_t index);
bool DecodeAES(const char * str, size_t key);
char GetAlgoritmTypeAsString();
template<typename Value>
void Append(std::string & str, Value val);
+89 -63
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2019, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,11 +35,13 @@
#include <sys/stat.h>
#include <limits>
#include "sessionmanager.h"
#include "core/misc.h"
#include "request.h"
#include "log.h"
#include "session.h"
#include "sessionparser.h"
#include "functions/functionbase.h"
#include "system.h"
@@ -89,9 +91,9 @@ void SessionManager::SetLastContainer(LastContainer * plast_container)
}
void SessionManager::set_dependency(WinixModel * winix_model)
void SessionManager::set_dependency(WinixModelDeprecated * winix_model)
{
WinixModel::set_dependency(winix_model);
WinixModelDeprecated::set_dependency(winix_model);
session_tab.set_dependency(winix_model);
session_id_manager.set_dependency(winix_model);
}
@@ -107,7 +109,7 @@ void SessionManager::InitBanList()
void SessionManager::InitCookieEncoding()
{
if( config->session_cookie_encode && !config->session_keys_file.empty() )
session_id_manager.Init(config->session_keys_file);
session_id_manager.InitMultipleKeys(config->session_keys_file);
session_id_manager.SetKeyRenewTime(config->session_key_renew_time);
}
@@ -241,7 +243,7 @@ void SessionManager::SetSessionPutLogInfo(Session & ses, bool has_index, unsigne
main_log << ", index difference: " << (size_t)difference;
if( ses.puser )
main_log << log2 << ", user: " << ses.puser->name << ", id: " << ses.puser->id;
main_log << log2 << ", user: " << ses.puser->login << ", id: " << ses.puser->id;
main_log << log2 << logend;
}
@@ -256,7 +258,7 @@ void SessionManager::IncrementBanLevel(IPBan * ip_ban)
cur->request->start_time + (time_t)config->ban_level_2_delay,
cur->request->start_time + (time_t)config->ban_level_3_delay);
PT::Date date(ip_ban->expires);
pt::Date date(ip_ban->expires);
main_log << log2 << "SM: this IP address has been banned to: " << date << " UTC" << logend;
}
@@ -444,7 +446,7 @@ bool SessionManager::IsIPBanned()
else
if( current_ip_ban->IsIPBanned() )
{
PT::Date date = current_ip_ban->expires;
pt::Date date = current_ip_ban->expires;
main_log << log2 << "SM: this ip is bannned to: " << date << " UTC" << logend;
return true;
}
@@ -474,31 +476,34 @@ Session * SessionManager::PrepareSession()
{
session = nullptr;
if( !IsIPBanned() )
if( config->use_internal_session_mechanism )
{
CookieTab::iterator i = cur->request->cookie_tab.find(config->http_session_id_name);
if( i != cur->request->cookie_tab.end() )
if( !IsIPBanned() )
{
if( !SetSessionFromCookie(i->second) )
CookieTab::iterator i = cur->request->cookie_tab.find(config->session_cookie_name);
if( i != cur->request->cookie_tab.end() )
{
cur->request->cookie_tab.erase(i);
if( !SetSessionFromCookie(i->second) )
{
cur->request->cookie_tab.erase(i);
}
}
else
{
if( cur->request->function && cur->request->function->need_session )
{
NoSessionCookieWasSent();
}
}
}
else
{
if( cur->request->function && cur->request->function->need_session )
{
NoSessionCookieWasSent();
}
}
}
if( !session && cur->request->function && cur->request->function->need_session )
{
if( !current_ip_ban || !current_ip_ban->IsIPBanned() )
if( !session && cur->request->function && cur->request->function->need_session )
{
CreateSession();
if( !current_ip_ban || !current_ip_ban->IsIPBanned() )
{
CreateSession();
}
}
}
@@ -515,14 +520,17 @@ Session * SessionManager::PrepareSession()
Session * SessionManager::CheckIfFunctionRequireSession()
{
if( cur->request->function && cur->request->function->need_session )
if( config->use_internal_session_mechanism )
{
if( session == &temporary_session )
if( cur->request->function && cur->request->function->need_session )
{
if( !current_ip_ban || !current_ip_ban->IsIPBanned() )
if( session == &temporary_session )
{
CreateSession();
session->ip_ban = current_ip_ban;
if( !current_ip_ban || !current_ip_ban->IsIPBanned() )
{
CreateSession();
session->ip_ban = current_ip_ban;
}
}
}
}
@@ -558,7 +566,7 @@ SessionContainer::Iterator SessionManager::SessionEnd()
// called from the main thread (from App::Close)
void SessionManager::DeleteSessions()
{
SessionContainer::Iterator i;
@@ -567,7 +575,7 @@ void SessionManager::DeleteSessions()
{
if( i->puser && !i->remember_me )
{
plugin->Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_PREPARE_USER_TO_LOGOUT, i->puser, nullptr, 0, 0);
last_container->UserLogout(i->puser->id, i->id);
}
}
@@ -599,7 +607,7 @@ SessionContainer::Iterator i = session_tab.FindById(old_id);
}
if( changed )
plugin->Call(&(*i), WINIX_SESSION_CHANGED_ID, old_id, new_id);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_SESSION_CHANGED_ID, nullptr, nullptr, old_id, new_id);
else
main_log << log1 << "SM: I cannot create a new session id (still uses old one)" << logend;
}
@@ -612,19 +620,20 @@ return changed;
}
// called from the main thread (from App::Init)
void SessionManager::InitTmpSession()
{
Session * old_session = cur->session;
main_log << log4 << "SM: initializing temporary session" << logend;
cur->session = &temporary_session;
plugin->Call(WINIX_SESSION_CREATED);
plugin->Call(main_model_connector, &main_log, nullptr, WINIX_SESSION_CREATED);
cur->session = old_session;
}
// called from the main thread at the and (from App::Close)
void SessionManager::UninitTmpSession()
{
Session * old_session = cur->session;
@@ -635,43 +644,52 @@ void SessionManager::UninitTmpSession()
if( cur->session->plugin_data.HasAllocatedData() )
{
plugin->Call(cur->session, WINIX_PLUGIN_SESSION_DATA_REMOVE);
plugin->Call(main_model_connector, &main_log, cur->session, nullptr, nullptr, WINIX_PLUGIN_SESSION_DATA_REMOVE);
}
//cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_PLUGIN_SESSION_DATA_REMOVE);
cur->session->plugin_data.Resize(0);
cur->session = old_session;
}
// called from the main thread (from App::Init)
void SessionManager::LoadSessions()
{
SessionParser sp;
SessionContainer::Iterator i;
sp.set_dependency(this);
// sessions will be overwritten (pointers are invalidated)
cur->session = &temporary_session;
sp.SetUsers(&system->users);
sp.Parse(config->session_file, session_tab);
for(i=session_tab.Begin() ; i != session_tab.End() ; ++i)
if( config->use_internal_session_mechanism )
{
i->plugin_data.Resize(plugin->Size());
plugin->Call(&(*i), WINIX_SESSION_CREATED);
if( !config->session_file.empty() )
{
sp.set_dependency(this);
/*
!! IMPROVE ME
we do not add it to the last_container (we don't have IP address stored yet)
*/
// sessions will be overwritten (pointers are invalidated)
cur->session = &temporary_session;
if( i->puser )
plugin->Call(&(*i), WINIX_USER_LOGGED);
sp.SetUsers(&system->users);
sp.Parse(config->session_file, session_tab);
for(i=session_tab.Begin() ; i != session_tab.End() ; ++i)
{
i->plugin_data.Resize(plugin->Size());
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_SESSION_CREATED);
/*
!! IMPROVE ME
we do not add it to the last_container (we don't have IP address stored yet)
*/
if( i->puser )
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_USER_LOGGED);
}
}
else
{
// FIXME this log is not printed, why?
main_log << log1 << "SM: session_file config parameter is empty, not loading sessions" << logend;
}
}
cur->session = &temporary_session;
@@ -685,10 +703,18 @@ void SessionManager::SaveSessions()
{
char file_path[WINIX_OS_PATH_SIZE];
if( config->session_file.empty() )
if( !config->use_internal_session_mechanism )
{
return;
}
if( !WideToUTF8(config->session_file, file_path, WINIX_OS_PATH_SIZE) )
if( config->session_file.empty() )
{
main_log << log1 << "SM: session_file config parameter is empty, not saving sessions - sessions lost" << logend;
return;
}
if( !pt::wide_to_utf8(config->session_file, (char*)file_path, WINIX_OS_PATH_SIZE) )
return;
std::ofstream file(file_path);
@@ -747,7 +773,7 @@ size_t SessionManager::MarkAllSessionsToRemove(long user_id)
{
if( i->puser && i->puser->id == user_id )
{
plugin->Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
last_container->UserLogout(i->puser->id, i->id);
i->remove_me = true;
i->puser = 0;
@@ -860,7 +886,7 @@ const int deleted_max_at_once = 10;
}
else
{
if( i->remove_me || IsSessionOutdated(*i) )
if( i->allow_to_delete && (i->remove_me || IsSessionOutdated(*i)) )
{
Session * ses = &(*i);
++i;
@@ -906,16 +932,16 @@ void SessionManager::DeleteSession(Session * del_session)
{
if( del_session->puser )
{
plugin->Call(del_session, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser);
plugin->Call(model_connector, &log, del_session, nullptr, nullptr, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser, nullptr, 0, 0);
last_container->UserLogout(del_session->puser->id, del_session->id);
del_session->puser = 0;
}
long id = del_session->id;
plugin->Call(del_session, WINIX_PREPARE_SESSION_TO_REMOVE);
plugin->Call(model_connector, &log, del_session, nullptr, nullptr, WINIX_PREPARE_SESSION_TO_REMOVE, del_session->puser, nullptr, 0, 0);
session_tab.EraseById(del_session->id);
plugin->Call((Session*)0, WINIX_SESSION_REMOVED, id);
plugin->Call(model_connector, &log, nullptr, WINIX_SESSION_REMOVED, nullptr, nullptr, id, 0);
}
+2 -3
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2019, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,6 @@
#include "config.h"
#include "request.h"
#include "lastcontainer.h"
#include "system.h"
#include "synchro.h"
#include "basethread.h"
#include "sessionidmanager.h"
@@ -65,7 +64,7 @@ public:
void SetSystem(System * psystem);
void SetLastContainer(LastContainer * plast_container);
void set_dependency(WinixModel * winix_model);
void set_dependency(WinixModelDeprecated * winix_model);
// can return a null pointer
Session * FindSession(long id);
+3 -3
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2014, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,7 +60,7 @@ char file_path[WINIX_OS_PATH_SIZE];
container.Clear();
if( !WideToUTF8(path, file_path, WINIX_OS_PATH_SIZE) )
if( !pt::wide_to_utf8(path, (char*)file_path, WINIX_OS_PATH_SIZE) )
return false;
file.open(file_path, std::ios_base::in | std::ios_base::binary);
@@ -135,7 +135,7 @@ void SessionParser::MakeSession(long id, long user_id, SessionContainer & contai
// !! IMPROVE ME we do not save last_time_get
users->IncrementLoggedUsers();
log << log2 << "SP: read session id: " << id << " for user: " << puser->name << logend;
log << log2 << "SP: read session id: " << id << " for user: " << puser->login << logend;
}
else
{
-257
View File
@@ -1,257 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "slog.h"
#include "utf8/utf8.h"
namespace Winix
{
SLog::SLog()
{
cur = 0;
locale = 0;
}
void SLog::SetCur(Cur * pcur)
{
cur = pcur;
}
void SLog::SetLocale(Locale * plocale)
{
locale = plocale;
}
SLog & SLog::operator<<(const void * s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const char * s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const std::string * s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const std::string & s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const wchar_t * s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const std::wstring * s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const std::wstring & s)
{
return PutLog(s);
}
SLog & SLog::operator<<(int s)
{
return PutLog(s);
}
SLog & SLog::operator<<(long s)
{
return PutLog(s);
}
SLog & SLog::operator<<(char s)
{
return PutLog(s);
}
SLog & SLog::operator<<(wchar_t s)
{
return PutLog(s);
}
SLog & SLog::operator<<(size_t s)
{
return PutLog(s);
}
SLog & SLog::operator<<(double s)
{
return PutLog(s);
}
SLog & SLog::operator<<(const PT::Date & date)
{
return PutLog(date);
}
SLog & SLog::operator<<(LogManipulators m)
{
if( cur && cur->session )
{
TextStream<std::wstring> & buf = cur->session->log_buffer;
switch(m)
{
case logend:
buf << '\n';
if( buf.Size() > WINIX_SLOG_MAX_LOG_SIZE )
{
buf.Clear();
(*this) << logwarning << T("slog_turn_over") << " " << WINIX_SLOG_MAX_LOG_SIZE << logend;
}
break;
case loginfo:
case logwarning:
case logerror:
buf << (wchar_t)(int)m;
break;
default:
break;
}
}
return *this;
}
SLog & SLog::TranslateText(const char * str)
{
PT::UTF8ToWide(str, key_temp);
return TranslateText(key_temp.c_str());
}
SLog & SLog::TranslateText(const wchar_t * str)
{
if( cur && cur->session )
{
const std::wstring * trans = 0;
if( locale )
trans = &locale->Get(str);
// !! IMPROVE ME "Not translated" add to locale
if( !trans || trans->empty() )
cur->session->log_buffer << "Not translated: " << str;
else
cur->session->log_buffer << trans;
}
return *this;
}
SLog & SLog::operator<<(const TranslateTextHelper<const char*> & raw)
{
return TranslateText(raw.par);
}
SLog & SLog::operator<<(const TranslateTextHelper<const wchar_t*> & raw)
{
return TranslateText(raw.par);
}
SLog & SLog::operator<<(TranslateTextHelper<const std::string*> raw)
{
return TranslateText(raw.par->c_str());
}
SLog & SLog::operator<<(TranslateTextHelper<const std::wstring*> raw)
{
return TranslateText(raw.par->c_str());
}
SLog & SLog::operator<<(TranslateTextHelper<std::string> raw)
{
return TranslateText(raw.par.c_str());
}
SLog & SLog::operator<<(TranslateTextHelper<std::wstring> raw)
{
return TranslateText(raw.par.c_str());
}
} // namespace Winix
-173
View File
@@ -1,173 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_slog
#define headerfile_winix_core_slog
#include "cur.h"
#include "logmanipulators.h"
#include "templates/locale.h"
#include "textstream/textstream.h"
namespace Winix
{
#define WINIX_SLOG_MAX_LOG_SIZE 10240
/*
session logger
sample:
#include "log.h" (or slog.h)
slog << logerror << "message" << "something" << logend;
slog << logwarning << T("message_to_translate") << x << logend;
if the latter example "message_to_translate" will be taken from locales
currently following manipulators are taken into account:
loginfo - the message in a normal info
logwarning - this is a warning
logerror - this is an error
logend - end of a line -- we have one kind of a message (info, warning, error) per line
loginfo, logwarning, logerror should be specified at the beginning of a line
(other manipulators are skipped)
*/
class SLog
{
public:
SLog();
void SetCur(Cur * pcur);
void SetLocale(Locale * plocale);
template<class RawType>
struct TranslateTextHelper
{
const RawType & par;
TranslateTextHelper(const TranslateTextHelper<RawType> & p) : par(p.par) {}
TranslateTextHelper(const RawType & p) : par(p) {}
};
SLog & operator<<(const void * s);
SLog & operator<<(const char * s);
SLog & operator<<(const std::string * s);
SLog & operator<<(const std::string & s);
SLog & operator<<(const wchar_t * s);
SLog & operator<<(const std::wstring * s);
SLog & operator<<(const std::wstring & s);
SLog & operator<<(int s);
SLog & operator<<(long s);
SLog & operator<<(char s);
SLog & operator<<(wchar_t s);
SLog & operator<<(size_t s);
SLog & operator<<(double s);
SLog & operator<<(LogManipulators m);
SLog & operator<<(const PT::Date & date);
template<typename char_type, size_t stack_size, size_t heap_block_size>
SLog & operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf);
SLog & TranslateText(const char * str);
SLog & TranslateText(const wchar_t * str);
template<size_t str_size>
SLog & operator<<(const TranslateTextHelper<const char [str_size]> & raw) { return TranslateText(raw.par); }
template<size_t str_size>
SLog & operator<<(const TranslateTextHelper<const wchar_t [str_size]> & raw){ return TranslateText(raw.par); }
template<size_t str_size>
SLog & operator<<(const TranslateTextHelper<char [str_size]> & raw) { return TranslateText(raw.par); }
template<size_t str_size>
SLog & operator<<(const TranslateTextHelper<wchar_t [str_size]> & raw){ return TranslateText(raw.par); }
SLog & operator<<(const TranslateTextHelper<const char*> & raw);
SLog & operator<<(const TranslateTextHelper<const wchar_t*> & raw);
SLog & operator<<(TranslateTextHelper<const std::string*> raw);
SLog & operator<<(TranslateTextHelper<const std::wstring*> raw);
SLog & operator<<(TranslateTextHelper<std::string> raw);
SLog & operator<<(TranslateTextHelper<std::wstring> raw);
private:
template<class LogParam>
SLog & PutLog(const LogParam & par);
Cur * cur;
Locale * locale;
std::wstring key_temp;
};
template<class RawType>
SLog::TranslateTextHelper<RawType> T(const RawType & par)
{
return SLog::TranslateTextHelper<RawType>(par);
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
SLog & SLog::operator<<(const PT::TextStreamBase<char_type, stack_size, heap_block_size> & buf)
{
return PutLog(buf);
}
template<class LogParam>
SLog & SLog::PutLog(const LogParam & par)
{
if( cur && cur->session )
cur->session->log_buffer << par;
return *this;
}
} // namespace Winix
#endif
+198 -140
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2018, Tomasz Sowa
* Copyright (c) 2010-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -58,12 +58,6 @@ void System::SetCur(Cur * pcur)
//}
void System::SetDb(Db * pdb)
{
db = pdb;
}
//void System::SetSynchro(Synchro * psynchro)
//{
// synchro = psynchro;
@@ -81,13 +75,14 @@ void System::SetSessionManager(SessionManager * sm)
}
void System::set_dependency(WinixModel * winix_model)
void System::set_dependency(WinixModelDeprecated * winix_model)
{
WinixModel::set_dependency(winix_model);
WinixModelDeprecated::set_dependency(winix_model);
dirs.set_dependency(this);
mounts.set_dependency(this);
users.set_dependency(this);
//users.set_dependency(this);
users.set_connector(model_connector);
groups.set_dependency(this);
rebus.set_dependency(this);
load_avg.set_dependency(this);
@@ -123,28 +118,26 @@ void System::ReadTimeZones()
}
void System::Init()
bool System::Init()
{
//thread_manager.SetSynchro(synchro);
thread_manager.Init();
dirs.SetDb(db);
dirs.SetCur(cur); // only one method is using cur, can be passed as a parameter to the method
dirs.SetNotify(&notify);
dirs.ReadDirs();
mounts.SkipStaticDirs(config->dont_use_static_dirs);
mounts.SetDirs(&dirs);
mounts.SetDb(db);
mounts.SetCur(cur); // only one method is using cur, can be passed as a parameter to the method
mounts.CreateMounts();
mounts.ReadMounts();
users.SetCur(cur);
users.SetSessionManager(session_manager);
users.ReadUsers(db);
// users.SetCur(cur);
// users.SetSessionManager(session_manager);
users.set_connector(model_connector);
users.ReadUsers();
groups.ReadGroups(db); // !! chwilowe przekazanie argumentu, db bedzie zmienione
groups.ReadGroups();
rebus.SetCur(cur);
rebus.Init();
@@ -155,21 +148,29 @@ void System::Init()
notify.SetUsers(&users);
notify.SetDirs(&dirs);
notify.SetThreadManager(&thread_manager);
notify.Init();
image.SetDb(db);
if( !notify.Init() )
return false;
image.SetConfig(config);
image.SetSystem(this);
thread_manager.Add(&image, L"image");
if( !thread_manager.Add(&image, L"image") )
return false;
job.SetCur(cur);
job.SetFunctions(functions);
job.SetLoadAvg(&load_avg);
job.SetMounts(&mounts);
job.SetReqTab(&req_tab);
// SetSynchro will be called by ThreadManager itself
// job.ReadFromFile();
thread_manager.Add(&job, L"job");
if( !thread_manager.Add(&job, L"job") )
return false;
ReadTimeZones();
return true;
}
@@ -219,7 +220,7 @@ void System::PutUrlProto(bool can_use_ssl, std::wstring & str, bool clear_str)
/*
* try_to_use_ssl is to be meant: config->use_ssl, config->use_ssl_static, config->use_ssl_common
*/
void System::PutUrlProto(bool can_use_ssl, PT::TextStream & str, bool clear_stream)
void System::PutUrlProto(bool can_use_ssl, pt::Stream & str, bool clear_stream)
{
if( clear_stream )
str.clear();
@@ -241,7 +242,7 @@ void System::PutUrlProto(std::wstring & str, bool clear_str)
}
void System::PutUrlProto(PT::TextStream & str, bool clear_stream)
void System::PutUrlProto(pt::Stream & str, bool clear_stream)
{
return PutUrlProto(config->use_ssl, str, clear_stream);
}
@@ -337,14 +338,23 @@ void System::RedirectTo(long item_id, const wchar_t * postfix, bool use_reqtype)
else
{
// item_id is pointing to a file
DbItemQuery iq;
// DbItemQuery iq;
iq.SetAllSel(false);
iq.WhereId(item_id);
iq.sel_parent_id = true;
iq.sel_url = true;
// iq.SetAllSel(false);
// iq.WhereId(item_id);
// iq.sel_parent_id = true;
// iq.sel_url = true;
if( db->GetItem(item_temp, iq) == WINIX_ERR_OK )
morm::Finder<Item> finder(model_connector);
item_temp = finder.
select().
where().
eq(L"id", item_id).
get();
//if( db->GetItem(item_temp, iq) == WINIX_ERR_OK )
if( item_temp.found() )
{
if( dirs.MakePath(item_temp.parent_id, cur->request->redirect_to, false) )
cur->request->redirect_to += item_temp.url;
@@ -524,11 +534,11 @@ bool System::CanChangeUser(const Item & item, long new_user_id)
// session must be set
return false;
if( cur->session->puser && cur->session->puser->super_user )
if( cur->session->puser && cur->session->puser->is_super_user )
// super user is allowed everything
return true;
if( item.user_id == -1 || new_user_id == -1 || item.user_id != new_user_id )
if( item.item_content.user_id == -1 || new_user_id == -1 || item.item_content.user_id != new_user_id )
// only super user can change the owner of an item
return false;
@@ -544,11 +554,11 @@ bool System::CanChangeGroup(const Item & item, long new_group_id)
// session must be set
return false;
if( cur->session->puser && cur->session->puser->super_user )
if( cur->session->puser && cur->session->puser->is_super_user )
// super user is allowed everything
return true;
if( item.group_id != new_group_id )
if( item.item_content.group_id != new_group_id )
{
// user is allowed to change the group only if he is an owner of the item
// he can change only into a group in which he is a member of, or into a 'no_group'
@@ -556,7 +566,7 @@ bool System::CanChangeGroup(const Item & item, long new_group_id)
if( !cur->session->puser || cur->session->puser->id == -1 )
return false;
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
if( item.item_content.user_id == -1 || cur->session->puser->id != item.item_content.user_id )
return false;
if( new_group_id == -1 )
@@ -578,18 +588,18 @@ bool System::CanChangePrivileges(const Item & item, int new_priv)
// session must be set
return false;
if( cur->session->puser && cur->session->puser->super_user )
if( cur->session->puser && cur->session->puser->is_super_user )
// super user is allowed everything
return true;
if( item.privileges != new_priv )
if( item.item_content.privileges != new_priv )
{
// the owner of an item is allowed to change the privileges
if( !cur->session->puser || cur->session->puser->id == -1 )
return false;
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
if( item.item_content.user_id == -1 || cur->session->puser->id != item.item_content.user_id )
return false;
}
@@ -597,69 +607,31 @@ return true;
}
// private
bool System::HasAccess(const Item & item, int mask)
{
if( !cur->session )
// session must be set
return false;
if( cur->session->puser && cur->session->puser->super_user )
// super user is allowed everything
return true;
if( cur->session->puser && item.user_id != -1 && cur->session->puser->id == item.user_id )
{
// the owner
return ((item.privileges >> 9) & mask) == mask;
}
if( cur->session->puser && item.group_id != -1 && cur->session->puser->IsMemberOf(item.group_id) )
{
// group
return ((item.privileges >> 6) & mask) == mask;
}
if( cur->session->puser )
{
// others -- others logged people
return ((item.privileges >> 3) & mask) == mask;
}
// guests -- not logged people
return (item.privileges & mask) == mask;
}
// DEPRACATED
bool System::HasReadAccess(const Item & item)
{
return HasAccess(item, 4);
return item.item_content.has_read_access();
}
// DEPRACATED
bool System::HasWriteAccess(const Item & item)
{
return HasAccess(item, 2);
return item.item_content.has_write_access();
}
// DEPRACATED
bool System::HasReadWriteAccess(const Item & item)
{
return HasAccess(item, 6); // r+w
return item.item_content.has_read_write_access();
}
// DEPRACATED
bool System::HasReadExecAccess(const Item & item)
{
if( cur->session && cur->session->puser && cur->session->puser->super_user )
{
// there must be at least one 'x' (for the root)
// !! CHECK ME: is it applicable to directories too?
return (item.privileges & 01111) != 0;
}
return HasAccess(item, 5); // r+x
return item.item_content.has_read_exec_access();
}
@@ -746,7 +718,7 @@ int System::NewPrivileges(int creation_mask)
{
if( cur && cur->session && cur->session->puser )
{
int umask = cur->session->puser->env.Int(L"umask", config->umask);
int umask = cur->session->puser->env.to_int(L"umask", config->umask);
return (~umask) & creation_mask;
}
else
@@ -774,19 +746,19 @@ bool System::CanRemoveRenameChild(const Item & dir, long child_item_user_id)
if( !HasWriteAccess(dir) )
return false;
if( (dir.privileges & 010000) == 0 )
if( (dir.item_content.privileges & 010000) == 0 )
// there is no a sticky bit set to this directory
return true;
if( cur->session->puser )
{
if( cur->session->puser->super_user )
if( cur->session->puser->is_super_user )
return true;
if( dir.user_id != -1 && cur->session->puser->id != -1 && child_item_user_id != -1 )
if( dir.item_content.user_id != -1 && cur->session->puser->id != -1 && child_item_user_id != -1 )
{
if( cur->session->puser->id == child_item_user_id ||
cur->session->puser->id == dir.user_id )
cur->session->puser->id == dir.item_content.user_id )
return true;
}
}
@@ -840,7 +812,7 @@ bool System::IsSuperUser(long user_id)
if( !puser )
return false;
return puser->super_user;
return puser->is_super_user;
}
@@ -867,12 +839,12 @@ return puser->IsMemberOf(group);
// the path depends on parent_id
bool System::CreateNewFileSimpleFs(Item & item)
{
bool res = dirs.MakePath(item.parent_id, item.file_path);
bool res = dirs.MakePath(item.parent_id, item.item_content.file_path);
if( res )
{
if( !item.file_path.empty() && item.file_path[0] == '/' )
item.file_path.erase(0, 1);
if( !item.item_content.file_path.empty() && item.item_content.file_path[0] == '/' )
item.item_content.file_path.erase(0, 1);
}
else
{
@@ -897,7 +869,7 @@ size_t buffer_len = sizeof(buffer)/sizeof(wchar_t);
buffer[0] = '0';
swprintf(buffer+1, buffer_len, L"%lx", (unsigned long)item.id);
item.file_path.clear();
item.item_content.file_path.clear();
// make sure that the length is even
if( (wcslen(hash) & 1) != 0 )
@@ -905,16 +877,16 @@ size_t buffer_len = sizeof(buffer)/sizeof(wchar_t);
for(size_t i=0 ; hash[i] != 0 ; i+=2)
{
item.file_path += hash[i];
item.file_path += hash[i+1];
item.item_content.file_path += hash[i];
item.item_content.file_path += hash[i+1];
if( hash[i+2] != 0 )
item.file_path += '/';
item.item_content.file_path += '/';
}
// one character more to make sure the path is unique
// (we can have a directory without the character)
item.file_path += '_';
item.item_content.file_path += '_';
return true;
}
@@ -939,18 +911,18 @@ bool res;
if( !pmount || pmount->fs != mounts.MountFsHashfs() )
{
res = CreateNewFileSimpleFs(item);
item.file_fs = mounts.MountFsSimplefs();
item.item_content.file_fs = mounts.MountFsSimplefs();
}
else
{
res = CreateNewFileHashFs(item);
item.file_fs = mounts.MountFsHashfs();
item.item_content.file_fs = mounts.MountFsHashfs();
}
if( res )
item.file_path += item.url;
item.item_content.file_path += item.url;
else
item.file_path.clear();
item.item_content.file_path.clear();
return res;
}
@@ -968,7 +940,7 @@ bool System::MakeFilePath(const Item & item, std::wstring & path, bool thumb, bo
return false;
}
if( item.file_path.empty() || item.file_type == WINIX_ITEM_FILETYPE_NONE )
if( item.item_content.file_path.empty() || item.item_content.file_type == WINIX_ITEM_FILETYPE_NONE )
{
log << log1 << "System: MakePath: this item has not a static file" << logend;
return false;
@@ -976,7 +948,7 @@ bool System::MakeFilePath(const Item & item, std::wstring & path, bool thumb, bo
path = config->upload_dir;
if( item.file_fs == mounts.MountFsHashfs() )
if( item.item_content.file_fs == mounts.MountFsHashfs() )
path += L"/hashfs";
else
path += L"/simplefs";
@@ -988,11 +960,48 @@ bool System::MakeFilePath(const Item & item, std::wstring & path, bool thumb, bo
path += L"/normal";
if( create_dir && !CreateDirs(path, item.file_path, chmod, group, true) )
if( create_dir && !CreateDirs(path, item.item_content.file_path, chmod, group, true) )
return false;
path += '/';
path += item.file_path;
path += item.item_content.file_path;
return true;
}
bool System::MakeRelativeFilePath(const Item & item, const std::wstring & path_prefix, std::wstring & path, bool thumb)
{
path.clear();
if( item.item_content.file_path.empty() || item.item_content.file_type == WINIX_ITEM_FILETYPE_NONE )
{
log << log1 << "System: MakePath: this item has not a static file" << logend;
return false;
}
// we allow the prefix to be empty
if( !path_prefix.empty() )
{
if( path_prefix[0] != '/' )
path += '/';
path += path_prefix;
TrimLast(path, '/');
}
if( item.item_content.file_fs == mounts.MountFsHashfs() )
path += L"/hashfs";
else
path += L"/simplefs";
if( thumb )
path += L"/thumb";
else
path += L"/normal";
path += '/';
path += item.item_content.file_path;
return true;
}
@@ -1025,14 +1034,17 @@ return res;
Error System::AddFile(Item & item, int notify_code, bool call_plugins)
bool System::AddFile(Item & item, int notify_code, bool call_plugins)
{
if( item.type != Item::file )
return WINIX_ERR_FILE_EXPECTED;
Error status = db->AddItem(item);
if( status == WINIX_ERR_OK )
//Error status = db->AddItem(item);
item.set_connector(model_connector);
bool status = item.insert();
if( status )
{
log << log2 << "System: added a new file, url: " << item.url << ", id: " << item.id
<< ", parent_id: " << item.parent_id << logend;
@@ -1050,20 +1062,25 @@ return status;
Error System::EditFile(Item & item, bool with_url, int notify_code, bool call_plugins)
bool System::EditFile(Item & item, bool with_url, int notify_code, bool call_plugins)
{
if( item.type != Item::file )
return WINIX_ERR_FILE_EXPECTED;
if( cur->session && cur->session->puser )
cur->request->item.modification_user_id = cur->session->puser->id;
cur->request->item.item_content.modification_user_id = cur->session->puser->id;
else
cur->request->item.modification_user_id = -1;
cur->request->item.item_content.modification_user_id = -1;
item.SetDateModifyToNow();
Error status = db->EditItemById(item, with_url);
item.item_content.SetDateModifyToNow();
if( status == WINIX_ERR_OK )
ItemModelData item_model_data;
item_model_data.prepare_unique_url = with_url;
bool status = item.update(item_model_data);
//Error status = db->EditItemById(item, with_url);
if( status )
{
TemplatesFunctions::pattern_cacher.UpdatePattern(item);
@@ -1101,7 +1118,7 @@ return utc_time;
PT::Date System::ToLocal(const PT::Date & utc_date)
pt::Date System::ToLocal(const pt::Date & utc_date)
{
size_t tz_id;
@@ -1140,7 +1157,7 @@ return local_time;
PT::Date System::ToUTC(const PT::Date & local_date)
pt::Date System::ToUTC(const pt::Date & local_date)
{
size_t tz_id;
@@ -1184,7 +1201,17 @@ int System::FollowLink(const std::vector<Item*> & current_dir_tab, const std::ws
if( res == 1 )
{
if( db->GetItem(out_dir_tab.back()->id, name_temp, out_item) == WINIX_ERR_OK )
morm::Finder<Item> finder(model_connector);
bool status = finder.
select().
where().
eq(L"parent_id", out_dir_tab.back()->id).
eq(L"url", name_temp).
get(out_item);
//if( db->GetItem(out_dir_tab.back()->id, name_temp, out_item) == WINIX_ERR_OK )
if( status )
return 1;
else
return 2;
@@ -1213,12 +1240,12 @@ bool System::FollowAllLinksDirFound(std::vector<Item*> & out_dir_tab,
return false;
}
if( !out_dir_tab.back()->link_to.empty() )
if( !out_dir_tab.back()->item_content.link_to.empty() )
{
if( follow_dir_default )
{
if( !(stop_on_link_redirect && out_dir_tab.back()->link_redirect==1) )
link_to_temp = out_dir_tab.back()->link_to;
if( !(stop_on_link_redirect && out_dir_tab.back()->item_content.link_redirect==1) )
link_to_temp = out_dir_tab.back()->item_content.link_to;
}
}
@@ -1252,15 +1279,15 @@ bool System::FollowAllLinksFileOrSymlinkFound(std::vector<Item*> & out_dir_tab,
if( out_item.type == Item::symlink )
{
if( out_item.link_to.empty() )
if( out_item.item_content.link_to.empty() )
{
log << log1 << "System: symlink empty" << logend;
return false;
}
else
{
if( !(stop_on_link_redirect && out_item.link_redirect==1) )
link_to_temp = out_item.link_to;
if( !(stop_on_link_redirect && out_item.item_content.link_redirect==1) )
link_to_temp = out_item.item_content.link_to;
}
}
@@ -1392,8 +1419,8 @@ bool System::FollowAllLinks(const std::wstring & link_to,
cur->request->item.Clear();
cur->request->last_item = cur->request->dir_tab.back();
if( !cur->request->dir_tab.back()->link_to.empty() )
RedirectTo(cur->request->dir_tab.back()->link_to);
if( !cur->request->dir_tab.back()->item_content.link_to.empty() )
RedirectTo(cur->request->dir_tab.back()->item_content.link_to);
log << log3 << "System: current directory changed" << logend;
}
@@ -1404,12 +1431,13 @@ bool System::FollowAllLinks(const std::wstring & link_to,
cur->request->last_item = &cur->request->item;
if( cur->request->item.type == Item::symlink )
RedirectTo(cur->request->item.link_to); // cur->request->item.link_to is not empty
RedirectTo(cur->request->item.item_content.link_to); // cur->request->item.item_content.link_to is not empty
log << log3 << "System: current directory changed and the new file loaded" << logend;
}
mounts.CalcCurMount();
cur->mount = mounts.CalcCurMount(cur->request);
cur->request->mount = cur->mount;
}
else
{
@@ -1433,7 +1461,7 @@ return ok;
current limitation:
warning: the url is not prepared by PrepareUrl() (PrepareUrl is from functions)
*/
bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url, bool overwrite_existing)
bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url, const wchar_t * mime_type, bool overwrite_existing)
{
if( config->common_dir.empty() )
{
@@ -1459,27 +1487,57 @@ bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url,
return false;
}
if( db->GetItem(var->id, url, file_content_item) == WINIX_ERR_OK )
morm::Finder<Item> finder(model_connector);
file_content_item = finder.select().where().eq(L"parent_id", var->id).eq(L"url", url).get();
if( file_content_item.found() )
{
if( overwrite_existing )
db->DelItem(file_content_item);
else
if( !overwrite_existing )
return true;
file_content_item.remove();
}
file_content_item.Clear();
file_content_item.parent_id = var->id;
file_content_item.user_id = var->user_id;
file_content_item.group_id = var->group_id;
file_content_item.privileges = 07555; // !! IMPROVE ME: may it should be added as a parameter to this function?
file_content_item.item_content.user_id = var->item_content.user_id;
file_content_item.item_content.group_id = var->item_content.group_id;
file_content_item.item_content.privileges = 07555; // !! IMPROVE ME: may it should be added as a parameter to this function?
file_content_item.subject = url;
file_content_item.url = url;
file_content_item.type = Item::file;
file_content_item.html_template = config->templates_index_raw;
file_content_item.content = file_content;
file_content_item.content_type = Item::ct_other;
file_content_item.item_content.content_raw = file_content;
file_content_item.item_content.content_raw_type = ItemContent::ct_other;
return AddFile(file_content_item, false) == WINIX_ERR_OK;
if( mime_type )
file_content_item.item_content.file_mime_type = mime_type;
return AddFile(file_content_item, false);
}
void System::DeleteOldRequests(bool leave_one_object)
{
std::list<Request>::iterator i = req_tab.begin();
while( i != req_tab.end() )
{
// leave at least one object (even if it is finished)
if( (i->run_state == Request::RunState::finished || i->run_state == Request::RunState::not_assigned) && (!leave_one_object || req_tab.size() > 1) )
{
log << log3 << "System: removing a finished or not assigned request " << cur->request << logend;
std::list<Request>::iterator old_i = i;
++i;
req_tab.erase(old_i);
}
else
{
++i;
}
}
}
+19 -15
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2018, Tomasz Sowa
* Copyright (c) 2010-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,6 @@
#include "job.h"
#include "dirs.h"
#include "mounts.h"
#include "db/db.h"
#include "request.h"
#include "config.h"
#include "crypt.h"
@@ -64,7 +63,7 @@ class SessionManager;
// file system
class System : WinixModel
class System : public WinixModelDeprecated
{
public:
@@ -108,26 +107,30 @@ public:
// when winix starts
TimeZones time_zones;
// list of requests, if a request is to be continued in a job then it is preserved in the req_tab
// and a new Request is inserted for the next incoming request
std::list<Request> req_tab;
using WinixModelDeprecated::get_model_connector;
void SetCur(Cur * pcur);
//void SetConfig(Config * pconfig);
void SetDb(Db * pdb);
//void SetSynchro(Synchro * psynchro);
void SetFunctions(Functions * pfunctions);
void SetSessionManager(SessionManager * sm);
void set_dependency(WinixModel * winix_model);
void set_dependency(WinixModelDeprecated * winix_model);
void Init();
bool Init();
void AddParams(const ParamTab & param_tab, std::wstring & str, bool clear_str = true);
bool IsSSLRequired(bool try_to_use_ssl);
bool IsSSLRequired();
void PutUrlProto(bool can_use_ssl, std::wstring & str, bool clear_str = true);
void PutUrlProto(bool can_use_ssl, PT::TextStream & str, bool clear_stream = true);
void PutUrlProto(bool can_use_ssl, pt::Stream & str, bool clear_stream = true);
void PutUrlProto(std::wstring & str, bool clear_str = true);
void PutUrlProto(PT::TextStream & str, bool clear_stream = true);
void PutUrlProto(pt::Stream & str, bool clear_stream = true);
void RedirectTo(const Item & item, const wchar_t * postfix = 0, bool use_reqtype = true);
void RedirectTo(long item_id, const wchar_t * postfix = 0, bool use_reqtype = true);
@@ -176,17 +179,19 @@ public:
bool CreateNewFile(Item & item);
bool MakeFilePath(const Item & item, std::wstring & path, bool thumb = false, bool create_dir = false, int chmod = 0755, int group = -1);
bool MakeRelativeFilePath(const Item & item, const std::wstring & path_prefix, std::wstring & path, bool thumb = false);
bool MakePath(const Item & item, std::wstring & path, bool clear_path = true);
Error AddFile(Item & item, int notify_code = 0, bool call_plugins = true);
Error EditFile(Item & item, bool with_url = true, int notify_code = 0, bool call_plugins = true);
bool AddFile(Item & item, int notify_code = 0, bool call_plugins = true);
bool EditFile(Item & item, bool with_url = true, int notify_code = 0, bool call_plugins = true);
time_t ToLocal(time_t utc_time);
PT::Date ToLocal(const PT::Date & utc_date);
pt::Date ToLocal(const pt::Date & utc_date);
time_t ToUTC(time_t local_time);
PT::Date ToUTC(const PT::Date & local_date);
pt::Date ToUTC(const pt::Date & local_date);
int FollowLink(const std::vector<Item*> & current_dir_tab, const std::wstring & link_to,
@@ -206,7 +211,7 @@ public:
bool follow_dir_default = false, bool stop_on_link_redirect = false, bool check_access = true);
bool AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url, bool overwrite_existing = true);
bool AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url, const wchar_t * mime_type = nullptr, bool overwrite_existing = true);
// reloading time zones
void ReadTimeZones();
@@ -217,11 +222,11 @@ public:
void CreateItemLink(const Item & item, std::wstring & link, bool clear_str = true);
void DeleteOldRequests(bool leave_one_object = false);
private:
Cur * cur;
Db * db;
//Config * config;
//Synchro * synchro;
Functions * functions;
@@ -237,7 +242,6 @@ private:
std::vector<Item*> root_follow_dir_tab;
Item temp_follow_item;
bool HasAccess(const Item & item, int mask);
int NewPrivileges(int creation_mask);
bool CreateNewFileSimpleFs(Item & item);
-556
View File
@@ -1,556 +0,0 @@
/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_textstream
#define headerfile_winix_core_textstream
#include <string>
#include <ctime>
#include "misc.h"
#include "space/space.h"
#include "date/date.h"
#include "textstream/textstream.h"
#include "utf8/utf8.h"
namespace Winix
{
/*
a special class representing a stream buffer
similar to std::ostringstream
StringType can be either std::string or std::wstring
this class uses UTF-8 <-> wide characters conversions:
if StringType is std::string:
operator<<(const char*) only copies the input string
operator<<(const wchar_t*) converts from wide characters to UTF-8
(similary for an operator with std::string and std::wstring)
if StringType is std::wstring:
operator<<(const char*) converts from UTF-8 to wide characters
operator<<(const wchar_t*) only copies the input string
(similary for an operator with std::string and std::wstring)
*/
template<class StringType>
class TextStream
{
public:
typedef typename StringType::value_type CharType;
typedef typename StringType::value_type char_type;
void Clear();
bool Empty() const;
size_t Size() const;
void Reserve(size_t len);
const StringType & Str() const;
const CharType * CStr() const;
void Str(const StringType & str);
void Str(const StringType && str);
CharType operator[](size_t index);
TextStream & operator<<(const char * str);
TextStream & operator<<(const std::string * str);
TextStream & operator<<(const std::string & str);
TextStream & operator<<(const wchar_t * str);
TextStream & operator<<(const std::wstring * str);
TextStream & operator<<(const std::wstring & str);
TextStream & operator<<(char);
TextStream & operator<<(wchar_t);
TextStream & operator<<(int);
TextStream & operator<<(long);
TextStream & operator<<(unsigned int);
TextStream & operator<<(unsigned long);
TextStream & operator<<(double);
TextStream & operator<<(const void *);// printing a pointer
TextStream & operator<<(const PT::Space & space);
TextStream & operator<<(const PT::Date & date);
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
TextStream & operator<<(const PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
TextStream & Write(const char * buf, size_t len);
TextStream & Write(const wchar_t * buf, size_t len);
TextStream & write(const char * buf, size_t len); // for compatibility with standard library (Ezc uses it)
TextStream & write(const wchar_t * buf, size_t len);
protected:
StringType buffer;
void Convert(wchar_t c, std::string & dst);
void Convert(wchar_t c, std::wstring & dst);
void Convert(const char * src, size_t len, std::wstring & dst);
void Convert(const char * src, std::wstring & dst);
void Convert(const std::string & src, std::wstring & dst);
void Convert(const wchar_t * src, size_t len, std::string & dst);
void Convert(const wchar_t * src, std::string & dst);
void Convert(const std::wstring & src, std::string & dst);
void Convert(const char * src, size_t len, std::string & dst);
void Convert(const char * src, std::string & dst);
void Convert(const std::string & src, std::string & dst);
void Convert(const wchar_t * src, size_t len, std::wstring & dst);
void Convert(const wchar_t * src, std::wstring & dst);
void Convert(const std::wstring & src, std::wstring & dst);
};
template<class StringType>
void TextStream<StringType>::Clear()
{
buffer.clear();
}
template<class StringType>
bool TextStream<StringType>::Empty() const
{
return buffer.empty();
}
template<class StringType>
size_t TextStream<StringType>::Size() const
{
return buffer.size();
}
template<class StringType>
void TextStream<StringType>::Reserve(size_t len)
{
buffer.reserve(len);
}
template<class StringType>
const StringType & TextStream<StringType>::Str() const
{
return buffer;
}
template<class StringType>
const typename TextStream<StringType>::CharType * TextStream<StringType>::CStr() const
{
return buffer.c_str();
}
template<class StringType>
void TextStream<StringType>::Str(const StringType & str)
{
buffer = str;
}
template<class StringType>
void TextStream<StringType>::Str(const StringType && str)
{
buffer = str;
}
template<class StringType>
typename TextStream<StringType>::CharType TextStream<StringType>::operator[](size_t index)
{
return buffer[index];
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const char * str)
{
Convert(str, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const std::string * str)
{
Convert(*str, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const std::string & str)
{
Convert(str, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const wchar_t * str)
{
Convert(str, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const std::wstring * str)
{
Convert(*str, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const std::wstring & str)
{
Convert(str, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(char v)
{
/*
* there is no any possibility to treat 'v' as UTF-8 character if we have got
* only one character so we only copy it
*/
buffer += v;
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(wchar_t v)
{
Convert(v, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(int v)
{
wchar_t buf[50];
size_t len = sizeof(buf) / sizeof(wchar_t);
Toa(v, buf, len);
Convert(buf, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(long v)
{
wchar_t buf[50];
size_t len = sizeof(buf) / sizeof(wchar_t);
Toa(v, buf, len);
Convert(buf, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(unsigned int v)
{
wchar_t buf[50];
size_t len = sizeof(buf) / sizeof(wchar_t);
Toa(v, buf, len);
Convert(buf, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(unsigned long v)
{
wchar_t buf[50];
size_t len = sizeof(buf) / sizeof(wchar_t);
Toa(v, buf, len);
Convert(buf, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(double v)
{
char buf[50];
sprintf(buf, "%f", v);
Convert(buf, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const void * v)
{
wchar_t buf[50];
size_t len = sizeof(buf) / sizeof(wchar_t);
buf[0] = '0';
buf[1] = 'x';
Toa(reinterpret_cast<unsigned long>(v), buf+2, len-2, 16);
Convert(buf, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::Write(const char * buf, size_t len)
{
Convert(buf, len, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::write(const char * buf, size_t len)
{
return Write(buf, len);
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::Write(const wchar_t * buf, size_t len)
{
Convert(buf, len, buffer);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::write(const wchar_t * buf, size_t len)
{
return Write(buf, len);
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const PT::Space & space)
{
space.Serialize(*this, true, false);
return *this;
}
template<class StringType>
TextStream<StringType> & TextStream<StringType>::operator<<(const PT::Date & date)
{
date.Serialize(*this);
return *this;
}
template<class StringType>
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
TextStream<StringType> & TextStream<StringType>::operator<<(
const PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg)
{
typename PT::TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size>::const_iterator i;
for(i=arg.begin() ; i != arg.end() ; ++i)
buffer += static_cast<char_type>(*i);
return *this;
}
template<class StringType>
void TextStream<StringType>::Convert(wchar_t c, std::string & dst)
{
PT::IntToUTF8((int)c, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(wchar_t c, std::wstring & dst)
{
dst += c;
}
template<class StringType>
void TextStream<StringType>::Convert(const char * src, size_t len, std::wstring & dst)
{
PT::UTF8ToWide(src, len, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(const char * src, std::wstring & dst)
{
PT::UTF8ToWide(src, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(const std::string & src, std::wstring & dst)
{
PT::UTF8ToWide(src, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(const wchar_t * src, size_t len, std::string & dst)
{
PT::WideToUTF8(src, len, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(const wchar_t * src, std::string & dst)
{
PT::WideToUTF8(src, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(const std::wstring & src, std::string & dst)
{
PT::WideToUTF8(src, dst, false);
}
template<class StringType>
void TextStream<StringType>::Convert(const char * src, size_t len, std::string & dst)
{
// we suppose that append is smart enough and we don't have to use reserve()
dst.append(src, len);
}
template<class StringType>
void TextStream<StringType>::Convert(const char * src, std::string & dst)
{
size_t len;
for(len=0 ; src[len] ; ++len){}
Convert(src, len, dst);
}
template<class StringType>
void TextStream<StringType>::Convert(const std::string & src, std::string & dst)
{
dst.append(src);
}
template<class StringType>
void TextStream<StringType>::Convert(const wchar_t * src, size_t len, std::wstring & dst)
{
// we suppose that append is smart enough and we don't have to use reserve()
dst.append(src, len);
}
template<class StringType>
void TextStream<StringType>::Convert(const wchar_t * src, std::wstring & dst)
{
size_t len;
for(len=0 ; src[len] ; ++len){}
Convert(src, len, dst);
}
template<class StringType>
void TextStream<StringType>::Convert(const std::wstring & src, std::wstring & dst)
{
dst.append(src);
}
} // namespace Winix
#endif
+56 -25
View File
@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2019, Tomasz Sowa
* Copyright (c) 2011-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ sigset_t set;
void ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
bool ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
{
thread_tab.emplace_back();
ThreadItem & item = thread_tab.back();
@@ -82,20 +82,45 @@ void ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
item.object->set_dependency(this);
// main log buffer (from the main thread)
item.object->set_main_log_buffer(log.GetLogBuffer());
item.object->set_main_file_log(log.GetFileLog());
item.object->set_main_log_buffer(log.get_log_buffer());
item.object->set_main_file_log(log.get_file_log());
// the logger buffer and model_connector are different
item.object->set_log_buffer(&data.log_buffer);
//data.postgresql_connector.set_logger(logger);
data.postgresql_connector.set_conn_param(config->db_database, config->db_user, config->db_pass);
if( !config->db_conn_string.empty() )
data.postgresql_connector.set_conn_param(config->db_conn_string);
else
data.postgresql_connector.set_conn_param(config->db_host, config->db_hostaddr, config->db_port, config->db_database, config->db_user, config->db_pass);
data.postgresql_connector.set_logger(item.object->get_logger());
data.postgresql_connector.set_log_queries(config->log_db_query);
data.postgresql_connector.wait_for_connection();
if( !data.postgresql_connector.wait_for_connection(config->db_startup_connection_max_attempts, config->db_startup_connection_attempt_delay) )
{
Log * plog = item.object->get_logger();
(*plog) << logsave;
return false;
}
data.model_connector.set_db_connector(data.postgresql_connector);
data.model_connector.set_flat_connector(data.json_connector);
data.model_connector.set_logger(item.object->get_logger());
data.model_connector.set_winix_config(config);
data.model_connector.set_winix_request(nullptr);
data.model_connector.set_winix_logger(item.object->get_logger());
data.model_connector.set_winix_dirs(nullptr);
data.model_connector.set_winix_mounts(nullptr);
data.model_connector.set_winix_users(nullptr);
data.model_connector.set_winix_groups(nullptr);
data.model_connector.set_winix_session(nullptr);
data.model_connector.set_winix_locale(nullptr); // null for a moment, may will be changed
data.model_connector.set_winix_session_manager(nullptr);// null for a moment, may will be changed
data.model_connector.set_winix_time_zones(nullptr); // null for a moment, may will be changed
data.model_connector.set_winix_pattern_cacher(nullptr); // null for a moment, may will be changed
item.object->set_main_model_connector(get_model_connector());
item.object->set_model_connector(&data.model_connector);
if( were_started )
@@ -107,31 +132,33 @@ void ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
log << log4 << "TM: added a thread to the queue, number: " << (thread_tab.size()-1)
<< ", name: " << thread_name << logend;
}
return true;
}
void ThreadManager::Add(BaseThread & pbase, const wchar_t * thread_name)
bool ThreadManager::Add(BaseThread & pbase, const wchar_t * thread_name)
{
Add(&pbase, thread_name);
return Add(&pbase, thread_name);
}
void ThreadManager::Add(BaseThread * pbase, const std::wstring & thread_name)
bool ThreadManager::Add(BaseThread * pbase, const std::wstring & thread_name)
{
Add(pbase, thread_name.c_str());
return Add(pbase, thread_name.c_str());
}
void ThreadManager::Add(BaseThread & pbase, const std::wstring & thread_name)
bool ThreadManager::Add(BaseThread & pbase, const std::wstring & thread_name)
{
Add(&pbase, thread_name.c_str());
return Add(&pbase, thread_name.c_str());
}
void ThreadManager::StartAll()
{
synchro->Lock();
Winix::Lock lock(synchro);
int id = 0;
for(ThreadItem & item : thread_tab)
@@ -140,7 +167,7 @@ void ThreadManager::StartAll()
id += 1;
}
synchro->Unlock();
lock.Unlock();
were_started = true;
}
@@ -165,28 +192,32 @@ void ThreadManager::StopAll()
if( !were_started )
return;
// WakeUpThread() should be used with Lock/Unlock
synchro->Lock();
for(ThreadItem & item : thread_tab)
{
item.object->WakeUpThread();
Winix::Lock lock(synchro);
for(ThreadItem & item : thread_tab)
{
// WakeUpThread() should be used with Lock/Unlock
item.object->WakeUpThread();
}
}
synchro->Unlock();
int id = 0;
for(ThreadItem & item : thread_tab)
{
log << log4 << "TM: waiting for thread " << id << " (" << item.object->ThreadId()
<< ", name: " << item.name << ")" << logend;
<< ", name: " << item.name << ")" << logend << logsave;
item.object->WaitForThread();
log << log4 << "TM: thread " << id << " terminated" << logend;
log << log4 << "TM: thread " << id << " terminated" << logend << logsave;
// the thread is stopped and we can set the thread log buffer pointing to
// the main log buffer (from the main thread)
item.object->set_log_buffer(log.get_log_buffer());
delete item.thread_item_data;
item.thread_item_data = nullptr;
id += 1;
}

Some files were not shown because too many files have changed in this diff Show More