Cybozu Office からスケジュールデータをスクレイピングして、ical形式でレスポンスするスクリプトです。
元は名古屋の社長様が作られたもので、その後、望遠鏡ドットコム様が修正したものを勝手にメンテしたものとなります。
<?php
/*
機能説明: CybozuOffice10に対してスケジュールをスクレイピングし、ical形式に変換して返却するスクリプト
利用方法: https://hoge/cybouz2ical.php?user=username&pass=password
usernameはCybozuOfficeの下記ページの「ログイン名」欄にて確認できます。
https://hoge/fuga/ag.cgi?page=PersonalUser
改版履歴:
2009/05/13
名古屋ではたらく社長ブログだもんで
サイボウズofffice8と同期するツール暫定版
http://ameblo.jp/sitescope/entry-10260113074.html
2013/08/26
上記にて公開していただいているスクリプトをサイボウズ9用に勝手改変版
サイボウズ Office Version 9.3.1 20130703181739にて確認
望遠鏡ドットコム
サイボウズ9・サイボウズ10のスケジュールをiCal形式でGoogleカレンダーに同期(一方通行)
サイボウズ9・サイボウズ10のスケジュールをiCal形式でGoogleカレンダーに同期(一方通行)
2020/09/18
上記で公開しているソースについて以下を改修しました
・ icalのUIDの重複を避ける(Googleカレンダーで同日の複数予定が1日1件しか取り込めないのを修正)
・ 基本認証設置しているCybozuOfficeに対応
・ URLパラメタにUser/Passを含めるように修正(SSLを使用しないと平文で送られるので要注意)
・ その他微修正
*/
$username = $_GET['user'];
$password = $_GET['pass'];
if(empty($username) || empty($password)){
die("parameter error!");
}
//-------------------------------------------------------------------------------------------------------------------
// 設定
//-------------------------------------------------------------------------------------------------------------------
//define("CHAR_CODE", 'SJIS'); //サイボウズの文字コード サイボウズ9はSJIS
define("CHAR_CODE", 'UTF-8'); //サイボウズの文字コード サイボウズ10はUTF-8
define("SCHEDULE_TITLE", 'Cybozu'); //スケジュールタイトル
define("SCHEDULE_MEMO", TRUE); //スケジュールメモまで取得する場合は'TRUE'
define('PRODID', 'Cybozu2iCal'); //http://ameblo.jp/sitescope/entry-10260113074.html
define('CYBOZU_URL', 'https://hoge/fuga/ag.cgi'); //サイボウズのURL
define("VERSION", 10); //CybozuOfficeバージョン(9,10のみ対応)
define("SALU_ID", ''); //基本認証(ある場合だけセット)
define("SALU_PW", ''); //基本認証(ある場合だけセット)
//-------------------------------------------------------------------------------------------------------------------
//POSTデータ組み立て
$data = array(
"_System" => "login",
"_Login" => "1",
"LoginMethod" => "2",
"_Account" => $username,
"Password" => $password
);
$data = http_build_query($data, "", "&");
//headerにセット
$header = array(
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: ".strlen($data)
);
//基本認証があるサイボウズの場合
if(!empty(SALU_ID)){
$header[] = "Authorization: Basic " . base64_encode(SALU_ID . ":" . SALU_PW);
}
$context = array(
"http" => array(
"method" => "POST",
"header" => implode("\r\n", $header),
"content" => $data
)
);
//個人月間スケジュール
$url = CYBOZU_URL . '?page=ScheduleUserMonth';
//サイボウズからHTMLデータ取得
$work = file_get_contents($url, false, stream_context_create($context));
//文字コードをUTF-8へ変換
$work = mb_convert_encoding($work, "UTF-8", CHAR_CODE);
//正規表現がめんどくさいのでそのまま文字列比較で不要なとこをまず削除
$work = substr(strchr($work,'<table class="schedule usermonth" id="schedulemonth" width="100%" >'), 0);
$work = substr($work, 0, strpos($work, '<table class="monthNavi" '));
$work = substr(strchr($work,'<tbody id="um__body">'), 0);
$work = substr($work, 0, strpos($work, '</table>'));
//文字列比較でとりあえず、スケジュールを配列に格納
$wdate1 = "";
$wdate2 = "";
$schedule_list = "";
$loop_flg = TRUE;
while ( $loop_flg == TRUE ) {
//日付の取得
$wdate = "";
$wdate = substr(strchr($work,'<span class="date">'), 19);
$wdate = substr($wdate, 0, strpos($wdate, '</span>'));
if ($wdate == "") {
break;
}
//日付のフォーマットを変更
$date_sp = "";
$date_sp = split('/', $wdate);
$schedule_date = Date('Y') . sprintf("%02d",$date_sp[0]) . sprintf("%02d",$date_sp[1]);
//次の日も取得しとく
$schedule_date_tommorow = "";
$schedule_date_tommorow = Date('Ymd', mktime(0, 0, 0, (int)$date_sp[0], (int)((int)$date_sp[1] + 1), (int)Date('Y') ) );
//日付部分をカット
$work = substr(strchr($work,'<span class="date">'), 30);
$loop_flg2 = TRUE;
while ( $loop_flg2 == TRUE ) {
if ( strpos($work, '<a class="event" href=') > strpos($work, '<span class="date">') ) {
break;
} else {
//スケジュールIDを取得
if( VERSION == 9 ){
// サイボウズ9
$schedule_id = substr(strchr($work,'<div class="eventLink scheduleMarkTitle0" name="'), 53);
$schedule_id = substr($schedule_id, 0, strpos($schedule_id, '">'));
}else{
// サイボウズ10
$schedule_id = substr(strchr($work,'<div class="eventLink scheduleMarkTitle0 highlight-event'), 56);
$schedule_id = substr($schedule_id, 0, strpos($schedule_id, '" '));
}
if ( $schedule_id == "" ) {
break;
}
//----------------------------------
if ( SCHEDULE_MEMO ) {
//スケジュール内容まで取得
$wlink = substr(strchr($work,'<a class="event" href="ag.cgi?'), 30);
$wlink = substr($wlink, 0, strpos($wlink, '" title="'));
$url = CYBOZU_URL . '?' . $wlink;
//サイボウズからHTMLデータ取得
$work2 = file_get_contents($url, false, stream_context_create($context));
//文字コードをUTF-8へ変換
$work2 = mb_convert_encoding($work2, "UTF-8", CHAR_CODE);
//正規表現がめんどくさいのでそのまま文字列比較で不要なとこをまず削除
$work2 = substr(strchr($work2,'<table class="dataView scheduleDataView" width="100%" >'), 0);
$work2 = substr($work2, 0, strpos($work2, '<span class="vr_scheduleUserCount">'));
//スケジュールタイトルを取得
$work2 = str_replace("\n\r","", $work2);
$work2 = str_replace("\n","", $work2);
$work2 = str_replace("\r","", $work2);
$schedule_description = substr(strchr($work2,'<div id="scheduleMemo"><tt>'), 27);
$schedule_description = substr($schedule_description, 0, strpos($schedule_description, '</tt>'));
$schedule_description = strip_tags($schedule_description);
}
//----------------------------------
//スケジュールタイトルを取得
$schedule_title = substr(strchr($work,'=sm" title="'), 12);
$schedule_title = substr($schedule_title, 0, strpos($schedule_title, '">'));
//時刻を取得
if (strpos($work, '<span class="eventDateTime">') < strpos($work, '=sm" title="')) {
$schedule_time = substr(strchr($work, '<span class="eventDateTime">'), 28);
$schedule_time = substr($schedule_time, 0, strpos($schedule_time, ' '));
} else {
$schedule_time = '';
}
//タイトル部分をカット
$work = substr(strchr($work,'=sm" title="'), 12);
//時間指定があるか判定
if ( !empty($schedule_time) ) {
$time_sp = "";
$time_sp = split('-', $schedule_time);
$from_sp = split(':', @$time_sp[0]);
//http://www.sunvisor.net/node/383
if ( count($time_sp) > 1 ) {
$to_sp = split(':', @$time_sp[1]);
} else {
$to_sp = $from_sp;
}
$from_sp[0] = sprintf('%02d', @$from_sp[0]);
$to_sp[0] = sprintf('%02d', @$to_sp[0]);
$from_hour = "";
$to_hour = "";
if ($from_sp[0]<10) {
$from_hour = '0' . @$from_sp[0];
} else {
$from_hour = $from_sp[0];
}
if ($to_sp[0]<10) {
$to_hour = '0' . $to_sp[0];
} else {
$to_hour = $to_sp[0];
}
if (count($to_sp)<2){
$to_hour = $from_hour + 1;
$to_sp[1] = $from_sp[1];
}
$schedule_summary = $schedule_title;
//http://www.sunvisor.net/node/383
$schedule_from = ':' . $schedule_date . 'T' . @$from_sp[0] . @$from_sp[1]. '00';
$schedule_to = ':' . $schedule_date . 'T' . @$to_sp[0] . @$to_sp[1]. '00';
$schedule_description = $schedule_title . " " . $schedule_description;
} else {
$schedule_summary = $schedule_title;
//http://www.sunvisor.net/node/383
$schedule_from = ';VALUE=DATE:' . $schedule_date;
$schedule_to = ';VALUE=DATE:' . $schedule_date_tommorow;
$schedule_description = $schedule_title . " " . $schedule_description;
}
//http://www.sunvisor.net/node/383
$schedule_list[] = Array('id' => $schedule_id.$schedule_date,
'description' => $schedule_description,
'dtstart' => $schedule_from,
'dtend' => $schedule_to,
'summary' => $schedule_summary);
}
}
}
//ここから出力
header('Content-Type: text/calendar; charset=utf-8');
echo 'BEGIN:VCALENDAR'. "\n";
echo 'PRODID:' . PRODID. "\n";
echo 'VERSION:2.0'. "\n";
echo 'METHOD:PUBLISH'. "\n";
echo 'CALSCALE:GREGORIAN'. "\n";
echo 'X-WR-CALNAME:' . SCHEDULE_TITLE . "\n";
echo 'X-WR-CALDESC:' . SCHEDULE_TITLE . "\n";
echo 'X-WR-TIMEZONE:Asia/Tokyo'. "\n";
if ( !empty($schedule_list) ) {
foreach ( $schedule_list as $key => $vale ) {
echo 'BEGIN:VEVENT'. "\n";
// UIDの重複を避ける(Googleカレンダーで同日の複数予定が1件しか取り込めないのを修正)
// echo 'UID:' . SCHEDULE_TITLE . '-' . $vale['id'] . "\n";
echo 'UID:' . SCHEDULE_TITLE . '-' . $vale['id'] . md5($vale['description'].$vale['dtstart'].$vale['dtend']) . "\n";
echo 'DESCRIPTION:' . $vale['description']. "\n";
//http://www.sunvisor.net/node/383
echo 'DTSTART;TZID=Asia/Tokyo' . $vale['dtstart'] . "\n";
echo 'DTEND;TZID=Asia/Tokyo' . $vale['dtend'] . "\n";
echo 'SUMMARY:'. $vale['summary']. "\n";
echo 'END:VEVENT'. "\n";
}
}
echo 'BEGIN:VTIMEZONE'. "\n";
echo 'TZID:Asia/Tokyo'. "\n";
echo 'BEGIN:STANDARD'. "\n";
echo 'DTSTART:19700101T000000'. "\n";
echo 'TZOFFSETFROM:+0900'. "\n";
echo 'TZOFFSETTO:+0900'. "\n";
echo 'END:STANDARD'. "\n";
echo 'END:VTIMEZONE'. "\n";
echo 'END:VCALENDAR'. "\n";
?>
最近のコメント