Posts filed under ‘ekus.net’

Simple web proxy in ASP.NET

In last two weeks, on two separate occasions, I needed a simple web service that would act as proxy to remote servers.

First, while writing my crude twitter ticker in Silverlight, I run into issue with lack of support for GIF images in Silverlight, and potentially also with accessing 3rd party servers. Normally, Silverlight and Flash (and also JavaScript) are able to freely contact ONLY their server of origin, but due to XSS attacks accessing other hosts is… less than ideal.

In this case I set up a simple ASP.NET handler that receives requests from my Silverlight program using URL like this:
http://localhost/imageproxy.ashx?url=http://remote.server.com/some/alien/avatar.gif

then the service contacts the URL specified in parameter, downloads the data and returns it to the original Silverlight app, in single trip. In my case the service also re-encodes the images as JPEG’s or PNG’s which are easier to work with in SL, but that step is optional, as most of the pictures are JPEG’s anyway and are passed through without changes. I used code from the article Silverlight: Handling Cross-Domain Images and Gifs by and modified it slightly.

A week later I was forced to overhear my unholy fallen .netless colleagues talking repeatedly about problems with accessing MS Reporting Services from Hell Java and blaming Integrated Windows Authentication (a.k.a. NTLM). When they started considering setting up ISA Server (aptly renamed to Microsoft Forefront Threat Management Gateway), I offered a single-file alternative that I could write in 5 minutes. Java would call this unsecured proxy, which in turn would apply security and access the MS Reporting server.

Two hours later the file was mostly done, tested and somewhat working. In order to host it under IIS on Windows you need to put it some existing “web folder”, e.g. c:\Inetpub\wwwroot\ or create separate one using IIS manager. No manual compilation is needed, just make sure the server has ASP.NET installed and enabled (tested on version 4.0 and IIS 7.5).

The usage is similar to the previous example, but it adds hard-coded credentials and POST support, used for talking to SOAP web services.

Please see the whole file below, including a funny fake password. Some cleaning and tuning advised, regarding error handling and security. I’m posting it anyway, even though one could probably write it from scratch faster than read this lengthy blog post.

The file should be saved with .ashx extension. Use at your own risk.

<%@ WebHandler Language="C#" Class="Ekus.WebServiceProxy" %>
using System;
using System.Collections;
using System.Data;
using System.Drawing;
using System.IO;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Net;
using System.Collections.Generic;

namespace Ekus
{

	/// <summary>
	/// Receives a web request with target URL, 
	/// invokes another web request to the target URL with added NTLM credentials, 
	/// and returns the response to the original caller.
	/// </summary>
	
	public class WebServiceProxy : IHttpHandler
	{
		public void ProcessRequest(HttpContext context)
		{
			string webServiceUrl = context.Request["url"].ToString();
			string proxy;
			// proxy = "127.0.0.1:8888"; used for testing with Fiddler2

			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(webServiceUrl);
			if (proxy != null) req.Proxy = new WebProxy(proxy, true);
			// if SOAPAction header is required, add it here...
			req.Headers.Add("SOAPAction", context.Request.Headers["SOAPAction"]);
			req.ContentType = "text/xml;charset=\"utf-8\"";
			req.Accept = "text/xml";
			req.Method = context.Request.HttpMethod; // "POST";
			req.Credentials = new NetworkCredential(
				"joker", // username; didn't work when using domain\username format
				"funny",  // password
				"gotham"); // domain
			req.PreAuthenticate = true; // Cargo_cult_programming

			if (req.Method == "POST")
			{
				// copy original request "body" to the new request
				string input = new StreamReader(context.Request.InputStream).ReadToEnd();
				// encode it using the predefined encoding (see above, req.ContentType)
				System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
				byte[] bytesToSend = encoding.GetBytes(input);
				// Set the content length of the string being posted.
				req.ContentLength = bytesToSend.Length;
				Stream newStream = req.GetRequestStream(); // This method has the side effect of initiating delivery of the request in its current state to the server. Any properties like the request method, content type or content length as well as any custom headers need to be assigned before calling the GetRequestStream() method.
				newStream.Write(bytesToSend, 0, bytesToSend.Length);
				// Close the Stream object.
				newStream.Close();
			} // else GET, no body to send. Other verbs are not supported at the moment.

			WebResponse resp = req.GetResponse();
			Stream respStream = resp.GetResponseStream();
			StreamReader r = new StreamReader(respStream);
			// process SOAP return doc here. For now, we'll just send the XML out to the browser ...
			string output = r.ReadToEnd();
			context.Response.Write(output);
		}

