手動広告貼り付けオートメーション

手動を自動にするって矛盾しないか?

「XHTML 1.1のtargetあり」にすることとする。 詳しくは前章を参照せよ。 他の方法も大きくは変わらないだろう。

ココにあるプログラムはかなり怪しいです。 自己責任で使ってください。 らっしーは一切の保証が出来ません。

広告を貼り付けると言うこと

ドキュメント宣言を書き換えることと、 広告をbodyの開始タグの直後に挿入すること。 この二つだけである。

ドキュメント宣言

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"[
  <!ATTLIST a
      target  CDATA  #IMPLIED
  >
]>

通常広告(ブロック)

<div class="ad_block">
  <a href="http://ad.xrea.com/ad_click.fcg?site=user.s*.xrea.com"
     target="_blank" class="ad_anchor">
    <img src="http://ad.xrea.com/ad_img.fcg?site=user.s*.xrea.com"
         height="60" width="468" alt="ad image" class="ad_image" />
  </a>
</div>

方法を考える

思いつくだけあげてみる。 他にも知っているなら教えてください。

実際にやってみよう

mod_layout

自動広告も一緒に現れてしまうから、 無理なのでは?

SSI

タグを挿入するくらいなら、初めから広告を貼った方が早い?

Action

これは、特定のファイルにアクセスすると、 CGIにアクセスするようになる機能を利用する。

まず、広告を適切に挿入するCGIを用意する。 addad.cgiとして、/public_html/x/addad.cgiに置くとしよう。

.heaccseeに次のように記述する。

AddType application/x-httpd-xhtml xhtml
Action application/x-httpd-xhtml /x/addad.cgi

addad.cgi

言語は何でもいいだろう。 なるべくなら、Cが一番いいと思われる。 fastcgiが使えるようであれば、それが一番いい。 mod_phpはポートが違うので無理だと思う。

なお、Python版、PHP版、Perl版を募集中…。

これらのプログラムは全て未保証です。 重大なバグが含まれている可能性があります。 自己責任で使用してください。

ライセンスについてはただいま少し考え中です。 Rubyと似たようなライセンスまたはGPLにしようと思っています。 もしかしたらLGPLにするかも知れません。 BSDと言うのもあり得ます。

少なくとも自由に使っていいです。 再配布するときはGPLであれば今のところ文句は言いません。

Ruby

たぶんあまり問題はないと思います。 速度も気にするほど遅くはありません。

既知の不具合と言うより仕様
使用方法

addad.cgiと言う名前で保存して、 $userと$serverには自分のユーザー名とサーバー名を入れてください。 あとは、自分のサイトに置くだけ。

ソース
#!/usr/local/bin/ruby

$user = ""  # user id
$sever = "" # sever name

INTERNAL_DTD_SUBSET = "[<!ATTLIST a target CDATA #IMPLIED>]"
PUBID = "-//W3C//DTD XHTML 1.1//EN"
SYSTEM = "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
DOC_DECLr = /(<!DOCTYPE\s+html\s+PUBLIC\s+"#{PUBID}"\s+"#{SYSTEM}"\s*)(>)/

def ad_tag(user, server)
  site = "#{user}.#{server}.xrea.com"
  %|<div class="ad_block">| +
  %|<a href="http://ad.xrea.com/ad_click.fcg?site=#{site}"| +
  %| target="_blank" class="ad_anchor">| +
  %|<img src="http://ad.xrea.com/ad_img.fcg?site=#{site}"| +
  %| height="60" width="468" alt="ad image" class="ad_image" />| +
  %|</a>| +
  %|</div>|
end

def add_ad(xhtml, user, server)
  xhtml = xhtml.sub(DOC_DECLr){ $1 + INTERNAL_DTD_SUBSET + $2 }
  xhtml = xhtml.sub(/<body(\s[^>]*)?>/){ $& + ad_tag(user, server) }
  return xhtml
end

if $0 == __FILE__
  xhtml = nil
  if xhtml_file = ENV['PATH_TRANSLATED']
    open(xhtml_file) do |file|
      xhtml = file.read
    end
  else
    xhtml = ARGF.read # commandline mode
  end
  xhtml = add_ad(xhtml, $user, $server)
  print "Content-type: application/xhtml+xml\n\n"
  print xhtml
end
TODO
C

テストは不十分です! このプログラムは参考程度にしてください。 使用して何かあっても私は一切責任を持てません。

出来上がったが、妖しさ100倍。 USERとSERVERに自分のユーザー名とサーバー名を入れてください。

既知の不具合と言うより仕様
使用方法

下のソースをaddad.cとして保存して、 USERとSERVERには自分のユーザー名とサーバー名を入れてください。 次にXREAにアップし、 SSHでgcc -o addad addad.cと打ってください。 addadというファイルをaddad.cgiとリネームして後は適当に置くだけです。 コンパイルされたaddad(addad.cgi)はバイナリ転送してください。

コンパイルはgcc 3.2とgcc 2.95.3-10でそれぞれcygwinでは出来ました。 XREA上では未テストです。

そーす
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define USER   "" /* user id */
#define SERVER "" /* sever name */

#define INTERNAL_DTD_SUBSET "[<!ATTLIST a target CDATA #IMPLIED>]"

#define MAX_LINE 1024 /* buffer size */

static FILE *xhtml_file;
static char line_buff[MAX_LINE];

void print_line(char *xhtml_line, FILE *file);

void print_ad_tag(const char *user, const char *server)
{
  printf("<div class=\"ad_block\">"
    "<a href=\"http://ad.xrea.com/ad_click.fcg?site=%s.%s.xrea.com\""
    " target=\"_blank\" class=\"ad_anchor\">"
    "<img src=\"http://ad.xrea.com/ad_img.fcg?site=%s.%s.xrea.com\""
    " height=\"60\" width=\"468\" alt=\"ad image\" class=\"ad_image\" />"
    "</a>"
    "</div>", user, server, user, server);
}

void print_doc_decl(char* xhtml_line, FILE *file)
{
  char *p, s[MAX_LINE];
  int i;

  for (i = 0; i < MAX_LINE; i++) {
    s[i] = '\0';
  }

  while (1) {
    if ((p = strchr(xhtml_line, '>')) == NULL) {
      printf("%s", xhtml_line);
      xhtml_line = fgets(line_buff, MAX_LINE, file);
      if (xhtml_line == NULL) {
        break;
      }
      /* next */
    } else {
      printf("%s", strncpy(s, xhtml_line, (p - xhtml_line)));
      printf("%s", INTERNAL_DTD_SUBSET);
      print_line(p, file);
      break;
    }
  }
}

void print_body_tag(char* xhtml_line, FILE *file)
{
  char *p, s[MAX_LINE];
  int i;

  for (i = 0; i < MAX_LINE; i++) {
    s[i] = '\0';
  }

  while (1) {
    if ((p = strchr(xhtml_line, '>')) == NULL) {
      printf("%s", xhtml_line);
      xhtml_line = fgets(line_buff, MAX_LINE, file);
      if (xhtml_line == NULL) {
        break;
      }
      /* next */
    } else {
      printf("%s", strncpy(s, xhtml_line, (p - xhtml_line) + 1));
      print_ad_tag(USER, SERVER);
      print_line(p + 1, file);
      break;
    }
  }
}
void print_tag(char* xhtml_line, FILE *file)
{
  /* xhtml_line[0] must be '<' */

  switch (xhtml_line[1]) {
  case '!': /* doc_decl or comment or CDATA etc. */
    if (xhtml_line[2] == 'D' && xhtml_line[3] == 'O' && 
    xhtml_line[4] == 'C' && xhtml_line[5] == 'T' &&
    xhtml_line[6] == 'Y' && xhtml_line[7] == 'P' &&
    xhtml_line[8] == 'E') {
      /* "<!DOCTYPE" */
      print_doc_decl(xhtml_line, file);
      break; /* switch */
    }
    /* not break... but it make no bug on valid xml! */
  case 'b': /* body? */
    if (xhtml_line[2] == 'o' && xhtml_line[3] == 'd' && 
    xhtml_line[4] == 'y') {
      /* "<body" */
      switch (xhtml_line[5]) {
      case '>':
        printf("%s", "<body>");
        print_ad_tag(USER, SERVER); /* ad! */
        print_line(xhtml_line + 6, file);
        break;
      case ' ': case '\t': case '\r': case '\n': /* spaces */
        /* body start tag */
        print_body_tag(xhtml_line, file);
        break;
      default:
        printf("%s", "<");
        print_line(xhtml_line + 1, file);
        break;
      }
      break; /* switch */
    }
  default:
    printf("%s", "<");
    print_line(xhtml_line + 1, file);
    break;
  }
}

void print_line(char *xhtml_line, FILE *file)
{
  char *p, s[MAX_LINE];
  int i;

  for (i = 0; i < MAX_LINE; i++) {
    s[i] = '\0';
  }

  if ((p = strchr(xhtml_line, '<')) == NULL) {
    /* no tag... */
    printf("%s", xhtml_line);
  } else {
    printf("%s", strncpy(s, xhtml_line, p - xhtml_line));
    print_tag(p, file);
  }
}

int main(int argc, char **argv)
{
  int c;
  char *file_name, *xhtml_line;
  FILE *xhtml_file;

  if ((file_name = getenv("PATH_TRANSLATED")) == NULL) {
    if (argc > 1) {
      file_name = argv[1]; /* commandline mode */
    }
  }
  xhtml_file = fopen(file_name, "r");
  printf("Content-type: application/xhtml+xml\n\n");
  while ((xhtml_line = fgets(line_buff, MAX_LINE, xhtml_file)) != NULL) {
    print_line(xhtml_line, xhtml_file);
  }
  fclose(xhtml_file);
  return 0;
}
TODO

本当にいい方法は?

初めから手動広告を貼り付ければいいだけです。 しかし、ローカルの時点で広告を貼り付けるのはウザイという人も いるかも知れません。 そんなときは自動で張り付けるプログラムをローカルで実行して、 保存すればいいだけです。 上にあるプログラムを参考に作ってみてはどうでしょうか?

もっとも素晴らしいのは、FTPアップするときに変換するプログラムでしょう。 たぶん、自分で作るしかないですが…。

util for XHTML 1.1 on XREA.COM

XREAで使える便利な広告のためのプログラム群をまとめる予定ですが、 どうなるかあまり決まっていない。

なお、Rubyで書く予定なので、他の言語は…。