Archive for September, 2008


香港政府粵語拼音

From http://zh.wikipedia.org/wiki/%E9%A6%99%E6%B8%AF%E6%94%BF%E5%BA%9C%E7%B2%B5%E8%AA%9E%E6%8B%BC%E9%9F%B3

香港政府粵語拼音香港政府以英文字音拼寫中文(以粵語為準)的方法。在香港出生的人、街道、地方以及公共屋邨的名稱都是以這套方法來拼寫。由殖民地時代開始沿用至今。大多數香港人只懂得這一套粵語拼音。

出處

出處不詳,應沿自香港政府內部。生死註冊處、入境事務處、路政署等政府部門以此拼法分別為香港人名、地名和街名等定出對應的英文名稱。有不少人都見過當帶同初生嬰兒到入境事務處登記時,職員會從一本類似字典的書中將父母取的中文名字查出對應的英文拼法。

此拼音系統可能是為方便不諳粵語的英人而設,標音原則上以英文音模擬粵音,故拼音不能準確反映實際粵音(詳見下文)。因此,教育局考評局有「教育學院拼音方案系統」,供中小學教育工作者使用。然而教育學院拼音方案並無應用於人名、地名等教學以外的範疇。

常用拼法舉例

注意:因英文音與粵音的分別,同一拼法的例字實際粵語發音未必相同。粵音聲調亦會略去。同一中文字也可以有多於一種拼法。

香港政府拼法,粗體為聲母 例字
a(零聲母)
au(零聲母) 歐坳
ap(零聲母)
ba
bo 保寶波埔普佈怖
cha
chan 陳親
chai 柴仔
chak 澤擇
chau
chap 集插
che 輋車
chek
cheng
cheong 暢昌唱搶
cheuk
cheung 張長象
chi 志誌
chik 直值植殖積織
ching 呈青靜程
chiu 趙朝昭超
cho 草曹
choi 彩蔡
chong 創莊
choy
chuen 川全
chui 徐翠趣除
chuk 竹築捉濁
chun 進春震振珍真圳晉
chung 中松沖重頌鍾鐘
dai
dung
eu
fa
fai 輝暉
fan 範范繁分粉反飯
fat 發佛罰
fau
fei 飛非菲翡肥
fo 火貨
fong 方仿芳防舫訪房放
foo
fook
fu 夫富虎傅芙
fui
fuk
fung 鳳風豐馮
ha 下霞
hoi
hak
ham
hang 恆坑亨杏
hau 厚口侯喉
hay
hee
hei 喜熙戲希晞禧
heng
heung 香享
hi
hin 顯軒騫
hing 興慶卿兄
hip
hiu
ho 何浩好酷皓
hoi 海開愷凱
hok 鶴學
hon 漢韓瀚
hong 康慷糠
hop 合盒
how 巧考
hui 許虛去
hung 洪紅虹熊鴻孔
ip(零聲母) 葉頁
jo
ka 嘉加珈假價家稼嫁鎵
kai 啟佳溪
kam 金甘柑咁錦敢鑒監鑑
kap
kat 吉桔
kau 舊九教
kei 奇其基琪淇琦
keng
kent
keung 強鏹
ki 奇其基琪淇琦
kik
kim
kin 健堅
king 景京敬競境勁
kiu
ko
kok
kong
koo 古顧故辜
koon
ku
kuk
kung 功共
kwa
kwai 葵桂貴
kwan 關君珺軍
kwok 國郭
kwong 光廣
kwu
kwun 觀冠官管
lai 拉癩賴籟瀨酹落禮澧醴鱧蠡劙黎藜犁黧來麗儷厲勵癘礪糲蠣荔例栵隸捩
lam 藍籃林琳霖淋臨
lan
lap
lau 劉留
lee 李利莉
lei 梨鯉理
leung 梁良涼兩
lin
li
ling 凌靈另令零伶玲拎齡
liu 廖尿料
lo 路露羅
lok 樂洛落
long 朗郎廊
luen 聯亂
lui 女呂旅裡累雷蕾類
luk 六陸鹿錄碌轆
lung 隆窿龍籠嚨隴朧矓
ma 馬媽麻
mak 墨麥默勿物
man 曼慢漫謾問聞閩憫萬民文汶玟炆抆雯敏
mei 美未味尾娓眉媚
ming 明冥鳴
mok 莫膜
mui 梅每
na 那娜
nam
ng(輔音元音化) 吳午忤五伍
nga 雅啞
ngai 毅藝蟻矮
ngan 銀顏
ngar 雅啞
ngau
nin
nip
o(零聲母) 奧澳
oi(零聲母) 愛哀
on(零聲母) 安按
pak 白北百柏
ping 平萍蘋
po 保寶波埔普佈怖
poon 盤潘
pong 龐旁蚌
pui 佩珮配倍培陪蓓
pun 盤潘
sai 西細洗
san
sang
sha
shan 山珊姍
shi 施師獅時匙史屎屍試軾四思斯撕絲
shui 水睡瑞衰歲誰
shuk 叔淑熟粟屬宿縮
si 施師獅時匙史屎屍試軾四思斯撕絲
sin 先仙冼善
sing 升昇星醒聲
sit
so 蘇騷甦掃素嫂
sui 水睡瑞衰歲誰
suk 叔淑熟粟屬宿縮
sung 宋送鬆崇
sze 施師獅時匙史屎屍試軾四思斯撕絲
tai 大太戴
tin 田天填
ting 亭婷停霆
tsz 止芷紫致字祠慈梓
tuen 團屯
tung 彤童董懂東棟凍同銅統桶痛
tze 止芷紫致字祠慈梓
wa
wah
wai 慧惠韋偉瑋為衛圍胃畏
wan 溫搵灣彎還環雲尹運
wang 宏弘橫
wing 穎永詠泳詠榮
wo 禾和窩禍蝸
wong 黃王汪枉
wu 胡湖糊狐壺烏戶惡
wun 奐煥換媛緩豌碗
yan 茵欣恩因仁忍人印殷
yau 丘邱優休遊游悠由油柚
yee 怡義議儀異宜而以姒意
yeung 楊陽揚煬瘍仰羊洋烊蛘樣養讓釀央泱殃鞅怏氧
yi 怡義議儀異宜而以姒意
yim 嚴鹽驗厭懨艷豔炎閻閆焰掩
yin 胭妍研賢寅演現然言燕讌嬿宴煙彥諺廷筳
ying 影形認瑩螢營英應
yip 葉頁
yiu 姚要擾謠遙搖瑤
yu 宇俞愉瑜如茹余餘魚乳
yuen 淵鳶冤宛蜿鵷眢鴛蜎苑宛婉惋琬畹菀怨元刓完岏沅芫黿丸汍紈芄原嫄源螈騵員圓隕袁園猿轅爰媛援湲蝯緣櫞蝝懸縣沿鉛堧壖玄圜洹遠薳軟阮耎蝡蠕泫鉉願願炫眩衒媛援瑗院縣遠掾眴繯
yung 雍擁翁用容溶鎔蓉

問題

表音不準確

此方案可能為便英人讀出香港的人名、地名,故拼音以英語模擬粵音,拼音難免有變異和簡化。而粵音跟英文音有很多不同之處,也令拼音不能準確反映實際粵音。本文舉數例說明如下。

例子:

廣州話發音(粵音韻彙系統,粗體為聲母 香港政府拼法 原因
tsun Chan 以英文讀tsun,t音常給略去,變成”zun”。另外,英文裏z加un難於發音。改為Chan可能比tsun 在英文裏更易讀。
dai tai 粵音的d是清不送氣音,而英語中的d是濁不送氣音、t在字的開首時則是清送氣音。無論拼作dai或tai,都不能以英語準確讀出「大」的粵音。港府拼音可能參考威妥瑪拼音,以t表示不送氣清音[t]。另一可能tai是客家話讀法,而早期英人分不清客家話和粵語兩種方言。
tai tai 粵語「大」和「泰」發音不同,但以此拼法卻得出同一標音。
bou po 可能跟「大」的問題一樣,即是參考威妥瑪拼音以p表示不送氣清音[p]。
sa sha 粵音s 和sh 沒有分別(即是allophone),但英文卻非。

拼法不一致

  • 「邨」,有拼作 tsuen,亦有拼作 chuen
  • 「余」,有拼作 yu,亦有拼作 eu (例子:余仁生 [Eu Yan Seng])
  • 「元」,有拼作 yuen(例子:元朗 [Yuen Long]),亦有拼作 un(例子:元州邨 [Un Chau Estate])
  • 拼音 chai 同時是灣仔的「仔」字 [Wan Chai] 以及柴灣的「柴」字 [Chai Wan] 的拼音,但「仔」字和「柴」字的讀音並不相同。原因可能是「柴」字 [Ch'ai] 的[']被省去,「仔」的韻母[ɐi]卻 與[ai]混同。此問題可能也出於方便英文發音,因英人常誤將”tsai”讀成”zai”(即略去t音,見上文「陳」例)。位於香港島和新界西貢的兩個 「灣仔」原本均作”Wan Tsai”,但約於二十世紀初期,香港島的改作”Wan Chai”。政府或許意識到發音的差異,故改一個比較容易的發音。

應用

因為這套拼音只會用來轉寫專有名詞(人名、街道名、地方名等),所以一些常用但很少用在專有名詞中的字(如:)沒有什麼人知道他們的拼音,使得這套拼音不能如漢語拼音注音符號般用作普通的中文輸入法。關於粵語拼音的輸入法可參考粵語拼音輸入法

From http://www.php.net/manual/en/function.fread.php#84115

I couldn't get some of the previous resume scripts to work with Free Download Manager or Firefox. I did some clean up and modified the code a little.

Changes:
1. Added a Flag to specify if you want download to be resumable or not
2. Some error checking and data cleanup for invalid/multiple ranges based on http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
3. Always calculate a $seek_end even though the range specification says it could be empty... eg: bytes 500-/1234
4. Removed some Cache headers that didn't seem to be needed. (add back if you have problems)
5. Only send partial content header if downloading a piece of the file (IE workaround)

<?php

function dl_file_resumable($file, $is_resume=TRUE)
{
//First, see if the file exists
if (!is_file($file))
{
die(
"<b>404 File not found!</b>");
}

//Gather relevent info about file
$size = filesize($file);
$fileinfo = pathinfo($file);

//workaround for IE filename bug with multiple periods / multiple dots in filename
//that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
$filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ?
preg_replace('/\./', '%2e', $fileinfo['basename'], substr_count($fileinfo['basename'], '.') - 1) :
$fileinfo['basename'];

$file_extension = strtolower($path_info['extension']);

//This will set the Content-Type to the appropriate setting for the file
switch($file_extension)
{
case
'exe': $ctype='application/octet-stream'; break;
case
'zip': $ctype='application/zip'; break;
case
'mp3': $ctype='audio/mpeg'; break;
case
'mpg': $ctype='video/mpeg'; break;
case
'avi': $ctype='video/x-msvideo'; break;
default:
$ctype='application/force-download';
}

//check if http_range is sent by browser (or download manager)
if($is_resume && isset($_SERVER['HTTP_RANGE']))
{
list(
$size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);

if ($size_unit == 'bytes')
{
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else
{
$range = '';
}
}
else
{
$range = '';
}

//figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);

//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)),($size - 1));
$seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);

//add headers if resumable
if ($is_resume)
{
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($size - 1))
{
header('HTTP/1.1 206 Partial Content');
}

header('Accept-Ranges: bytes');
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size);
}

