private unsafe void FetchCacheControl(string s, bool forCache) {
//Initialize it
ResponseCacheControl control = new ResponseCacheControl();
if (forCache) {
CacheCacheControl = control;
}
else {
ResponseCacheControl = control;
}
if (s != null && s.Length != 0) {
fixed (char *sp = s) {
int len = s.Length;
for (int i = 0; i < len-4; ++i) {
if (sp[i] < ' ' || sp[i] >= 0x7F) {
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_cache_control_error, s));
//invalid format
return;
}
if (sp[i] == ' ' || sp[i] == ',') {
continue;
}
// These if-else are two logically identical blocks that differ only in the way of how text search is done.
// The text search is done differently for 32 and X-bits platforms.
// ATTN: You are responsible for keeping the rest of the logic in sync.
if (IntPtr.Size == 4) {
// We are on 32-bits platform
long *mask = (long*)&(sp[i]);
//making interested chars lowercase, others are ignored anyway
switch(*mask|LO) {
case _prox: if (i+16 > len) continue;
if ((*(mask+1)|LO) != _y_re || (*(mask+2)|LO) != _vali || (*(mask+3)|LO) != _date) continue;
control.ProxyRevalidate = true;
i+=15;
break;
case _publ: if (i+6 > len) return;
if ((*((int*)(mask+1))|LOI) != _ic) continue;
control.Public = true;
i+=5;
break;
case _priv: if (i+7 > len) return;
if ((*((int*)(mask+1))|LOI) != _at || (sp[i+6]|0x20) != 'e') continue;
control.Private = true;
i+=6;
// Check for a case: private = "name1,name2"
while (i < len && sp[i] == ' ') {++i;}
if (i >= len || sp[i] != '=') {--i;break;}
while (i < len && sp[++i] == ' ') {;}
if (i >= len || sp[i] != '\"') {--i;break;}
System.Collections.ArrayList privateList = new System.Collections.ArrayList();
++i;
while(i < len && sp[i] != '\"') {
while (i < len && sp[i] == ' ') {++i;}
int start = i;
while (i < len && sp[i] != ' ' && sp[i] != ',' && sp[i] != '\"') {++i;}
if (start != i) {
privateList.Add(s.Substring(start, i-start));
}
while (i < len && sp[i] != ',' && sp[i] != '\"') {++i;}
}
if (privateList.Count != 0) {
control.PrivateHeaders = (string[])privateList.ToArray(typeof(string));
}
break;
case _no_c: if (i+8 > len) return;
if ((*(mask+1)|LOI) != _ache) continue;
control.NoCache = true;
i+=7;
// Check for a case: no-cache = "name1,name2"
while (i < len && sp[i] == ' ') {++i;}
if (i >= len || sp[i] != '=') {--i;break;}
while (i < len && sp[++i] == ' ') {;}
if (i >= len || sp[i] != '\"') {--i;break;}
System.Collections.ArrayList nocacheList = new System.Collections.ArrayList();
++i;
while(i < len && sp[i] != '\"') {
while (i < len && sp[i] == ' ') {++i;}
int start = i;
while (i < len && sp[i] != ' ' && sp[i] != ',' && sp[i] != '\"') {++i;}
if (start != i) {
nocacheList.Add(s.Substring(start, i-start));
}
while (i < len && sp[i] != ',' && sp[i] != '\"') {++i;}
}
if (nocacheList.Count != 0) {
control.NoCacheHeaders = (string[])nocacheList.ToArray(typeof(string));
}
break;
case _no_s: if (i+8 > len) return;
if ((*(mask+1)|LOI) != _tore) continue;
control.NoStore = true;
i+=7;
break;
case _must: if (i+15 > len) continue;
if ((*(mask+1)|LO) != __rev || (*(mask+2)|LO) != _alid || (*(int*)(mask+3)|LOI) != _at || (sp[i+14]|0x20) != 'e') continue;
control.MustRevalidate = true;
i+=14;
break;
case _max_: if (i+7 > len) return;
if ((*((int*)(mask+1))|LOI) != _ag || (sp[i+6]|0x20) != 'e') continue;
i+=7;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len || sp[i++] != '=') return;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len) return;
control.MaxAge = 0;
while (i < len && sp[i] >= '0' && sp[i] <= '9') {
control.MaxAge =control.MaxAge*10 + (sp[i++]-'0');
}
--i;
break;
case _s_ma: if (i+8 > len) return;
if ((*(mask+1)|LOI) != _xage) continue;
i+=8;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len || sp[i++] != '=') return;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len) return;
control.SMaxAge = 0;
while (i < len && sp[i] >= '0' && sp[i] <= '9') {
control.SMaxAge = control.SMaxAge*10 + (sp[i++]-'0');
}
--i;
break;
}
}
else {
if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "proxy-revalidate")) {
control.ProxyRevalidate = true;
i+=15;
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "public")) {
control.Public = true;
i+=5;
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "private")) {
control.Private = true;
i+=6;
// Check for a case: private = "name1,name2"
while (i < len && sp[i] == ' ') {++i;}
if (i >= len || sp[i] != '=') {--i;break;}
while (i < len && sp[++i] == ' ') {;}
if (i >= len || sp[i] != '\"') {--i;break;}
System.Collections.ArrayList privateList = new System.Collections.ArrayList();
++i;
while(i < len && sp[i] != '\"') {
while (i < len && sp[i] == ' ') {++i;}
int start = i;
while (i < len && sp[i] != ' ' && sp[i] != ',' && sp[i] != '\"') {++i;}
if (start != i) {
privateList.Add(s.Substring(start, i-start));
}
while (i < len && sp[i] != ',' && sp[i] != '\"') {++i;}
}
if (privateList.Count != 0) {
control.PrivateHeaders = (string[])privateList.ToArray(typeof(string));
}
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "no-cache")) {
control.NoCache = true;
i+=7;
// Check for a case: no-cache = "name1,name2"
while (i < len && sp[i] == ' ') {++i;}
if (i >= len || sp[i] != '=') {--i;break;}
while (i < len && sp[++i] == ' ') {;}
if (i >= len || sp[i] != '\"') {--i;break;}
System.Collections.ArrayList nocacheList = new System.Collections.ArrayList();
++i;
while(i < len && sp[i] != '\"') {
while (i < len && sp[i] == ' ') {++i;}
int start = i;
while (i < len && sp[i] != ' ' && sp[i] != ',' && sp[i] != '\"') {++i;}
if (start != i) {
nocacheList.Add(s.Substring(start, i-start));
}
while (i < len && sp[i] != ',' && sp[i] != '\"') {++i;}
}
if (nocacheList.Count != 0) {
control.NoCacheHeaders = (string[])nocacheList.ToArray(typeof(string));
}
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "no-store")) {
control.NoStore = true;
i+=7;
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "must-revalidate")) {
control.MustRevalidate = true;
i+=14;
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "max-age")) {
i+=7;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len || sp[i++] != '=') return;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len) return;
control.MaxAge = 0;
while (i < len && sp[i] >= '0' && sp[i] <= '9') {
control.MaxAge =control.MaxAge*10 + (sp[i++]-'0');
}
--i;
}
else if (Rfc2616.Common.UnsafeAsciiLettersNoCaseEqual(sp, i, len, "smax-age")) {
i+=8;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len || sp[i++] != '=') return;
while (i < len && sp[i] == ' ') {
++i;
}
if (i == len) return;
control.SMaxAge = 0;
while (i < len && sp[i] >= '0' && sp[i] <= '9') {
control.SMaxAge = control.SMaxAge*10 + (sp[i++]-'0');
}
--i;
}
}
}
}
}
}