http.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright STREAMIT BV, 2010.
  3. *
  4. * Project : SIR
  5. * Module : Http
  6. * File name $Workfile: Http.c $
  7. * Last Save $Date: 2003/08/23 18:39:38 $
  8. * $Revision: 0.1 $
  9. * Creation Date : 2003/08/23 18:39:38
  10. *
  11. * Description : Http client routines
  12. *
  13. */
  14. #define LOG_MODULE LOG_HTTP_MODULE
  15. /*--------------------------------------------------------------------------*/
  16. /* Include files */
  17. /*--------------------------------------------------------------------------*/
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <sys/confos.h>
  22. #include <arpa/inet.h>
  23. #include <netdb.h>
  24. //#pragma text:appcode
  25. #include "system.h"
  26. #include "log.h"
  27. #include "settings.h"
  28. #include "util.h"
  29. #include "http.h"
  30. /*--------------------------------------------------------------------------*/
  31. /* Constant definitions */
  32. /*--------------------------------------------------------------------------*/
  33. /*--------------------------------------------------------------------------*/
  34. /* Type declarations */
  35. /*--------------------------------------------------------------------------*/
  36. /*--------------------------------------------------------------------------*/
  37. /* Local variables */
  38. /*--------------------------------------------------------------------------*/
  39. static CONST char EncTable[] =
  40. {
  41. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  42. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  43. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  44. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  45. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  46. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  47. 'w', 'x', 'y', 'z', '0', '1', '2', '3',
  48. '4', '5', '6', '7', '8', '9', '+', '/'
  49. };
  50. /*--------------------------------------------------------------------------*/
  51. /* Global variables */
  52. /*--------------------------------------------------------------------------*/
  53. /*--------------------------------------------------------------------------*/
  54. /* Local functions */
  55. /*--------------------------------------------------------------------------*/
  56. /*--------------------------------------------------------------------------*/
  57. /* Global functions */
  58. /*--------------------------------------------------------------------------*/
  59. /*!
  60. * \brief Calculate the space needed to store data in Base64
  61. *
  62. * \param NrOfBytes number of bytes to encode
  63. *
  64. * \return Number of bytes needed
  65. */
  66. int Base64EncodedSize(size_t tNrOfBytes)
  67. {
  68. return ((tNrOfBytes + 2) / 3 * 4) + 1;
  69. }
  70. /*!
  71. * \brief Encode (binary) data into a Base64 encoded string.
  72. *
  73. * \param szDest pointer to destination
  74. * \param pSrc pointer to (binary) data to encode.
  75. * \param tSize nrof bytes to read from pSrc
  76. *
  77. * \return Number of bytes copied to szDest
  78. * 0 if errors or nothing to encode
  79. */
  80. size_t Base64Encode(char *szDest, CONST u_char *pSrc, size_t tSize)
  81. {
  82. size_t DestLen = 0; /* nrof bytes in szDest */
  83. u_char Index = 0;
  84. unsigned char Tmp[3]; /* source data */
  85. /* Encode all input data */
  86. while (tSize > 0)
  87. {
  88. /* Get a piece of data to encode */
  89. memset(Tmp, 0, sizeof(Tmp));
  90. for (Index = 0; Index < sizeof(Tmp) && tSize > 0; Index++, tSize--)
  91. {
  92. Tmp[Index] = *pSrc++;
  93. }
  94. /* Encode 3 chars into 4 */
  95. *szDest++ = EncTable[ ((Tmp[0] >> 2) & 0x3F) ];
  96. *szDest++ = EncTable[ ((Tmp[0] << 4) & 0x3F) | ((Tmp[1] >> 4) & 0x0F) ];
  97. *szDest++ = (Index < 1) ? '=' : EncTable[ ((Tmp[1] << 2) & 0x3C) | ((Tmp[2] >> 6) & 0x03) ];
  98. *szDest++ = (Index < 2) ? '=' : EncTable[ ( Tmp[2] & 0x3F) ];
  99. DestLen += 4;
  100. }
  101. *szDest = '\0';
  102. return (DestLen);
  103. }
  104. /*!
  105. * \brief Get ip address of a host
  106. *
  107. * \param szHostName Name or string of the IP address
  108. * of the host
  109. * \return The IP address of the host.
  110. * 0 if not an IP address, or we could not resolve the name
  111. */
  112. u_long GetHostByName(CONST char *szHostName)
  113. {
  114. u_long dwAddress;
  115. if ((dwAddress = inet_addr(szHostName)) == (u_long)-1)
  116. {
  117. dwAddress = NutDnsGetHostByName((u_char*)szHostName);
  118. }
  119. return (dwAddress);
  120. }
  121. /*!
  122. * \brief Break a Url down in parts
  123. *
  124. * The hostname, port and URI pointers are
  125. * set to the appropriate locations or an empty string
  126. * if not present.
  127. *
  128. * \note szUrl is modified
  129. *
  130. * \param szUrl Url to parse
  131. */
  132. void HttpParseUrl(char *szUrl, TUrlParts *tUrlParts)
  133. {
  134. char *szStart; /* Points to the first character of the part */
  135. char *szEnd; /* Points to the last character of the part */
  136. /*
  137. * In case we don't find a Host, port or URI, point
  138. * to empty string
  139. */
  140. tUrlParts->pszHost = tUrlParts->pszPort = tUrlParts->pszPath = (char *)(szUrl + strlen(szUrl));
  141. /*
  142. * skip the prefix
  143. */
  144. szStart = strstr_P(szUrl, PSTR("://"));
  145. if (szStart != NULL)
  146. {
  147. szStart += 3;
  148. }
  149. else
  150. {
  151. /*
  152. * Apparently there is no prefix
  153. */
  154. szStart = (char *)szUrl;
  155. }
  156. /*
  157. * We have found the hostname
  158. */
  159. tUrlParts->pszHost = szStart;
  160. /*
  161. * Find the end of the hostname
  162. * End of it is indicated by ':' or '/'
  163. * If neither are found, assume we have a URL in
  164. * the form 'http://demeterkast.net'
  165. */
  166. szEnd = strchr(szStart, ':');
  167. if (szEnd != NULL)
  168. {
  169. /*
  170. * There is a port specification, get it now
  171. */
  172. *szEnd = '\0'; /* Terminate the previous part */
  173. szStart = szEnd + 1; /* point to the portnumber */
  174. tUrlParts->pszPort = szStart;
  175. }
  176. szEnd = strchr(szStart, '/');
  177. if (szEnd != NULL)
  178. {
  179. /*
  180. * There is a URI specification, get it now
  181. */
  182. *szEnd = '\0'; /* Terminate the previous part */
  183. tUrlParts->pszPath = szEnd + 1; /* point to the URI */
  184. }
  185. }
  186. /*!
  187. * \brief Send a request to a server.
  188. *
  189. * The connection to the server should already be
  190. * present and associated with a stream.
  191. *
  192. * \param ptStream [in] Opened stream to send the request to
  193. * \param pszHeaders [in] The headers to send
  194. * \param wMode [in] Bitmask for the request to send
  195. * - HTTP_AUTH to send a Basic authentication consisting of our hostname and an empty password
  196. * \return The number of characters written or a negative value to
  197. * indicate an error.
  198. */
  199. int HttpSendRequest(FILE *ptStream, CONST char *pszHeaders, u_short wMode)
  200. {
  201. int nResult = 0; /* Bytes sent during last call (or -1) */
  202. int nSent = 0; /* Total bytes sent */
  203. if ((pszHeaders == NULL) || (ptStream == NULL))
  204. {
  205. nResult = -1;
  206. }
  207. /*
  208. * Send the headers
  209. */
  210. if (nResult >= 0)
  211. {
  212. nSent += nResult;
  213. nResult = fprintf_P(ptStream, PSTR("%s"), pszHeaders);
  214. }
  215. /*
  216. * Add authentication info (if requested)
  217. */
  218. if (nResult >= 0)
  219. {
  220. nSent += nResult;
  221. nResult = 0;
  222. if (wMode & HTTP_AUTH)
  223. {
  224. char *szEncoded;
  225. char szToken[sizeof(confos.hostname)+1];
  226. /*
  227. * Compose the username:password
  228. * (We use our hostname and an empty password)
  229. */
  230. strncpy(szToken, confos.hostname, sizeof(szToken)-1);
  231. szToken[sizeof(szToken)-1] = '\0';
  232. strcat_P(szToken, PSTR(":"));
  233. szEncoded = MyMalloc(Base64EncodedSize(strlen(szToken)));
  234. if (szEncoded == NULL)
  235. {
  236. nResult = -1;
  237. }
  238. else
  239. {
  240. (void)Base64Encode(szEncoded, (u_char*)szToken, strlen(szToken));
  241. nResult = fprintf_P(ptStream, PSTR("Authorization: Basic %s\r\n"), szEncoded);
  242. MyFree(szEncoded);
  243. }
  244. }
  245. }
  246. /*
  247. * Print the end of header
  248. */
  249. if (nResult >= 0)
  250. {
  251. nSent += nResult;
  252. nResult = fprintf_P(ptStream, PSTR("\r\n"));
  253. }
  254. fflush(ptStream);
  255. if (nResult >= 0)
  256. {
  257. nSent += nResult;
  258. }
  259. else
  260. {
  261. nSent = -1;
  262. }
  263. return (nSent);
  264. }