<commit_before>/* Swfdec
 * Copyright (C) 2007 <NAME> <<EMAIL>>
 *               2007 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
 * Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>

#include "swfdec_policy_file.h"
#include "swfdec_resource.h"
#include "swfdec_as_strings.h"
#include "swfdec_debug.h"
#include "swfdec_loader_internal.h"
#include "swfdec_player_internal.h"
#include "swfdec_xml.h"
#include "swfdec_xml_node.h"

typedef struct _SwfdecPolicyFileRequest SwfdecPolicyFileRequest;
struct _SwfdecPolicyFileRequest {
  SwfdecURL *	  	url;		/* URL we are supposed to check */
  SwfdecPolicyFunc	func;		/* function to call when we know if access is (not) allowed */
  gpointer		data;		/* data to pass to func */
};

static void
swfdec_policy_file_request_free (SwfdecPolicyFileRequest *request)
{
  swfdec_url_free (request->url);
  g_slice_free (SwfdecPolicyFileRequest, request);
}

/*** PARSING THE FILE ***/

static void
swfdec_policy_file_parse (SwfdecPolicyFile *file, const char *text)
{
  SwfdecXml *xml;
  gint32 i, j;

  g_return_if_fail (SWFDEC_IS_POLICY_FILE (file));
  g_return_if_fail (text != NULL);

  xml = swfdec_xml_new_no_properties (SWFDEC_AS_CONTEXT (file->player), text, TRUE);

  if (xml == NULL) {
    SWFDEC_ERROR ("failed to create an XML object for crossdomain policy");
    return;
  }

  if (SWFDEC_XML_NODE (xml)->type != SWFDEC_XML_NODE_ELEMENT) {
    SWFDEC_LOG ("empty crossdomain policy file");
    return;
  }

  for (i = 0; i < swfdec_xml_node_num_children (SWFDEC_XML_NODE (xml)); i++) {
    SwfdecXmlNode *node_cdp =
      swfdec_xml_node_get_child (SWFDEC_XML_NODE (xml), i);

    if (node_cdp->type != SWFDEC_XML_NODE_ELEMENT)
      continue;

    if (g_ascii_strcasecmp (node_cdp->name, "cross-domain-policy") != 0)
      continue;

    for (j = 0; j < swfdec_xml_node_num_children (node_cdp); j++) {
      SwfdecXmlNode *node_aaf = swfdec_xml_node_get_child (node_cdp, j);
      const char *value;
      GPatternSpec *pattern;
      char *value_lower;

      if (node_aaf->type != SWFDEC_XML_NODE_ELEMENT)
	continue;

      if (g_ascii_strcasecmp (node_aaf->name, "allow-access-from") != 0)
	continue;

      // FIXME: secure attribute?

      value = swfdec_xml_node_get_attribute (node_aaf, SWFDEC_AS_STR_domain);
      if (value == NULL)
	continue;

      if (strchr (value, '?') != NULL) {
	SWFDEC_WARNING ("'?' in allowed domain attribute for %s", value);
	continue;
      }

      value_lower = g_ascii_strdown (value, -1);
      pattern = g_pattern_spec_new (value_lower);
      g_free (value_lower);

      file->allowed_hosts = g_slist_prepend (file->allowed_hosts, pattern);
    }
  }
}

/*** SWFDEC_STREAM_TARGET ***/

static SwfdecPlayer *
swfdec_policy_file_target_get_player (SwfdecStreamTarget *target)
{
  return SWFDEC_POLICY_FILE (target)->player;
}