		public bool IsReusable
		{
			get
			{
				return false;
			}
		}
	}
}
Advertisements

2011-02-13 at 1:11 2 comments

The safest password

Today at work I was forced to change my silly, complicated Windows password: Pas$w0rdX to Pas$w0rdY.
That’s it. I changed one letter and called it a day. And not just any letter. The last letter. And I changed it in the least relevant way. I incremented it by a single bit. Looking at binary representation, this is my password before and after the change:

010100000110000101110011001001000111011100110000011100100110010001011000
010100000110000101110011001001000111011100110000011100100110010001011001

Looks like my network administrator hopes that in case my old password was about to be compromised by a hacker (for example by using the simplest method possible – trying all possible combinations one after another), he/she won’t be able to hack it now. Phew, disaster averted.

This ridiculous waste of time led me to idea: in order to make the hacking as difficult as possible, I will switch to

The Ultimate Safest Password

Of course I could make it idiotically long, but where is the fun in that? Instead, I will use the strongest password that fits in the minimum length, lets say 8 characters.

Looking at the binary representation of my previous and current password, the solution presents itself very easily:
If somebody tries to iterate all possible values, they will (obviously) start from 0 and increment it over and over. Thus, the binary form of the very last password to hack is…
1111111111111111111111111111111111111111111111111111111111111111

This password is guaranteed to be the most difficult 8-letter password to break using the most sophisticated KISS algorithm known to man (exactly 264 = 1.84467441 × 1019 iterations, as opposed to 5.7920372 × 1018 for the old password limited to 8 characters). That’s mind-bogglingly 3.18 times more secure (requires 3.18 x longer time to hack using very brute force).

But wait, there’s more!

Translating to decimal, it’s series of 8 bytes with value 255 (binary 11111111) each.
And now, the ultimatest safety haxx0r. Please turn on the NumLock key on your keyboard, and check the character that the code 255 produces:

First, you need to open Notepad and press and hold Left Alt, and then use the numeric keypad to type the character code. Tablet and Apple users should not apply, they don’t know what a numpad (nor a password) is:

Apple keyboard without numpad

The location of the new, magical Numeric Pad on the current Apple keyboard

Still holding that Alt key? Type 255 on the numeric keypad (while nothing happens) and… release the Alt key.

That’s it! Did you miss it? You just typed it! Code 255 produces an invisible space character!
Now, type it 7 more times.

invisible password in notepad

invisible password in notepad

Now, you can even save it on pendrive or print it and tape it to your desk. Your ultimate password is invisible and secure!

2011-02-10 at 22:07

Are there any windows in Windows Phone 7?

A friend made a pun about lack of windows in the incoming Windows Phone 7:

image

http://twitter.com/marcin_walus/status/27182240050

Funny, because there seem to be none. Also, even in Windows Mobile, the predecessor to WP7, they weren’t really used (the only “window” that I could drag was probably a MessageBox control). However, since the WM was based on Windows CE, which in turn was based (visually) on Windows 95… there are windows there, and you can even move them ;-)

[DllImport("coredll.dll")]
extern private static int MoveWindow(IntPtr hWnd,
int X, int Y, int nWidth, int nHeight, int bRepaint);

While I am sure that similar API is technically present (though not available) on Windows Phone (which is based on Windows CE, too), I have even better answer to the title question:

The phone itself is a window. A window to the world your data:

panorama-ctrl_3

Image by Stephane Crozatier, http://blogs.msdn.com/b/stephanc/archive/2010/04/04/windows-phone-7-panorama-control-sample.aspx

The suggested UI layout for most applications, called Panorama, shows it very clearly, by offering a seamless – yet modular – view. It would be even cooler, if you could pan or tilt your phone (or move your head, tracked by the ..gulp.. non-existing front-facing camera) to change the “point of view”. But dragging with fingers should do for now.

What’s that? You asked for plural windows? Damn…

2010-10-13 at 9:29

Automatyczne auta

Jakąś ironią jest, że coś co określamy mianem “auta” czy “samochodu” nie potrafi samo jeździć (podobnie jest z samolotem, ale to raczej kwestia formy w języku polskim, w przeciwieństwie do międzynarodowego określenia automobilu).

Ostatnio wpadłem na artykuł o kolejnych postępach w pracy nad nauczeniem aut samodzielności: Audi widmo nabiera kolorów.

Artykuł, czy raczej sam fakt, niezbyt odkrywczy, ale ciekawy. Niestety komentarze tradycyjnie są bardzo… kolorowe.
Choć sprowadzają się do tego, że przeterminowany GPS wpędzi te auta do stawu. Załatwione, nic nie zastąpi człowieka. Wpisujcie miasta!

Aż ziewać by się chciało, gdyby nie ilość i powszechność tak krótkowzrocznych komentarzy. Dla mnie perspektywa robotyzacji jest oczywistością tak oczywistą jak to, że lód w słońcu topnieje a dysk twardy jest zawsze za mały. Skąd się zatem biorą forumowi nay-sayers, w dodatku w każdym temacie i w dużych ilościach?

Czy to jest nasza polska cecha? Chrześcijańska? Zachodnia? Czegoś nie było w Biblii, konstytucji ojców-założycieli, lub w tradycji naszych własnych ojców, więc to nie istnieje i nie zaistnieje? Oczywiście używamy komórek, internetu, jakiś komputer na końcu świata przysyła nam sms-a przypominającego o wydarzeniu z google calendar, ale to przecież nie znaczy że postęp galopuje na naszych oczach..? Po prostu to pojawiło się nagle samo z siebie i już tak zostało. A wcześniejsze telefony, radia, pagery, telefony satelitarne – one też były chorymi pomysłami przez cały okres developmentu, testów i uczenia się na błędach?

Dlaczego nasz dziadek który powiedziałby swoim kolegom w podstawówce że jego wnuki będą mogły nie tylko za darmo czytać gazety z całego świata w sekundę po ich opublikowaniu, ale będą też mogły w każdej chwili napisać i opublikować swoje artykuły, zdjęcia, przemyślenia, i udostępnić je jednym gestem miliardom ludzi – dlaczego ten dziadek byłby przez kumpli wyśmiany lub oblany dla jaj atramentem?

(a propos miliardów – zastanawiam się kim jest ta druga – oprócz mnie – osoba, która wg statystyk codziennie czyta mojego bloga?)

Jest wiele tematów, dla mnie oczywistych, a które ku mojemu zdumieniu nie są oczywiste dla mojego otoczenia (niekoniecznie najbliższego, ale generalnie z tej planety):
Globalizacja, unifikacja i drastyczna redukcja ilości języków którymi porozumiewać się będą nasze pra-prawnuki (przy zachowaniu dużej liczby środowiskowych slangów, jednak wewnątrz wspólnej całości), powszechne modyfikacje genetyczne, klonowanie i projektowanie “sztucznego” życia, kontrola klimatu, eliminacja (czy też “zużycie się”) zarówno wszelkich religii jak i wojen, sztuczna inteligencja mądrzejsza od człowieka (i która go zastąpi w toku przewrotnie konsekwentnej ewolucji), są dla mnie tak samo nieuniknione (a dla wielu tak samo niedorzeczne) jak utrata przez Google dominującej pozycji na rynku wyszukiwarek.
Wake up, people! Czy nikt nie widzi ciągłości naszego rozwoju i – nade wszystko – jego kształtu i tendencji?

Uff, udało się wypocić kolejny wpis w tym półroczu. Zawsze lubiłem czerwiec.

2010-06-30 at 16:17

Simple .NET application testing with PowerShell

I had a need today to quickly test some functionality of an existing assembly. It is a part of a web app, but can be tested without a web context. It also could be (and partly is) tested using unit testing (nunit in this case). Unfortunately, I need to break some rules and manually modify the app’s environment during the test, to see how it reacts.

We (at my work) are using a relatively unpopular, yet very nice library for authorization management: Microsoft Authorization Manager, also called AzMan. Interestingly, it is a COM library with official Interop wrapper available, for which we have created yet another simple wrapper, to better interface with our system.

AzMan lets us define roles and operations, and then mix and match them to assign appropriate user privileges to our users. Its API is very simple, but it offers very flexible and elegant model. Obviously, we define some roles, such as salespeople and administrators, and assign users to them. What is particularly convenient for us is that we DO NOT hard-code any roles directly in our source:

if User.IsInRole("admin") or User.IsInRole("sales") 
then enableFeatureX

Instead, our developers only need to care about actual privileges:

if User.HasAccess(FeatureX) then enableFeatureX

 

This gives us great flexibility regarding actual roles. One day we can give some privilege to engineers, another day to salespeople, and even to a single user, if he is the boss’s son. I was surprised (ok, not really) to see how often business rules need to be changed in a company. Especially when we deploy our application at several locations, all with their little quirks and differences. The idea of abstract “scopes” in AzMan elevates us to a whole new level, where we can customize role definitions to be partly inherited from “global” roles, but adjusted to local needs. And all this without really recompiling the app.

For example, in a disk management system scopes can be folders or disks, in a company they can define divisions, or – like in our case – separate manufacturing sites. AzMan also allows us to use simple code inside a privilege check:

if cost>1000 then return false

Such snippets of code are called BizRules and offer even more flexibility without recompiling the actual app, but we decided to stick to simple true/false flags instead.

In our application we keep a simple definition of roles and privileges, called security policy, in AzMan-specific XML file, though there are other ways. When our application is loaded, we initialize a global AzMan model and create a security context for each user. The problem I worked on today is: Is AzMan aware of any changes made to the xml policy file after it has been initialized? I have read different opinions, but our experience showed that our web app had to be restarted to reload the file. Interestingly, there is a method in AzMan called UpdateCache, which we didn’t use, but which seemed to fit our needs.

Not wanting to play with recompilation of our actual complex app, I firstly used PowerShell to slip into the assembly and play around, dynamically calling some code.

I knew that PowerShell (object-aware command line on steroids) was by default included in Windows 7, but it turns out that also included is a nice PowerShell ISE (integrated scripting environment).

powershell in windows 7

Of course the ISE is not necessary to get started with PowerShell, as we can use a simple PowerShell console, but the tool is a nice step up. Oh, and it includes live console, anyway.

PowerShell ISE

The first  thing we need to do is to import the assembly:

[System.Reflection.Assembly]::LoadFile(
"C:\Path\To\Security.dll")

Then we need to instantiate the Model which in turn is used to create user context:

$model = New-Object Security.Model;
$model.AppLoaded;
# the above returns false

$model.LoadApp("msxml://C:\Policy.xml", "App");
$model.AppLoaded;
# now returns true

$user = $model.LoadCtx("S-1-XXX");
$user.HasAccess([Security.Operations]::AccessDenied, "");
# returns false, and always should, for everybody.

 

Now the nunit-unfriendly part: I quickly update the Policy.xml file (using azman.msc in Windows 7) and give the user with ID “S-1-XXX” access to operation “AccessDenied”.

Since my PowerShell session is still live, I can test $user.HasAccess again.

# now we can update the underlying policy file
# and run the commands below:

$user.HasAccess([Security.Operations]::AccessDenied, "");
# still returns false because policy has not been reloaded

 

Turns out, the change was not picked up by our little Security assembly. Luckily, all we need to do is to add a call to UpdateCache:

$model.UpdateCache();
$user.HasAccess([Security.Operations]::AccessDenied, "");
# returns true! success!

This way I have successfully tested my code. I only need to unassign the AccessDenied operation, since my real unit tests require it to be never used by anybody.
In addition, I’ve accomplished two more things:

  • learned PowerShell a tiny bit more
  • created script that could be automated for integration testing, if only it had some real value ;-)

All the script commands above can be called either from PowerShell console, one be one, or pasted into .ps1 file (PowerShell script). Of course, the .ps1 file will not wait for you to fiddle with the policy.xml file, so you would have to add the appropriate code yourself (either call to pause/sleep or some kind of xml poke for full automation).

P.S.

If you liked AzMan, you should take a look at NetSqlAzMan – open source implementation, without COM dependency but with very similar look&feel. I am considering upgrading to it from AzMan in the future.

2010-01-07 at 22:56

Clipboard image support in Silverlight

Clipboard text support is an obvious feature for silverlight, but clipboard image support could be silverlight’s “killer feature”, and help developers choose it over Air, Flash or javascript.

Continue Reading 2009-11-26 at 10:23

Sieciowe porządki, część 2: energooszczędny serwer

Jako geek mam wiele zboczeń, ale szczególnie cenię sobie to dotyczące ekologii, od czasów kiedy pacholęciem będąc poznawałem Bieszczady. Co prawda nie byłem harcerzem ani innym zorganizowanym skautem, ale dzięki odpowiedniej opiece i zachęcie udało mi się w czynie społecznym posadzić kilkaset drzew i wynieść z lasu podobną ilość porzuconych butelek.

Dlatego z ciężkim sercem słuchałem nieraz nocnego warczenia mojego komputera, który zużywał wiadro prądu, mimo że był obciążony zaledwie w kilku procentach podczas ściągania różnych… triali, dem i freeware’ów.

Rozwiązanie problemu zbiegło się w czasie z moją zabawą Home Serverem, choć nie od razu było ono wygodne. Przez pewien czas mój Windows Home Server działał jako maszyna wirtualna pod MS Virtual Serverem (zwykły MS Virtual PC nie obsługiwał dużych dysków). Był to podpięty przez USB 1-terabajtowy dysk WD Green Power (z tego co pamiętam, ciągnie on ok. 8 watów zamiast tradycyjnych(?) 10). Dzięki temu mój WHS – nieświadomy niczego – działał czasem “wewnątrz” netbooka, a czasem w ramach (w RAMie?) mojego desktopa. Owe 8W to jak dotąd mój rekord, w praktyce jednak rozwiązanie to było niedoskonałe, głównie za sprawą niskiego transferu i zabawy z wirtualnymi kartami sieciowymi (może uda mi się kiedyś napisać o tym więcej).

Aktualnie mój Chomik (WHS) działa bezpośrednio zainstalowany na wspomnianym netbooku i póki co jestem z tego rozwiązania zajebardzo dumny.

P1210738P1210743 P1210750 P1210764

Składniki:

  • netbook asus eee 900A, cena ok. 150-180 USD za refurbished. Free shipping w USA, opłaca się zwłaszcza kiedy trafi się darmowy przemyt ;-)
  • dysk 1TB Western Digital Green Power, ok 70-100 USD (300 PLN)
  • adapter mini-pci to SATA, opcjonalny bo można lutować SATA bezpośrednio do płyty ale adapter to dobry kompromis dla takich jak ja lutników. Bodajże 8 USD z przesyłką listem z Hong Kongu do Polski.
  • kabel+śledź eSATA do rozbiórki i lutowania, ok. 8 USD (25 PLN)
  • obudowa na dysk 3,5” USB+eSATA, ok. 30 USD (100 PLN). Częściowo opcjonalna, ważniejszy jest sam zasilacz 5V+12V.

W sumie ok. 300 USD, ale można taniej, zwłaszcza gdy niektóre części zalegają nam w szafie. Niestety po dodaniu kosztu licencji WHS (ok 100 USD) sprawa jest mniej fajna ale za to mamy bardzo energooszczędny serwer z MONITOREM (9”) i kul touchpadem multi-touch ;-), a w niektórych przypadkach także z bateryjnym podtrzymywaniem zasilania.
Co więcej system WHS wcale nie jest niezbędny, 80% jego funkcjonalności (torrent i NAS) można zrobić za darmo na Win XP czy innym Linuksie. Pozostałe 20% również, o ile kilka nieprzespanych nocy mamy też “za darmo”. Co osobiście uważam za bardzo kuszące, po tym jak WHS zawiódł mnie kilkakrotnie. Serwer przy normalnym użyciu nie przekracza 20 watów. Sam dysk zabiera 8,3 wata a monitor sporo poniżej 1.

