From 0e63c14613c1b8b02ea74d1468e3999e6d637b23 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Tue, 13 Oct 2015 10:23:30 -0300 Subject: [PATCH 1/3] Added Module Custom Search Added Google custom search library Added HTTP client extension libaray Updated demo example to use the Module Custom Search --- examples/demo/demo-safe.ecf | 2 + .../custom_search/config/custom_search.json | 6 + .../custom_search/templates/block_search.tpl | 40 +++ examples/demo/site/themes/bootstrap/page.tpl | 11 + examples/demo/src/ewf_roc_server_execution.e | 3 + library/gcse/Readme.md | 4 + library/gcse/gcse-safe.ecf | 21 ++ library/gcse/gcse.ecf | 28 ++ library/gcse/license.lic | 10 + library/gcse/src/gcse_api.e | 243 ++++++++++++++++++ library/gcse/src/gcse_page.e | 113 ++++++++ library/gcse/src/gcse_page_item.e | 220 ++++++++++++++++ library/gcse/src/gcse_page_map.e | 38 +++ library/gcse/src/gcse_query_parameters.e | 237 +++++++++++++++++ library/gcse/src/gcse_response.e | 88 +++++++ library/gcse/test/application.e | 80 ++++++ library/gcse/test/gcse_api_test_set.e | 31 +++ library/gcse/test/test.ecf | 21 ++ .../http_client_extension-safe.ecf | 26 ++ .../http_client_extension.ecf | 25 ++ .../src/request/request.e | 199 ++++++++++++++ .../src/request/request_executor.e | 97 +++++++ .../src/response/response.e | 57 ++++ .../src/util/http_client_helper.e | 99 +++++++ modules/auth/cms_authentication_module.e | 1 + modules/custom_search/Readme.md | 1 + modules/custom_search/custom_search.ecf | 18 ++ .../site/config/custom_search.json | 6 + .../site/templates/block_search.tpl | 40 +++ .../src/google_custom_search_module.e | 154 +++++++++++ 30 files changed, 1919 insertions(+) create mode 100644 examples/demo/site/modules/custom_search/config/custom_search.json create mode 100644 examples/demo/site/modules/custom_search/templates/block_search.tpl create mode 100644 library/gcse/Readme.md create mode 100644 library/gcse/gcse-safe.ecf create mode 100644 library/gcse/gcse.ecf create mode 100644 library/gcse/license.lic create mode 100644 library/gcse/src/gcse_api.e create mode 100644 library/gcse/src/gcse_page.e create mode 100644 library/gcse/src/gcse_page_item.e create mode 100644 library/gcse/src/gcse_page_map.e create mode 100644 library/gcse/src/gcse_query_parameters.e create mode 100644 library/gcse/src/gcse_response.e create mode 100644 library/gcse/test/application.e create mode 100644 library/gcse/test/gcse_api_test_set.e create mode 100644 library/gcse/test/test.ecf create mode 100644 library/http_client_extension/http_client_extension-safe.ecf create mode 100644 library/http_client_extension/http_client_extension.ecf create mode 100644 library/http_client_extension/src/request/request.e create mode 100644 library/http_client_extension/src/request/request_executor.e create mode 100644 library/http_client_extension/src/response/response.e create mode 100644 library/http_client_extension/src/util/http_client_helper.e create mode 100644 modules/custom_search/Readme.md create mode 100644 modules/custom_search/custom_search.ecf create mode 100644 modules/custom_search/site/config/custom_search.json create mode 100644 modules/custom_search/site/templates/block_search.tpl create mode 100644 modules/custom_search/src/google_custom_search_module.e diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index 8f28c4b..2f8ffc1 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -26,6 +26,8 @@ + + +
    + + + {foreach from="$result.items" item="item"} +
  1. + +
  2. + {/foreach} + + +