static void
swfdec_policy_file_finished_loading (SwfdecPolicyFile *file, const char *text)
{
  SwfdecPlayerPrivate *priv;
  SwfdecPolicyFile *next;
  GList *link;

  swfdec_stream_set_target (file->stream, NULL);
  file->stream = NULL;

  if (text)
    swfdec_policy_file_parse (file, text);

  priv = file->player->priv;
  link = g_list_find (priv->loading_policy_files, file);
  next = link->next ? link->next->data : NULL;
  priv->loading_policy_files = g_list_delete_link (priv->loading_policy_files, link);
  priv->policy_files = g_slist_prepend (priv->policy_files, file);
  if (next) {
    next->requests = g_slist_concat (next->requests, file->requests);
  } else {
    GSList *walk;

    for (walk = file->requests; walk; walk = walk->next) {
      SwfdecPolicyFileRequest *request = walk->data;
      gboolean allow = swfdec_player_allow_now (file->player, request->url);
      request->func (file->player, allow, request->data);
      swfdec_policy_file_request_free (request);
    }
    g_slist_free (file->requests);
  }
  file->requests = NULL;
}

static void
swfdec_policy_file_target_error (SwfdecStreamTarget *target,
    SwfdecStream *stream)
{
  SwfdecPolicyFile *file = SWFDEC_POLICY_FILE (target);

  swfdec_policy_file_finished_loading (file, NULL);
}

