00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "includes.h"
00029
00030 static int null_match(const smb_ucs2_t *p)
00031 {
00032 for (;*p;p++) {
00033 if (*p != UCS2_CHAR('*') &&
00034 *p != UCS2_CHAR('<') &&
00035 *p != UCS2_CHAR('"') &&
00036 *p != UCS2_CHAR('>')) return -1;
00037 }
00038 return 0;
00039 }
00040
00041
00042
00043
00044
00045
00046 struct max_n {
00047 const smb_ucs2_t *predot;
00048 const smb_ucs2_t *postdot;
00049 };
00050
00051
00052
00053
00054
00055
00056
00057 static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n,
00058 struct max_n *max_n, const smb_ucs2_t *ldot,
00059 BOOL is_case_sensitive)
00060 {
00061 smb_ucs2_t c;
00062 int i;
00063
00064 while ((c = *p++)) {
00065 switch (c) {
00066
00067 case UCS2_CHAR('*'):
00068 if (max_n->predot && max_n->predot <= n) {
00069 return null_match(p);
00070 }
00071 for (i=0; n[i]; i++) {
00072 if (ms_fnmatch_core(p, n+i, max_n+1, ldot, is_case_sensitive) == 0) {
00073 return 0;
00074 }
00075 }
00076 if (!max_n->predot || max_n->predot > n) max_n->predot = n;
00077 return null_match(p);
00078
00079
00080
00081
00082 case UCS2_CHAR('<'):
00083 if (max_n->predot && max_n->predot <= n) {
00084 return null_match(p);
00085 }
00086 if (max_n->postdot && max_n->postdot <= n && n <= ldot) {
00087 return -1;
00088 }
00089 for (i=0; n[i]; i++) {
00090 if (ms_fnmatch_core(p, n+i, max_n+1, ldot, is_case_sensitive) == 0) return 0;
00091 if (n+i == ldot) {
00092 if (ms_fnmatch_core(p, n+i+1, max_n+1, ldot, is_case_sensitive) == 0) return 0;
00093 if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n;
00094 return -1;
00095 }
00096 }
00097 if (!max_n->predot || max_n->predot > n) max_n->predot = n;
00098 return null_match(p);
00099
00100
00101 case UCS2_CHAR('?'):
00102 if (! *n) {
00103 return -1;
00104 }
00105 n++;
00106 break;
00107
00108
00109 case UCS2_CHAR('>'):
00110 if (n[0] == UCS2_CHAR('.')) {
00111 if (! n[1] && null_match(p) == 0) {
00112 return 0;
00113 }
00114 break;
00115 }
00116 if (! *n) return null_match(p);
00117 n++;
00118 break;
00119
00120 case UCS2_CHAR('"'):
00121 if (*n == 0 && null_match(p) == 0) {
00122 return 0;
00123 }
00124 if (*n != UCS2_CHAR('.')) return -1;
00125 n++;
00126 break;
00127
00128 default:
00129 if (c != *n) {
00130 if (is_case_sensitive) {
00131 return -1;
00132 }
00133 if (toupper_w(c) != toupper_w(*n)) {
00134 return -1;
00135 }
00136 }
00137 n++;
00138 break;
00139 }
00140 }
00141
00142 if (! *n) {
00143 return 0;
00144 }
00145
00146 return -1;
00147 }
00148
00149 int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern,
00150 BOOL is_case_sensitive)
00151 {
00152 wpstring p, s;
00153 int ret, count, i;
00154 struct max_n *max_n = NULL;
00155
00156 if (strcmp(string, "..") == 0) {
00157 string = ".";
00158 }
00159
00160 if (strpbrk(pattern, "<>*?\"") == NULL) {
00161
00162
00163 if (is_case_sensitive) {
00164 return strcmp(pattern, string);
00165 } else {
00166 return StrCaseCmp(pattern, string);
00167 }
00168 }
00169
00170 if (push_ucs2(NULL, p, pattern, sizeof(p), STR_TERMINATE) == (size_t)-1) {
00171
00172
00173 return -1;
00174 }
00175
00176 if (push_ucs2(NULL, s, string, sizeof(s), STR_TERMINATE) == (size_t)-1) {
00177
00178
00179 return -1;
00180 }
00181
00182 if (translate_pattern) {
00183
00184
00185
00186
00187
00188 for (i=0;p[i];i++) {
00189 if (p[i] == UCS2_CHAR('?')) {
00190 p[i] = UCS2_CHAR('>');
00191 } else if (p[i] == UCS2_CHAR('.') &&
00192 (p[i+1] == UCS2_CHAR('?') ||
00193 p[i+1] == UCS2_CHAR('*') ||
00194 p[i+1] == 0)) {
00195 p[i] = UCS2_CHAR('"');
00196 } else if (p[i] == UCS2_CHAR('*') && p[i+1] == UCS2_CHAR('.')) {
00197 p[i] = UCS2_CHAR('<');
00198 }
00199 }
00200 }
00201
00202 for (count=i=0;p[i];i++) {
00203 if (p[i] == UCS2_CHAR('*') || p[i] == UCS2_CHAR('<')) count++;
00204 }
00205
00206 if (count != 0) {
00207 max_n = SMB_CALLOC_ARRAY(struct max_n, count);
00208 if (!max_n) {
00209 return -1;
00210 }
00211 }
00212
00213 ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.')), is_case_sensitive);
00214
00215 if (max_n) {
00216 free(max_n);
00217 }
00218
00219 return ret;
00220 }
00221
00222
00223
00224 int gen_fnmatch(const char *pattern, const char *string)
00225 {
00226 return ms_fnmatch(pattern, string, PROTOCOL_NT1, False);
00227 }