2012-03-16 22:55

[PHP] 檢查 XML 文件結構

利用 SimpleXML 去檢查 XML 結構是否符合規格,為了讓這個程式可以多用途,採用了一個基準文件的作為結構準則,依據裡面定義的節點跟屬性,去檢查文件是否符合基本要求的格式。

<?php

/**檢查 XML 文件結構
 * @param string $baseFilePath 基準結構文件
 * @param string $checkFilePath 待檢查文件
 * @return bool 當結構與基準文件相符合時則回傳 true,否則是 false
 * */
function checkXmlFileStructure($baseFilePath,$checkFilePath){
    /*開啟 Base File*/
    if(!file_exists($baseFilePath)){ return false; }
    $base = simplexml_load_file($baseFilePath);
    if($base===false){ return false; }

    /*開啟 Check File*/
    if(!file_exists($checkFilePath)){ return false; }
    $check = simplexml_load_file($checkFilePath);
    if($check===false){ return false; }

    /*比較起始點的名稱*/
    if($base->getName() != $check->getName()){ return false; }

    /*比較結構*/
    return checkXmlStructure($base,$check);
}

/**檢查 XML 結構
 * @param SimpleXMLElement $base 基準結構物件
 * @param SimpleXMLElement $check 待檢查 XML 物件
 * @return bool 當結構與基準物件相符合時則回傳 true,否則是 false
 * */
function checkXmlStructure($base,$check){
    /*檢查屬性*/
    foreach ($base->attributes() as $name => $baseAttr){
        /*必要的屬性不存在*/
        if(!isset($check->attributes()->$name)){ return false; }
    }

    /*當沒有子節點時,則檢查對象也不能有子節點*/
    if(count($base->children())==0){
        return (count($check->children())==0);
    }

    /*將檢查對象的子節點分群*/
    $checkChilds = array();
    foreach($check->children() as $name => $child){
        $checkChilds[$name][] = $child;
    }

    /*檢查子節點*/
    $checked = array();
    foreach($base->children() as $name => $baseChild){
        /*跳過已經檢查的子節點*/
        if(in_array($name, $checked)){ continue; }
        $checked[] = $name;

        /*檢查必要的子節點是否存在*/
        if(empty($checkChilds[$name])){ return false; }

        foreach ($checkChilds[$name] as $child){
            /*遞迴檢查子節點*/
            if( !checkXmlStructure($baseChild, $child) ){ return false; }
        }
    }

    return true;
}


/*==============================================================================*/

if(isset($_SERVER['argv'])){
    parse_str(preg_replace('/&[\-]+/','&',join('&',$_SERVER['argv'])), $_GET);

    if(empty($_GET['base_file']) || empty($_GET['check_file'])){
        echo "Run: ".basename(__FILE__)." base_file=base.xml check_file=check.xml\n"; exit(1);
    }

    exit( checkXmlFileStructure($_GET['base_file'],$_GET['check_file']) ? 0 : 1);

}else{
    if(empty($_GET['base_file']) || empty($_GET['check_file'])){
        echo "Run: ".basename(__FILE__)."?base_file=base.xml&check_file=check.xml<br />"; exit;
    }

    echo( checkXmlFileStructure($_GET['base_file'],$_GET['check_file']) ? '1' : '0');
}


使用方式(shell)
php check_xml_file_structure.php base_file=base.xml check_file=check.xml

if [ "j$?" != "j0" ]; then
    echo "Run Error"
fi


測試範例 1
base_1.xml
<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item>
        <Category>Category文字</Category>
        <Title>Title文字</Title>
    </item>
</items>

check_1.xml
<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item>
        <Category>Category文字</Category>
        <Title>Title文字</Title>
    </item>
    <item>
        <Category>Category文字</Category>
        <Title>Title文字</Title>
        <Description>Description文字</Description>
    </item>
</items>


測試範例 2
base_2.xml
<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item category="Category文字" Title="Title文字"/>
</items>

