Skip to content

Commit a722f9c

Browse files
authored
Merge pull request #792 from berryzplus/feature/workaround_for_issue398
Feature/workaround for issue398
2 parents 8087f26 + b32afa2 commit a722f9c

File tree

9 files changed

+213
-688
lines changed

9 files changed

+213
-688
lines changed

sakura_core/parse/CWordParse.cpp

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,202 @@ bool CWordParse::SearchNextWordPosition4KW(
308308
}
309309
return false;
310310
}
311+
312+
//! wcがasciiなら0-127のまま返す。それ以外は0を返す。
313+
uchar_t wc_to_c(wchar_t wc)
314+
{
315+
#if 0
316+
//! wcがSJIS1バイト文字ならcharに変換して0~255を返す。SJIS2バイト文字なら0を返す。
317+
char buf[3]={0,0,0};
318+
int ret=wctomb(buf,wc);
319+
if(ret==-1)return 0; //エラー
320+
if(buf[1]!=0)return 0; //エラー扱い
321+
return buf[0] <= 0x7F ? buf[0]: 0; //1バイトで表せたので、これを返す 2011.12.17 バッファオーバーランの修正
322+
#endif
323+
// 2011.12.15 wctombを使わない版
324+
if(wc <= 0x7F){
325+
return (uchar_t)wc;
326+
}
327+
return 0;
328+
}
329+
330+
//@@@ 2002.01.24 Start by MIK
331+
/*!
332+
文字列がURLかどうかを検査する。
333+
334+
@retval TRUE URLである
335+
@retval FALSE URLでない
336+
337+
@note 関数内に定義したテーブルは必ず static const 宣言にすること(性能に影響します)。
338+
url_char の値は url_table の配列番号+1 になっています。
339+
新しい URL を追加する場合は #define 値を修正してください。
340+
url_table は頭文字がアルファベット順になるように並べてください。
341+
342+
2007.10.23 kobake UNICODE対応。//$ wchar_t専用のテーブル(または判定ルーチン)を用意したほうが効率は上がるはずです。
343+
*/
344+
BOOL IsURL(
345+
const wchar_t* pszLine, //!< [in] 文字列
346+
int offset, //!< [in] 検査を開始する位置。
347+
int nLineLen, //!< [in] 文字列の長さ
348+
int* pnMatchLen //!< [out] URLの長さ。offset からの距離。
349+
)
350+
{
351+
struct _url_table_t {
352+
wchar_t name[12];
353+
int length;
354+
bool is_mail;
355+
};
356+
static const struct _url_table_t url_table[] = {
357+
/* アルファベット順 */
358+
{ L"file://", 7, false }, /* 1 */
359+
{ L"ftp://", 6, false }, /* 2 */
360+
{ L"gopher://", 9, false }, /* 3 */
361+
{ L"http://", 7, false }, /* 4 */
362+
{ L"https://", 8, false }, /* 5 */
363+
{ L"mailto:", 7, true }, /* 6 */
364+
{ L"news:", 5, false }, /* 7 */
365+
{ L"nntp://", 7, false }, /* 8 */
366+
{ L"prospero://", 11, false }, /* 9 */
367+
{ L"telnet://", 9, false }, /* 10 */
368+
{ L"tp://", 5, false }, /* 11 */ //2004.02.02
369+
{ L"ttp://", 6, false }, /* 12 */ //2004.02.02
370+
{ L"wais://", 7, false }, /* 13 */
371+
{ L"{", 0, false } /* 14 */ /* '{' is 'z'+1 : terminate */
372+
};
373+
374+
/* テーブルの保守性を高めるための定義 */
375+
const char urF = 1;
376+
const char urG = 3;
377+
const char urH = 4;
378+
const char urM = 6;
379+
const char urN = 7;
380+
const char urP = 9;
381+
const char urT = 10;
382+
const char urW = 13; //2004.02.02
383+
384+
static const char url_char[] = {
385+
/* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
386+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +00: */
387+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +10: */
388+
0, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, /* +20: " !"#$%&'()*+,-./" */
389+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, /* +30: "0123456789:;<=>?" */
390+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +40: "@ABCDEFGHIJKLMNO" */
391+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, /* +50: "PQRSTUVWXYZ[\]^_" */
392+
0, -1, -1, -1, -1, -1,urF,urG,urH, -1, -1, -1, -1,urM,urN, -1, /* +60: "`abcdefghijklmno" */
393+
urP, -1, -1, -1,urT, -1, -1,urW, -1, -1, -1, 0, 0, 0, -1, 0, /* +70: "pqrstuvwxyz{|}~ " */
394+
/* あと128バイト犠牲にすればif文を2箇所削除できる */
395+
/* 0 : not url char
396+
* -1 : url char
397+
* other: url head char --> url_table array number + 1
398+
*/
399+
};
400+
401+
const wchar_t * const begin = pszLine + offset;
402+
const wchar_t * const end = pszLine + nLineLen;
403+
const struct _url_table_t *urlp;
404+
int i;
405+
406+
if( wc_to_c(*begin)==0 ) return FALSE; /* 2バイト文字 */
407+
if( 0 < url_char[wc_to_c(*begin)] ){ /* URL開始文字 */
408+
for(urlp = &url_table[url_char[wc_to_c(*begin)]-1]; urlp->name[0] == wc_to_c(*begin); urlp++){ /* URLテーブルを探索 */
409+
if( (urlp->length <= end - begin) && (auto_memcmp(urlp->name, begin, urlp->length) == 0) ){ /* URLヘッダは一致した */
410+
if( urlp->is_mail ){ /* メール専用の解析へ */
411+
if( IsMailAddress(begin, urlp->length, end - begin - urlp->length, pnMatchLen) ){
412+
*pnMatchLen = *pnMatchLen + urlp->length;
413+
return TRUE;
414+
}
415+
return FALSE;
416+
}
417+
for(i = urlp->length; i < end - begin; i++){ /* 通常の解析へ */
418+
if( wc_to_c(begin[i])==0 || (!(url_char[wc_to_c(begin[i])])) ) break; /* 終端に達した */
419+
}
420+
if( i == urlp->length ) return FALSE; /* URLヘッダだけ */
421+
*pnMatchLen = i;
422+
return TRUE;
423+
}
424+
}
425+
}
426+
return IsMailAddress(pszLine, offset, nLineLen, pnMatchLen);
427+
}
428+
429+
/* 現在位置がメールアドレスならば、NULL以外と、その長さを返す
430+
@date 2016.04.27 記号類を許可
431+
*/
432+
BOOL IsMailAddress( const wchar_t* pszBuf, int offset, int nBufLen, int* pnAddressLenfth )
433+
{
434+
struct {
435+
bool operator()(const wchar_t ch)
436+
{
437+
return 0x21 <= ch && ch <= 0x7E && NULL == wcschr(L"\"(),:;<>@[\\]", ch);
438+
}
439+
} IsValidChar;
440+
441+
/*
442+
直前の文字を利用した境界判定
443+
*/
444+
if (0 < offset && IsValidChar(pszBuf[offset-1])) {
445+
return FALSE;
446+
}
447+
448+
pszBuf += offset;
449+
nBufLen -= offset;
450+
offset = 0;
451+
452+
int j;
453+
int nDotCount;
454+
int nBgn;
455+
456+
457+
j = 0;
458+
if(pszBuf[j] != L'.' && IsValidChar(pszBuf[j])){
459+
j++;
460+
}else{
461+
return FALSE;
462+
}
463+
while( j < nBufLen - 2 && IsValidChar(pszBuf[j]) ){
464+
j++;
465+
}
466+
if( j == 0 || j >= nBufLen - 2 ){
467+
return FALSE;
468+
}
469+
if( L'@' != pszBuf[j] ){
470+
return FALSE;
471+
}
472+
// nAtPos = j;
473+
j++;
474+
nDotCount = 0;
475+
// nAlphaCount = 0;
476+
477+
478+
for (;;) {
479+
nBgn = j;
480+
while( j < nBufLen &&
481+
(
482+
(pszBuf[j] >= L'a' && pszBuf[j] <= L'z')
483+
|| (pszBuf[j] >= L'A' && pszBuf[j] <= L'Z')
484+
|| (pszBuf[j] >= L'0' && pszBuf[j] <= L'9')
485+
|| (pszBuf[j] == L'-')
486+
|| (pszBuf[j] == L'_')
487+
)
488+
){
489+
j++;
490+
}
491+
if( 0 == j - nBgn ){
492+
return FALSE;
493+
}
494+
if( L'.' != pszBuf[j] ){
495+
if( 0 == nDotCount ){
496+
return FALSE;
497+
}else{
498+
break;
499+
}
500+
}else{
501+
nDotCount++;
502+
j++;
503+
}
504+
}
505+
if( NULL != pnAddressLenfth ){
506+
*pnAddressLenfth = j;
507+
}
508+
return TRUE;
509+
}

sakura_core/parse/CWordParse.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,19 @@ class CWordParse{
125125
static bool _match_charlist( const WCHAR c, const WCHAR *pszList );
126126
};
127127

128+
BOOL IsURL( const wchar_t* psz, int offset, int length, int* outLength);/* offset 引数の追加により境界判定が行える高速版 */
129+
inline
130+
BOOL IsURL( const wchar_t* psz, int length, int* outLength) /* 指定アドレスがURLの先頭ならばTRUEとその長さを返す。高速版の追加により obsolete. */
131+
{
132+
return IsURL(psz, 0, length, outLength);
133+
}
134+
BOOL IsMailAddress( const wchar_t* psz, int offset, int length, int* outLength); /* offset 引数の追加により境界判定が行える高速版 */
135+
inline
136+
BOOL IsMailAddress( const wchar_t* psz, int length, int* outLength) /* 現在位置がメールアドレスならば、NULL以外と、その長さを返す。高速版の追加により obsolete. */
137+
{
138+
return IsMailAddress(psz, 0, length, outLength);
139+
}
140+
128141
// ACHAR 版
129142
inline bool CWordParse::_match_charlist( const ACHAR c, const ACHAR *pszList )
130143
{

0 commit comments

Comments
 (0)