diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index b00a415..482e63e 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -1,14 +1,14 @@ - + Example/demo for Eiffel ROC CMS library - /EIFGENs$ - /CVS$ /.svn$ + /CVS$ + /EIFGENs$ - @@ -29,20 +29,17 @@ - - + + - @@ -57,6 +54,7 @@ + diff --git a/examples/demo/modules/file_upload/cms_file_upload.e b/examples/demo/modules/file_upload/cms_file_upload.e new file mode 100644 index 0000000..0edf440 --- /dev/null +++ b/examples/demo/modules/file_upload/cms_file_upload.e @@ -0,0 +1,254 @@ +note + description: "file_upload application root class" + date: "$Date$" + revision: "$Revision$" + +class + CMS_FILE_UPLOAD + +inherit + CMS_MODULE + redefine + install, + initialize, + setup_hooks + end + + CMS_HOOK_BLOCK + + CMS_HOOK_MENU_SYSTEM_ALTER + + -- WSF_ROUTED_URI_TEMPLATE_HELPER + + SHARED_EXECUTION_ENVIRONMENT + +create + make + +feature {NONE} -- Initialization + + make + do + name := "file_uploader" + version := "1.0" + description := "Service to upload some files" + package := "file upload" + end + +feature -- Access + + name: STRING + +feature {CMS_API} -- Module Initialization + + initialize (api: CMS_API) + -- + do + Precursor (api) + end + +feature {CMS_API }-- Module management + + install (api: CMS_API) + -- install the module + local + sql: STRING + do + -- create a database table + if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then + if not l_sql_storage.sql_table_exists ("file_upload_table") then + sql := "[ +CREATE TABLE file_upload_table( + `id` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL CHECK("id">=0), + `name` VARCHAR(100) NOT NULL, + `uploaded_date` DATE, + `size` INTEGER +); + ]" + l_sql_storage.sql_execute_script (sql, Void) + if l_sql_storage.has_error then + api.logger.put_error ("Could not initialize database for file uploader module", generating_type) + end + end + Precursor {CMS_MODULE}(api) + end + end + +feature -- Access: router + + + setup_router (a_router: WSF_ROUTER; a_api: CMS_API) + -- + local + www: WSF_FILE_SYSTEM_HANDLER + do + + map_uri_template_agent (a_router, "/upload{?nb}", agent execute_upload_handler, void) + + create www.make_with_path (document_root) + www.set_directory_index (<<"index.html">>) + www.set_not_found_handler (agent execute_not_found_handler) + a_router.handle("", www, a_router.methods_get) + end + +feature -- Hooks + + setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER) + do + a_hooks.subscribe_to_menu_system_alter_hook (Current) + a_hooks.subscribe_to_block_hook (Current) + end + + block_list: ITERABLE [like {CMS_BLOCK}.name] + do + Result := <<"Uploader info TODO">> + end + + get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) + do + + end + + menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) + local + link: CMS_LOCAL_LINK + do + create link.make ("Upload", "/upload") + a_menu_system.primary_menu.extend (link) + end + +feature -- Configuration + + document_root: PATH + -- Document root to look for files or directories + once + Result := execution_environment.current_working_path.extended ("docs") + end + + files_root: PATH + -- Uploaded files will be stored in `files_root' folder + once + Result := document_root.extended ("files") + end + +feature -- Handler + + execute_not_found_handler (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE) + -- `uri' is not found, redirect to default page + do + res.redirect_now_with_content (req.script_url ("/"), uri + ": not found. %N Redirectioin to" + req.script_url ("/"), "text/html") + end + + execute_upload_handler(req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API) + local + body: STRING_8 + safe_filename: STRING_8 + path: PATH + page: WSF_HTML_PAGE_RESPONSE + n: INTEGER + do + if req.is_request_method ("GET") or else not req.has_uploaded_file then + create page.make + page.set_title ("EWF: Upload file") + page.add_style (req.script_url ("style.css"), "all") + create body.make_empty + page.set_body (body) + + -- create the body + body.append ("

EWF: Upload files

%N") + body.append ("
%N") + + -- tetermine how many files to upload by a query parameter ?nb=number_of_files + if attached {WSF_STRING} req.query_parameter ("nb") as p_nb and then p_nb.is_integer then + n := p_nb.integer_value + else + n := 1 + end + + -- llist for the number of wanted files a upload button + from + until + n = 0 + loop + body.append ("
%N") + n := n-1 + end + + -- set the submit button + body.append ("%N") + + res.send (page) + else + create body.make_empty + body.append ("

