Categories
Software Development

Apache, cgi-bins, and the Authorization header

I had a problem: Server A runs a web service, which requires users to authenticate using the standard HTTP authentication mechanism. Server B should have web pages that use AJAX to query A’s web services. Server B’s web pages also require authentication, using the same scheme, backend and database as server A. There are two problems:

  1. JavaScript web pages can only access web services/pages on the same server using XMLHttpRequest, for security reasons. Solution: Use a forwarding/proxy service. E.g. to access http://a.example.com/service from b.example.com add a service http://b.example.com/servicethat just forwards requests to the web service on A. This solution is quite straight forward.
  2. Since B uses the same authentication scheme as A we need to forward authentication information passed to B’s forwarding service on to A. Unfortunately this is not straight-forward, since the Apache HTTP Server provides no easy way to read the full authentication information passed to it via a cgi-bin. The only available information is the REMOTE_USER environment variable. This is not enough to construct a new Authenticationheader, though, since password information is stored encrypted in the account database.Finally I found a solution in the Zope 2 documentation. Apache’s mod_rewrite comes to the rescue. It allows you to read arbitrary HTTP headers and add arbitrary environment variables before executing a cgi-bin. The following recipe added to the appropriate .htaccess file adds a HTTP_AUTHORIZATION variable:
    RewriteEngine on
    RewriteBase /
    RewriteCond %{HTTP:Authorization}  ^(.*)
    RewriteRule ^(.*)$ $1 [e=HTTP_AUTHORIZATION:%1] 
    
Categories
Javascript

Loading Modules in JavaScript

One of the weaknesses of the JavaScript language is that it does not have the concept of “importing” or “including” other source files or modules. In client-side JavaScript as used in web browsers you have to include all JavaScript files you intend to use in the main HTML file like this:

<html>
    <head>
        <title>...</title>
        <script src="A.js"></script>
        <script src="B.js"></script>
        <script src="S.js"></script>
    </head>
    ...
</body>

In this case S.js is a page-specific JavaScript script that uses features from A.js and B.js.

The standard way to load other JavaScript files dynamically is to add a script element programmatically to the head section of the document, using DOM:

function include(filename) {
    var scriptTag = document.createElement("script");
    scriptTag.setAttribute("lang"), "javascript"));
    scriptTag.setAttribute("type"), "application/javascript"));
    scriptTag.setAttribute("src", filename);
    document.getElementsByTagName("head")[0].appendChild(scriptTag);
}

Unfortunately this approach has some problems as well: The include file is loaded “lazily”, i.e. the next time the JavaScript interpreter hands back control to the browser. (At least it is this way in Firefox.) If, for example, a file A.js defines a function func_a, the following will not work:

include("A.js");
func_a();

My first solution was to use a callback, invoked when the module has been loaded:

function include(filename, callback) {
    var scriptTag = createScriptTag(filename); // as above
    scriptTag.onreadystatechange = function() {
        if (scriptTag.readyState == "complete") {
            callback();
        }
    }
    scriptTag.onload = function() {
        callback(file);
    }
}

This solution uses the non-standard onload (Firefox) or onreadstatechange (IE) events. It is invoked like this:

include("A.js", function() {
    a_func();
});

This solution also has several problems: It is non-standard, it is ugly (though this can’t be helped, due to the asynchronous script loading), and including a module from a module still doesn’t work. To explain the last problem, I will use a script S.js which depends on the function a_func defined in A.js, which in turn depends on b_func defined in B.js. Now the code should look like this:

// S.js
include("A.js", function() {
    a_func();
});

// A.js
include("B.js", function() {
    a_func = function() {
    }
    a_func.prototype = new b_func();
});

// B.js
// ...

The problem is that the callback in S.js is not necessarily processed after the callback in A.js, leading to a_func being undefined.

The solution I have come up with is not particularily nice, but this can’t really be helped. Basically each module has to call a function when it has fully loaded, like this:

// A.js

include.module("B.js", function() {
    // ...

    include.moduleLoaded("A");
});

The main HTML file must load the include.js before loading any other module and modules should only be loaded via include.module. Also my implementation uses “real” module names, e.g. a.b.c instead of a/b/c.js. This allows me to expand the mechanism easily, for example to add a module search path.

Sample implementation

Categories
Magic the Gathering

PTQ Geneva in Berlin

Yesterday the Pro Tour Qualifier Geneva in Berlin was held at FUNtainment. We had 110 players, a rather high turnout, among them many players from Poland. It’s always nice to have these guys around. One thing I noted, though, was that I stepped in multiple times when a player and a spectator were speaking in Polish. When players and spectators do that in German I often don’t step in, since I hear what they say and most of the time it’s not about the game. So I subconsciously filter that talk out. I can’t do that for a language that I don’t understand, though.

Helping me were acting TO Peter, Christoph (L1), and Kersten, my promising judgeling. While we were understaffed by one person for this event (but aren’t we always?) the event went rather smooth. The main problem was that we couldn’t do as much deck checks as I would have liked to and that sometimes we couldn’t cover all the matches in overtime. One more judge would have been quite beneficial in these cases, but as I have explained before, we don’t have that many active judges anymore and a few possible candidates chose to play instead of judging.

Also of note was the high number of appeals I got. During the first two rounds I had three appeals, while I usually get about one per tournament. But this became less during later rounds.

About a quarter of an hour before the tournament began we had a call in the store. A rather young boy asked whether it was possible to participate in the event where “you can qualify for the Pro Tour”. I told him to hurry up, since we wanted to start soon. He showed up a bit too late with his mother, but I still let him participate. This was obviously his first sealed deck tournament, and I absolutely forgot to mention that the cards were in English. I would have liked to have more time to talk to him before the event to explain everything, but unfortunately didn’t have the time in the stress at tournament start. Well, he build an 80 card deck, playing all the basic lands from the tournament pack, although I had explained to him that he can get more lands if he wanted to. Not very surprisingly he went 0-4 drop. I am kind of sorry for him, and wish I could have found more time for him.

In the last round I handed back the decks from a deck check seven minutes into the round. The players from a neighbouring table asked me: “Can we get extra time? We didn’t start playing yet, since we couldn’t decide whether to take an intentional draw.” I explained to them the errors of their ways.

Categories
Python

PyUnit and Decorators

One of the shortcomings of the Python standard library is in my opinion that PyUnit doesn’t use decorators (as later versions of JUnit and NUnit do). Therefore I have written a sample implementation that adds decorator support. (unittest.pydiff to Python 2.5’s unittest.py)

To do:

  • Warn when old-style and new-style tests are mixed.
  • Throw an exception when multiple setup or teardown methods exist.
  • Ability to warn when old-style methods are used.
Categories
Magic the Gathering

German Nationals 2006

Last weekend I was judging at the German Magic: The Gathering Nationals 2006 in Aschaffenburg. I took the train on Thursday morning, leaving from the new main station in Berlin. The ride was fairly uneventful, but when I exchanged trains in Hanau, I met Martin Golm, a L2 judge from Dresden. I had travelled with Martin to Grand Prix Nottingham and also met him on the train ride to GP Hasselt. Travelling with and meeting Martin by chance has tradition by now. Arriving in Aschaffenburg we went to the hotel where we picked up coverage guy Hanno Terbuyken, before leaving to the site. (I can only recommend you check out the coverage. Hanno is easily my favorite coverage writer.)

Schloss Johannisburg in Aschaffenburg, Sven Teschke, CC-BY-SA-3.0

The site was near the Main river and Schloss Johannisburg. When we arrived the meat grinders were starting slowly. (Meat grinders are 64 person single elimination events, where the winner qualifies for German Nationals.) I helped with the meat grinders, but all in all it was a slow day. We had only six grinders in total, probably mainly because this time the meat grinders were outside of holidays. So I had enough time to meet people I hadn’t met for a long time and to watch the matches that were going on. Special congrats go to GerMagic’s webmaster EvilBernd, who won the last grinder of the day. He was complaining that the slowly increasing crowd of judges that were watching his matches were irritating him. All I can say is: Tough luck, win early grinders, where you still have less judges than players.

Lutz Hofmann’s (L3 from Berlin) meat grinder had a DQ situation. During a deck check I noticed something suspicious: The sleeves were cut badly. (This seems to be an increasingly common problem.) But there were two clearly distinguishable types of cuts. All lands plus four Chars were in one type of sleeves, while the other cards were in the other type. According to the player the sleeves had been bought on-site and were unplayed. It was a 100 sleeve pack of black Dragon Shields. While these are sold in quantities of 100 sleeves per pack, each pack consists of two separately produced part of 50 sleeves each. This explained the two sleeve types. In the end we were not convinced that the player had known about the production differences. Therefore Lutz did not disqualify the player, but issued a Marked Cards – Major penalty, resulting in a Match Loss. We advised the player to always shuffle the sleeves before sleeving the deck and wished him good luck in the next meat grinder (since meat grinders are single elimination events).

There was an interesting discussion among judges about issuing Match Losses in single elimination events. In the only draft grinder a player played a Devouring Light in a deck without sleeves, which was supposedly clearly marked due to wear. Some judges were reluctant to issue a Marked Cards – Major penalty, since this would mean a Match Loss at Rules Enforcement Level 3. In single elimination events this equals a disqualification from the event (sans consequences like DQ investigations and possible bannings). I firmly believe that a single elimination event is no reason to downgrade penalties, and using this as a reason to change penalties is wrong.

We only finished the meat grinders around 10:30 in the evening. I went on a food hunt. Not easy in a small town in Bavaria during the week. But eventually we found a döner booth that was still open.

The next day I was assigned to side events. Since I had not too much to do, I peeked a bit into judge certification and helped with deck list counting in the main event. The most exciting event of the day was the project Save the Judge Test. Level 3 judge Ingo Kemper was doing judge certification. Unfortunately at the start of this day our internet connection was down. When this problem was fixed, the Judge Center refused to generate new judge exams. Finally I went onto #mtgjudge on IRC, where Lee Sharpe could help us out and send a test he had still saved to Ingo. Unfortunately only one of the candidates on this day passed.

In the evening most of the event staff went into a local Irish Pub where we drafted Coldsnap.

Saturday was the second day of the main event. I worked in Tobias Licht’s deck check team. The day started with a Coldsnap draft. Unfortunately during the draft one of my local players was disqualified for peeking.

Later in the day during the constructed rounds, I had an interesting situation: While I walked the floor I picked up a card from the floor. It turned out to be a Rumbling Slum. After looking around at the matches still playing I saw a player playing a Zoo deck using the same sleeves. A quick check confirmed that the card was missing from his deck. But since the player and opponent didn’t count the deck, we couldn’t be sure whether the player presented an illegal deck or whether the card was dropped from the library during game play. The player claimed that he didn’t draw that card during the current game. After a consultation with head-judge Philip Schulz (L3) and backup Justus Rönnau (L3) we decided to issue a Warning for Procedural Error – Major and shuffle the card back into the library.

To be continued …

Categories
GNOME

Porting Tomboy from C# to C++

Hubert Figuiere writes about porting Tomboy from C# to C++. I tried to leave a comment in his blog, but something doesn’t work, so here is my comment:

Porting Tomboy from C# to C++ seems like a step back to me. C# is a higher level language than C++ and is much easier to write good and clean code with than C++. C++ rises the maintenance burden.

Also, at the moment Tomboy’s code base is under heavy development with one WSOP project (Maria Soler Climent’s) and one Summer of Code project (mine) going on. The code base is changing rapidly, so it seems this is a bad time to do such porting.

