/* Copyright 1997 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/***************************************************/
/* File   : URLveneer.c                            */
/*                                                 */
/* Purpose: Veneer to the URL_Fetcher module SWIs. */
/*                                                 */
/* Author : A.D.Hodgkinson                         */
/*                                                 */
/* History: 17-Aug-97: Created from Fetch.c.       */
/***************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "swis.h"

#include "wimp.h"
#include "event.h"

#include "svcprint.h"
#include "Global.h"
#include "Utils.h"

#include "URLutils.h"

#include "URLveneer.h"

/*************************************************/
/* url_register()                                */
/*                                               */
/* Registers a requirement to fetch a URL with   */
/* the URL module.                               */
/*                                               */
/* Parameters: Flags (must be 0 at present);     */
/*                                               */
/*             Pointer to int into which the     */
/*             session handle is placed. May be  */
/*             NULL.                             */
/*************************************************/

_kernel_oserror * url_register(unsigned int flags, unsigned int * handle)
{
  _kernel_oserror * e;
  unsigned int      h;

  /* If there's a pointer to put the handle into, set it to zero initially */

  if (handle) *handle = 0;

  e = _swix(URL_Register,
            _IN(0) | _OUT(1),

            flags,

            &h);

  /* If the call didn't return an error, store the session handle */

  if ((!e) && (handle)) *handle = h;

  #ifdef TRACE
    if (tl & (1u<<6))
    {
      if (!e) Printf("url_register: Registered ID %d\n",*handle);
      else Printf("url_register: Exitting with error\n");
    }
  #endif

  return e;
}

/*************************************************/
/* url_deregister()                              */
/*                                               */
/* Deregisters a requirement to fetch a URL with */
/* the URL module.                               */
/*                                               */
/* Parameters: Flags (must be 0 at present);     */
/*                                               */
/*             The session handle.               */
/*************************************************/

_kernel_oserror * url_deregister(unsigned int flags, unsigned int handle)
{
  #ifdef TRACE
    if (tl & (1u<<6)) Printf("url_deregister: Deregistering ID %d\n",handle);
  #endif

  /* Abort any current action */

  url_stop(flags,handle);

  /* Deregister the session */

  return _swix(URL_Deregister,
               _INR(0,1),

               flags,
               handle);
}

/*************************************************/
/* url_stop()                                    */
/*                                               */
/* Interrupts a fetch if one is going on.        */
/*                                               */
/* Parameters: Flags (must be 0 at present);     */
/*                                               */
/*             The session handle.               */
/*************************************************/

_kernel_oserror * url_stop(unsigned int flags, unsigned int handle)
{
  #ifdef TRACE
    if (tl & (1u<<6)) Printf("url_stop: Stop with ID %d\n",handle);
  #endif

  return _swix(URL_Stop,
               _INR(0,1),

               flags,
               handle);
}

/*************************************************/
/* url_get_url()                                 */
/*                                               */
/* Starts fetching data from a URL.              */
/*                                               */
/* Parameters: Flags - if URL_GetURL_AgentGiven  */
/*             (see URLveneer.h) is set, this    */
/*             function works out the agent      */
/*             string so you don't need to pass  */
/*             it in externally;                 */
/*                                               */
/*             The session handle;               */
/*                                               */
/*             The fetch method, as in html_get  */
/*             in FetchHTML.c;                   */
/*                                               */
/*             Pointer to URL to fetch;          */
/*                                               */
/*             Pointer to a pointer to any extra */
/*             data to send for POST etc. (this  */
/*             allows such data to be stored in  */
/*             a flex block - you'd pass the     */
/*             pointer to the flex anchor);      */
/*                                               */
/*             Pointer to an int into which a    */
/*             status flag is placed (this may   */
/*             be NULL);                         */
/*                                               */
/*             The fetch mode:                   */
/*                                               */
/*             0: Get data only,                 */
/*             1: Get header only,               */
/*             2: Get both.                      */
/*************************************************/

_kernel_oserror * url_get_url(unsigned int flags, unsigned int handle, int method, char * url,
                              char ** extradata, unsigned int * status, int mode)
{
  char              agent[Limits_UserAgent];
  _kernel_oserror * e = NULL;
  int               s;

  agent[0] = '\0';

  #ifdef TRACE
    if (tl & (1u<<6)) Printf("url_get_url: Called with ID %d\n",handle);
  #endif

  /* If a pointer to the int in which status information can be written */
  /* is not NULL, set the current status to 0                           */

  if (status) *status = 0;

  /* Only proceed if we have a URL, and it's not an internal one */

  if (url && strncmp(url, Internal_URL, strlen(Internal_URL)))
  {
    #ifdef DUMP_HEADERS
      {
        FILE * file;

        file = fopen("<Wimp$ScrapDir>.Headers", "ab");

        if (!extradata || !*extradata || !**extradata) fprintf(file, "Fetch URL '%s'; sending standard header\r\n\r\n", url);
        else
        {
          fprintf(file, "Fetch URL '%s'; sending standard header plus:\r\n\r\n%s\r\n", url, *extradata);
          if ((*extradata)[strlen(*extradata) - 1] != '\n') fprintf(file, "\r\n");
        }

        fclose(file);
      }
    #endif

    /* We may need to work out the user agent string */

    if (flags & URL_GetURL_AgentGiven)
    {
      utils_build_user_agent_string(choices.clone, agent, sizeof(agent));
    }

    /* Now call the SWI - it can take a while to complete, */
    /* so turn the hourglass on.                           */

    _swix(Hourglass_Start, _IN(0), 50);

    e = _swix(URL_GetURL,
              _INR(0,6) | _OUT(0),

              flags,
              handle,
              method,
              url,
              *extradata,
              mode,
              agent,

              &s);

    _swix(Hourglass_Off, 0);

    /* If the GetURL call didn't return an error, write the new status */

    if (status && !e) *status = s;
  }

  #ifdef TRACE
    if (tl & (1u<<6))
    {
      if (!e) Printf("url_get_url: Successful\n");
      else Printf("url_get_url: Exitting with error\n");
    }
  #endif

  return e;
}