+ + \ No newline at end of file diff --git a/examples/demo/site/themes/bootstrap/page.tpl b/examples/demo/site/themes/bootstrap/page.tpl index 31474dc..aba3059 100644 --- a/examples/demo/site/themes/bootstrap/page.tpl +++ b/examples/demo/site/themes/bootstrap/page.tpl @@ -37,6 +37,17 @@ {/if} + +
+
+
+
+ + +
+
+
+
diff --git a/examples/demo/src/ewf_roc_server_execution.e b/examples/demo/src/ewf_roc_server_execution.e index db4dbf7..d6017f8 100644 --- a/examples/demo/src/ewf_roc_server_execution.e +++ b/examples/demo/src/ewf_roc_server_execution.e @@ -92,6 +92,9 @@ feature -- CMS setup create {CMS_DEMO_MODULE} m.make a_setup.register_module (m) + + create {GOOGLE_CUSTOM_SEARCH_MODULE} m.make + a_setup.register_module (m) end end diff --git a/library/gcse/Readme.md b/library/gcse/Readme.md new file mode 100644 index 0000000..dc80b1f --- /dev/null +++ b/library/gcse/Readme.md @@ -0,0 +1,4 @@ +Google Custom Search Engine Eiffel Lbrary + +Based on https://developers.google.com/custom-search/json-api/v1/using_rest + diff --git a/library/gcse/gcse-safe.ecf b/library/gcse/gcse-safe.ecf new file mode 100644 index 0000000..235412e --- /dev/null +++ b/library/gcse/gcse-safe.ecf @@ -0,0 +1,21 @@ + + + + + + /.git$ + /EIFGENs$ + /CVS$ + /.svn$ + + + + + + + + + + diff --git a/library/gcse/gcse.ecf b/library/gcse/gcse.ecf new file mode 100644 index 0000000..a086fb8 --- /dev/null +++ b/library/gcse/gcse.ecf @@ -0,0 +1,28 @@ + + + + + + /.git$ + /EIFGENs$ + /CVS$ + /.svn$ + + + + + + + + + + + + + + diff --git a/library/gcse/license.lic b/library/gcse/license.lic new file mode 100644 index 0000000..93c113a --- /dev/null +++ b/library/gcse/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR} Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" diff --git a/library/gcse/src/gcse_api.e b/library/gcse/src/gcse_api.e new file mode 100644 index 0000000..5a46f82 --- /dev/null +++ b/library/gcse/src/gcse_api.e @@ -0,0 +1,243 @@ +note + description: "[ + Simple API to call Google Custome Search Engine + Example call: + GET https://www.googleapis.com/customsearch/v1?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures + ]" + date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $" + revision: "$Revision: 97973 $" + EIS: "name=Google Custom Search Engine", "src=https://developers.google.com/custom-search/json-api/v1/using_rest", "protocol=uri" + +class + GCSE_API + +create + make + +feature {NONE} -- Initialization + + make (a_query_parameters: GCSE_QUERY_PARAMETERS) + -- Create an object GCSE with query_parameters `a_query_parameters' + do + query_paremeter := a_query_parameters + ensure + query_parameters_set: query_paremeter = a_query_parameters + end + +feature -- Access + + base_uri: STRING_8 = "https://www.googleapis.com/customsearch/v1" + -- Google custom search base URI + + query_paremeter: GCSE_QUERY_PARAMETERS + -- Google custom search parameters. + + last_result: detachable GCSE_RESPONSE + -- Search results. + +feature -- Status Reports + + errors: detachable LIST [READABLE_STRING_8] + -- optional table of error codes + +feature -- API + + search + -- Search + local + l_parser: JSON_PARSER + l_gcse_response: detachable GCSE_RESPONSE + do + -- Data format for the response. + -- At the moment we are using the default value: json + -- but it's possible to define atom response using the alt parameter. + last_result := Void + if attached get as l_response then + if attached l_response.body as l_body then + create l_parser.make_with_string (l_body) + l_parser.parse_content + if l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv then + -- Queries + create l_gcse_response + if attached {JSON_OBJECT} jv.item (queries_key) as jqueries then + -- Next Page + if attached {GCSE_PAGE} query_page (next_page_key, jqueries) as l_page then + l_gcse_response.set_next_page (l_page) + end + -- Current Page + if attached {GCSE_PAGE} query_page (request_key, jqueries) as l_page then + l_gcse_response.set_current_page (l_page) + end + -- Previous Page + if attached {GCSE_PAGE} query_page (previous_page_key, jqueries) as l_page then + l_gcse_response.set_previous_page (l_page) + end + end + if attached {JSON_ARRAY} jv.item (items_key) as jitems then + across jitems as ic loop + if attached{JSON_OBJECT} ic.item as j_item then + l_gcse_response.add_item (item (j_item)) + end + end + end + + end + else + put_error (l_response.status.out) + end + else + put_error ("unknown") + end + last_result := l_gcse_response + end + +feature {NONE} -- REST API + + get: detachable RESPONSE + -- Reading Data. + local + l_request: REQUEST + do + create l_request.make ("GET", new_uri) + Result := l_request.execute + end + +feature {NONE} -- Implementation + + new_uri: STRING_8 + -- new uri (BaseUri?key=secret_value&cx=a_cx_id&q=a_query + -- ?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures + -- full teamplte BaseUri?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}& + -- safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}& + -- googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}& + -- siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}& + -- orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}& + -- searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}& + -- imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json" + + do + create Result.make_from_string (base_uri) + Result.append ("?key=") + Result.append (query_paremeter.secret) + Result.append ("&cx=") + Result.append (query_paremeter.cx) + Result.append ("&q=") + Result.append (query_paremeter.query) + -- num + if attached query_paremeter.num as l_num then + Result.append ("&num=") + Result.append (l_num) + end + if attached query_paremeter.start as l_start then + Result.append ("&start=") + Result.append (l_start) + end + end + + put_error (a_code: READABLE_STRING_GENERAL) + -- put error with code `a_code'. + local + l_errors: like errors + utf: UTF_CONVERTER + do + l_errors := errors + if l_errors = Void then + create {ARRAYED_LIST [STRING]} l_errors.make (1) + errors := l_errors + end + l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_code)) + end + + item (a_item: JSON_OBJECT): GCSE_PAGE_ITEM + -- Google Result Metadata Item. + do + create Result + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("kind")) as l_kind then + Result.set_kind (l_kind.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("title")) as l_title then + Result.set_title (l_title.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("htmlTitle")) as l_htmltitle then + Result.set_html_title (l_htmltitle.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("link")) as l_link then + Result.set_link (l_link.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("displayLink")) as l_display_link then + Result.set_display_link (l_display_link.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("snippet")) as l_snippet then + Result.set_snippet (l_snippet.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("htmlSnippet")) as l_html_snippet then + Result.set_html_snippet (l_html_snippet.item) + end + if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("formattedUrl")) as l_formatted_url then + Result.set_formatted_url (l_formatted_url.item) + end + end + + query_page (a_page_key: JSON_STRING; a_queries: JSON_OBJECT): detachable GCSE_PAGE + -- Google result medata query. Return a query page based for a query with page key `a_page_key', if any. + do + if attached {JSON_ARRAY} a_queries.item (a_page_key) as jquerypage and then attached {JSON_OBJECT} jquerypage.i_th (1) as jpage then + create Result + if attached {JSON_STRING} jpage.item (create {JSON_STRING}.make_from_string ("title")) as l_title then + Result.set_title (l_title.item) + end + if attached {JSON_STRING} jpage.item (create {JSON_STRING}.make_from_string ("totalResults")) as l_results then + Result.set_total_results (l_results.item.to_integer) + end + if attached {JSON_STRING} jpage.item (create {JSON_STRING}.make_from_string ("searchTerms")) as l_search_terms then + Result.set_search_terms (l_search_terms.item) + end + -- TODO check if we should use INTEGER_64 + if attached {JSON_NUMBER} jpage.item (create {JSON_STRING}.make_from_string ("count")) as l_count then + Result.set_count (l_count.integer_64_item.as_integer_32) + end + if attached {JSON_NUMBER} jpage.item (create {JSON_STRING}.make_from_string ("startIndex")) as l_index then + Result.set_start_index (l_index.integer_64_item.as_integer_32) + end + end + end + +feature {NONE} -- JSON Keys + + queries_key: JSON_STRING + do + create Result.make_from_string ("queries") + end + + next_page_key: JSON_STRING + do + create Result.make_from_string ("nextPage") + end + + request_key: JSON_STRING + do + create Result.make_from_string ("request") + end + + previous_page_key: JSON_STRING + do + create Result.make_from_string ("previousPage") + end + + items_key: JSON_STRING + do + create Result.make_from_string ("items") + end + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/gcse/src/gcse_page.e b/library/gcse/src/gcse_page.e new file mode 100644 index 0000000..9fc2cae --- /dev/null +++ b/library/gcse/src/gcse_page.e @@ -0,0 +1,113 @@ +note + description: "Represent metadata describing the query for the current set of results." + date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $" + revision: "$Revision: 97973 $" + +class + GCSE_PAGE + +feature -- Access + + search_terms: detachable STRING_8 + -- search term + + title: detachable STRING_8 + -- Search title. + + total_results: INTEGER + -- Search total results. + + count: INTEGER + -- Rows per page. + + start_index: INTEGER + -- Page index. + +feature -- Element change + + set_search_terms (a_search_terms: like search_terms) + -- Assign `search_terms' with `a_search_terms'. + do + search_terms := a_search_terms + ensure + search_terms_assigned: search_terms = a_search_terms + end + +feature -- Change element + + set_title (a_title: like title) + -- Set title with `a_title' + do + title := a_title + ensure + title_set: title = a_title + end + + set_total_results (a_total_results: like total_results) + -- Set total_results with `a_total_results'. + do + total_results := a_total_results + ensure + total_results_set: total_results = a_total_results + end + + set_count (a_count: like count) + -- Set count with `a_count'. + do + count := a_count + ensure + count_set: count = a_count + end + + set_start_index (a_start_index: like start_index) + -- Set start_index with `a_start_index'. + do + start_index := a_start_index + ensure + start_index_set: start_index = a_start_index + end + +feature -- Output + + to_string: STRING_8 + do + create Result.make_from_string ("%NPage details%N") + if attached title as l_title then + Result.append ("Title:") + Result.append (l_title) + Result.append_character ('%N') + end + if attached search_terms as l_search_tearm then + Result.append ("Search Tearm:") + Result.append (l_search_tearm) + Result.append_character ('%N') + end + + Result.append ("Count:") + Result.append (count.out) + Result.append_character ('%N') + Result.append ("Total Result:") + Result.append (count.out) + Result.append_character ('%N') + Result.append ("Count:") + Result.append (total_results.out) + Result.append_character ('%N') + Result.append ("Start index:") + Result.append (start_index.out) + Result.append_character ('%N') + + end + + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/gcse/src/gcse_page_item.e b/library/gcse/src/gcse_page_item.e new file mode 100644 index 0000000..469bacc --- /dev/null +++ b/library/gcse/src/gcse_page_item.e @@ -0,0 +1,220 @@ +note + description: "Represent a search result, include the URL, title and text snippets that describe the result" + date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $" + revision: "$Revision: 97973 $" + +class + GCSE_PAGE_ITEM + +inherit + + SHARED_HTML_ENCODER + +feature -- Access + + html_formatted_url: detachable STRING_8 + -- Html formatted url of this result + + formatted_url: detachable STRING_8 + -- Formatted url of this result + + cache_id: detachable STRING_8 + -- Cache id of this result + + html_snippet: detachable STRING_8 + -- Html snippet of this request + + snippet: detachable STRING_8 + -- Snippet of this result + + snippet_2: detachable STRING_8 + -- Snippet of this result + + display_link: detachable STRING_8 + -- Display link of this result + + link: detachable STRING_8 + -- link of this result + + html_title: detachable STRING_8 + -- html title of result + + title: detachable STRING_8 + -- title of result. + + kind: detachable STRING_8 + -- Kind of actual search result. + + page_map: detachable GCSE_PAGE_MAP + -- Page map + --! Not supported for now. + +feature -- Element change + + set_html_formatted_url (a_html_formatted_url: like html_formatted_url) + -- Assign `html_formatted_url' with `a_html_formatted_url'. + do + html_formatted_url := a_html_formatted_url + ensure + html_formatted_url_assigned: html_formatted_url = a_html_formatted_url + end + + set_formatted_url (a_formatted_url: like formatted_url) + -- Assign `formatted_url' with `a_formatted_url'. + do + formatted_url := a_formatted_url + ensure + formatted_url_assigned: formatted_url = a_formatted_url + end + + set_cache_id (a_cache_id: like cache_id) + -- Assign `cache_id' with `a_cache_id'. + do + cache_id := a_cache_id + ensure + cache_id_assigned: cache_id = a_cache_id + end + + set_html_snippet (a_html_snippet: like html_snippet) + -- Assign `html_snippet' with `a_html_snippet'. + do + html_snippet := a_html_snippet + snippet_2 := html_encoded (a_html_snippet) + ensure + html_snippet_assigned: html_snippet = a_html_snippet + end + + set_snippet (a_snippet: like snippet) + -- Assign `snippet' with `a_snippet'. + do + snippet := a_snippet + ensure + snippet_assigned: snippet = a_snippet + end + + set_display_link (a_display_link: like display_link) + -- Assign `display_link' with `a_display_link'. + do + display_link := a_display_link + ensure + display_link_assigned: display_link = a_display_link + end + + set_link (a_link: like link) + -- Assign `link' with `a_link'. + do + link := a_link + ensure + link_assigned: link = a_link + end + + set_html_title (a_html_title: like html_title) + -- Assign `html_title' with `a_html_title'. + do + html_title := a_html_title + ensure + html_title_assigned: html_title = a_html_title + end + + set_title (a_title: like title) + -- Assign `title' with `a_title'. + do + title := a_title + ensure + title_assigned: title = a_title + end + + set_kind (a_kind: like kind) + -- Assign `kind' with `a_kind'. + do + kind := a_kind + ensure + kind_assigned: kind = a_kind + end + + set_page_map (a_map: like page_map) + -- Assign `kind' with `a_kind'. + do + page_map := a_map + ensure + page_map_assigned: page_map = a_map + end + + +feature -- Output + + to_string: STRING_8 + do + create Result.make_from_string ("%NPage Item details%N") + if attached title as l_title then + Result.append ("Title:") + Result.append (l_title) + Result.append_character ('%N') + end + if attached kind as l_kind then + Result.append ("Kind:") + Result.append (l_kind) + Result.append_character ('%N') + end + if attached html_title as l_html_title then + Result.append ("Html title:") + Result.append (l_html_title) + Result.append_character ('%N') + end + if attached link as l_link then + Result.append ("Link:") + Result.append (l_link) + Result.append_character ('%N') + end + if attached display_link as l_display_link then + Result.append ("Display link:") + Result.append (l_display_link) + Result.append_character ('%N') + end + if attached snippet as l_snippet then + Result.append ("Snippet:") + Result.append (l_snippet) + Result.append_character ('%N') + end + if attached html_snippet as l_html_snippet then + Result.append ("Html snippet:") + Result.append (l_html_snippet) + Result.append_character ('%N') + end + if attached cache_id as l_cache_id then + Result.append ("Cache_id:") + Result.append (l_cache_id) + Result.append_character ('%N') + end + if attached formatted_url as l_formatted_url then + Result.append ("Formatted url:") + Result.append (l_formatted_url) + Result.append_character ('%N') + end + if attached html_formatted_url as l_html_formatted_url then + Result.append ("Html formatted url:") + Result.append (l_html_formatted_url) + Result.append_character ('%N') + end + + end + + html_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8 + do + if s /= Void then + Result := html_encoder.general_encoded_string (s) + else + create Result.make_empty + end + end +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/gcse/src/gcse_page_map.e b/library/gcse/src/gcse_page_map.e new file mode 100644 index 0000000..67468ab --- /dev/null +++ b/library/gcse/src/gcse_page_map.e @@ -0,0 +1,38 @@ +note + description: "Represent a google page map" + date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $" + revision: "$Revision: 97973 $" + EIS: "name=PageMaps", "src=https://developers.google.com/custom-search/docs/structured_data#pagemaps", "protocol=url" + +class + GCSE_PAGE_MAP + +feature -- Access + +-- "pagemap": { +-- "cse_image": [ +-- { +-- "src": "https://www.eiffel.org/portal/files/userpictures/picture-40.jpg" +-- } +-- ], +-- "cse_thumbnail": [ +-- { +-- "width": "81", +-- "height": "61", +-- "src": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRnC-RKzps6BFItx_MLYBVskFI7U6u0y3VJBInomPYEF5sO6gkip94mLw" +-- } +-- ] +-- } + + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/gcse/src/gcse_query_parameters.e b/library/gcse/src/gcse_query_parameters.e new file mode 100644 index 0000000..77e91e1 --- /dev/null +++ b/library/gcse/src/gcse_query_parameters.e @@ -0,0 +1,237 @@ +note + description: "[ + Represent google custom search parameters + Example url template + "template": "https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json" + ]" + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + EIS: "GCSE parameters", "src=https://developers.google.com/custom-search/json-api/v1/reference/cse/list", "protocol=URI" + +class + GCSE_QUERY_PARAMETERS + +create + make + +feature {NONE} -- Initialization + + make (a_secret_key, a_cx, a_query: READABLE_STRING_8) + -- Create an object GCSE_QUERY_PARAMETERS with secret key `a_secret_key' and a custom search engine id `a_cx'. + -- and query `a_query'. + do + -- TODO + -- At the moment the API only use cx as Google Custom Search id. + -- Custom search engine ID - Use either cx or cref to specify the custom search engine you want to use to perform this search + + secret := a_secret_key + cx := a_cx + query := a_query + ensure + secret_set: secret.same_string (a_secret_key) + cx_set: cx.same_string (a_cx) + query_set: query.same_string (a_query) + end + +feature -- Access : Required Parameters + + secret: READABLE_STRING_8 + -- Required. The shared key between your site and Google Custom Search Engine. + + cx: READABLE_STRING_8 + -- Custom search engine id to perform this search. + + query: READABLE_STRING_8 + -- Search query, query parameter to specify your search expression. + +feature -- Optional Parameters + +--Optional parameters +--c2coff string Enables or disables Simplified and Traditional Chinese Search. +-- The default value for this parameter is 0 (zero), meaning that the feature is enabled. Supported values are: +-- 1: Disabled +-- 0: Enabled (default) +--cr string Restricts search results to documents originating in a particular country. +-- You may use Boolean operators in the cr parameter's value. +-- Google Search determines the country of a document by analyzing: +-- the top-level domain (TLD) of the document's URL +-- the geographic location of the Web server's IP address +-- See the Country Parameter Values page for a list of valid values for this parameter. +--cref string The URL of a linked custom search engine specification to use for this request. +-- Does not apply for Google Site Search +-- If both cx and cref are specified, the cx value is used +--cx string The custom search engine ID to use for this request. +-- If both cx and cref are specified, the cx value is used. +--dateRestrict string Restricts results to URLs based on date. Supported values include: +-- d[number]: requests results from the specified number of past days. +-- w[number]: requests results from the specified number of past weeks. +-- m[number]: requests results from the specified number of past months. +-- y[number]: requests results from the specified number of past years. +--exactTerms string Identifies a phrase that all documents in the search results must contain. +--excludeTerms string Identifies a word or phrase that should not appear in any documents in the search results. +--fileType string Restricts results to files of a specified extension. A list of file types indexable by Google can be found in Webmaster Tools Help Center. +--filter string Controls turning on or off the duplicate content filter. +-- See Automatic Filtering for more information about Google's search results filters. Note that host crowding filtering applies only to multi-site searches. +-- By default, Google applies filtering to all search results to improve the quality of those results. + + +-- Acceptable values are: +-- "0": Turns off duplicate content filter. +-- "1": Turns on duplicate content filter. +-- gl string Geolocation of end user. +--The gl parameter value is a two-letter country code. The gl parameter boosts search results whose country of origin matches the parameter value. See the Country Codes page for a list of valid values. +--Specifying a gl parameter value should lead to more relevant results. This is particularly true for international customers and, even more specifically, for customers in English- speaking countries other than the United States. +--googlehost string The local Google domain (for example, google.com, google.de, or google.fr) to use to perform the search. +--highRange string +--Specifies the ending value for a search range. +--Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query. +--hl string Sets the user interface language. +--Explicitly setting this parameter improves the performance and the quality of your search results. +--See the Interface Languages section of Internationalizing Queries and Results Presentation for more information, and Supported Interface Languages for a list of supported languages. +--hq string Appends the specified query terms to the query, as if they were combined with a logical AND operator. +--imgColorType string Returns black and white, grayscale, or color images: mono, gray, and color. + +-- Acceptable values are: +-- "color": color +-- "gray": gray +-- "mono": mono +--imgDominantColor string Returns images of a specific dominant color. + +-- Acceptable values are: +-- "black": black +-- "blue": blue +-- "brown": brown +-- "gray": gray +-- "green": green +-- "pink": pink +-- "purple": purple +-- "teal": teal +-- "white": white +-- "yellow": yellow +--imgSize string Returns images of a specified size. + +-- Acceptable values are: +-- "huge": huge +-- "icon": icon +-- "large": large +-- "medium": medium +-- "small": small +-- "xlarge": xlarge +-- "xxlarge": xxlarge +--imgType string Returns images of a type. + +-- Acceptable values are: +-- "clipart": clipart +-- "face": face +-- "lineart": lineart +-- "news": news +-- "photo": photo +--linkSite string Specifies that all search results should contain a link to a particular URL +--lowRange string Specifies the starting value for a search range. +--Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query. +--lr string Restricts the search to documents written in a particular language (e.g., lr=lang_ja). + +-- Acceptable values are: +-- "lang_ar": Arabic +-- "lang_bg": Bulgarian +-- "lang_ca": Catalan +-- "lang_cs": Czech +-- "lang_da": Danish +-- "lang_de": German +-- "lang_el": Greek +-- "lang_en": English +-- "lang_es": Spanish +-- "lang_et": Estonian +-- "lang_fi": Finnish +-- "lang_fr": French +-- "lang_hr": Croatian +-- "lang_hu": Hungarian +-- "lang_id": Indonesian +-- "lang_is": Icelandic +-- "lang_it": Italian +-- "lang_iw": Hebrew +-- "lang_ja": Japanese +-- "lang_ko": Korean +-- "lang_lt": Lithuanian +-- "lang_lv": Latvian +-- "lang_nl": Dutch +-- "lang_no": Norwegian +-- "lang_pl": Polish +-- "lang_pt": Portuguese +-- "lang_ro": Romanian +-- "lang_ru": Russian +-- "lang_sk": Slovak +-- "lang_sl": Slovenian +-- "lang_sr": Serbian +-- "lang_sv": Swedish +-- "lang_tr": Turkish +-- "lang_zh-CN": Chinese (Simplified) +-- "lang_zh-TW": Chinese (Traditional) + +--orTerms string Provides additional search terms to check for in a document, where each document in the search results must contain at least one of the additional search terms. +--relatedSite string Specifies that all search results should be pages that are related to the specified URL. +--rights string Filters based on licensing. Supported values include: cc_publicdomain, cc_attribute, cc_sharealike, cc_noncommercial, cc_nonderived, and combinations of these. +--safe string Search safety level. + +-- Acceptable values are: +-- "high": Enables highest level of SafeSearch filtering. +-- "medium": Enables moderate SafeSearch filtering. +-- "off": Disables SafeSearch filtering. (default) +--searchType string Specifies the search type: image. If unspecified, results are limited to webpages. + +--Acceptable values are: +-- "image": custom image search. +--siteSearch string Specifies all search results should be pages from a given site. +--siteSearchFilter string Controls whether to include or exclude results from the site named in the siteSearch parameter. + +-- Acceptable values are: +-- "e": exclude +-- "i": include +-- sort string The sort expression to apply to the results. +-- + + + num : detachable STRING_8 + -- Number of search results to return. + -- Valid values are integers between 1 and 10, inclusive. + + start: detachable STRING_8 + -- The index of the first result to return. + + +feature -- Change Elements + + set_num (a_num: READABLE_STRING_8) + require + is_number: a_num.is_integer + valid_range: a_num.to_integer >= 1 and then a_num.to_integer <= 10 + do + num := a_num + ensure + num_set: num = a_num + valid_rage_set: attached num as l_num and then l_num.to_integer >= 1 and then l_num.to_integer <= 10 + end + + + set_start (a_start: READABLE_STRING_8) + require + is_number: a_start.is_integer + valid_start: a_start.to_integer >= 1 + do + start := a_start + ensure + start_set: start = a_start + valid_start_set: attached start as l_start and then l_start.to_integer >= 1 + end + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/gcse/src/gcse_response.e b/library/gcse/src/gcse_response.e new file mode 100644 index 0000000..5ffdfcb --- /dev/null +++ b/library/gcse/src/gcse_response.e @@ -0,0 +1,88 @@ +note + description: "[ + Represent search request metadata + URL: search template used for the current results. + Queries: current, next and previous page. + Context + Search infromation + Items: array of actual search results. + ]" + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + +class + GCSE_RESPONSE + + --! TODO + --! All suppport for for url, context and search information. + +feature -- Access + + + current_page: detachable GCSE_PAGE + -- Metadata describing the query for the current set of results. + -- This role is always present in the response. + -- It is always an array with just one element. + + next_page: detachable GCSE_PAGE + -- Metadata describing the query to use for the next page of results. + -- This role is not present if the current results are the last page. Note: This API returns up to the first 100 results only. + -- When present, it is always a array with just one element. + + previous_page: detachable GCSE_PAGE + -- Metadata describing the query to use for the previous page of results. + -- Not present if the current results are the first page. + -- When present, it is always a array with just one element. + + items: detachable LIST [GCSE_PAGE_ITEM] + -- Contains the actual search results. The search results include the URL, title and text snippets that describe the result. + +feature -- Change Element + + set_current_page (a_page: GCSE_PAGE) + -- Set `current_page' with `a_page'. + do + current_page := a_page + ensure + current_page_set: current_page = a_page + end + + set_next_page (a_page: GCSE_PAGE) + -- Set `next_page' with `a_page'. + do + next_page := a_page + ensure + next_page_set: next_page = a_page + end + + set_previous_page (a_page: GCSE_PAGE) + -- Set `previous_page' with `a_page'. + do + previous_page := a_page + ensure + previous_page_set: previous_page = a_page + end + + add_item (a_item: GCSE_PAGE_ITEM) + -- Add item `a_item' to the list of items. + local + l_items: like items + do + l_items := items + if l_items = Void then + create {ARRAYED_LIST[GCSE_PAGE_ITEM]}l_items.make (10) + items := l_items + end + l_items.force (a_item) + end +;note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/gcse/test/application.e b/library/gcse/test/application.e new file mode 100644 index 0000000..bdc9b06 --- /dev/null +++ b/library/gcse/test/application.e @@ -0,0 +1,80 @@ +note + description : "test application root class" + date : "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision : "$Revision: 97966 $" + +class + APPLICATION + +inherit + ARGUMENTS + +create + make + +feature {NONE} -- Initialization + + make + -- Run application. + local + gcse: GCSE_API + l_parameters: GCSE_QUERY_PARAMETERS + do + create l_parameters.make (key, cx, "scoop") + create gcse.make (l_parameters) + gcse.search + + if attached {GCSE_RESPONSE} gcse.last_result as l_result then + if attached l_result.current_page as l_page then + print ("Current Page%N") + print (l_page.to_string) + end + if attached l_result.next_page as l_page then + print ("Next Page%N") + print (l_page.to_string) + end + if attached l_result.previous_page as l_page then + print ("Previous Page%N") + print (l_page.to_string) + end + + if attached l_result.items as l_items then + print ("Number of items:" + l_items.count.out) + across l_items as ic loop print (ic.item.to_string) end + end + + if attached l_result.next_page as l_page then + l_parameters.set_start (l_page.start_index.out) + gcse.search + end + end + + if attached {GCSE_RESPONSE} gcse.last_result as l_result then + if attached l_result.current_page as l_page then + print ("Current Page%N") + print (l_page.to_string) + end + if attached l_result.next_page as l_page then + print ("Next Page%N") + print (l_page.to_string) + end + if attached l_result.previous_page as l_page then + print ("Previous Page%N") + print (l_page.to_string) + end + + if attached l_result.items as l_items then + print ("Number of items:" + l_items.count.out) + across l_items as ic loop print (ic.item.to_string) end + end + + end + + + end + +feature {NONE} -- Implementation + + Key: STRING = "AIzaSyBKAXNofo-RqZb6kUmpbiCwPEy7n7-E51k" + cx : STRING = "015017565055626880074:9gdgp1fvt-g" +end diff --git a/library/gcse/test/gcse_api_test_set.e b/library/gcse/test/gcse_api_test_set.e new file mode 100644 index 0000000..02deb68 --- /dev/null +++ b/library/gcse/test/gcse_api_test_set.e @@ -0,0 +1,31 @@ +note + description: "[ + Eiffel tests that can be executed by testing tool. + ]" + author: "EiffelStudio test wizard" + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + testing: "type/manual" + +class + GCSE_API_TEST_SET + +inherit + EQA_TEST_SET + +feature -- Test routines + + +feature {NONE} -- Implementation + + has_error (l_captcha: GCSE_API; a_error: READABLE_STRING_32): BOOLEAN + do + if attached l_captcha.errors as l_errors then + l_errors.compare_objects + Result := l_errors.has (a_error) + end + end + +end + + diff --git a/library/gcse/test/test.ecf b/library/gcse/test/test.ecf new file mode 100644 index 0000000..0db0a14 --- /dev/null +++ b/library/gcse/test/test.ecf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + /EIFGENs$ + /CVS$ + /.svn$ + + + + diff --git a/library/http_client_extension/http_client_extension-safe.ecf b/library/http_client_extension/http_client_extension-safe.ecf new file mode 100644 index 0000000..83979b3 --- /dev/null +++ b/library/http_client_extension/http_client_extension-safe.ecf @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + /.git$ + /EIFGENs$ + /CVS$ + /.svn$ + + + + diff --git a/library/http_client_extension/http_client_extension.ecf b/library/http_client_extension/http_client_extension.ecf new file mode 100644 index 0000000..f15887d --- /dev/null +++ b/library/http_client_extension/http_client_extension.ecf @@ -0,0 +1,25 @@ + + + + + + /.git$ + /EIFGENs$ + /CVS$ + /.svn$ + + + + + + + + + + + + + + diff --git a/library/http_client_extension/src/request/request.e b/library/http_client_extension/src/request/request.e new file mode 100644 index 0000000..5d4713f --- /dev/null +++ b/library/http_client_extension/src/request/request.e @@ -0,0 +1,199 @@ +note + description: "Represent an HTTP request." + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + +class + REQUEST + +inherit + + HTTP_CONSTANTS + +create + make + +feature {NONE} -- Initialization + + make (a_method: READABLE_STRING_8; a_uri: READABLE_STRING_8) + require + valid_http_method: is_http_method (a_method) + valid_uri: is_valid_uri (a_uri) + do + verb := a_method + uri := a_uri + create headers.make (5) + ensure + ver_set: verb = a_method + uri_set: uri = a_uri + end + +feature -- Status Report + + is_valid_uri (a_uri: READABLE_STRING_8): BOOLEAN + local + l_uri: URI + do + create l_uri.make_from_string (a_uri) + Result := l_uri.is_valid + end + + query_string: detachable READABLE_STRING_8 + local + l_uri: URI + do + create l_uri.make_from_string (uri) + Result := l_uri.query + end + + sanitized_url: READABLE_STRING_8 + -- Returns the URL without the query string part + local + l_uri: URI + do + create l_uri.make_from_string (uri) + l_uri.remove_query + Result := l_uri.string + ensure + sanitized: not as_uri (Result).has_query + end + + is_http_method (a_method: READABLE_STRING_GENERAL): BOOLEAN + do + if a_method.same_string (method_connect) then + Result := True + elseif a_method.same_string (method_delete) then + Result := True + elseif a_method.same_string (method_get) then + Result := True + elseif a_method.same_string (method_head) then + Result := True + elseif a_method.same_string (method_options) then + Result := True + elseif a_method.same_string (method_patch) then + Result := True + elseif a_method.same_string (method_post) then + Result := True + elseif a_method.same_string (method_put) then + Result := True + elseif a_method.same_string (method_trace) then + Result := True + end + end + +feature -- Constants + + content_type_header_name: STRING_8 = "Content-Type"; + + default_content_type: STRING + once + Result := application_json + end + +feature -- Access + + uri: READABLE_STRING_8 + + verb: READABLE_STRING_8 + + headers: STRING_TABLE [READABLE_STRING_8] + + payload: detachable READABLE_STRING_8 + + executor: detachable REQUEST_EXECUTOR + +feature -- Change Element + + add_payload (a_payload: like payload) + do + payload := a_payload + ensure + payload_set: attached payload as l_payload implies l_payload = a_payload + end + + add_header (key: READABLE_STRING_8; value: READABLE_STRING_8) + do + headers.force (value, key) + end + +feature -- Execute + + execute: detachable RESPONSE + do + initialize_executor + Result := execute_request + end + + initialize_executor + do + create executor.make (uri, verb) + end + +feature {NONE} -- Implementation + + execute_request: detachable RESPONSE + do + if attached executor as l_executor then + -- add headers + add_headers (l_executor) + if verb.same_string (method_put) or else verb.same_string (method_post) or else verb.same_string (method_patch) then + l_executor.set_body (body_contents) + end + if not l_executor.context_executor.headers.has (content_type_header_name) then + l_executor.context_executor.add_header (content_type_header_name, default_content_type) + end + if attached l_executor.execute as l_response then + create Result.make (l_response) + end + end + end + +feature {NONE} -- Implementation + + add_headers (a_executor: REQUEST_EXECUTOR) + local + l_context_executor: HTTP_CLIENT_REQUEST_CONTEXT + s: READABLE_STRING_GENERAL + utf: UTF_CONVERTER + do + l_context_executor := a_executor.context_executor + across + headers as ic + loop + s := ic.key + if s.is_valid_as_string_8 then + l_context_executor.add_header (s.as_string_8, ic.item) + else + l_context_executor.add_header (utf.utf_32_string_to_utf_8_string_8 (s), ic.item) + end + end + end + + body_contents: READABLE_STRING_8 + do + if attached payload as l_payload then + Result := l_payload + else + Result := "" + end + end + + as_uri (a_string: READABLE_STRING_8): URI + require + is_valid_uri: is_valid_uri (a_string) + do + create Result.make_from_string (a_string) + end + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/http_client_extension/src/request/request_executor.e b/library/http_client_extension/src/request/request_executor.e new file mode 100644 index 0000000..0e0e5d0 --- /dev/null +++ b/library/http_client_extension/src/request/request_executor.e @@ -0,0 +1,97 @@ +note + description: "Executes an HTTP request" + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + +class + REQUEST_EXECUTOR + +inherit + + HTTP_CLIENT_HELPER + + HTTP_CONSTANTS + +create + make + +feature {NONE} -- Initialization + + make (a_url: READABLE_STRING_8; a_method: READABLE_STRING_8) + do + set_base_url (a_url) + verb := a_method + ensure + base_url_set: base_url.same_string (a_url) + method_set: verb.same_string (a_method) + end + + set_base_url (a_url: READABLE_STRING_8) + -- Set base_url with `a_url' + local + s: STRING + do + create s.make_from_string (a_url) + s.left_adjust + s.right_adjust + base_url := s + ensure + base_url_set: a_url.has_substring (base_url) + end + +feature -- Access + + verb: READABLE_STRING_8 + -- HTTP METHOD (Get, Post, ...) + + body: detachable READABLE_STRING_8 + -- body content + +feature -- Element Change + + set_body (a_body: like body) + -- Set body with `a_body'. + do + body := a_body + ensure + body_set: body = a_body + end + +feature -- Execute + + execute: detachable HTTP_CLIENT_RESPONSE + -- Http executor + do + if verb.same_string (method_connect) then + Result := Void -- not supported for now + elseif verb.same_string (method_delete) then + Result := execute_delete ("") + elseif verb.same_string (method_get) then + Result := execute_get ("") + elseif verb.same_string (method_head) then + Result := Void + elseif verb.same_string (method_options) then + Result := Void + elseif verb.same_string (method_patch) then + Result := execute_patch ("", body) + elseif verb.same_string (method_post) then + Result := execute_post ("", body) + elseif verb.same_string (method_put) then + Result := execute_put ("", body) + elseif verb.same_string (method_trace) then + Result := Void + end + end + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/http_client_extension/src/response/response.e b/library/http_client_extension/src/response/response.e new file mode 100644 index 0000000..4ee711a --- /dev/null +++ b/library/http_client_extension/src/response/response.e @@ -0,0 +1,57 @@ +note + description: "Represent and HTTP Response" + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + +class + RESPONSE + +create + make + +feature {NONE} --Initialization + + make (a_response: HTTP_CLIENT_RESPONSE) + do + http_response := a_response + body := a_response.body + status := a_response.status + headers := a_response.headers + status_message := a_response.status_line + error_message := a_response.error_message + ensure + http_reponse_set: http_response = a_response + headers_set: headers = a_response.headers + status_set: status = a_response.status + status_message_set: status_message = a_response.status_line + error_message_set: error_message = a_response.error_message + end + +feature -- Access + + status: INTEGER + + status_message: detachable READABLE_STRING_8 + + error_message: detachable READABLE_STRING_8 + + body: detachable READABLE_STRING_8 + + headers: LIST [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]] + +feature {NONE} -- Implementation + + http_response: HTTP_CLIENT_RESPONSE; + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/http_client_extension/src/util/http_client_helper.e b/library/http_client_extension/src/util/http_client_helper.e new file mode 100644 index 0000000..f120da2 --- /dev/null +++ b/library/http_client_extension/src/util/http_client_helper.e @@ -0,0 +1,99 @@ +note + description: "Wrapper class for HTTP_CLIENT_SESSION" + date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" + revision: "$Revision: 97966 $" + +deferred class + HTTP_CLIENT_HELPER + +feature -- Access + + http_session: detachable HTTP_CLIENT_SESSION + + get_http_session + local + h: LIBCURL_HTTP_CLIENT + b: like base_url + do + create h.make + b := base_url + if b = Void then + b := "" + end + if attached {HTTP_CLIENT_SESSION} h.new_session (base_url) as sess then + http_session := sess + sess.set_timeout (-1) + sess.set_connect_timeout (-1) + sess.set_is_insecure (True) + sess.set_any_auth_type + debug ("curl") + sess.set_is_debug (True) + end + debug ("proxy8888") + sess.set_proxy ("127.0.0.1", 8888) --| inspect traffic with http://www.fiddler2.com/ + end + end + end + +feature -- HTTP client helpers + + execute_get (command_name: READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE + do + get_http_session + if attached http_session as sess then + Result := sess.get (command_name, context_executor) + end + end + + execute_post (command_name: READABLE_STRING_8; data: detachable READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE + do + get_http_session + if attached http_session as sess then + Result := sess.post (command_name, context_executor, data) + end + end + + execute_delete (command_name: READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE + do + get_http_session + if attached http_session as sess then + Result := sess.delete (command_name, context_executor) + end + end + + execute_put (command_name: READABLE_STRING_8; data: detachable READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE + do + get_http_session + if attached http_session as sess then + Result := sess.put (command_name, context_executor, data) + end + end + + execute_patch (command_name: READABLE_STRING_8; data: detachable READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE + do + get_http_session + if attached http_session as sess then + Result := sess.patch (command_name, context_executor, data) + end + end + + context_executor: HTTP_CLIENT_REQUEST_CONTEXT + -- request context for each request + once + create Result.make + end + + base_url: STRING; + +note + copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/modules/auth/cms_authentication_module.e b/modules/auth/cms_authentication_module.e index 21e59b1..5c786bb 100644 --- a/modules/auth/cms_authentication_module.e +++ b/modules/auth/cms_authentication_module.e @@ -123,6 +123,7 @@ feature -- Hooks configuration lnk.set_weight (98) a_menu_system.primary_menu.extend (lnk) end + end feature -- Handler diff --git a/modules/custom_search/Readme.md b/modules/custom_search/Readme.md new file mode 100644 index 0000000..279cd07 --- /dev/null +++ b/modules/custom_search/Readme.md @@ -0,0 +1 @@ +Google Custom Search Module. \ No newline at end of file diff --git a/modules/custom_search/custom_search.ecf b/modules/custom_search/custom_search.ecf new file mode 100644 index 0000000..35bdfe6 --- /dev/null +++ b/modules/custom_search/custom_search.ecf @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/modules/custom_search/site/config/custom_search.json b/modules/custom_search/site/config/custom_search.json new file mode 100644 index 0000000..9b7ab8c --- /dev/null +++ b/modules/custom_search/site/config/custom_search.json @@ -0,0 +1,6 @@ +{ + "gcse": { + "cx":"", + "secret_key":"" + } +} diff --git a/modules/custom_search/site/templates/block_search.tpl b/modules/custom_search/site/templates/block_search.tpl new file mode 100644 index 0000000..d37d146 --- /dev/null +++ b/modules/custom_search/site/templates/block_search.tpl @@ -0,0 +1,40 @@ +
+
+

