想要 浏览更多Fiddler内容:请点击进入Fiddler官方文档web
3、建立Fiddler扩展项目cookie
4、在扩展程序选项卡中添加一个图标session
6、构建自定义检查器less
7、导入器和导出器接口编辑器
9、将参数传递给Importer或Exporter Extension
使用Fiddler的可扩展性机制添加到Fiddler的UI,自动修改请求或响应,并建立自定义检查器,以启用特定于方案的显示和手动修改请求和响应。
要使扩展可供计算机上的全部用户使用,请将扩展程序集DLL安装到:
%Program Files%\Fiddler2\Scripts
要使扩展仅对当前用户可用,请将扩展程序集DLL安装到:
%USERPROFILE%\My Documents\Fiddler2\Scripts
在AssemblyInfo.cs文件(或代码中的其余位置)中设置Fiddler.RequiredVersion属性,以下所示:
using Fiddler; // Extension requires Fiddler 2.2.8.6+ because it uses types introduced in v2.2.8... [assembly: Fiddler.RequiredVersion("2.2.8.6")]
启动Visual Studio 2005或更高版本。
建立一个Visual C#类库类型的新项目。
在解决方案资源管理器中右键单击项目的References文件夹。
单击“ 浏览”选项卡,而后在C:\ Program Files \ Fiddler2文件夹中选择Fiddler.exe。
单击“ 肯定”以添加引用。
若是您的扩展程序修改了Fiddler的UI:
在“构建事件”选项卡上,将如下内容添加到“构建后事件”命令行:
复制“$(TargetPath)”“%userprofile%\ My Documents \ Fiddler2 \ Scripts \ $(TargetFilename)”
修改项目中的默认class1.cs(或建立一个新类),以下所示:
using System; using System.Windows.Forms; using Fiddler; [assembly: Fiddler.RequiredVersion("2.3.5.0")] public class Violin : IAutoTamper // Ensure class is public, or Fiddler won't see it! { string sUserAgent = ""; public Violin(){ /* NOTE: It's possible that Fiddler UI isn't fully loaded yet, so don't add any UI in the constructor. But it's also possible that AutoTamper* methods are called before OnLoad (below), so be sure any needed data structures are initialized to safe values here in this constructor */ sUserAgent = "Violin"; } public void OnLoad(){ /* Load your UI here */ } public void OnBeforeUnload() { } public void AutoTamperRequestBefore(Session oSession){ oSession.oRequest["User-Agent"] = sUserAgent; } public void AutoTamperRequestAfter(Session oSession){} public void AutoTamperResponseBefore(Session oSession){} public void AutoTamperResponseAfter(Session oSession){} public void OnBeforeReturningError(Session oSession){} }
实现Fiddler接口
2、
在Fiddler执行期间实现Fiddler接口以加载程序集。
实现IFiddlerExtension接口的程序集中的公共类将在启动期间由Fiddler加载。
public interface IFiddlerExtension { // Called when Fiddler User Interface is fully available void OnLoad(); // Called when Fiddler is shutting down void OnBeforeUnload(); }
该的OnLoad当小提琴手加载完成其UI是彻底可用的功能将被调用。此时,您能够安全地将菜单项,选项卡式页面或其余元素添加到Fiddler UI。
该OnBeforeUnload函数将被调用时,提琴手被关闭和卸载全部扩展。
为每一个HTTP / HTTPS请求和响应调用实现IAutoTamper接口(扩展IFiddlerExtension)的扩展,从而启用修改,日志记录或其余操做。
警告:此接口中的函数在后台非UI线程上调用。要更新UI,请使用 Invoke或 BeginInvoke更新UI。另请注意,能够在调用 OnLoad事件以前调用IAutoTamper :: *函数 -Fiddler容许流量在UI彻底可用以前流动。
public interface IAutoTamper : IFiddlerExtension { // Called before the user can edit a request using the Fiddler Inspectors void AutoTamperRequestBefore(Session oSession); // Called after the user has had the chance to edit the request using the Fiddler Inspectors, but before the request is sent void AutoTamperRequestAfter(Session oSession); // Called before the user can edit a response using the Fiddler Inspectors, unless streaming. void AutoTamperResponseBefore(Session oSession); // Called after the user edited a response using the Fiddler Inspectors. Not called when streaming. void AutoTamperResponseAfter(Session oSession); // Called Fiddler returns a self-generated HTTP error (for instance DNS lookup failed, etc) void OnBeforeReturningError(Session oSession); }
当响应头可用时,将调用实现IAutoTamper2接口(扩展IAutoTamper)的扩展。
/// <summary> /// Interface for AutoTamper extensions that want to "peek" at response headers /// </summary> public interface IAutoTamper2 : IAutoTamper { /// <summary> /// Called when the response headers become available /// </summary> /// <param name="oSession">The Session object for which the response headers are available</param> void OnPeekAtResponseHeaders(Session oSession); }
当请求标头可用时,将调用实现IAutoTamper3接口(扩展IAutoTamper2)的扩展。
/// <summary> /// Interface for AutoTamper extensions that want to "peek" at request headers /// </summary> public interface IAutoTamper3 : IAutoTamper2 { /// <summary> /// Called when the request headers become available /// </summary> /// <param name="oSession">The Session object for which the request headers are available</param> void OnPeekAtRequestHeaders(Session oSession); }
当用户在QuickExec框中输入命令时,将调用实现IHandleExecAction接口的扩展。要对命令做出反应(并防止其余扩展和Fiddler自己进一步处理),请今后方法返回true。
public interface IHandleExecAction { // return TRUE if handled. bool OnExecAction(string sCommand); }
Fiddler.Utilities类包含一个辅助函数Parameterize(),它有助于解释sCommand参数。
[CodeDescription("Tokenize a string into tokens. Delimits on whitespace; Quotation marks are dropped unless preceded by a \ character.")] public static string[] Parameterize(string sCommand)
按照如下步骤建立示例Fiddler扩展,修改全部出站请求的User-Agent字符串:
启动Visual Studio 2005或更高版本。
建立一个Visual C#类库类型的新项目。
在解决方案资源管理器中右键单击项目的References文件夹。
单击“ 浏览”选项卡,而后在C:\ Program Files \ Fiddler2文件夹中选择Fiddler.exe。
单击“ 肯定”以添加引用。
若是您的扩展程序修改了Fiddler的UI:
再次右键单击解决方案资源管理器中项目的References文件夹。
在.NET选项卡上,选择System.Windows.Forms。
单击“ 肯定”以添加引用。
在解决方案资源管理器中,右键单击该项目。
单击属性。
单击“ 构建事件”选项卡。
将如下内容添加到Post-build事件命令行:
copy "$(TargetPath)" "%userprofile%\My Documents\Fiddler2\Scripts\$(TargetFilename)"
修改项目中的默认class1.cs(或建立一个新类),以下所示:
using System; using System.Windows.Forms; using Fiddler; [assembly: Fiddler.RequiredVersion("2.3.5.0")] public class Violin : IAutoTamper // Ensure class is public, or Fiddler won't see it! { string sUserAgent = ""; public Violin(){ /* NOTE: It's possible that Fiddler UI isn't fully loaded yet, so don't add any UI in the constructor. But it's also possible that AutoTamper* methods are called before OnLoad (below), so be sure any needed data structures are initialized to safe values here in this constructor */ sUserAgent = "Violin"; } public void OnLoad(){ /* Load your UI here */ } public void OnBeforeUnload() { } public void AutoTamperRequestBefore(Session oSession){ oSession.oRequest["User-Agent"] = sUserAgent; } public void AutoTamperRequestAfter(Session oSession){} public void AutoTamperResponseBefore(Session oSession){} public void AutoTamperResponseAfter(Session oSession){} public void OnBeforeReturningError(Session oSession){} }
请参阅Fiddler接口。
设置.ImageIndex属性,以下所示:
public void OnLoad() { oPage = new TabPage("Timeline"); oPage.ImageIndex = (int)Fiddler.SessionIcons.Timeline; oView = new TimelineView(); oPage.Controls.Add(oView); oView.Dock = DockStyle.Fill; FiddlerApplication.UI.tabsViews.TabPages.Add(oPage); }
将图像添加到imglSessionIcons。
设置.ImageIndex属性,以下所示:
public void OnLoad() { oPage = new TabPage("Timeline"); oPage.ImageIndex = (int)Fiddler.SessionIcons.Timeline; oView = new TimelineView(); oPage.Controls.Add(oView); oView.Dock = DockStyle.Fill; FiddlerApplication.UI.tabsViews.TabPages.Add(oPage); }
编译您的项目。
将程序集.DLL复制到正确的Scripts文件夹:
使用\ My Documents \ Fiddler2 \ Scripts使扩展可供当前用户使用。
使用\ Program Files \ Fiddler2 \ Scripts使扩展可供计算机上的全部用户使用。
重启Fiddler。
建立一个Fiddler扩展项目。
更改代码以从Inspector2类派生并实现IResponseInspector2或IRequestInspector2。
using Fiddler; [assembly: Fiddler.RequiredVersion("2.3.0.0")] public class WebViewer: Inspector2, IResponseInspector2 { public Viewers() { // // TODO: Add constructor logic here // } }
在课堂内,建立一个新方法。经过键入公共覆盖,您将得到须要编写的方法的自动完成列表。
在解决方案资源管理器中,右键单击项目,而后单击添加>用户控件。
使用工具箱将控件添加到用户控件。这些将显示有关正在检查的HTTP消息的数据。
在body {set}和headers {set}属性中,您应该更新控件的请求或响应的可视化表示。
目前,在MAIN UI线程上调用ISessionImporter和ISessionExporter接口。这几乎确定会在未来发生变化,所以您应该确保您的类是线程安全的,而且他们不会尝试直接操做Fiddler UI。
对Fiddler UI的操纵仍是不明智的,由于Fiddler自己可能没法加载; FiddlerCore可能直接托管您的进口商/出口商。为了支持FiddlerCore,建议您在dictOptions参数中支持Filename键(具备彻底限定路径的字符串值),并考虑支持Silent键(值为boolean)。
当用户使用“ 文件”>“导入”菜单选项时,将调用实现ISessionImporter接口(实现IDisposable接口)的扩展。
public interface ISessionImporter : IDisposable { Session[] ImportSessions(string sImportFormat, Dictionary<string, object> dictOptions, EventHandler<ProgressCallbackEventArgs> evtProgressNotifications); }
该方法返回从导入数据建立的Session对象数组。
所述dictOptions字典能够为空,也能够含有一组字符串键控对象。大多数进口商都支持文件名的规范。例如:
dictOptions["Filename"] = "C:\\test.file"
此类由Fiddler定义,容许您报告导入或导出操做的进度。
若是没法肯定完成率,只需传递0或0到1.0之间的“猜想”。
若是在传递给evtProgressNotifications回调后在ProgressCallbackEventArgs对象上设置了Cancel标志,则导入或导出应该尽快正常终止。
public class ProgressCallbackEventArgs: EventArgs { public ProgressCallbackEventArgs(float flCompletionRatio, string sProgressText) public string ProgressText { get; } public string PercentComplete { get; } public bool Cancel { get; set; } }
构建自定义导入程序或导出程序
8、
建立一个Fiddler扩展项目。
修改项目中的默认class1.cs(或建立一个新类),以下所示:
using System; using System.IO; using System.Text; using System.Windows.Forms; using Fiddler; using System.Diagnostics; using System.Reflection; [assembly: AssemblyVersion("1.0.0.0")] [assembly: Fiddler.RequiredVersion("2.4.0.0")] [ProfferFormat("TAB-Separated Values", "Session List in Tab-Delimited Format")] [ProfferFormat("Comma-Separated Values", "Session List in Comma-Delimited Format; import into Excel or other tools")] public class CSVTranscoder: ISessionExporter // Ensure class is public, or Fiddler won't see it! { public bool ExportSessions(string sFormat, Session[] oSessions, Dictionary<string, object> dictOptions, EventHandler<ProgressCallbackEventArgs> evtProgressNotifications) { bool bResult = false; string chSplit; // Determine if we already have a filename from the dictOptions collection string sFilename = null; if (null != dictOptions && dictOptions.ContainsKey("Filename")) { sFilename = dictOptions["Filename"] as string; } if (sFormat == "Comma-Separated Values") { chSplit = ","; if (string.IsNullOrEmpty(sFilename)) sFilename = Fiddler.Utilities.ObtainSaveFilename("Export As " + sFormat, "CSV Files (*.csv)|*.csv"); } else { chSplit = "\t"; if (string.IsNullOrEmpty(sFilename)) sFilename = Fiddler.Utilities.ObtainSaveFilename("Export As " + sFormat, "TSV Files (*.tsv)|*.tsv"); } if (String.IsNullOrEmpty(sFilename)) return false; try { StreamWriter swOutput = new StreamWriter(sFilename, false, Encoding.UTF8); int iCount = 0; int iMax = oSessions.Length; #region WriteColHeaders bool bFirstCol = true; foreach (ColumnHeader oLVCol in FiddlerApplication.UI.lvSessions.Columns) { if (!bFirstCol) { swOutput.Write(chSplit); } else { bFirstCol = false; } swOutput.Write(oLVCol.Text.Replace(chSplit, "")); } swOutput.WriteLine(); #endregion WriteColHeaders #region WriteEachSession foreach (Session oS in oSessions) { iCount++; if (null != oS.ViewItem) { bFirstCol = true; ListViewItem oLVI = (oS.ViewItem as ListViewItem); if (null == oLVI) continue; foreach (ListViewItem.ListViewSubItem oLVC in oLVI.SubItems) { if (!bFirstCol) { swOutput.Write(chSplit); } else { bFirstCol = false; } swOutput.Write(oLVC.Text.Replace(chSplit,""));} swOutput.WriteLine();}if(null!= evtProgressNotifications){ evtProgressNotifications(null,newProgressCallbackEventArgs(,));ProgressCallbackEventArgs PCEA =newProgressCallbackEventArgs((iCount/(float)iMax),"wrote "+ iCount.ToString()+" records."); evtProgressNotifications(null, PCEA);if(PCEA.Cancel){ swOutput.Close();returnfalse;}}}#endregion WriteEachSession swOutput.Close(); bResult =true;}catch(Exception eX){MessageBox.Show(eX.Message,"Failed to export"); bResult =false;}}return bResult;}publicvoidDispose(){}}
9、将参数传递给Importer或Exporter Extension
转码器(实现导入器或导出器接口的对象)能够在字典对象中传递参数。例如,FiddlerScript能够调用HTTPArchive转码器,传递文件名字符串和最大响应大小整数,以下所示:
var oSessions = FiddlerApplication.UI.GetAllSessions(); var oExportOptions = FiddlerObject.createDictionary(); oExportOptions.Add("Filename", "C:\\users\\ericlaw\\desktop\\out1.har"); oExportOptions.Add("MaxTextBodyLength", 1024); oExportOptions.Add("MaxBinaryBodyLength", 16384); FiddlerApplication.DoExport("HTTPArchive v1.2", oSessions, oExportOptions, null);
代码转换器扩展能够按以下方式收集这些选项:
public bool ExportSessions(string sFormat, Session[] oSessions, Dictionary<string, object> dictOptions, EventHandler<ProgressCallbackEventArgs> evtProgressNotifications) { //... if (null != dictOptions) { if (dictOptions.ContainsKey("Filename")) { sFilename = dictOptions["Filename"] as string; } if (dictOptions.ContainsKey("MaxTextBodyLength")) { iMaxTextBodyLength = (int)dictOptions["MaxTextBodyLength"]; } if (dictOptions.ContainsKey("MaxBinaryBodyLength")) { iMaxBinaryBodyLength = (int)dictOptions["MaxBinaryBodyLength"]; } }
若是您但愿扩展程序集在Fiddler2和Fiddler4中运行,请为.NET Framework v2构建它,并避免对在更高版本的Framework中删除或移动的任何类具备任何依赖性。(我所知道的惟一一个实例是Microsoft JScript.NET代码编译器,其类移动了一下)。
您还须要确保若是使用任何不推荐使用的方法(例如,使用带有Evidence参数的重载调用Assembly.LoadFrom),则只能有条件地执行此操做。例如:
if (CONFIG.bRunningOnCLRv4) { a = Assembly.LoadFrom(oFile.FullName); } else { a = Assembly.LoadFrom(oFile.FullName, evidenceFiddler); }
来自Fiddler网站的全部扩展都是针对Fiddler v2编译的。
或者,您能够简单地构建两个版本的DLL,一个版本针对.NET Framework v4,另外一个针对.NET Framework v2。
这就是Fiddler自己的构建方式。基本上,只需将v2目标项目的“克隆”版本添加到同一解决方案中。使用“ 添加”>“现有项”上下文菜单将.CS文件从以v2为目标的项目添加到以v4为目标的项目,但在选择文件时,请务必使用文件选取器对话框中的拆分按钮,而后选择“ 添加为”。连接。在v4项目的“ 属性”>“构建”选项卡上,添加像DOTNET4这样的条件编译符号。而后,您能够将任何特定于.NETv4的代码置于条件编译以后:
#if DOTNET4 // ... code targeting .NETv4 #else // ... code targeting .NETv2 #endif
您的扩展程序可能会根据在其中找到的InstalledVersion注册表项的内容安装适当目标的版本:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fiddler2
.NET2版的Fiddler目前比.NETv4版本更受欢迎。当.NET Framework v4.5发布时,我可能会将v4项目移到v4.5。除此以外,这将容许我在后面的框架中利用新的内置.ZIP类。
RequiredVersion属性怎么样?
Fiddler v4是“聪明的” - 若是您的扩展指定
[assembly: Fiddler.RequiredVersion("2.1.0.1")]
当Fiddler v4加载它时,它将须要4.3.9.9或更高版本。
示例扩展11、
要查看一些示例扩展,请查看Fiddler Add-Ons页面或Privacy Scanner Add-On代码。
要将自定义列添加到Fiddler UI,修改请求或响应,测试应用程序性能以及各类其余自定义任务,请在FiddlerScript中向Fiddler的JScript.NET CustomRules.js文件添加规则。
按此规则>自定义规则...。
在相应的函数内输入FiddlerScript代码。
保存文件。
Fiddler会自动从新加载规则。
要在脚本中使用其余.NET程序集:
单击工具>提琴选项。
单击“ 扩展”选项卡。
编辑参考列表。
或者:
在GAC中注册程序集; 要么
将程序集复制到包含Fiddler.exe的文件夹。
要在不彻底限定它们的状况下使用新程序集的函数,请更新脚本顶部的#import子句。
单击工具>提琴选项。
编辑编辑器字符串。
删除〜/ Documents / Fiddler2 / Scripts中的CustomRules.js文件。
重启Fiddler。
注意:Fiddler的默认规则存储在〜/ Program Files / Fiddler2 / Scripts / SampleRules.js中。
要将菜单操做添加到“ 工具”菜单或上下文菜单,或者将选项添加到“ 规则”菜单:
建立并执行.REG文件,以下所示:
[HKEY_CURRENT_USER\Software\Microsoft\Fiddler2\MenuExt\&YourMenuItemName] "Command"="YourExeName.exe" "Parameters"="Your Parameters To Pass To The EXE"
重启Fiddler。
要使用.NET插件(对于此示例,修改用户代理字符串的C#插件):
关闭提琴手。
保存.NET文件(例如,此文件名为UASimulator.cs):
using System; using System.Windows.Forms; using Fiddler; namespace FiddlerUtility{ public class UASimulator { string m_sUAString; public UASimulator(string s_UAString){ m_sUAString = s_UAString; } public bool OverwriteUA(Session oSession){ oSession.oRequest["User-Agent"] = m_sUAString; return true; } } }
在VS命令提示符下,转到找到.CS文件的文件夹。
输入命令以在VS命令提示符中建立DLL。例如:
csc /target:library /out:c:\UASim.dll UASimulator.cs /reference:"C:\program files\fiddler2\fiddler.exe"
在Fiddler中,单击工具> Fiddler选项。
单击“ 扩展”选项卡。
在“ 引用”字段中,输入DLL的位置。例如:
C:\UASim.dll
向Fiddler添加规则以更新脚本。例如:
import System; import System.Windows.Forms; import Fiddler; import FiddlerUtility; class Handlers{ static var UASim = new UASimulator("Mozilla/12.0"); static function OnBeforeRequest(oSession:Fiddler.Session){ UASim.OverwriteUA(oSession); } static function Main(){ var today: Date = new Date(); FiddlerObject.StatusText = " CustomRules.js was loaded at: " + today; } }
构建Cookie扫描扩展
十5、
如下是Fiddler Privacy Scanner插件的代码。
using System; using System.Collections; using System.Globalization; using System.Collections.Generic; using System.Windows.Forms; using System.Text; using Fiddler; using System.IO; using System.Diagnostics; using Microsoft.Win32; using System.Reflection; using System.Text.RegularExpressions; [assembly: Fiddler.RequiredVersion("2.3.9.0")] [assembly: AssemblyVersion("1.0.1.0")] [assembly: AssemblyTitle("PrivacyScanner")] [assembly: AssemblyDescription("Scans for Cookies and P3P")] [assembly: AssemblyCompany("Eric Lawrence")] [assembly: AssemblyProduct("PrivacyScanner")] public class TagCookies : IAutoTamper2 { private bool bEnabled = false; private bool bEnforceP3PValidity = false; private bool bCreatedColumn = false; private System.Windows.Forms.MenuItem miEnabled; private System.Windows.Forms.MenuItem miEnforceP3PValidity; private System.Windows.Forms.MenuItem mnuCookieTag; public void OnLoad() { /* * NB: You might not get called here until ~after~ one of the AutoTamper methods was called. * This is okay for us, because we created our mnuContentBlock in the constructor and its simply not * visible anywhere until this method is called and we merge it onto the Fiddler Main menu. */ FiddlerApplication.UI.mnuMain.MenuItems.Add(mnuCookieTag); } public void OnBeforeUnload() { /*noop*/ } private void InitializeMenu() { this.miEnabled = new System.Windows.Forms.MenuItem("&Enabled"); this.miEnforceP3PValidity = new System.Windows.Forms.MenuItem("&Rename P3P header if invalid"); this.miEnabled.Index = 0; this.miEnforceP3PValidity.Index = 1; this.mnuCookieTag = new System.Windows.Forms.MenuItem(); this.mnuCookieTag.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.miEnabled, this.miEnforceP3PValidity }); this.mnuCookieTag.Text = "Privacy"; this.miEnabled.Click += new System.EventHandler(this.miEnabled_Click); this.miEnabled.Checked = bEnabled; this.miEnforceP3PValidity.Click += new System.EventHandler(this.miEnforceP3PValidity_Click); this.miEnforceP3PValidity.Checked = bEnforceP3PValidity; } public void miEnabled_Click(object sender, EventArgs e) { miEnabled.Checked = !miEnabled.Checked; bEnabled = miEnabled.Checked; this.miEnforceP3PValidity.Enabled = bEnabled; if (bEnabled) { EnsureColumn(); } FiddlerApplication.Prefs.SetBoolPref("extensions.tagcookies.enabled", bEnabled); }publicvoid miEnforceP3PValidity_Click(object sender,EventArgs e){ miEnforceP3PValidity.Checked=!miEnforceP3PValidity.Checked; bEnforceP3PValidity = miEnforceP3PValidity.Checked;FiddlerApplication.Prefs.SetBoolPref("extensions.tagcookies.EnforceP3PValidity", bEnforceP3PValidity);}privatevoidEnsureColumn(){if(bCreatedColumn)return;FiddlerApplication.UI.lvSessions.AddBoundColumn("Privacy Info",1,120,"X-Privacy"); bCreatedColumn =true;}publicTagCookies(){this.bEnabled =FiddlerApplication.Prefs.GetBoolPref("extensions.tagcookies.enabled",false);this.bEnforceP3PValidity =FiddlerApplication.Prefs.GetBoolPref("extensions.tagcookies.EnforceP3PValidity",true);InitializeMenu();if(bEnabled){EnsureColumn();}else{this.miEnforceP3PValidity.Enabled=false;}}privatevoidSetP3PStateFromHeader(string sValue,ref P3PState oP3PState){if(string.IsNullOrEmpty(sValue)){return;}string sUnsatCat =String.Empty;string sUnsatPurpose =String.Empty; sValue = sValue.Replace('\'','"');string sCP =null;Regex r =newRegex("CP\\s?=\\s?[\"]?(?<TokenValue>[^\";]*)");Match m = r.Match(sValue);if(m.Success&&(null!= m.Groups["TokenValue"])){ sCP = m.Groups["TokenValue"].Value;}if(String.IsNullOrEmpty(sCP)){return;}// Okay, we've got a compact policy token. oP3PState = P3PState.P3POk;string[] sTokens = sCP.Split(newchar[]{' '},StringSplitOptions.RemoveEmptyEntries);foreach(string sToken in sTokens){// Reject clearly invalid tokens...if((sToken.Length<3)||(sToken.Length>4)){ oP3PState = P3PState.P3PMalformed;return;}if(",PHY,ONL,GOV,FIN,".IndexOf(","+ sToken +",",StringComparison.OrdinalIgnoreCase)>-1){ sUnsatCat +=(sToken +" ");continue;}if(",SAM,OTR,UNR,PUB,IVA,IVD,CON,TEL,OTP,".IndexOf(","+ sToken +",",StringComparison.OrdinalIgnoreCase)>-1){ sUnsatPurpose +=(sToken +" ");continue;}// TODO: Look up the token in the complete collection and check validity}// If a cookie contains an unsatisfactory purpose and an unsatisfactory category, mark it// https://msdn.microsoft.com/en-us/library/ie/ms537343(v=vs.85).aspx#unsatisfactory_cookiesif((sUnsatCat.Length>0)&&(sUnsatPurpose.Length>0)){if(oP3PState == P3PState.P3POk){ oP3PState = P3PState.P3PUnsatisfactory;}}}privateenum P3PState {NoCookies,NoP3PAndSetsCookies, P3POk, P3PUnsatisfactory, P3PMalformed }publicvoidOnPeekAtResponseHeaders(Session oSession){if(!bEnabled)return; P3PState oP3PState = P3PState.NoCookies;if(!oSession.oResponse.headers.Exists("Set-Cookie")){return;} oP3PState = P3PState.NoP3PAndSetsCookies;if(oSession.oResponse.headers.Exists("P3P")){SetP3PStateFromHeader(oSession.oResponse.headers["P3P"],ref oP3PState);}switch(oP3PState){case P3PState.P3POk: oSession["ui-backcolor"]="#ACDC85"; oSession["X-Privacy"]="Sets cookies & P3P";break;case P3PState.NoP3PAndSetsCookies: oSession["ui-backcolor"]="#FAFDA4"; oSession["X-Privacy"]="Sets cookies without P3P";break;case P3PState.P3PUnsatisfactory: oSession["ui-backcolor"]="#EC921A"; oSession["X-Privacy"]="Sets cookies; P3P unsatisfactory for 3rd-party use";break;case P3PState.P3PMalformed: oSession["ui-backcolor"]="#E90A05";if(bEnforceP3PValidity){ oSession.oResponse.headers["MALFORMED-P3P"]= oSession.oResponse.headers["P3P"]; oSession["X-Privacy"]="MALFORMED P3P: "+ oSession.oResponse.headers["P3P"]; oSession.oResponse.headers.Remove("P3P");}break;}}publicvoidAutoTamperRequestBefore(Session oSession){}publicvoidAutoTamperRequestAfter(Session oSession){/*noop*/}publicvoidAutoTamperResponseAfter(Session oSession){/*noop*/}publicvoidAutoTamperResponseBefore(Session oSession){/*noop*/}publicvoidOnBeforeReturningError(Session oSession){/*noop*/}}
十3、添加菜单项: