2007年12月3日 星期一

haserl:Html And Shell Embedded Report Language

haserl:Html And Shell Embedded Report Language,一個小型的 CGI wrapper,可以直接在 HTML 文件中嵌入 shell script 語法,使用用 POST 或 GET 傳入的變數會自動轉換成環境變數,在標記內( <? ?> )的語法則視為 shell script 來執行。

haserl 網址:http://haserl.sourceforge.net/



範例程式
#!/usr/bin/haserl
<?
temp='Html And Shell Embedded Report Language '

echo $temp

echo $FORM_foo

?>
<html>
<body>
<form action=1.cgi method=post>
<input type=text name=foo></input>
<input type=submit>
</form>
</body>
</html>

2007年10月26日 星期五

NetBIOS over TCP/IP 名稱解析 IP 位址方法

NetBIOS over TCP/IP 名稱解析 IP 位址方法
1.在LMHOSTS檔案中尋找。
2.區域網路中廣播。
3.透過WINS伺服器。

MS Windows系統使用下列四種方法解析:
B Mode(Broadcast、ox1)
不適合大型網路,查詢順序如下
1.LMHOSTS CACHE
2.Broadcast
3.LMHOSTS

P Mode(per-to-per、0x2)
僅使用WINS伺服器查詢。

M Mode(mixed、0x4)
聯合使用B Mode及P Mode,預設使用B Mode,如果不能使用Broadcast,則使用P Mode的WINS伺服器。

H Mode(hybrid、0x8)
聯合使用B Mode及P Mode,預設使用P Mode。

2007年10月23日 星期二

計算中文 big5 在編碼中的順序

//計算中文 big5 在編碼中的順序
//高位元區段 81-8D 8E-A0 A1-FE ---->126個
//低位元區段 40-7E A1-FE ---> 157 個
//先計算高位元的距離 公式:(高位元 - 0x81) * 157
//再計算低位元距離 分為兩組 40-7E A1-FE
//0x40=64 0x7E=126 63個
//0xA1=161 0xFE=254 94個
//落在 0x40-0x7E 直接加上 (低位元的值 - 0x40 + 1)
//落在 0xA1-0xFE 63 + (低位元的值 - 0xA1 + 1)

// PHP