Categories
Python

XML Test Runner for PyUnit

JUnit features an XML Test Runner. This means that the result of a test run is not written to stdout, but instead written into an XML file. This XML file can then be automatically processed. This is for example useful for fully automated builds using software like CruiseControl. The XML output is easily converted into an XHTML file for easy human reading.

Until now PyUnit was lacking an XML Test Runner. Since I needed one for one of my projects that used CruiseControl, I wrote one. It is available for download here. Since this is an extension to a unit testing framework, the classes are of course fully tested. 🙂

If you have any suggestions or criticism, please let me know. I’m a nitpicker myself, so even if you have some small suggestions about coding style or improvement hints, I would like to hear about them.

Update: I have now submitted this patch to Python’s patch tracker, ticket number 1522704.

Update^2: I created a page with more information about PyUnit and CruiseControl integration, including sample configuration files and scripts.

Update^3: I updated the XmlTestRunner after input from Mirko Friedenhagen: It now recovers gracefully from unit tests overriding sys.stdout and sys.stderr, the XmlTestRunner returns the TestResult instance instead of a boolean value, and you can now stream multiple test suite results into a single XML file, since the XML header is not written to file streams by default.

Update 2017-10-30: While XMLTestRunner can be found on GitHub nowadays, its use has been deprecated for a while. Instead, use maintainer projects, such as unittest-xml-reporting.

Categories
Python

Python Warts

I started my own page of Python warts, similar to A. M. Kuchling’s popular page. At the moment it just features one wart (the len() function vs. a length property on container classes). But I plan to add more warts in the future. I will probably concentrate on warts in the standard library. (And there are tons of them.) Two warts that come to mind are the unpythonic (but very SAXy) SAX library, and several warts in the unittest module.

Categories
GNOME

Google Summer of Code and Networked Tomboy

My Google Summer of Code application, called Networked Tomboy was accepted. Just to quote myself:

Tomboy is a note-taking application for the GNOME desktop. As such it is evolving as a replacement for the traditional ‘sticky notes’ applet and offers several advantages, including easy formatting and wiki-style links. But currently Tomboy notes are limited to the desktop. That means that users can’t easily transfer their notes between different desktops (e.g. their home and work computer or their desktop and laptop PC) or publish their notes for other users.

This project is supposed to solve this problem. Using an abstraction of Tomboy’s data storage format and system, an alternative system for storing notes in a central repository will be developed. This repository can then be accessed by Tomboy instances. Additionally a note publishing system will be developed. It will allow to publish selected notes either on a local network (using Zeroconf) or to web pages.

I’m rather happy to get the opportunity to hack on a program that I use myself and that missed functionality I need.

Categories
Magic the Gathering

Team PTQ Charleston in Berlin

Yesterday we had a team PTQ for Pro Tour Charleston in Berlin. The turnout was pretty with 23 teams for a total of 69 players, although we had a few players from Hamburg and eventual winners, Team Hans (Hans-Joachim Höh, Pro Tour Honolulu quarterfinalist Maximilian Bracht, and Stefan Urban), came from further away even.

At first I was a bit worried, since my staff was rather inexperienced. Besides level 1 judge Christopher Eucken I had help from two judgelings (Lars-Peer and Kersten). Lars-Peer had helped us before and left a good impression as scorekeeper. Therefore I used him as scorekeeper again at this event, since I wanted to get much floor time. On the one hand I have done a lot of scorekeeping lately and wanted to hone my floor judging skills again. On the other hand I wanted to be able to give feedback to Christopher and our new judgeling, Kersten.

My team did good work and we managed to have a smooth event, so my worries weren’t justified. We had one situation where a player of team A had finished his match and leaned over to get a better look at the board of another match. Doing this he got a glimpse at the hand of the opponent team’s player of that match. He talked a bit more with his team, but after investigating I could determine that it was very unlikely he disclosed any information about the hand to his team mates.

