You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
17 KiB

  1. <?php
  2. // Project: Web Reference Database (refbase) <http://www.refbase.net>
  3. // Copyright: Matthias Steffens <mailto:refbase@extracts.de> and the file's
  4. // original author(s).
  5. //
  6. // This code is distributed in the hope that it will be useful,
  7. // but WITHOUT ANY WARRANTY. Please see the GNU General Public
  8. // License for more details.
  9. //
  10. // File: ./includes/opensearch.inc.php
  11. // Repository: $HeadURL$
  12. // Author(s): Matthias Steffens <mailto:refbase@extracts.de>
  13. //
  14. // Created: 09-Jan-08, 00:30
  15. // Modified: $Date: 2008-09-18 13:54:33 +0000 (Thu, 18 Sep 2008) $
  16. // $Author$
  17. // $Revision: 1240 $
  18. // This include file contains functions that'll return an OpenSearch response.
  19. // Requires ActiveLink PHP XML Package, which is available under the GPL from:
  20. // <http://www.active-link.com/software/>. See 'opensearch.php' for more info.
  21. // TODO: I18n
  22. // Incorporate some include files:
  23. include_once 'includes/webservice.inc.php'; // include functions that are commonly used with the refbase webservices
  24. // Import the ActiveLink Packages
  25. require_once("classes/include.php");
  26. import("org.active-link.xml.XML");
  27. import("org.active-link.xml.XMLDocument");
  28. // --------------------------------------------------------------------
  29. // Return an OpenSearch description document if the OpenSearch client issued:
  30. // - .../opensearch.php?operation=explain
  31. //
  32. // Spec: <http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document>
  33. // See also: <http://developer.mozilla.org/en/docs/Creating_OpenSearch_plugins_for_Firefox>
  34. function openSearchDescription($exportStylesheet)
  35. {
  36. global $contentTypeCharset; // these variables are specified in 'ini.inc.php'
  37. global $convertExportDataToUTF8;
  38. global $officialDatabaseName;
  39. global $hostInstitutionName;
  40. global $hostInstitutionAbbrevName;
  41. global $feedbackEmail;
  42. global $databaseBaseURL;
  43. global $databaseKeywords;
  44. global $logoSmallImageURL;
  45. global $logoSmallImageWidth;
  46. global $logoSmallImageHeight;
  47. global $logoSmallImageType;
  48. global $faviconImageURL;
  49. global $loc; // defined in 'locales/core.php'
  50. $openSearchCollectionDoc = new XMLDocument();
  51. $openSearchCollectionDoc->setEncoding($contentTypeCharset);
  52. $openSearchCollection = openSearchGenerateBaseTags("Description");
  53. // --- begin search engine info -----------------------------
  54. // (note that we don't enforce any character length limits)
  55. // The 'ShortName' element contains a brief human-readable title that identifies this search engine:
  56. // (the value must contain 16 or fewer characters of plain text)
  57. addNewBranch($openSearchCollection, "ShortName", array(), "refbase (" . $hostInstitutionAbbrevName . ")"); // function 'addNewBranch()' is defined in 'webservice.inc.php'
  58. // The 'LongName' element contains an extended human-readable title that identifies this search engine:
  59. // (the value must contain 48 or fewer characters of plain text)
  60. addNewBranch($openSearchCollection, "LongName", array(), $officialDatabaseName);
  61. // The 'Description' element contains a human-readable text description of the search engine:
  62. // (the value must contain 1024 or fewer characters of plain text)
  63. addNewBranch($openSearchCollection,
  64. "Description",
  65. array(),
  66. $officialDatabaseName . ": " . $loc["SearchMain"] . ". " . $loc["ThisDatabaseIsMaintained"] . " " . $hostInstitutionName . " (" . $hostInstitutionAbbrevName . ")."
  67. );
  68. // The 'Tags' element contains a set of words that are used as keywords to identify and categorize the search content:
  69. // (the value must contain 256 or fewer characters of plain text; tags must be a single word and are delimited by the space character)
  70. addNewBranch($openSearchCollection, "Tags", array(), $databaseKeywords);
  71. // The 'Contact' element contains an email address at which the maintainer of the description document can be reached:
  72. // (the value must conform to the requirements of Section 3.4.1 "Addr-spec specification" in RFC 2822 <http://tools.ietf.org/html/rfc2822>)
  73. addNewBranch($openSearchCollection, "Contact", array(), $feedbackEmail);
  74. // The 'Attribution' element contains a list of all sources or entities that should be credited for the content contained in the search feed:
  75. // (the value must contain 256 or fewer characters of plain text)
  76. // addNewBranch($openSearchCollection, "Attribution", array(), "Search data copyright ..."); // uncomment and edit copyright statement if desired
  77. // The 'SyndicationRight' element contains a value that indicates the degree to which the search results provided by this search engine can be queried, displayed, and redistributed:
  78. // (possible values: "open", "limited", "private", "closed"; see <http://www.opensearch.org/Specifications/OpenSearch/1.1#The_.22SyndicationRight.22_element>)
  79. addNewBranch($openSearchCollection, "SyndicationRight", array(), "open");
  80. // The 'AdultContent' element contains a boolean value that should be set to true if the search results may contain material intended only for adults:
  81. // (possible values: "true", "false")
  82. addNewBranch($openSearchCollection, "AdultContent", array(), "false");
  83. // The 'Language' element contains a string that indicates that the search engine supports search results in the specified language:
  84. // (the value must conform to the XML 1.0 Language Identification, as specified by RFC 3066 in <http://tools.ietf.org/html/rfc3066>;
  85. // in addition, a value of "*" signifies that the search engine does not restrict search results to any particular language)
  86. addNewBranch($openSearchCollection, "Language", array(), "*");
  87. // The 'InputEncoding' element contains a string that indicates that the search engine supports search requests encoded with the specified character encoding:
  88. // (the value must conform to the XML 1.0 Character Encodings, as specified by the IANA Character Set Assignments: <http://www.iana.org/assignments/character-sets>)
  89. addNewBranch($openSearchCollection, "InputEncoding", array(), $contentTypeCharset);
  90. // The 'OutputEncoding' element contains a string that indicates that the search engine supports search responses encoded with the specified character encoding:
  91. // (the value must conform to the XML 1.0 Character Encodings, as specified by the IANA Character Set Assignments: <http://www.iana.org/assignments/character-sets>)
  92. if (($convertExportDataToUTF8 == "yes") AND ($contentTypeCharset != "UTF-8"))
  93. addNewBranch($openSearchCollection, "OutputEncoding", array(), "UTF-8");
  94. else
  95. addNewBranch($openSearchCollection, "OutputEncoding", array(), $contentTypeCharset);
  96. // The 'Developer' element contains the human-readable name or identifier of the creator or maintainer of the description document:
  97. // (the value must contain 64 or fewer characters of plain text)
  98. addNewBranch($openSearchCollection, "Developer", array(), "Web Reference Database (http://refbase.sourceforge.net)");
  99. // The 'Query' element defines a search query that can be performed by search clients:
  100. // (Spec: <http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_Query_element>)
  101. addNewBranch($openSearchCollection,
  102. "Query",
  103. array("role" => "example",
  104. "title" => "Sample search",
  105. "searchTerms" => "Miller", // search term example (we could also use ".+" but an ubiquitous author name such as "Miller" seems more intuitive and almost always results in some hits)
  106. "startIndex" => "1", // index number of the first search result, starting with one
  107. "count" => $_SESSION['userRecordsPerPage'] // default number of records per page preferred by the current user
  108. ),
  109. ""
  110. );
  111. // The 'Image' element contains a URL that identifies the location of an image that can be used in association with the search content:
  112. // (images with square aspect ratios are recommended, e.g. a 16x16 image of type ".ico" and a 64x64 image of type ".jpeg" or ".png")
  113. // - favicon image (16x16):
  114. addNewBranch($openSearchCollection,
  115. "Image",
  116. array("type" => "image/x-icon", // MIME type of this image
  117. "height" => "16", // image height, in pixels
  118. "width" => "16" // image width, in pixels
  119. ),
  120. $databaseBaseURL . $faviconImageURL
  121. );
  122. // - small logo image (e.g. 64x64):
  123. addNewBranch($openSearchCollection,
  124. "Image",
  125. array("type" => $logoSmallImageType,
  126. "height" => $logoSmallImageHeight,
  127. "width" => $logoSmallImageWidth
  128. ),
  129. $databaseBaseURL . $logoSmallImageURL
  130. );
  131. // --- end search engine info -------------------------------
  132. // --- begin URL templates ----------------------------------
  133. // The 'Url' element describes an interface by which a search client can make search requests of the search engine:
  134. // - URL template for output of OpenSearch Atom XML (which is the default):
  135. addNewBranch($openSearchCollection,
  136. "Url",
  137. array("type" => "application/atom+xml", // MIME type of the search result format
  138. "template" => $databaseBaseURL . "opensearch.php?query={searchTerms}&amp;startRecord={startIndex?}&amp;maximumRecords={count?}&amp;recordSchema=atom", // search URL template to be processed according to the OpenSearch URL template syntax
  139. "indexOffset" => "1", // index number of the first search result, starting with one
  140. // "pageOffset" => "1" // page number of the first set of search results (NOTE: currently, page-based searches are not supported by refbase)
  141. ),
  142. ""
  143. );
  144. // - URL template for output of RSS XML:
  145. addNewBranch($openSearchCollection,
  146. "Url",
  147. array("type" => "application/rss+xml",
  148. "template" => $databaseBaseURL . "opensearch.php?query={searchTerms}&amp;startRecord={startIndex?}&amp;maximumRecords={count?}&amp;recordSchema=rss",
  149. "indexOffset" => "1"
  150. ),
  151. ""
  152. );
  153. // - URL template for output of SRW_DC XML:
  154. addNewBranch($openSearchCollection,
  155. "Url",
  156. array("type" => "application/xml",
  157. "template" => $databaseBaseURL . "opensearch.php?query={searchTerms}&amp;startRecord={startIndex?}&amp;maximumRecords={count?}&amp;recordSchema=srw_dc",
  158. "indexOffset" => "1"
  159. ),
  160. ""
  161. );
  162. // - URL template for output of SRW_MODS XML:
  163. addNewBranch($openSearchCollection,
  164. "Url",
  165. array("type" => "application/xml",
  166. "template" => $databaseBaseURL . "opensearch.php?query={searchTerms}&amp;startRecord={startIndex?}&amp;maximumRecords={count?}&amp;recordSchema=srw_mods",
  167. "indexOffset" => "1"
  168. ),
  169. ""
  170. );
  171. // - URL template for output of HTML:
  172. addNewBranch($openSearchCollection,
  173. "Url",
  174. array("type" => "text/html",
  175. "template" => $databaseBaseURL . "opensearch.php?query={searchTerms}&amp;startRecord={startIndex?}&amp;maximumRecords={count?}&amp;recordSchema=html",
  176. "indexOffset" => "1"
  177. ),
  178. ""
  179. );
  180. // - URL template for output of JSON-formatted search suggestions:
  181. //
  182. // NOTE: An URL template with 'type="application/x-suggestions+json"' is used by Firefox
  183. // to specify the URL to use for fetching search suggestions in JSON format
  184. // See also: <http://developer.mozilla.org/en/Creating_OpenSearch_plugins_for_Firefox>
  185. // <http://developer.mozilla.org/en/Supporting_search_suggestions_in_search_plugins>
  186. // <http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0>
  187. // <http://hublog.hubmed.org/archives/001681.html>
  188. addNewBranch($openSearchCollection,
  189. "Url",
  190. array("type" => "application/x-suggestions+json",
  191. "template" => $databaseBaseURL . "opensearch.php?query={searchTerms}&amp;startRecord={startIndex?}&amp;maximumRecords={count?}&amp;recordSchema=json&amp;operation=suggest&amp;client=sug-refbase_suggest-1.0",
  192. "indexOffset" => "1"
  193. ),
  194. ""
  195. );
  196. // --- end URL templates ------------------------------------
  197. // --- begin Mozilla-specific elements ----------------------
  198. // The 'SearchForm' element contains the URL to go to to open up the search page at the site for which the plugin is designed to search:
  199. // (this provides a way for Firefox to let the user visit the web site directly)
  200. addNewBranch($openSearchCollection, "mozilla:SearchForm", array(), $databaseBaseURL); // this will show the main refbase page with the Quick Search form (to link to other search pages, append '. "simple_search.php"' etc)
  201. // --- end Mozilla-specific elements ------------------------
  202. $openSearchCollectionDoc->setXML($openSearchCollection);
  203. $openSearchCollectionString = $openSearchCollectionDoc->getXMLString();
  204. // Add the XML Stylesheet definition:
  205. // Note that this is just a hack (that should get fixed) since I don't know how to do it properly using the ActiveLink PHP XML Package ?:-/
  206. if (!empty($exportStylesheet))
  207. $openSearchCollectionString = preg_replace("/(?=\<OpenSearchDescription)/i","<?xml-stylesheet type=\"text/xsl\" href=\"" . $exportStylesheet . "\"?>\n",$openSearchCollectionString);
  208. return $openSearchCollectionString;
  209. }
  210. // --------------------------------------------------------------------
  211. // Return OpenSearch diagnostics (i.e. OpenSearch error information) wrapped into OpenSearch Atom XML:
  212. function openSearchDiagnostics($diagCode, $diagDetails, $exportStylesheet)
  213. {
  214. global $contentTypeCharset; // defined in 'ini.inc.php'
  215. // Map SRU/W diagnostic numbers to their corresponding messages:
  216. // (i.e., for OpenSearch diagnostics, we simply re-use the SRU/W diagnostics)
  217. $diagMessages = mapSRWDiagnostics(); // function 'mapSRWDiagnostics()' is defined in 'webservice.inc.php'
  218. if (isset($diagMessages[$diagCode]))
  219. $diagMessage = $diagMessages[$diagCode];
  220. else
  221. $diagMessage = "Unknown error";
  222. $atomCollectionDoc = new XMLDocument();
  223. $atomCollectionDoc->setEncoding($contentTypeCharset);
  224. $atomCollection = openSearchGenerateBaseTags("Error");
  225. // add feed-level tags:
  226. // - 'id':
  227. addNewBranch($atomCollection, "id", array(), "info:srw/diagnostic/1/"); // could something else be used as diagnostics feed ID instead?
  228. // - OpenSearch elements:
  229. addNewBranch($atomCollection, "opensearch:totalResults", array(), "1");
  230. addNewBranch($atomCollection, "openSearch:startIndex", array(), "1");
  231. addNewBranch($atomCollection, "openSearch:itemsPerPage", array(), "1");
  232. $diagnosticsBranch = new XMLBranch("entry");
  233. // add entry-level tags:
  234. addNewBranch($diagnosticsBranch, "title", array(), $diagMessage);
  235. // addNewBranch($atomCollection, "link", array("href" => ""), ""); // TODO (what could be used as link for a diagnostics entry?)
  236. addNewBranch($diagnosticsBranch, "updated", array(), generateISO8601TimeStamp()); // function 'generateISO8601TimeStamp()' is defined in 'include.inc.php'
  237. addNewBranch($diagnosticsBranch, "id", array(), "info:srw/diagnostic/1/" . $diagCode);
  238. $diagContent = $diagMessage;
  239. if (!empty($diagDetails))
  240. $diagContent .= ": " . $diagDetails;
  241. addNewBranch($diagnosticsBranch, "content", array("type" => "text"), "Error " . $diagCode . ": " . $diagContent); // TODO: I18n
  242. $atomCollection->addXMLBranch($diagnosticsBranch);
  243. $atomCollectionDoc->setXML($atomCollection);
  244. $atomCollectionString = $atomCollectionDoc->getXMLString();
  245. return $atomCollectionString;
  246. }
  247. // --------------------------------------------------------------------
  248. // Generate the basic OpenSearch XML tree required for a query response:
  249. function openSearchGenerateBaseTags($openSearchOperation)
  250. {
  251. if ($openSearchOperation == "Error") // OpenSearch Atom XML is used for diagnostics
  252. $atomCollection = atomGenerateBaseTags($openSearchOperation); // function 'atomGenerateBaseTags()' is defined in 'atomxml.inc.php'
  253. elseif ($openSearchOperation == "Description") // OpenSearch Description XML
  254. {
  255. $atomCollection = new XML("OpenSearchDescription");
  256. $atomCollection->setTagAttribute("xmlns", "http://a9.com/-/spec/opensearch/1.1/");
  257. $atomCollection->setTagAttribute("xmlns:opensearch", "http://a9.com/-/spec/opensearch/1.1/");
  258. $atomCollection->setTagAttribute("xmlns:mozilla", "http://www.mozilla.org/2006/browser/search/");
  259. }
  260. return $atomCollection;
  261. }
  262. // --------------------------------------------------------------------
  263. ?>