diff --git a/README.md b/README.md index 1456d778..e52fc08a 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,6 @@ An alternative to the last 2 instructions is to use the script from tools folder ### text * __encoder__: Various simpler encoders: base64, url-encoder, xml entities, html entities [read more](library/text/encoder) -### crypto -* eel -* eapml - ### Others * error: very simple/basic library to handle error diff --git a/doc/wiki/Doc_Getting_Started.mediawiki b/doc/wiki/Doc_Getting_Started.mediawiki new file mode 100644 index 00000000..550862d8 --- /dev/null +++ b/doc/wiki/Doc_Getting_Started.mediawiki @@ -0,0 +1,57 @@ +Menu :: [[Doc_Getting_Started|Getting Started]] :: [[Doc_Community|Community]] + += Getting Started = +This page will help you to get started with EWF. We will first see how to install EWF and then how to compile and run the venerable Hello World example. + +== Installation == +=== EiffelStudio 7.2 === +EWF is already included in EiffelStudio 7.2: you don't have to do anything in this case! This is the recommanded solution if you are a new developer or are new to Eiffel. + +=== Other EiffelStudio versions === +If you have another version of EiffelStudio than 7.2, you have to + +* dowload EWF +* create a directory where you will put your custum Eiffel libraries +* extract EWF in the newly created directory +* define the environment variable EIFFEL_LIBRARY to point to the newly created directory + +=== Source code === +The source code is available on Github. You can get it by running the command: + +git clone git://github.com/EiffelWebFramework/EWF.git + +== Hello World == +The hello world example is located in the directory $ISE_EIFFEL/contrib/examples/web/ewf/simple. Just double click on the simple.ecf file and select the simple target or if you prefer the command line, run the command: +estudio -config simple.ecf -target simple + +Once the project is compiled, we will adapt the root class to point to port number 9090. + +'''Note''': By default, the application listens on port 80, which is often already used by standard webservers (Apache, nginx, ...). Moreover, on Linux, ports below 1024 can only be opened by root. + +To do this, we will redefine the feature initialize as follows: + + + class + APPLICATION + + inherit + WSF_DEFAULT_SERVICE + redefine + initialize + end + + create + make_and_launch + + feature {NONE} -- Initialization + + initialize + -- Initialize current service + do + set_service_option ("port", 9090) + end + end + + +After one more compile, you can now launch the application and point your browser to [http://localhost:9090]. +You should now see a simple page with Hello World. \ No newline at end of file diff --git a/doc/wiki/Doc_Index.mediawiki b/doc/wiki/Doc_Index.mediawiki new file mode 100644 index 00000000..90016448 --- /dev/null +++ b/doc/wiki/Doc_Index.mediawiki @@ -0,0 +1,7 @@ +Menu :: [[Doc_Getting_Started|Getting Started]] :: [[Doc_Community|Community]] + += Eiffel Web Framework = +Framework to build web applications in Eiffel + +[ [http://github.com/EiffelWebFramework/EWF/zipball/ Download Current] ] +[ [http://github.com/EiffelWebFramework/EWF/zipball/release-0.3 Download v0.3] ] \ No newline at end of file diff --git a/doc/wiki/Home.md b/doc/wiki/Home.md index 4da5d7b7..23fa81e5 100644 --- a/doc/wiki/Home.md +++ b/doc/wiki/Home.md @@ -6,7 +6,7 @@ The official documentation/wiki is located at https://github.com/EiffelWebFramew ## Organization ## - Mailing list: please visit and subscribe to the mailing list page [[http://groups.google.com/group/eiffel-web-framework]] ![logo](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif) - Most of the topics are discussed on the mailing list (google group). -- For time to time we have web meeting, and less frequently physical meetings that occurs usually during other Eiffel related events. +- For time to time we have [[web meetings|meetings]], and less frequently [[physical meetings|meetings]] that occurs usually during other Eiffel related events. ## Documentation ## - to redo diff --git a/doc/wiki/Meetings.md b/doc/wiki/Meetings.md new file mode 100644 index 00000000..a75a124f --- /dev/null +++ b/doc/wiki/Meetings.md @@ -0,0 +1,4 @@ +# Previous and future meetings + +* [[Web-meeting: 2012-09-18|Web-meeting-2012-09-18]] +* For previous meetings, check the ["meeting" topics](https://groups.google.com/forum/?fromgroups=#!tags/eiffel-web-framework/meeting) on the [forum](http://groups.google.com/group/eiffel-web-framework) diff --git a/doc/wiki/Projects-new-suggestions.md b/doc/wiki/Projects-new-suggestions.md index b7278fee..6093b9c9 100644 --- a/doc/wiki/Projects-new-suggestions.md +++ b/doc/wiki/Projects-new-suggestions.md @@ -12,3 +12,9 @@ For any entry, please use this template ---- +## Add support for Swagger +* _Suggested by **Olivier**_ +* _Description_: Build a Swagger Eiffel implementation +* _References_: http://swagger.wordnik.com/ + +---- diff --git a/doc/wiki/Projects.md b/doc/wiki/Projects.md index ad4f235f..2aaa7a50 100644 --- a/doc/wiki/Projects.md +++ b/doc/wiki/Projects.md @@ -96,6 +96,7 @@ If you are a student, don't hesitate to pick one, or even suggest a new project, * _Suggested by **Jocelyn**_ * _Supervisor_: * _Suitability_: TODO +* _Status_: started, and open for contribution, collaboration, please contact Jocelyn. * _Description_: Using EWF, Build a simple CMS (Content Management System) framework and then an example. It should provide common features such as: - user management (register, login, lost password -> send email) - page editing @@ -225,6 +226,13 @@ If you are a student, don't hesitate to pick one, or even suggest a new project, * This should reuse and improve the "http_client" provided by EWF. Eventually also write the EiffelNet implementation to be independant from cURL * **Requirement**: OAuth client eiffel component +## Build a ESI preprocessor, or proxy +* _Suggested by **Jocelyn**_ +* _Supervisor_: +* _Suitability_: TODO +* _Description_: TODO +* See: http://en.wikipedia.org/wiki/Edge_Side_Includes + ---- # Feel free to add new idea below this line ---- diff --git a/doc/wiki/Useful-links.md b/doc/wiki/Useful-links.md new file mode 100644 index 00000000..29c810b7 --- /dev/null +++ b/doc/wiki/Useful-links.md @@ -0,0 +1,14 @@ +## Eiffel + +* http://www.scoop.it/t/eiffel-resources +* http://www.scoop.it/t/eiffel + +## Hypermedia + +* http://www.scoop.it/t/hyper-media-apis +* http://www.scoop.it/t/hypermedia-api + +## ETags + +* http://www.mnot.net/blog/2007/08/07/etags +* http://bitworking.org/news/150/REST-Tip-Deep-etags-give-you-more-benefits \ No newline at end of file diff --git a/doc/wiki/Web-meeting-2012-09-18.md b/doc/wiki/Web-meeting-2012-09-18.md new file mode 100644 index 00000000..65f538af --- /dev/null +++ b/doc/wiki/Web-meeting-2012-09-18.md @@ -0,0 +1,62 @@ +## Participants + +* Jocelyn Fiat +* Berend de Boer +* Olivier Ligot +* Javier Velilla + +## Information + +### When ? +* Tuesday 18th of september, 19:00 - 20:00 UTC/GMT time (see 3rd time in http://www.doodle.com/8v2sekiyebp4dpyh) + +### Where ? +Web meeting using webex + +* Short url: http://goo.gl/wBz11 +* Long url: https://eiffel.webex.com/eiffel/j.php?ED=211265702&UID=0&PW=NZWNiMjBiZWIz&RT=MiMyMA%3D%3D +* Related Google group topic: https://groups.google.com/d/topic/eiffel-web-framework/A7ADPAT3nj8/discussion + +## Agenda + +* Current status of EWF + * Focus on new design for the router system, and take decision + * decide if this replace the previous system, + * or if this is provided as another solution (we would then have 2 routers system). + * It might be possible to implement the previous uri and uri-template router with the new design, and mark them obsolete, this would avoid breaking existing code, but if no-one ask for it, no need to spend time doing it. + * Current activities + * Technology forecasting about REST, Hypermedia API, Collection/JSON, HAL, ... + * Building a CMS framework inspired by Drupal, and using EWF + * Libraries in-progress or draft: OAuth (consumer), Google API, Github API, Template engine, Wikitext parser, CMS (including sub libraries which will be part of EWF, such as session handling, mailer, ...) + * Documentation + * Remaining issues + * Review design in relation to concurrency, and provide example demonstrating concurrency with EWF + * Review design to allow easier extension/customization of EWF, such as using its own MIME handlers. + * Demo for a CMS built with EWF (inspired by Drupal) +* Future tasks + * [graphviz-server](https://github.com/EiffelWebFramework/graphviz-server) + * Improving Eiffel Web Nino: to support persistent connection, and better concurrency design. + * Provide friendly components to generate HTML (DHTML, HTML5, ...), (coders do not want to learn HTML and +CSS) +* Users feedback, suggestions and requests + * ... +* Next meeting + +## Materials + +## Minutes +* swagger: see if we could generate EWF code from a swagger specification +* Jocelyn will publish its attempt to build a CMS with EWF + * CMS demo: ... as announced ... some parts look very like drupal. +* Jocelyn will publish a few in-progress draft libraries +* Javier will focus on graphviz-server and hypermedia API +* Berend may send a short note on how he uses EWF (and generate code from description) +* Jocelyn will try to find time to complete the thread and SCOOP implementation of Eiffel Web Nino +* Olivier will have a closer look at swagger +* EWF will adopt the new WSF_ROUTER design as no-one expressed opposition. Olivier said converting his code is not a big task. Same for other users. +* The current state of EWF/WSF seems to be ok for users, we can focus on libraries on top of EWF/WSF +* We might need an HTML parser, if we want to support HTML as an hypermedia API (maybe we can require XHTML for now) +* No high priority to improve Eiffel Web Nino , for now it is mainly used during development. + +* It seems RESTful + Hypermedia API is the top priority for EWF. + diff --git a/draft/application/cms/README.md b/draft/application/cms/README.md new file mode 100644 index 00000000..32472422 --- /dev/null +++ b/draft/application/cms/README.md @@ -0,0 +1,2 @@ +The "cms" component moved. +Please visit https://github.com/EiffelWebFramework/cms to follow the project. diff --git a/draft/application/cms/cms-safe.ecf b/draft/application/cms/cms-safe.ecf deleted file mode 100644 index 6766f70c..00000000 --- a/draft/application/cms/cms-safe.ecf +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - /EIFGENs$ - /CVS$ - /.svn$ - - - - - - - - - - - - - - - - - - - diff --git a/draft/application/cms/cms.ecf b/draft/application/cms/cms.ecf deleted file mode 100644 index 164e5649..00000000 --- a/draft/application/cms/cms.ecf +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - /EIFGENs$ - /CVS$ - /.svn$ - - - - - - - - - - - - - - - - - - - - - diff --git a/draft/application/cms/example/demo.rc b/draft/application/cms/example/demo.rc deleted file mode 100644 index b0ec159c..00000000 --- a/draft/application/cms/example/demo.rc +++ /dev/null @@ -1,6 +0,0 @@ -#include - -STRINGTABLE -BEGIN - 1 "This Program was made using EiffelStudio using Visual Studio C++" -END diff --git a/draft/application/cms/example/src/web_cms.e b/draft/application/cms/example/src/web_cms.e deleted file mode 100644 index 716da98f..00000000 --- a/draft/application/cms/example/src/web_cms.e +++ /dev/null @@ -1,135 +0,0 @@ -note - description: "[ - This class implements the Demo of WEB CMS service - - ]" - -class - WEB_CMS - -inherit - WSF_DEFAULT_SERVICE - redefine - initialize - end - -create - make_and_launch - -feature {NONE} -- Initialization - - initialize - local - args: ARGUMENTS_32 - cfg: detachable READABLE_STRING_32 - i,n: INTEGER - do - --| Arguments - create args - from - i := 1 - n := args.argument_count - until - i > n or cfg /= Void - loop - if attached args.argument (i) as s then - if s.same_string_general ("--config") or s.same_string_general ("-c") then - if i < n then - cfg := args.argument (i + 1) - end - end - end - i := i + 1 - end - if cfg = Void then - if file_exists ("cms.ini") then - cfg := {STRING_32} "cms.ini" - end - end - - --| EWF settings - service_options := create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("ewf.ini") - Precursor - - --| CMS initialization - launch_cms (cms_setup (cfg)) - end - - cms_setup (a_cfg_fn: detachable READABLE_STRING_GENERAL): CMS_CUSTOM_SETUP - do - if a_cfg_fn /= Void then - create Result.make_from_file (a_cfg_fn) - else - create Result -- Default - end - setup_modules (Result) - setup_storage (Result) - end - - launch_cms (a_setup: CMS_SETUP) - local - cms: CMS_SERVICE - do - create cms.make (a_setup) - on_launched (cms) - cms_service := cms - end - -feature -- Execution - - cms_service: CMS_SERVICE - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - do - cms_service.execute (req, res) - end - -feature -- Access - - setup_modules (a_setup: CMS_SETUP) - local - m: CMS_MODULE - do - create {DEMO_MODULE} m.make - m.enable - a_setup.add_module (m) - - create {SHUTDOWN_MODULE} m.make - m.enable - a_setup.add_module (m) - - create {DEBUG_MODULE} m.make - m.enable - a_setup.add_module (m) - - create {OPENID_MODULE} m.make - m.enable - a_setup.add_module (m) - end - - setup_storage (a_setup: CMS_SETUP) - do - - end - -feature -- Event - - on_launched (cms: CMS_SERVICE) - local - e: CMS_EMAIL - do - create e.make (cms.site_email, cms.site_email, "[" + cms.site_name + "] launched...", "The site [" + cms.site_name + "] was launched at " + (create {DATE_TIME}.make_now_utc).out + " UTC.") - cms.mailer.safe_process_email (e) - end - -feature -- Helper - - file_exists (fn: READABLE_STRING_GENERAL): BOOLEAN - local - f: RAW_FILE - do - create f.make_with_name (fn) - Result := f.exists and then f.is_readable - end - -end diff --git a/draft/application/cms/src/cms_configuration.e b/draft/application/cms/src/cms_configuration.e deleted file mode 100644 index 937629e3..00000000 --- a/draft/application/cms/src/cms_configuration.e +++ /dev/null @@ -1,311 +0,0 @@ -note - description: "Summary description for {CMS_CONFIGURATION}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - CMS_CONFIGURATION - -inherit - ANY - - SHARED_EXECUTION_ENVIRONMENT - export - {NONE} all - end - -create - make, - make_from_file - -feature {NONE} -- Initialization - - make - do - create options.make_equal (10) - analyze - end - - make_from_file (a_filename: READABLE_STRING_GENERAL) - -- Initialize `Current'. - local - p: PATH - do - make - create p.make_from_string (a_filename) - configuration_location := p - import_from_path (p) - analyze - end - - analyze - do - get_root_location - get_var_location - get_themes_location - get_files_location - end - -feature -- Access - - configuration_location: detachable PATH - - option (a_name: READABLE_STRING_GENERAL): detachable ANY - do - Result := options.item (a_name) - end - - options: STRING_TABLE [STRING_32] - -feature -- Conversion - - append_to_string (s: STRING) - local - utf: UTF_CONVERTER - do - s.append ("Options:%N") - across - options as c - loop - s.append (c.key.to_string_8) - s.append_character ('=') - utf.string_32_into_utf_8_string_8 (c.item, s) - s.append_character ('%N') - end - - s.append ("Specific:%N") - s.append ("root_location=" + root_location.utf_8_name + "%N") - s.append ("var_location=" + var_location.utf_8_name + "%N") - s.append ("files_location=" + files_location.utf_8_name + "%N") - s.append ("themes_location=" + themes_location.utf_8_name + "%N") - end - -feature -- Element change - - set_option (a_name: READABLE_STRING_GENERAL; a_value: STRING_32) - do - options.force (a_value, a_name.as_string_8) - end - -feature -- Access - - var_location: PATH - - root_location: PATH - - files_location: PATH - - themes_location: PATH - - theme_name (dft: detachable like theme_name): READABLE_STRING_8 - do - if attached options.item ("theme") as s then - Result := s - elseif dft /= Void then - Result := dft - else - Result := "default" - end - end - - site_id: READABLE_STRING_8 - do - if attached options.item ("site.id") as s then - Result := s - else - Result := "_EWF_CMS_NO_ID_" - end - end - - site_name (dft: like site_name): READABLE_STRING_8 - do - if attached options.item ("site.name") as s then - Result := s - else - Result := dft - end - end - - site_url (dft: like site_url): READABLE_STRING_8 - do - if attached options.item ("site.url") as s then - Result := s - else - Result := dft - end - if Result /= Void then - if Result.is_empty then - -- ok - elseif not Result.ends_with ("/") then - Result := Result + "/" - end - end - end - - site_script_url (dft: like site_script_url): detachable READABLE_STRING_8 - do - if attached options.item ("site.script_url") as s then - Result := s - else - Result := dft - end - if Result /= Void then - if Result.is_empty then - elseif not Result.ends_with ("/") then - Result := Result + "/" - end - end - end - - site_email (dft: like site_email): READABLE_STRING_8 - do - if attached options.item ("site.email") as s then - Result := s - else - Result := dft - end - end - -feature -- Change - - get_var_location - local - utf: UTF_CONVERTER - do - if attached options.item ("var-dir") as s then - create var_location.make_from_string (utf.utf_8_string_8_to_escaped_string_32 (s)) - else - var_location := execution_environment.current_working_path - end - end - - get_root_location - local - utf: UTF_CONVERTER - do - if attached options.item ("root-dir") as s then - create root_location.make_from_string (utf.utf_8_string_8_to_escaped_string_32 (s)) - else - root_location := execution_environment.current_working_path - end - end - - get_files_location - local - utf: UTF_CONVERTER - do - if attached options.item ("files-dir") as s then - create files_location.make_from_string (utf.utf_8_string_8_to_escaped_string_32 (s)) - else - create files_location.make_from_string ("files") - end - end - - get_themes_location - local - utf: UTF_CONVERTER - do - if attached options.item ("themes-dir") as s then - create themes_location.make_from_string (utf.utf_8_string_8_to_escaped_string_32 (s)) - else - themes_location := root_location.extended ("themes") - end - end - -feature {NONE} -- Implementation - - import_from_file (fn: READABLE_STRING_GENERAL) - do - import_from_path (create {PATH}.make_from_string (fn)) - end - - import_from_path (a_filename: PATH) - -- Import ini file content - local - f: PLAIN_TEXT_FILE - l,v: STRING_8 - p: INTEGER - do - create f.make_with_path (a_filename) - if f.exists and f.is_readable then - f.open_read - from - f.read_line - until - f.exhausted - loop - l := f.last_string - l.left_adjust - if not l.is_empty then - if l[1] = '#' then - -- commented line - else - p := l.index_of ('=', 1) - if p > 1 then - v := l.substring (p + 1, l.count) - l.keep_head (p - 1) - v.left_adjust - v.right_adjust - l.right_adjust - - if l.is_case_insensitive_equal ("@include") then - import_from_file (resolved_string (v)) - else - set_option (l.as_lower, resolved_string (v)) - end - end - end - end - f.read_line - end - f.close - end - end - -feature {NONE} -- Environment - - resolved_string (s: READABLE_STRING_8): STRING_32 - -- Resolved `s' using `options' or else environment variables. - local - i,n,b,e: INTEGER - k: detachable READABLE_STRING_8 - do - from - i := 1 - n := s.count - create Result.make (s.count) - until - i > n - loop - if i + 1 < n and then s[i] = '$' and then s[i+1] = '{' then - b := i + 2 - e := s.index_of ('}', b) - 1 - if e > 0 then - k := s.substring (b, e) - if attached option (k) as v then - if attached {READABLE_STRING_32} v as s32 then - Result.append (s32) - else - Result.append (v.out) - end - i := e + 1 - elseif attached execution_environment.item (k) as v then - Result.append (v) - i := e + 1 - else - Result.extend (s[i]) - end - else - Result.extend (s[i]) - end - else - Result.extend (s[i]) - end - i := i + 1 - end - end - - - -end diff --git a/draft/application/cms/src/cms_default_setup.e b/draft/application/cms/src/cms_default_setup.e deleted file mode 100644 index 96002a52..00000000 --- a/draft/application/cms/src/cms_default_setup.e +++ /dev/null @@ -1,132 +0,0 @@ -note - description: "Summary description for {CMS_DEFAULT_SETUP}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - CMS_DEFAULT_SETUP - -inherit - CMS_SETUP - redefine - default_create - end - -create - default_create, - make, - make_from_file - -feature {NONE} -- Initialization - - make (a_cfg: CMS_CONFIGURATION) - do - configuration := a_cfg - default_create - end - - make_from_file (fn: READABLE_STRING_GENERAL) - local - cfg: CMS_CONFIGURATION - do - create cfg.make_from_file (fn) - make (cfg) - end - - default_create - do - Precursor - build_modules - build_storage - build_session_manager - build_auth_engine - build_mailer - end - -feature -- Access - - modules: ARRAYED_LIST [CMS_MODULE] - - storage: CMS_STORAGE - -- CMS persistent layer - - session_manager: WSF_SESSION_MANAGER - -- CMS Session manager - - auth_engine: CMS_AUTH_ENGINE - -- CMS Authentication engine - - mailer: NOTIFICATION_MAILER - -feature {NONE} -- Initialization - - build_modules - local - m: CMS_MODULE - do - create modules.make (3) - - -- Core - create {USER_MODULE} m.make - m.enable - modules.extend (m) - - create {ADMIN_MODULE} m.make - m.enable - modules.extend (m) - - create {NODE_MODULE} m.make - m.enable - modules.extend (m) - end - - build_storage - local - dn: PATH - do - if attached configuration as cfg and then attached cfg.var_location as l_site_var_dir then - dn := l_site_var_dir - else - create dn.make_current - end - create {CMS_SED_STORAGE} storage.make (dn.extended ("_storage_").name) - end - - build_session_manager - local - dn: PATH - do - if attached configuration as cfg and then attached cfg.var_location as l_site_var_dir then - dn := l_site_var_dir - else - create dn.make_empty - end - dn := dn.extended ("_storage_").extended ("_sessions_") - create {WSF_FS_SESSION_MANAGER} session_manager.make_with_folder (dn.name) - end - - build_auth_engine - do - create {CMS_STORAGE_AUTH_ENGINE} auth_engine.make (storage) - end - - build_mailer - local - ch_mailer: NOTIFICATION_CHAIN_MAILER - st_mailer: CMS_STORAGE_MAILER - do - create st_mailer.make (storage) - create ch_mailer.make (st_mailer) - ch_mailer.set_next (create {NOTIFICATION_SENDMAIL_MAILER}) - mailer := ch_mailer - end - -feature -- Change - - add_module (m: CMS_MODULE) - do - modules.force (m) - end - -end diff --git a/draft/application/cms/src/cms_service.e b/draft/application/cms/src/cms_service.e deleted file mode 100644 index c0bab037..00000000 --- a/draft/application/cms/src/cms_service.e +++ /dev/null @@ -1,442 +0,0 @@ -note - description: "[ - This class implements the CMS service - - It could be used to implement the main EWF service, or - even for a specific handler. - ]" - -class - CMS_SERVICE - -inherit - WSF_SERVICE - -create - make - -feature {NONE} -- Initialization - - make (a_setup: CMS_SETUP) - local - cfg: detachable CMS_CONFIGURATION - do - cfg := a_setup.configuration - if cfg = Void then - create cfg.make - end - - configuration := cfg - base_url := a_setup.base_url - - site_id := cfg.site_id - site_url := cfg.site_url ("") - site_name := cfg.site_name ("EWF::CMS") - site_email := cfg.site_email ("webmaster") - site_dir := cfg.root_location - site_var_dir := cfg.var_location - files_location := cfg.files_location - themes_location := cfg.themes_location - theme_name := cfg.theme_name ("default") - - set_script_url (cfg.site_script_url (Void)) -- Temporary value - - compute_theme_resource_location - - create content_types.make (3) - - modules := a_setup.modules - storage := a_setup.storage - session_manager := a_setup.session_manager - auth_engine := a_setup.auth_engine - mailer := a_setup.mailer - - initialize_storage - initialize_auth_engine - initialize_session_manager - initialize_mailer - initialize_router - initialize_modules - end - - initialize_session_manager --- local --- dn: DIRECTORY_NAME - do --- create dn.make_from_string (site_var_dir) --- dn.extend ("_storage_") --- dn.extend ("_sessions_") --- create {WSF_FS_SESSION_MANAGER} session_manager.make_with_folder (dn.string) - end - - initialize_storage - do - if not storage.has_user then - initialize_users - end - end - - initialize_users - require - has_no_user: not storage.has_user - local - u: CMS_USER - ur: CMS_USER_ROLE - do - create u.make_new ("admin") - u.set_password ("istrator") - storage.save_user (u) - - create ur.make_with_id (1, "anonymous") - storage.save_user_role (ur) - create ur.make_with_id (2, "authenticated") - ur.add_permission ("create page") - ur.add_permission ("edit page") - storage.save_user_role (ur) - end - - initialize_mailer - local --- ch_mailer: CMS_CHAIN_MAILER --- st_mailer: CMS_STORAGE_MAILER - do --- create st_mailer.make (storage) --- create ch_mailer.make (st_mailer) --- ch_mailer.set_next (create {CMS_SENDMAIL_MAILER}) --- mailer := ch_mailer - end - - initialize_router - local --- h: CMS_HANDLER - file_hdl: CMS_FILE_SYSTEM_HANDLER - do - create router.make (10) - router.set_base_url (base_url) - - router.map (create {WSF_URI_MAPPING}.make ("/", create {CMS_HANDLER}.make (agent handle_home))) - router.map (create {WSF_URI_MAPPING}.make ("/favicon.ico", create {CMS_HANDLER}.make (agent handle_favicon))) - - create file_hdl.make_with_path (files_location) - file_hdl.disable_index - file_hdl.set_max_age (8*60*60) - router.map (create {WSF_STARTS_WITH_MAPPING}.make ("/files/", file_hdl)) - - create file_hdl.make_with_path (theme_resource_location) - file_hdl.set_max_age (8*60*60) - router.map (create {WSF_STARTS_WITH_MAPPING}.make ("/theme/", file_hdl)) - end - - initialize_modules - do - across - modules as m - loop - if m.item.is_enabled then - m.item.register (Current) - if attached {CMS_HOOK_AUTO_REGISTER} m.item as h_auto then - h_auto.hook_auto_register (Current) - end - end - end - end - - initialize_auth_engine - do --- create {CMS_STORAGE_AUTH_ENGINE} auth_engine.make (storage) - end - -feature -- Access - - configuration: CMS_CONFIGURATION - - auth_engine: CMS_AUTH_ENGINE - - modules: LIST [CMS_MODULE] - -feature -- Hook: menu_alter - - add_menu_alter_hook (h: like menu_alter_hooks.item) - local - lst: like menu_alter_hooks - do - lst := menu_alter_hooks - if lst = Void then - create lst.make (1) - menu_alter_hooks := lst - end - if not lst.has (h) then - lst.force (h) - end - end - - menu_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_MENU_ALTER] - - call_menu_alter_hooks (m: CMS_MENU_SYSTEM; a_execution: CMS_EXECUTION) - do - if attached menu_alter_hooks as lst then - across - lst as c - loop - c.item.menu_alter (m, a_execution) - end - end - end - -feature -- Hook: form_alter - - add_form_alter_hook (h: like form_alter_hooks.item) - local - lst: like form_alter_hooks - do - lst := form_alter_hooks - if lst = Void then - create lst.make (1) - form_alter_hooks := lst - end - if not lst.has (h) then - lst.force (h) - end - end - - form_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_FORM_ALTER] - - call_form_alter_hooks (f: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_execution: CMS_EXECUTION) - do - if attached form_alter_hooks as lst then - across - lst as c - loop - c.item.form_alter (f, a_form_data, a_execution) - end - end - end - -feature -- Hook: block - - add_block_hook (h: like block_hooks.item) - local - lst: like block_hooks - do - lst := block_hooks - if lst = Void then - create lst.make (1) - block_hooks := lst - end - if not lst.has (h) then - lst.force (h) - end - end - - block_hooks: detachable ARRAYED_LIST [CMS_HOOK_BLOCK] - - hook_block_view (a_execution: CMS_EXECUTION) - do - if attached block_hooks as lst then - across - lst as c - loop - across - c.item.block_list as blst - loop - c.item.get_block_view (blst.item, a_execution) - end - end - end - end - -feature -- Router - - site_id: READABLE_STRING_8 - - site_name: READABLE_STRING_32 - - site_email: READABLE_STRING_8 - - site_url: READABLE_STRING_8 - - site_dir: PATH - - site_var_dir: PATH - - files_location: PATH - - themes_location: PATH - - compute_theme_resource_location - do - theme_resource_location := themes_location.extended (theme_name).extended ("res") - end - - theme_resource_location: PATH - - theme_name: READABLE_STRING_32 - - router: WSF_ROUTER - - map_uri_template (tpl: STRING; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) - do - router.map (create {WSF_URI_TEMPLATE_MAPPING}.make_from_template (tpl, create {CMS_HANDLER}.make (proc))) - end - - map_uri (a_uri: STRING; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) - do - router.map (create {WSF_URI_MAPPING}.make (a_uri, create {CMS_HANDLER}.make (proc))) - end - -feature -- URL related - - front_path: STRING - do - if attached base_url as l_base_url then - Result := l_base_url + "/" - else - Result := "/" - end - end - - urls_set: BOOLEAN - - initialize_urls (req: WSF_REQUEST) - local - u: like base_url - do - if not urls_set then - u := base_url - if u = Void then - u := "" - end - urls_set := True - if site_url.is_empty then - site_url := req.absolute_script_url (u) - end - set_script_url (req.script_url (u)) - end - end - - base_url: detachable READABLE_STRING_8 - -- Base url (related to the script path). - - script_url: detachable READABLE_STRING_8 - - set_script_url (a_url: like script_url) - local - s: STRING_8 - do - if a_url = Void then - script_url := Void - elseif not a_url.is_empty then - if a_url.ends_with ("/") then - create s.make_from_string (a_url) - else - create s.make (a_url.count + 1) - s.append (a_url) - s.append_character ('/') - end - script_url := s - end - ensure - attached script_url as l_url implies l_url.ends_with ("/") - end - -feature -- Report - - is_front_page (req: WSF_REQUEST): BOOLEAN - do - Result := req.path_info.same_string (front_path) - end - -feature {CMS_EXECUTION, CMS_MODULE} -- Security report - - user_has_permission (u: detachable CMS_USER; s: detachable READABLE_STRING_8): BOOLEAN - -- Anonymous or user `u' has permission for `s' ? - --| `s' could be "create page", - do - Result := storage.user_has_permission (u, s) - end - -feature -- Storage - - session_controller (req: WSF_REQUEST): CMS_SESSION_CONTROLER - -- New session controller for request `req' - do - create Result.make (req, session_manager, site_id) - end - - session_manager: WSF_SESSION_MANAGER - -- CMS Session manager - - storage: CMS_STORAGE - -feature -- Logging - - log (a_category: READABLE_STRING_8; a_message: READABLE_STRING_8; a_level: INTEGER; a_link: detachable CMS_LINK) - local - l_log: CMS_LOG - do - create l_log.make (a_category, a_message, a_level, Void) - if a_link /= Void then - l_log.set_link (a_link) - end - storage.save_log (l_log) - end - -feature -- Content type - - content_types: ARRAYED_LIST [CMS_CONTENT_TYPE] - -- Available content types - - add_content_type (a_type: CMS_CONTENT_TYPE) - do - content_types.force (a_type) - end - - content_type (a_name: READABLE_STRING_8): detachable CMS_CONTENT_TYPE - do - across - content_types as t - until - Result /= Void - loop - if t.item.name.same_string (a_name) then - Result := t.item - end - end - end - -feature -- Notification - - mailer: NOTIFICATION_MAILER - -feature -- Core Execution - - handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE) - local - fres: WSF_FILE_RESPONSE - do - create fres.make_with_path (theme_resource_location.extended ("favicon.ico")) - fres.set_expires_in_seconds (7 * 24 * 60 * 60) -- 7 jours - res.send (fres) - end - - handle_home (req: WSF_REQUEST; res: WSF_RESPONSE) - do - (create {HOME_CMS_EXECUTION}.make (req, res, Current)).execute - end - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Default request handler if no other are relevant - local - e: CMS_EXECUTION - sess: WSF_ROUTER_SESSION - do - initialize_urls (req) - create sess - router.dispatch (req, res, sess) - if not sess.dispatched then - create {NOT_FOUND_CMS_EXECUTION} e.make (req, res, Current) - e.execute - end - end - -end diff --git a/draft/application/cms/src/cms_setup.e b/draft/application/cms/src/cms_setup.e deleted file mode 100644 index 2f2902ba..00000000 --- a/draft/application/cms/src/cms_setup.e +++ /dev/null @@ -1,55 +0,0 @@ -note - description: "Summary description for {CMS_SETUP}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - CMS_SETUP - -feature -- Access - - configuration: detachable CMS_CONFIGURATION - - base_url: detachable READABLE_STRING_8 - - modules: LIST [CMS_MODULE] - deferred - end - - storage: CMS_STORAGE - -- CMS persistent layer - deferred - end - - session_manager: WSF_SESSION_MANAGER - -- CMS Session manager - deferred - end - - auth_engine: CMS_AUTH_ENGINE - -- CMS Authentication engine - deferred - end - - mailer: NOTIFICATION_MAILER - -- CMS email engine - deferred - end - -feature -- Change - - set_base_url (a_base_url: like base_url) - do - if a_base_url /= Void and then not a_base_url.is_empty then - base_url := a_base_url - else - base_url := Void - end - end - - add_module (m: CMS_MODULE) - deferred - end - -end diff --git a/draft/application/cms/src/handler/cms_file_system_handler.e b/draft/application/cms/src/handler/cms_file_system_handler.e deleted file mode 100644 index 6e36d089..00000000 --- a/draft/application/cms/src/handler/cms_file_system_handler.e +++ /dev/null @@ -1,17 +0,0 @@ -note - description: "Summary description for {CMS_FILE_SYSTEM_HANDLER}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - CMS_FILE_SYSTEM_HANDLER - -inherit - WSF_FILE_SYSTEM_HANDLER - -create - make, - make_with_path - -end diff --git a/draft/application/cms/src/kernel/content/format/filters/cms_html_filter.e b/draft/application/cms/src/kernel/content/format/filters/cms_html_filter.e deleted file mode 100644 index 55c509e6..00000000 --- a/draft/application/cms/src/kernel/content/format/filters/cms_html_filter.e +++ /dev/null @@ -1,128 +0,0 @@ -note - description: "Summary description for {CMS_HTML_FILTER}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - CMS_HTML_FILTER - -inherit - CMS_FILTER - redefine - default_create - end - -feature {NONE} -- Initialization - - default_create - do - Precursor - allowed_html_tags := <<"a", "em", "strong", "cite", "blockquote", "code", "ul", "ol", "li", "dl">> - description := "Allowed HTML tags: " - across - allowed_html_tags as c - loop - description.append ("<" + c.item + "> ") - end - end - -feature -- Access - - name: STRING_8 = "html_filter" - - title: STRING_8 = "HTML filter" - - description: STRING_8 - - allowed_html_tags: ITERABLE [READABLE_STRING_8] - -feature -- Conversion - - filter (a_text: STRING_8) - local - l_new: STRING_8 - i: INTEGER - n: INTEGER - in_tag: BOOLEAN - p1, p2: INTEGER - do - create l_new.make (a_text.count) - from - p1 := 1 - i := a_text.index_of ('<', 1) - if i > 0 then - l_new.append (a_text.substring (1, i - 1)) - end - n := a_text.count - until - i = 0 or i > n - loop - if a_text[i] = '<' then - in_tag := True - p1 := i - p2 := a_text.index_of ('>', i + 1) - if p2 = 0 then - -- next '<' - i := a_text.index_of ('<', i + 1) - if i > 0 then - l_new.append (a_text.substring (p1, i - 1)) - end - else - if is_authorized (a_text.substring (p1, p2)) then - l_new.append (a_text.substring (p1, p2)) - i := a_text.index_of ('<', p2 + 1) - else - i := a_text.index_of ('<', p2 + 1) - end - if i = 0 then - p1 := p2 + 1 - else - l_new.append (a_text.substring (p2 + 1, i - 1)) - end - end - else - i := i + 1 - end - end - l_new.append (a_text.substring (p1, n)) - a_text.wipe_out - a_text.append (l_new) - end - - is_authorized (s: READABLE_STRING_8): BOOLEAN - -- Is `s' authorized? - --| `s' has either "<....>" or "<..../>" or "" - local - l_tagname: detachable STRING - i,n,p1: INTEGER - do --- create l_tagname.make_empty - from - i := 2 -- skip first '<' - n := s.count - until - i > n or l_tagname /= Void - loop - if p1 > 0 then - if s[i].is_space or s[i] = '/' or s[i] = '>' then - l_tagname := s.substring (p1, i - 1) - end - else - if s[i].is_space or s[i] = '/' then - else - p1 := i - end - end - i := i + 1 - end - if l_tagname /= Void then - l_tagname.to_lower - Result := across allowed_html_tags as c some c.item.same_string (l_tagname) end - else - Result := True - end - end - - -end diff --git a/draft/application/cms/src/modules/debug/debug_module.e b/draft/application/cms/src/modules/debug/debug_module.e deleted file mode 100644 index 6444fc4c..00000000 --- a/draft/application/cms/src/modules/debug/debug_module.e +++ /dev/null @@ -1,128 +0,0 @@ -note - description: "Summary description for {DEBUG_MODULE}." - date: "$Date$" - revision: "$Revision$" - -class - DEBUG_MODULE - -inherit - CMS_MODULE - --- CMS_HOOK_BLOCK - - CMS_HOOK_AUTO_REGISTER - - SHARED_EXECUTION_ENVIRONMENT - export - {NONE} all - end - -create - make - -feature {NONE} -- Initialization - - make - do - name := "debug" - version := "1.0" - description := "Debug" - package := "cms" - end - -feature {CMS_SERVICE} -- Registration - - service: detachable CMS_SERVICE - - register (a_service: CMS_SERVICE) - do - service := a_service - a_service.map_uri_template ("/debug/", agent handle_debug (a_service, ?, ?)) - end - -feature -- Hooks - --- block_list: ITERABLE [like {CMS_BLOCK}.name] --- do --- Result := <<"debug-info">> --- end - --- get_block_view (a_block_id: detachable READABLE_STRING_8; a_execution: CMS_EXECUTION) --- local --- b: CMS_CONTENT_BLOCK --- do --- create b.make ("debug-info", "Debug", "... ", a_execution.formats.plain_text) --- a_execution.add_block (b, Void) --- end - -feature -- Handler - - handle_debug (cms: CMS_SERVICE; req: WSF_REQUEST; res: WSF_RESPONSE) - local - e: CMS_EXECUTION - s: STRING - do - if req.is_get_request_method then - create {ANY_CMS_EXECUTION} e.make (req, res, cms) - e.set_title ("DEBUG") - - create s.make_empty - append_info_to ("Name", cms.site_name, e, s) - append_info_to ("Url", cms.site_url, e, s) - - if attached cms.configuration as cfg and then attached cfg.configuration_location as l_loc then - s.append ("
") - append_info_to ("Configuration file", l_loc.name, e, s) - end - - s.append ("
") - - append_info_to ("Current dir", execution_environment.current_working_path.utf_8_name, e, s) - append_info_to ("Base url", cms.base_url, e, s) - append_info_to ("Script url", cms.script_url, e, s) - s.append ("
") - append_info_to ("Dir", cms.site_dir.utf_8_name, e, s) - append_info_to ("Var dir", cms.site_var_dir.utf_8_name, e, s) - s.append ("
") - append_info_to ("Theme", cms.theme_name, e, s) - append_info_to ("Theme location", cms.theme_resource_location.utf_8_name, e, s) - s.append ("
") - append_info_to ("Files location", cms.files_location.utf_8_name, e, s) - s.append ("
") - - append_info_to ("Url", e.url ("/", Void), e, s) - if attached e.user as u then - append_info_to ("User", u.name, e, s) - append_info_to ("User url", e.user_url (u), e, s) - - end - - e.set_main_content (s) - else - create {NOT_FOUND_CMS_EXECUTION} e.make (req, res, cms) - end - e.execute - end - - append_info_to (n: READABLE_STRING_8; v: detachable READABLE_STRING_GENERAL; e: CMS_EXECUTION; t: STRING) - do - t.append ("
  • ") - t.append ("" + n + ": ") - if v /= Void then - t.append (e.html_encoded (v)) - end - t.append ("
  • ") - end - -note - copyright: "Copyright (c) 1984-2013, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/draft/application/cms/src/notification/cms_email.e b/draft/application/cms/src/notification/cms_email.e deleted file mode 100644 index 3826a4fc..00000000 --- a/draft/application/cms/src/notification/cms_email.e +++ /dev/null @@ -1,18 +0,0 @@ -note - description : "[ - Component representing an email - ]" - author : "$Author$" - date : "$Date$" - revision : "$Revision$" - -class - CMS_EMAIL - -inherit - NOTIFICATION_EMAIL - -create - make - -end diff --git a/draft/application/cms/src/notification/cms_storage_mailer.e b/draft/application/cms/src/notification/cms_storage_mailer.e deleted file mode 100644 index c5a4c2d7..00000000 --- a/draft/application/cms/src/notification/cms_storage_mailer.e +++ /dev/null @@ -1,38 +0,0 @@ -note - description: "Summary description for {CMS_CHAIN_MAILER}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - CMS_STORAGE_MAILER - -inherit - NOTIFICATION_MAILER - -create - make - -feature {NONE} -- Initialization - - make (a_storage: like storage) - do - storage := a_storage - end - -feature -- Access - - storage: CMS_STORAGE - -feature -- Status - - is_available: BOOLEAN = True - -feature -- Basic operation - - process_email (a_email: NOTIFICATION_EMAIL) - do - storage.save_email (a_email) - end - -end diff --git a/draft/application/cms/src/storage/cms_sed_storage.e b/draft/application/cms/src/storage/cms_sed_storage.e deleted file mode 100644 index 20e340fd..00000000 --- a/draft/application/cms/src/storage/cms_sed_storage.e +++ /dev/null @@ -1,615 +0,0 @@ -note - description : "[ - CMS Storage implemented using SED - ]" - date : "$Date$" - revision : "$Revision$" - -class - CMS_SED_STORAGE - -inherit - CMS_STORAGE - -create - make - -feature {NONE} -- Initialization - - make (dn: READABLE_STRING_GENERAL) - -- Initialize `Current'. - do - create directory_name.make_from_string (dn) - ensure_directory_exists (directory_name) - create sed - initialize - end - - directory_name: PATH - - sed: SED_STORABLE_FACILITIES - - sed_file_retrieved (f: FILE): detachable ANY - local - r: SED_MEDIUM_READER_WRITER - do - create r.make (f) - r.set_for_reading - Result := sed.retrieved (r, True) - end - - sed_file_store (obj: ANY; f: FILE) - local - w: SED_MEDIUM_READER_WRITER - do - create w.make (f) - w.set_for_writing - sed.store (obj, w) - end - - save_object_with_id (obj: ANY; a_id: INTEGER; a_type: STRING) - local - fn: PATH - f: RAW_FILE - do - fn := directory_name.extended (a_type) - ensure_directory_exists (fn) - fn := fn.extended (a_id.out) --- .appended_with_extension ("txt") - create f.make_with_path (fn) --- check not f.exists end - f.create_read_write - sed_file_store (obj, f) - f.close - end - - object_with_id (a_id: INTEGER; a_type: STRING): detachable ANY - local - fn: PATH - f: RAW_FILE - do - fn := directory_name.extended (a_type) - ensure_directory_exists (fn) - fn := fn.extended (a_id.out) --- .append_with_extension ("txt") - create f.make_with_path (fn) - if f.exists and f.is_readable then - f.open_read - Result := sed_file_retrieved (f) - f.close - end - end - -feature -- Access: user - - has_user: BOOLEAN - -- Has any user? - do - Result := users_count > 0 - end - - users_count: INTEGER - do - Result := last_sequence ("user") - end - - fill_user_profile (a_user: CMS_USER) - do - if a_user.profile = Void then - if attached user_profile (a_user) as p then - a_user.set_profile (p) - end - end - end - - all_users: LIST [CMS_USER] - local - res: ARRAYED_LIST [like all_users.item] - i, n: like last_sequence - do - n := last_sequence ("user") - create res.make (n) - from - i := 1 - until - i > n - loop - if attached user_by_id (i) as u then - res.force (u) - end - i := i + 1 - end - Result := res - end - - user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER - do - if attached {like user_by_id} object_with_id (a_id, "user") as u then - Result := u - end - end - - user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER - local - uid: INTEGER - do - if attached users_index as t then - uid := t.by_name.item (a_name) - if uid > 0 then - Result := user_by_id (uid) - end - end - end - - user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER - local - uid: INTEGER - do - if attached users_index as t then - uid := t.by_email.item (a_email) - if uid > 0 then - Result := user_by_id (uid) - end - end - end - - is_valid_credential (u, p: READABLE_STRING_32): BOOLEAN - do - if attached user_by_name (u) as l_user then - Result := attached l_user.encoded_password as l_pass and then l_pass.same_string (encoded_password (p)) - end - end - - encoded_password (a_raw_password: STRING_32): attached like {CMS_USER}.encoded_password - do - Result := a_raw_password.as_string_8 + "!123!" - end - -feature -- Change: user - - save_user (a_user: CMS_USER) - local - uid: INTEGER - prof: like {CMS_USER}.profile - l_has_new_name: BOOLEAN - l_has_new_email: BOOLEAN - l_stored_user: like user_by_id - do - if a_user.has_id then - uid := a_user.id - l_stored_user := user_by_id (uid) - if l_stored_user /= Void then - l_has_new_name := not l_stored_user.name.same_string (a_user.name) - l_has_new_email := not (l_stored_user.email ~ a_user.email) - end - else - l_has_new_name := True - l_has_new_email := True - uid := next_sequence ("user") - a_user.set_id (uid) - end - if attached a_user.password as p then - a_user.set_encoded_password (encoded_password (p)) - a_user.set_password (Void) - end - - prof := a_user.profile - a_user.set_profile (Void) - if prof /= Void then - save_user_profile (a_user, prof) - end - save_object_with_id (a_user, uid, "user") - if l_has_new_name or l_has_new_email then - if attached users_index as l_index then - l_index.by_name.force (uid, a_user.name) - l_index.by_email.force (uid, a_user.email) - store_users_index (l_index) - end - end - a_user.set_profile (prof) - end - -feature -- Access: user_role - - user_role_by_id (a_id: INTEGER): detachable CMS_USER_ROLE - do - if attached {like user_role_by_id} object_with_id (a_id, "user_roles") as ur then - Result := ur - end - end - - user_roles: LIST [CMS_USER_ROLE] - local - i: INTEGER - n: like last_sequence - do - n := last_sequence ("user_roles") - create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (n) - if n > 0 then - from - i := 1 - until - i > n - loop - if attached user_role_by_id (i) as ur then - Result.force (ur) - end - i := i + 1 - end - end - end - -feature -- Change: user_role - - save_user_role (a_role: CMS_USER_ROLE) - do - if not a_role.has_id then - a_role.set_id (next_sequence ("user_roles")) - end - save_object_with_id (a_role, a_role.id, "user_roles") - end - -feature -- Email - - save_email (a_email: NOTIFICATION_EMAIL) - local - dn: PATH - fn: PATH - f: RAW_FILE - ts: INTEGER_64 - i: INTEGER - do - dn := directory_name.extended ("emails") - ensure_directory_exists (dn) - ts := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp (a_email.date) - from - fn := dn.extended (ts.out).appended_with_extension ("txt") - create f.make_with_path (fn) - until - not f.exists - loop - i := i + 1 - fn := dn.extended (ts.out + "-" + i.out).appended_with_extension ("txt") - f.make_with_path (fn) - end - f.create_read_write - f.put_string (a_email.message) - f.close - end - -feature -- Log - - log (a_id: like {CMS_LOG}.id): detachable CMS_LOG - do - if attached {CMS_LOG} object_with_id (a_id, "log") as l then - Result := l - end - end - - recent_logs (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_LOG] - local - n: Like last_sequence - i, p1, nb: INTEGER - do - n := last_sequence ("log") - p1 := n - a_lower + 1 - - if p1 > 0 then - create {ARRAYED_LIST [CMS_LOG]} Result.make (a_count) - from - i := p1 - until - i < 1 or nb = a_count - loop - if attached log (i) as obj then - Result.force (obj) - nb := nb + 1 - end - i := i - 1 - end - else - create {ARRAYED_LIST [CMS_LOG]} Result.make (0) - end - end - - - save_log (a_log: CMS_LOG) - do - if not a_log.has_id then - a_log.set_id (next_sequence ("log")) - end - save_object_with_id (a_log, a_log.id, "log") - end - -feature -- Node - - recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] - local - n: Like last_sequence - i, p1, nb: INTEGER - do - n := last_sequence ("node") - p1 := n - a_lower + 1 - - if p1 > 0 then - create {ARRAYED_LIST [CMS_NODE]} Result.make (a_count) - from - i := p1 - until - i < 1 or nb = a_count - loop - if attached node (i) as l_node then - Result.force (l_node) - nb := nb + 1 - end - i := i - 1 - end - else - create {ARRAYED_LIST [CMS_NODE]} Result.make (0) - end - end - - node (a_id: INTEGER): detachable CMS_NODE - do - if attached {like node} object_with_id (a_id, "node") as obj then - Result := obj - end - end - - save_node (a_node: CMS_NODE) - local - nid: INTEGER - do - if a_node.has_id then - nid := a_node.id - else - nid := next_sequence ("node") - a_node.set_id (nid) - end - - save_object_with_id (a_node, nid, "node") - end - -feature {NONE} -- Implementation - - last_sequence (a_type: STRING): INTEGER - local - fn: PATH - f: RAW_FILE - do - fn := directory_name.extended (a_type).appended_with_extension ("last_id") - create f.make_with_path (fn) - if f.exists and then f.is_readable then - f.open_read - f.read_line - if f.last_string.is_integer then - Result := f.last_string.to_integer - else - check is_integer: False end - end - f.close - end - end - - next_sequence (a_type: STRING): INTEGER - local - fn: PATH - f: RAW_FILE - do - fn := directory_name.extended (a_type).appended_with_extension ("last_id") - create f.make_with_path (fn) - if f.exists and then f.is_readable then - f.open_read - f.read_line - if f.last_string.is_integer then - Result := f.last_string.to_integer - else - check is_integer: False end - end - f.close - end - Result := Result + 1 - f.open_write - f.put_string (Result.out) - f.put_new_line - f.close - end - - users_index: TUPLE [ - by_name: HASH_TABLE [like {CMS_USER}.id, like {CMS_USER}.name]; - by_email: HASH_TABLE [like {CMS_USER}.id, like {CMS_USER}.email] - ] - local - f: RAW_FILE - fn: PATH - res: detachable like users_index - retried: INTEGER - do - fn := directory_name.extended ("users.db") - create f.make_with_path (fn) - if retried = 0 then - if f.exists and then f.is_readable then - f.open_read - if attached {like users_index} sed_file_retrieved (f) as r then - res := r - end - f.close - else - end - end - if res = Void then - res := [ create {HASH_TABLE [like {CMS_USER}.id, like {CMS_USER}.name]}.make (1), - create {HASH_TABLE [like {CMS_USER}.id, like {CMS_USER}.email]}.make (1) ] - end - Result := res - rescue - retried := retried + 1 - retry - end - - store_users_index (a_users_index: like users_index) - local - f: RAW_FILE - fn: PATH - do - fn := directory_name.extended ("users.db") - create f.make_with_path (fn) - if not f.exists or else f.is_writable then - f.open_write - sed_file_store (a_users_index, f) - f.close - end - end - - user_profile (a_user: CMS_USER): detachable CMS_USER_PROFILE - do - if attached {like user_profile} object_with_id (a_user.id, "user_profile") as obj then - Result := obj - end - end - - save_user_profile (a_user: CMS_USER; a_prof: CMS_USER_PROFILE) - local - l_id: INTEGER - do - if a_user.has_id then - l_id := a_user.id - end - - save_object_with_id (a_prof, l_id, "user_profile") - end - -feature -- Misc - - custom_type (a_type: READABLE_STRING_8): STRING - do - Result := "custom__" + a_type - end - - custom_value_id (a_name: READABLE_STRING_8; a_type: READABLE_STRING_8): INTEGER - -- Storage `id' for custom value named `a_name' if any. - -- If no such data exists, return 0 - local - i, - l_id, l_last_id: INTEGER - t: STRING - do - t := custom_type (a_type) - l_last_id := last_sequence (t) - from - i := 1 - until - i > l_last_id or l_id > 0 - loop - if - attached {TUPLE [name: READABLE_STRING_8; value: attached like custom_value]} object_with_id (i, t) as obj and then - obj.name.same_string (a_name) - then - l_id := i - end - i := i + 1 - end - end - - set_custom_value (a_name: READABLE_STRING_8; a_value: attached like custom_value ; a_type: READABLE_STRING_8) - -- Save data `a_name:a_value' for type `a_type' - local - t: STRING - l_id: INTEGER - do - t := custom_type (a_type) - l_id := custom_value_id (a_name, a_type) - if l_id = 0 then - l_id := next_sequence (t) - end - save_object_with_id ([a_name, a_value], l_id, t) - end - - custom_value (a_name: READABLE_STRING_8; a_type: READABLE_STRING_8): detachable TABLE_ITERABLE [READABLE_STRING_8, STRING_8] - -- Data for name `a_name' and type `a_type'. - local - i, - l_id, l_last_id: INTEGER - t: STRING - do - t := custom_type (a_type) - l_last_id := last_sequence (t) - from - i := 1 - until - i > l_last_id or l_id > 0 - loop - if - attached {TUPLE [name: READABLE_STRING_8; value: attached like custom_value]} object_with_id (i, t) as obj and then - obj.name.same_string (a_name) - then - l_id := i - Result := obj.value - end - i := i + 1 - end - end - - custom_value_names_where (a_where_key, a_where_value: READABLE_STRING_8; a_type: READABLE_STRING_8): detachable LIST [READABLE_STRING_8] - -- Name where custom value has item `a_where_key' same as `a_where_value' for type `a_type'. - local - i, l_last_id: INTEGER - t: STRING - l_key_found: BOOLEAN - res: ARRAYED_LIST [READABLE_STRING_8] - do - create res.make (0) - t := custom_type (a_type) - l_last_id := last_sequence (t) - from - i := 1 - until - i > l_last_id - loop - if - attached {TUPLE [name: READABLE_STRING_8; value: attached like custom_value]} object_with_id (i, t) as d - then - l_key_found := False - across - d.value as c - until - l_key_found or Result /= Void - loop - if c.key.same_string (a_where_key) then - l_key_found := True - if c.item.same_string (a_where_value) then - res.force (d.name) - end - end - end - end - i := i + 1 - end - if not res.is_empty then - Result := res - end - end - -feature {NONE} -- Implementation - - ensure_directory_exists (dn: PATH) - local - d: DIRECTORY - do - d := tmp_dir - d.make_with_path (dn) - if not d.exists then - d.recursive_create_dir - end - end - -feature {NONE} -- Implementation - - tmp_dir: DIRECTORY - once - create Result.make_with_path (directory_name) - end - -invariant - -end diff --git a/draft/application/cms/src/storage/cms_storage.e b/draft/application/cms/src/storage/cms_storage.e deleted file mode 100644 index 4bf8818c..00000000 --- a/draft/application/cms/src/storage/cms_storage.e +++ /dev/null @@ -1,186 +0,0 @@ -note - description : "[ - CMS interface to storage - ]" - date : "$Date$" - revision : "$Revision$" - -deferred class - CMS_STORAGE - -feature {NONE} -- Initialization - - initialize - do - end - -feature -- Access: user - - has_user: BOOLEAN - -- Has any user? - deferred - end - - fill_user_profile (a_user: CMS_USER) - deferred - end - - all_users: LIST [CMS_USER] - deferred - end - - user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER - require - a_id > 0 - deferred - ensure - same_id: Result /= Void implies Result.id = a_id - no_password: Result /= Void implies Result.password = Void - end - - user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER - require - a_name /= Void and then not a_name.is_empty - deferred - ensure - no_password: Result /= Void implies Result.password = Void - end - - user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER - deferred - ensure - no_password: Result /= Void implies Result.password = Void - end - - is_valid_credential (u, p: READABLE_STRING_32): BOOLEAN - deferred - end - -feature -- Change: user - - save_user (a_user: CMS_USER) - deferred - ensure - a_user_password_is_encoded: a_user.password = Void - a_user.has_id - end - -feature -- Access: roles and permissions - - user_has_permission (u: detachable CMS_USER; s: detachable READABLE_STRING_8): BOOLEAN - -- Anonymous or user `u' has permission for `s' ? - --| `s' could be "create page", - do - if s = Void then - Result := True - elseif u = Void then - Result := user_role_has_permission (anonymous_user_role, s) - else - Result := user_role_has_permission (authenticated_user_role, s) - if not Result and attached u.roles as l_roles then - across - l_roles as r - until - Result - loop - if attached user_role_by_id (r.item) as ur then - Result := user_role_has_permission (ur, s) - end - end - end - end - end - - anonymous_user_role: CMS_USER_ROLE - do - if attached user_role_by_id (1) as l_anonymous then - Result := l_anonymous - else - create Result.make ("anonymous") - end - end - - authenticated_user_role: CMS_USER_ROLE - do - if attached user_role_by_id (2) as l_authenticated then - Result := l_authenticated - else - create Result.make ("authenticated") - end - end - - user_role_has_permission (a_role: CMS_USER_ROLE; s: READABLE_STRING_8): BOOLEAN - do - Result := a_role.has_permission (s) - end - - user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE - deferred - end - - user_roles: LIST [CMS_USER_ROLE] - deferred - end - -feature -- Change: roles and permissions - - save_user_role (a_user_role: CMS_USER_ROLE) - deferred - end - -feature -- Email - - save_email (a_email: NOTIFICATION_EMAIL) - deferred - end - -feature -- Log - - recent_logs (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_LOG] - deferred - end - - log (a_id: like {CMS_LOG}.id): detachable CMS_LOG - require - a_id > 0 - deferred - end - - save_log (a_log: CMS_LOG) - deferred - end - -feature -- Node - - recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] - deferred - end - - node (a_id: INTEGER): detachable CMS_NODE - require - a_id > 0 - deferred - end - - save_node (a_node: CMS_NODE) - deferred - end - -feature -- Misc - - set_custom_value (a_name: READABLE_STRING_8; a_value: attached like custom_value; a_type: READABLE_STRING_8) - -- Save data `a_name:a_value' for type `a_type' - deferred - end - - custom_value (a_name: READABLE_STRING_8; a_type: READABLE_STRING_8): detachable TABLE_ITERABLE [READABLE_STRING_8, STRING_8] - -- Data for name `a_name' and type `a_type'. - deferred - end - - custom_value_names_where (a_where_key, a_where_value: READABLE_STRING_8; a_type: READABLE_STRING_8): detachable LIST [READABLE_STRING_8] - -- Names where custom value has item `a_where_key' same as `a_where_value' for type `a_type'. - deferred - end - -end diff --git a/draft/application/cms/www/themes/test/res/style.css b/draft/application/cms/www/themes/test/res/style.css deleted file mode 100644 index deb06a83..00000000 --- a/draft/application/cms/www/themes/test/res/style.css +++ /dev/null @@ -1,192 +0,0 @@ -body { margin: 0; background-color: #eeeeff;} -div#header { background-color: #300; color: #fff; border: solid 1px #003; padding: 0px; margin: 0px;} -div#header img#logo { float: left; margin: 5px 15px 5px 10px; } -div#header div#title {font-size: 180%; font-weight: bold; margin-top: 10px; } -ul.horizontal { - list-style-type: none; -} -ul.horizontal li { - display: inline; - padding: 0 5px 0 5px; -} - -div#menu-bar li.active { - border: solid 1px #ff0; - color: #ff0; -} -div#menu-bar li:hover { - background-color: #fff; - color: #00f; -} -div#menu-bar li a { - text-decoration: none; - color: #fff; -} -div#menu-bar li:hover a { - color: #00f; - font-style: bold; -} - - -div#primary-tabs li { - color: #00f; - padding: 2px 5px 2px 5px; - background-color: #eee; - border: solid 1px #ccf; -} -div#primary-tabs li.active { - padding: 2px 7px 1px 7px; - border-top: solid 2px #99f; - border-left: solid 1px #99f; - border-right: solid 1px #99f; - border-bottom: 0; - background-color: #fff; - color: #00f; -} -div#primary-tabs li:hover { - background-color: #fff; - color: #00f; -} -div#primary-tabs li a { - text-decoration: none; - color: #00f; -} -div#primary-tabs li:hover a { - color: #00f; - font-style: bold; -} - - - -div#menu-first { margin-left: 20%; color: #ccf; background-color: #003; } -div#menu-first a { color: #ccf; } -div#menu-second { color: #99f; background-color: #333; } -div#menu-second a { color: #99f; } - -div#main-wrapper { - clear: both; - display: block; - height: 0; -} -div#main { margin: 0; padding: 0; clear: both; height:0; display: block; } - -div#content { padding: 5px 3px 5px 20px; - margin-top: 10px; - min-width: 80%; - display: inline; - float: left; - position: relative; - background-color: #ffffff; - padding-bottom: 30px; -} - -div#first_sidebar { - width: 200px; - margin: 5px; - padding: 5px; - display: inline; - float: left; - position: relative; -} -div#second_sidebar { - width: 100px; - margin: 5px; - padding: 5px; - display: inline; - float: left; - position: relative; -} -div.sidebar div.block { - margin-bottom: 5px; - padding: 0; - border: dotted 1px #999; - background-color: #fff; -} -div.sidebar div.block div.title { - padding: 3px 3px 3px 3px; - font-weight: bold; - background-color: #dedede; - border-bottom: dotted 1px #999; -} -div.sidebar div.block div.inside { - margin: 3px; -} - -div#content { padding: 5px 3px 5px 20px; - margin-top: 10px; - width: 50%; - display: inline; - float: left; - position: relative; - background-color: #ffffff; - padding-bottom: 30px; -} -div#footer { margin: 10px 0 10px 0; clear: both; display: block; text-align: center; padding: 10px; border-top: solid 1px #00f; color: #fff; background-color: #333;} -div#footer a { color: #ff0; } - -form div.error { - border-top: dotted 1px #f00; - border-bottom: dotted 1px #f00; - border-left: solid 3px #f00; -} -div.node div.title { - font-weight: bold; - font-size: 110%; - border-bottom: dotted 1 px #009; -} -div.description { - font-style: italic; - font-color: #999; -} - -div.node-wrapper { - margin: 5px 2px 5px 2px; - border: dotted 1px #dddddd; - padding: 5px 3px 5px 3px; -} -div.node div.title { - font-weight: bold; - font-size: 110%; - border-bottom: dotted 1 px #009; - float: left; -} -div.node div.description { - text-align: right; -} -div.node div.inner { - padding: 5px 5px 5px 10px; - border-top: dotted 1px #dddddd; -} - -form#login-form { - border: dotted 1px #099; - display: inline-block; - padding: 10px; - margin: 10px; -} - -div#message { - border: solid 1px #fc0; - background-color: #fed; - color: #000; - padding: 5px; - margin: 5px; -} - -div#message li { - padding-left: 5px; - margin-left: 3px; -} -div#message li.success { - color: #003300; - background-color: #ccffcc; -} - -div#message li.error { - color: #330000; - background-color: #ff9494; -} -div#message li.warning { - color: #aa2200; - background-color: #ffcc99; -} diff --git a/draft/src/gewf/README.md b/draft/src/gewf/README.md new file mode 100644 index 00000000..a5cfd020 --- /dev/null +++ b/draft/src/gewf/README.md @@ -0,0 +1,3 @@ +The gewf tool, is an experimentation to generate EWF project from template. + +status: experimental, POC, in-progress, draft diff --git a/draft/src/gewf/gewf.ecf b/draft/src/gewf/gewf.ecf new file mode 100644 index 00000000..140da892 --- /dev/null +++ b/draft/src/gewf/gewf.ecf @@ -0,0 +1,21 @@ + + + + Generator for EWF project + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + diff --git a/draft/src/gewf/license.lic b/draft/src/gewf/license.lic new file mode 100644 index 00000000..27384d13 --- /dev/null +++ b/draft/src/gewf/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" diff --git a/draft/src/gewf/src/gewf.e b/draft/src/gewf/src/gewf.e new file mode 100644 index 00000000..41f04891 --- /dev/null +++ b/draft/src/gewf/src/gewf.e @@ -0,0 +1,169 @@ +note + description : "Objects that ..." + author : "$Author$" + date : "$Date$" + revision : "$Revision$" + +class + GEWF + +create + make + +feature {NONE} -- Initialization + + make + -- Initialize `Current'. + local + args: ARGUMENTS_32 + cfg: detachable READABLE_STRING_32 + do + create args + if args.argument_count > 0 then + cfg := args.argument (1) + end + if cfg /= Void then + load_configuration (cfg) + end + execute + end + +feature -- Status + +feature -- Access + + config (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + local + l_keys: LIST [READABLE_STRING_GENERAL] + do + if attached {JSON_STRING} json_item (json, k) as js then + Result := js.unescaped_string_32 + end + end + + json_item (j: detachable JSON_VALUE; k: READABLE_STRING_GENERAL): detachable JSON_VALUE + local + l_keys: LIST [READABLE_STRING_GENERAL] + v: detachable JSON_VALUE + s: STRING_32 + js: JSON_STRING + do + if attached {JSON_OBJECT} j as jo then + l_keys := k.split ('.') + l_keys.start + create js.make_json_from_string_32 (l_keys.item.as_readable_string_32) + v := jo.item (js) + l_keys.remove + if l_keys.count > 0 then + if v /= Void then + create s.make (k.count) + across + l_keys as c + loop + s.append_string_general (c.item) + s.append_character ('.') + end + s.remove_tail (1) + Result := json_item (v, s) + end + else + Result := v + end + end + end + + load_configuration (fn: READABLE_STRING_GENERAL) + local + p: JSON_PARSER + f: PLAIN_TEXT_FILE + s: STRING + do + create s.make (1_024) + + create f.make_with_name (fn) + if f.exists and then f.is_access_readable then + f.open_read + from + until + f.exhausted + loop + f.read_stream_thread_aware (1_024) + s.append (f.last_string) + end + f.close + end + + create p.make_parser (s) + json := p.parse + end + + json: detachable JSON_VALUE + +feature -- Execution + + execute + local + tpl_name: READABLE_STRING_32 + vals: STRING_TABLE [READABLE_STRING_8] + uuid_gen: UUID_GENERATOR + do + if attached config ("template") as s32 then + create vals.make (5) + + tpl_name := s32 + create uuid_gen + vals.force (uuid_gen.generate_uuid.out, "UUID") + + if + attached config ("application.name") as appname + then + vals.force (appname.to_string_8, "APPNAME") + else + vals.force ("application", "APPNAME") + end + + if + attached config ("application.root_class") as approot + then + vals.force (approot.to_string_8, "APP_ROOT") + else + vals.force ("APPLICATION", "APP_ROOT") + end + generate (tpl_name, vals) + else + io.error.put_string ("Error no template value! %N") + end + end + + generate (tpl: READABLE_STRING_32; vals: STRING_TABLE [READABLE_STRING_8]) + local + gen: GEWF_GENERATOR + p: PATH + appname: detachable READABLE_STRING_GENERAL + do + create p.make_from_string ("template") + p := p.extended (tpl) + appname := vals.item ("APPNAME") + if appname = Void then + appname := "_generated" + end + create gen.make (p, create {PATH}.make_from_string (appname)) + gen.execute (vals) + end + +feature {NONE} -- Implementation + +invariant +-- invariant_clause: True + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/draft/src/gewf/src/gewf_generator.e b/draft/src/gewf/src/gewf_generator.e new file mode 100644 index 00000000..389c606e --- /dev/null +++ b/draft/src/gewf/src/gewf_generator.e @@ -0,0 +1,132 @@ +note + description: "Summary description for {GEWF_GENERATOR}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + GEWF_GENERATOR + +inherit + DIRECTORY_ITERATOR + redefine + process_directory, + process_file + end + +create + make + +feature {NONE} -- Initialization + + make (tpl: PATH; tgt: PATH) + do + template_folder := tpl + target_folder := tgt + end + +feature -- Execution + + execute (vals: STRING_TABLE [READABLE_STRING_8]) + do + values := vals + process_directory (template_folder) + values := Void + end + +feature -- Operation + + process_file (fn: PATH) + -- + local + s: STRING_32 + line: STRING + src,tgt: RAW_FILE + do + create s.make_from_string (fn.name) + s := s.substring (template_folder.name.count + 2, s.count) + if attached fn.extension as ext and then ext.is_case_insensitive_equal ("tpl") then + s.remove_tail (4) -- ".tpl" + end + + evaluate_string_32 (s) + s.to_lower + create src.make_with_path (fn) + create tgt.make_with_path (target_folder.extended (s)) + tgt.create_read_write + src.open_read + from + until + src.exhausted + loop + src.read_line_thread_aware + line := src.last_string + evaluate_string_8 (line) + tgt.put_string (line) + tgt.put_new_line + end + src.close + tgt.close + +-- Precursor (fn) + end + + process_directory (dn: PATH) + -- + local + s: STRING_32 + p: PATH + dir: DIRECTORY + do + create s.make_from_string (dn.name) + s := s.substring (template_folder.name.count + 1, s.count) + evaluate_string_32 (s) + p := target_folder.extended (s) + create dir.make_with_path (p) + dir.recursive_create_dir + Precursor (dn) + end + +feature -- Access + + values: detachable STRING_TABLE [READABLE_STRING_8] + + template_folder: PATH + target_folder: PATH + +feature -- Implementation + + evaluate_string_8 (s: STRING_8) + do + if attached values as l_values then + across + l_values as c + loop + s.replace_substring_all ({STRING_8} "${" + c.key.as_string_8 + "}", c.item) + end + end + end + + evaluate_string_32 (s: STRING_32) + do + if attached values as l_values then + across + l_values as c + loop + s.replace_substring_all ({STRING_32} "${" + c.key.as_string_32 + "}", c.item) + end + end + end + + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/draft/src/gewf/template/basic/${APPNAME}.ecf.tpl b/draft/src/gewf/template/basic/${APPNAME}.ecf.tpl new file mode 100644 index 00000000..d293c122 --- /dev/null +++ b/draft/src/gewf/template/basic/${APPNAME}.ecf.tpl @@ -0,0 +1,45 @@ + + + + + /EIFGENs$ + /CVS$ + /.svn$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draft/src/gewf/template/basic/ecf-target-any_connector.tpl b/draft/src/gewf/template/basic/ecf-target-any_connector.tpl new file mode 100644 index 00000000..eb7f6c90 --- /dev/null +++ b/draft/src/gewf/template/basic/ecf-target-any_connector.tpl @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/draft/src/gewf/template/basic/ecf-target-connector.tpl b/draft/src/gewf/template/basic/ecf-target-connector.tpl new file mode 100644 index 00000000..d4a6fd75 --- /dev/null +++ b/draft/src/gewf/template/basic/ecf-target-connector.tpl @@ -0,0 +1,6 @@ + + + + + + diff --git a/draft/src/gewf/template/basic/launcher/any/application_launcher.e b/draft/src/gewf/template/basic/launcher/any/application_launcher.e new file mode 100644 index 00000000..7182d350 --- /dev/null +++ b/draft/src/gewf/template/basic/launcher/any/application_launcher.e @@ -0,0 +1,85 @@ +note + description: "Summary description for {APPLICATION_LAUNCHER}." + author: "" + date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $" + revision: "$Revision: 36 $" + +deferred class + APPLICATION_LAUNCHER + +feature {NONE} -- Initialization + + launcher_nature: detachable READABLE_STRING_8 + -- Initialize the launcher nature + -- either cgi, libfcgi, or nino. + --| We could extend with more connector if needed. + --| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time. + local + p: PATH + l_entry_name: READABLE_STRING_32 + ext: detachable READABLE_STRING_32 + do + create p.make_from_string (execution_environment.arguments.command_name) + if attached p.entry as l_entry then + ext := l_entry.extension + end + if ext /= Void then + if ext.same_string (nature_nino) then + Result := nature_nino + end + if ext.same_string (nature_cgi) then + Result := nature_cgi + end + if ext.same_string (nature_libfcgi) or else ext.same_string ("fcgi") then + Result := nature_libfcgi + end + end + end + +feature {NONE} -- nino + + nature_nino: STRING = "nino" + + launch_nino (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + do + create {WSF_NINO_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) + end + +feature {NONE} -- cgi + + nature_cgi: STRING = "cgi" + + launch_cgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + do + create {WSF_CGI_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) + end + +feature {NONE} -- libfcgi + + nature_libfcgi: STRING = "libfcgi" + + launch_libfcgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + do + create {WSF_LIBFCGI_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) + end + +feature {NONE} -- Launcher + + launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + local + nature: like launcher_nature + do + nature := launcher_nature + if nature = Void or else nature = nature_nino then + launch_nino (a_service, opts) + elseif nature = nature_cgi then + launch_cgi (a_service, opts) + elseif nature = nature_libfcgi then + launch_libfcgi (a_service, opts) + else + -- bye bye + (create {EXCEPTIONS}).die (-1) + end + end + +end diff --git a/draft/src/gewf/template/basic/launcher/default/application_launcher.e b/draft/src/gewf/template/basic/launcher/default/application_launcher.e new file mode 100644 index 00000000..e20b06ac --- /dev/null +++ b/draft/src/gewf/template/basic/launcher/default/application_launcher.e @@ -0,0 +1,19 @@ +note + description: "Summary description for {APPLICATION}." + author: "" + date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $" + revision: "$Revision: 36 $" + +deferred class + APPLICATION_LAUNCHER + +feature {NONE} -- Launcher + + launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + local + launcher: WSF_SERVICE_LAUNCHER + do + create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) + end + +end diff --git a/draft/src/gewf/template/basic/src/${APP_ROOT}.e.tpl b/draft/src/gewf/template/basic/src/${APP_ROOT}.e.tpl new file mode 100644 index 00000000..d93b9ef5 --- /dev/null +++ b/draft/src/gewf/template/basic/src/${APP_ROOT}.e.tpl @@ -0,0 +1,45 @@ +note + description: "[ + application service + ]" + date: "$Date$" + revision: "$Revision$" + +class + ${APP_ROOT} + +inherit + WSF_LAUNCHABLE_SERVICE + redefine + initialize + end + + WSF_ROUTED_SERVICE + + APPLICATION_LAUNCHER + +create + make_and_launch + +feature {NONE} -- Initialization + + initialize + -- Initialize current service. + do + Precursor + set_service_option ("port", 9090) + initialize_router + end + + setup_router + -- Setup `router' + local + fhdl: WSF_FILE_SYSTEM_HANDLER + do + router.handle_with_request_methods ("/doc", create {WSF_ROUTER_SELF_DOCUMENTATION_HANDLER}.make (router), router.methods_GET) + create fhdl.make_hidden (".") + fhdl.set_directory_index (<<"index.html">>) + router.handle_with_request_methods ("", fhdl, router.methods_GET) + end + +end diff --git a/draft/src/gewf/testing/README.txt b/draft/src/gewf/testing/README.txt new file mode 100644 index 00000000..1d7b2986 --- /dev/null +++ b/draft/src/gewf/testing/README.txt @@ -0,0 +1,9 @@ +To generate "demo" + + +gewf demo.cfg + + +It will generate the project under demo\demo.ecf + +note for now, the "template" folder should be in the current folder. diff --git a/draft/src/gewf/testing/demo.cfg b/draft/src/gewf/testing/demo.cfg new file mode 100644 index 00000000..545f164c --- /dev/null +++ b/draft/src/gewf/testing/demo.cfg @@ -0,0 +1,4 @@ +{ +"template": "basic", +"application": {"name" : "demo", "root_class": "EWF_DEMO" } +} diff --git a/examples/restbucksCRUD/restbucks-safe.ecf b/examples/restbucksCRUD/restbucks-safe.ecf index 4c54445f..86dcda7f 100644 --- a/examples/restbucksCRUD/restbucks-safe.ecf +++ b/examples/restbucksCRUD/restbucks-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ /\.git$ /\.svn$ - diff --git a/library/network/http_client/http_client-safe.ecf b/library/network/http_client/http_client-safe.ecf index f1d90a8d..c9c641e3 100644 --- a/library/network/http_client/http_client-safe.ecf +++ b/library/network/http_client/http_client-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ /EIFGENs$ /.svn$ - diff --git a/library/network/http_client/src/http_client_request_context.e b/library/network/http_client/src/http_client_request_context.e index 3d1c69e4..78819831 100644 --- a/library/network/http_client/src/http_client_request_context.e +++ b/library/network/http_client/src/http_client_request_context.e @@ -69,7 +69,7 @@ feature -- Access -- Upload data --| Note: make sure to precise the Content-Type header - upload_filename: detachable READABLE_STRING_8 + upload_filename: detachable IMMUTABLE_STRING_32 -- Upload data read from `upload_filename' --| Note: make sure to precise the Content-Type header @@ -154,11 +154,15 @@ feature -- Element change upload_data := a_data end - set_upload_filename (a_fn: like upload_filename) + set_upload_filename (a_fn: detachable READABLE_STRING_GENERAL) require has_no_upload_filename: a_fn /= Void implies not has_upload_filename do - upload_filename := a_fn + if a_fn = Void then + upload_filename := Void + else + create upload_filename.make_from_string_general (a_fn) + end end set_write_agent (agt: like write_agent) diff --git a/library/network/http_client/src/spec/libcurl/libcurl_http_client_request.e b/library/network/http_client/src/spec/libcurl/libcurl_http_client_request.e index 87d3d4ee..083ca687 100644 --- a/library/network/http_client/src/spec/libcurl/libcurl_http_client_request.e +++ b/library/network/http_client/src/spec/libcurl/libcurl_http_client_request.e @@ -61,7 +61,7 @@ feature -- Execution retried: BOOLEAN l_form_data: detachable HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32] l_upload_data: detachable READABLE_STRING_8 - l_upload_filename: detachable READABLE_STRING_8 + l_upload_filename: detachable READABLE_STRING_GENERAL l_headers: like headers do if not retried then @@ -172,7 +172,7 @@ feature -- Execution or request_method.is_case_insensitive_equal ("PUT") end - create l_upload_file.make (l_upload_filename) + create l_upload_file.make_with_name (l_upload_filename) if l_upload_file.exists and then l_upload_file.is_readable then curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_upload, 1) @@ -388,7 +388,7 @@ feature {NONE} -- Implementation end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/network/http_client/src/spec/libcurl/libcurl_http_client_session.e b/library/network/http_client/src/spec/libcurl/libcurl_http_client_session.e index c7c6a210..d68eb98b 100644 --- a/library/network/http_client/src/spec/libcurl/libcurl_http_client_session.e +++ b/library/network/http_client/src/spec/libcurl/libcurl_http_client_session.e @@ -85,7 +85,7 @@ feature -- Basic operation f.close check ctx /= Void then ctx.set_upload_data (Void) - ctx.set_upload_filename (f.name) + ctx.set_upload_filename (f.path.name) end end Result := custom ("PUT", a_path, ctx) @@ -151,7 +151,7 @@ feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation ;note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/runtime/process/notification_email/notification_external_mailer.e b/library/runtime/process/notification_email/notification_external_mailer.e index 1e88e856..41f106f1 100644 --- a/library/runtime/process/notification_email/notification_external_mailer.e +++ b/library/runtime/process/notification_email/notification_external_mailer.e @@ -113,7 +113,7 @@ feature -- Basic operation f.put_string (a_email.message) f.close create args.make (1) - args.force (f.name) + args.force (f.path.name) end end p := l_factory.process_launcher (executable_path.name, args, Void) diff --git a/library/security/openid/consumer/openid-safe.ecf b/library/security/openid/consumer/openid-safe.ecf index 70e590a7..059358e4 100644 --- a/library/security/openid/consumer/openid-safe.ecf +++ b/library/security/openid/consumer/openid-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ /EIFGENs$ /.svn$ - diff --git a/library/server/wsf/connector/nino-safe.ecf b/library/server/wsf/connector/nino-safe.ecf index 5b3c13ee..c7a77a3a 100644 --- a/library/server/wsf/connector/nino-safe.ecf +++ b/library/server/wsf/connector/nino-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ /\.git$ /\.svn$ - diff --git a/library/server/wsf/default/nino-safe.ecf b/library/server/wsf/default/nino-safe.ecf index 94ac1a05..1aafe224 100644 --- a/library/server/wsf/default/nino-safe.ecf +++ b/library/server/wsf/default/nino-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ /\.git$ /\.svn$ - diff --git a/library/server/wsf/router/wsf_file_system_handler.e b/library/server/wsf/router/wsf_file_system_handler.e index f494b5b4..a3a4b57e 100644 --- a/library/server/wsf/router/wsf_file_system_handler.e +++ b/library/server/wsf/router/wsf_file_system_handler.e @@ -91,8 +91,12 @@ feature -- Access index_disabled: BOOLEAN -- Index disabled? + index_ignores_function: detachable FUNCTION [ANY, TUPLE [PATH], BOOLEAN] + -- Function to evaluate if a path is ignored or not during autoindex. + -- If `index_ignores' is Void and `index_ignores_function' is Void, use default ignore rules. + directory_index: detachable ARRAY [READABLE_STRING_8] - -- File serve if a directory index is requested + -- File serve if a directory index is requested. not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE]] @@ -137,6 +141,44 @@ feature -- Element change access_denied_handler := h end + set_default_index_ignores + -- Use default auto index ignores behavior. + do + index_ignores_function := Void + end + + set_index_ignores_function (fct: attached like index_ignores_function) + -- Use `fct' to compute auto index ignores behavior. + do + index_ignores_function := fct + end + +feature -- Status report + + ignoring_index_entry (p: PATH): BOOLEAN + -- Ignoring path `p' for auto index? + local + e: detachable PATH + n: READABLE_STRING_32 + do + if attached index_ignores_function as fct then + Result := fct.item ([p]) + else + -- default + e := p.entry + if e = Void then + e := p + end + if e.is_parent_symbol then + else + n := e.name + Result := n.starts_with ({STRING_32} ".") + or n.ends_with ({STRING_32} "~") + or n.ends_with ({STRING_32} ".swp") + end + end + end + feature -- Execution execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE) @@ -189,6 +231,11 @@ feature -- Execution uri, s: STRING_8 d: DIRECTORY l_files: LIST [PATH] + p: PATH + n: READABLE_STRING_32 + httpdate: HTTP_DATE + pf: RAW_FILE + l_is_dir: BOOLEAN do create d.make_with_path (dn) d.open_read @@ -202,11 +249,16 @@ feature -- Execution s := "[ - Index for folder: $URI + Index of $URI + -

    Index for $URI

    -
      +

      Index of $URI

      + + + ]" s.replace_substring_all ("$URI", uri) @@ -216,15 +268,54 @@ feature -- Execution until l_files.after loop - s.append ("
    • ") - s.append (html_encoder.encoded_string (l_files.item.name)) - s.append ("
    • %N") + p := l_files.item + if ignoring_index_entry (p) then + + else + n := p.name + create pf.make_with_path (p) + if pf.is_directory then + l_is_dir := True + else + l_is_dir := False + end + + s.append ("") + s.append ("") + s.append ("") + s.append ("") + s.append ("") + end l_files.forth end s.append ("[ - + +
      NameLast modifiedSize

      ") + if l_is_dir then + s.append ("[dir]") + else + s.append (" ") + end + s.append ("") + if p.is_parent_symbol then + s.append ("[Parent Directory] ..") + else + s.append (html_encoder.encoded_string (n)) + end + if l_is_dir then + s.append ("/") + end + + s.append ("") + create httpdate.make_from_date_time (file_date (pf)) + httpdate.append_to_rfc1123_string (s) + s.append ("") + if not l_is_dir then + s.append_integer (file_size (pf)) + end + s.append ("

      ]" @@ -480,6 +571,11 @@ feature {NONE} -- Implementation feature {NONE} -- implementation: date time + file_size (f: FILE): INTEGER + do + Result := f.count + end + file_date (f: FILE): DATE_TIME do Result := timestamp_to_date (f.date) diff --git a/tests/all-safe.ecf b/tests/all-safe.ecf index 06f538ee..2fcb5f33 100644 --- a/tests/all-safe.ecf +++ b/tests/all-safe.ecf @@ -1,5 +1,5 @@ - + Integration project including many lib @@ -8,7 +8,7 @@ /EIFGENs$ /.svn$ - @@ -26,7 +26,6 @@ - @@ -37,6 +36,7 @@ + @@ -57,7 +57,6 @@ - Compiling as Windows , on other platforms than Windows