<?php
function big5order($big5){
$big5_h = $big5[0] . $big5[1];
$big5_l = $big5[2] . $big5[3];int big5order(unsigned short big5){
unsigned short big5order;
unsigned char hi, lo;

hi = (big5 & 0xFF00) >> 0x08;
lo = big5 &0x00FF;

big5order = (hi - 0x81) * 157;

if(lo>=0x40 && lo<=0x7E)
big5order = big5order + lo - 0x40 + 1;
else if(lo>=0xA1 && lo<=0xFE)
big5order = big5order + 63 + lo - 0xA1 + 1;

return big5order;
}

?>

// C/C++

int big5order(unsigned short big5){
unsigned short big5order;
unsigned char hi, lo;

hi = (big5 & 0xFF00) >> 0x08;
if(!(hi>=0x81 && hi<=0xFE)) return -1;

lo = big5 &0x00FF;
if(!((lo>=0x40 && lo<=0x7E) (lo>=0xA1 && lo<=0xFE))) return -2;

big5order = (hi - 0x81) * 157;

if(lo>=0x40 && lo<=0x7E)
big5order = big5order + lo - 0x40 + 1;
else if(lo>=0xA1 && lo<=0xFE)
big5order = big5order + 63 + lo - 0xA1 + 1;

return big5order;
}

2007年10月18日 星期四

將字串型態表示的16位元數字轉為整數資料型態

將字串型態表示的16位元數字轉為整數資料型態

傳入的參數可為 " ffbc","FFbC","0xFFFC", "12F4"


//字元 HEX 轉 OCT
int chex2oct(char ch[]){
unsigned int i, j[10], leng, leng_s=0, chex=0;
unsigned int hex16[] = {1, 16, 256, 4096, 65536, 1048576, 16777216,268435456};
leng = strlen(ch);

for(i=0; i<leng; i++) {
if(ch[i]>47 && ch[i]<58) j[leng_s++] = ch[i] - 48;
else {
switch (ch[i]){
case 'a': case 'A': j[leng_s++] = 10; break;
case 'b': case 'B': j[leng_s++] = 11; break;
case 'c': case 'C': j[leng_s++] = 12; break;
case 'd': case 'D': j[leng_s++] = 13; break;
case 'e': case 'E': j[leng_s++] = 14; break;
case 'f': case 'F': j[leng_s++] = 15; break;
}
}
}

for(i=0; i<leng_s; i++) chex += j[i] * hex16[leng_s - i - 1];
return chex;
}

2007年9月7日 星期五

Linux syslog 程式設計筆記

LINUX下執行的程式除了自己輸出系統日誌到特定檔案外,還可以透過 syslogd來達成這個功能,免除了自行開檔關檔的工作。

程式要使用系統日誌功能,只需要在程式啟動時使用openlog函數來連接syslogd程式,後面隨時用syslog函數傳人系統日誌就行了。

相關的函式有 openlog,syslog,closelog。

#include <syslog.h>

void openlog(const char *ident, int option, int facility)

開啟一個到系統日誌記錄程式的連接,開啟後就可使用用syslog或vsyslog函數在系統日誌中添加資訊

ident 是一個標記,ident所表示的字串將固定地加在每行日誌的前面以標識這個日誌,通常就寫成當前程式的名稱以作標記。

option 是下列值取與運算的結果:

LOG_CONS
Write directly to system console if there is an error while sending to system logger.

LOG_NDELAY
Open the connection immediately (normally, the connection is opened when the first message is logged).

LOG_NOWAIT
Don’t wait for child processes that may have been created while logging the message. (The GNU C library does not create a
child process, so this option has no effect on Linux.)

LOG_ODELAY
The converse of LOG_NDELAY; opening of the connection is delayed until syslog() is called. (This is the default, and need
not be specified.)

LOG_PERROR
(Not in SUSv3.) Print to stderr as well.

LOG_PID
Include PID with each message.


facility 指明記錄日誌的程式的類型。facility is the default facility code for this connection. A syslog on this connection that specifies default facility causes this facility to be associated with the message. See syslog for possible values. A value of zero means the default default, which is LOG_USER.

#include <syslog.h>

void syslog(int priority, const char *format, ...)

把日誌消息發給系統程式輸出至syslogd記錄

priority 日誌消息的緊急級別

LOG_USER

A miscellaneous user process
LOG_MAIL

Mail
LOG_DAEMON

A miscellaneous system daemon
LOG_AUTH

Security (authorization)
LOG_SYSLOG

Syslog
LOG_LPR

Central printer
LOG_NEWS

Network news (e.g. Usenet)
LOG_UUCP

UUCP
LOG_CRON

Cron and At
LOG_AUTHPRIV

Private security (authorization)
LOG_FTP

Ftp server
LOG_LOCAL0

Locally defined
LOG_LOCAL1

Locally defined
LOG_LOCAL2

Locally defined
LOG_LOCAL3

Locally defined
LOG_LOCAL4

Locally defined
LOG_LOCAL5

Locally defined
LOG_LOCAL6

Locally defined
LOG_LOCAL7

Locally defined

format 日誌消息的格式,之後是格式對應的參數類似printf函數。

#include <syslog.h>

void closelog(void)

關閉 開啟的 openlog 連接

#include <stdarg.h>

void vsyslog(int priority, const char *format, va_list ap);

把日誌消息發給系統程式輸出至syslogd記錄


簡單範例

#include <syslog.h>

int main(int argc, char **argv)
{
openlog("test", LOG_CONS | LOG_PID, 0);
syslog(LOG_INFO, "This is a syslog test message generated by program '%s'n", argv[0]);
closelog();

return 0;
}

結果輸出一般是 /var/log/messages 或是 /var/log/syslog

視 /etc/syslog.conf 中的設定,下面的設定是輸出至 /var/log/messages

# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.* /dev/console

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none /var/log/messages

# The authpriv file has restricted access.
authpriv.* /var/log/secure

# Log all the mail messages in one place.
mail.* -/var/log/maillog


# Log cron stuff
cron.* /var/log/cron

# Everybody gets emergency messages
*.emerg *

# Save news errors of level crit and higher in a special file.
uucp,news.crit /var/log/spooler

# Save boot messages also to boot.log
local7.* /var/log/boot.log

補充

Linux有關syslog的函式沒有提供syslog寫到遠端syslogd的功能,如果在程式中想要將syslog寫到遠端的syslog 伺服器,可以使用socket udp(514)的函式,將訊息送出。

參考資料

http://insecure.org/sploits/aix.generic.syslogd.problem.html

http://zhoulifa.bokee.com/6104993.html

http://www.dusek.ch/manual/glibc/libc_18.html

http://www.balabit.com/network-security/syslog-ng/

2007年8月31日 星期五

C Function - split

ANSI C 中缺少類似 PHP 中的 split 處理函式,在字串處理中卻又常使用,以下是簡單範例

str:欲被 split 的字串

delim:用來分隔的字串

num:設定分隔出來的子字串最大的數目,如果 <1則不限制

傳回值為一儲存分割結果的字串陣列,當陣列中的值為 NULL表示結束。

char** split(char* str, const char* delim, int num){
char** tab=NULL;
int flag;
unsigned int pos_num=0, pos_num2=0;
unsigned long int i, j, k, str_leng, delim_leng, *pos;

str_leng = strlen(str);
delim_leng = strlen(delim);

pos = (unsigned long int*)malloc(sizeof(unsigned long int)*(int)(str_leng/delim_leng+1));

i = 0;

while(i<=(str_leng - delim_leng)) {
flag = 0;
for(j=0; j<delim_leng; j++) {
if(str[i+j]!=delim[j]) { flag=-1; break; }
flag = 1;
}
if(flag == 1) {
i = i + delim_leng;
pos[pos_num++] = i - delim_leng;
if(num<1) continue;
else if(num==pos_num) break;
} else i++;
}

if(pos_num==0) {
tab = (char **)malloc(sizeof(char*)*2);
tab[0] = (char *)malloc(sizeof(char)*(str_leng+1));
strcpy(tab[0], str);
tab[1] = NULL;
return tab;
}

tab = (char **)malloc(sizeof(char*)*pos_num);

if(pos[0]!=0) {
tab[pos_num2] = (char *)malloc(sizeof(char)*pos[0]);
for(i=0, j=0; i<pos[0]; i++, j++) tab[pos_num2][j] = str[i];
tab[pos_num2][j] = '\0';
pos_num2++;
}

for(i=1; i<pos_num; i++) {
if(pos[i] - (pos[i-1] + delim_leng) >0) {
tab[pos_num2] = (char *)malloc(sizeof(char)*(pos[i] - (pos[i-1] + delim_leng)) + 1 + 1);
for(j=pos[i-1] + delim_leng, k=0; j<pos[i]; j++, k++) tab[pos_num2][k] = str[j];
tab[pos_num2][k] = '\0';
pos_num2++;
}
}

if((pos[pos_num-1] + delim_leng - 1) < str_leng - 1) {
tab[pos_num2] = (char *)malloc(sizeof(char)*(pos[pos_num-1] + delim_leng - 1) + 1 + 1);
for(j=pos[pos_num - 1] + delim_leng, i=0; j<str_leng; j++, i++) tab[pos_num2][i] = str[j];
tab[pos_num2][i] = '\0';
pos_num2++;
}

tab[pos_num2] = NULL;
return tab;
}

使用範例

char **tab;
int i;

tab = split("1,2,3,4,5,6,7,8,9,0", ",", -1);
i = 0;
while(tab[i]!=NULL) printf("%d = %s =\n", i, tab[i++]);

C Function - fgetc、fgets讀取整個檔案內容

fgetc:傳回所讀到的字元,傳回值如果是 EOF,可能是有錯誤發生或是檔案終止(end-of-file),所以應該利用 feof 或是 ferror 來判定錯誤發生或是檔案終止。

fgets: 傳回所讀到的字串,傳回值如果是 NULL,可能是有錯誤發生或是檔案終止(end-of-file),所以應該利用 feof 或是 ferror 來判定錯誤發生或是檔案終止。

使用 fgetc 讀取整個檔案 

#include "stdio.h"
main()
{
FILE *fp;
ch ch;

if((fp=fopen("test", "r"))==NULL)
{
printf("file cannot be opened\n");
exit(1);
}

while((ch=fgetc(fp))!=EOF) fputc(ch,stdout);
fclose(fp);
}

使用 fgets 讀取整個檔案
#include "stdio.h"
main()
{
FILE *fp;
char str[128];

if((fp=fopen("test", "r"))==NULL)
{
printf("cannot open file\n");
exit(1);
}

while(!feof(fp))
if(fgets(str,128,fp)!=NULL) printf("%s",str);

fclose(fp);
}

2007年8月30日 星期四

C Function - trim

不少程式語言都有提供 trim 這個字串處理函式,但標準的 C 函式庫並沒有,以下是一個簡單的範例


void trim(char *s){
int i=0, j, k, l=0;

while((s[i]==' ')||(s[i]=='\t')||(s[i]=='\n'))
i++;

j = strlen(s)-1;
while((s[j]==' ')||(s[j]=='\t')||(s[j]=='\n'))
j--;

if(i==0 && j==strlen(s)-1) { }
else if(i==0) s[j+1] = '\0';
else {
for(k=i; k<=j; k++) s[l++] = s[k];
s[l] = '\0';
}
}

2007年8月15日 星期三

無磁碟 Linux 工作站安裝筆記

無磁碟 Linux工作站具有維護容易,新增設備簡便的優點,因此有不少的 Cluster,或是電腦教室採用這個方式建置。

建置和安裝方式有很多種,以下使用 DHCP Server + TFTP Server + NFSROOT + PXELinux 方式建置。

環境說明

OS:SUSE Linux Enterprise 9.0

Master-Server及Node1有相同的硬體規格,提供網路PXE的開機功能,唯一的差異是Node1上沒有任何的硬碟。

Master-Server:提供Node1開機及所需的任何資源,已安裝 SUSE Linux 9 Enterprise 所有軟體。

Node1:透過網路開機的設備,網卡MAC為 00:0C:29:7D:A2:CD

安裝步驟

1.設定 NFS Server 及準備 Node1 所需檔案

mkdir /remote

mkdir /remote/node1

cp -rpi /bin/ /remote/node1/

cp -rpi /dev/ /remote/node1/

cp -rpi /etc/ /remote/node1/

cp -rpi /lib/ /remote/node1/

cp -rpi /sbin/ /remote/node1/

cp -rpi /var/ /remote/node1/

cp -rpi /root/ /remote/node1/

mkdir /remote/node1/proc

mkdir /remote/node1/sys

mkdir /remote/node1/tmp

chmod a+rwx /remote/node1/tmp

mkdir /remote/node1/home

mkdir /remote/node1/usr

編輯 /remote/node1/etc/fstab 檔案 內容如下

192.168.120.128:/remote/node1 / nfs

編輯/etc/exports 檔案 內容如下

/home *(rw,root_squash,sync)
/usr *(ro)
/remote/node1 *(rw,no_root_squash)

重新啟動 nfs /etc/initd./nfs restart

2.安裝設定 tftp server

mkdir /tftpboot

mkdir /tftpboot/pxelinux.cfg

cp /usr/share/syslinux/pxelinux.0 /tftpboot

vi /tftpboot/pxelinux.cfg/01-00-0c-29-7a-a2-cd 內容如下

default linux

label linux
kernel bzImage
append ip=dhcp root=nfs nfsroot=192.168.120.128:/remote/node1

設定 tftp server 相關設定檔:/etc/xinetd.d/tftp 內容如下

# default: off
# description: tftp service is provided primarily for booting or when a
# router need an upgrade. Most sites run this only on machines acting as
# "boot servers".
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
disable = no
}

