OWASP O2 Platform Blog

Example of creating, consuming and serializing C# classes

I’m currently helping Sarah Baso (from OWASP) to use O2 to streamline a number of OWASP admin tasks, and here are a couple script samples from the code that she is writing on retrieving details from Mailman Mailing lists

Here is the base class with data

// This file is part of the OWASP O2 Platform (http://www.owasp.org/index.php/OWASP_O2_Platform) and is released under the Apache 2.0 License (<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)
using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;
using O2.Kernel;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.DotNet;
using O2.DotNetWrappers.Windows;
using O2.DotNetWrappers.ExtensionMethods;
using O2.Views.ASCX.classes.MainGUI;
using O2.Views.ASCX.ExtensionMethods;
namespace O2.Script
    public class MailingLists
        public DateTime             DateCollected    { get; set;}
        public List<MailingList> Lists          { get; set; }
        public MailingLists()
            Lists = new List<MailingList>();
    public class MailingList
        public string Name                     { get; set; }
        public bool  Public                 { get; set; }       
        public List<Subscriber> Admins        { get; set; }
        public List<Subscriber> Subscribers { get; set; }       
        public MailingList()
            Admins = new List<Subscriber>();
            Subscribers = new List<Subscriber>();
    public class Subscriber
        public string Name           { get; set; }
        public string Email       { get; set; }       

Here is how that data can be consumed

var mailingLists = new MailingLists();</pre>
Action<string, bool> addList =
    (listName, isPublic)=>
            var mailingList = new MailingList();
            mailingList.Name = listName;
            mailingList.Public = isPublic;           
addList("owasp-london", true);
addList("owasp-rh", true);
addList("owasp-chapter", true);
/*var londonList = new MailingList();
londonList.Name = "Owasp-london";
londonList.Public = true;


var chaptersList = new MailingList();
chaptersList.Name = "Owasp-chapter";
chaptersList.Public = true;


//return mailingLists;
//return myData;
var result = mailingLists.serialize(false);

return mailingLists;
//using O2.Script    
//O2File:C:\O2\_XRules_Local\Sarah's Test\MyData.cs

Here is how to normalize the email addresses

var url = https://lists.owasp.org/mailman/options/owasp-xyz-list/aaa_at_gmail.com;

if (url.contains("https://lists.owasp.org/mailman/options/"))
    var items = url.remove("https://lists.owasp.org/mailman/options/").split("/");
    var listName = items[0];
    var email = items[1].replace("_at_","@");
    return email;

return "no data";

February 5, 2012 Posted by | Mailman, OWASP | Leave a comment

Mapping out the OWASP Mailman admins (from web exposed data)

There was a recent thread on the OWASP-leaders list about unsubscribing to that list. The problem was caused by the auto population of that list with the current admins of an owasp mailing list.

As you can see on https://lists.owasp.org/mailman/admin , the problem is that there are a LOT of OWASP mailing lists (466 to be specific) and it is not easy to find out who is the current admin of what list.

To help with these mappings, I just wrote a quick O2 script which allows the collection and visualization of that data.

The script is called OWASP Mailing Lists – admins mappings.h2 and this is what it looks like when executed:

And here is its source code:

var hideTableDuringLoad = true;
var topPanel = "OWASP Mailing Lists - List admin mappings/emails".popupWindow(1200,500);
//var topPanel = panel.clear().add_Panel();
var tableList = topPanel.add_GroupBox("OWASP Mailing list mappigs").add_TableList();
var browser = topPanel.insert_Right("List Admin WebPage").add_WebBrowser_Control();


tableList.add_Columns("#", "email", "list", "href" );
var tempDir = "_owasp-leaders_mainmanMappings".tempDir(false);

var baseUrl = "https://lists.owasp.org/mailman/admin";
Func<string, string> getHtml_UsingCache =
(urlToGet)=> {
var cacheFilePath = tempDir.pathCombine(urlToGet.safeFileName() + ".html");
return (cacheFilePath.fileExists())
? cacheFilePath.fileContents()
: urlToGet.uri()

Func<string,string, List<HtmlNode>> getNodesFromHtmlPage =
(urlToGet, filter)=> {
var htmlDocument = getHtml_UsingCache(urlToGet).htmlDocument();
return htmlDocument.select(filter);
//return getNodesFromHtmlPage(baseUrl, "//a");

var linksToFollow = (from link in getNodesFromHtmlPage(baseUrl, "//a")
where link.attribute("href").value().contains("mailman/admin")
select link).toList();

var listNumber = 1;
foreach(var linkToFollow in linksToFollow)
var href = linkToFollow.attribute("href").value();
var links = getNodesFromHtmlPage(href, "//a");
foreach(var link in links)
if (link.InnerText.contains(" at "))
foreach(var email in link.InnerText.split(","))
email.replace(" at <a href="mailto:%22,%20%22@%22).trim().ToLower">", "@").trim().ToLower</a>(),
listNumber++.str() ,



return "done";
//using HtmlAgilityPack
//using O2.XRules.Database.Utils.ExtensionMethods

November 12, 2011 Posted by | Mailman, OWASP | Leave a comment