OWASP O2 Platform Blog

Extrating OWASP Chapter data via MediaWiki API and viewing it

Here is a script that uses O2’s MediaWiki API to extract OWASP’s chapter information from its WIKI.

Once the data is collected, a mini gui is used to show it:

var topPanel = panel.clear().add_Panel();
var owaspWiki = new OwaspWikiAPI(false);

var treeView = topPanel.add_TreeView();
var textArea = topPanel.insert_Right().add_TextArea();
var webBrowser = textArea.insert_Below().add_WebBrowser_Control();
Action<List<string>,TreeNode, bool> loadArea = null;
var addedCategories = new List<string>();

                var wikiText = owaspWiki.wikiText(page);
                var htmlCode = owaspWiki.html(page);
loadArea = (pages, parentNode, addChapters) =>
            foreach(var page in pages)
                if (page.contains("Category") && addedCategories.contains(page).isFalse())
                    var categoryNode = parentNode.add_Node(page);                   
                    var chaptersInArea = owaspWiki.pagesInCategory(page);       
                    loadArea(chaptersInArea, categoryNode , true);
                    if (addChapters)

var chapters = owaspWiki.pagesInCategory("Category:OWASP Chapter");
//var chapters = @"C:\O2\_tempDir\2-8-2012\tmpA92F.tmp.xml".load<List<string>>();

//return pages.size();

return "ok";

February 8, 2012 Posted by | MediaWiki, OWASP | Leave a comment

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

OWASP MediaWiki Tool – File Uploader (O2 Script)

Following a request from a fellow OWASP Leader for an easier way to upload files to the OWASP wiki, here is an O2 script that allows the uploading of file(s) by just drag-and-droping then from a local folder (note that not all file types are currenly supported by the OWASP Wiki).

The script is called “Tool – OWASP Wiki – File Uploader.h2” and here is what the GUI looks like:

This script supports the upload of all files in a folder, but be careful when using it, since (in this version) there is no stop botton, and if you make a mistake, you might end uploading the wrong files to the OWASP wiki 🙂

The script was created using the very powerful O2 MediaWiki APIs, who can also be seen in action in these two YouTube videos:

Here is this script source code:

var userAccount = @"accounts.xml".credential("owasp.dinis");     
var permitedFileTypes = "vsd, odp, gif, png, jpg, jpeg, doc, ppt, mp3, pdf, psd, zip, tar, tar.gz, tar.bz2, jar, docx, pptx, xls, xlsx";
//var topPanel = panel.clear().add_Panel();
var topPanel = "Tool - OWASP Wiki - File Uploader : {0}".format(permitedFileTypes).popupWindow(1000,500); 

var actionsPanel = topPanel.insert_Above(40,"Actions");
var recentChanges = topPanel.insert_Right("Recent Changes to OWASP Wiki"); 
var filesToUpload = topPanel.insert_Left(recentChanges.width()/2, "Files To Upload").add_TreeView();
var filesUploaded = topPanel.add_GroupBox("Files Uploaded").add_TextArea().wordWrap(false);
Label messageLabel = null;

var wikiApi = new OwaspWikiAPI(false);

Action showRecentChanges = `
Action login =
            if (userAccount.isNull())
                userAccount = ascx_AskUserForLoginDetails.ask();
            if (userAccount.isNull() || userAccount.UserName.inValid() )
                messageLabel.set_Text("Error, no user provided ").textColor(Color.Red);
                messageLabel.set_Text("Logging in as user: {0}".format(userAccount.UserName)).textColor(Color.DarkOrange);
                if (wikiApi.login(userAccount.UserName, userAccount.Password))
                    messageLabel.set_Text("Logged in OK as: {0}".format(userAccount.UserName)).textColor(Color.Green);    
                messageLabel.set_Text("Failed to Login as : {0}".format(userAccount.UserName)).textColor(Color.Red);    
            userAccount = null;           
Action<string> uploadFile =
                                    var fileUrl = wikiApi.uploadImage(fileToUpload);
                                    if (fileUrl.valid())
                                        filesUploaded.append_Line("Uploaded OK: {0} ->".line() +
                                                                  "\t{1}", fileToUpload , fileUrl);
                                        messageLabel.set_Text("Uploaded file: {0}".format(fileToUpload)).textColor(Color.Black);
                                        filesUploaded.append_Line("Error uploading: {0}", fileToUpload);
messageLabel = actionsPanel.add_Link("refresh recent changes table", ()=>showRecentChanges())
                            .append_Link("Login", ()=> login())

messageLabel.set_Text("To Upload files, please login");
filesToUpload.add_Node("After login, drop file here to upload");
                 foreach(var file in fileOrDir.files())




November 14, 2011 Posted by | MediaWiki, 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