重新啟動 /etc/init.d/xinetd restart

3.建立適合 Node1 開機的核心

cd /usr/src/linux

make menuconfig --> 產生 .config 檔案 可直接編輯 .config

核心必須包含的選項

網路卡的驅動程式

# Networking options

# Kernel level IP autoconfiguration
CONFIG_IP_PNP=y
# DHCP support
CONFIG_IP_PNP_DHCP=y

# Network File Systems

# NFS file system support
CONFIG_NFS_FS=y
# Provide NFSv3 client support
CONFIG_NFS_V3=y
# Root file system on NFS
CONFIG_ROOT_NFS=y

make bzImage

cp /usr/src/linux/arch/i386/boot/bzImage /tftpboot

4.設定 DHCP Server

dhcpd相關設定檔 /etc/sysconfig/dhcpd

/etc/dhcpd.conf 內容如下

allow booting;
allow bootp;

option domain-name-servers 168.95.1.1;
option routers 192.168.120.2;
ddns-update-style none;
subnet 192.168.120.0 netmask 255.255.255.0 {
host node1 {
# option root-path "192.168.120.128:/remote/node1,v3,tcp,hard";
hardware ethernet 00:0C:29:7D:A2:CD;
fixed-address 192.168.120.20;
option broadcast-address 192.168.120.255;
filename "pxelinux.0";
}
}

重新啟動 /etc/init.d/dhcpd restart

5.將 Node1 開機設定為網路 PXE 開機,即完成

6.其他

大部份相關的安裝說明文件會提到NIS或是LDAP的安裝,作為帳號管理使用,在此文件就略過了,因為所有安裝過程中最關鍵的部份都在上面了。

2007年7月25日 星期三

ORACLE ARCHIVE LOG Mode 筆記

ORACLE DATABASE 切換到 Archive LOG 或 NO ARCHIVE LOG 模式必須關閉、重新啟動資料庫。

切換到ARCHIVE LOG 模式並不表示系統會自動執行 ARCHIVE LOG,必須下指令執行,如果希望一開機就自動執行必須在 spfile 中作設定。

切換到ARCHIVE LOG 模式後應立即作備份的動作,如果使用之前的備份回復資料,資料只能回復至 NOARCHIVE LOG Mode 時的狀況。

檢查是否為 Archive Log 模式
SQL>select archiver select * from v$log;
SQL>archive log list;

更改 ARCHIVE/NOARCHIVE LOG 模式步驟:
1.SQL>shutdown immediate
2.SQL>startup mount
3.SQL>alter database archivelog/noarchivelog;
4.SQL>alter database open;
5.backup full database and control file;

啟動 Archive LOG Mode
SQL>alter system archive log start/stop;

變更啟動 Parameter,讓資料庫一啟動就自動執行 ARCHIVE LOG
SQL>alter system set log_archive_start=true scope=spfile;
或是在 pfile 中加入 log_archive_start=true

查詢 ARCHIVE LOG 狀況
SQL>Archive Log List

其它一些相關的設定參數和查詢
SQL>show parameter log_archive_format
SQL>alter SYSTEM SET LOG_ARCHIVE_MAX_PROCESSES=3 scope=spfile sid='*';;
SQL>alter SYSTEM SET log_archive_dest_1 = "location=C:Oracleoradataoradbarchive" scope=spfile sid='*';
SQL>alter SYSTEM SET log_archive_format = %%ORACLE_SID%%T%TS%S.ARC scope=spfile sid='*';

2007年7月24日 星期二

Windows XP停用USB裝置自動播放功能

可以採用以下任一方法:

一、[開始]->[執行]->[在開啟欄中輸入 gpedit.msc],然後,參考下圖,設定完成後,重新開機。

二、USB 裝置插入電腦時,一直按著「Shift」鍵,直到系統已經連結此裝置 (作業系統將不會執行 autorun.inf)。

三、修改登錄機碼

機碼名稱 名稱 資料值
HKEY_CURRENT_USER->Software->Microsoft->Windows->CurrentVersion->Policies->Explorer NoDriveTypeAutoRun 0×00000095
HKEY_USERS->.DEFAULT->Software->Microsoft->Windows->CurrentVersion->Policies->Explorer NoDriveTypeAutoRun 0×00000095

2007年7月4日 星期三

那些ORACLE 物件支援重新命名

物件

支援

說明

CLUSTER X -
CONSTRAINT O ALTER TABLE table_name RENAME CONSTRAINT old_name TO new_name
CONTROL FILE o Alter the control_files parameter using the ALTER SYSTEM comamnd.
Shutdown the database.
Rename the physical file on the OS.
Start the database.
COLUMN O ALTER TABLE table_name RENAME COLUMN old_name TO new_name
DATAFILE O Shutdown the database.
Rename the physical file on the OS.
Start the database in mount mode.
Issue the ALTER DATABASE RENAME FILE command to rename the file within the Oracle dictionary.
Open the database.
DATABASE NAME O

SQL>alter system switch logfile;
SQL>alter database backup controlfile to trace;
SQL>shutdown
Modify (and optionally rename) the created trace file:
create new controlfile
modify db_name in init.ora
SQL>STARTUP

FUNCTION X -
INDEX O ALTER INDEX old_name RENAME TO new_name;
INDEX PARTITION O ALTER INDEX index_name RENAME PARTITION ptn_name TO new_name
INDEX SUB PARTITION O ALTER INDEX index_name RENAME SUBPARTITION ptn_name TO new_name
INSTANCE O SQL>SHUTDOWN
change ORACLE_SID (方法參考DATABASE NAME 更名)
SQL>STARTUP
LOB O ALTER TABLE T MOVE LOB(lob_column) STORE AS newlogseg_name;
LOGFILE X

Shutdown the database.
Rename the physical file on the OS.
Start the database in mount mode.
Issue the ALTER DATABASE RENAME FILE command to rename the file within the Oracle dictionary.
Open the database.

OUTLINE O ALTER OUTLINE old_name RENAME TO new_name
PACKAGE X -
PACKAGE BODY X -
PROCEDURE X -
SEQUENCE O RENAME oldseq_name TO newseq_name;
SYNONYM X -
SCHEMA X -
TABLE O RENAME old_table TO new_table;
TABLE PARTITION O ALTER TABLE table_name RENAME PARTITION ptn_name TO new_name;
TABLE SUB PARTITION O ALTER TABLE table_name RENAME SUBPARTITION ptn_name TO new_name
TRIGGER O ALTER TRIGGER old_name RENAME TO new_name
TABLESPACE O ALTER TABLESPACE old_name RENAME TO new_name [10g new]
VIEW O RENAME old_table TO new_table;

2007年6月14日 星期四

Microsoft Windows XP/2003 的 PowerToys

增加 Windows XP/2K3 系統功能的一些小工具

Color Control Panel Applet
在控制面板添加'Color'(色彩)項,查看並編輯色彩管理配置檔。
可以安裝或移除色彩配置,改變同顯示器、印表機和掃描器相關的色彩剖面,提供一個3D的界面觀看。

SyncToySyncToy
資料夾同步軟體,能對所指定的不同資料夾中的內容進行比對,並且依照使用者的需求來同步兩個資料夾之中的內容。
下載 SyncToy,需先通過微軟的合法性驗證,必須搭配 Microsoft .NET Framework 1.1。

RAW Image Thumbnailer and Viewer
讓Windows XP 支援RAW高階圖檔格式

ClearType Tuner
螢幕字體平滑工具

HTML Slide Show Wizard
製作網頁幻燈片的小工具,只需幾個步驟即可將指定的圖片或目錄中的圖片製作成在網頁中播放的幻燈片。

Open Command Window Here
在檔案系統資料夾裡增加了一個 "Open Command Window Here" 的快顯功能表選項-開啟命令視窗 (cmd.exe)。

Alt-Tab Replacement
有了這個 PowerToy,您除了會看到要轉換的應用程式圖示外,還可看到該網頁的預覽畫面。當應用程式有數個工作階段開啟時,特別有用。

Tweak UI
存取未在 Windows XP 預設使用者介面公開的系統設定,包括登入畫面、滑鼠、檔案總管、工作列設定等。
2.10 版支援 Windows XP SP 1 或 Windows Server 2003。

Power Calculator
可以製作函數的圖表並加以評估,也可執行各種不同的轉換。

Image Resizer
只需要按一下滑鼠右鍵,就可以調整一個或多個影像檔案的大小。

CD Slide Show Generator
用投影片放映的方式檢視燒錄在 CD 上的影像,支援 Windows 9x 舊版作業系統。

Virtual Desktop Manager
可以從 Windows 工作列管理四個桌面。

Taskbar Magnifier
可以從工作列放大螢幕的某部分。

Webcam Timershot
在特定時間間隔,從連接至電腦的網路攝影機來拍攝照片,並存到指定位置。

參考資料:
http://www.microsoft.com/windowsxp/downloads/powertoys/xppowertoys.mspx
http://www.microsoft.com/taiwan/windowsxp/downloads/powertoys/xppowertoys.mspx

2007年6月5日 星期二

MySQL 中 LongBlob 及 LongText 實際的最大長度

MySQL 中使用Blob及Text資料型態來儲存有大資料的欄位,以下是官方文件中各類型資料型態所能儲存的長度

類型 長度
Blob
Text
65535個字元(2^16-1)
MediumBlob
MediumText
16777215 個字元(2^24-1)
LongBlob
LongText
4294967295個字元 (2^32-1)

但規格歸規格,產品不見得和規格相符,資料最大的長度其實是取決於 my.cnf 中 max_allowed_packet 參數設定
MySQL 3.23 最大的值是 16M
MySQL 4.0. 最大的值是 1G
MySQL 5.0. 最大的值是 1G

所以所能儲存的資料長度最大是 16M(MySQL 3.23) 或 1G (MySQL 4.0/5.0)

參考文件:
http://www.mysql.com/news-and-events/newsletter/2003-08/a0000000216.html
http://dev.mysql.com/doc/refman/5.1/en/packet-too-large.html

ORACLE SELECT 查詢指定傳回筆數

ORACLE 中 SELECT 指令沒有類似 MySQL 中有 LIMIT 的參數可以使用來限制傳回資料的筆數,但是可以利用 ORACLE 中 ROWNUM 的值作一點手腳來限制傳回值的範圍。

ROWNUM 說明:
1. ORACLE 使用 ROWNUM 作為查詢結果行的編號,第一行是1,第二行是2, 以此類推,可以用於限制查詢返回的總行數。
2. ROWNUM 的值在查詢結果輸出時自動產生,因此不能以任何表格名稱作為首碼,因此下面的結果查詢不到任何的記錄。
SQL>select rownum, a, b from table_a where rownum=2;
SQL>select rownum, a, b from table_a where rownum>5;

使用 ROWNUM 限制資料範例:
查詢表格 TABLE_A中欄位 ID,並以 ID 排序,限制第 5筆至第10筆。
SQL>SELECT * FROM (SELECT ROWNUM ROW_ID, ID FROM TABLE_A ORDER BY ID) WHERE ROW_ID BETWEEN 5 AND 10;

2007年6月4日 星期一

Windows 2000/XP 下如何移除已經不存在設備的驅動程式

這個問題最常出現的狀況是更換不同廠牌網路卡後,設定 IP時卻出現錯誤訊息:所輸入的IP已經指定給舊的的網路卡使用,要設定另一個IP 給新的網路卡,要如何徹底移除舊的網路卡驅動程式?Windows 裝置管理員預設只會列出搜尋到的裝置,而不會列出所有安裝的驅動程式,因此必須改變預設的參數才能順利的移除已經不用的驅動程式。

步驟:

1.執行命令提示字元
2.set devmgr_show_nonpresent_devices=1
3.start devmgmt.msc
4.檢視 -> 顯視隱藏裝置

說明
環境變數 devmgr_show_nonpresent_devices=1:裝置管理員顯示所有已經安裝的設備驅動程式,就算是目前不在機器上的設備。
start devmgmt.msc:啟動裝置管理員
Devmgr_show_details=1

參考資料:
http://support.microsoft.com/kb/315539

2007年5月31日 星期四

SQL*Plus 使用環境的一些限制

項目

限制

filename length system dependent
username length 30 bytes
user variable name length 30 bytes
user variable value length 240 characters
command-line length 2500 characters
length of a LONG value entered through SQL*Plus LINESIZE value
LINESIZE system dependent
LONGCHUNKSIZE value system dependent
output line size system dependent
line size after variable substitution 3,000 characters (internal only)
number of characters in a COMPUTE command label 500 characters
number of lines per SQL command 500 (assuming 80 characters per line)
maximum PAGESIZE 50,000 lines
total row width

60,000 characters for VMS;

otherwise, 32,767 characters

maximum ARRAYSIZE 5000 rows
maximum number of nested scripts

20 for VMS, CMS, Unix;

otherwise, 5

maximum page number 99,999
maximum PL/SQL error message size 2K
maximum ACCEPT character string length 240 Bytes
maximum number of DEFINE variables 2048

SQL*Plus COPY 命令筆記

透過 SQL*Plus(9iR2) COPY 命令可以直接在不同資料庫間複製表格內容,支援模式如下:

  1. 由本地資料庫至遠端資料庫 (預設)
  2. 由遠端資料庫至本地資料庫
  3. 由遠端資料庫至遠端資料庫

來源表格欄位支援以下資料型態:CHAR、DATE、LONG、NUMBER、VARCHAR2,但不支援 LOB 這類資料型態。

SQL*Plus COPY 語法

COPY {FROM database | TO database | FROM database TO database} {APPEND|CREATE|INSERT|REPLACE} destination_table [(column, column, column, ...)] USING query

參數說明:

FROM database 指定資料來源資料庫
TO database 指定目標資料庫
database 以 username[/password] @connect_identifier 格式指定
APPEND 會直接將複製資料INSERT至指定目的表格,如果指定目的表格不存在會先建立指定目的表格。
CREATE 複製資料前會先建立指定目的表格,如果指定目的表格已經存在會傳回錯誤訊息。
INSERT 如果指定目的表格已經存在會傳回錯誤訊息,使用這個選項必須指定欄位名稱。
REPLACE 如果指定目的表格已經存在會刪除舊有的表格,如果不存在則複製資料前會建立表格。
destination_table 指定目的表格名稱。
(column, column, column, ...) 以逗點隔開的目的表格的資料欄別名。
USING query 任何有效的 SQL SELECT 敘述句。

通常 COPY 指令是用於 Oracle 和 non-Oracle 資料庫間的表格複製,因此如果同樣是在 ORACLE,應該使用 SQL 指令 (CREATE TABLE AS 和 INSERT) 。

Usage:
To enable the copying of data between Oracle and non-Oracle databases, NUMBER columns are changed to DECIMAL columns in the destination table. Hence, if you are copying between Oracle databases, a NUMBER column with no precision will be changed to a DECIMAL(38) column. When copying between Oracle databases, you should use SQL commands (CREATE TABLE AS and INSERT) or you should ensure that your columns have a precision specified.

The SQL*Plus SET LONG variable limits the length of LONG columns that you copy. If any LONG columns contain data longer than the value of LONG, COPY truncates the data.

SQL*Plus performs a commit at the end of each successful COPY. If you set the SQL*Plus SET COPYCOMMIT variable to a positive value n, SQL*Plus performs a commit after copying every n batches of records. The SQL*Plus SET ARRAYSIZE variable determines the size of a batch.

Some operating environments require that service names be placed in double quotes.

範例:

COPY FROM HR/your_password@HQ TO JOHN/your_password@WEST REPLACE WESTEMPLOYEES USING SELECT * FROM EMPLOYEES

參考文件:

SQL*Plus User's Guide and Reference Release 9.2:Part Number A90842-01:APPEND B:SQL*Plus COPY Command

2007年5月29日 星期二

將 Oracle 9i export 出的 dump file 匯入指定帳號、指定表格空間

如何將 Oracle 9i export 工具(exp) 輸出的 Oracle binary-format dump file 匯入指定帳號、並指定表格空間?

網路上有不少人提出了這樣奇怪的問題,這個問題很重要嗎?為什麼會有這樣的需求?在我看來有這樣的問題是一件很奇怪的事。

如果是客戶對軟體公司的產品或修補發生這樣的需求,可以推測很可能是軟體公司的開發人員直接將開發平台上的資料庫匯出來給客戶,而不是採用執行SQL Script的方式來更新資料庫中物件的Schema或資料,對很多公司有重要 Oracle 資料庫的 DBA,大概都很難接受這樣的事情,因為根本不曉得匯入的物件是不是有問題,也很難確定匯出的資料,轉到匯入的平台版本是否不會有問題(是否上了相同的修補檔)。萬一不幸匯入中的物件與原資料庫中有相同的物件名稱,又沒注意到一不小心可能就造成大災難了。如果資料庫大的話匯入的工程浩大又費時,當然匯入前要先作完整備份、匯入後要馬上作完整備份比較安全,如果是Archive Log Mode,那一堆的Archive Log 就要思考一下,匯入時是不是要暫時停止 Archive Log 的運作。

Oracle export 及 import 工具是用來轉移 Oracle Database 到另一個平台的工具,如果僅僅是想透過這個工具在不同的帳號和指定的表格空間中轉移,可能會很失望,因為他們不是為這個目的被設計出來的,不信邪,試到鬍鬚白了又打結也一樣。

以下是 Oracle Database Administration Fundamentals II 教材對 export 及 import 工具的說明:

The Export utility provides a simple way for you to transfer data objects between Oracle database, even if they reside on platforms with different hardware and software configurations.

When you run Export against an Oracle database, objects(such as tables) are extracted, followed by their related objects(such as indexes, comments, and grants), if any. The extracted data is written to an Export file, which is an Oracle binary-format dump file that is typically located on disk or tape.

The Import utility reads the object definitions and table data from an Export dump file. It inserts the data objects into an Oracle database.

Import 工具的執行順序過程:

  1. 建立新表格。
  2. 資料匯入表格。
  3. 建立索引。
  4. 匯入Trigger。
  5. 設定新表格上的 constraints。
  6. 建立其它 bimap,function,domain index。

首先使用 Oracle 9i export 和 import 工具有幾個觀念要釐清:

  1. 用來執行 import 工具的版本不能低於 export 版本。
  2. Oracle Export 及 Import 工具沒有任何選項、參數可以指定匯入的表格空間 (Tablespace)。
  3. Import 時會在目的 "資料庫帳號下的表格空間(Tablespace)" 中建立物件,而不是在目的 "帳號預設的表格空間(Tablespace)" 中建立物件。匯入時 import 程式在建立表格時會指定使用的表格空間,而表格空間名稱就是原匯出時的名稱,大部份情況在指定的表格空間不存在時,會改用匯入帳號預設的表格空間,但當表格中有比較特別的資料型態時,則無法使用匯入帳號預設的表格空間建立表格,而造成匯入失敗,這也是最多人搞不清楚的一點。
  4. 表格在表格空間裡並不是不可以被移動的,可以透過簡單的指令移動。
  5. 索引在表格空間裡雖然無法被移動的,但是可以透過簡單的指令重建。

觀念釐清後我們可以利用 export 及 import 工具先將資料庫物件轉移到目標資料庫,再作一些工作來達成目標(指定帳號、並指定表格空間),以下是簡單的步驟:

  1. 建立所需表格空間及調整表格空間的存取權限讓 Oracle Import 工具能正確無誤的執行,匯入到指定的帳號下。imp 中加入INDEXES=N參數、INDEXFILE=index.sql,產生建立索引指令的檔案 index.sql,索引等到表格都搬到正確表格空間再重建。
  2. 若由較低版本資料庫匯出的檔案,可能需要執行一些修正檔(略,自行處理)。
  3. 使用 ALL_TABLES View 查詢那些表格需要被移動。
  4. 使用 表格在表格空間移動的指令。移動指令:ALTER TABLE <table name> MOVE TABLESPACE <tablespace name>
  5. 如果表格中有 LOB 這類資料類型的欄位,則還需將這些欄位的資料移至新的表格空間。查詢 ALL_TAB_COLUMNS View;
  6. 移動LOB 這類資料類型的欄位資移至新的表格空間。移動指令:ALTER TABLE <table name> MOVE LOB(lobseg name) STORE AS (TABLESPACE <>tablespace name);
  7. 編輯 index.sql 檔案中 tablespace 的設定。
  8. 執行 index.sql 重建索引,或自行下指令重建需要移動表格空間的索引。重建索引的指令:ALTER INDEX <index name> REBUILD TABLESPACE <tablespace name>。

步驟 3、4,5、6,7、8 是可以寫成一個PL/SQL程序來執行的(略)。

其它參考資訊-Oracle 10g 如何變更 TABLESPACE NAME:

  1. Oracle 10g 新增指令,可以透過指令變更 TABLESPACE NAME,這和之前的版本比較,舊版本要變更 TABLESPACE NAME 是件浩大的工程。
  2. 指令:ALTER TABLESPACE <tablespace old name> RENAME TO <tablespace new name>;
  3. 資料庫 compatibility level 最低必須設為 10.0.1。
  4. 不能更改 SYSTEM、SYSAUX tablespace 表格名稱。
  5. 不能更改 offline tablespace。
  6. 不能更改 含有 offline datafiles 的 tablespace 名稱。
  7. 更改 tablespace 名稱,不會變更 tablespace identifier。
  8. 更改 tablespace 名稱,不會變更 tablespace 中 datafile 的名稱。

2007年5月23日 星期三

Linux 使用 USB 裝置筆記

USB規格簡介

USB Univeral Serial Bus (通用串列匯流排),常見的外部匯流排,支援熱插拔 (hot plugable),一個 USB 最多可以連接127個裝置。

目前規格包括:
  1. USB 1.1 支援二種傳輸速率:Low speed - 1.5 Mbps 及 Full Speed - 12 Mbps。
  2. USB 2.0 傳輸速率 480 Mbps 並支援 USB 1.1。

USB 採用 Single-Master (單主控) 設計,線路架構就像多個點對點的樹狀結構,具 USB 介面的 PC 至少有一個 "root hub",並提供二個外接孔供 USB 設備或另一個 USB hub。在電腦中的 USB 主控器會去 poll USB 匯流排上的各個裝置,每個 USB 設備連接到主機時,USB 主控器會分配一個代碼給該裝置,並讀取該裝置的描述表 (Device Descriptor) 以獲知裝置的硬體資訊。