check_2.xml
<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item category="Category文字" Title="Title文字" Description="Description文字" />
    <item category="Category文字" Title="Title文字" />
    <item category="Category文字" Title="Title文字" Description="Description文字" />
</items>
2012-03-14 14:48

[Ubuntu 11] 安裝 Redmine 與 SVN

安裝 LAMP & Redmine
# 安裝 LAMP
apt-get install apache2 php5 mysql-server php5-mysql libapache2-mod-php5 libapache2-mod-auth-mysql 

# 安裝 svn, dav_svn
apt-get install subversion libapache2-svn 

# 安裝 redmine
apt-get install redmine redmine-mysql libapache2-mod-fcgid libapache2-mod-passenger

# 可以使用下面的方式重新設定 redmine DB 連結
#dpkg-reconfigure redmine 

# 啟用 Apache 套件 php5, headers, expires
a2enmod php5 dav_svn auth_mysql cgid fcgid passenger rewrite ssl setenvif 

# 安裝 git, phpmyadmin
apt-get install mercurial git-core phpmyadmin

# 連結 phpmyadmin 設定檔
cd /etc/apache2/conf.d/
ln -s ../../phpmyadmin/apache.conf phpmyadmin.conf
service apache2 restart


安裝 Redmine 套件
gem install pandoc-ruby rdiscount rpeg-markdown bluefeather

cd /usr/share/redmine/vendor/plugins


# 安裝 Code Review 套件
hg clone https://bitbucket.org/haru_iida/redmine_code_review
rake db:migrate_plugins RAILS_ENV=production


# 安裝 Markdown Extra formatter 套件
git clone git://github.com/juno/redmine_markdown_extra_formatter.git


# 安裝 reStructuredText formatting 套件
git clone git://github.com/alphabetum/redmine_restructuredtext_formatter.git
cd redmine_restructuredtext_formatter
git checkout pandoc-ruby


建立SVN庫
mkdir -p /home/repoadmin/repos
svnadmin create /home/repoadmin/repos/team1
svnadmin create /home/repoadmin/repos/team2
chown -R www-data:www-data /home/repoadmin/repos


建立SVN認證時需要的DB使用者(redmine_svn_auth)
CREATE USER 'redmine_svn_auth'@'localhost' IDENTIFIED BY 'redmine_svn_auth';
GRANT SELECT(id, login, hashed_password, status ,type) ON redmine_default.users TO 'redmine_svn_auth'@'localhost';


設定 Apache2 Site
cd /etc/apache2/sites-available/
cp default redmine_svn
vim redmine_svn

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /usr/share/redmine/public

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    <Directory /usr/share/redmine/public>
        Options ExecCGI FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all

        RewriteEngine On
        RewriteRule ^$ index.html [QSA]
        RewriteRule ^([^.]+)$ $1.html [QSA]
        RewriteCond %{REQUEST_FILENAME} !-f [OR]
        RewriteCond %{REQUEST_FILENAME} dispatch.fcgi$
        RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
    </Directory>

    <Location /svn>
        DAV svn
        SVNParentPath /home/repoadmin/repos
        SVNPathAuthz off

        AuthBasicAuthoritative Off
        AuthUserFile /dev/null
        AuthType Basic
        AuthName "Subversion Repository"

        # auth_mysql help in http://localhost/doc/libapache2-mod-auth-mysql/DIRECTIVES.gz
        Auth_MYSQL On
        Auth_MySQL_Host localhost
        Auth_MYSQL_DB redmine_default
        Auth_MYSQL_Username redmine_svn_auth
        Auth_MYSQL_Password redmine_svn_auth
        Auth_MYSQL_Password_Table users
        Auth_MYSQL_Username_Field login
        Auth_MYSQL_Password_Field hashed_password
        Auth_MySQL_Password_Clause " AND status=1 AND type='User' "
        Auth_MYSQL_Empty_Passwords Off
        Auth_MYSQL_Encryption_Types SHA1Sum
        # Options: Crypt_DES, Crypt_MD5, Crypt, PHP_MD5, SHA1Sum, MySQL, Apache

        Require valid-user
    </Location>

    LogLevel warn
    CustomLog /var/log/apache2/redmine_access.log combined
    ErrorLog /var/log/apache2/redmine_error.log