Results for {$result.current_page.search_terms/}

+
+ + +
    + + + {foreach from="$result.items" item="item"} +
  1. + +
  2. + {/foreach} + + +
+ +
\ No newline at end of file diff --git a/modules/custom_search/src/google_custom_search_module.e b/modules/custom_search/src/google_custom_search_module.e new file mode 100644 index 0000000..0d7267e --- /dev/null +++ b/modules/custom_search/src/google_custom_search_module.e @@ -0,0 +1,154 @@ +note + description: "[ + Module that provide Google Custom Search functionality. + ]" + date: "$Date: 2015-10-09 20:50:01 -0300 (vi. 09 de oct. de 2015) $" + revision: "$Revision: 97982 $" + +class + GOOGLE_CUSTOM_SEARCH_MODULE + +inherit + + CMS_MODULE + redefine + register_hooks + end + + CMS_HOOK_BLOCK_HELPER + + CMS_HOOK_AUTO_REGISTER + + CMS_HOOK_MENU_SYSTEM_ALTER + + SHARED_EXECUTION_ENVIRONMENT + export + {NONE} all + end + + REFACTORING_HELPER + + SHARED_LOGGER + +create + make + +feature {NONE} -- Initialization + + make + -- Create current module + do + version := "1.0" + description := "Google custome search module" + package := "search" + end + +feature -- Access + + name: STRING = "custom_search" + -- + +feature -- Router + + setup_router (a_router: WSF_ROUTER; a_api: CMS_API) + -- Router configuration. + do + a_router.handle ("/gcse", create {WSF_URI_AGENT_HANDLER}.make (agent handle_search (a_api, ?, ?)), a_router.methods_head_get) + end + +feature -- Recaptcha + + gcse_secret_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get recaptcha security key. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("gcse.secret_key") as l_recaptcha_key and then + not l_recaptcha_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) + end + end + end + + gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get recaptcha security key. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("gcse.cx") as l_recaptcha_key and then + not l_recaptcha_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) + end + end + end + +feature -- Hooks configuration + + register_hooks (a_response: CMS_RESPONSE) + -- Module hooks configuration. + do + auto_subscribe_to_hooks (a_response) + end + +feature -- Hooks + + menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) + -- Hook execution on collection of menu contained by `a_menu_system' + -- for related response `a_response'. + do + end + + block_list: ITERABLE [like {CMS_BLOCK}.name] + do + Result := <<"search">> + end + +feature -- Handler + + handle_search (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + l_parameters:GCSE_QUERY_PARAMETERS + l_search: GCSE_API + do + -- TODO handle errors!!! + write_debug_log (generator + ".handle_search") + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if attached {WSF_STRING} req.query_parameter ("q") as l_query then + if + attached gcse_cx_key (api) as l_cx and then + attached gcse_secret_key (api) as l_key + then + create l_parameters.make (l_key, l_cx, l_query.value ) + if + attached {WSF_STRING} req.query_parameter ("start") as l_index and then + attached {WSF_STRING} req.query_parameter ("num") as l_num + then + l_parameters.set_start (l_index.value) + l_parameters.set_num (l_num.value) + end + create l_search.make (l_parameters) + l_search.search + if attached template_block (Current, "search", r) as l_tpl_block then + l_tpl_block.set_value (l_search.last_result, "result") + r.add_block (l_tpl_block, "content") + end + else + -- If no key are provided, at least output google search result page. + if req.is_https then + r.set_redirection ("https://www.google.com/search?sitesearch=" + r.absolute_url ("", Void) + "&q=" + l_query.url_encoded_value) + else + r.set_redirection ("http://www.google.com/search?sitesearch=" + r.absolute_url ("", Void) + "&q=" + l_query.url_encoded_value) + end + end + end + r.execute + end + +end From 9263f31521389b9a2bdcd4137a240335db9d58d6 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Wed, 14 Oct 2015 11:51:59 -0300 Subject: [PATCH 2/3] Renamed module name to google_search (custom_search) Clean code. Updated google custom search to handle quota limit and no query submit. Updated encoding issues for input searches: like "void safe" and "void + safe". --- examples/demo/demo-safe.ecf | 2 +- .../config/google_search - copia.json | 6 + .../config/google_search.json} | 0 .../templates/block_search.tpl | 6 +- .../bootstrap/assets/js/popup_search.js | 8 + examples/demo/site/themes/bootstrap/page.tpl | 8 +- library/gcse/gcse.ecf | 25 +- library/gcse/src/gcse_api.e | 101 +++--- library/gcse/src/gcse_page.e | 9 +- library/gcse/src/gcse_page_item.e | 17 +- library/gcse/src/gcse_page_map.e | 33 +- library/gcse/src/gcse_query_parameters.e | 287 +++++++++--------- library/gcse/src/gcse_response.e | 29 +- .../Readme.md | 0 .../google_search.ecf} | 4 +- .../site/config/google_search.json} | 0 .../site/templates/block_search.tpl | 6 +- .../src/google_custom_search_module.e | 150 +++++++++ 18 files changed, 435 insertions(+), 256 deletions(-) create mode 100644 examples/demo/site/modules/google_search/config/google_search - copia.json rename examples/demo/site/modules/{custom_search/config/custom_search.json => google_search/config/google_search.json} (100%) rename examples/demo/site/modules/{custom_search => google_search}/templates/block_search.tpl (92%) create mode 100644 examples/demo/site/themes/bootstrap/assets/js/popup_search.js rename modules/{custom_search => google_search}/Readme.md (100%) rename modules/{custom_search/custom_search.ecf => google_search/google_search.ecf} (91%) rename modules/{custom_search/site/config/custom_search.json => google_search/site/config/google_search.json} (100%) rename modules/{custom_search => google_search}/site/templates/block_search.tpl (92%) create mode 100644 modules/google_search/src/google_custom_search_module.e diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index 2f8ffc1..83bb689 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -26,7 +26,7 @@ - + -
    +
      {foreach from="$result.items" item="item"} @@ -18,7 +18,7 @@
      -

      {htmlentities}{$item.snippet/}{/htmlentities}

      +

      {$item.html_snippet/}

      @@ -37,4 +37,4 @@
    1. Next
    2. {/if} - \ No newline at end of file + diff --git a/examples/demo/site/themes/bootstrap/assets/js/popup_search.js b/examples/demo/site/themes/bootstrap/assets/js/popup_search.js new file mode 100644 index 0000000..5854223 --- /dev/null +++ b/examples/demo/site/themes/bootstrap/assets/js/popup_search.js @@ -0,0 +1,8 @@ + $(document).ready(function() { + $('#gcse_search_form').submit(function() { + window.open('', 'formpopup', 'width=600,height=600,resizeable,scrollbars'); + this.target = 'formpopup'; + }); + }); + + diff --git a/examples/demo/site/themes/bootstrap/page.tpl b/examples/demo/site/themes/bootstrap/page.tpl index aba3059..76eb77a 100644 --- a/examples/demo/site/themes/bootstrap/page.tpl +++ b/examples/demo/site/themes/bootstrap/page.tpl @@ -5,9 +5,10 @@ - + + {if isset="$head"}{$head/}{/if} {if isset="$styles"}{$styles/}{/if} @@ -21,7 +22,10 @@ {$head_title/} + + + {if isset="$region_top"} @@ -40,7 +44,7 @@
      -
      +
      diff --git a/library/gcse/gcse.ecf b/library/gcse/gcse.ecf index a086fb8..707023d 100644 --- a/library/gcse/gcse.ecf +++ b/library/gcse/gcse.ecf @@ -1,28 +1,21 @@ - + - - /.git$ - /EIFGENs$ - /CVS$ - /.svn$ - + + /.git$ + /EIFGENs$ + /CVS$ + /.svn$ + - - - - - - + + diff --git a/library/gcse/src/gcse_api.e b/library/gcse/src/gcse_api.e index 5a46f82..213b3c5 100644 --- a/library/gcse/src/gcse_api.e +++ b/library/gcse/src/gcse_api.e @@ -19,17 +19,17 @@ feature {NONE} -- Initialization make (a_query_parameters: GCSE_QUERY_PARAMETERS) -- Create an object GCSE with query_parameters `a_query_parameters' do - query_paremeter := a_query_parameters + query_parameter := a_query_parameters ensure - query_parameters_set: query_paremeter = a_query_parameters + query_parameters_set: query_parameter = a_query_parameters end feature -- Access base_uri: STRING_8 = "https://www.googleapis.com/customsearch/v1" - -- Google custom search base URI + -- Google custom search base URI. - query_paremeter: GCSE_QUERY_PARAMETERS + query_parameter: GCSE_QUERY_PARAMETERS -- Google custom search parameters. last_result: detachable GCSE_RESPONSE @@ -38,7 +38,7 @@ feature -- Access feature -- Status Reports errors: detachable LIST [READABLE_STRING_8] - -- optional table of error codes + -- optional list of error messages. feature -- API @@ -53,12 +53,15 @@ feature -- API -- but it's possible to define atom response using the alt parameter. last_result := Void if attached get as l_response then + create l_gcse_response + l_gcse_response.set_status (l_response.status) + l_gcse_response.set_status_nessage (l_response.status_message) + if attached l_response.body as l_body then create l_parser.make_with_string (l_body) l_parser.parse_content - if l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv then + if l_response.status = 200 and then l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv then -- Queries - create l_gcse_response if attached {JSON_OBJECT} jv.item (queries_key) as jqueries then -- Next Page if attached {GCSE_PAGE} query_page (next_page_key, jqueries) as l_page then @@ -80,7 +83,8 @@ feature -- API end end end - + else + put_error (l_body) end else put_error (l_response.status.out) @@ -107,7 +111,7 @@ feature {NONE} -- Implementation new_uri: STRING_8 -- new uri (BaseUri?key=secret_value&cx=a_cx_id&q=a_query -- ?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures - -- full teamplte BaseUri?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}& + -- full template BaseUri?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}& -- safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}& -- googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}& -- siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}& @@ -118,24 +122,24 @@ feature {NONE} -- Implementation do create Result.make_from_string (base_uri) Result.append ("?key=") - Result.append (query_paremeter.secret) + Result.append (query_parameter.secret) Result.append ("&cx=") - Result.append (query_paremeter.cx) + Result.append (query_parameter.cx) Result.append ("&q=") - Result.append (query_paremeter.query) + Result.append (query_parameter.query) -- num - if attached query_paremeter.num as l_num then + if attached query_parameter.num as l_num then Result.append ("&num=") Result.append (l_num) end - if attached query_paremeter.start as l_start then + if attached query_parameter.start as l_start then Result.append ("&start=") Result.append (l_start) end end - put_error (a_code: READABLE_STRING_GENERAL) - -- put error with code `a_code'. + put_error (a_message: READABLE_STRING_GENERAL) + -- put error message `a_message'. local l_errors: like errors utf: UTF_CONVERTER @@ -145,35 +149,35 @@ feature {NONE} -- Implementation create {ARRAYED_LIST [STRING]} l_errors.make (1) errors := l_errors end - l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_code)) + l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_message)) end item (a_item: JSON_OBJECT): GCSE_PAGE_ITEM -- Google Result Metadata Item. do create Result - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("kind")) as l_kind then + if attached {JSON_STRING} a_item.item ("kind") as l_kind then Result.set_kind (l_kind.item) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("title")) as l_title then + if attached {JSON_STRING} a_item.item ("title") as l_title then Result.set_title (l_title.item) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("htmlTitle")) as l_htmltitle then - Result.set_html_title (l_htmltitle.item) + if attached {JSON_STRING} a_item.item ("htmlTitle") as l_htmltitle then + Result.set_html_title (l_htmltitle.unescaped_string_32) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("link")) as l_link then + if attached {JSON_STRING} a_item.item ("link") as l_link then Result.set_link (l_link.item) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("displayLink")) as l_display_link then + if attached {JSON_STRING} a_item.item ("displayLink") as l_display_link then Result.set_display_link (l_display_link.item) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("snippet")) as l_snippet then - Result.set_snippet (l_snippet.item) + if attached {JSON_STRING} a_item.item ("snippet") as l_snippet then + Result.set_snippet (l_snippet.unescaped_string_8) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("htmlSnippet")) as l_html_snippet then - Result.set_html_snippet (l_html_snippet.item) + if attached {JSON_STRING} a_item.item ("htmlSnippet") as l_html_snippet then + Result.set_html_snippet (l_html_snippet.unescaped_string_32) end - if attached {JSON_STRING} a_item.item (create {JSON_STRING}.make_from_string ("formattedUrl")) as l_formatted_url then + if attached {JSON_STRING} a_item.item ("formattedUrl") as l_formatted_url then Result.set_formatted_url (l_formatted_url.item) end end @@ -181,22 +185,26 @@ feature {NONE} -- Implementation query_page (a_page_key: JSON_STRING; a_queries: JSON_OBJECT): detachable GCSE_PAGE -- Google result medata query. Return a query page based for a query with page key `a_page_key', if any. do - if attached {JSON_ARRAY} a_queries.item (a_page_key) as jquerypage and then attached {JSON_OBJECT} jquerypage.i_th (1) as jpage then + if + attached {JSON_ARRAY} a_queries.item (a_page_key) as jquerypage and then + jquerypage.count > 0 and then + attached {JSON_OBJECT} jquerypage.i_th (1) as jpage + then create Result - if attached {JSON_STRING} jpage.item (create {JSON_STRING}.make_from_string ("title")) as l_title then + if attached {JSON_STRING} jpage.item ("title") as l_title then Result.set_title (l_title.item) end - if attached {JSON_STRING} jpage.item (create {JSON_STRING}.make_from_string ("totalResults")) as l_results then + if attached {JSON_STRING} jpage.item ("totalResults") as l_results then Result.set_total_results (l_results.item.to_integer) end - if attached {JSON_STRING} jpage.item (create {JSON_STRING}.make_from_string ("searchTerms")) as l_search_terms then + if attached {JSON_STRING} jpage.item ("searchTerms") as l_search_terms then Result.set_search_terms (l_search_terms.item) end -- TODO check if we should use INTEGER_64 - if attached {JSON_NUMBER} jpage.item (create {JSON_STRING}.make_from_string ("count")) as l_count then + if attached {JSON_NUMBER} jpage.item ("count") as l_count then Result.set_count (l_count.integer_64_item.as_integer_32) end - if attached {JSON_NUMBER} jpage.item (create {JSON_STRING}.make_from_string ("startIndex")) as l_index then + if attached {JSON_NUMBER} jpage.item ("startIndex") as l_index then Result.set_start_index (l_index.integer_64_item.as_integer_32) end end @@ -204,30 +212,15 @@ feature {NONE} -- Implementation feature {NONE} -- JSON Keys - queries_key: JSON_STRING - do - create Result.make_from_string ("queries") - end + queries_key: STRING = "queries" - next_page_key: JSON_STRING - do - create Result.make_from_string ("nextPage") - end + next_page_key: STRING = "nextPage" - request_key: JSON_STRING - do - create Result.make_from_string ("request") - end + request_key: STRING = "request" - previous_page_key: JSON_STRING - do - create Result.make_from_string ("previousPage") - end + previous_page_key: STRING = "previousPage" - items_key: JSON_STRING - do - create Result.make_from_string ("items") - end + items_key: STRING = "items" note copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" diff --git a/library/gcse/src/gcse_page.e b/library/gcse/src/gcse_page.e index 9fc2cae..5387e75 100644 --- a/library/gcse/src/gcse_page.e +++ b/library/gcse/src/gcse_page.e @@ -6,6 +6,10 @@ note class GCSE_PAGE +inherit + + DEBUG_OUTPUT + feature -- Access search_terms: detachable STRING_8 @@ -67,9 +71,10 @@ feature -- Change element start_index_set: start_index = a_start_index end -feature -- Output +feature -- Status report - to_string: STRING_8 + debug_output: STRING_8 + -- do create Result.make_from_string ("%NPage details%N") if attached title as l_title then diff --git a/library/gcse/src/gcse_page_item.e b/library/gcse/src/gcse_page_item.e index 469bacc..7e5426c 100644 --- a/library/gcse/src/gcse_page_item.e +++ b/library/gcse/src/gcse_page_item.e @@ -8,7 +8,7 @@ class inherit - SHARED_HTML_ENCODER + DEBUG_OUTPUT feature -- Access @@ -27,9 +27,6 @@ feature -- Access snippet: detachable STRING_8 -- Snippet of this result - snippet_2: detachable STRING_8 - -- Snippet of this result - display_link: detachable STRING_8 -- Display link of this result @@ -79,7 +76,6 @@ feature -- Element change -- Assign `html_snippet' with `a_html_snippet'. do html_snippet := a_html_snippet - snippet_2 := html_encoded (a_html_snippet) ensure html_snippet_assigned: html_snippet = a_html_snippet end @@ -143,7 +139,8 @@ feature -- Element change feature -- Output - to_string: STRING_8 + debug_output: STRING_8 + -- do create Result.make_from_string ("%NPage Item details%N") if attached title as l_title then @@ -199,14 +196,6 @@ feature -- Output end - html_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8 - do - if s /= Void then - Result := html_encoder.general_encoded_string (s) - else - create Result.make_empty - end - end note copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/gcse/src/gcse_page_map.e b/library/gcse/src/gcse_page_map.e index 67468ab..9b5f099 100644 --- a/library/gcse/src/gcse_page_map.e +++ b/library/gcse/src/gcse_page_map.e @@ -1,5 +1,21 @@ note - description: "Represent a google page map" + description: "[ + Represent a google page map + "pagemap": { + "cse_image": [ + { + "src": "https://www.eiffel.org/portal/files/userpictures/picture-40.jpg" + } + ], + "cse_thumbnail": [ + { + "width": "81", + "height": "61", + "src": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRnC-RKzps6BFItx_MLYBVskFI7U6u0y3VJBInomPYEF5sO6gkip94mLw" + } + ] + } + ]" date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $" revision: "$Revision: 97973 $" EIS: "name=PageMaps", "src=https://developers.google.com/custom-search/docs/structured_data#pagemaps", "protocol=url" @@ -9,20 +25,7 @@ class feature -- Access --- "pagemap": { --- "cse_image": [ --- { --- "src": "https://www.eiffel.org/portal/files/userpictures/picture-40.jpg" --- } --- ], --- "cse_thumbnail": [ --- { --- "width": "81", --- "height": "61", --- "src": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRnC-RKzps6BFItx_MLYBVskFI7U6u0y3VJBInomPYEF5sO6gkip94mLw" --- } --- ] --- } + note diff --git a/library/gcse/src/gcse_query_parameters.e b/library/gcse/src/gcse_query_parameters.e index 77e91e1..6d8c18e 100644 --- a/library/gcse/src/gcse_query_parameters.e +++ b/library/gcse/src/gcse_query_parameters.e @@ -4,6 +4,150 @@ note Example url template "template": "https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json" ]" + optional_parameters: "[ + Optional parameters + c2coff string Enables or disables Simplified and Traditional Chinese Search. + The default value for this parameter is 0 (zero), meaning that the feature is enabled. Supported values are: + 1: Disabled + 0: Enabled (default) + cr string Restricts search results to documents originating in a particular country. + You may use Boolean operators in the cr parameter's value. + Google Search determines the country of a document by analyzing: + the top-level domain (TLD) of the document's URL + the geographic location of the Web server's IP address + See the Country Parameter Values page for a list of valid values for this parameter. + cref string The URL of a linked custom search engine specification to use for this request. + Does not apply for Google Site Search + If both cx and cref are specified, the cx value is used + cx string The custom search engine ID to use for this request. + If both cx and cref are specified, the cx value is used. + dateRestrict string Restricts results to URLs based on date. Supported values include: + d[number]: requests results from the specified number of past days. + w[number]: requests results from the specified number of past weeks. + m[number]: requests results from the specified number of past months. + y[number]: requests results from the specified number of past years. + exactTerms string Identifies a phrase that all documents in the search results must contain. + excludeTerms string Identifies a word or phrase that should not appear in any documents in the search results. + fileType string Restricts results to files of a specified extension. A list of file types indexable by Google can be found in Webmaster Tools Help Center. + filter string Controls turning on or off the duplicate content filter. + See Automatic Filtering for more information about Google's search results filters. Note that host crowding filtering applies only to multi-site searches. + By default, Google applies filtering to all search results to improve the quality of those results. + + + Acceptable values are: + "0": Turns off duplicate content filter. + "1": Turns on duplicate content filter. + gl string Geolocation of end user. + The gl parameter value is a two-letter country code. The gl parameter boosts search results whose country of origin matches the parameter value. See the Country Codes page for a list of valid values. + Specifying a gl parameter value should lead to more relevant results. This is particularly true for international customers and, even more specifically, for customers in English- speaking countries other than the United States. + googlehost string The local Google domain (for example, google.com, google.de, or google.fr) to use to perform the search. + highRange string + Specifies the ending value for a search range. + Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query. + hl string Sets the user interface language. + Explicitly setting this parameter improves the performance and the quality of your search results. + See the Interface Languages section of Internationalizing Queries and Results Presentation for more information, and Supported Interface Languages for a list of supported languages. + hq string Appends the specified query terms to the query, as if they were combined with a logical AND operator. + imgColorType string Returns black and white, grayscale, or color images: mono, gray, and color. + + Acceptable values are: + "color": color + "gray": gray + "mono": mono + imgDominantColor string Returns images of a specific dominant color. + + Acceptable values are: + "black": black + "blue": blue + "brown": brown + "gray": gray + "green": green + "pink": pink + "purple": purple + "teal": teal + "white": white + "yellow": yellow + imgSize string Returns images of a specified size. + + Acceptable values are: + "huge": huge + "icon": icon + "large": large + "medium": medium + "small": small + "xlarge": xlarge + "xxlarge": xxlarge + imgType string Returns images of a type. + + Acceptable values are: + "clipart": clipart + "face": face + "lineart": lineart + "news": news + "photo": photo + linkSite string Specifies that all search results should contain a link to a particular URL + lowRange string Specifies the starting value for a search range. + Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query. + lr string Restricts the search to documents written in a particular language (e.g., lr=lang_ja). + + Acceptable values are: + "lang_ar": Arabic + "lang_bg": Bulgarian + "lang_ca": Catalan + "lang_cs": Czech + "lang_da": Danish + "lang_de": German + "lang_el": Greek + "lang_en": English + "lang_es": Spanish + "lang_et": Estonian + "lang_fi": Finnish + "lang_fr": French + "lang_hr": Croatian + "lang_hu": Hungarian + "lang_id": Indonesian + "lang_is": Icelandic + "lang_it": Italian + "lang_iw": Hebrew + "lang_ja": Japanese + "lang_ko": Korean + "lang_lt": Lithuanian + "lang_lv": Latvian + "lang_nl": Dutch + "lang_no": Norwegian + "lang_pl": Polish + "lang_pt": Portuguese + "lang_ro": Romanian + "lang_ru": Russian + "lang_sk": Slovak + "lang_sl": Slovenian + "lang_sr": Serbian + "lang_sv": Swedish + "lang_tr": Turkish + "lang_zh-CN": Chinese (Simplified) + "lang_zh-TW": Chinese (Traditional) + + orTerms string Provides additional search terms to check for in a document, where each document in the search results must contain at least one of the additional search terms. + relatedSite string Specifies that all search results should be pages that are related to the specified URL. + rights string Filters based on licensing. Supported values include: cc_publicdomain, cc_attribute, cc_sharealike, cc_noncommercial, cc_nonderived, and combinations of these. + safe string Search safety level. + + Acceptable values are: + "high": Enables highest level of SafeSearch filtering. + "medium": Enables moderate SafeSearch filtering. + "off": Disables SafeSearch filtering. (default) + searchType string Specifies the search type: image. If unspecified, results are limited to webpages. + + Acceptable values are: + "image": custom image search. + siteSearch string Specifies all search results should be pages from a given site. + siteSearchFilter string Controls whether to include or exclude results from the site named in the siteSearch parameter. + + Acceptable values are: + "e": exclude + "i": include + sort string The sort expression to apply to the results. +]" date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $" revision: "$Revision: 97966 $" EIS: "GCSE parameters", "src=https://developers.google.com/custom-search/json-api/v1/reference/cse/list", "protocol=URI" @@ -46,149 +190,6 @@ feature -- Access : Required Parameters feature -- Optional Parameters ---Optional parameters ---c2coff string Enables or disables Simplified and Traditional Chinese Search. --- The default value for this parameter is 0 (zero), meaning that the feature is enabled. Supported values are: --- 1: Disabled --- 0: Enabled (default) ---cr string Restricts search results to documents originating in a particular country. --- You may use Boolean operators in the cr parameter's value. --- Google Search determines the country of a document by analyzing: --- the top-level domain (TLD) of the document's URL --- the geographic location of the Web server's IP address --- See the Country Parameter Values page for a list of valid values for this parameter. ---cref string The URL of a linked custom search engine specification to use for this request. --- Does not apply for Google Site Search --- If both cx and cref are specified, the cx value is used ---cx string The custom search engine ID to use for this request. --- If both cx and cref are specified, the cx value is used. ---dateRestrict string Restricts results to URLs based on date. Supported values include: --- d[number]: requests results from the specified number of past days. --- w[number]: requests results from the specified number of past weeks. --- m[number]: requests results from the specified number of past months. --- y[number]: requests results from the specified number of past years. ---exactTerms string Identifies a phrase that all documents in the search results must contain. ---excludeTerms string Identifies a word or phrase that should not appear in any documents in the search results. ---fileType string Restricts results to files of a specified extension. A list of file types indexable by Google can be found in Webmaster Tools Help Center. ---filter string Controls turning on or off the duplicate content filter. --- See Automatic Filtering for more information about Google's search results filters. Note that host crowding filtering applies only to multi-site searches. --- By default, Google applies filtering to all search results to improve the quality of those results. - - --- Acceptable values are: --- "0": Turns off duplicate content filter. --- "1": Turns on duplicate content filter. --- gl string Geolocation of end user. ---The gl parameter value is a two-letter country code. The gl parameter boosts search results whose country of origin matches the parameter value. See the Country Codes page for a list of valid values. ---Specifying a gl parameter value should lead to more relevant results. This is particularly true for international customers and, even more specifically, for customers in English- speaking countries other than the United States. ---googlehost string The local Google domain (for example, google.com, google.de, or google.fr) to use to perform the search. ---highRange string ---Specifies the ending value for a search range. ---Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query. ---hl string Sets the user interface language. ---Explicitly setting this parameter improves the performance and the quality of your search results. ---See the Interface Languages section of Internationalizing Queries and Results Presentation for more information, and Supported Interface Languages for a list of supported languages. ---hq string Appends the specified query terms to the query, as if they were combined with a logical AND operator. ---imgColorType string Returns black and white, grayscale, or color images: mono, gray, and color. - --- Acceptable values are: --- "color": color --- "gray": gray --- "mono": mono ---imgDominantColor string Returns images of a specific dominant color. - --- Acceptable values are: --- "black": black --- "blue": blue --- "brown": brown --- "gray": gray --- "green": green --- "pink": pink --- "purple": purple --- "teal": teal --- "white": white --- "yellow": yellow ---imgSize string Returns images of a specified size. - --- Acceptable values are: --- "huge": huge --- "icon": icon --- "large": large --- "medium": medium --- "small": small --- "xlarge": xlarge --- "xxlarge": xxlarge ---imgType string Returns images of a type. - --- Acceptable values are: --- "clipart": clipart --- "face": face --- "lineart": lineart --- "news": news --- "photo": photo ---linkSite string Specifies that all search results should contain a link to a particular URL ---lowRange string Specifies the starting value for a search range. ---Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query. ---lr string Restricts the search to documents written in a particular language (e.g., lr=lang_ja). - --- Acceptable values are: --- "lang_ar": Arabic --- "lang_bg": Bulgarian --- "lang_ca": Catalan --- "lang_cs": Czech --- "lang_da": Danish --- "lang_de": German --- "lang_el": Greek --- "lang_en": English --- "lang_es": Spanish --- "lang_et": Estonian --- "lang_fi": Finnish --- "lang_fr": French --- "lang_hr": Croatian --- "lang_hu": Hungarian --- "lang_id": Indonesian --- "lang_is": Icelandic --- "lang_it": Italian --- "lang_iw": Hebrew --- "lang_ja": Japanese --- "lang_ko": Korean --- "lang_lt": Lithuanian --- "lang_lv": Latvian --- "lang_nl": Dutch --- "lang_no": Norwegian --- "lang_pl": Polish --- "lang_pt": Portuguese --- "lang_ro": Romanian --- "lang_ru": Russian --- "lang_sk": Slovak --- "lang_sl": Slovenian --- "lang_sr": Serbian --- "lang_sv": Swedish --- "lang_tr": Turkish --- "lang_zh-CN": Chinese (Simplified) --- "lang_zh-TW": Chinese (Traditional) - ---orTerms string Provides additional search terms to check for in a document, where each document in the search results must contain at least one of the additional search terms. ---relatedSite string Specifies that all search results should be pages that are related to the specified URL. ---rights string Filters based on licensing. Supported values include: cc_publicdomain, cc_attribute, cc_sharealike, cc_noncommercial, cc_nonderived, and combinations of these. ---safe string Search safety level. - --- Acceptable values are: --- "high": Enables highest level of SafeSearch filtering. --- "medium": Enables moderate SafeSearch filtering. --- "off": Disables SafeSearch filtering. (default) ---searchType string Specifies the search type: image. If unspecified, results are limited to webpages. - ---Acceptable values are: --- "image": custom image search. ---siteSearch string Specifies all search results should be pages from a given site. ---siteSearchFilter string Controls whether to include or exclude results from the site named in the siteSearch parameter. - --- Acceptable values are: --- "e": exclude --- "i": include --- sort string The sort expression to apply to the results. --- num : detachable STRING_8 diff --git a/library/gcse/src/gcse_response.e b/library/gcse/src/gcse_response.e index 5ffdfcb..32fdb2e 100644 --- a/library/gcse/src/gcse_response.e +++ b/library/gcse/src/gcse_response.e @@ -18,7 +18,6 @@ class feature -- Access - current_page: detachable GCSE_PAGE -- Metadata describing the query for the current set of results. -- This role is always present in the response. @@ -75,6 +74,34 @@ feature -- Change Element end l_items.force (a_item) end + + +feature -- Acess: HTTP Response + + status: INTEGER + -- HTTP status code. + + status_message: detachable READABLE_STRING_8 + -- associated textual phrase for the response status. + +feature -- Change Element: HTTP Response + + set_status (a_status: like status) + -- Set `status' with `a_status'. + do + status := a_status + ensure + status_set: status = a_status + end + + set_status_nessage (a_message: like status_message) + -- Set `status_message' with `a_message'. + do + status_message := a_message + ensure + status_message_set: status_message = a_message + end + ;note copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/modules/custom_search/Readme.md b/modules/google_search/Readme.md similarity index 100% rename from modules/custom_search/Readme.md rename to modules/google_search/Readme.md diff --git a/modules/custom_search/custom_search.ecf b/modules/google_search/google_search.ecf similarity index 91% rename from modules/custom_search/custom_search.ecf rename to modules/google_search/google_search.ecf index 35bdfe6..e772135 100644 --- a/modules/custom_search/custom_search.ecf +++ b/modules/google_search/google_search.ecf @@ -1,6 +1,6 @@ - - + + diff --git a/modules/custom_search/site/config/custom_search.json b/modules/google_search/site/config/google_search.json similarity index 100% rename from modules/custom_search/site/config/custom_search.json rename to modules/google_search/site/config/google_search.json diff --git a/modules/custom_search/site/templates/block_search.tpl b/modules/google_search/site/templates/block_search.tpl similarity index 92% rename from modules/custom_search/site/templates/block_search.tpl rename to modules/google_search/site/templates/block_search.tpl index d37d146..b11c31b 100644 --- a/modules/custom_search/site/templates/block_search.tpl +++ b/modules/google_search/site/templates/block_search.tpl @@ -4,7 +4,7 @@ -
        +
          {foreach from="$result.items" item="item"} @@ -18,7 +18,7 @@
          -

          {htmlentities}{$item.snippet/}{/htmlentities}

          +

          {$item.html_snippet/}

          @@ -37,4 +37,4 @@
        1. Next
        2. {/if} - \ No newline at end of file + diff --git a/modules/google_search/src/google_custom_search_module.e b/modules/google_search/src/google_custom_search_module.e new file mode 100644 index 0000000..d325eb0 --- /dev/null +++ b/modules/google_search/src/google_custom_search_module.e @@ -0,0 +1,150 @@ +note + description: "[ + Module providing Google Custom Search functionality. + ]" + date: "$Date: 2015-10-09 20:50:01 -0300 (vi. 09 de oct. de 2015) $" + revision: "$Revision: 97982 $" + +class + GOOGLE_CUSTOM_SEARCH_MODULE + +inherit + + CMS_MODULE + + CMS_HOOK_BLOCK_HELPER + + SHARED_EXECUTION_ENVIRONMENT + export + {NONE} all + end + + REFACTORING_HELPER + + SHARED_LOGGER + +create + make + +feature {NONE} -- Initialization + + make + -- Create current module + do + version := "1.0" + description := "Google custome search module" + package := "search" + end + +feature -- Access + + name: STRING = "google_search" + -- + +feature -- Router + + setup_router (a_router: WSF_ROUTER; a_api: CMS_API) + -- Router configuration. + do + a_router.handle ("/gcse", create {WSF_URI_AGENT_HANDLER}.make (agent handle_search (a_api, ?, ?)), a_router.methods_head_get) + end + +feature -- Recaptcha + + gcse_secret_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get recaptcha security key. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("gcse.secret_key") as l_recaptcha_key and then + not l_recaptcha_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) + end + end + end + + gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get recaptcha security key. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("gcse.cx") as l_recaptcha_key and then + not l_recaptcha_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) + end + end + end + +feature -- Handler + + handle_search (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + l_parameters:GCSE_QUERY_PARAMETERS + l_search: GCSE_API + do + -- TODO handle errors!!! + write_debug_log (generator + ".handle_search") + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if + attached {WSF_STRING} req.query_parameter ("q") as l_query and then + not l_query.value.is_empty + then + if + attached gcse_cx_key (api) as l_cx and then + attached gcse_secret_key (api) as l_key + then + create l_parameters.make (l_key, l_cx, l_query.url_encoded_value ) + if + attached {WSF_STRING} req.query_parameter ("start") as l_index and then + attached {WSF_STRING} req.query_parameter ("num") as l_num + then + l_parameters.set_start (l_index.value) + l_parameters.set_num (l_num.value) + end + create l_search.make (l_parameters) + l_search.search + if + attached l_search.last_result as l_result and then + l_result.status = 200 + then + if attached template_block (Current, "search", r) as l_tpl_block then + l_tpl_block.set_value (l_result, "result") + r.add_block (l_tpl_block, "content") + end + else + -- Quota limit (403 status code) or not results. + google_search_site (req, r, l_query) + end + else + -- If no key are provided, at least output google search result page. + google_search_site (req, r, l_query) + end + else + r.add_message ("No query submitted", Void) + end + r.execute + end + +feature {NONE} -- Helper + + google_search_site (req: WSF_REQUEST; res: CMS_RESPONSE; query: WSF_STRING) + -- Workaround to output google search result page + -- If no key are provided or if GCSE reached the quota limit. + local + l_url_encoder: URL_ENCODER + do + create l_url_encoder + if req.is_https then + res.set_redirection ("https://www.google.com/search?sitesearch=" + l_url_encoder.general_encoded_string (res.absolute_url ("", Void)) + "&q=" + query.url_encoded_value) + else + res.set_redirection ("http://www.google.com/search?sitesearch=" + l_url_encoder.general_encoded_string (res.absolute_url ("", Void)) + "&q=" + query.url_encoded_value) + end + end +end From 193760b34fbcd57d960756b10b983a32f1aefe3a Mon Sep 17 00:00:00 2001 From: jvelilla Date: Wed, 14 Oct 2015 11:57:06 -0300 Subject: [PATCH 3/3] Remove unneeded file. --- .../modules/google_search/config/google_search - copia.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 examples/demo/site/modules/google_search/config/google_search - copia.json diff --git a/examples/demo/site/modules/google_search/config/google_search - copia.json b/examples/demo/site/modules/google_search/config/google_search - copia.json deleted file mode 100644 index aab3e8d..0000000 --- a/examples/demo/site/modules/google_search/config/google_search - copia.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "gcse": { - "cx":"015017565055626880074:9gdgp1fvt-g", - "secret_key":"AIzaSyBKAXNofo-RqZb6kUmpbiCwPEy7n7-E51k" - } -}