file_find_check(const char *filename)	/* I - File or URL */
{
  int		i;			/* Looping var */
  int		retry;			/* Current retry */
  char		scheme[HTTP_MAX_URI],	/* Method/scheme */
		username[HTTP_MAX_URI],	/* Username:password */
		hostname[HTTP_MAX_URI],	/* Hostname */
		resource[HTTP_MAX_URI];	/* Resource */
  int		port;			/* Port number */
  const char	*connscheme;		/* Scheme for connection */
  const char	*connhost;		/* Host to connect to */
  int		connport;		/* Port to connect to */
  char		connpath[HTTP_MAX_URI],	/* Path for GET */
		connauth[HTTP_MAX_VALUE];/* Auth string */
  http_status_t	status;			/* Status of request... */
  FILE		*fp;			/* Web file */
  ssize_t	bytes,			/* Bytes read */
		count;			/* Number of bytes so far */
  off_t		total;			/* Total bytes in file */
  char		tempname[HTTP_MAX_URI];	/* Temporary filename */


  DEBUG_printf(("file_find_check(filename=\"%s\")\n", filename));

  if (strncmp(filename, "http:", 5) == 0 || strncmp(filename, "//", 2) == 0)
    strlcpy(scheme, "http", sizeof(scheme));
  else if (strncmp(filename, "https:", 6) == 0)
    strlcpy(scheme, "https", sizeof(scheme));
  else if (strncmp(filename, "data:", 5) == 0)
    strlcpy(scheme, "data", sizeof(scheme));
  else
    strlcpy(scheme, "file", sizeof(scheme));

  if (strcmp(scheme, "file") == 0)
  {
   /*
    * Return immediately if we aren't allowing access to local files...
    */

    if (no_local)
      return (NULL);

   /*
    * If the filename exists, return the filename...
    */

    if (!access(filename, 0))
    {
      DEBUG_printf(("file_find_check: Returning \"%s\"!\n", filename));
      return (filename);
    }
  }
  else if (!strcmp(scheme, "data"))
  {
   /*
    * Data URI; look it up in the web cache, then save to a temporary file...
    */

    const char	*data;			/* Pointer to data */
    int		len;			/* Number of bytes */
    char	buffer[8192];		/* Data buffer */

    for (i = 0; i < (int)web_files; i ++)
    {
      if (web_cache[i].url && strcmp(web_cache[i].url, filename) == 0)
      {
        DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", web_cache[i].name, filename));
        return (web_cache[i].name);
      }
    }

    if ((data = strstr(filename, ";base64,")) != NULL)
    {
      len = sizeof(buffer);
      httpDecode64_2(buffer, &len, data + 8);

      if ((fp = file_temp(tempname, sizeof(tempname))) == NULL)
      {
	progress_hide();
	progress_error(HD_ERROR_WRITE_ERROR, "Unable to create temporary file \"%s\": %s", tempname, strerror(errno));
	return (NULL);
      }

      fwrite(buffer, 1, (size_t)len, fp);
      fclose(fp);

      progress_hide();

      web_cache[web_files - 1].url = strdup(filename);

      DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", tempname, filename));

      return (web_cache[web_files - 1].name);
    }
  }
  else
  {
   /*
    * Remote file; look it up in the web cache, and then try getting it
    * from the remote system...
    */

    for (i = 0; i < (int)web_files; i ++)
    {
      if (web_cache[i].url && strcmp(web_cache[i].url, filename) == 0)
      {
        DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", web_cache[i].name, filename));
        return (web_cache[i].name);
      }
    }

    httpSeparateURI(HTTP_URI_CODING_ALL, filename, scheme, sizeof(scheme),
                    username, sizeof(username), hostname, sizeof(hostname),
		    &port, resource, sizeof(resource));

    for (status = HTTP_STATUS_ERROR, retry = 0; status != HTTP_STATUS_OK && retry < 5; retry ++)
    {
      if (proxy_port)
      {
        // Send request to proxy host...
        connscheme = proxy_scheme;
        connhost   = proxy_host;
        connport   = proxy_port;
        httpAssembleURI(HTTP_URI_CODING_ALL, connpath, sizeof(connpath), scheme, NULL, hostname, port, resource);
      }
      else
      {
        // Send request to host directly...
        connscheme = scheme;
        connhost   = hostname;
        connport   = port;
        strlcpy(connpath, resource, sizeof(connpath));
      }

      if (connport != httpAddrPort(httpGetAddress(http)) ||
#ifdef HAVE_SSL
	  (!strcmp(connscheme, "https") && !httpIsEncrypted(http)) ||
          (!strcmp(connscheme, "http") && httpIsEncrypted(http)) ||
#endif // HAVE_SSL
          strcasecmp(httpGetHostname(http, tempname, sizeof(tempname)), hostname))
      {
        httpClose(http);
        http = NULL;
      }

      if (http == NULL)
      {
        progress_show("Connecting to %s...", connhost);

        http_encryption_t encryption = !strcmp(connscheme, "http") ? HTTP_ENCRYPTION_IF_REQUESTED : HTTP_ENCRYPTION_ALWAYS;

        if ((http = httpConnect2(connhost, connport, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL)
	{
          progress_hide();
          progress_error(HD_ERROR_NETWORK_ERROR, "Unable to connect to %s:%d", connhost, connport);
          return (NULL);
        }
      }

      progress_show("Getting %s...", connpath);

      httpClearFields(http);
      httpSetField(http, HTTP_FIELD_HOST, hostname);
      httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
      httpSetField(http, HTTP_FIELD_REFERER, referer_url);

      if (username[0])
      {
        strlcpy(connauth, "Basic ", sizeof(connauth));
        httpEncode64_2(connauth + 6, sizeof(connauth) - 6, username, strlen(username));
        httpSetField(http, HTTP_FIELD_AUTHORIZATION, connauth);
      }

      if (cookies[0])
        httpSetCookie(http, cookies);

      if (!httpGet(http, connpath))
      {
	while ((status = httpUpdate(http)) == HTTP_CONTINUE);
      }
      else
	status = HTTP_ERROR;

      if (status >= HTTP_STATUS_MULTIPLE_CHOICES && status < HTTP_STATUS_BAD_REQUEST)
      {
        // Redirect status code, grab the new location...
        const char *newurl = httpGetField(http, HTTP_FIELD_LOCATION);
					// New URL
        char	newresource[256];	// New resource

        progress_show("Redirecting to %s...", newurl);
	httpSeparateURI(HTTP_URI_CODING_ALL, newurl, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, newresource, sizeof(newresource));

        // Don't use new resource path if it is empty...
        if (strchr(newurl + strlen(scheme) + 3, '/'))
          strlcpy(resource, newresource, sizeof(resource));

        // ... then flush any text in the response...
	httpFlush(http);
      }
    }

    if (status != HTTP_OK)
    {
      progress_hide();
      progress_error((HDerror)status, "%s (%s)", httpStatus(status), filename);
      httpFlush(http);
      return (NULL);
    }

    if ((fp = file_temp(tempname, sizeof(tempname))) == NULL)
    {
      progress_hide();
      progress_error(HD_ERROR_WRITE_ERROR,
                     "Unable to create temporary file \"%s\": %s", tempname,
                     strerror(errno));
      httpFlush(http);
      return (NULL);
    }

    if ((total = httpGetLength2(http)) == 0)
      total = 8192;

    count = 0;
    while ((bytes = httpRead2(http, resource, sizeof(resource))) > 0)
    {
      count += bytes;
      progress_update((100 * count / total) % 101);
      fwrite(resource, 1, (size_t)bytes, fp);
    }

    progress_hide();

    fclose(fp);

    web_cache[web_files - 1].url = strdup(filename);

    DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", tempname, filename));

    return (web_cache[web_files - 1].name);
  }

  return (NULL);
}
file_find_check(const char *filename)	 
{
  int		i;			 
  int		retry;			 
  char		scheme[HTTP_MAX_URI],	 
		username[HTTP_MAX_URI],	 
		hostname[HTTP_MAX_URI],	 
		resource[HTTP_MAX_URI];	 
  int		port;			 
  const char	*connscheme;		 
  const char	*connhost;		 
  int		connport;		 
  char		connpath[HTTP_MAX_URI],	 
		connauth[HTTP_MAX_VALUE]; 
  http_status_t	status;			 
  FILE		*fp;			 
  ssize_t	bytes,			 
		count;			 
  off_t		total;			 
  char		tempname[HTTP_MAX_URI];	 


  DEBUG_printf(("file_find_check(filename=\"%s\")\n", filename));

  if (strncmp(filename, "http:", 5) == 0 || strncmp(filename, "//", 2) == 0)
    strlcpy(scheme, "http", sizeof(scheme));
  else if (strncmp(filename, "https:", 6) == 0)
    strlcpy(scheme, "https", sizeof(scheme));
  else if (strncmp(filename, "data:", 5) == 0)
    strlcpy(scheme, "data", sizeof(scheme));
  else
    strlcpy(scheme, "file", sizeof(scheme));

  if (strcmp(scheme, "file") == 0)
  {
    

    if (no_local)
      return (NULL);

    

    if (!access(filename, 0))
    {
      DEBUG_printf(("file_find_check: Returning \"%s\"!\n", filename));
      return (filename);
    }
  }
  else if (!strcmp(scheme, "data"))
  {
    

    const char	*data;			 
    int		len;			 
    char	buffer[8192];		 

    for (i = 0; i < (int)web_files; i ++)
    {
      if (web_cache[i].url && strcmp(web_cache[i].url, filename) == 0)
      {
        DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", web_cache[i].name, filename));
        return (web_cache[i].name);
      }
    }

    if ((data = strstr(filename, ";base64,")) != NULL)
    {
      len = sizeof(buffer);
      httpDecode64_2(buffer, &len, data + 8);

      if ((fp = file_temp(tempname, sizeof(tempname))) == NULL)
      {
	progress_hide();
	progress_error(HD_ERROR_WRITE_ERROR, "Unable to create temporary file \"%s\": %s", tempname, strerror(errno));
	return (NULL);
      }

      fwrite(buffer, 1, (size_t)len, fp);
      fclose(fp);

      progress_hide();

      web_cache[web_files - 1].url = strdup(filename);

      DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", tempname, filename));

      return (web_cache[web_files - 1].name);
    }
  }
  else
  {
    

    for (i = 0; i < (int)web_files; i ++)
    {
      if (web_cache[i].url && strcmp(web_cache[i].url, filename) == 0)
      {
        DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", web_cache[i].name, filename));
        return (web_cache[i].name);
      }
    }

    httpSeparateURI(HTTP_URI_CODING_ALL, filename, scheme, sizeof(scheme),
                    username, sizeof(username), hostname, sizeof(hostname),
		    &port, resource, sizeof(resource));

    for (status = HTTP_STATUS_ERROR, retry = 0; status != HTTP_STATUS_OK && retry < 5; retry ++)
    {
      if (proxy_port)
      {
         
        connscheme = proxy_scheme;
        connhost   = proxy_host;
        connport   = proxy_port;
        httpAssembleURI(HTTP_URI_CODING_ALL, connpath, sizeof(connpath), scheme, NULL, hostname, port, resource);
      }
      else
      {
         
        connscheme = scheme;
        connhost   = hostname;
        connport   = port;
        strlcpy(connpath, resource, sizeof(connpath));
      }

      if (connport != httpAddrPort(httpGetAddress(http)) ||
#ifdef HAVE_SSL
	  (!strcmp(connscheme, "https") && !httpIsEncrypted(http)) ||
          (!strcmp(connscheme, "http") && httpIsEncrypted(http)) ||
#endif  
          strcasecmp(httpGetHostname(http, tempname, sizeof(tempname)), hostname))
      {
        httpClose(http);
        http = NULL;
      }

      if (http == NULL)
      {
        progress_show("Connecting to %s...", connhost);

        http_encryption_t encryption = !strcmp(connscheme, "http") ? HTTP_ENCRYPTION_IF_REQUESTED : HTTP_ENCRYPTION_ALWAYS;

        if ((http = httpConnect2(connhost, connport, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL)
	{
          progress_hide();
          progress_error(HD_ERROR_NETWORK_ERROR, "Unable to connect to %s:%d", connhost, connport);
          return (NULL);
        }
      }

      progress_show("Getting %s...", connpath);

      httpClearFields(http);
      httpSetField(http, HTTP_FIELD_HOST, hostname);
      httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
      httpSetField(http, HTTP_FIELD_REFERER, referer_url);

      if (username[0])
      {
        strlcpy(connauth, "Basic ", sizeof(connauth));
        httpEncode64_2(connauth + 6, sizeof(connauth) - 6, username, strlen(username));
        httpSetField(http, HTTP_FIELD_AUTHORIZATION, connauth);
      }

      if (cookies[0])
        httpSetCookie(http, cookies);

      if (!httpGet(http, connpath))
      {
	while ((status = httpUpdate(http)) == HTTP_CONTINUE);
      }
      else
	status = HTTP_ERROR;

      if (status >= HTTP_STATUS_MULTIPLE_CHOICES && status < HTTP_STATUS_BAD_REQUEST)
      {
         
        const char *newurl = httpGetField(http, HTTP_FIELD_LOCATION);
					 
        char	newresource[256];	 

        progress_show("Redirecting to %s...", newurl);
	httpSeparateURI(HTTP_URI_CODING_ALL, newurl, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, newresource, sizeof(newresource));

         
        if (strchr(newurl + strlen(scheme) + 3, '/'))
          strlcpy(resource, newresource, sizeof(resource));

         
	httpFlush(http);
      }
    }

    if (status != HTTP_OK)
    {
      progress_hide();
      progress_error((HDerror)status, "%s (%s)", httpStatus(status), filename);
      httpFlush(http);
      return (NULL);
    }

    if ((fp = file_temp(tempname, sizeof(tempname))) == NULL)
    {
      progress_hide();
      progress_error(HD_ERROR_WRITE_ERROR,
                     "Unable to create temporary file \"%s\": %s", tempname,
                     strerror(errno));
      httpFlush(http);
      return (NULL);
    }

    if ((total = httpGetLength2(http)) == 0)
      total = 8192;

    count = 0;
    while ((bytes = httpRead2(http, resource, sizeof(resource))) > 0)
    {
      count += bytes;
      progress_update((100 * count / total) % 101);
      fwrite(resource, 1, (size_t)bytes, fp);
    }

    progress_hide();

    fclose(fp);

    web_cache[web_files - 1].url = strdup(filename);

    DEBUG_printf(("file_find_check: Returning \"%s\" for \"%s\".\n", tempname, filename));

    return (web_cache[web_files - 1].name);
  }

  return (NULL);
}