USB 主控器(USB hoot Controller) 分為三種規格:

  1. OHCI (Open Host Controller Interface):USB 1.1 規格,Compaq(康柏)公司主導, 使用廠商包括 Compaq、iMacs、OPTi、SIS、ALi,採用 Memory-mapped 的 I/O 方式 (CPU 使用記憶體指令來存取 USB 主控器)。
  2. UHCI (Universal Host Controller Interface) :USB 1.1 規格,Intel公司提倡, 線路比 OHCI 線路簡單,但是需要比較複雜的驅動程式,對CPU負擔也微重了些,使用廠商包括 Intel、VIA,採用 I/O-mapped 的 I/O 方式 (CPU 使用 I/O 指令來存取 USB 主控器)。
  3. EHCI (Enhanced Host Controller Interface):USB 2.0 規格,速度較快 (480 Mbps),支援 USB 1.1,相容於 OHCI 和 UHCI。

Linux 對 USB的支援

Linux 從 kernel 2.2.7 版本便開始支援 USB,USB 2.0 是從 2.4.19 開始, Linux 以三層式架構來支援 USB 系統,這三層是內核層 (Core) 、主控層 (Controller)、裝置層 (Device)。內核層指的是 kernel 對 USB 系統的支援,主控層對應到不同規格的 USB 主控器,連接 USB 設備時不必考慮主控器的規格,裝置層的設定,依裝置類型會有所不同。

Linux USB 驅動程式共有三種不同的 USB 主控制器選項,因為在主板和 PCI 卡上有三種不同類型的 USB 控制晶片。

  1. EHCI (ehci-hcd.o) :USB 2.0 協定的晶片。
  2. OHCI (usb-ohci.o) :非 PC 系統上的(以及帶有 SiS 和 ALi 晶片組的 PC 主板上的)USB 晶片。
  3. UHCI (usb-uhci.o) :大部份 PC 主機板(包括 Intel 和 Via)。

在 Linux 下可查詢 /proc/pci 所記錄的 PCI 子系統資源配置情況,或指令 lspci,從中分辦出 USB 主控器屬於那種規格,只需載入 USB 類型對應的 ?HCI 驅動程式即可,若單獨載入 EHCI 不行,則根據主板類型載入UHCI 或 OHCI 後,再載入EHCI。

使用 usbmodules 指令可查詢己連接至系統的 USB 裝置有那些可以使用的核心驅動模組,在載入/卸載核心模組會利用到 usbmodules 程式,利用 hotplug 或 usbmgr 程式可以在 USB 裝置與電腦連接/移除時,自動載入/卸載核心模組、執行相關 Scripts。

Linux 相關的指令和檔案:

mount none /proc/bus/usb -t usbdevfs
usbmodules
hotplug
usbmgr
/etc/usbmgr/
/etc/hotplug/

Linux 對應USB設備一些常用必要的驅動程式模組:
usbcore.o:支援usb所需要的最基礎模組。
usb-uhci.o / usb-ohci.o / ehci-hcd.o:USB 控制晶片驅動程式。
uhci.o :另一個uhci驅動程式,一般不需載入,可能會當機。
hid.o:USB人機界面設備,如滑鼠、鍵盤。
usbmouse.o:USB滑鼠(還需再載入mousedev.o)。
usbkbd.o:USB鍵盤(還需再載入keybdev.o)。
usb-storage.o:USB 存儲設備,Flash Disk 等。
usbnet.o:USB並聯線,讓兩部電腦資料透過USB傳輸。


Linux 相關驅動程式模組:

ide-disk.o :IDE硬碟。
ide-scsi.o :把IDE設備類比SCSI介面。
scsi_mod.o:SCSI 裝置。
sd_mod.o:SCSI硬碟。
sr_mod.o:SCSI光碟機。
sg.o:SCSI 一般裝置,在某些 Flash Disk、SCSI裝置偵測中會使用到。


Linux 使用 Flash Disk 需要載入的模組:

1.usbcore
2.usb-uhci / usb-ohci / ehci-hcd
3.scsi_mod
4.sd_mod
5.usb-storage

2007年5月18日 星期五

建置 uClibc 開發環境

uClibc是嵌入式Linux作業系統系統的C語言程式庫,可以在標準的 Linux 或沒有記憶體管理單元的Linux系統,如uCLinux。uClibc比GNU的C語言程式庫小的多,幾乎所有被glibc支援的應用程式都可以順利的移植過去,由 glibc 移植到 uClibc 只需重新編譯程式碼,目前處理器平台有 i386、i960、h8300、m68k、mips/mipsel、PowerPC、SH、SPARC及v850處理機。

安裝及設定 uClibc 的環境有點麻煩,好在uClibc 提供了root_fs image,如果不是很堅持一定要自己建置開發環境,可以由官方網站直接下載使用。

步驟如下:

1.Download root_fs_i386.bz2 from uclibc.org http://www.uclibc.org/downloads/
2.bunzip2 root_fs_i386.bz2
3.mkdir root_fs
4.su root
5.mount -o loop root_fs_i386 root_fs
6.chroot root_fs /bin/su -

2007年5月7日 星期一

如何解決 /var/spool/cilentmqueue 中有大量檔案無法刪除

/var/spool/clientmqueue 目錄是 smmsp:smmsp 使用者目錄,僅用於郵件的收受與傳遞,增加這個使用者是 sendmail 8.12 後新增,主要的目的在於提供更安全的 sendmail 使用環境。啟動Sendmail 程式之前,client 端寄出的信件會暫存到/var/spool/clientmqueue 中,因此如果系統沒有啟動 sendmail 時,/var/spool/clientmqueue 下所產生的檔案時間久了會灌爆系統的硬碟空間。

Unix系統預設有可用的MTA,將 sendmail完全停用而又不安裝其他 MTA 會導致非常多的問題,一些應用程式也會透過 email 傳送程式執行結果或通知,例如 crond。

出現這個問題主要在於系統沒有可用的 MTA,最大的原因是把系統的 MTA (例如:sendmail) 關閉了,卻沒有作適當的設定。如果是為了安全上的考量關閉 sendmail,可以使用限制連線的設定,而不要關閉 sendmail 比較好。

刪除 /var/spool/cilentmqueue 目錄中檔案的方法,可以使用