static void
swfdec_policy_file_target_close (SwfdecStreamTarget *target,
    SwfdecStream *stream)
{
  SwfdecPolicyFile *file = SWFDEC_POLICY_FILE (target);
  char *text;

  swfdec_stream_set_target (stream, NULL);
  file->stream = NULL;
  if (SWFDEC_IS_LOADER (stream)) {
    text = swfdec_loader_get_text (SWFDEC_LOADER (stream), 8);
  } else {
    SWFDEC_FIXME ("rewrite swfdec_loader_get_text() to swfdec_buffer_queue_get_text()");
    text = NULL;
  }

  if (text == NULL) {
    SWFDEC_ERROR ("couldn't get text from crossdomain policy file %s", <commit_msg>swfdec_xml_new_no_properties requires a sandbox, so give it one<commit_after>/* Swfdec
 * Copyright (C) 2007 <NAME> <<EMAIL>>
 *               2007 <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
 * Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>

#include "swfdec_policy_file.h"
#include "swfdec_resource.h"
#include "swfdec_as_strings.h"
#include "swfdec_debug.h"
#include "swfdec_loader_internal.h"
#include "swfdec_player_internal.h"
#include "swfdec_xml.h"
#include "swfdec_xml_node.h"

typedef struct _SwfdecPolicyFileRequest SwfdecPolicyFileRequest;
struct _SwfdecPolicyFileRequest {
  SwfdecURL *	  	url;		/* URL we are supposed to check */
  SwfdecPolicyFunc	func;		/* function to call when we know if access is (not) allowed */
  gpointer		data;		/* data to pass to func */
};

static void
swfdec_policy_file_request_free (SwfdecPolicyFileRequest *request)
{
  swfdec_url_free (request->url);
  g_slice_free (SwfdecPolicyFileRequest, request);
}

/*** PARSING THE FILE ***/

static void
swfdec_policy_file_parse (SwfdecPolicyFile *file, const char *text)
{
  SwfdecXml *xml;
  gint32 i, j;

  g_return_if_fail (SWFDEC_IS_POLICY_FILE (file));
  g_return_if_fail (text != NULL);

  /* FIXME: the sandboxes are a HACK */
  swfdec_sandbox_use (SWFDEC_MOVIE (file->player->priv->roots->data)->resource->sandbox);
  xml = swfdec_xml_new_no_properties (SWFDEC_AS_CONTEXT (file->player), text, TRUE);
  swfdec_sandbox_unuse (SWFDEC_MOVIE (file->player->priv->roots->data)->resource->sandbox);

  if (xml == NULL) {
    SWFDEC_ERROR ("failed to create an XML object for crossdomain policy");
    return;
  }

  if (SWFDEC_XML_NODE (xml)->type != SWFDEC_XML_NODE_ELEMENT) {
    SWFDEC_LOG ("empty crossdomain policy file");
    return;
  }

  for (i = 0; i < swfdec_xml_node_num_children (SWFDEC_XML_NODE (xml)); i++) {
    SwfdecXmlNode *node_cdp =
      swfdec_xml_node_get_child (SWFDEC_XML_NODE (xml), i);

    if (node_cdp->type != SWFDEC_XML_NODE_ELEMENT)
      continue;

    if (g_ascii_strcasecmp (node_cdp->name, "cross-domain-policy") != 0)
      continue;

    for (j = 0; j < swfdec_xml_node_num_children (node_cdp); j++) {
      SwfdecXmlNode *node_aaf = swfdec_xml_node_get_child (node_cdp, j);
      const char *value;
      GPatternSpec *pattern;
      char *value_lower;

      if (node_aaf->type != SWFDEC_XML_NODE_ELEMENT)
	continue;

      if (g_ascii_strcasecmp (node_aaf->name, "allow-access-from") != 0)
	continue;

      // FIXME: secure attribute?

      value = swfdec_xml_node_get_attribute (node_aaf, SWFDEC_AS_STR_domain);
      if (value == NULL)
	continue;

      if (strchr (value, '?') != NULL) {
	SWFDEC_WARNING ("'?' in allowed domain attribute for %s", value);
	continue;
      }

      value_lower = g_ascii_strdown (value, -1);
      pattern = g_pattern_spec_new (value_lower);
      g_free (value_lower);

      file->allowed_hosts = g_slist_prepend (file->allowed_hosts, pattern);
    }
  }
}

/*** SWFDEC_STREAM_TARGET ***/

static SwfdecPlayer *
swfdec_policy_file_target_get_player (SwfdecStreamTarget *target)
{
  return SWFDEC_POLICY_FILE (target)->player;
}

static void
swfdec_policy_file_finished_loading (SwfdecPolicyFile *file, const char *text)
{
  SwfdecPlayerPrivate *priv;
  SwfdecPolicyFile *next;
  GList *link;

  swfdec_stream_set_target (file->stream, NULL);
  file->stream = NULL;

  if (text)
    swfdec_policy_file_parse (file, text);

  priv = file->player->priv;
  link = g_list_find (priv->loading_policy_files, file);
  next = link->next ? link->next->data : NULL;
  priv->loading_policy_files = g_list_delete_link (priv->loading_policy_files, link);
  priv->policy_files = g_slist_prepend (priv->policy_files, file);
  if (next) {
    next->requests = g_slist_concat (next->requests, file->requests);
  } else {
    GSList *walk;

    for (walk = file->requests; walk; walk = walk->next) {
      SwfdecPolicyFileRequest *request = walk->data;
      gboolean allow = swfdec_player_allow_now (file->player, request->url);
      request->func (file->player, allow, request->data);
      swfdec_policy_file_request_free (request);
    }
    g_slist_free (file->requests);
  }
  file->requests = NULL;
}

static void
swfdec_policy_file_target_error (SwfdecStreamTarget *target,
    SwfdecStream *stream)
{
  SwfdecPolicyFile *file = SWFDEC_POLICY_FILE (target);

  swfdec_policy_file_finished_loading (file, NULL);
}

static void
swfdec_policy_file_target_close (SwfdecStreamTarget *target,
    SwfdecStream *stream)
{
  SwfdecPolicyFile *file = SWFDEC_POLICY_FILE (target);
  char *text;

  if (SWFDEC_IS_LOADER (stream)) {
    text = swfdec_loader_get_text (SWFDEC_LOADER (stream), 8);
  } else {
    SWFDEC_FIXME ("rewrite swfdec_loader_get_text() to swfdec_buffer_queue_get_text()");
    text = NULL;
  }

  if (text == NULL) {
    SWFDEC_ERROR ("couldn't get text from crossdomain policy file %s", 
{'fraction_non_alphanumeric': 0.10862851952770208, 'fraction_numerical': 0.005267938237965486, 'mean_word_length': 4.206146572104019, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 29}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '213900', 'n_tokens_mistral': 3957, 'n_tokens_neox': 3841, 'n_words': 972}