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:
jvelilla
2013-07-08 18:08:35 -03:00
50 changed files with 849 additions and 2501 deletions

View File

@@ -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

View 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.

View 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] ]

View File

@@ -6,7 +6,7 @@ The official documentation/wiki is located at https://github.com/EiffelWebFramew
## Organization ##
- Mailing list: please visit and subscribe to the mailing list page [[http://groups.google.com/group/eiffel-web-framework]] ![logo](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif)
- Most of the topics are discussed on the mailing list (google group).
- For time to time we have web meeting, and less frequently physical meetings that occurs usually during other Eiffel related events.
- For time to time we have [[web meetings|meetings]], and less frequently [[physical meetings|meetings]] that occurs usually during other Eiffel related events.
## Documentation ##
- to redo

4
doc/wiki/Meetings.md Normal file
View 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)

View File

@@ -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/
----

View File

@@ -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
View 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

View 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.

View File

@@ -0,0 +1,2 @@
The "cms" component moved.
Please visit https://github.com/EiffelWebFramework/cms to follow the project.

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,6 +0,0 @@
#include <windows.h>
STRINGTABLE
BEGIN
1 "This Program was made using EiffelStudio using Visual Studio C++"
END

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 ("&lt;" + c.item + "&gt; ")
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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
View 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>

View 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
View 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

View 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

View 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>

View File

@@ -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>

View 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>

View File

@@ -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

View File

@@ -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

View 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

View 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.

View File

@@ -0,0 +1,4 @@
{
"template": "basic",
"application": {"name" : "demo", "root_class": "EWF_DEMO" }
}

View File

@@ -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>

View File

@@ -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">

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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"/>

View File

@@ -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"/>

View File

@@ -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"/>

View File

@@ -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 ("&nbsp;")
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)

View File

@@ -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>