#if FNMATCH_TEST
#include <stdio.h>
#include <stdlib.h>
#else
#include "includes.h"
#endif
static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern,
const smb_ucs2_t *string,
BOOL case_sensitive)
{
const smb_ucs2_t *p = pattern, *n = string;
smb_ucs2_t c;
if (strcmp_wa(p, "?")==0 && strcmp_wa(n, ".")) goto match;
while ((c = *p++)) {
switch (c) {
case UCS2_CHAR('.'):
if (! *n) goto next;
if (*n != UCS2_CHAR('.')) goto nomatch;
n++;
break;
case UCS2_CHAR('?'):
if (! *n) goto next;
if ((*n == UCS2_CHAR('.') &&
n[1] != UCS2_CHAR('.')) || ! *n)
goto next;
n++;
break;
case UCS2_CHAR('>'):
if (! *n) goto next;
if (n[0] == UCS2_CHAR('.')) {
if (! n[1] && ms_fnmatch_lanman_core(p, n+1, case_sensitive) == 0) goto match;
if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
goto nomatch;
}
n++;
break;
case UCS2_CHAR('*'):
if (! *n) goto next;
if (! *p) goto match;
for (; *n; n++) {
if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
}
break;
case UCS2_CHAR('<'):
for (; *n; n++) {
if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
if (*n == UCS2_CHAR('.') &&
!strchr_w(n+1,UCS2_CHAR('.'))) {
n++;
break;
}
}
break;
case UCS2_CHAR('"'):
if (*n == 0 && ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
if (*n != UCS2_CHAR('.')) goto nomatch;
n++;
break;
default:
if (case_sensitive) {
if (c != *n) goto nomatch;
} else {
if (tolower_w(c) != tolower_w(*n)) goto nomatch;
}
n++;
}
}
if (! *n) goto match;
nomatch:
return -1;
next:
if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match;
goto nomatch;
match:
return 0;
}
static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern,
const smb_ucs2_t *string, BOOL case_sensitive)
{
if (!strpbrk_wa(pattern, "?*<>\"")) {
smb_ucs2_t s[] = {UCS2_CHAR('.'), 0};
if (strcmp_wa(string,"..") == 0) string = s;
return strcasecmp_w(pattern, string);
}
if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) {
smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0};
smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0};
return ms_fnmatch_lanman_core(pattern, dotdot, case_sensitive) &&
ms_fnmatch_lanman_core(pattern, dot, case_sensitive);
}
return ms_fnmatch_lanman_core(pattern, string, case_sensitive);
}
static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string,
int protocol, BOOL case_sensitive)
{
const smb_ucs2_t *p = pattern, *n = string;
smb_ucs2_t c;
if (protocol <= PROTOCOL_LANMAN2) {
return ms_fnmatch_lanman1(pattern, string, case_sensitive);
}
while ((c = *p++)) {
switch (c) {
case UCS2_CHAR('?'):
if (! *n) return -1;
n++;
break;
case UCS2_CHAR('>'):
if (n[0] == UCS2_CHAR('.')) {
if (! n[1] && ms_fnmatch_w(p, n+1, protocol, case_sensitive) == 0) return 0;
if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
return -1;
}
if (! *n) return ms_fnmatch_w(p, n, protocol, case_sensitive);
n++;
break;
case UCS2_CHAR('*'):
for (; *n; n++) {
if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
}
break;
case UCS2_CHAR('<'):
for (; *n; n++) {
if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) {
n++;
break;
}
}
break;
case UCS2_CHAR('"'):
if (*n == 0 && ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
if (*n != UCS2_CHAR('.')) return -1;
n++;
break;
default:
if (case_sensitive) {
if (c != *n) return -1;
} else {
if (tolower_w(c) != tolower_w(*n)) return -1;
}
n++;
}
}
if (! *n) return 0;
return -1;
}
int ms_fnmatch(const char *pattern, const char *string, int protocol,
BOOL case_senstive)
{
wpstring buffer_pattern, buffer_string;
int ret;
size_t size;
size = push_ucs2(NULL, buffer_pattern, pattern, sizeof(buffer_pattern), STR_TERMINATE);
if (size == (size_t)-1) {
return -1;
}
size = push_ucs2(NULL, buffer_string, string, sizeof(buffer_string), STR_TERMINATE);
if (size == (size_t)-1) {
return -1;
}
ret = ms_fnmatch_w(buffer_pattern, buffer_string, protocol, case_senstive);
DEBUG(10,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret));
return ret;
}
int gen_fnmatch(const char *pattern, const char *string)
{
return ms_fnmatch(pattern, string, PROTOCOL_NT1, True);
}