</VirtualHost>


重新啟動 Apache
a2dissite default
a2ensite redmine_svn
service apache2 restart


測試網址


參考來源:
將 Redmine 安裝於 Debian、Ubuntu Linux
Ubuntu 10.04 using Passenger
svn 使用和 redmine 相同帳號進行認證
2012-03-08 19:38

Aptana Unified Builder 卡住

Aptana 2 的建置器(Aptana Unified Builder)時不時就會卡住,通常會發生這種狀況的原因,就是專案中有某個檔案無法正常解析,或路徑不對造成的。

解決的辦法是先關閉『專案->自動建置』,然後將有問題的專案複製一份到新的工作區,然後用過濾法找出無效的檔案,然後先刪除再重新建立。
2012-03-08 16:43

Ubuntu 10 設定預設語系

sudo vim /etc/default/locale
LANG="zh_TW.UTF-8"
LANGUAGE="zh_TW:zh"
2012-03-08 16:00

[Linux] 使用 MD5 檢查 FTP 上傳的檔案

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

MAIL_TO="my_mail@gmail.com"
TARGET_PATH="/var/www/file/show.mp4"
FILE="upload_file"
EXTEND="mp4"

cd /home/ftp_user


# md5 file is not exist
if [ ! -f $FILE.md5 ]; then exit 0; fi

# MD5 check sum 
md5sum -c $FILE.md5 >/dev/null 2>&1
if [ "j$?" != "j0" ]; then  
 # Notice: md5 check fail 
 echo "" |mail -s "[Failed] $FILE.$EXTEND md5 check sum fail" $MAIL_TO
 rm -f ./$FILE.md5
 exit 1; 
fi

mv ./$FILE.$EXTEND $TARGET_PATH
rm -f ./$FILE.md5

exit 0;
2012-03-07 14:06

[Ubuntu] 安裝 Oracle Client 與 PDO_OCI

Oracle Database Instant Client 下載 Client/SDK
(Version 10.2.0.4 Instant Client Package - Basic, Instant Client Package - SDK)
oracle-instantclient-basic-10.2.0.4-1.i386.rpm
oracle-instantclient-devel-10.2.0.4-1.i386.rpm

# 安裝套件轉換器
apt-get install alien 

# 轉換 rpm 套件到 deb,並安裝
alien -i oracle-instantclient-basic*.rpm
alien -i oracle-instantclient-devel*.rpm

# 安裝 Apache2,PHP,MySQL
apt-get install apache2 php5 mysql-server php5-mysql libapache2-mod-php5

# 安裝 PEAR 
apt-get install php-pear php5-dev dh-make-php make re2c

# 下載 PDO_OCI 原始檔 
pecl download pdo
pecl download pdo_oci
tar zxvf PDO-1.0.3.tgz
tar zxvf PDO_OCI-1.0.tgz

mkdir -p PDO_OCI-1.0/include/php/ext/
mv PDO-1.0.3 PDO_OCI-1.0/include/php/ext/pdo
cd PDO_OCI-1.0/
phpize
./configure --with-pdo-oci=instantclient,/usr,10.2.0.4

make -j$(grep processor /proc/cpuinfo |wc -l)
make install  # /usr/lib/php5/20xxxxxx+lfs/pdo_oci.so

vim /etc/php5/conf.d/pdo_oci.ini # 建立 pdo_oci.ini, 內容如下:
extension=pdo_oci.so

vim /etc/apache2/envvars # 在最後面加入環境變數, 內容如下: 
export NLS_LANG="TRADITIONAL CHINESE_TAIWAN.UTF8"
export NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS"

# 重新啟動 Apache 
service apache2 restart

參考來源:
Debian 安裝設定 PHP 連 Oracle extension 使用 PDO(PDO_OCI)
Oracle Instant Client