cppcms-users Mailing List for CppCMS C++ Web Framework (Page 93)
Brought to you by:
artyom-beilis
You can subscribe to this list here.
2009 |
Jan
|
Feb
(22) |
Mar
|
Apr
(3) |
May
|
Jun
(4) |
Jul
|
Aug
|
Sep
|
Oct
(15) |
Nov
(16) |
Dec
(13) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2010 |
Jan
(4) |
Feb
|
Mar
(8) |
Apr
(8) |
May
(8) |
Jun
(36) |
Jul
(63) |
Aug
(126) |
Sep
(47) |
Oct
(66) |
Nov
(46) |
Dec
(42) |
2011 |
Jan
(87) |
Feb
(24) |
Mar
(54) |
Apr
(21) |
May
(22) |
Jun
(18) |
Jul
(22) |
Aug
(101) |
Sep
(57) |
Oct
(33) |
Nov
(34) |
Dec
(66) |
2012 |
Jan
(64) |
Feb
(76) |
Mar
(73) |
Apr
(105) |
May
(93) |
Jun
(83) |
Jul
(84) |
Aug
(88) |
Sep
(57) |
Oct
(59) |
Nov
(35) |
Dec
(49) |
2013 |
Jan
(67) |
Feb
(17) |
Mar
(49) |
Apr
(64) |
May
(87) |
Jun
(64) |
Jul
(93) |
Aug
(23) |
Sep
(15) |
Oct
(16) |
Nov
(62) |
Dec
(73) |
2014 |
Jan
(5) |
Feb
(23) |
Mar
(21) |
Apr
(11) |
May
(1) |
Jun
(19) |
Jul
(27) |
Aug
(16) |
Sep
(5) |
Oct
(37) |
Nov
(12) |
Dec
(9) |
2015 |
Jan
(7) |
Feb
(7) |
Mar
(44) |
Apr
(28) |
May
(5) |
Jun
(12) |
Jul
(8) |
Aug
|
Sep
(39) |
Oct
(34) |
Nov
(30) |
Dec
(34) |
2016 |
Jan
(66) |
Feb
(23) |
Mar
(33) |
Apr
(15) |
May
(11) |
Jun
(15) |
Jul
(26) |
Aug
(4) |
Sep
(1) |
Oct
(30) |
Nov
(10) |
Dec
|
2017 |
Jan
(52) |
Feb
(9) |
Mar
(24) |
Apr
(16) |
May
(9) |
Jun
(12) |
Jul
(33) |
Aug
(8) |
Sep
|
Oct
(1) |
Nov
(2) |
Dec
(6) |
2018 |
Jan
(5) |
Feb
|
Mar
|
Apr
|
May
(14) |
Jun
(1) |
Jul
(9) |
Aug
(1) |
Sep
(13) |
Oct
(8) |
Nov
(2) |
Dec
(2) |
2019 |
Jan
(1) |
Feb
(1) |
Mar
(3) |
Apr
(3) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
|
2020 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
(9) |
Jul
(6) |
Aug
(25) |
Sep
(10) |
Oct
(10) |
Nov
(6) |
Dec
|
2021 |
Jan
|
Feb
|
Mar
(7) |
Apr
(1) |
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
(9) |
Oct
(1) |
Nov
|
Dec
|
2022 |
Jan
|
Feb
|
Mar
|
Apr
(3) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: william l. <we...@gm...> - 2012-03-21 12:08:27
|
Hi, I read the roadmap of CppCMS, it looks like current version's embedded web server does not support HTTPS. http://cppcms.com/wikipp/en/page/cppcms_1x_tasks#Implement.HTTPS.support I have a basic question regarding that. For example, if a website support HTTPS. Then it should use SSL certificate, and signed, verified by 3rd organization, like Verisign. And this SSL should bind to domain. We can create self signed security, but browser will pop up a SSL warning page/dialog while loading the https site. The question is, what if I want to create a embedded HTTPS server, running on localhost and accept request from localhost. How can I provide the certificate to this HTTPs site? I guess Verisign will not provide any ssl info bind to Localhost domain:) So how can I make sure web browser request to localhost:443 via HTTPS will not pop up SSL warning page/dialog? Thanks, William L. |
From: Artyom B. <art...@ya...> - 2012-03-21 08:13:20
|
> Thanks for response. > I have tried it with the same skin name across all views, > but It just does not produce anything. Each cppcms template compilation unit should have its own skin name. It is actually namespace - the module. You should for course have different view names (classes) withing the same skin but view names can be shared between different skins (namespaces) You can define skin name by two methods: - using <% skin NAME %> - using -s NAME flag for cppcms_tmpl_cc > > As soon as I supply different name for each view, it works fine. Can you show the code - the pattern you use > Should I include the skin name in the config.js or ... ? If you create **dynamically loadable** view than yes, if it is statically linked then: If you have multiple skins you man need to define only the default one > I cannot really see what is wrong as the views are > working fine with distinct skin names. > Each compilation unit created by cppcms_tmpl_cc should have distinct skin names > >Any suggestions. >Thanks, > > More pointers: http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hello_templates http://cppcms.com/wikipp/en/page/cppcms_1x_tut_templates_inheritance http://cppcms.com/wikipp/en/page/cppcms_1x_templates_gen http://cppcms.com/wikipp/en/page/cppcms_1x_config#views Artyom Beilis |
From: Jan V. <jan...@gm...> - 2012-03-21 07:01:22
|
Hi Marcel, Thanks for response. I have tried it with the same skin name across all views, but It just does not produce anything. As soon as I supply different name for each view, it works fine. Should I include the skin name in the config.js or ... ? I cannot really see what is wrong as the views are working fine with distinct skin names. Any suggestions. Thanks, Jan On Tue, Mar 20, 2012 at 8:42 AM, Marcel Hellwig <ke...@co...> wrote: > Am 20.03.2012 08:51, schrieb Jan Vlasak: > > Hi, > > > > I would like to ask whether there is a way of specifying only one skin > > for all views. I found an example in the message_board but these views > > are dynamically linked and I need them static. > > When I try and remove the config section "views" and run the > > application, it does not produce any output (blank page). > I hope you included them in the make /CMake file (whatever) Look at this > > http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hello_templates#Linking.Statically > > The specific view is rendered by: render("view_name", model) > > The view looks like this: > > <% c++ #include "model.h" %> > > <% xhtml %> > > <% skin %> > > <% view view_name uses Model %> > > <% template render() %> > > ......... > > <% end template %> > > <% end view %> > > <% end skin %> > > > What's wrong about this? Afaik you do not must name your skin, but I > really would prefer it? Why don't you name it and then stay with that > name all the time? This is how I do it often, with little projects. > > Thank you > > > > Jan Vlasak > Marcel > > > ------------------------------------------------------------------------------ > This SF email is sponsosred by: > Try Windows Azure free for 90 days Click Here > http://p.sf.net/sfu/sfd2d-msazure > _______________________________________________ > Cppcms-users mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cppcms-users > -- Jan Vlasak Flat 2 39 Hurst Lane Birmingham B34 7HS ph.:+44 754 6124920 |
From: Marcel H. <ke...@co...> - 2012-03-20 08:43:16
|
Am 20.03.2012 08:51, schrieb Jan Vlasak: > Hi, > > I would like to ask whether there is a way of specifying only one skin > for all views. I found an example in the message_board but these views > are dynamically linked and I need them static. > When I try and remove the config section "views" and run the > application, it does not produce any output (blank page). I hope you included them in the make /CMake file (whatever) Look at this http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hello_templates#Linking.Statically > The specific view is rendered by: render("view_name", model) > The view looks like this: > <% c++ #include "model.h" %> > <% xhtml %> > <% skin %> > <% view view_name uses Model %> > <% template render() %> > ......... > <% end template %> > <% end view %> > <% end skin %> > What's wrong about this? Afaik you do not must name your skin, but I really would prefer it? Why don't you name it and then stay with that name all the time? This is how I do it often, with little projects. > Thank you > > Jan Vlasak Marcel |
From: Jan V. <jan...@ap...> - 2012-03-20 07:52:09
|
Hi, I would like to ask whether there is a way of specifying only one skin for all views. I found an example in the message_board but these views are dynamically linked and I need them static. When I try and remove the config section "views" and run the application, it does not produce any output (blank page). The specific view is rendered by: render("view_name", model) The view looks like this: <% c++ #include "model.h" %> <% xhtml %> <% skin %> <% view view_name uses Model %> <% template render() %> ......... <% end template %> <% end view %> <% end skin %> Thank you Jan Vlasak |
From: Artyom B. <art...@ya...> - 2012-03-16 20:42:05
|
> >But still my problem is that i want to specific different log level for >different handlers (the sinks in your way) >I may try to include them. Are you interested in or do you want to make >them on your own? It's up to you. You may create a filter sink that would be kind of "tee" device that can split a sink to different sinks... That may be nice. > >Also i uploaded the diff for the sinks. >https://sourceforge.net/tracker/index.php?func=detail&aid=3505317&group_id=209965&atid=1011837 > Applied, I changed an interfaces a little bit and made it more consistent with the CppCMS coding standards. >also you haven't answered or implemented my patch i submitted a month ago! >https://sourceforge.net/tracker/?func=detail&aid=3488226&group_id=209965&atid=1011837 > >come on... they are just whitespaces! (: > Fixed as well. Best, Artyom |
From: sergey l. <ccp...@gm...> - 2012-03-15 19:41:32
|
Wow! Great work! Thank you! On Thu, Mar 15, 2012 at 1:31 PM, Artyom Beilis <art...@ya...> wrote: > Hello, > > I discovered an easy way to build binary RPMs - Open Build Service. > > Now you can use repositories from there: > > http://download.opensuse.org/repositories/home:/artyom-beilis/ > > Enjoy, > > > Artyom Beilis > -------------- > CppCMS - C++ Web Framework: http://cppcms.com/ > CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ > > > > ------------------------------------------------------------------------------ > This SF email is sponsosred by: > Try Windows Azure free for 90 days Click Here > http://p.sf.net/sfu/sfd2d-msazure > _______________________________________________ > Cppcms-users mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cppcms-users > |
From: Marcel H. <ke...@co...> - 2012-03-15 15:55:02
|
ahh (: a light-bulb in front of me. the module is this BOOSTER_DEBUG("foo") << "bar"; ------ But still my problem is that i want to specific different log level for different handlers (the sinks in your way) I may try to include them. Are you interested in or do you want to make them on your own? It's up to you. Also i uploaded the diff for the sinks. https://sourceforge.net/tracker/index.php?func=detail&aid=3505317&group_id=209965&atid=1011837 also you haven't answered or implemented my patch i submitted a month ago! https://sourceforge.net/tracker/?func=detail&aid=3488226&group_id=209965&atid=1011837 come on... they are just whitespaces! (: Regards Marcel |
From: Marcel H. <ke...@co...> - 2012-03-15 15:24:15
|
so if i guess it right: - a level is not sink specific, it's dependent on the message that should be logged. - a sink is the backend of the logger - every message goes to the logger and then to every sink. My idea is to implement a sink specifiec logger level, that means you register a sink l.add_sink(fsink, debug); l.add_sink(csink, error); with the error level. What does it mean: The responsibolity of logging is not in the message itself but in the registered sink. You don't have to check if the message itself should be logged, but if a sink is registered that has this loglevel (or above of course) You also may specific a name, instead of a pointer for a registered sink, f.e. fsink.name("fileLogger"); csink.name("ConsoleLogger"); My inspiration is the logger util from java which I really like. http://docs.oracle.com/javase/1.4.2/docs/api/java/util/logging/Logger.html The hirachy is optional but I like the concept. Regards, Marcel |
From: Artyom B. <art...@ya...> - 2012-03-15 12:44:41
|
> I don't get it. > If I write something like this: > > using namespace booster::log; > booster::shared_ptr<sinks::file> fsink(new sinks::file()); > fsink->open("server.log"); > fsink->max_files(2); > booster::shared_ptr<sinks::standard_error> csink(new > sinks::standard_error()); > > logger::instance().add_sink(fsink); > logger::instance().add_sink(csink); > > because I want to different log levels, which one is which? :D so how do > I edit the level of fsink and csink separate? Which module should i > declare? Wouldn't it be easier to hand a pointer to the method?! > The question to log or not to log decided on the logger level and not on the sink level. For example: BOOSTER_DEBUG("foo") << "This " << foo.heavy_value(); In normal (non-debug) mode the "foo.heavy_value()" would not be evaluated. Note, you can set logging level per module such that "foo" module would be logged for everything (debug) and "bar" module would be logged only for errors. The sinks are just allow to write to different locations, for example to both syslog and file or something like that. Of course you can do (if you want to) some filtering on sink level as well, but it is not its purpose. Just override the log(message const &) member function of a sink. Artyom Beilis |
From: Marcel H. <ke...@co...> - 2012-03-15 12:30:43
|
>> and two other questions: >> - what is the const char *module in should_be_logged, set_log_level >> and so on? It's a "string", of course, but where do I get the string for >> my sink?! > > This string is module name so you write: > > BOOSTER_WARNING("bank")<< "We run out of money"; > > This is handled automatically by macros for you. > > This string is a part of the message object. I don't get it. If I write something like this: using namespace booster::log; booster::shared_ptr<sinks::file> fsink(new sinks::file()); fsink->open("server.log"); fsink->max_files(2); booster::shared_ptr<sinks::standard_error> csink(new sinks::standard_error()); logger::instance().add_sink(fsink); logger::instance().add_sink(csink); because I want to different log levels, which one is which? :D so how do I edit the level of fsink and csink separate? Which module should i declare? Wouldn't it be easier to hand a pointer to the method?! Marcel |
From: Artyom B. <art...@ya...> - 2012-03-15 10:53:32
|
> >hi everyone, > >I'm searching for a good logger tool for c++ and found (oh what a >wonder) booster::log. >It's simple and powerfull. Nice to handle and everything. I found >boost.log too but can't install it, because I don't know how :D (funny, >isn't it?) Boost.Log passed a formal review about a year ago but needs lots of updates and meanwhile it is not ready. >Would it be possible to add two things?! > - add a constructor for sinks::file which takes the file name as a > parameter and optionally the max files? It would be easier to construct > this, because you don't have to create a pointer (or whatever) first and > then hand it over to the logger 1. You will still need to write something like booster::log::logger::instance().add_skink(booster::shared_ptr<booster::log::sink>(new booster::log::sinks::file(...))); 2. If you are using logger with CppCMS - it can configure it for you automatically: http://cppcms.com/wikipp/en/page/cppcms_1x_config#logging 3. Yes I can add an option :-), fill a request feature ticket or send a patch. > - add a constructor to sinks::standard_error which takes a ostream as >parameter. Maybe you define an other class that does this. The standard_error sink is defined as simple as that: class standard_error : public booster::log::sink { public: void standard_error::log(message const &msg) { std::cerr << format_plain_text_message(msg) << std::endl; } }; So just write your own sink :-) > >and two other questions: > - what is the const char *module in should_be_logged, set_log_level > and so on? It's a "string", of course, but where do I get the string for > my sink?! This string is module name so you write: BOOSTER_WARNING("bank") << "We run out of money"; This is handled automatically by macros for you. This string is a part of the message object. > - Is it true, that I can only use booster without cppcms and that it's >licended under the boost license? > Yes, it is true. Booster is an answer of my needs from Boost that boost does not allow me to handle properly, that is why Booster has the same license as Boost. >Regards, > >Marcel Hellwig > Regards, Artyom Beilis |
From: Marcel H. <ke...@co...> - 2012-03-15 10:29:43
|
hi everyone, I'm searching for a good logger tool for c++ and found (oh what a wonder) booster::log. It's simple and powerfull. Nice to handle and everything. I found boost.log too but can't install it, because I don't know how :D (funny, isn't it?) So two major questions. Would it be possible to add two things?! - add a constructor for sinks::file which takes the file name as a parameter and optionally the max files? It would be easier to construct this, because you don't have to create a pointer (or whatever) first and then hand it over to the logger - add a constructor to sinks::standard_error which takes a ostream as parameter. Maybe you define an other class that does this. and two other questions: - what is the const char *module in should_be_logged, set_log_level and so on? It's a "string", of course, but where do I get the string for my sink?! - Is it true, that I can only use booster without cppcms and that it's licended under the boost license? Regards, Marcel Hellwig |
From: Artyom B. <art...@ya...> - 2012-03-15 09:31:49
|
Hello, I discovered an easy way to build binary RPMs - Open Build Service. Now you can use repositories from there: http://download.opensuse.org/repositories/home:/artyom-beilis/ Enjoy, Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ |
From: Artyom B. <art...@ya...> - 2012-03-14 13:50:00
|
CppCMS 1.0.1 Released - a bug fix release. http://blog.cppcms.com/post/103 Note, now source RPM is available on sourceforge making it much simpler to create proper rpms for your own distributions Artyom Beilis -------------- CppCMS - C++ Web Framework: http://cppcms.com/ CppDB - C++ SQL Connectivity: http://cppcms.com/sql/cppdb/ |
From: Artyom B. <art...@ya...> - 2012-03-09 16:41:55
|
> > > Hello Artyom, > > I cannot compile the latest trunk (1.1.0): > > CMake Error at CMakeLists.txt:653 (add_executable): > Cannot find source file: > tests/todec_test.cpp > http://cppcms.svn.sourceforge.net/viewvc/cppcms/framework/trunk/CMakeLists.txt?r1=2141&r2=2142& > > Apparently, the file hasn't been committed to the svn repository. > Fixed. I had noticed this due to obvious: http://cppcms.com/files/nightly-build-report.html But had no time to commit yet. Now fixed in trunk. Artyom |
From: augustin <aug...@ov...> - 2012-03-08 20:30:11
|
Hello Artyom, I cannot compile the latest trunk (1.1.0): CMake Error at CMakeLists.txt:653 (add_executable): Cannot find source file: tests/todec_test.cpp http://cppcms.svn.sourceforge.net/viewvc/cppcms/framework/trunk/CMakeLists.txt?r1=2141&r2=2142& Apparently, the file hasn't been committed to the svn repository. Augustin. -- Friends: http://www.reuniting.info/ My projects: http://astralcity.org/ http://3enjeux.overshoot.tv/ http://linux.overshoot.tv/ http://overshoot.tv/ http://charityware.info/ http://masquilier.org/ http://openteacher.info/ http://minguo.info/ http://www.wechange.org/ http://searching911.info/ . |
From: Artyom B. <art...@ya...> - 2012-03-07 15:25:44
|
>> It was just an example >> >> However, if you call <% render ... %> from the view it renders to the >> output stream without intermediate buffers. > > My plugin has a print(ostream& ) function and the print() is wrapped in a > cppcms::filters::streamable main which is printed by <%= main | raw %>. > There should also be no intermediate buffer, or? > Yep >> I think you had not added m_form.x to m_form (using m_form.add(x)); >> so when you access x.value() it appears not to be loaded when you >> call load(app.context()); > > You are completely right! > Thanks a lot! > I suggest to change the text "Value was not loaded" to something like > "The > value or the parent was not loaded. Check the hierarchy." ;) > Ok... It may not always be the case but I'll take a look on i. >>> Is there some explanation how this works if multiple applications are >>> mounted at the same root? >> >> The behavior is undefined for `cppcms::application_pool` > > Mmmh, but exactly this happens when you use the file server? > It is also mounted at "". > Note, CppCMS HTTP server requires a set of script names that are valid. The invalid script name would be "" - i.e. the script name that could not be found and internal file server is mounted to it. It still uniquely defines it. So do not relay on this behavior, create mutually exclusive mount points. And for most of cases it is better to have one hierarchy and mount entirly different applications to different mount points. I mean if you add a new application it is better to add it as sub-application to the hierarchy then add it to the new mount point. > >>>> Because when you map sub-application and refer to it >>>> you automatically referred to the default URL >>>> of the sub-application - empty one "empty key" >>> >>> Sorry, I do not understand this statement. >>> > > How does the <% url ... %> using syntax work? > > Why does <% url "/blog/post" using slug %> resolves to > "/myblog/Hi%20%3cyou%3e/" > (see http://cppcms.com/wikipp/en/page/cppcms_1x_templates_comm#URL.Mapping) > > I would rather expect /blog/post/Hi%20%3cyou%3e/? > See, it is YOUR urls design, it is rendered the way you define it. You do not have to name applications and URLs the same way (of course it is good idea to be consistent) Remember there is: URL format and Application Hierarchy they do not have to be the same. > Both > <% url "/gui/system" %> > <% url "system" %> > work without problem, but I could not figure out how to resolve a variable > containing "system"? > > E.g. <% url "/gui/" using menu_element.m_href %> does not work? > What do you mean? > >> when you call url("foo") it looks for the object named > "foo" >> >> If it is actual function (not sub application) it provides a url >> >> if it is subapplication it tries to dispatch the "" key. > > Ok, I think I understand the approach now much better. > > I still can't figure out the details between: > url("") > url(".") > url("/") > > while the first two seem to be equivalent, url("/") seems to link to > the > same url where the request() came from? No "/" - means default URL of the topmost application - root, the "." and "" refer to CURRENT application, i.e. the application that calls url() or render() that uses <% url ... %> If the path does not begin with "/" then relative URLs are sed. > e.g. when I request http://localhost:10000/gui/wrong_url > url("/") resolves to http://localhost:10000/gui/wrong_url > but url("") and url(".") resolves to > http://localhost:10000/gui > > When I use > dispatcher().assign("", &GUI::show_error_page, this); > mapper().assign("/"); // changed here instead of "" > See you are not consistent > dispatcher().assign("", &GUI::show_error_page, this); This would map show_error_page to some empty ending. > mapper().assign("/"); // changed here instead of "" Would create "/" as ending != "", In your case if the "show_error_page" is the default URL for the application then you should call mapper().assign(""); > the urls resolve to: > url("/") -> http://localhost:10000/gui/wrong_url > url(".") -> http://localhost:10000/gui/ > url("") -> http://localhost:10000/gui/ > Because "/" does not go to GUI but rather GUI's parent (topmost) > > Thanks, I think I do not need parameters, because I prefer to have > user/browser specific language and not by url. > Parameters rather define some named resource like /post/124 then the formatting would be "/post/{1}" and you would call url("post,124); >> Actually, wikipp was written before URL-mapper existed and I had >> no time to update it. Take a look rather on the cppcms's blog >> it uses url mapper fully. > > Ok, so I think the examples you gave in this mail are perfect! > Not sure so how to make it even more clear, because I assume more question will come. Artyom |
From: Markus R. <us...@ma...> - 2012-03-07 14:45:35
|
Hi! Thanks for your detailled answer! The problems with the plugin and localization are now resolved, too. Artyom Beilis wrote: >>> my_stream.imbue(context().locale()); >> >>That is working. >> >>I was asking myself how the booster::locale::translate is working within >>plugins. In the main program translate() is working, but not in the >>plugins. I did not called std::locale::global(gen("")); >> > > See: > > stream << booster::locale::translate("foo") > > Works because actual translation is postponed to the > stage were the data is written to the stream and rendered withing it. > > booster::locale::translate-> booster::locale::message + std::ostream's > locale gives translation. > > So if you want to use locale for your plugin you need to have some locale > context. It can be done by > > std::string translated = app.translate("foo"); > > or use locale explicitly as: > > std::locale loc = app.context().locale(); > std::string translated = booster::locale::translate("foo").str(loc); > > > or > > std::locale loc = app.context().locale(); > std::string translated = booster::locale::gettext("foo",loc); > > > Of course if your application uses only one language globally > you can just set std::locale::global. Thanks, I think we now have every option available. I found a method for every problem! >>But if it does not work well - see problem below - I may change to use >>render() template. I do not understand the "With the command render" >>example: In std::string main_html(cppcms::applicatin *app) the plugin >>still renders to a buffer and returs the string, so what is the >>difference? >> > > It was just an example > > However, if you call <% render ... %> from the view it renders to the > output stream without intermediate buffers. My plugin has a print(ostream& ) function and the print() is wrapped in a cppcms::filters::streamable main which is printed by <%= main | raw %>. There should also be no intermediate buffer, or? >>E.g. I have the following code: > >> >>17 void My_plugin::do(std::ostream & buf, cppcms::application & app) >>18 { >>19 if(app.request().request_method()=="POST") >>20 { >>21 m_main.m_form.load(app.context()); >>22 m_main.m_form.validate(); >>23 ::std::cout << "x is: " << m_main.m_form.x.value() << >>std::endl; >>24 m_main.m_form.clear(); >>25 } >>26 >>27 app.render("plugin_skin","main_html",buf,m_main); >>28 } >> >>Then I get following exception: >>2012-03-06 09:52:08; cppcms, error: Caught exception [Value was not >>loaded] 0x40566414: booster::stack_trace::trace(void**, int) + 0x24 in >>/usr/lib/libbooster.so.0 >>0x4015fe9b: cppcms::widgets::base_text::value() + 0xcb in >>/usr/lib/libcppcms.so.1 >>0x43132180: My_plugin::do(std::ostream&, cppcms::application&) in line 23 >> > > I think you had not added m_form.x to m_form (using m_form.add(x)); > so when you access x.value() it appears not to be loaded when you > call load(app.context()); You are completely right! Thanks a lot! I suggest to change the text "Value was not loaded" to something like "The value or the parent was not loaded. Check the hierarchy." ;) >> Is there some explanation how this works if multiple applications are >> mounted at the same root? > > The behavior is undefined for `cppcms::application_pool` Mmmh, but exactly this happens when you use the file server? It is also mounted at "". > Generally the first one will be selected, but non necessary, it > may be changed in future. So you should provide mutually > exclusive mount points. I do not have that situation within my own framework. > The dispatching and matching withing application (url_dispatched) is done > according to the order of adding them to url_dispatcher. Ok, good to know. >>> Because when you map sub-application and refer to it >>> you automatically referred to the default URL >>> of the sub-application - empty one "empty key" >> >>Sorry, I do not understand this statement. >> > > First of all take a look on this tutorial carefully. > > http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hierarchy > > > >>There are some examples for mapper and dispatcher, but I can't find >>anything related to how the url() call works. >>Doxygen just says: "Map url-key key to actual URL, without parameters" > >>What does url("gui") does? >> > > application::url() and <% url ... %> is a family of functions with > variable number of parameters. How does the <% url ... %> using syntax work? Why does <% url "/blog/post" using slug %> resolves to "/myblog/Hi%20%3cyou%3e/" (see http://cppcms.com/wikipp/en/page/cppcms_1x_templates_comm#URL.Mapping) I would rather expect /blog/post/Hi%20%3cyou%3e/? Both <% url "/gui/system" %> <% url "system" %> work without problem, but I could not figure out how to resolve a variable containing "system"? E.g. <% url "/gui/" using menu_element.m_href %> does not work? > when you call url("foo") it looks for the object named "foo" > > If it is actual function (not sub application) it provides a url > > if it is subapplication it tries to dispatch the "" key. Ok, I think I understand the approach now much better. I still can't figure out the details between: url("") url(".") url("/") while the first two seem to be equivalent, url("/") seems to link to the same url where the request() came from? e.g. when I request http://localhost:10000/gui/wrong_url url("/") resolves to http://localhost:10000/gui/wrong_url but url("") and url(".") resolves to ttp://localhost:10000/gui When I use dispatcher().assign("", &GUI::show_error_page, this); mapper().assign("/"); // changed here instead of "" the urls resolve to: url("/") -> http://localhost:10000/gui/wrong_url url(".") -> http://localhost:10000/gui/ url("") -> http://localhost:10000/gui/ So url(".") with assign("/") seems to be what I want ;) > See, applications are generated in the hierary, so > > For given application: foo, sub application bar and bar's method baz > > url("/foo/bar/baz") would map to the "baz"'s url. > > url("/foo/bar") would map to default (empty) url of baz application. > > You can have parameters as well for example > > // withing bar > > mapper().assign("baz","/baz"); > mapper().assign("baz","/baz/{1}"); > mapper().assign("baz","/baz/{1}/{2}"); > > Then you can call: > > url("/foo/bar/baz") -> something/baz > url("/foo/bar/baz",20) -> something/baz/20 > url("/foo/bar/baz","x","y") -> something/baz/x/y Thanks, I think I do not need parameters, because I prefer to have user/browser specific language and not by url. >>Can I use mapper().set_value? >> >> > > set_value should be used for some horizontal parameters > like for example language when you want to change the URL > independently from, the hierary. > > mapper().set_value("lang","en") > url("/foo/bar") -> en.wiki.org/foo/bar > url("/baz") -> en.wiki.org/baz > > mapper().set_value("lang","he") > url("/foo/bar") -> he.wiki.org/foo/bar > url("/baz") -> he.wiki.org/baz Ok, thank you! >>I think copy&paste of how wikipp does + explanation would help, because >>the > >>redirecting + url resolving there is what most users want anyway. >> > > Actually, wikipp was written before URL-mapper existed and I had > no time to update it. Take a look rather on the cppcms's blog > it uses url mapper fully. Ok, so I think the examples you gave in this mail are perfect! > P.S.: URL Mapper/Dispatcher is actually not-so simple and powerful part > I need to write a better tutorial. Yeah, they are powerful, I like them :-) best regards Markus |
From: Artyom B. <art...@ya...> - 2012-03-07 09:29:20
|
> >Hi, > >Does cppcms provide any help serving static files? Any tutorial? For serving static files the web server it the best option... :-) > >I would like to use cppcms to serve static files so that I can >implement the same permission logic as dynamic contents. > Since it was asked more then once. -------------------------------- This is quite different. To handle this kind of situation you should be aware of two very important factors: 1. Security 2. Performance ## Security Let's start from the first. I assume you want to let user to download certain files that you are controlling. For url like /some/files/[...] <- these are allows. Things you DO NOT EVER-EVER-EVER do: class my_server { my_server(...) { ... dispatcher().assign("/some/files/(.*)",&my_server::serve_file,this,1) } void serve_file(std::string file_name) { std::ifstream f(("some_dir_name/" + file_name).c_str()); if(!f) { response().status(404) } else { response().content_type("application/octet-stream") response().out() << f.rdbuf(); } } ... } Because attacker cat create path /some/files/../../../etc/some_secret.txt And read it... It would be VERY BAD. If you want to serve a file create a very strict **WHITE** list of allowed names like: /some/files/([a-z_0-9\.]\.txt) Or even better convert the name to sha1 representation and save files using cryptographic hash. Like: name = some_dir_per_user + "/" + cppcms::util::md5hex(file_name) + ".dat"; std::ifstream f(name.c_str()); ## Performance For small files (several K or even MB) response().out() << f.rdbuf(); Is fine and works very well. For the big files it is better to use headers like X-Send-File that are supported by lighttpd, apache and nginx. http://redmine.lighttpd.net/projects/1/wiki/X-LIGHTTPD-send-file So instead of calling response().content_type("application/octet-stream") response().out() << f.rdbuf(); You call: response().content_type("application/octet-stream") response().set_header("X-Lighttpd-Send-File",pysical_file_name); This is specially critical for big files were the server may for example save the entire FastCGI output to temporary file and before serving it (Nginx) or cache entire (huge) buffer in the memory (Lighttpd) More then that X-SendFile usually much more effective as it allows to the web server not to transfer buffers to the memory. ---------------- Now, please be so kind and put this to the wiki under the tutorial section :-) Artyom Beilis. |
From: Leon <le...@wl...> - 2012-03-07 08:53:22
|
Hi, Does cppcms provide any help serving static files? Any tutorial? I would like to use cppcms to serve static files so that I can implement the same permission logic as dynamic contents. Thanks for any help. |
From: Artyom B. <art...@ya...> - 2012-03-06 21:06:06
|
>> >> my_stream.imbue(context().locale()); > >That is working. > >I was asking myself how the booster::locale::translate is working within >plugins. In the main program translate() is working, but not in the plugins. >I did not called std::locale::global(gen("")); > See: stream << booster::locale::translate("foo") Works because actual translation is postponed to the stage were the data is written to the stream and rendered withing it. booster::locale::translate-> booster::locale::message + std::ostream's locale gives translation. So if you want to use locale for your plugin you need to have some locale context. It can be done by std::string translated = app.translate("foo"); or use locale explicitly as: std::locale loc = app.context().locale(); std::string translated = booster::locale::translate("foo").str(loc); or std::locale loc = app.context().locale(); std::string translated = booster::locale::gettext("foo",loc); Of course if your application uses only one language globally you can just set std::locale::global. > >But if it does not work well - see problem below - I may change to use >render() template. I do not understand the "With the command render" >example: In std::string main_html(cppcms::applicatin *app) the plugin still >renders to a buffer and returs the string, so what is the difference? > It was just an example However, if you call <% render ... %> from the view it renders to the output stream without intermediate buffers. >E.g. I have the following code: > >17 void My_plugin::do(std::ostream & buf, cppcms::application & app) >18 { >19 if(app.request().request_method()=="POST") >20 { >21 m_main.m_form.load(app.context()); >22 m_main.m_form.validate(); >23 ::std::cout << "x is: " << m_main.m_form.x.value() << >std::endl; >24 m_main.m_form.clear(); >25 } >26 >27 app.render("plugin_skin","main_html",buf,m_main); >28 } > >Then I get following exception: >2012-03-06 09:52:08; cppcms, error: Caught exception [Value was not loaded] >0x40566414: booster::stack_trace::trace(void**, int) + 0x24 in >/usr/lib/libbooster.so.0 >0x4015fe9b: cppcms::widgets::base_text::value() + 0xcb in >/usr/lib/libcppcms.so.1 >0x43132180: My_plugin::do(std::ostream&, cppcms::application&) in line 23 > I think you had not added m_form.x to m_form (using m_form.add(x)); so when you access x.value() it appears not to be loaded when you call load(app.context()); > > Is there some explanation how this works if multiple applications are > mounted at the same root? The behavior is undefined for `cppcms::application_pool` Generally the first one will be selected, but non necessary, it may be changed in future. So you should provide mutually exclusive mount points. The dispatching and matching withing application (url_dispatched) is done according to the order of adding them to url_dispatcher. >> >> Because when you map sub-application and refer to it >> you automatically referred to the default URL >> of the sub-application - empty one "empty key" > >Sorry, I do not understand this statement. > First of all take a look on this tutorial carefully. http://cppcms.com/wikipp/en/page/cppcms_1x_tut_hierarchy >There are some examples for mapper and dispatcher, but I can't find anything >related to how the url() call works. >Doxygen just says: "Map url-key key to actual URL, without parameters" >What does url("gui") does? > application::url() and <% url ... %> is a family of functions with variable number of parameters. when you call url("foo") it looks for the object named "foo" If it is actual function (not sub application) it provides a url if it is subapplication it tries to dispatch the "" key. See, applications are generated in the hierary, so For given application: foo, sub application bar and bar's method baz url("/foo/bar/baz") would map to the "baz"'s url. url("/foo/bar") would map to default (empty) url of baz application. You can have parameters as well for example // withing bar mapper().assign("baz","/baz"); mapper().assign("baz","/baz/{1}"); mapper().assign("baz","/baz/{1}/{2}"); Then you can call: url("/foo/bar/baz") -> something/baz url("/foo/bar/baz",20) -> something/baz/20 url("/foo/bar/baz","x","y") -> something/baz/x/y >Can I use mapper().set_value? > > set_value should be used for some horizontal parameters like for example language when you want to change the URL independently from, the hierary. mapper().set_value("lang","en") url("/foo/bar") -> en.wiki.org/foo/bar url("/baz") -> en.wiki.org/baz mapper().set_value("lang","he") url("/foo/bar") -> he.wiki.org/foo/bar url("/baz") -> he.wiki.org/baz >I think copy&paste of how wikipp does + explanation would help, because the >redirecting + url resolving there is what most users want anyway. > Actually, wikipp was written before URL-mapper existed and I had no time to update it. Take a look rather on the cppcms's blog it uses url mapper fully. Regards, Artyom Beilis, P.S.: URL Mapper/Dispatcher is actually not-so simple and powerful part I need to write a better tutorial. |
From: Markus R. <us...@ma...> - 2012-03-06 16:05:01
|
Hi! Thanks for your detailed answer. Artyom Beilis wrote: >> In the first example of the plugin interface you pass >> the application pointer to the plugin. I think it >> would be more decoupled if the plugin could create >> its own stripped down application just for rendering. > > It is up to you, really. > > I just had shown the general concept how it can be > done. Yes, there are of course different requirements on how plugins should work. >> Btw. the functions rendering to a stream should be >> const, or do they modify the application? That change >> would however break the API.. >> > > It is not const. Because when you call render to access > response().out() that does many things under the hood. > > So even thou technically it may be const. Semantically > it does not have to. > >> Is there any approach how to get booster::locale working >> Inside own plugins? >> > > No problem: > > 1. All applications that are build in hierarchy > share same http::context() that holds the locale, > > 2. Also the response().out() stream has std::locale > imbued inside it. That is why you can call > for example <% gt ... %> from the view. > > Of course if you render to your own std::ostream > then you should imbue the std::locale object. > > my_stream.imbue(context().locale()); That is working. I was asking myself how the booster::locale::translate is working within plugins. In the main program translate() is working, but not in the plugins. I did not called std::locale::global(gen("")); > But it is better to use <% render ... %> template > to render the plugin's view, this way you don\t use > intermediate buffers and render to the same ostream. The advantage of using a own buffer to render is that it is completely up to the plugins if they want to use cppcms rendering at all. They might directly stream the text, e.g. for error pages or where templates are overkill. But if it does not work well - see problem below - I may change to use render() template. I do not understand the "With the command render" example: In std::string main_html(cppcms::applicatin *app) the plugin still renders to a buffer and returs the string, so what is the difference? The problem I currently have with the streaming to buffer is when having a form and requesting the POST data within the plugin. E.g. I have the following code: 17 void My_plugin::do(std::ostream & buf, cppcms::application & app) 18 { 19 if(app.request().request_method()=="POST") 20 { 21 m_main.m_form.load(app.context()); 22 m_main.m_form.validate(); 23 ::std::cout << "x is: " << m_main.m_form.x.value() << std::endl; 24 m_main.m_form.clear(); 25 } 26 27 app.render("plugin_skin","main_html",buf,m_main); 28 } Then I get following exception: 2012-03-06 09:52:08; cppcms, error: Caught exception [Value was not loaded] 0x40566414: booster::stack_trace::trace(void**, int) + 0x24 in /usr/lib/libbooster.so.0 0x4015fe9b: cppcms::widgets::base_text::value() + 0xcb in /usr/lib/libcppcms.so.1 0x43132180: My_plugin::do(std::ostream&, cppcms::application&) in line 23 >> Is it possible with the integrated webserver to >> have the script at /? If "script_names" is set to "/", >> the url is localhost//name. If it is not given or "", >> I always get 404 for every url. >> > > Yes: > > http://cppcms.com/wikipp/en/page/run_application_web_server_root > > > Specifically: > > http://cppcms.com/wikipp/en/page/run_application_web_server_root#CppCMS- Embedded Works perfectly, thanks! >> Is it possible to reconfigure the internal file server >> to be at another root? > > You mean "document root"? > > Yes: > > http://cppcms.com/wikipp/en/page/cppcms_1x_config#file_server.document_root No, I mean the root where the internal file server application is mounted to. But it seems to be hardcoded with "" in line 238: applications_pool().mount(applications_factory<cppcms::impl::file_server>(),mount_point("")); > Also you may be interested in aliases: > > http://cppcms.com/wikipp/en/page/cppcms_1x_config#file_server.alias Yeah, that seems to solve the issue. Is there some explanation how this works if multiple applications are mounted at the same root? >> I am afraid I do not fully understand the url mapper. >> E.g. I have: >> >> 27 attach (new Base_gui(srv), >> 28 "gui", "/gui{1}", >> 29 "/gui(/(.*))?", 1); >> 30 >> 31 attach (new Base_rpc(srv), >> 32 "rpc", "/rpc{1}", >> 33 "/rpc(/(.*))?", 1); >> >> >> For any reason >> >> 52 << "<a href='" << >> url("gui")<< "'>GUI</a><br>" >> 53 << "<a href='" << >> url("rpc")<< "'>RPC</a><br> >> >> works for gui, but not for rpc? See following error for rpc: >> >> 2012-03-01 15:46:48; cppcms, error: url_mapper: key `' not found for url >> `gui' > > Because when you map sub-application and refer to it > you automatically referred to the default URL > of the sub-application - empty one "empty key" Sorry, I do not understand this statement. There are some examples for mapper and dispatcher, but I can't find anything related to how the url() call works. Doxygen just says: "Map url-key key to actual URL, without parameters" What does url("gui") does? Can I use mapper().set_value? I think copy&paste of how wikipp does + explanation would help, because the redirecting + url resolving there is what most users want anyway. > See: > > http://cppcms.com/cppcms_ref/latest/classcppcms_1_1url__mapper.html#a249e59de419f7fd0241cab6634c68393 "Map the default key for the application, url has same rules as for assign(key,url) but they rather refer to default application's URL when it is used in hierarchy. " does not help much either > Also I'd recommend to update to CppCMS 1.0.0 as in latest > version exception is not thrown in case of invalid URL but > rather "/this_is_invalid_url" some something like that generated. Done :-) But I still get http://localhost:10000/this_is_an_invalid_url_generated_by_url_mapper best regards Markus |
From: Artyom B. <art...@ya...> - 2012-03-05 16:04:05
|
>> CppCMS json parser supports two extensions to the standard json syntax, >> that make it very easy to use for configuration: > > Yeah, that are useful extensions but in the end it is not json anymore. > Perl implemented # comments and others may do other or do not support them > at all. I mean in context of the configuration file context not in general >>> What do you think >>> about a patch which let you switch to http://www.libelektra.org/ at >>> compiletime if preferred? >>> >> >> What is the license libelektra distributed under? > > It is BSD licenced. And as described: you can choose at build time if you > want that dependency or not. > From what I can seen from the quick glance that libelektra does not support arrays. Many data structures in the CppCMS configuration files are arrays and they are not 1-to-1 convertible to "registry" style operations. In any case, CppCMS's settings is based on JSON, if you want to use other formats it should be possible to convert them to JSON object and then you can start CppCMS main service as cppcms::json::value settings; settings = // load from whatever you want from cppcms::service srv(settings); Including converting from example from "Elektra" format to JSON one. If you want to create a patch that allows converting elektra to cppcms::json::value then I can put it under "contrib" section. Please note this Copyrights section http://cppcms.com/wikipp/en/page/cppcms_1x_coding_standards#Copyrights For submitting patches. Best Regards, Artyom |
From: Markus R. <us...@ma...> - 2012-03-05 14:52:55
|
Hi! Artyom Beilis wrote: >> Yeah, I was also using CppCMS 1.x.x for some time now. > >> But I had some legacy code which needed to be ported to 1.x. >> I am sure, however, I am not the only one in this situation, so I >> finished the article: >> http://cppcms.com/wikipp/en/page/cppcms_1x_migration >> >> CppCMS 1.x is vastly superior to 0.x - I realized that again during >> porting ;) >> > > Yes, I've began to write it but then left as I thought it was not > really required as most of the users had already switched by now. Yeah, you are right. But there is always some legacy code somewhere. >> I am not very fond of json as configuration format - even though it is >> very good as data exchange format - because it lacks comments. > > Actually I was sure that it was mentioned in documentation (but I can't > find it now) There are many discussions about the lacking of comments. > CppCMS json parser supports two extensions to the standard json syntax, > that make it very easy to use for configuration: > > 1. C++ style comments i.e. "//" > 2. It ignores trailing comma in objects and array definitions > so stuff like that works. > > { > "foo" : 10, > "bar" : 20, > // "baz" : 30 > } Yeah, that are useful extensions but in the end it is not json anymore. Perl implemented # comments and others may do other or do not support them at all. > It makes it very suitable as configuration file format. > >> What do you think >> about a patch which let you switch to http://www.libelektra.org/ at >> compiletime if preferred? >> >> Basically it would be just an alternative implementation of >> json::value service::load_settings(int argc,char *argv[]) >> >> What do you think? >> > > I'm not really fond of adding more 3rd party dependencies. > > What is the license libelektra distributed under? It is BSD licenced. And as described: you can choose at build time if you want that dependency or not. >>> I don't understand the question, you mean extra spaces when you press >> on >>> "view plain" ? >> >> Steps to reproduce: >> Go to http://cppcms.com/wikipp/en/page/cppcms_1x_json with firefox/chrome >> Select some text of a sourcecode, press ctrl+c and ctrl+v or middle >> mouse. >> >> I get: >> my_object["name"]="Moshe"; >> my_object["salary"]=1000.0; >> (Note the two spaces at the end of each line) >> >> I expect: >> No spaces at the end of lines. >> >> It seems to be some problem within the syntax highlighter, which >> generates a "<span>; </span>" that adds these two spaces. It is a >> little bit strange, >> because the line numbers are suppressed successfully. >> >> Workaround: >> Press "view plain" and copy there. >> > > I assume that this is syntax highlighter bug > > (I hadn't written it, I just use it) Yeah, I think that too. So its up to me to report the bug there I assume ;) >> Yeah, the decision to drop CgiCC is ok, cppcms is now more homogen and >> easier to use. >> > > Also CgiCC was quite buggy and limited :-) > I don't miss it. ;) best regards Markus |