/*************************************************/
/* url_read_data()                               */
/*                                               */
/* Asks the URL module to copy some of the data  */
/* it has fetched over into a buffer.            */
/*                                               */
/* Parameters: Flags (must be 0 at present);     */
/*                                               */
/*             The session handle;               */
/*                                               */
/*             Pointer to buffer into which the  */
/*             data is transferred, or NULL to   */
/*             just get a Pending state;         */
/*                                               */
/*             The size of the buffer;           */
/*                                               */
/*             Pointer to an int, into which a   */
/*             status word is placed;            */
/*                                               */
/*             Pointer to int, into which the    */
/*             number of bytes read (and put in  */
/*             the bufrer) is placed;            */
/*                                               */
/*             Pointer to int, into which the    */
/*             number of bytes that are still to */
/*             be fetched s placed.              */
/*************************************************/

_kernel_oserror * url_read_data(unsigned int flags, unsigned int handle, void * buffer,
                                int size, int * status, int * read, int * pending)
{

  _kernel_oserror * e;
  int               s, r, p = 0;

  #ifdef TRACE
    if (tl & (1u<<6)) Printf("url_read_data: Called with ID %d\n",handle);
  #endif

  /* Ensure all returned data is set to a sensible default to start with */

  if (status)  * status  = 0;
  if (read)    * read    = 0;
  if (pending) * pending = 0;

  /* Call the URL module */

  e = _swix(URL_ReadData,
            _INR(0,3) | _OUT(0) | _OUTR(4,5),

            flags,
            handle,
            buffer,
            size,

            &s,
            &r,
            &p);

  #ifdef TRACE
    if (tl & (1u<<6)) Printf("url_read_data: Status %p, error %p returned\n",s,e);
  #endif

  /* In the absence of any errors, fill in the relevant returned data */

  if (!e)
  {
    if (status)  *status  = s;
    if (read)    *read    = r;
    if (pending) *pending = p;
  }

  #ifdef TRACE
    if (tl & (1u<<6))
    {
      if (!e) Printf("url_read_data: Successful\n");
      else Printf("url_read_data: Exitting with error\n");
    }
  #endif

  return e;
}

/*************************************************/
/* url_status()                                  */
/*                                               */
/* Returns the status of a fetch.                */
/*                                               */
/* Parameters: Flags (must be 0 at present);     */
/*                                               */
/*             The session handle;               */
/*                                               */
/*             Pointer to an int, into which a   */
/*             status word is placed;            */
/*                                               */
/*             Pointer to an int, into which the */
/*             server's response is placed;      */
/*                                               */
/*             Pointer to an int, into which the */
/*             number of bytes transferred so    */
/*             far is placed.                    */
/*************************************************/

_kernel_oserror * url_status(unsigned int flags, unsigned int handle,
                             int * status, int * response, int * bytes)
{
  _kernel_oserror * e;
  int               s, r, b;

  #ifdef TRACE
    if (tl & (1u<<6)) Printf("url_status: Called with ID %d\n",handle);
  #endif

  /* Set returned data to zero to begin with */

  if (status)   *status   = 0;
  if (response) *response = 0;
  if (bytes)    *bytes    = 0;

  e = _swix(URL_Status,
            _INR(0,1) | _OUT(0) | _OUTR(2,3),

            flags,
            handle,

            &s,
            &r,
            &b);

  /* In the absence of an error, fill in the returned data */

  if (!e)
  {
    if (status)   *status   = s;
    if (response) *response = r;
    if (bytes)    *bytes    = b;
  }

  #ifdef TRACE
    if (tl & (1u<<6))
    {
      if (!e) Printf("url_status: Successful\n");
      else Printf("url_status: Exitting with error\n");
    }
  #endif

  return e;
}

/*************************************************/
/* url_set_proxy()                               */
/*                                               */
/* Instructs the URL module to fetch through a   */
/* proxy (or not).                               */
/*                                               */
/* Parameters: Flags (must be 0 at present);     */
/*                                               */
/*             The session handle;               */
/*                                               */
/*             Pointer to the base URL of the    */
/*             proxy server, e.g. for a local    */
/*             proxy, "http://127.0.0.1/";       */
/*                                               */
/*             Pointer to a string holding the   */
/*             protocol to use, e.g. "http:" or  */
/*             "ftp:";                           */
/*                                               */
/*             1 to disable proxying, 0 to       */
/*             enable it with the above data.    */
/*************************************************/

_kernel_oserror * url_set_proxy(int flags, unsigned int session, char * baseurl,
                                char * protocol, int noproxy)
{
  return _swix(URL_SetProxy,
               _INR(0,4),

               flags,
               session,
               baseurl,
               protocol,
               noproxy);
}