//headers for IE Bugs (is this necessary?)
//header("Cache-Control: cache, must-revalidate");
//header("Pragma: public");

header('Content-Type: ' . $ctype);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: '.($seek_end - $seek_start + 1));

//open the file
$fp = fopen($file, 'rb');
//seek to start of missing part
fseek($fp, $seek_start);

//start buffered download
while(!feof($fp))
{
//reset time limit for big files
set_time_limit(0);
print(
fread($fp, 1024*8));
flush();
ob_flush();
}

fclose($fp);
exit;
}

?>

From http://support.microsoft.com/default.aspx?kbid=184988

function loadTOCNode(){}

Article ID : 184988
Last Review : January 22, 2007
Revision : 3.1
This article was previously published under Q184988
Novice: Requires knowledge of the user interface on single-user computers.

SYMPTOMS

loadTOCNode(1, ‘symptoms’);

When you try to open a database or an object in a database, or when you try to compact a database, you may receive one of the following error messages:

Selected collating sequence not supported by the operating system.
Invalid collating sequence.
Unrecognized database format ‘<pathname>\<filename>’.

CAUSE

loadTOCNode(1, ’cause’);

One of the following conditions is true:

You are trying to open a database or an object in a database that was created in another language edition of Microsoft Access.
You are trying to open a database that was created or compacted while the New Database Sort Order was set to a value other than General.

To check the setting of the New Database Sort Order, follow these steps:

1. Open an existing database that was not created or compacted while the Sort Order was set to a value other than General. For example, open the sample database Northwind.mdb.
2. On the Tools menu, click Options, and then click the General tab.
3. Make sure that the New Database Sort Order is set to General and then click OK.If you are receiving the errors described in the “Symptoms” section, setting the New Database Sort Order back to General does not resolve the problem; however, it prevents the problem from occurring with new databases.

RESOLUTION

loadTOCNode(1, ‘resolution’);

Install or enable multilanguage support for your operating system.NOTE: Even if you install multilanguage support, you cannot open a database if it requires a code page that is not supported by your operating system. For more information, please see the following article in the Microsoft Knowledge Base:

142867 (http://support.microsoft.com/kb/142867/EN-US/) ACC: Mixing Language Editions of Microsoft Access and Windows

If the database was created in a language that uses a type of character set supported by your operating system, you can open the database after you have enabled support for multiple languages.

To install multilanguage support in Windows 95/98 or Windows NT, please follow the steps in one of the following articles in the Microsoft Knowledge Base:

141306 (http://support.microsoft.com/kb/141306/EN-US/) How to Enable Support for Multiple Languages in Windows

177561 (http://support.microsoft.com/kb/177561/EN-US/) HOWTO: Add and Enable Additional Languages in Windows NT

Note: This feature is included in the CD-ROM version of Windows 95, but not in the floppy disk version. If you are using the floppy disk version of Windows 95 and you want to enable multilanguage support, please see the following article in the Microsoft Knowledge Base:

135315 (http://support.microsoft.com/kb/135315/EN-US/) CD-ROM Extras for Microsoft Windows 95 Upgrade

REFERENCES

loadTOCNode(1, ‘references’);

For more information about mixing language editions of Microsoft Access and Windows, please see the following articles in the Microsoft Knowledge Base:140409 (http://support.microsoft.com/kb/140409/EN-US/) ACC: Code Pages (Character Sets) & How They Affect MS Access

133381 (http://support.microsoft.com/kb/133381/EN-US/) ACC: How the Windows Code Page Affects Sort Order


APPLIES TO
Microsoft Access 95 Standard Edition
Microsoft Access 97 Standard Edition

Keywords:
kberrmsg kbprb KB184988

“學無止境”翻譯

‘The more I learn, the more I learn how little I know.’ — Socrates
‘The more you know, the less you understand.’ — Lao-Tse (Tao Te Ching, The Book of the Way and its Virtue, 6th C. BC)
‘The more you learn, the more you know. The more you know, the more you forget. The more you forget, the less you know. So why bother to learn?’ — George Bernard Shaw
Confucius said: ‘To know that one knows what one knows, and to know that one doesn’t know what one doesn’t know, there lies true wisdom.’

From http://www.ibm.com/developerworks/java/library/wa-javascript.html

Level: Introductory

Shantanu Bhattacharya (shantanu@justawordaway.com), Chief consultant, Siemens Information Systems Limited

13 Jun 2006

Functional, or declarative, programming is a very powerful programming method and is gaining popularity in the software industry. This article introduces some of the relevant functional programming concepts, and provides examples to use those concepts effectively. The author explains how to write elegant code with JavaScript™, which can import constructs and features from functional programming.

Introduction

Functional programming languages have been in academia for quite some time, but historically they do not have extensive tools and libraries available. With the advent of Haskell in the .NET platform, functional programming is becoming more popular. Some traditional programming languages, such as C++ and JavaScript, import constructs and features from functional programming. In many cases, repetitive code in JavaScript leads to clumsy coding. You can avoid all that if you use functional programming. Also, you can write more elegantl callbacks with a functional programming style.

Functional programming
Functional programming describes only the operations to be performed on the inputs to the programs, without use of temporary variables to store intermediate results. The emphasis is to capture “what and why” rather than the “how.” It emphasizes the definition of functions rather than the implementation of state machines, in contrast to procedural programming, which emphasizes execution of sequential commands.

Large scale knowledge management applications benefit greatly from using a functional programming style as it simplifies development.

Because functional programming encompasses a very different way of composing programs, programmers who are used to the imperative paradigm can find it difficult to learn. In this article you’ll see examples of how to write good, elegant code in JavaScript in a functional style. I’ll discuss:

  • Functional programming concepts, including anonymous functions, different ways to call functions, and how to pass functions as arguments to other functions.
  • Use of functional concepts, with examples of: extending array sort; elegant code for dynamic HTML generation; and application of a sequence of functions.

Functional programming concepts

Many developers know how to code in languages where you specify the method of solving a problem by describing “how.” For example, to code a function to compute a factorial, I describe the program by coding a loop or using recursion to find the product of all the numbers. In both cases, the procedure for the computation is detailed in the program. Listing 1 shows possible C code for a factorial.
Listing 1. Factorial in procedural style

int factorial (int n)
{
  if (n <= 0)
    return 1;
  else
    return n * factorial (n-1);
}

Such languages are also called procedural programming languages because they define the procedure to solve the problem. Functional programming is markedly different from that philosophy. In functional programming, you need to describe the “what” of the problem. Functional programming languages are also called declarative. The same program computing factorial would be written as a product of all the numbers up to n. A typical functional program for a factorial looks like the example in Listing 2.
Listing 2. Factorial in functional style

factorial n, where n <= 0 	:= 1
factorial n    := foldr * 1 take n [1..]

The second statement instructs you to take a list of first n numbers starting from 1 (take n [1..]), then find their product with 1 as the identity. This definition does not have the loop, or recursion, as with the earlier case. It is like the mathematical definition of the factorial function. Once you know the meaning of the library functions (take and foldr), and the notation (list notation [ ]), it is very easy to code and also very readable.

You can write a routine to process each element of an n-ary tree using breadth-first or depth-first traversal, depending on a parameter, where the elements could be of any generic type, in just three lines of Miranda code.

Historically, functional programming languages have not been very popular for various reasons. Recently, however, a few of these languages are entering the computer industry. One example is Haskell in the .NET platform. In other cases, some of the existing languages borrow concepts from functional programming languages. Iterators and continuations show up in some implementations of C++ and some functional constructs provided in JavaScript. However, by borrowing functional constructs, the overall programming paradigm of the language does not change. JavaScript has not become a functional programming language because of the addition of the functional constructs.

I will now discuss the various niceties of the functional constructs in JavaScript, and ways to use them in our day-to-day coding and work. You’ll start with some basic capabilities, then use them to see some of the more interesting applications.

Anonymous functions

In JavaScript, you have the ability to write anonymous functions, or functions without a name. Why would you need that? Keep reading, but first you’ll learn how to write one. If you had the following JavaScript function:
Listing 3. A typical function

function sum(x,y,z) {
  return (x+y+z);
}

Then the corresponding anonymous function would look like:
Listing 4. An anonymous Function

function(x,y,z) {
  return (x+y+z);
}

To use it, you write the following:
Listing 5. Applying an anonymous function

var sum = function(x,y,z) {
  return (x+y+z);
}(1,2,3);
alert(sum);

Using functions as values

You could also use functions as values. You could have variables with functions as values assigned to them. In the last example, you could also do the following:
Listing 6. Using function assignment

var sum = function(x,y,z) {
  return (x+y+z);
}
alert(sum(1,2,3));

In the example in Listing 6 above, the variable sum is assigned the function definition itself. Therefore, sum is a function and called anywhere you want.

Different ways of calling functions

JavaScript allows you to call a function in two ways, as shown in Listings 7 and 8.
Listing 7. Typical function application

alert (“Hello, World!");

Or
Listing 8. Using function as an expression

(alert) (“Hello, World!");

Therefore you can also write the following:
Listing 9. Function application just after definition

( function(x,y,z) { return (x+y+z) } ) (1, 2, 3);

You might write a function expression in parentheses and then pass arguments to get them evaluated. Though in the example in Listing 8, with a function name directly enclosed in parentheses, this need not be the case while using it as shown in Listing 9.

Passing functions as arguments to other functions

You can also pass functions as argument to other functions. Though this is not a new concept, it is used in the subsequent examples extensively. You can pass function arguments as shown in Listing 10.
Listing 10. Passing function as a parameter and applying it

var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };

var sum = function(x,y,z) {
  return x+y+z;
};

alert( passFunAndApply(sum,3,4,5) ); // 12

Execution of the last alert statement prints the value 12.

Using functional concepts

The previous section showed some programming concepts using the functional style. The examples are by no means complete coverage of all the concepts, nor are they in any order of importance, but are the relevant concepts for this discussion. To quickly summarize, with the functional style in JavaScript:

  • Functions need not have names all the time.
  • Functions can be assigned to variables like other values.
  • A function expression cqn be written and enclosed in parentheses for application later.
  • Functions can be passed as arguments to other functions.

This section shows some examples of how you can use the concepts effectively to write good and elegant code in JavaScript. (Using a functional style of JavaScript, you can do many other things that are out of the scope of this discussion.)

Extending array sort
Let’s plan to write a sort method that can sort the array elements according to their date. Writing this is very simple in JavaScript. The sort method of array objects takes an optional parameter that is the comparison function. In this case, you need the comparison function in Listing 11.
Listing 11. Comparison function

function (x,y) {
	return x.date – y.date;
}

To get the required function, use the example in Listing 12.
Listing 12. Extension of the sort function

arr.sort( function (x,y) {	return x.date – y.date; } );

Where arr is an object of type array. This will sort all the objects in arr according to their respective dates. The comparison function, along with its definition, is passed to the sort function to complete the sort operation. With this function:

  • Each JavaScript object has a date property.
  • The sort function of array type in JavaScript takes an optional parameter, which is the comparison function used for sorting. This is similar to the qsort function in the C library.
Elegant code for dynamic HTML generation
In this example, you’ll see how to write elegant code to generate dynamic HTML from arrays. You can generate tables from the values obtained from an array. Or, you might generate ordered and unordered lists using the contents of an array. You can also generate vertical or horizontal menu items.The coding style in Listing 13 is commonly used to generate dynamic HTML from arrays.
Listing 13. Normal code for generating dynamic HTML

var str=' ';
for (var i=0;i<arr.length;i++) {
  var element=arr[i];
  str+=... HTML generation code...
}
document.write(str);

You can replace this code using the code in Listing 14.
Listing 14. Generic way of generating dynamic HTML

Array.prototype.fold=function(templateFn) {
  var len=this.length;
  var str=' ';
  for (var i=0 ; i<len ; i++)
	str+=templateFn(this[i]);
  return str;
}

function templateInstance(element) {
  return ... HTML generation code ...
}

document.write(arr.fold(templateInstance));

I’ve used the prototype property of Array type to define the new function fold. You can now use this function in any of the arrays that are defined later.

Application of a sequence of functions
Consider the case where you want to use a set of functions as the callback function. For this purpose you’ll use a window.setTimeout function, which has two parameters. The first parameter is the function to be called after the number of milliseconds indicated by the second parameter. Listing 15 shows one way to do this.
Listing 15. Calling a set of functions in a callback

window.setTimeout(function(){alert(‘First!’);alert(‘Second!’);}, 5000);

Listing 16 shows the more elegant way of doing it.
Listing 16. Elegant way of calling a sequence of functions

Function.prototype.sequence=function(g) {
  var f=this;
  return function() {
    f();g();
  }
};
function alertFrst() { alert(‘First!’); }
function alertSec() { alert(‘Second!’); }
setTimeout( alertFrst.sequence(alertSec), 5000);

You can also use an extension of the code in Listing 16 if you want to call one callback after calling another while handling an event. Perhaps that is an exercise for you to pursue, now that your interest is sparked.

Back to top

In conclusion

In many areas, you can apply functional programming concepts in JavaScript to accomplish day-to-day activities in an elegant way. The examples in this article show only a few of the cases. If you identify the right scenarios for functional programming, and apply the concepts, you’ll make a lot of sense and can increase your elegance level.
Resources

Learn

Get products and technologies

Discuss

About the author

Photo of Shantanu Bhattacharya Shantanu Bhattacharya has extensively designed and created architecture for application software for retail, system integration, and healthcare; networking software that’s SNMP-based, and TCP/IP stack; security software; a file system for India’s first supercomputer; and Real Time Software for the Indian Missile Program. Currently he is working in the healthcare industry for Siemens in Bangalore, India as a chief architect.

From http://www.phpbb.com/community/viewtopic.php?f=64&t=993475

Scenario:

I have one existing system with a “user” table. The key elements of this table:

UserID > Auto increment primary key
Email > varchar with unique constraint; this also acts as the login for the “website”
Password > varchar
IsActive > integer for storing user’s “active” status (null or 1)

I also have a fresh phpbb3 installation into which i need to integrate the website users.

I also have to create a list of categories and forums that match the structure of my main websites main categories and sub-categories – a 1 to 1 match. I will discuss this if necessary.

Additional task: I have to integrate the website’s interface elements into the phpbb theme. I used simple approach. I will probably not discuss it as there are very easy solutions already available.

Mapping:

Have to create mapping between the users inside the two tables. These will be referred as:

user (website users)
- and -
phpbb_user (phpbb users)

The question, how should I map website users onto phpbb users? There are many ways to do this. I chose the simplest one to implement. Map user.UserID to phpbb_users.user_id. This way a user can always be looked up into phpbb users and vice versa.

There is one problem however. PHPBB3 fresh installation creates about 50 users by default. These include the super administrator, anonymous and search bots. That means user_id 1 to 50 are unavailable.

I could have created 50 fake users in the user table so that any further website users can be mapped properly. However, I already had about 250+ users by the time integration was supposed to be made. So I chose to map by adding a constant – 1000. So:

Website user #1 becomes phpbb user #1001
Website user #2 becomes phpbb user #1002

and so on.

This way I don’t have to run any lookup queries when I have for find phpbb user given website user id and vice versa.

Drawback:

The process creates clones of website users inside phpbb. It should not go the other way round. So, before integration you should disable phpbb “registration”. You can do this from the phpbb admin section. When you do this, no new user can “register” him/herself. The registration should be done on the main website. Later in the discussion i will provide the hack for creating the user.

Next step is to write functions that ease the task of importing the users. While we are on it, it is also desirable to create another function that synchronizes information of existing users. For example, if someone changes his/her email address on the main website, we should have the mechanism that copies the change into the corresponding phpbb user record. These the fields I am interested in:

Email, Password, IsActive

There may be other fields too but in my scenario, there aren’t any. I am not storing persons age, date of birth, aim/icq information, location, work information etc. I’ll leave it on phpbb user control panel to allow user to edit phpbb related information.

Besides creating new users, the function must place the newly created user in registered users group. I also hacked into phpbb code to find out there are a few other things that are done when a user is created. Usually the default group settings are copied into the the user record.

Note: The way I am implementing the integration it is *not necessary* to create a clone of user into phpbb immediately upon registration although this is a good idea.

Next step is to write functions that ease the task of importing the users. While we are on it, it is also desirable to create another function that synchronizes information of existing users. For example, if someone changes his/her email address on the main website, we should have the mechanism that copies the change into the corresponding phpbb user record. These the fields I am interested in:

Email, Password, IsActive

There may be other fields too but in my scenario, there aren’t any. I am not storing persons age, date of birth, aim/icq information, location, work information etc. I’ll leave it on phpbb user control panel to allow user to edit phpbb related information.

Besides creating new users, the function must place the newly created user in registered users group. I also hacked into phpbb code to find out there are a few other things that are done when a user is created. Usually the default group settings are copied into the the user record.

Note: The way I am implementing the integration it is *not necessary* to create a clone of user into phpbb immediately upon registration although this is a good idea.

function phpbb_synchronize_user( $UserID, $Email, $Password, $IsActive )
{
global $cn1;
$message = array( );
$librium_default_group_id = 2;
static $phpbb_config;
static $group_config;
if ( is_array( $phpbb_config ) == false )
{
$phpbb_config = array( );
$query = "SELECT config_name, config_value FROM phpbb_config";
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
while ( $myrow = mysql_fetch_assoc( $ident ) )
{
$phpbb_config[ $myrow[ "config_name" ] ] = $myrow[ "config_value" ];
}
}
if ( is_array( $group_config ) == false )
{
$query = sprintf( "SELECT group_id, group_colour, group_rank, group_avatar, group_avatar_type, group_avatar_width, group_avatar_height FROM phpbb_groups WHERE group_id = %d", $librium_default_group_id );
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
$group_config = mysql_fetch_assoc( $ident );
}
$bbuser_newid = $UserID + 1000;
$bbuser_email = strtolower( $Email );
$bbuser_passw = $Password;
$bbuser_class = $IsActive ? 0 : 1;
$bbuser_login = $bbuser_email;
$bbuser_login = explode( "@", $bbuser_login );
$bbuser_login = $bbuser_login[ 0 ];
$bbuser_login = preg_replace( "/[^a-z0-9]/i", "", $bbuser_login );
$bbuser_login = $bbuser_login . $bbuser_newid;
$query = sprintf( "SELECT username, username_clean, user_type FROM phpbb_users WHERE user_id = %d", $bbuser_newid );
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
$myrow = mysql_fetch_assoc( $ident );
if ( $myrow === false )
{
$dataarray = array( );
$dataarray[ "user_id" ] = $bbuser_newid;
$dataarray[ "user_email" ] = $bbuser_email;
$dataarray[ "user_email_hash" ] = crc32( $bbuser_email ) . strlen( $bbuser_email );
$dataarray[ "user_password" ] = md5( $bbuser_passw );
$dataarray[ "username" ] = $bbuser_login;
$dataarray[ "username_clean" ] = $bbuser_login;
$dataarray[ "group_id" ] = $librium_default_group_id;
$dataarray[ "user_type" ] = $bbuser_class;
$dataarray[ "user_colour" ] = $group_config[ "group_colour" ];
$dataarray[ "user_rank" ] = $group_config[ "group_rank" ];
$dataarray[ "user_avatar" ] = $group_config[ "group_avatar" ];
$dataarray[ "user_avatar_type" ] = $group_config[ "group_avatar_type" ];
$dataarray[ "user_avatar_width" ] = $group_config[ "group_avatar_width" ];
$dataarray[ "user_avatar_height" ] = $group_config[ "group_avatar_height" ];
$dataarray[ "user_lang" ] = $phpbb_config[ "default_lang" ];
$dataarray[ "user_timezone" ] = $phpbb_config[ "board_timezone" ];
$dataarray[ "user_dst" ] = $phpbb_config[ "board_dst" ];
$dataarray[ "user_dateformat" ] = $phpbb_config[ "default_dateformat" ];
$dataarray[ "user_style" ] = $phpbb_config[ "default_style" ];
$dataarray[ "user_actkey" ] = "";
$dataarray[ "user_allow_massemail" ] = 1;
$dataarray[ "user_allow_pm" ] = 1;
$dataarray[ "user_allow_viewemail" ] = 1;
$dataarray[ "user_allow_viewonline" ] = 1;
$dataarray[ "user_emailtime" ] = 0;
$dataarray[ "user_full_folder" ] = -3;
$dataarray[ "user_inactive_reason" ] = $bbuser_class ? 3 : 0;
$dataarray[ "user_inactive_time" ] = $bbuser_class ? time( ) : 0;
$dataarray[ "user_interests" ] = "";
$dataarray[ "user_ip" ] = "";
$dataarray[ "user_last_privmsg" ] = 0;
$dataarray[ "user_lastmark" ] = time( );
$dataarray[ "user_lastpage" ] = "";
$dataarray[ "user_lastpost_time" ] = 0;
$dataarray[ "user_lastvisit" ] = 0;
$dataarray[ "user_message_rules" ] = 0;
$dataarray[ "user_new_privmsg" ] = 0;
$dataarray[ "user_notify" ] = 0;
$dataarray[ "user_notify_pm" ] = 1;
$dataarray[ "user_notify_type" ] = 0;
$dataarray[ "user_occ" ] = "";
$dataarray[ "user_options" ] = 895;
$dataarray[ "user_pass_convert" ] = 0;
$dataarray[ "user_permissions" ] = "";
$dataarray[ "user_posts" ] = 0;
$dataarray[ "user_sig" ] = "";
$dataarray[ "user_sig_bbcode_bitfield" ] = "";
$dataarray[ "user_sig_bbcode_uid" ] = "";
$dataarray[ "user_unread_privmsg" ] = 0;
$dataarray[ "user_regdate" ] = time( );
$dataarray[ "user_passchg" ] = time( );
$dataarray[ "user_form_salt" ] = substr( md5( microtime( ) ), 4, 16 );
$query = "";
foreach ( $dataarray as $column => $value )
{
if ( $query == "" )
{
$query .= "INSERT phpbb_users SET ";
}
else
{
$query .= ", ";
}
$query .= sprintf( "%s = '%s'", $column, addslashes( $value ) );
}
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
$message[ ] = sprintf( "Created user <b>%s</b>", rtext( $bbuser_login ) );
$query = sprintf( "
INSERT INTO phpbb_user_group
( group_id, user_id, group_leader, user_pending )
VALUES
( %d, %d, 0, 0 )
", $librium_default_group_id, $bbuser_newid
);
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
$message[ ] = "&rsaquo; Assigned user to registered users group";
}
else
{
$dataarray = array( );
$dataarray[ "user_email" ] = $bbuser_email;
$dataarray[ "user_email_hash" ] = crc32( $bbuser_email ) . strlen( $bbuser_email );
$dataarray[ "user_password" ] = md5( $bbuser_passw );
if ( $myrow[ "username" ] == "" || $myrow[ "username_clean" ] == "" )
{
$dataarray[ "username" ] = $bbuser_login;
$dataarray[ "username_clean" ] = $bbuser_login;
}
if ( $myrow[ "user_type" ] != $bbuser_class )
{
$dataarray[ "user_type" ] = $bbuser_class;
$dataarray[ "user_inactive_reason" ] = $bbuser_class ? 3 : 0;
$dataarray[ "user_inactive_time" ] = $bbuser_class ? time( ) : 0;
}
$query = "";
foreach ( $dataarray as $column => $value )
{
if ( $query == "" )
{
$query .= "UPDATE phpbb_users SET ";
}
else
{
$query .= ", ";
}
$query .= sprintf( "%s = '%s'", $column, addslashes( $value ) );
}
$query .= sprintf( " WHERE user_id = %d", $bbuser_newid );
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
if ( mysql_affected_rows( $cn1 ) )
{
$message[ ] = sprintf( "Updated user <b>%s</b>", rtext( $bbuser_login ) );
}
}
return implode( "<br>\n", $message );
}

Function description:

Input:

$UserID user id of the user (user = user of the website) whose clone is to be created or whose information is to be updated
$Email is the email address of the user
$Password is the email address of the user
$IsActive is the flag that states whether the user is active or not (1 or NULL)

Local variables:

global $cn1 is a valid, open mysql connection identifier. Its you job to do handle it. Replace with your mysql connection identifier.

$message is An array that will contain strings of information/debug info/whatever

$phpbb_config will contain information from phpbb_config table that will be used later.
$group_config will contain information from phpbb_groups table for group #2 – registered users. This information will be used later.

The above two are made static so that they are faster to fetch if you call the function in a loop (10,000 times for example)

$bbuser_newid contains the id that will be assigned to the new user. As discussed, I wont allow phpbb to generate user ids. Instead I’ll use my own to keep things simple. I just add 1000 to the $UserID.
$bbuser_email same as $Email except transformed – trimmed and lowercased
$bbuser_passw same as $Password
$bbuser_class more like a flag for checking if the user is active or not
$bbuser_login is a “generated” phpbb login name. The steps to create this “generated login” are up to you. I just extract the first part of email address, shave it clean and append the $bbuser_newid to make sure it is unique

Rest of the function is pretty simple. You check for the presence of a phpbb user based on the user id of the website user.

If not found then

  • prepare a phpbb user record (most of the process is copied from phpbb native function) and inert
  • assign this new user to registered users group

otherwise

  • update phpbb user email address, password, username (only in rare cases) and active status

How to use the function:

IMPORTING USER

Loop over all of your users and call the function:

$message = array( );
$query = "SELECT UserID, Email, Password, IsActive FROM user";
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
while ( $myrow = mysql_fetch_assoc( $ident ) )
{
$result = phpbb_synchronize_user( $myrow[ "UserID" ], $myrow[ "Email" ], $myrow[ "Password" ], $myrow[ "IsActive" ] );
if ( $result )
{
$message[ ] = $result;
}
}

UPON USER REGISTRATION

Call the function once, pass the ID of the newly inserted user and additional fields that you just stored in the database:

mysql_query( "INSERT INTO user YADA YADA", $cn1 ) or die( mysql_error( $cn1 ) );
$result = phpbb_synchronize_user( mysql_insert_id( $cn1 ), $_POST[ "Email" ], $_POST[ "Password" ], 1 );

UPON USER PROFILE UPDATE

Call the function once, pass the ID logged in user and additional fields that you just stored in the database:

mysql_query( "UPDATE user YADA YADA WHERE UserID = {$_SESSION["UserID"]}", $cn1 ) or die( mysql_error( $cn1 ) );
$result = phpbb_synchronize_user( $_SESSION[ "UserID" ], $_POST[ "Email" ], $_POST[ "Password" ], 1 );

Finally, Login:

I hacked into phpbb code and invented this solution for seamless login:

  • make sure user is logged in
  • synchronize information before phpbb login (optional… use it if you do not call the synchronize function frequently)
  • use phpbb functions to start a phpbb session

it kind of goes like this:

#
# since we are not storing phpbb username in the website user table
# we need to look it up
#

$query = sprintf(
“SELECT username FROM phpbb_users WHERE user_id = %d + 1000″,
$_SESSION[ "UserID" ]
);
$ident = mysql_query( $query, $cn1 ) or die( mysql_error( $cn1 ) );
$myrow = mysql_fetch_assoc( $ident );

if ( $myrow === false )
{
die( “PHPBB USER NOT FOUND” );
}

#
# phpbb init
#

define( “IN_PHPBB”, true );

$phpbb_root_path = “./bb/”;
$phpEx = substr( strrchr( __FILE__, “.” ), 1 );

require( $phpbb_root_path . “common.” . $phpEx );
require( $phpbb_root_path . “includes/functions_user.” . $phpEx );
require( $phpbb_root_path . “includes/functions_module.” . $phpEx );

$user->session_begin();

#
# hack that i used from phpbb code
#

$result = $auth->login( $myrow[ "username" ], $_SESSION[ "Password" ] );

if ( $result[ "status" ] == LOGIN_SUCCESS )
{
if ( defined( “IN_CHECK_BAN” ) && $result[ "user_row" ][ "user_type" ] != USER_FOUNDER )
{
return;
}
$successurl = $_GET[ "successurl" ];
if ( $successurl == “” )
{
$successurl = “/bb/”;
}
$successurl = reapply_sid( $successurl );
$successurl = str_replace( “&amp;”, “&”, $successurl );
header( “Location: $successurl” );
exit( 0 );
}
else
{
die( $result[ "error_msg" ] );
}

DynaBean And EL

org.apache.commons.beanutils.DynaBean And Expression Language

Referred to BeanUtils API Document, DynaBean has ‘get’ method which can not be used as the output in expression language. Since ‘get’ method in DynaBean is neither a correct Java Bean property method, nor java.util.Map ‘get’ method. And according to Expression Language, it could not be rendered properly.

Uploading Issue in PHP: Max Size

From PHP manual

post_max_size integer
Sets max size of post data allowed. This setting also affects file upload. To upload large files, this value must be larger than upload_max_filesize. If memory limit is enabled by your configure script, memory_limit also affects file uploading. Generally speaking, memory_limit should be larger than post_max_size . When an integer is used, the value is measured in bytes. Shorthand notation, as described in this FAQ, may also be used. If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty. This can be tracked in various ways, e.g. by passing the $_GET variable to the script processing the data, i.e. <form action=”edit.php?processed=1″>, and then checking if $_GET['processed'] is set.

Note: PHP allows shortcuts for bit values, including K (kilo), M (mega) and G (giga). PHP will do the conversions automatically if you use any of these. Be careful not to exceed the 32 bit signed integer limit (if you’re using 32bit versions) as it will cause your script to fail.

MySQL error 1017: errno: 24

From Re: Mysqldump error 1017: errno: 24 - help?
Yep, that seems to have done it, at least when I'm testing it.  I'm
pretty sure the problem is fixed, but the next couple of days of
automated backups will tell.

Thanks!

On Tue, 2005-01-11 at 00:43, Gleb Paharenko wrote:
> Hello.
>
> Try '--open-files-limit=8192' at least. Check the real value of
> open_file_limits with such statement:
>   show variables like '%open_f%';
>
> You can find some recommendations for SuSe Linux at:
>   http://dev.mysql.com/doc/mysql/en/Linux-post-install.html
>
> Mysql user <mysql@stripped> wrote:
> > Hi..
> >
> > I've got an ISP, and all of our customers have databases in our mysql
> > system.
> >
> > My backup command is:
> >
> > mysqldump --force --opt -A -pxxxxxxxx' | gzip -c >
> > /var/sqlbackup/mysqldump-`date +\%A`.sql.gz
> >
> > This has worked fine for some time.
> >
> > Now, however, I get an error message:
> >
> > mysqldump: Got error: 1017: Can't find file:
> > './usr_web22_1/invoices_va.frm' (errno: 24) when using LOCK TABLES
> >
> > On different runs, it reports different files, even right after
> > restarting mysqld.
> >
> > I've looked at the mysql documentation for this error; it's at
> > http://dev.mysql.com/doc/mysql/en/Not_enough_file_handles.html
> >
> > I've looked at the startup script, put in '--open-files-limit=1024',
> > restarted mysql, and the error is the same.
> >
> > I've looked at the table_cache and max_connections system variables,
> > which are 64 and 100, respectively.
> >
> > My question is: what should I do now?
> >
> > Since table_cache and max_connections are far less than 1024, do I
> > reduce them even further?
> > Is there something else I should be looking at?
> >
> > This is mysql-3.23.52-106 on SuSE Linux 8.1, running on a dual PIII
> > 866Mhz system, with 512M of ram and 1G of swap, on a RAID-1 pair of 17G
> > hard drives.
> >
> > Thanks!
> >
> >
>
>
> --
> For technical support contracts, goto https://order.mysql.com/?ref=ensita
> This email is sponsored by Ensita.NET http://www.ensita.net/
>    __  ___     ___ ____  __
>   /  |/  /_ __/ __/ __ \/ /    Gleb Paharenko
>  / /|_/ / // /\ \/ /_/ / /__   Gleb.Paharenko@stripped
> /_/  /_/\_, /___/\___\_\___/   MySQL AB / Ensita.NET
>        <___/   www.mysql.com
> 
Powered by WordPress. Theme: Motion by 85ideas.