rm -rf /var/spool/cilentmqueue/*

有時因為 /var/spool/cilentmqueue 下檔案數量太多,而造成無法刪除,可以使用先刪除整個目錄再重建目錄

rm -rf /var/spool/cilentmqueue

mkdir /var/spool/cilentmqueue

chown smmsp.smmsp /var/spool/cilentmqueue

若是想保留之前應用程式發送的email訊息,可以將sendmail 啟動,sendmail 會自動處理/var/spool/cilentmqueue 未送出的email,處理完後/var/spool/cilentmqueue 自然清空。

2007年5月1日 星期二

Mysql 函式 current_user() 及 USER()、SYSTEM_USER()、SESSION_USER() 差異

Mysql 函式 current_user() 及 USER()、SYSTEM_USER()、SESSION_USER() 有何差異,以下是文件的定義說明:

  1. USER()、SYSTEM_USER()、SESSION_USER() 傳回目前 MySQL 使用者名稱,在 MySQL 3.22.11 或更新的版本中,傳回值包含使用者名稱和客戶機的主機名稱。
  2. CURRENT_USER() 傳回目前連線帳號被驗証的使用者名稱。


使用下面的範例就可以很快的瞭解之間的差異
1.先建立一個測試用的帳號
CREATE USER 'user'@ '%' IDENTIFIED BY 'user';

2.使用建立的帳號由不同的機器連線

由本機連線結果

由另一部機器連線結果

由以上實驗結果可以發現current_user() 不會因為不同連線機器的結果而不同,USER()、SYSTEM_USER()、SESSION_USER() 會因不同連線機器有所差異。


應用:

Q1.取出目前連線的使用者帳號?

A1.SELECT SUBSTRING_INDEX(USER(),"@",1); 或 SELECT SUBSTRING_INDEX(CURRENT_USER(),"@",1);

Q2.取出目前連線的主機名稱?

A2.SELECT SUBSTRING_INDEX(USER(),"@",-1);

2007年4月27日 星期五

IE 有時會出現 "無法開啟網際網路 操作已終止"

我的 IE 有問題為什麼某些特定的網站一直無法瀏覽,明明瀏覽的網頁沒有問題,為什麼別人的沒有問題,偏偏我的IE有問題,不是出現

就是

按下確定後,當然是出現下面的畫面

是中毒、木馬、間諜程式嗎,還是系統出問題了,換了好幾個掃毒軟體,已經掃了N遍還是無法解決問題,是不是只剩重新安裝系統而已?

在發生這個問題時,可以先檢查一下是不是所安裝的 Google Toolbar、MSN Search ToolBar 等第三方瀏覽器延伸軟體在作怪。

可以先將這類的軟體暫時停用,再使用瀏覽器重新瀏覽看看,如果是的話就將它移除或停用即可解決問題。

停用方法如下

IE->工具->網際網路選項->進階->啟用第三方瀏覽器延伸(需要重新啟動) 取消,記得重新啟動瀏覽器才會生效

2007年4月24日 星期二

Windows 平台執行遠端 X 應用軟體(Secure X Windows with SSH)

以往想在 Windows 平台上執行 遠端 X 應用程式,必須在 Windows 上安裝 CygwinX-Win32Xmanager 等 X 伺服軟體,不是要錢就是設定繁複,而且常是忙了老半天,最後還是一無所獲,若是遠端的 X 主機因防火牆的關係只開放 SSH 連線,那設定起來更是麻煩的不得了,現在只要使用 Xming X Server for Windows 加上 PuTTY 即可輕輕鬆鬆連上遠端主機執行 X 應用程式。

案例環境說明:

1.使用 Windows XP 平台執行遠端 X 應用程式。

2.欲執行的 X 應用程式所在主機只能透過 SSH 登入主機執行程式。

方法步驟:

1.下載安裝 Xming 及 Xming-portable-PuTTY,下載點 Xming 官方網站 http://sourceforge.net/projects/xming/

2.執行 Xming,執行後會在工作列出現 Xming 圖示。

3.使用 PuTTy 登入工作站,連線前先勾選 X11 forwarding。

4.登入遠端主機後直接執行 X 應用程式執可。

其他關於 Xming 的操作設定方法見 http://sourceforge.net/projects/xming/

PHP程式使用 Windows Server AD 認證身份

Windows Server AD 說穿了就是一個 LADP 伺服器,可讓您將資訊儲存在目錄服務中,在資料庫中進行查詢,並可以使用他來作為身份的認證授權。

使用PHP撰寫程式難免會遇到需要作身份認證的問題,除了自行撰寫這部份程式的選擇外,PHP 的函式庫中亦提供了標準的 LDAP 函式,如果公司組織中已經有架設 Windows 2K/2003 網域的環境 ,將身份認證的工作交由 Windows AD 亦是一個不錯的選擇。

案例環境說明:
1.公司組織內有一個Windows 網域,名稱為: domain.com。
2.domain.com 的網域有兩部網域主控站(DC)分別為:dc.domain.com、dc2.domain.com。
3.PHP版本:5.1.4

PHP程式碼範例:
以下的程式範例為精簡版,帳號和密碼不可為空的
<?php

$domain = 'domain.com'; //設定網域名稱
$user = 'user'; //設定欲認證的帳號名稱
$password = 'password'; //設定欲認證的帳號密碼
$dn = "dc=domain,dc=com";

// 使用 ldap bind 
$ldaprdn = $user . '@' . $domain; // ldap rdn or dn 
$ldappass = $password; // 設定密碼

// 連接至網域控制站
$ldapconn = ldap_connect($domain) or die("無法連接至 $domain");

// 如果要特別指定某一部網域主控站(DC)來作認證則上面改寫為
// $ldapconn = ldap_connect('dc.domain.com) or die("無法連接至 dc.domain.com"); 
// 或 
// $ldapconn = ldap_connect('dc2.domain.com)or die("無法連接至 dc2.domain.com"); 

//以下兩行務必加上,否則 Windows AD 無法在不指定 OU 下,作搜尋的動作
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);

if ($ldapconn) { // binding to ldap server 
    $ldapbind = @ldap_bind($ldapconn, $ldaprdn, $ldappass); 
    // verify binding 
    if ($ldapbind) { 
        $filter = "(sAMAccountName=$user)";
        $result = @ldap_search($ldapconn, $dn, $filter);

        if($result==false) echo "認證失敗";
        else {
            echo "認證成功..."; 
            //取出帳號的所有資訊
             $entries = ldap_get_entries($ldapconn, $result); 
        }
    } else { 
        echo "認證失敗..."; 
    } 
} 
?>