Team Fortress 2 Source Code as on 22/4/2020
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.

515 lines
15 KiB

  1. //========= Copyright � 1996-2010, Valve LLC, All rights reserved. ============
  2. //
  3. // Purpose: Header for CWebAPIResponse objects
  4. //
  5. //=============================================================================
  6. #ifndef WEBAPI_RESPONSE_H
  7. #define WEBAPI_RESPONSE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "bufferpool.h"
  12. namespace GCSDK
  13. {
  14. enum EWebAPIOutputFormat
  15. {
  16. k_EWebAPIOutputFormat_JSON = 1,
  17. k_EWebAPIOutputFormat_XML = 2,
  18. k_EWebAPIOutputFormat_VDF = 3,
  19. k_EWebAPIOutputFormat_ParameterEncoding = 4,
  20. };
  21. enum EWebAPIValueType
  22. {
  23. // Object is the initial value
  24. k_EWebAPIValueType_Object = 0,
  25. k_EWebAPIValueType_Int32 = 1,
  26. k_EWebAPIValueType_Int64 = 2,
  27. k_EWebAPIValueType_UInt32 = 3,
  28. k_EWebAPIValueType_UInt64 = 4,
  29. k_EWebAPIValueType_Double = 5,
  30. k_EWebAPIValueType_String = 6,
  31. k_EWebAPIValueType_BinaryBlob = 7,
  32. k_EWebAPIValueType_Bool = 8,
  33. k_EWebAPIValueType_Null = 9,
  34. k_EWebAPIValueType_NumericArray = 10,
  35. };
  36. class CWebAPIValues;
  37. class CWebAPIResponse
  38. {
  39. public:
  40. CWebAPIResponse();
  41. ~CWebAPIResponse();
  42. // Set the HTTP status code for the response
  43. void SetStatusCode( EHTTPStatusCode eStatusCode ) { m_eStatusCode = eStatusCode; }
  44. // Set how many seconds until this response expires
  45. void SetExpirationSeconds( uint32 unExpirationSeconds ) { m_unExpirationSeconds = unExpirationSeconds; }
  46. // Set when this response was last modified
  47. void SetLastModified( RTime32 rtLastModified ) { m_rtLastModified = rtLastModified; }
  48. // Get the status code for the response
  49. EHTTPStatusCode GetStatusCode() const { return m_eStatusCode; }
  50. // Get how many seconds until this response expires
  51. uint32 GetExpirationSeconds() const { return m_unExpirationSeconds; }
  52. // Get when the response was last modified
  53. RTime32 GetLastModified() const { return m_rtLastModified; }
  54. // extended arrays include their element name as an object in JSON and VDF output formats
  55. void SetExtendedArrays( bool bExtendedArrays ) { m_bExtendedArrays = bExtendedArrays; }
  56. bool HasExtendedArrays() const { return m_bExtendedArrays; }
  57. // Outputs formatted data to buffer
  58. bool BEmitFormattedOutput( EWebAPIOutputFormat eFormat, CUtlBuffer &outputBuffer, size_t unMaxResultSize );
  59. // Resets the response to be empty
  60. void Clear();
  61. // Create the root value element in the response
  62. CWebAPIValues *CreateRootValue( const char *pchName );
  63. const CWebAPIValues *GetRootValue() const { return m_pValues; }
  64. CWebAPIValues *GetRootValue() { return m_pValues; }
  65. // Anonymous root nodes affect only JSON output and, when enabled, result in
  66. // the omission of the extra set of { } braces and the name of the root node.
  67. //
  68. // So this JSON:
  69. // { "root" : { "key1" : "value1", "key2" : "value2" } }
  70. // becomes:
  71. // { "key1" : "value1", "key2" : "value2" }
  72. void SetJSONAnonymousRootNode( bool bAnonymousRootNode ) { m_bJSONAnonymousRootNode = bAnonymousRootNode; }
  73. bool HasJSONAnonymousRootNode() const { return m_bJSONAnonymousRootNode; }
  74. private:
  75. // Emits JSON formatted representation of response
  76. bool BEmitJSON( CUtlBuffer &outputBuffer, size_t unMaxResultSize );
  77. // Emits KeyValues .vdf style formatted representation of response
  78. bool BEmitVDF( CUtlBuffer &outputBuffer, size_t unMaxResultSize );
  79. // Emits XML formatted representation of response
  80. bool BEmitXML( CUtlBuffer &outputBuffer, size_t unMaxResultSize );
  81. // parameter encoding, as used in a lot of open standards
  82. bool BEmitParameterEncoding( CUtlBuffer &outputBuffer );
  83. CWebAPIValues *m_pValues;
  84. EHTTPStatusCode m_eStatusCode;
  85. uint32 m_unExpirationSeconds;
  86. RTime32 m_rtLastModified;
  87. bool m_bExtendedArrays;
  88. bool m_bJSONAnonymousRootNode;
  89. };
  90. class CWebAPIValues
  91. {
  92. // !FIXME! DOTAMERGE
  93. //DECLARE_CLASS_MEMPOOL_MT( CWebAPIValues );
  94. private:
  95. void InitInternal( CWebAPIValues *pParent, int nNamePos, EWebAPIValueType eValueType, const char *pchArrayElementNames );
  96. CWebAPIValues( CWebAPIValues *pParent, int nNamePos, EWebAPIValueType eValueType, const char *pchArrayElementNames = NULL );
  97. CWebAPIValues( CWebAPIValues *pParent, const char *pchName, EWebAPIValueType eValueType, const char *pchArrayElementNames = NULL );
  98. public:
  99. explicit CWebAPIValues( const char *pchName );
  100. CWebAPIValues( const char *pchName, const char *pchArrayElementNames );
  101. ~CWebAPIValues();
  102. #ifdef GC
  103. // Gets the buffer pool used to reduce allocs in CWebAPIValues
  104. static CBufferPoolMT &GetBufferPool();
  105. #endif
  106. //
  107. // Child node handling
  108. //
  109. // Create a child object of this node, all children of the resultant
  110. // object must be named.
  111. CWebAPIValues *CreateChildObject( const char *pchName );
  112. // Return an existing child object - otherwise create one and return that.
  113. CWebAPIValues *FindOrCreateChildObject( const char *pchName );
  114. // Add a child object to the array, this should only be called on objects that are of the array type
  115. CWebAPIValues *AddChildObjectToArray();
  116. // Add a child array to the array, this should only be called on objects that are of the array type
  117. CWebAPIValues *AddChildArrayToArray( const char * pchArrayElementNames );
  118. // Create a child array of this node. Note that array nodes can only
  119. // have un-named children, in XML the pchArrayElementNames value will be used
  120. // as the element name for each of the children of the array, in JSON it will simply
  121. // be a numerically indexed [] array.
  122. CWebAPIValues *CreateChildArray( const char *pchName, const char *pchArrayElementNames );
  123. // Find first matching child by name, O(N) on number of children, this class isn't designed for searching
  124. CWebAPIValues * FindChild( const char *pchName );
  125. const CWebAPIValues * FindChild( const char *pchName ) const { return const_cast<CWebAPIValues *>(this)->FindChild( pchName ); }
  126. // Get the first child of this node
  127. CWebAPIValues * GetFirstChild();
  128. const CWebAPIValues * GetFirstChild() const { return m_pFirstChild; }
  129. // Call this on the returned value from GetFirstChild() or a previous GetNextChild() call to
  130. // proceed to the next child of the parent GetFirstChild() was originally called on.
  131. CWebAPIValues * GetNextChild();
  132. const CWebAPIValues * GetNextChild() const { return m_pNextPeer; }
  133. // Returns the parent of this node or NULL if this is the root of a tree
  134. CWebAPIValues * GetParent();
  135. const CWebAPIValues * GetParent() const { return m_pParent; }
  136. // Deletes the child with the given name - no-op if no child by that name
  137. void DeleteChild( const char *pchName );
  138. //
  139. // Setters
  140. //
  141. // Set string value
  142. void SetStringValue( const char *pchValue );
  143. // Set int32 value
  144. void SetInt32Value( int32 nValue );
  145. // Set uint32 value
  146. void SetUInt32Value( uint32 unValue );
  147. // Set int64 value
  148. void SetInt64Value ( int64 lValue );
  149. // Set uint64 value
  150. void SetUInt64Value( uint64 ulValue );
  151. // Set double value
  152. void SetDoubleValue( double flValue );
  153. // Set binary blob value
  154. void SetBinaryValue( const uint8 *pValue, uint32 unBytes );
  155. // Set boolean value
  156. void SetBoolValue( bool bValue );
  157. // Set boolean value
  158. void SetNullValue( );
  159. //
  160. // Accessors
  161. //
  162. // Get the name of the current node
  163. const char *GetName() const { return m_nNamePos >= 0 ? ( (const char *)m_pStringBuffer->Base() + m_nNamePos ) : NULL; }
  164. // get the name of the elements of this numeric array (if this is an array)
  165. const char *GetElementName() const { return m_nArrayChildElementNamePos >= 0 ? ( (const char *)m_pStringBuffer->Base() + m_nArrayChildElementNamePos ) : NULL; }
  166. // Get the type currently held by the node
  167. EWebAPIValueType GetType() const;
  168. // returns true if this is an object
  169. bool IsObject() const { return GetType() == k_EWebAPIValueType_Object; }
  170. // returns true if this is an object
  171. bool IsArray() const { return GetType() == k_EWebAPIValueType_NumericArray; }
  172. // Get int32 value
  173. int32 GetInt32Value() const;
  174. // Get uint32 value
  175. uint32 GetUInt32Value() const;
  176. // Get int64 value
  177. int64 GetInt64Value() const;
  178. // Get uint64 value
  179. uint64 GetUInt64Value() const;
  180. // Get double value
  181. double GetDoubleValue() const;
  182. // Get string value
  183. void GetStringValue( CUtlString &stringOut ) const;
  184. // Get binary blob value
  185. void GetBinaryValue( CUtlBuffer &bufferOut ) const;
  186. // Get bool value
  187. bool GetBoolValue() const;
  188. // Get Null value
  189. bool IsNullValue() const { return GetType() == k_EWebAPIValueType_Null; }
  190. //
  191. // Child Setters
  192. //
  193. // Set string value
  194. void SetChildStringValue( const char *pchChildName, const char *pchValue );
  195. // Set int32 value
  196. void SetChildInt32Value( const char *pchChildName, int32 nValue );
  197. // Set uint32 value
  198. void SetChildUInt32Value( const char *pchChildName, uint32 unValue );
  199. // Set int64 value
  200. void SetChildInt64Value ( const char *pchChildName, int64 lValue );
  201. // Set uint64 value
  202. void SetChildUInt64Value( const char *pchChildName, uint64 ulValue );
  203. // Set double value
  204. void SetChildDoubleValue( const char *pchChildName, double flValue );
  205. // Set binary blob value
  206. void SetChildBinaryValue( const char *pchChildName, const uint8 *pValue, uint32 unBytes );
  207. // Set boolean value
  208. void SetChildBoolValue( const char *pchChildName, bool bValue );
  209. // Set null value
  210. void SetChildNullValue( const char *pchChildName );
  211. //
  212. // Accessors
  213. //
  214. // Get int32 value
  215. int32 GetChildInt32Value( const char *pchChildName, int32 nDefault = 0 ) const;
  216. // Get uint32 value
  217. uint32 GetChildUInt32Value( const char *pchChildName, uint32 unDefault = 0 ) const;
  218. // Get int64 value
  219. int64 GetChildInt64Value( const char *pchChildName, int64 lDefault = 0 ) const;
  220. // Get uint64 value
  221. uint64 GetChildUInt64Value( const char *pchChildName, uint64 ulDefault = 0 ) const;
  222. // Get double value
  223. double GetChildDoubleValue( const char *pchChildName, double flDefault = 0 ) const;
  224. // Get string value
  225. void GetChildStringValue( CUtlString &stringOut, const char *pchChildName, const char *pchDefault ) const;
  226. // Get binary blob value (returns false if the child wasn't found)
  227. bool BGetChildBinaryValue( CUtlBuffer &bufferOut, const char *pchChildName ) const;
  228. // Get bool value
  229. bool GetChildBoolValue( const char *pchChildName, bool bDefault = false ) const;
  230. // get null value
  231. bool IsChildNullValue( const char *pchChildName ) const;
  232. //
  233. // Output methods
  234. //
  235. // Emits JSON formatted representation of response
  236. static bool BEmitJSONRecursive( const CWebAPIValues *pCurrent, CUtlBuffer &outputBuffer, int nTabLevel, size_t unMaxResultSize, bool bIncludeArrayElementName = true );
  237. // Emits KeyValues .vdf style formatted representation of response
  238. static bool BEmitVDFRecursive( const CWebAPIValues *pCurrent, CUtlBuffer &outputBuffer, int nTabLevel, uint32 nArrayElement, size_t unMaxResultSize, bool bIncludeArrayElementName = true );
  239. // Emits XML formatted representation of response
  240. static bool BEmitXMLRecursive( const CWebAPIValues *pCurrent, CUtlBuffer &outputBuffer,int nTabLevel, size_t unMaxResultSize );
  241. //
  242. // Parsing methods
  243. //
  244. // parses JSON into a tree of CWebAPIValues nodes.
  245. static CWebAPIValues * ParseJSON( CUtlBuffer &inputBuffer );
  246. static CWebAPIValues * ParseJSON( const char *pchJSONString );
  247. //
  248. // Utility methods
  249. //
  250. // copies the children and type from the specified node into this node
  251. void CopyFrom( const CWebAPIValues *pSource );
  252. private:
  253. // sets the name of the node when constructing or copying
  254. void SetName( const char * pchName );
  255. // Clears any existing value, freeing memory if needed
  256. void ClearValue();
  257. // Assert that we don't have any child nodes, this is used when setting a native type value. We don't
  258. // support having both our own value and children. You are either an array of more values, or you are a value yourself.
  259. void AssertNoChildren();
  260. // Internal helper for creating children
  261. CWebAPIValues *CreateChildInternal( const char *pchName, EWebAPIValueType eValueType, const char *pchArrayElementNames = NULL );
  262. // Name of this node
  263. int32 m_nNamePos;
  264. // Data value contained in this node
  265. EWebAPIValueType m_eValueType;
  266. struct WebAPIBinaryValue_t
  267. {
  268. int32 m_nDataPos;
  269. uint32 m_unBytes;
  270. };
  271. union
  272. {
  273. int32 m_nValue;
  274. int64 m_lValue;
  275. uint32 m_unValue;
  276. uint64 m_ulValue;
  277. double m_flValue;
  278. int32 m_nStrValuePos;
  279. bool m_bValue;
  280. int32 m_nArrayChildElementNamePos;
  281. WebAPIBinaryValue_t m_BinaryValue;
  282. };
  283. CWebAPIValues * m_pFirstChild;
  284. CWebAPIValues * m_pLastChild;
  285. CWebAPIValues * m_pNextPeer;
  286. CWebAPIValues * m_pParent;
  287. CUtlBuffer *m_pStringBuffer;
  288. };
  289. #define FOR_EACH_WEBAPI_CHILD( pParentParam, pChildParam ) \
  290. for( CWebAPIValues *pChildParam = pParentParam->GetFirstChild(); pChildParam != NULL; pChildParam = pChildParam->GetNextChild() )
  291. }
  292. #include "tier0/memdbgon.h"
  293. namespace GCSDK
  294. {
  295. //-----------------------------------------------------------------------------
  296. // Purpose: KeyValues wrapper that automatically deletes itself on close
  297. //-----------------------------------------------------------------------------
  298. class CWebAPIValuesAD
  299. {
  300. public:
  301. CWebAPIValuesAD()
  302. {
  303. m_pwav = NULL;
  304. }
  305. // create a webapivalues object of the object type
  306. CWebAPIValuesAD( const char *pchName )
  307. {
  308. m_pwav = new CWebAPIValues( pchName );
  309. }
  310. // create a webapivalues object of the array type
  311. CWebAPIValuesAD( const char *pchName, const char *pchArrayElementName )
  312. {
  313. m_pwav = new CWebAPIValues( pchName, pchArrayElementName );
  314. }
  315. CWebAPIValuesAD( const CWebAPIValuesAD &rhs )
  316. {
  317. m_pwav = NULL;
  318. Copy( rhs.m_pwav );
  319. }
  320. CWebAPIValuesAD( const CWebAPIValues *pwav )
  321. {
  322. m_pwav = NULL;
  323. Copy( pwav );
  324. }
  325. ~CWebAPIValuesAD()
  326. {
  327. delete m_pwav;
  328. }
  329. CWebAPIValues *operator->() { if ( !m_pwav ) m_pwav = new CWebAPIValues( "root" ); return m_pwav; }
  330. operator CWebAPIValues *() { if ( !m_pwav ) m_pwav = new CWebAPIValues( "root" ); return m_pwav; }
  331. operator const CWebAPIValues *() const { return m_pwav; }
  332. CWebAPIValuesAD & operator= ( const CWebAPIValuesAD &rhs )
  333. {
  334. Copy( rhs.m_pwav );
  335. return *this;
  336. }
  337. void Take( CWebAPIValues *pwav )
  338. {
  339. if ( pwav )
  340. {
  341. delete m_pwav;
  342. m_pwav = pwav;
  343. }
  344. else if ( m_pwav )
  345. {
  346. delete m_pwav;
  347. m_pwav = NULL;
  348. }
  349. }
  350. void Copy( const CWebAPIValues *pwav )
  351. {
  352. if ( m_pwav )
  353. delete m_pwav;
  354. if ( pwav )
  355. {
  356. if( pwav->IsArray() )
  357. m_pwav = new CWebAPIValues( pwav->GetName(), pwav->GetElementName() );
  358. else
  359. m_pwav = new CWebAPIValues( pwav->GetName() );
  360. m_pwav->CopyFrom( pwav );
  361. }
  362. else
  363. m_pwav = NULL;
  364. }
  365. private:
  366. CWebAPIValues *operator=(CWebAPIValues *); // use Take() or Copy()
  367. CWebAPIValues *m_pwav;
  368. };
  369. // use to decode binary values
  370. bool Base64Decode( const char *pchData, uint32 cchDataMax, uint8 *pubDecodedData, uint32 *pcubDecodedData, bool bIgnoreInvalidCharacters );
  371. bool Base64Encode( const uint8 *pubData, uint32 cubData, char *pchEncodedData, uint32 *pcchEncodedData, const char *pszLineBreak = NULL );
  372. uint32 Base64EncodeMaxOutput( const uint32 cubData, const char *pszLineBreak = NULL );
  373. inline bool Base64EncodeIntoUTLMemory( const uint8 *pubData, uint32 cubData, CUtlMemory<char>& out_pBuffer )
  374. {
  375. // Stomp buffer and pre-allocate space.
  376. out_pBuffer.EnsureCapacity( Base64EncodeMaxOutput( cubData ) );
  377. // Perform encode, swallowing the used space output.
  378. uint32 unBufferCapacity = out_pBuffer.Count();
  379. return Base64Encode( pubData, cubData, out_pBuffer.Base(), &unBufferCapacity );
  380. }
  381. }
  382. namespace ProtoBufHelper
  383. {
  384. bool RecursiveAddProtoBufToWebAPIValues( GCSDK::CWebAPIValues *pWebAPIRoot, const ::google::protobuf::Message & msg );
  385. bool ParseWebAPIValues( ::google::protobuf::Message & msg, const GCSDK::CWebAPIValues *pWebAPIRoot, bool bEnforceRequired = false );
  386. }
  387. #include "tier0/memdbgoff.h"
  388. #endif // WEBAPI_RESPONSE_H