EWF: Uploaded files

%N") + body.append ("
    %N") + + n := 0 + + across + req.uploaded_files as u_file + loop + body.append ("
  • %N") + body.append ("
    " + u_file.item.name + "=" + html_encode (u_file.item.filename) + " size=" + u_file.item.size.out + " type" + u_file.item.content_type + "
    %N") + safe_filename := u_file.item.safe_filename + path := files_root.extended (safe_filename) + + -- TODO: list dhe uploaded items + + body.append ("
  • %N") + end + + body.append ("
%N") + + -- create page + create page.make + page.add_style ("../style.css", "all") + page.set_body (body) + res.send (page) + end + end + +feature {NONE} -- Encoder + + url_encode (s: READABLE_STRING_32): STRING_8 + -- URL Encode `s' as Result + do + Result := url_encoder.encoded_string (s) + end + + url_encoder: URL_ENCODER + once + create Result + end + + html_encode (s: READABLE_STRING_32): STRING_8 + -- HTML Encode `s' as Result + do + Result := html_encoder.encoded_string (s) + end + + html_encoder: HTML_ENCODER + once + create Result + end + +feature -- Mapping helper: uri template agent + + map_uri_template (a_router: WSF_ROUTER; a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `h' as handler for `a_tpl', according to `rqst_methods'. + require + a_tpl_attached: a_tpl /= Void + h_attached: h /= Void + do + a_router.map (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods) + end + + map_uri_template_agent (a_router: WSF_ROUTER; a_tpl: READABLE_STRING_8; proc: PROCEDURE [TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `proc' as handler for `a_tpl', according to `rqst_methods'. + require + a_tpl_attached: a_tpl /= Void + proc_attached: proc /= Void + do + map_uri_template (a_router, a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods) + end +end diff --git a/examples/demo/modules/file_upload/file_uploader.ecf b/examples/demo/modules/file_upload/file_uploader.ecf new file mode 100644 index 0000000..ab71576 --- /dev/null +++ b/examples/demo/modules/file_upload/file_uploader.ecf @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + /.svn$ + /CVS$ + /EIFGENs$ + + + + diff --git a/examples/demo/site/files/.cache/feed_aggregator/feed__forum__5_True b/examples/demo/site/files/.cache/feed_aggregator/feed__forum__5_True new file mode 100644 index 0000000..011edfd --- /dev/null +++ b/examples/demo/site/files/.cache/feed_aggregator/feed__forum__5_True @@ -0,0 +1,64 @@ +
+
    +
  • +
    Jan 07
    +RE: [eiffel-users] Book suggestion +
    I agree with each of the three you’ve mentioned: 1. Thick-client GUI 2. Browser/Webserver/Web-services 3. Mobile applications (phones/tablets) I will add: RaspberryPi! The RaspberryPi is relatively young and needs Eiffel. I have seen folks ganging these little $5 PC’s together to produce
    +
  • +
  • +
    Jan 07
    +Book suggestion +
    What the world needs, besides peace, is a new edition of the excellent book *Windows Programming Made Easy* by Maughan and Simon, rewritten for Vision2. I've looked in vain for an equally thorough reference for Vision2. The Vision2 section at docs.eiffel.com is good as far as it goes, but nowhere
    +
  • +
  • +
    Jan 06
    +Re: [eiffel-users] Easiest way to do type comparisons? +
    I've been looking at the code. There are around 1,500 lines of code affected, and in fact, a pretty high dependence on using type ids rather than testing types of objects. Fixing this is going to be major surgery, but I have to do something because it's broken every project we have in Eiffel,
    +
  • +
  • +
    Jan 06
    +Creating dynamic objects (Eiffel) +

    I have to find a way to create objects dynamically, that means the user can decide how many objects to create once the program starts. What I tried to do is:

    + +
                    if count = 6 then
    +                create player1.player
    +                create player2.player 
    +                create player3.player
    +                create player4.player
    +                create player5.player
    +                create player6.player
    +                  elseif count > 4 then
    +                    create player1.player
    +                    create player2.player 
    +                    create player3.player
    +                    create player4.player
    +                    create player5.player
    +                      elseif count > 3 then
    +                        create player1.player
    +                        create player2.player 
    +                        create player3.player
    +                        create player4.player
    +                          elseif count > 2 then
    +                            create player1.player
    +                            create player2.player 
    +                            create player3.player
    +                           else
    +                             create player1.player
    +                             create player2.player 
    +               end
    +
    + +

    Once the user has choosen the number of players, the variable count gets updated and the feature that creates the objects gets called.

    + +

    I used this kind of brute force method, instead of a loop, because I need the "names" of the objects, I have to called them again in the program.

    + +

    Anyways the compiler gives me a VEVI error, variable is not properly set. +Some help?

    +
  • +
  • +
    Jan 05
    +RE: [eiffel-users] Easiest way to do type comparisons? +
    In the old way, you will get the detachable type ID. In the new way (only available in experimental mode), you will always get an attached type ID. This is why, even if you are increasing the size of your table which should have a minimal impact on performance, it will work now and then. >
    +
  • +See more ... +
