Merge branch 'master' of https://github.com/EiffelWebFramework/EWF
Conflicts: draft/application/cms/README.md draft/application/cms/src/cms_session.e draft/src/gewf/license.lic library/network/http_client/src/expectation/http_client_response_expectation.e
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
57
doc/wiki/Doc_Getting_Started.mediawiki
Normal file
57
doc/wiki/Doc_Getting_Started.mediawiki
Normal file
@@ -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:
|
||||
|
||||
<code>git clone git://github.com/EiffelWebFramework/EWF.git</code>
|
||||
|
||||
== 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:
|
||||
<code>estudio -config simple.ecf -target simple</code>
|
||||
|
||||
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.
|
||||
7
doc/wiki/Doc_Index.mediawiki
Normal file
7
doc/wiki/Doc_Index.mediawiki
Normal file
@@ -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] ]
|
||||
@@ -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]] 
|
||||
- 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
|
||||
|
||||
4
doc/wiki/Meetings.md
Normal file
4
doc/wiki/Meetings.md
Normal file
@@ -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)
|
||||
@@ -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/
|
||||
|
||||
----
|
||||
|
||||
@@ -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
|
||||
----
|
||||
|
||||
14
doc/wiki/Useful-links.md
Normal file
14
doc/wiki/Useful-links.md
Normal file
@@ -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
|
||||
62
doc/wiki/Web-meeting-2012-09-18.md
Normal file
62
doc/wiki/Web-meeting-2012-09-18.md
Normal file
@@ -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.
|
||||
|
||||
2
draft/application/cms/README.md
Normal file
2
draft/application/cms/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
The "cms" component moved.
|
||||
Please visit https://github.com/EiffelWebFramework/cms to follow the project.
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="cms" uuid="0D24AE3C-61DA-4E81-8DCF-90C2E65FB669" library_target="cms">
|
||||
<target name="cms">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="exception_trace" value="true"/>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="encoder" location="..\..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\library\network\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
<library name="openid" location="..\..\..\library\security\openid\consumer\openid-safe.ecf" readonly="false"/>
|
||||
<library name="process" location="$ISE_LIBRARY\library\process\process-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="uri_template" location="..\..\..\library\text\parser\uri_template\uri_template-safe.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_html" location="..\..\..\library\server\wsf_html\wsf_html-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_session" location="..\..\..\library\server\wsf\wsf_session-safe.ecf" readonly="false"/>
|
||||
<library name="notification_email" location="..\..\..\library\runtime\process\notification_email\notification_email-safe.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="cms" library_target="cms" uuid="0D24AE3C-61DA-4E81-8DCF-90C2E65FB669">
|
||||
<target name="cms">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<setting name="exception_trace" value="true"/>
|
||||
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="encoder" location="..\..\..\library\text\encoder\encoder.ecf" readonly="false"/>
|
||||
<library name="wsf_html" location="..\..\..\library\server\wsf_html\wsf_html.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\library\network\protocol\http\http.ecf" readonly="false"/>
|
||||
<library name="openid" location="..\..\..\library\security\openid\consumer\openid.ecf" />
|
||||
<library name="process" location="$ISE_LIBRARY\library\process\process.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid.ecf"/>
|
||||
<library name="uri_template" location="..\..\..\library\text\parser\uri_template\uri_template.ecf"/>
|
||||
<library name="wsf" location="..\..\..\library\server\wsf\wsf.ecf" readonly="false"/>
|
||||
<library name="wsf_session" location="..\..\..\library\server\wsf\wsf_session.ecf" readonly="false"/>
|
||||
<library name="notification_email" location="..\..\..\library\runtime\process\notification_email\notification_email.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,6 +0,0 @@
|
||||
#include <windows.h>
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
1 "This Program was made using EiffelStudio using Visual Studio C++"
|
||||
END
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ("<hr/>")
|
||||
append_info_to ("Configuration file", l_loc.name, e, s)
|
||||
end
|
||||
|
||||
s.append ("<hr/>")
|
||||
|
||||
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 ("<hr/>")
|
||||
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 ("<hr/>")
|
||||
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 ("<hr/>")
|
||||
append_info_to ("Files location", cms.files_location.utf_8_name, e, s)
|
||||
s.append ("<hr/>")
|
||||
|
||||
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 ("<li>")
|
||||
t.append ("<strong>" + n + "</strong>: ")
|
||||
if v /= Void then
|
||||
t.append (e.html_encoded (v))
|
||||
end
|
||||
t.append ("</li>")
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
3
draft/src/gewf/README.md
Normal file
3
draft/src/gewf/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
The gewf tool, is an experimentation to generate EWF project from template.
|
||||
|
||||
status: experimental, POC, in-progress, draft
|
||||
21
draft/src/gewf/gewf.ecf
Normal file
21
draft/src/gewf/gewf.ecf
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="gewf" uuid="2D4957D5-77D3-4EC7-BF80-E4E6AC7A3EF3">
|
||||
<target name="gewf">
|
||||
<description>Generator for EWF project </description>
|
||||
<root class="GEWF" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="standard">
|
||||
</option>
|
||||
<setting name="executable_name" value="gewf"/>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid-safe.ecf"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
10
draft/src/gewf/license.lic
Normal file
10
draft/src/gewf/license.lic
Normal file
@@ -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
|
||||
]"
|
||||
169
draft/src/gewf/src/gewf.e
Normal file
169
draft/src/gewf/src/gewf.e
Normal file
@@ -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
|
||||
132
draft/src/gewf/src/gewf_generator.e
Normal file
132
draft/src/gewf/src/gewf_generator.e
Normal file
@@ -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)
|
||||
-- <Precursor>
|
||||
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)
|
||||
-- <Precursor>
|
||||
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
|
||||
45
draft/src/gewf/template/basic/${APPNAME}.ecf.tpl
Normal file
45
draft/src/gewf/template/basic/${APPNAME}.ecf.tpl
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="${APPNAME}" uuid="${UUID}" library_target="${APPNAME}">
|
||||
<target name="common" abstract="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||
</target>
|
||||
<target name="${APPNAME}_any" extends="common">
|
||||
<root class="${APP_ROOT}" feature="make_and_launch"/>
|
||||
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
|
||||
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
|
||||
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="${APPNAME}_nino" extends="common">
|
||||
<root class="${APP_ROOT}" feature="make_and_launch"/>
|
||||
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="${APPNAME}_cgi" extends="common">
|
||||
<root class="${APP_ROOT}" feature="make_and_launch"/>
|
||||
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="${APPNAME}_libfcgi" extends="common">
|
||||
<root class="${APP_ROOT}" feature="make_and_launch"/>
|
||||
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
<target name="${APPNAME}" extends="${APPNAME}_nino"/>
|
||||
</system>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<target name="${APPNAME}_any" extends="_common">
|
||||
<root class="${APP_ROOT}" feature="make_and_launch"/>
|
||||
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
|
||||
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
|
||||
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
6
draft/src/gewf/template/basic/ecf-target-connector.tpl
Normal file
6
draft/src/gewf/template/basic/ecf-target-connector.tpl
Normal file
@@ -0,0 +1,6 @@
|
||||
<target name="${APPNAME}_${EWF.connector}" extends="_common">
|
||||
<root class="${APP_ROOT}" feature="make_and_launch"/>
|
||||
<library name="default_${EWF.connector}" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\${EWF.connector}-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
@@ -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
|
||||
@@ -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
|
||||
45
draft/src/gewf/template/basic/src/${APP_ROOT}.e.tpl
Normal file
45
draft/src/gewf/template/basic/src/${APP_ROOT}.e.tpl
Normal file
@@ -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
|
||||
9
draft/src/gewf/testing/README.txt
Normal file
9
draft/src/gewf/testing/README.txt
Normal file
@@ -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.
|
||||
4
draft/src/gewf/testing/demo.cfg
Normal file
4
draft/src/gewf/testing/demo.cfg
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"template": "basic",
|
||||
"application": {"name" : "demo", "root_class": "EWF_DEMO" }
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433" library_target="restbucks">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433" library_target="restbucks">
|
||||
<target name="restbucks">
|
||||
<root class="RESTBUCKS_SERVER" feature="make"/>
|
||||
<file_rule>
|
||||
@@ -7,7 +7,7 @@
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="provisional">
|
||||
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<debug name="nino" enabled="true"/>
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
|
||||
<target name="http_client">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
@@ -7,7 +7,7 @@
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="provisional">
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL-safe.ecf">
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="openid" uuid="FCDB4F81-31EC-462B-9183-D506E6798C0B" library_target="openid">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="openid" uuid="FCDB4F81-31EC-462B-9183-D506E6798C0B" library_target="openid">
|
||||
<target name="openid">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
@@ -7,7 +7,7 @@
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="standard">
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL-safe.ecf" readonly="false"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_nino" uuid="BACF0220-900B-4409-8CB2-30A09836A650" library_target="wsf_nino">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="wsf_nino" uuid="BACF0220-900B-4409-8CB2-30A09836A650" library_target="wsf_nino">
|
||||
<target name="wsf_nino">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
@@ -7,7 +7,7 @@
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="provisional">
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_nino" location="..\..\ewsgi\connectors\nino\nino-safe.ecf"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="default_nino" uuid="ACBEDC97-956C-45F5-97E3-65A6D9987625" library_target="default_nino">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="default_nino" uuid="ACBEDC97-956C-45F5-97E3-65A6D9987625" library_target="default_nino">
|
||||
<target name="default_nino">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
@@ -7,7 +7,7 @@
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="provisional">
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="wsf" location="..\wsf-safe.ecf"/>
|
||||
|
||||
@@ -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 := "[
|
||||
<html>
|
||||
<head>
|
||||
<title>Index for folder: $URI</title>
|
||||
<title>Index of $URI</title>
|
||||
<style>
|
||||
td { padding-left: 10px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Index for $URI</h1>
|
||||
<ul>
|
||||
<h1>Index of $URI</h1>
|
||||
<table>
|
||||
<tr><th/><th>Name</th><th>Last modified</th><th>Size</th></tr>
|
||||
<tr><th colspan="4"><hr></th></tr>
|
||||
]"
|
||||
s.replace_substring_all ("$URI", uri)
|
||||
|
||||
@@ -216,15 +268,54 @@ feature -- Execution
|
||||
until
|
||||
l_files.after
|
||||
loop
|
||||
s.append ("<li><a href=%"" + uri)
|
||||
url_encoder.append_percent_encoded_string_to (l_files.item.name, s)
|
||||
s.append ("%">")
|
||||
s.append (html_encoder.encoded_string (l_files.item.name))
|
||||
s.append ("</a></li>%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 ("<tr><td>")
|
||||
if l_is_dir then
|
||||
s.append ("[dir]")
|
||||
else
|
||||
s.append (" ")
|
||||
end
|
||||
s.append ("</td>")
|
||||
s.append ("<td><a href=%"" + uri)
|
||||
url_encoder.append_percent_encoded_string_to (n, s)
|
||||
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 ("</td>")
|
||||
s.append ("<td>")
|
||||
create httpdate.make_from_date_time (file_date (pf))
|
||||
httpdate.append_to_rfc1123_string (s)
|
||||
s.append ("</td>")
|
||||
s.append ("<td>")
|
||||
if not l_is_dir then
|
||||
s.append_integer (file_size (pf))
|
||||
end
|
||||
s.append ("</td>")
|
||||
s.append ("</tr>")
|
||||
end
|
||||
l_files.forth
|
||||
end
|
||||
s.append ("[
|
||||
</ul>
|
||||
<tr><th colspan="4"><hr></th></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
]"
|
||||
@@ -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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="all" uuid="1172C52C-6979-4293-8F01-80FADA5A2B69">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="all" uuid="1172C52C-6979-4293-8F01-80FADA5A2B69">
|
||||
<description>Integration project including many lib</description>
|
||||
<target name="all">
|
||||
<root all_classes="true"/>
|
||||
@@ -8,7 +8,7 @@
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="standard">
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="atom" location="..\draft\library\protocol\syndication\atom\atom-safe.ecf" readonly="false"/>
|
||||
<library name="client" location="..\examples\restbucksCRUD\client\client-safe.ecf" readonly="false"/>
|
||||
@@ -26,7 +26,6 @@
|
||||
<library name="demo-1" location="..\library\security\openid\consumer\demo\demo-safe.ecf" readonly="false"/>
|
||||
<library name="encoder" location="..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="error" location="..\library\utility\general\error\error-safe.ecf" readonly="false"/>
|
||||
<library name="ewf_support" location="..\library\server\ewf_support\ewf_support-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi" location="..\library\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi_spec" location="..\library\server\ewsgi\ewsgi_spec-safe.ecf" readonly="false"/>
|
||||
<library name="filter" location="..\examples\filter\filter-safe.ecf" readonly="false"/>
|
||||
@@ -37,6 +36,7 @@
|
||||
<library name="json" location="..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="libfcgi" location="..\library\server\libfcgi\libfcgi-safe.ecf" readonly="false"/>
|
||||
<library name="nino" location="..\contrib\library\network\server\nino\nino-safe.ecf" readonly="false"/>
|
||||
<library name="notification_email" location="..\library\runtime\process\notification_email\notification_email-safe.ecf" readonly="false"/>
|
||||
<library name="oauth" location="..\draft\library\security\oauth\oauth-safe.ecf" readonly="false"/>
|
||||
<library name="openid" location="..\library\security\openid\consumer\openid-safe.ecf" readonly="false"/>
|
||||
<library name="precomp_wsf" location="..\precomp\wsf-safe.ecf" readonly="false"/>
|
||||
@@ -57,7 +57,6 @@
|
||||
<library name="wsf_openshift" location="..\library\server\wsf\connector\openshift-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_router_context" location="..\library\server\wsf\wsf_router_context-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_session" location="..\library\server\wsf\wsf_session-safe.ecf" readonly="false"/>
|
||||
<library name="notification_email" location="..\library\runtime\process\notification_email\notification_email-safe.ecf" readonly="false"/>
|
||||
</target>
|
||||
<target name="all_windows" extends="all">
|
||||
<description>Compiling as Windows , on other platforms than Windows</description>
|
||||
|
||||
Reference in New Issue
Block a user