0

我在 Drupal 中有一个 Web 应用程序,它基本上充当其他地方的多页 HTML 表单的代理。我可以使用 cURL 检索页面并使用 DOMDocument 对其进行解析,然后将内容嵌入到<form>Drupal 表单中:

<?php
function proxy_get_dom($url, $method = 'get', $arguments = array()) {
  // Keep a static cURL resource for speed.
  static $web = NULL;
  if (!is_resource($web)) {
    $web = curl_init();
    // Don't include any HTTP headers in the output.
    curl_setopt($web, CURLOPT_HEADER, FALSE);
    // Return the result as a string instead of echoing directly.
    curl_setopt($web, CURLOPT_RETURNTRANSFER, TRUE);
  }

  // Add any GET arguments directly to the URL.
  if ($method == 'get' && !empty($arguments)) {
    $url .= '?' . http_build_arguments($arguments, 'n', '&');
  }

  curl_setopt($web, CURLOPT_URL, $url);

  // Include POST data.
  if ($method == 'post' && !empty($arguments)) {
    curl_setopt($web, CURLOPT_POST, TRUE);
    curl_setopt($web, CURLOPT_POSTFIELDS, http_build_query($arguments));
  }
  else {
    curl_setopt($web, CURLOPT_POST, FALSE);
  }

  $use_errors = libxml_use_internal_errors(TRUE);
  try {
    $dom = new DOMDocument();
    $dom->loadHTML(curl_exec($web));
  }
  catch (Exception $e) {
    // Error handling...
    return NULL;
  }

  if (!isset($dom)) {
    // Error handling...
    return NULL;
  }

  libxml_use_internal_errors($use_errors);

  return $dom;
}

function FORM_ID($form, &$form_state) {
  // Set the initial URL if it hasn't already been set.
  if (!isset($form_state['remote_url'])) {
    $form_state['remote_url'] = 'http://www.example.com/form.faces';
  }

  // Get the DOMDocument
  $dom = proxy_get_dom($form_state['remote_url'], 'post', $_POST);
  if (!isset($dom)) {
    return $form;
  }

  // Pull out the <form> and insert it into $form['embedded'].
  $nlist = $dom->getElementsByTagName('form');
  // assert that $nlist->length == 1

  $form['embedded']['#markup'] = '';
  foreach ($nlist->item(0)->childNodes as $childnode) {
    // It would be better to use $dom->saveHTML but it does not accept the
    // $node parameter until php 5.3.6, which we are not guaranteed to be
    // using.
    $form['embedded']['#markup'] .= $dom->saveXML($childnode);
  }

  // Apply some of the attributes from the <form> element onto our <form>
  // element.
  if (isset($element->attributes)) {
    foreach ($nlist->item(0)->attributes as $attr) {
      if ($attr->nodeName == 'action') {
        $form_state['remote_action'] = $attr->nodeValue;
      }
      elseif ($attr->nodeName == 'class') {
        $form['#attributes']['class'] = explode(' ', $attr->nodeValue);
      }
      elseif ($attr->nodeName != 'method') {
        $form['#attributes'][$attr->nodeName] = $attr->nodeValue;
      }
    }
  }

  return $form;
}

function FORM_ID_submit($form, &$form_state) {
  // Use the remote_action as the remote_url, if set.
  if (isset($form_state['remote_action'])) {
    $form_state['remote_url'] = $form_state['remote_action'];
  }
  // Rebuilt the form.
  $form_state['rebuild'] = TRUE;
}
?>

但是,嵌入的表单不会超过第一步。问题似乎是代理背后的页面正在设置一个会话 cookie,我在上面的代码中忽略了它。CURLOPT_COOKIEFILE我可以用and存储 cookie CURLOPT_COOKIEJAR,但我不确定文件应该在哪里。一方面,对于每个用户来说,它绝对应该是一个不同的位置,而且它绝对应该是一个可公开访问的位置。

我的问题是:如何在 Drupal 中存储和发送来自 cURL 每个用户的 cookie?

4

1 回答 1

0

假设您正在使用会话,则使用用户的会话 ID 来命名 cookie 文件。例如

curl_setopt(CURLOPT_COOKIEFILE, 'cookies.txt');

会给每个人相同的 cookie 文件,他们最终会共享相同的 cookie。但是做

curl_setopt(CURLOPT_COOKIEFILE, 'cookie-' . session_id() . '.txt');

将为每个用户生成一个唯一的会话文件。您将不得不手动删除该文件,否则您将得到一个巨大的 cookie 文件管理器存储库。如果您正在更改会话 ID(例如session_regenerate_id(),您将“丢失”cookie 文件,因为会话 ID 将不再相同。

于 2013-10-22T17:54:58.463 回答