Uwagi i nabyte doświadczenia:

  • podobno można zainstalować działający system Windows 2003 Server (czyli pewnie i WHS) tak, aby bootować z niego przez USB. Jednak SATA działa sporo szybciej i nie wymaga software’owego hackowania. A hackowanie hardware’owe jest jak wiadomo bardziej macho.
  • podłączenie SATA do płyty głównej lub do adaptera można zrobić prawie na ślepo (tzn. kolejność trzeba zachować, ale trudno czasem zgadnąć z której strony jest pin nr 1: http://pinouts.ru/HD/serialATA_pinout.shtml). Jest to 7 kabelków które jeśli się je podepnie odwrotnie, nic nie zrobią złego tylko nam nie wykryje dysku. Sprawdziłem, po przelutowniu w drugą stronę zadziałało. Oczywiście zasilanie to inna bajka ale tego nie hackowałem.
  • w przypadku mojego asusa – aby wykrył dysk SATA konieczne było zaktualizowanie BIOSu, bardzo proste (plik ROM na pendrive, boot).
  • z oczywistych względów warto podpiąć kablowy Ethernet zamiast WiFi (z drugiej strony wbudowane WiFi pozwala nam na zamurowanie serwera w ścianie lub pod wanną. Ale o tym zboczeniu innym razem).
  • Windows Home Server z powodzeniam działa jako zwykły domowy PC, z monitorem, kamerką USB, Youtubem, Winampem i Skypem.
  • W moim przypadku jest to zawsze włączony kuchenny skajpofon…
  • …oraz aktywowana ruchem zdalna kamera stojąca na straży lodówki – http://highlightcam.com/ ).
  • VNC to bardzo dobry zdalny dostęp do MONITORA serwera (zamiast osobnej sesji terminalowej). Można żonie rozłączyć skajpa. Aktualnie używam RealVNC bo jest częścią świetnego multi-instalatora http://ninite.com/
  • RealVNC choć instaluje się jako serwis w Windowsie, to nie dodaje siebie do wyjątków firewalla, trzeba to zrobić ręcznie (port 5900).
  • Zamiast dysku 3,5” bardzo warto rozważyć dysk 2,5”. Z moich kilkumiesięcznych doświadczeń wynika, że 500GB na spory czas wystarczy, później można uzbierać na drugi taki sam. Do SATA podpięty oczywiście bedzie tylko jeden, ale oba mogą ciągnąć prąd z USB, eliminując dodatkowy zasilacz 5V+12V…
  • albowiem eliminacja zasilacza dysku sprawia, że bateria w netbooku zadziała jak UPS, więc mamy serwer z prawdziwego zdarzenia, który się prędzej zahibernuje niż da zabić. To jest aktualnie mój drugi priorytet na liście ToDo.
  • dodatkowe dyski na USB mogą być 3,5-calowe, energożerne i bez UPSa, zwłaszcza gdy
    • potrafią/pozwalają się wyłączać podczas bezczynności
    • ewentualny zanik zasilania nie jest dla nich dużym problemem (przeważnie i tak są w spoczynku lub co najwyżej są odczytywane a nie zapisywane)
  • mój task numero uno to zainstalowanie TrueCrypta i zaszyfrowanie całego WHSa tak, jak to miało miejsce gdy Chomik był wirtualną maszyną w pliku .VHD
  • …niestety będzie to wymagało ode mnie (a przynajmniej będzie zalecało) lockowania konsoli, co jest niefajne w przypadku kuchennego komputera z kiepską/chowaną klawiaturą. Może czytnik odcisku palca załatwi sprawę, albo logowanie rozpoznawaniem twarzy przez kamerkę lub na podstawie bliskości telefonu z Bluetoothem. Niestety^2 wszystkie te rozwiązania podnoszą trochę zużycie energii.

Na koniec uwaga na temat niezawodności takiego zastosowania. Nie jest ono najwyższe, zwłaszcza w zasięgu dzieci które lubią kabelki; warto od razu pomyśleć o zamkniętej i unieruchomionej obudowie lub o innym zabezpieczeniu naszego zestawu. Z chwilą podpięcia do ethernetu nasz netbook przestaje być mobilny i musimy się z tym pogodzić. Darujmy sobie próby przestawiania, ustawiania, ciągłego rekonfigurowania. Wiem, bo dostałem nauczkę która nieomal kosztowała mnie dysk twardy i trochę danych. Najlepiej zamurować całość w ścianie. To jest mój trzeci task na liście ToDo :-)

2009-11-14 at 1:17 1 comment

Older Posts


RSS Unknown Feed

  • An error has occurred; the feed is probably down. Try again later.

RSS Unknown Feed

  • An error has occurred; the feed is probably down. Try again later.

Feeds

del.icio.us/Ekus