string[] domains = new string[] { // Если список domains пуст, то происходит полная очистка cookies
"", // Если заполнен хотя бы один домен, то происходит очистка только заданных cookies
"",
""
};
bool includeSubdomains = true; // При true удаляет домен со всеми поддоменами. Например, для домена hcaptcha.com будут удалены куки hcaptcha.com, .hcaptcha.com, api.hcaptcha.com, newassets.hcaptcha.com
bool logDetails = true; // Печатать ли каждую удаляемую куку отдельной строкой в логе ProjectMaker
int maxPasses = 2; // Максимум повторов цикла «прочитать дамп кук → погасить найденные»
Action<string> Log = delegate(string s) { project.SendInfoToLog("[cookies] " + s, false); };
Func<string,string> Norm = delegate(string d) {
if (d == null) return "";
d = d.Trim().ToLowerInvariant();
while (d.StartsWith(".")) d = d.Substring(1);
return d;
};
var targets = new List<string>();
if (domains != null) {
for (int i = 0; i < domains.Length; i++) {
string n = Norm(domains[i]);
if (n.Length > 0 && !targets.Contains(n)) targets.Add(n);
}
}
bool allMode = targets.Count == 0;
Log(allMode
? "режим: удаляю ВСЕ куки профиля"
: "режим: только домены " + string.Join(", ", targets.ToArray())
+ (includeSubdomains ? " (+поддомены)" : ""));
Func<string,bool> Match = delegate(string cookieDomain) {
if (allMode) return true;
string cd = Norm(cookieDomain);
for (int i = 0; i < targets.Count; i++) {
if (cd == targets[i]) return true;
if (includeSubdomains && cd.EndsWith("." + targets[i])) return true;
}
return false;
};
Func<object,string,object[],bool> Call = delegate(object target, string name, object[] args) {
if (target == null) return false;
int argc = args == null ? 0 : args.Length;
try {
foreach (var mi in target.GetType().GetMethods()) {
if (mi.IsSpecialName || mi.Name != name) continue;
if (mi.GetParameters().Length != argc) continue;
mi.Invoke(target, args);
return true;
}
} catch { }
return false;
};
Func<string> Dump = delegate() {
try { string s = instance.GetCookie("", false); return s == null ? "" : s; }
catch { return ""; }
};
Func<int> Live = delegate() {
int n = 0;
string[] rows = Dump().Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < rows.Length; i++) {
string row = rows[i].Trim();
if (row.Length == 0 || row.StartsWith("#")) continue;
string[] f = row.Split('\t');
if (f.Length < 7 || f[6].Trim().Length == 0) continue;
if (Match(f[0])) n++;
}
return n;
};
System.Reflection.MethodInfo miSet = null;
try {
foreach (var mi in instance.GetType().GetMethods()) {
if (mi.IsSpecialName || mi.Name != "SetCookie") continue;
var ps = mi.GetParameters();
if (ps.Length == 1 && ps[0].ParameterType == typeof(string)) { miSet = mi; break; }
}
} catch { }
if (miSet == null) { Log("instance.SetCookie не найден"); return "no-setcookie"; }
Action<string> Set = delegate(string line) {
try { miSet.Invoke(instance, new object[] { line }); } catch { }
};
object cc = null;
try { cc = project.Profile.CookieContainer; } catch { }
int before = Live();
Log("до очистки: " + before + " кук");
var killed = new HashSet<string>();
int after = before, kept = 0;
for (int pass = 1; pass <= maxPasses && after > 0; pass++) {
string dump = Dump();
if (dump.Length == 0) break;
string[] rows = dump.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
int found = 0;
kept = 0;
for (int i = 0; i < rows.Length; i++) {
string row = rows[i].Trim();
if (row.Length == 0 || row.StartsWith("#")) continue;
string[] f = row.Split('\t');
if (f.Length < 7) continue;
string dom = f[0].Trim(), name = f[5].Trim();
if (dom.Length == 0 || name.Length == 0) continue;
if (f[6].Trim().Length == 0) continue;
if (!Match(dom)) { kept++; continue; }
found++;
string[] g = (string[])f.Clone();
g[4] = "01/01/2000 00:00:00";
g[6] = "";
if (g.Length > 8) g[8] = "FALSE";
Set(string.Join("\t", g));
string[] h = (string[])g.Clone();
h[4] = "1";
Set(string.Join("\t", h));
string[] k = (string[])g.Clone();
k[0] = dom.StartsWith(".") ? dom.Substring(1) : "." + dom;
Set(string.Join("\t", k));
if (killed.Add(dom + "\t" + name) && logDetails) Log(" [" + dom + "] " + name);
}
Call(cc, "UpdateCookieContainer", null);
if (allMode) {
Call(cc, "Clear", null);
} else {
for (int i = 0; i < targets.Count; i++) {
Call(cc, "Clear", new object[] { targets[i] });
Call(cc, "Clear", new object[] { "." + targets[i] });
}
}
Call(cc, "UpdateCookieInstance", null);
after = Live();
Log("проход " + pass + ": найдено " + found + ", осталось живых " + after
+ (allMode ? "" : ", чужих кук " + kept));
if (found == 0) break;
}
if (after > 0) {
Log("не удалились:");
string[] rows = Dump().Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < rows.Length && i < 20; i++) {
string row = rows[i].Trim();
if (row.Length == 0 || row.StartsWith("#")) continue;
string[] f = row.Split('\t');
if (f.Length < 7 || f[6].Trim().Length == 0 || !Match(f[0])) continue;
Log(" " + f[0] + " | " + f[5]);
}
}
Log((after == 0 ? "готово: удалено кук " + killed.Count : "ВНИМАНИЕ: осталось живых " + after)
+ (allMode ? "" : ", чужих кук не тронуто " + kept));
return "before=" + before + " after=" + after;