drupal4.2의 trackback 수정 코드

ykskor의 이미지

drupal 4.2 의 tb 모듈 수정 파일입니다.

사용하기 위해서는 원본 tb모듈을 설치하고 인스톨 문서에 설명하고 있는테이블을 생성후 modules 디렉토리의 tb.module 파일을 아래의 코드로 교체하세요.

설정은 관리자의 모듈설정에서 익명의 사용자가 댓글을 사용할 수 있도록 합니다. 이유는 외부로부터 오는 trackback ping 데이타는 anonymous로 간주하기 때문입니다.

access trackback: anonymous 사용자도 사용할 수 있도록 합니다.
post trackback: trackback ping은 자기 게시물을 다른 곳에 ping하는 것이므로 인증된 사용자에게만 사용하도록 하면 됩니다.

현재 trackback ping을 보내기/받기 와 트랙백 데이타를 rss형태로 보는 기능이 됩니다. 자동 발견 기능을 위해서 rdf도 blog타입의 node에 숨겨져서 출력됩니다.(HTML 의 주석처리 형태). 현재 drupal에서는 이런 데이타의 자동발견 기능이 없습니다.

<?php
// $Id: tb.module,v 1.11.2.2 2003/08/10 13:48:50 ax Exp $

if ( !defined('HTTP_CRLF') ) define( 'HTTP_CRLF', chr(13) . chr(10));


function tb_system($field) {
   $system["description"] = t("Provide TrackBack capabilities.");
   return $system[$field];
}


function tb_perm() {
   return array("access trackback", "post trackback");
}


function tb_link($type, $node = 0, $main = "") {
   if (($type == "node") && $node->type == "blog" && (user_access("access trackback"))) {
      $links[] = l(t("TrackBack")."(".tb_getnumtrackbacks($node->nid).")", "tb/view/$node->nid",array("title" => t("View only comments by trackback ping for this node")));
   }
   if ( ($type == "node") && 
      $node->type == "blog" && 
      (blog_access("update", $node)) &&
      (user_access("post trackback"))) {
      $links[] = l(t("TrackBack Ping"), "tb/form/$node->nid", array("title" => t("Send a trackback ping for this node")));
   }
   if (($type == "node") && $node->type == "blog" && (user_access("access trackback"))) {
      $links[] = "<br />TrackBack URL: ".url("tb/$node->nid"). tb_discovery($node);
   }
   return $links ? $links : array();
}


function tb_help() {
   print _tb_help();
}


function _tb_help() {
   return t('<p>What is <a href="http://www.movabletype.org/trackback/">TrackBack</a>?  Basically, it is a way of recording who has linked to your posts and notifying others that you have linked to them (invented by the folks from <a href="http://www.moveabletype.org">Moveable Type</a>).</p>');
}


// 코멘트 등록시 코멘트 고유번호 갱신
function tb_comment($op, $edit) {
   if ($edit["cid"] > 0) {
      if($op == "insert") {
         db_query("UPDATE tb SET cid = ". $edit["cid"] ." WHERE (nid = ". $edit["nid"] .") AND (cid = 0)");
      }
   }
}


// 노드 삭제시 관련 데이타 삭제
function tb_nodeapi(&$node, $op, $arg = 0) {
   switch ($op) {
     case "delete":
        db_query("DELETE FROM tb WHERE nid = '$node->nid'");
        break;
  }
}


function tb_discovery($node) {
$result =
'<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" />
<rdf:Description
    rdf:about="'. url("node/view/$node->nid") .'"
    dc:title="'. strip_tags($node->title) .'"
    dc:identifier="'. url("node/view/$node->nid") .'"
    trackback:ping="'. url("tb/$node->nid") .'" />
</rdf:RDF>
-->';
return $result;
}


function tb_getnumtrackbacks($nid) {
   if ($nid > 0) {
      $result = db_query("SELECT COUNT(*) FROM tb WHERE nid = $nid");
      return db_result($result);
   }
   else {
      return 0;
   }
}


function _tb_node_exists($nid) {
   if ($nid > 0) {
      $result = db_query("SELECT nid FROM node WHERE nid = $nid");
      return (db_num_rows($result) > 0);
   }
   else {
      return 0;
   }
}


function tb_make_response($err_code = 0, $err_msg = '', $data = '') {
   Header('content-type: text/xml');
   /* $output  = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"; */
   $output  = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
   $output .= "<response>\n";
   $output .= "<error>$err_code</error>\n";
   if ($err_code > 0) {
      $output .= "<message>$err_msg</message>\n";
   }
   $output .= $data;
   $output .= "</response>";
   
   return $output;
}


