daeURI.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * Copyright 2006 Sony Computer Entertainment Inc.
  3. *
  4. * Licensed under the MIT Open Source License, for details please see license.txt or the website
  5. * http://www.opensource.org/licenses/mit-license.php
  6. *
  7. */
  8. #ifndef __DAE_URI_H__
  9. #define __DAE_URI_H__
  10. #include <string>
  11. #include <dae/daeTypes.h>
  12. #include <dae/daeElement.h>
  13. #include <dae/daeUtils.h>
  14. class DAE;
  15. /**
  16. * The @c daeURI is a simple class designed to aid in the parsing and resolution
  17. * of URI references inside COLLADA elements.
  18. * A @c daeURI is created for every @c anyURL and @c IDREF in the COLLADA schema.
  19. * For example, the <instance> element has the url= attribute of type @c anyURL, and the
  20. * <controller> element has the target= attribute of type @c IDREF.
  21. * The @c daeURI class contains a URI string; the @c set() method breaks the string into
  22. * its components including scheme, authority, path (directory), and fragment.
  23. * It also has the capability to attempt to resolve this reference
  24. * into a @c daeElement, through the method @c resolveElement().
  25. * If a @c daeURI is stored within a @c daeElement, it fills
  26. * its container field to point to the containing element.
  27. *
  28. * The main API on the @c daeURI, @c resolveElement(), uses a @c daeURIResolver
  29. * to search for the @c daeElement inside a @c daeDatabase.
  30. *
  31. * URIs are resolved hierarchically, where each URI is resolved based on
  32. * the following criteria via itself and its element's base URI, which represents the
  33. * URI of the document that contains the element, retrieved by
  34. * <tt>daeElement::getBaseURI().</tt>
  35. * If no base URI is provided, then the application URI
  36. * is used as a base.
  37. *
  38. * The URI resolution order for the COLLADA DOM is as follows:
  39. * - Absolute URI is specified (see definition below):
  40. * The URI ignores its parent/base URI when validating.
  41. * - Relative URI is specified:
  42. * The URI uses the base URI to provide the scheme, authority, and base path.
  43. * This URI's path is appended to the path given the the base URI.
  44. * This URI's file and ID are used.
  45. * - Each level of URI is resolved in this way against the base URI of the
  46. * containing file until the top level is reached. Then the application URI
  47. * is used as the default.
  48. *
  49. * <b>Definition of Absolute URI:</b>
  50. * For the purposes of the COLLADA DOM, a URI is considered absolute
  51. * if it starts by specifying a scheme.
  52. * For example,
  53. * - file:///c:/data/foo.dae#myScene is an absolute URI.
  54. * - foo.dae#myScene is relative.
  55. * - foo.dae is a top-level file reference and is relative.
  56. * If the URI does not include a pound sign (#), the <tt><i>fragment</i></tt> is empty.
  57. */
  58. class DLLSPEC daeURI
  59. {
  60. private:
  61. daeElement* internalResolveElement() const;
  62. public:
  63. /**
  64. * An enum describing the status of the URI resolution process.
  65. * This is pretty much entirely useless now. Just use the various accessors
  66. * to query the state of the uri.
  67. */
  68. enum ResolveState{
  69. /** No URI specified */
  70. uri_empty,
  71. /** URI specified but unresolved */
  72. uri_loaded,
  73. /** Resolution pending */
  74. uri_pending,
  75. /** Resolution successful */
  76. uri_success,
  77. /** Failure due to unsupported URI scheme */
  78. uri_failed_unsupported_protocol,
  79. /** Failure because the file was not found */
  80. uri_failed_file_not_found,
  81. /** Failure because the fragment was not found */
  82. uri_failed_id_not_found,
  83. /** Failure due to an invalid fragment */
  84. uri_failed_invalid_id,
  85. /** A flag specifying that the URI should be resolved locally to its own document */
  86. uri_resolve_local,
  87. /** A flag specifying that the URI should be resolved using this relative URI */
  88. uri_resolve_relative,
  89. /** A flag specifying that the URI should be resolved using this absolute URI */
  90. uri_resolve_absolute,
  91. /** Failure due to an invalid reference */
  92. uri_failed_invalid_reference,
  93. /** Failure due to an external error */
  94. uri_failed_externalization,
  95. /** Failure due to missing document */
  96. uri_failed_missing_container,
  97. /** Failure because automatic loading of a document is turned off */
  98. uri_failed_external_document
  99. };
  100. private:
  101. // All daeURIs have a pointer to a master DAE that they use to access global information.
  102. mutable DAE* dae;
  103. /** Resolved version of the URI */
  104. std::string uriString;
  105. /** Original URI before resolution */
  106. std::string originalURIString;
  107. /** scheme component */
  108. std::string _scheme;
  109. /** authority component */
  110. std::string _authority;
  111. /** path component */
  112. std::string _path;
  113. /** query component */
  114. std::string _query;
  115. /** fragment component */
  116. std::string _fragment;
  117. /** Pointer to the element that owns this URI */
  118. daeElement* container;
  119. public:
  120. /**
  121. * Constructs a daeURI object that contains no URI reference.
  122. * @param dae The DAE associated with this daeURI.
  123. * current working directory.
  124. */
  125. daeURI(DAE& dae);
  126. /**
  127. * Destructor
  128. */
  129. ~daeURI();
  130. /**
  131. * Constructs a daeURI object from a URI passed in as a string.
  132. * @param dae The DAE associated with this daeURI.
  133. * @param URIString Passed to set() automatically.
  134. * @param nofrag If true, the fragment part of the URI is stripped off before construction.
  135. */
  136. daeURI(DAE& dae, const std::string& URIString, daeBool nofrag = false);
  137. /**
  138. * Constructs a daeURI object using a <tt><i>baseURI</i></tt> and a <tt><i>uriString.</i></tt>
  139. * Calls set(URIString), and @c validate(baseURI).
  140. * @param baseURI Base URI to resolve against.
  141. * @param URIString String designating this URI.
  142. */
  143. daeURI(const daeURI& baseURI, const std::string& URIString);
  144. /**
  145. * Constructs a daeURI object based on a simple copy from an existing @c daeURI.
  146. * @param constructFromURI URI to copy into this one.
  147. */
  148. daeURI(const daeURI& constructFromURI);
  149. /**
  150. * Constructs a daeURI given a container element and a URI string.
  151. * @param container The container element.
  152. * @param uriString the URI string.
  153. */
  154. daeURI(daeElement& container, const std::string& uriString = "");
  155. // This constructor is for internal DOM purposes only. For client code, use the constructor
  156. // that takes only a daeElement instead of this one.
  157. daeURI(DAE& dae, daeElement& container, const std::string& uriString = "");
  158. /**
  159. * Gets the DAE objects associated with this daeURI.
  160. * @return Returns a pointer to the associated DAE. This will never return null.
  161. */
  162. DAE* getDAE() const;
  163. // Returns the fully resolved URI as a string
  164. const std::string& str() const;
  165. // Returns the URI as originally set (i.e. not resolved against the base URI)
  166. const std::string& originalStr() const;
  167. // Old C string versions of the previous functions
  168. daeString getURI() const; // Alias for str()
  169. daeString getOriginalURI() const; // Alias for originalStr();
  170. // Setter function for setting the full uri.
  171. void set(const std::string& uriStr, const daeURI* baseURI = NULL);
  172. // Setter function for setting the individual uri components.
  173. void set(const std::string& scheme,
  174. const std::string& authority,
  175. const std::string& path,
  176. const std::string& query,
  177. const std::string& fragment,
  178. const daeURI* baseURI = NULL);
  179. // Old C string function. Alias for set().
  180. void setURI(daeString uriStr, const daeURI* baseURI = NULL);
  181. // std::string based component accessors.
  182. const std::string& scheme() const;
  183. const std::string& authority() const;
  184. const std::string& path() const;
  185. const std::string& query() const;
  186. const std::string& fragment() const;
  187. const std::string& id() const; // Alias for fragment()
  188. // Component setter functions. If you're going to be calling multiple setters, as in
  189. // uri.path(path);
  190. // uri.fragment(frag);
  191. // it'd be more efficient to call uri.set once instead.
  192. void scheme(const std::string& scheme);
  193. void authority(const std::string& authority);
  194. void path(const std::string& path);
  195. void query(const std::string& query);
  196. void fragment(const std::string& fragment);
  197. void id(const std::string& id); // Alias for uri.fragment(frag)
  198. // Retrieves the individual path components. For example, in a uri of the form
  199. // file:/folder/file.dae, dir = /folder/, baseName = file, ext = .dae
  200. void pathComponents(std::string& dir, std::string& baseName, std::string& ext) const;
  201. // Individual path component accessors. If you need access to multiple path
  202. // components, calling pathComponents() will be faster.
  203. std::string pathDir() const; // daeURI("/folder/file.dae").pathDir() == "/folder/"
  204. std::string pathFileBase() const; // daeURI("/folder/file.dae").pathFileBase() == "file"
  205. std::string pathExt() const; // daeURI("/folder/file.dae").pathExt() == ".dae"
  206. std::string pathFile() const; // daeURI("/folder/file.dae").pathFile() == "file.dae"
  207. // Path component setter.
  208. void path(const std::string& dir, const std::string& baseName, const std::string& ext);
  209. // Individual path component setters. If you're going to be calling multiple setters,
  210. // it'd be more efficient to call set() instead.
  211. void pathDir(const std::string& dir);
  212. void pathFileBase(const std::string& baseName);
  213. void pathExt(const std::string& ext);
  214. void pathFile(const std::string& file);
  215. // The older C string accessors. Aliases for the std::string based component accessors.
  216. daeString getScheme() const;
  217. daeString getProtocol() const; // Alias for getScheme()
  218. daeString getAuthority() const;
  219. daeString getPath() const;
  220. daeString getQuery() const;
  221. daeString getFragment() const;
  222. daeString getID() const; // Alias for getFragment()
  223. // Same as getPath(), but puts the result in the destination buffer. This is only here
  224. // for backward compatibility. Use getPath() instead.
  225. daeBool getPath(daeChar* dest, daeInt size) const;
  226. /**
  227. * Gets the element that this URI resolves to in memory.
  228. * @return Returns a ref to the element.
  229. */
  230. daeElementRef getElement() const;
  231. // Returns the document that this URI references, or null if the document
  232. // hasn't been loaded yet.
  233. daeDocument* getReferencedDocument() const;
  234. /**
  235. * Gets a pointer to the @c daeElement that contains this URI.
  236. * @return Returns the pointer to the containing daeElmement.
  237. */
  238. inline daeElement* getContainer() const {return(container);};
  239. /**
  240. * Sets the pointer to the @c daeElement that contains this URI.
  241. * @param cont Pointer to the containing @c daeElmement.
  242. */
  243. void setContainer(daeElement* container);
  244. /**
  245. * Gets if this URI resolves to an element that is not contained in the same document as the URI.
  246. * @return Returns true if the URI references an external element. False otherwise.
  247. */
  248. daeBool isExternalReference() const;
  249. /**
  250. * Copies the URI specified in <tt><i>from</i></tt> into @c this.
  251. * Performs a simple copy without validating the URI.
  252. * @param from URI to copy from.
  253. */
  254. void copyFrom(const daeURI& from);
  255. /**
  256. * Outputs all components of this URI to stderr.
  257. * Useful for debugging URIs, this outputs each part of the URI separately.
  258. */
  259. void print();
  260. /**
  261. * Makes the "originalURI" in this URI relative to some other uri
  262. * @param uri the URI to make "this" relative to.
  263. * @note this is experimental and not fully tested, please don't use in critical code yet.
  264. */
  265. int makeRelativeTo(const daeURI* uri);
  266. /**
  267. * Comparison operator.
  268. * @return Returns true if URI's are equal.
  269. */
  270. inline bool operator==(const daeURI& other) const {
  271. return uriString == other.uriString;
  272. }
  273. daeURI& operator=(const daeURI& other);
  274. daeURI& operator=(const std::string& uri);
  275. // These methods are deprecated.
  276. void resolveElement(); // Call getElement directly.
  277. void validate(const daeURI* baseURI = NULL); // Shouldn't ever need to call this.
  278. ResolveState getState() const; // Call getElement to see if resolving succeeded.
  279. void setState(ResolveState newState); // Don't call this.
  280. private:
  281. /**
  282. * Resets this URI; frees all string references
  283. * and returns <tt><i>state</i></tt> to @c empty.
  284. */
  285. void reset();
  286. /**
  287. * Provides a shared initialization for all constructors
  288. */
  289. void initialize();
  290. public:
  291. /**
  292. * Performs RFC2396 path normalization.
  293. * @param path Path to be normalized.
  294. */
  295. static void normalizeURIPath(char* path);
  296. };
  297. class daeURIResolver;
  298. typedef daeTArray<daeURIResolver*> daeURIResolverPtrArray;
  299. /**
  300. * The @c daeURIResolver class is the plugin point for URI resolution.
  301. * This class is an abstract base class that defines an interface for
  302. * resolving URIs.
  303. * Every URI is passed through this list of @c daeURIResolvers for resolution.
  304. * The list is ordered on a first come, first serve basis, and resolution
  305. * terminates after any resolver instance resolves the URI.
  306. */
  307. class DLLSPEC daeURIResolver
  308. {
  309. public:
  310. /**
  311. * Constructor
  312. * @param dae The associated dae object.
  313. */
  314. daeURIResolver(DAE& dae);
  315. /**
  316. * Destructor
  317. */
  318. virtual ~daeURIResolver();
  319. /**
  320. * Sets a flag that tells the URI resolver whether or not to load a separate document if a URI
  321. * being resolved points to one.
  322. * @param load Set to true if you want the URI Resolver to automatically load other documents to
  323. * resolve URIs.
  324. */
  325. static void setAutoLoadExternalDocuments( daeBool load );
  326. /**
  327. * Gets a flag that tells if the URI resolver is set to load an external document if a URI
  328. * being resolved points to one.
  329. * @return Returns true if the resolver will automatically load documents to resolve a URI.
  330. * False otherwise.
  331. */
  332. static daeBool getAutoLoadExternalDocuments();
  333. /**
  334. * Provides an abstract interface for converting a @c daeURI into a @c daeElement
  335. * @param uri @c daeURI to resolve.
  336. * @return Returns the resolved element, or null if resolving failed.
  337. * returns false otherwise.
  338. */
  339. virtual daeElement* resolveElement(const daeURI& uri) = 0;
  340. /**
  341. * Gets the name of this resolver.
  342. * @return Returns the resolver name as a string.
  343. */
  344. virtual daeString getName() = 0;
  345. protected:
  346. static daeBool _loadExternalDocuments;
  347. DAE* dae;
  348. };
  349. // This is a container class for storing a modifiable list of daeURIResolver objects.
  350. class DLLSPEC daeURIResolverList {
  351. public:
  352. daeURIResolverList();
  353. ~daeURIResolverList();
  354. daeTArray<daeURIResolver*>& list();
  355. daeElement* resolveElement(const daeURI& uri);
  356. private:
  357. // Disabled copy constructor/assignment operator
  358. daeURIResolverList(const daeURIResolverList& resolverList) { };
  359. daeURIResolverList& operator=(const daeURIResolverList& resolverList) { return *this; };
  360. daeTArray<daeURIResolver*> resolvers;
  361. };
  362. // Helper functions for file path <--> URI conversion
  363. namespace cdom {
  364. // Takes a uri reference and parses it into its components.
  365. DLLSPEC bool parseUriRef(const std::string& uriRef,
  366. std::string& scheme,
  367. std::string& authority,
  368. std::string& path,
  369. std::string& query,
  370. std::string& fragment);
  371. // Takes the uri components of a uri ref and combines them.
  372. //
  373. // The 'forceLibxmlCompatible' param is meant to work around bugs in the file
  374. // scheme uri handling of libxml. It causes the function to output a uri
  375. // that's fully compatible with libxml. It only modifies file scheme uris,
  376. // since uris with other schemes seem to work fine.
  377. //
  378. // The known libxml uri bugs are as follows:
  379. // 1) libxml won't write files when given file scheme URIs with an empty
  380. // authority, as in "file:/home".
  381. // 2) libxml won't read or write Windows UNC paths represented with the
  382. // machine name in the authority, as in "file://otherMachine/folder/file.dae"
  383. // 3) On Windows, libxml won't read or write paths that don't have a drive
  384. // letter, as in "/folder/file.dae".
  385. DLLSPEC std::string assembleUri(const std::string& scheme,
  386. const std::string& authority,
  387. const std::string& path,
  388. const std::string& query,
  389. const std::string& fragment,
  390. bool forceLibxmlCompatible = false);
  391. // A wrapper function for calling assembleUri to create a URI that's compatible
  392. // with libxml.
  393. DLLSPEC std::string fixUriForLibxml(const std::string& uriRef);
  394. // This function takes a file path in the OS's native format and converts it to
  395. // a URI reference. If a relative path is given, a relative URI reference is
  396. // returned. If an absolute path is given, a relative URI reference containing
  397. // a fully specified path is returned. Spaces are encoded as %20. The 'type'
  398. // parameter indicates the format of the nativePath.
  399. //
  400. // Examples - Windows
  401. // nativePathToUri("C:\myFolder\myFile.dae") --> "/C:/myFolder/myFile.dae"
  402. // nativePathToUri("\myFolder\myFile.dae") --> "/myFolder/myFile.dae"
  403. // nativePathToUri("..\myFolder\myFile.dae") --> "../myFolder/myFile.dae"
  404. // nativePathToUri("\\otherComputer\myFile.dae") --> "//otherComputer/myFile.dae"
  405. //
  406. // Examples - Linux/Mac
  407. // nativePathToUri("/myFolder/myFile.dae") --> "/myFolder/myFile.dae"
  408. // nativePathToUri("../myFolder/myFile.dae") --> "../myFolder/myFile.dae"
  409. // nativePathToUri("/my folder/my file.dae") --> "/my%20folder/my%20file.dae"
  410. DLLSPEC std::string nativePathToUri(const std::string& nativePath,
  411. systemType type = getSystemType());
  412. // This function takes a URI reference and converts it to an OS file path. Conversion
  413. // can fail if the URI reference is ill-formed, or if the URI contains a scheme other
  414. // than "file", in which case an empty string is returned. The 'type' parameter
  415. // indicates the format of the returned native path.
  416. //
  417. // Examples - Windows
  418. // uriToNativePath("../folder/file.dae") --> "..\folder\file.dae"
  419. // uriToNativePath("/folder/file.dae") --> "\folder\file.dae"
  420. // uriToNativePath("file:/C:/folder/file.dae") --> "C:\folder\file.dae"
  421. // uriToNativePath("file://otherComputer/file.dae") --> "\\otherComputer\file.dae"
  422. // uriToNativePath("http://www.slashdot.org") --> "" (it's not a file scheme URI!)
  423. //
  424. // Examples - Linux/Mac
  425. // uriToNativePath("../folder/file.dae") --> "../folder/file.dae"
  426. // uriToNativePath("file:/folder/file.dae") --> "/folder/file.dae"
  427. // uriToNativePath("http://www.slashdot.org") --> "" (it's not a file scheme URI!)
  428. DLLSPEC std::string uriToNativePath(const std::string& uriRef,
  429. systemType type = getSystemType());
  430. DLLSPEC std::string filePathToUri(const std::string& filePath); // Alias for nativePathToUri
  431. DLLSPEC std::string uriToFilePath(const std::string& uriRef); // Alias for uriToNativePath
  432. }
  433. #endif //__DAE_URI_H__