The cut to the top 4 was rather exciting, since two last round matches in which all teams were still in contention for top 4 drew. In the end Team Hans slipped into top 4 on secondary tiebreaker over the Hamburg Hammelpriesters (Sebastian Homann, Merten Jensen, and Dennis Johannsen). Unfortunately during the top 4 there were two game wins by ruling (although in the end it probably didn’t matter in both cases). In the first situation Heartbeat player A combo’ed and finally tried to cast Maga, Traitor to Mortals. His opponent B claimed that A didn’t have the three black mana available that B needed for that. A had one Swamp and one Heartbeat of Spring out, but had used Early Harvest before to untap his lands. But B claimed that he knew exactly that among the three lands tapped to play the Heartbeat the player had used his Swamp. This would mean that A had no black mana left in the pool when he untapped with Early Harvest and therefore only two black mana still available. A couldn’t remember which lands he had tapped for the Heartbeat. B pointed out the three lands that were still neatly grouped together and also claimed that A didn’t move his lands around while playing stuff.

I had my attention divided between that match and their neighbour’s match, so I hadn’t taken notice what lands were tapped for playing Heartbeat. But B’s claims were largely consistent with my own observations. Additionally neither A nor B had made any notes about which mana was still available. A’s strongest argument was: “Using the black mana would have been stupid, since I knew what I wanted to play.” Since a lot of spells, including tutors had been played, there was no sane way to rewind the game state and I had to rule on it. Based on the fact that A failed to note down or announce what mana he retained when playing spells and based on B’s certainty about the tapped mana and the consistence with my own observations I ruled that A didn’t have a third black mana available and wouldn’t been able to play Maga.

The second ruling involved a very close third game between players C and D. C sacrified a creature during D’s turn to remove Ghost Council of Orzhova from the game. D asked: “When do you do that?” to which C replied: “End of turn.” Doing this End of Turn would leave C with no attacker during his own turn, since the Ghost Council would only return at his own End of Turn. Only when asked “Really?” did C correct himself: “No no, of course during the Second Main Phase.” Kersten was watching this match. When I discussed this with him, he thought about ruling by intent and let C activate the ability during the second main phase. I disagreed. This has been a sloppy play on C’s part, since he did not announce at first when he wanted to use the ability. D tried to clear up the game state by asking when he did that. To which C (probably lulled by the slow game) replied with the wrong answer. Since the “sloppiness”, i.e. the unclear game state, was cleared by D’s question, I do not think that Ruling by Intent applies here. In cases like this I follow another principle that I call Responsible Play: If a player uses explicit language (“End of turn” in this case) he will be held to it. Of course immediatly correcting oneself is perfectly ok for me: “End of turn. No wait, second main phase of course.” But in this case only the opponent asking “Really?” tipped him off that he probably made an error. If D hadn’t asked “When do you do this?” and had just let it go and then claimed that the Ghost Council’s ability was activated end of turn I would gladly rule by intent. (And in this case D would probably also face an Unsporting Conduct penalty.) Clearing up the game state on D’s part makes all the difference here.

On a side note: By asking this question D may have lead C into answering wrong, i.e. D might have known that Second Main Phase is the “right” answer and might have hoped that C answers wrongly. But in this case I see this as perfectly ok. He didn’t misrepresent the rules, the only thing he did was clearing up the game state and making use of the opponent’s lack of concentration.

The finals were tough and exciting. Team Hans played the Line-Inn Crew (Adrian Rosada, Dennis Jenkel, and Oliver Wieske). Stefan and Oliver had won their matches so the teams were drawn 1-1. The final match between Hajo and Dennis was also drawn, but finally Hajo managed to squeeze out a win. After the finals Team Hans drove on to play another PTQ in Bochum today. Good luck, guys!

Decklists (courtesy of the great EvilBernd)