function _tb_rss($nid) {
   global $languages;

   foreach ($languages as $key => $value) break;
   $lang = $key ? $key : "en";

   $node = node_load(array('nid' => $nid));

   $items  = "";
   $result = db_query("SELECT tb.*, c.subject, c.comment FROM tb, comments c WHERE (tb.cid = c.cid) AND (c.nid = $nid) ORDER BY c.timestamp DESC");
   while ($comment = db_fetch_object($result)) {
      $items .= format_rss_item($comment->subject, url("node/view/$nid") . "#".$comment->cid, $comment->comment);
   }

   $output  = "<rss version=\"0.92\">\n";
   $output .= format_rss_channel($node->title, url("node/view/$nid"), $node->teaser, $items,$lang);
   $output .= "</rss>";

   return $output;
}


function tb_rss($nid) {
   print tb_make_response(0, "", _tb_rss($nid));
}


function _tb_url_good($url) {
   return ereg('^http://', $url);
}


function tb_add($nid) {
   $url       = $_POST["url"];
   $title     = $_POST["title"];
   $excerpt   = $_POST["excerpt"];
   $blog_name = $_POST["blog_name"];

   if (module_exist("comment")) {
      if (_tb_node_exists($nid)) {
         if (($url != "") && (_tb_url_good($url))) {
            $edit["nid"] = $nid;
            $edit["pid"] = 0;
            $edit["subject"]  = ($title == "") ? $blog_name : $title;
            $edit["comment"]  = "<a href=\"$url\">". $edit["subject"] ."</a><br />";
            $edit["comment"] .= "Trackbacked by ".$blog_name."<br />";
            if ($excerpt != "") {
               $edit["comment"] .= $excerpt;
            }

            db_query("INSERT INTO tb (nid, cid) VALUES($nid, 0)");
            comment_post($edit);
            print tb_make_response();
         }
         else {
            print tb_make_response(1, t("Invalid URL."));
         }
      }
      else {
         print tb_make_response(1, t("Node doesn't exist."));
      }
   }
   else {
      print tb_make_response(1, t("Comments are disabled."));
   }
}


function tb_form($nid) {
   theme("header");
   if (user_access("post trackback")) {
      $output  = form_textfield(t("Trackback URL"), "tb_url", "", 40, 200, t("Enter a URL you wish to ping"));
      $output .= form_submit(t("Ping"));
      theme("box", t("TrackBack"), form($output, "post", url("tb/$nid")));
   }
   else {
      theme("box", t("Access denied"), message_access());
   }
   theme("footer");
}


// xml response parsing helper functions
function _tb_startElement($parser, $name, $attrs) {
   global $is_inerror;
   $is_inerror = ($name == "MESSAGE");
}


function _tb_endElement($parser, $name) {
   global $is_inerror;
   $is_inerror = 0;
}


function _tb_cdata($parser, $data) {
   global $is_inerror, $tb_error;
   $tb_error = ($is_inerror) ? $data : $tb_error;
}


// modified from http://www.dclp-faq.de/q/q-code-post.html
function _tb_post($url, $data) {
   $urlinfo = parse_url($url);

   $fp = fsockopen($urlinfo["host"], $urlinfo["port"] ? $urlinfo["port"] : 80);
   fputs($fp, "POST ". $urlinfo["path"] ." HTTP/1.1".HTTP_CRLF);
   fputs($fp, "Host: ". $urlinfo["host"] .HTTP_CRLF);
   fputs($fp, "Content-type: application/x-www-form-urlencoded".HTTP_CRLF);
   fputs($fp, "Content-length: ". strlen($data) .HTTP_CRLF);
   fputs($fp, "Connection: close".HTTP_CRLF.HTTP_CRLF);
   fputs($fp, "$data".HTTP_CRLF);

   // modified from http://www.phpclasses.org/browse.html/file/1222.html
   $isHeader = true;
   $blockSize = 0;
   $responseHeaders = "";
   $responseBody    = "";

   while (!feof($fp)) {
      if($isHeader){
         $line = fgets($fp, 1024); 
         $responseHeaders .= $line;
         if('' == trim($line)){
            $isHeader = false;
         }
      }
      else {
         if(!$blockSize){
            $line = fgets($fp, 1024);
            if($blockSizeHex = trim($line)){
               $blockSize = hexdec($blockSizeHex);
            }
         }
         else {
            $responseBody .= fread($fp,$blockSize);
            $blockSize = 0;
         }
      }
   }
   fclose($fp);

   return $responseBody;
}


function tb_ping($nid) {
   global $is_inerror, $tb_error;

   theme("header");

   if (user_access("post trackback")) 
   {
      $edit     = $_POST["edit"];
      $ping_url = $edit["tb_url"];

      $node     = node_load(array("nid" => $nid));

      $ping_arg = "url=" . urlencode(url("node/view/$nid"));
      if ($node->title != "") {
         $ping_arg .= "&title=" . urlencode(strip_tags($node->title));
      }
      $ping_arg .= "&excerpt=" . urlencode(strip_tags($node->teaser)); 
      $sname = variable_get("site_name", "drupal");
      if ($sname != "") {
         $ping_arg .= "&blog_name=" . urlencode(strip_tags($sname));
      }
      
      // pings are HTTP posted now
      $content = _tb_post($ping_url, $ping_arg);


      if ($content == "") {
         theme("box", t("TrackBack ping"), t("Could not HTTP get.(%pingurl)", array("%pingurl" => $pingurl)));
      }
      else {
         $xmlp = xml_parser_create("ISO-8859-1");
         xml_set_element_handler($xmlp, "_tb_startElement", "_tb_endElement");
         xml_set_character_data_handler($xmlp, "_tb_cdata");
         $is_inerror = 0;
         $tb_error = "";

         if(!xml_parse($xmlp, $content, 1)) {
            theme("box", t("TrackBack ping"), t('Could not parse response (%xmlerror).', array("%xmlerror" => xml_error_string(xml_get_error_code($xmlp)))));
            watchdog("error", $content);
         }
         else {
            $tb_msg = ($tb_error != '') ? $tb_error : "Site was succesfully pinged.";
            theme("box", t("TrackBack ping"),t($tb_msg));
         }
         xml_parser_free($xmlp);
      }
   }
   else {
      theme("box", t("Access denied"), message_access());
   }

   theme("footer");
}


function tb_view($nid) {
   tb_rss($nid);
}


// page hook
function tb_page() {
   $op = $_POST["op"];
   if (empty($op)) {
      $op  = arg(1);
      $nid = arg(2);
      if(!$nid) {
         $nid = $op;
         $op  = "";
      }
   }
   else {
      $nid = arg(1);
   }

   if (user_access("access trackback")) {
      if ($nid > 0) {
         switch($op) {
            case "form": // tb/form/nid
               tb_form($nid); 
               break;  

            case "view": // tb/view/nid
               tb_view($nid);
               break;

            case "rss": // tb/rss/nid
               tb_rss($nid);
               break;

            case t("Ping"): // tb/nid
               tb_ping($nid);
               break;

            default:   // tb/nid (receive an incoming ping)
               tb_add($nid);
               break;
         }
      }
      else {
         theme("header");
         theme("box", t("TrackBack"), _tb_help());
         theme("footer");
      }
   }
   else {
      message_access();
   }
}

?>
Forums: 
ykskor의 이미지

tb.moudle내의 함수 수정

..
..
// modified from http://www.dclp-faq.de/q/q-code-post.html
function _tb_post($url, $data) {
   $urlinfo = parse_url($url);
   $path =  (isset($urlinfo["query"])) ? $urlinfo["path"] ."?" . $urlinfo["query"] : $urlinfo["path"];

   $fp = fsockopen($urlinfo["host"], $urlinfo["port"] ? $urlinfo["port"] : 80);
   fputs($fp, "POST ". $path ." HTTP/1.1".HTTP_CRLF);
   fputs($fp, "Host: ". $urlinfo["host"] .HTTP_CRLF);
   fputs($fp, "Content-type: application/x-www-form-urlencoded".HTTP_CRLF);
   fputs($fp, "Content-length: ". strlen($data) .HTTP_CRLF);
   fputs($fp, "Connection: close".HTTP_CRLF.HTTP_CRLF);
   fputs($fp, "$data".HTTP_CRLF);
   ..
   ..
cdpark의 이미지

여기에 올리는 것보다는 drupal 사이트에 올리는 게 어떨까요? main tree에 포함되어야요.

권순선의 이미지

예... 어느 정도 동작이 잘 된다고 판단되면 www.drupal.org 의 적절한 곳 (메일링 리스트 혹은 포럼) 에 패치를 올려 주시면 곧 적용이 될 것입니다. 아무튼 수고 많이 하시네요... :o

Seyong의 이미지

서버의 포트가 80이 아닌 경우에 위의 모듈 소스로 trackback ping을 받지 못합니다. 왜그런가 하고 조사해 보니 index.php 에서 include 를 하지 못하더군요

이유를 알 수 없어 삽질만 하다가 ping 나가는걸 보니 포트가 안적혀 있더라구요
그래서 혹시나 해서 붙여보았더니 ping이 잘 됩니다.

fputs($fp, "Host: ". $urlinfo["host"] .HTTP_CRLF);

이 줄을

fputs($fp, "Host: ". $urlinfo["host"].$urlinfo["port"] .HTTP_CRLF);

이렇게 변경했습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.