diff --git a/examples/demo/site/files/.cache/feed_aggregator/feed__news__0_True b/examples/demo/site/files/.cache/feed_aggregator/feed__news__0_True new file mode 100644 index 0000000..15b8439 --- /dev/null +++ b/examples/demo/site/files/.cache/feed_aggregator/feed__news__0_True @@ -0,0 +1,138 @@ +
+
    +
  • +
    2015, Nov 17
    +Some lazy data structures implemented in Eiffel - Part I - Iterating the Calkin-Wilf tree +

    This is the first part of a series in which I intend to make some explorations of lazy, infinite data structures in Eiffel. If you want to compile the code in these articles, you will need EiffelStudio 15.11 or later. +

    In this first article, I am going to iterate an infinite data structure - the strictly-positive rational numbers, represented by an infinite tree - The Calkin-Wilf tree. The easiest way to follow the code is to view it directly on GitHub. An alternative is to checkout the repository and compile it in EiffelStudio. To do the latter (instructions are for Linux from a bash terminal, but should be similar for other O/S I think): +

    +
    1. git clone git@github.com:colin-adams/lazy_eiffel.git +
    2. git checkout V1 +
    3. cd lazy_eiffel/examples/calkin_wilf/src +
    4. estudio calkin_wilf.ecf & +
    5. Press OK +
    +

    The first class worth looking at briefly is LAZY_BINARY_TREE. This represents a single node in an infinite binary tree, together with a link to it's parent, and two FUNCTIONs to find the left and right children. Incidentally, you may be surprised at the syntax used for declaring these FUNCTIONs unless you have already read this thread. This is why 15.11 or later is needed to compile the code. I think it's worth showing one of those agents here: +

            left_child_function: FUNCTION [LAZY_BINARY_TREE [G], LAZY_BINARY_TREE [G]]
    +

    This syntax is starting to look lightweight. Looking quite comparable to Haskell, for example (leftChildFunction :: LazyBinaryTree a -> LazyBinaryTree a), and none of that horrible camelCase. +

    Then let's look at the CALKIN_WILF tree itself. The core of the class is a root node, two functions to navigate from any node in the tree to the left and right children (or to lazily build the tree structure, depending on how you want to look at it), and a creation procedure to initialize root to 1/1. +

    feature {NONE} -- Initialization
    +
    +        make
    +                        -- Create `root'.
    +                do
    +                        left_child_agent := agent left_child
    +                        right_child_agent := agent right_child
    +                        create root.make ((create {RATIONAL_NUMBER}.make (1, 1)), Void, left_child_agent, right_child_agent)
    +                        start
    +                end
    +
    +feature -- Access
    +
    +        root: LAZY_BINARY_TREE [RATIONAL_NUMBER]
    +                        -- 1/1
    +
    +        left_child_agent: FUNCTION [LAZY_BINARY_TREE [RATIONAL_NUMBER], LAZY_BINARY_TREE [RATIONAL_NUMBER]]
    +                        -- Function from a node to its left child
    +
    +        right_child_agent: FUNCTION [LAZY_BINARY_TREE [RATIONAL_NUMBER], LAZY_BINARY_TREE [RATIONAL_NUMBER]]
    +                        -- Function from a node to its left child
    +
    +        left_child (a_node: LAZY_BINARY_TREE [RATIONAL_NUMBER]): LAZY_BINARY_TREE [RATIONAL_NUMBER]
    +                        -- Left child of `a_node'
    +                do
    +                        create Result.make (create {RATIONAL_NUMBER}.make (
    +                                a_node.item.numerator, a_node.item.numerator + a_node.item.denominator),
    +                                a_node, left_child_agent, right_child_agent)
    +                end
    +
    +        right_child (a_node: LAZY_BINARY_TREE [RATIONAL_NUMBER]): LAZY_BINARY_TREE [RATIONAL_NUMBER]
    +                        -- Right child of `a_node'
    +                do
    +                        create Result.make (create {RATIONAL_NUMBER}.make (
    +                                a_node.item.numerator + a_node.item.denominator, a_node.item.denominator),
    +                                a_node, left_child_agent, right_child_agent)
    +                end
    +

    However, I muddled this nice little picture by inheriting from LINEAR [LAZY_BINARY_TREE [RATIONAL_NUMBER]]. So the class CALKIN_WILF has a lazy tree of rationals, and is a linear iteration of them. In the root class CALKIN_WILF_DEMO_ROOT we simply print the first 100 rational numbers (I could have made the program take an argument) using a LINEAR_ITERATOR [LAZY_BINARY_TREE [RATIONAL_NUMBER]]. However, the iteration is not in numerical order. In a future post we'll see other ways of iterating the rationals. +

    The really interesting thing (to me) about the Calkin-Wilf tree is the way I did a breadth-first traversal of this infinite tree. It turns out that the index in the linear structure, when translated into binary, can be considered as a set of instructions to move through the tree. You ignore all leading zeros. At the first one, move to the root. Then every time you see a zero, you take the left child, and every time you see a one, you take the right child. Lovely! +

    +
  • +
  • +
    2015, Sep 15
    +Design by Contract: ACM Webinar this Thursday +

    A third ACM webinar this year (after two on agile methods): I will be providing a general introduction to Design by Contract. The date is this coming Thursday, September 17, and the time is noon New York (18 Paris/Zurich, 17 London, 9 Los Angeles, see here for hours elsewhere). Please tune in! The event is […]

    +

    The post Design by Contract: ACM Webinar this Thursday appeared first on Bertrand Meyer's technology+ blog.

    +
  • +
  • +
    2015, Jan 21
    +Framing the frame problem (new paper) +

    Among the open problems of verification, particularly the verification of object-oriented programs, one of the most vexing is framing: how to specify and verify what programs element do not change. Continuing previous work, this article presents a “double frame inference” method, automatic on both sides the specification and verification sides. There is no need to […]

    +

    The post Framing the frame problem (new paper) appeared first on Bertrand Meyer's technology+ blog.

    +
  • +
  • +
    2015, Jan 21
    +Detecting deadlock automatically? (New paper) +
  • +
  • +
    2015, Jan 11
    +A colored year on the web for Eiffel +

    Happy new year! +

    ACE, Prism, and Rouge now support the syntax highlighting of the Eiffel language. +

    +
    Contents
    + +

    Prism

    +

    Prism is by-design a lightweight syntax highlighter for the web. +It is very simple to use, and the download page enables to get only what you need. It proposes interesting add-ons (Line numbers, File Highlight, ...). +

    The library is usable with a bench of tools, including Wordpress and Jekyll. +

    You can test the highlighting here. The Eiffel support should be full, including the verbatim options. +

    If you note any issues, you can report it on my github fork. +

    I have commited a Pull Request to enable class name highlighting. +Please feel free to express your support in the discussion thread of the Pull Request. +The PR is waiitng for author agreement since January... +

    +

    ACE editor

    +

    ACE Editor is certainly the most use web-based code editor. +A bench of web applications use ACE including: +

    + +

    The support of Eiffel is not full. In particular, the verbatim options and multiple-line strings are not supported. +

    If you note any issues, you can report it on my github fork. +

    +

    Rouge

    +

    Rouge is a recent syntax highlighter increasing in popularity. +It is compatible with the stylesheets of Pygments. +

    It is used by: +

    + +

    The support of Eiffel is not full. In particular, the verbatim options are not supported. +

    If you note any issues, you can report it on my github fork. +

    +

    Other syntax highlighters

    +

    Some tools need updates in order to fully support the highlighting of Eiffel. +For instance: +

    + +

    Enjoy ;) +

    +
  • +See more ... +
diff --git a/examples/demo/src/demo_cms_execution.e b/examples/demo/src/demo_cms_execution.e index c73948f..8a1490e 100644 --- a/examples/demo/src/demo_cms_execution.e +++ b/examples/demo/src/demo_cms_execution.e @@ -91,6 +91,10 @@ feature -- CMS modules a_setup.register_module (m) create {CMS_SESSION_AUTH_MODULE} m.make + a_setup.register_module (m) + + -- uploader + create {CMS_FILE_UPLOAD} m.make a_setup.register_module (m) end diff --git a/modules/file_upload/cms_file_upload.e b/modules/file_upload/cms_file_upload.e index 8540f4c..0edf440 100644 --- a/modules/file_upload/cms_file_upload.e +++ b/modules/file_upload/cms_file_upload.e @@ -18,7 +18,7 @@ inherit CMS_HOOK_MENU_SYSTEM_ALTER - WSF_ROUTED_URI_TEMPLATE_HELPER + -- WSF_ROUTED_URI_TEMPLATE_HELPER SHARED_EXECUTION_ENVIRONMENT @@ -47,7 +47,7 @@ feature {CMS_API} -- Module Initialization Precursor (api) end -feature -- Module management +feature {CMS_API }-- Module management install (api: CMS_API) -- install the module @@ -76,16 +76,18 @@ CREATE TABLE file_upload_table( feature -- Access: router + setup_router (a_router: WSF_ROUTER; a_api: CMS_API) -- local www: WSF_FILE_SYSTEM_HANDLER do - map_uri_template_agent ("/upload{?nb}", agent execute_upload_handler, void) + + map_uri_template_agent (a_router, "/upload{?nb}", agent execute_upload_handler, void) create www.make_with_path (document_root) www.set_directory_index (<<"index.html">>) - www.set_not_found_handler (agent execute_not_found) + www.set_not_found_handler (agent execute_not_found_handler) a_router.handle("", www, a_router.methods_get) end @@ -93,12 +95,13 @@ feature -- Hooks setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER) do - + a_hooks.subscribe_to_menu_system_alter_hook (Current) + a_hooks.subscribe_to_block_hook (Current) end block_list: ITERABLE [like {CMS_BLOCK}.name] do - + Result := <<"Uploader info TODO">> end get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) @@ -107,8 +110,11 @@ feature -- Hooks end menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) + local + link: CMS_LOCAL_LINK do - + create link.make ("Upload", "/upload") + a_menu_system.primary_menu.extend (link) end feature -- Configuration @@ -132,6 +138,7 @@ feature -- Handler do res.redirect_now_with_content (req.script_url ("/"), uri + ": not found. %N Redirectioin to" + req.script_url ("/"), "text/html") end + execute_upload_handler(req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API) local body: STRING_8 @@ -203,11 +210,11 @@ feature -- Handler feature {NONE} -- Encoder - url_encode (s: READABLE_STRING_32): STRING_8 - -- URL Encode `s' as Result - do - Result := url_encoder.encoded_string (s) - end + url_encode (s: READABLE_STRING_32): STRING_8 + -- URL Encode `s' as Result + do + Result := url_encoder.encoded_string (s) + end url_encoder: URL_ENCODER once @@ -224,4 +231,24 @@ feature {NONE} -- Encoder once create Result end + +feature -- Mapping helper: uri template agent + + map_uri_template (a_router: WSF_ROUTER; a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `h' as handler for `a_tpl', according to `rqst_methods'. + require + a_tpl_attached: a_tpl /= Void + h_attached: h /= Void + do + a_router.map (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods) + end + + map_uri_template_agent (a_router: WSF_ROUTER; a_tpl: READABLE_STRING_8; proc: PROCEDURE [TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `proc' as handler for `a_tpl', according to `rqst_methods'. + require + a_tpl_attached: a_tpl /= Void + proc_attached: proc /= Void + do + map_uri_template (a_router, a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods) + end end diff --git a/modules/file_upload/file_uploader.ecf b/modules/file_upload/file_uploader.ecf index ab71576..83a246c 100644 --- a/modules/file_upload/file_uploader.ecf +++ b/modules/file_upload/file_uploader.ecf @@ -1,12 +1,12 @@ - + - + diff --git a/modules/file_upload/file_uploader.ecf~ b/modules/file_upload/file_uploader.ecf~ new file mode 100644 index 0000000..eff107e --- /dev/null +++ b/modules/file_upload/file_uploader.ecf~ @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + /.svn$ + /CVS$ + /EIFGENs$ + + + +