<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -4,10 +4,9 @@
 
 static lfmmethod const album_method_declarations[] =
 {
-	{&quot;album.addTags&quot;, {{&quot;tags&quot;, utf8_array2csl, FALSE}}},
-    {&quot;album.getInfo&quot;, {{&quot;mbid&quot;, NULL, TRUE}}},
-    {&quot;album.removeTag&quot;, {{&quot;tag&quot;, NULL, FALSE}}},
-    {NULL}
+	{&quot;album.addTags&quot;,   POST_METHOD, {{&quot;tags&quot;, utf8_array2csl, FALSE}}},
+    {&quot;album.getInfo&quot;,   GET_METHOD,  {{&quot;mbid&quot;, NULL, TRUE}}},
+    {&quot;album.removeTag&quot;, POST_METHOD, {{&quot;tag&quot;, NULL, FALSE}}}
 };
 
 //enum has to be index of declarations</diff>
      <filename>album.c</filename>
    </modified>
    <modified>
      <diff>@@ -4,4 +4,13 @@
 #include &quot;include.h&quot;
 #include &quot;callback.h&quot;
 
+void album_get_artist_name(const gchar* musicbrainz_id, utf8_callback callback, gpointer user_data);
+void album_get_musicbrainz_id(const gchar* artist, const gchar* album, utf8_callback callback, gpointer user_data);
+void album_get_url(const gchar* artist, const gchar* album, url_callback callback, gpointer user_data);
+void album_get_release_date_time(const gchar* artist, const gchar* album, date_time_callback callback, gpointer user_data);
+void album_get_image_url(const gchar* artist, const gchar* album, const enum image_size size, url_callback callback, gpointer user_data);
+void album_get_listener_count(const gchar* artist, const gchar* album, uint_callback callback, gpointer user_data);
+void album_get_play_count(const gchar* artist, const gchar* album, uint_callback callback, gpointer user_data);
+void album_get_top_tags(const gchar* artist, const gchar* album, tags_callback callback, gpointer user_data);
+
 #endif /*ALBUM_H_*/</diff>
      <filename>album.h</filename>
    </modified>
    <modified>
      <diff>@@ -9,18 +9,17 @@ gchar* utf8_copy(gpointer data)
 
 static const lfmmethod artist_method_declarations[] =
 {
-	{&quot;artist.addTags&quot;, {{&quot;tags&quot;, utf8_array2csl, FALSE}}},
-    {&quot;artist.getEvents&quot;},
-    {&quot;artist.getInfo&quot;, {{&quot;mbid&quot;, utf8_copy, TRUE}}},
-    {&quot;artist.getSimilar&quot;, {{&quot;limit&quot;, uint2utf8, TRUE}}},
-    {&quot;artist.getTopAlbums&quot;},
-    {&quot;artist.getTopFans&quot;},
-    {&quot;artist.getTopTags&quot;},
-    {&quot;artist.getTopTracks&quot;},
-    {&quot;artist.removeTag&quot;, {{&quot;tag&quot;, NULL, FALSE}}},
-    {&quot;artist.search&quot;, {{&quot;limit&quot;, uint2utf8, TRUE}, {&quot;page&quot;, uint2utf8, TRUE}}},
-    {&quot;artist.share&quot;, {{&quot;recipient&quot;, utf8_array2csl, FALSE}, {&quot;message&quot;, NULL, TRUE}}},
-    {NULL}
+	{&quot;artist.addTags&quot;,      POST_METHOD, {{&quot;tags&quot;, utf8_array2csl, FALSE}}},
+    {&quot;artist.getEvents&quot;,    GET_METHOD},
+    {&quot;artist.getInfo&quot;,      GET_METHOD,  {{&quot;mbid&quot;, utf8_copy, TRUE}}},
+    {&quot;artist.getSimilar&quot;,   GET_METHOD,  {{&quot;limit&quot;, uint2utf8, TRUE}}},
+    {&quot;artist.getTopAlbums&quot;, GET_METHOD}, 
+    {&quot;artist.getTopFans&quot;,   GET_METHOD},
+    {&quot;artist.getTopTags&quot;,   GET_METHOD},
+    {&quot;artist.getTopTracks&quot;, GET_METHOD},
+    {&quot;artist.removeTag&quot;,    POST_METHOD, {{&quot;tag&quot;, utf8_copy, FALSE}}},
+    {&quot;artist.search&quot;,       GET_METHOD,  {{&quot;limit&quot;, uint2utf8, TRUE}, {&quot;page&quot;, uint2utf8, TRUE}}},
+    {&quot;artist.share&quot;,        POST_METHOD, {{&quot;recipient&quot;, utf8_array2csl, FALSE}, {&quot;message&quot;, NULL, TRUE}}}
 };
 
 //enum has to be index of declarations
@@ -35,7 +34,7 @@ enum artist_methods
 	get_top_fans,
 	get_top_tags,
 	get_top_tracks,
-	removeTag,
+	remove_tag,
 	search,
 	share
 };
@@ -53,7 +52,9 @@ static const lfmget primary_methods[] =
 	{&amp;artist_method_declarations[get_info], {&quot;artist&quot;, &quot;stats&quot;, &quot;plays&quot;}, DATA_UINT},
 	{&amp;artist_method_declarations[get_info], {&quot;artist&quot;, &quot;bio&quot;, &quot;published&quot;}, DATA_DATE_TIME},
 	{&amp;artist_method_declarations[get_info], {&quot;artist&quot;, &quot;bio&quot;, &quot;summary&quot;}, DATA_UTF8},
-	{&amp;artist_method_declarations[get_info], {&quot;artist&quot;, &quot;bio&quot;, &quot;content&quot;}, DATA_UTF8}	
+	{&amp;artist_method_declarations[get_info], {&quot;artist&quot;, &quot;bio&quot;, &quot;content&quot;}, DATA_UTF8},
+	{&amp;artist_method_declarations[add_tags], {}, DATA_VOID},
+	{&amp;artist_method_declarations[remove_tag], {}, DATA_VOID}	
 };
 
 enum primary_info
@@ -69,7 +70,9 @@ enum primary_info
 	ARTIST_PLAY_COUNT,
 	ARTIST_TEXT_PUBLISHED,
 	ARTIST_SUMMARY,
-	ARTIST_DESCRIPTION
+	ARTIST_DESCRIPTION,
+	ARTIST_ADD_TAGS,
+	ARTIST_REMOVE_TAG
 };
 
 lfmget related_methods[] =
@@ -96,7 +99,7 @@ enum related_info
 	ARTIST_TOP_TRACKS
 };
 
-G_GNUC_NULL_TERMINATED void artist_get_info_with_parameters(const gchar* artist, const lfmget* call, gpointer callback, gpointer user_data, ...)
+G_GNUC_NULL_TERMINATED void artist_call_method_with_parameters(const gchar* artist, const lfmget* call, gpointer callback, gpointer user_data, ...)
 {	
 	createv(lfmparametervalue, parameters);
 		
@@ -110,7 +113,7 @@ G_GNUC_NULL_TERMINATED void artist_get_info_with_parameters(const gchar* artist,
 	
 	fill_parameters(parameters, call-&gt;method, &amp;vl);
 	
-	get_data_from_method(call, parameters, callback, user_data);
+	call_method(call, parameters, callback, user_data);
 	
 	va_end(vl);
 	destroyv(lfmparametervalue, parameters);
@@ -118,14 +121,14 @@ G_GNUC_NULL_TERMINATED void artist_get_info_with_parameters(const gchar* artist,
 
 void artist_get_info(const gchar* artist, const lfmget* call, gpointer callback, gpointer user_data)
 {
-	artist_get_info_with_parameters(artist, call, callback, user_data, NULL);
-}  
+	artist_call_method_with_parameters(artist, call, callback, user_data, NULL);
+}
 
 //Primary information
 
 void artist_get_name(const gchar* musicbrainz_id, utf8_callback callback, gpointer user_data)
 {
-	get_info_with_parameters(&amp;primary_methods[ARTIST_NAME], callback, user_data, musicbrainz_id, NULL);
+	call_method_with_parameters(&amp;primary_methods[ARTIST_NAME], callback, user_data, musicbrainz_id, NULL);
 }
 
 void artist_get_musicbrainz_id(const gchar* artist, utf8_callback callback, gpointer user_data)
@@ -188,6 +191,16 @@ void artist_get_description(const gchar* artist, utf8_callback callback, gpointe
 	artist_get_info(artist, &amp;primary_methods[ARTIST_DESCRIPTION], callback, user_data);	
 }
 
+void artist_add_tags(const gchar* artist, const gchar** tags, void_callback callback, gpointer user_data)
+{	
+	artist_call_method_with_parameters(artist, &amp;primary_methods[ARTIST_ADD_TAGS], callback, user_data, tags, NULL); 
+}
+
+void artist_remove_tag(const gchar* artist, const gchar* tag, void_callback callback, gpointer user_data)
+{
+	artist_call_method_with_parameters(artist, &amp;primary_methods[ARTIST_REMOVE_TAG], callback, user_data, tag, NULL);
+}
+
 //
 //Related information
 //
@@ -200,7 +213,7 @@ void artist_get_events(const gchar* artist, events_callback callback, gpointer u
 //0 means no limit
 void artist_get_similar_artists(const gchar* artist, guint limit, artists_callback callback, gpointer user_data)
 {
-	artist_get_info_with_parameters(artist, &amp;related_methods[ARTIST_SIMILAR_2], callback, user_data, limit, NULL);
+	artist_call_method_with_parameters(artist, &amp;related_methods[ARTIST_SIMILAR_2], callback, user_data, limit, NULL);
 }
 
 void artist_get_tags(const gchar* artist, tags_callback callback, gpointer user_data)
@@ -228,12 +241,7 @@ void artist_get_top_tracks(const gchar* artist, tracks_callback callback, gpoint
 	artist_get_info(artist, &amp;related_methods[ARTIST_TOP_TRACKS], callback, user_data);
 }
 
-void artist_add_tags()
-{
-}
-
 /*
-    * artist.removeTag
     * artist.search
     * artist.share
 */</diff>
      <filename>artist.c</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,8 @@ void artist_get_play_count(const gchar* artist, uint_callback callback, gpointer
 void artist_get_published_date_time(const gchar* artist, date_time_callback callback, gpointer user_data);
 void artist_get_summary(const gchar* artist, utf8_callback callback, gpointer user_data);
 void artist_get_description(const gchar* artist, utf8_callback callback, gpointer user_data);
+void artist_add_tags(const gchar* artist, const gchar** tags, void_callback callback, gpointer user_data);
+void artist_remove_tag(const gchar* artist, const gchar* tag, void_callback callback, gpointer user_data);
 
 //
 //Related information</diff>
      <filename>artist.h</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@
 
 const lfmmethod authentication_method_declarations[] = 
 {
-	{&quot;auth.getToken&quot;, {}, {{TOKEN_NOT_GRANTED, &quot;There was an error granting the request token. Please try again later.&quot;},{0, NULL}}}
+	{&quot;auth.getToken&quot;, GET_METHOD, {}, {{TOKEN_NOT_GRANTED, &quot;There was an error granting the request token. Please try again later.&quot;},{0, NULL}}}
 };
 
 //enum has to be index of declarations
@@ -28,7 +28,7 @@ enum primary_info
 
 void authentication_get_token(utf8_callback callback, gpointer user_data)
 {
-	get_info_with_parameters(&amp;primary_methods[AUTHENTICATION_GET_TOKEN], callback, user_data, NULL);
+	call_method_with_parameters(&amp;primary_methods[AUTHENTICATION_GET_TOKEN], callback, user_data, NULL);
 }
 
 struct authenticate_data</diff>
      <filename>authentication.c</filename>
    </modified>
    <modified>
      <diff>@@ -20,6 +20,7 @@ enum error_codes
     SUBSCRIBERS_ONLY      = 12
 };
 
+typedef void (*void_callback)(gpointer user_data, GError* error);
 typedef void (*utf8_callback)(const gchar* utf8, gpointer user_data, GError* error);
 typedef void (*url_callback)(const gchar* url, gpointer user_data, GError* error);
 typedef void (*uint_callback)(guint digit, gpointer user_data, GError* error);</diff>
      <filename>callback.h</filename>
    </modified>
    <modified>
      <diff>@@ -8,8 +8,12 @@
 #define API_KEY &quot;100780b228c8aa69be51d709572b45b8&quot;
 #define SECRET &quot;ba296e6c0de47df63b43d4410a702626&quot;
 #define WEBSERVICE_URL &quot;http://ws.audioscrobbler.com/2.0/&quot;
-static const char METHOD_URL[] = WEBSERVICE_URL&quot;?method=&quot;;
-static const char API_PARAMETER[] = &quot;&amp;api_key=&quot;API_KEY;
+#define METHOD_KEY &quot;method&quot;
+#define METHOD_PARAMETER &quot;?&quot;METHOD_KEY&quot;=&quot;;
+static const char METHOD_URL[] = WEBSERVICE_URL&quot;&quot;METHOD_PARAMETER;
+
+#define API_PARAMETER &quot;&amp;api_key=&quot;API_KEY
+static const char API_PARAMETER_ARRAY[] = API_PARAMETER;
 
 size_t sum_uintv(guint* array)
 {
@@ -108,7 +112,7 @@ EMBED_PRINT_FUNCTIONS(token, &quot;Token&quot;)
 
 const lfmmethod token_method_declarations[] = 
 {
-	{&quot;auth.getSession&quot;, {{&quot;token&quot;, NULL, FALSE}}, {{AUTHENTICATION_FAILED, &quot;Invalid authentication token supplied&quot;},{TOKEN_UNAUTHORIZED, &quot;This token has not been authorized&quot;},{TOKEN_EXPIRED, &quot;This token has expired&quot;},{0, NULL}}}
+	{&quot;auth.getSession&quot;, GET_METHOD, {{&quot;token&quot;, NULL, FALSE}}, {{AUTHENTICATION_FAILED, &quot;Invalid authentication token supplied&quot;},{TOKEN_UNAUTHORIZED, &quot;This token has not been authorized&quot;},{TOKEN_EXPIRED, &quot;This token has expired&quot;},{0, NULL}}}
 };
 
 enum token_method
@@ -132,17 +136,17 @@ enum token_data
 
 void session_get_name(const gchar* token, utf8_callback callback, gpointer user_data)
 {
-	get_info_with_parameters(&amp;token_data_declarations[SESSION_NAME], callback, user_data, token, NULL); 
+	call_method_with_parameters(&amp;token_data_declarations[SESSION_NAME], callback, user_data, token, NULL); 
 }
 
 void session_get_key(const gchar* token, utf8_callback callback, gpointer user_data)
 {
-	get_info_with_parameters(&amp;token_data_declarations[SESSION_KEY], callback, user_data, token, NULL);
+	call_method_with_parameters(&amp;token_data_declarations[SESSION_KEY], callback, user_data, token, NULL);
 }
 
 void session_is_subscriber(const gchar* token, boolean_callback callback, gpointer user_data)
 {
-	get_info_with_parameters(&amp;token_data_declarations[SESSION_IS_SUBSCRIBER], callback, user_data, token, NULL);
+	call_method_with_parameters(&amp;token_data_declarations[SESSION_IS_SUBSCRIBER], callback, user_data, token, NULL);
 }	
 
 void token_request_authorization(const gchar* token)
@@ -203,7 +207,7 @@ const gchar* token_get_session(const gchar* token)
 
 void token_get_signature(const gchar* token, const gchar* method_name)
 {
-	gchar* string = g_strdup_printf(&quot;api_key&quot;API_KEY&quot;token%smethod%s&quot;SECRET, token, method_name);
+	gchar* string = g_strdup_printf(&quot;api_key&quot;API_KEY&quot;token%s&quot;METHOD_KEY&quot;%s&quot;SECRET, token, method_name);
 	//gchar* signature = md5();
 	g_free(string);
 }
@@ -300,6 +304,8 @@ struct xml_parser
 	size_t* text_lengths;
 	gboolean is_error;
 	guint error_code;
+	GFunc cleanup;
+	gpointer cleanup_data;
 };
 
 const gchar** get_paths(const struct xml_parser* parser)
@@ -712,7 +718,7 @@ lfmproxy* proxy_init()
 			FALSE,
 			G_THREAD_PRIORITY_LOW,
 			&amp;error
-		);	
+		);
 	
 	return proxy;
 }
@@ -726,7 +732,7 @@ void proxy_destroy(lfmproxy* proxy)
 		
 	proxy_end_process(proxy);
 		
-	CURLMcode code = curl_multi_cleanup(proxy-&gt;multi_handle);
+	curl_multi_cleanup(proxy-&gt;multi_handle);
 	g_free(proxy);
 }
 
@@ -745,16 +751,8 @@ size_t parse_xml(void *ptr, size_t size, size_t nmemb, void *stream)
 	return 0;
 }
 
-void proxy_request(lfmproxy* proxy, const lfmget* call, const lfmparametervalue** parameters, gpointer callback, gpointer user_data)
+struct xml_parser* init_parser(const lfmget* call, gpointer callback, gpointer user_data, GFunc cleanup, gpointer cleanup_data)
 {
-	CURL* easy_handle = curl_easy_init();
-	
-	gchar* url = build_request_url(easy_handle, call-&gt;method-&gt;name, parameters);
-	CURLcode code = curl_easy_setopt(easy_handle, CURLOPT_URL, url);	
-	g_free(url);
-	
-	code = curl_easy_setopt(easy_handle, CURLOPT_HTTPGET, TRUE);
-	
 	struct xml_parser* parser = g_new(struct xml_parser, 1);
 	parser-&gt;call = call;
 	parser-&gt;collect = FALSE;
@@ -765,6 +763,22 @@ void proxy_request(lfmproxy* proxy, const lfmget* call, const lfmparametervalue*
 	parser-&gt;text_lengths = g_new(size_t, 1);
 	*parser-&gt;text_lengths = 0;
 	parser-&gt;is_error = FALSE;
+	parser-&gt;cleanup = cleanup;
+	parser-&gt;cleanup_data = cleanup_data;
+	return parser;	
+}
+
+void proxy_request(lfmproxy* proxy, const lfmget* call, const lfmparametervalue** parameters, gpointer callback, gpointer user_data)
+{
+	CURL* easy_handle = curl_easy_init();
+	
+	gchar* url = build_request_url(easy_handle, call-&gt;method-&gt;name, parameters);
+	CURLcode code = curl_easy_setopt(easy_handle, CURLOPT_URL, url);	
+	g_free(url);
+	
+	code = curl_easy_setopt(easy_handle, CURLOPT_HTTPGET, TRUE);
+	
+	struct xml_parser* parser = init_parser(call, callback, user_data, NULL, NULL);
 	
 	//create new parse context
 	GMarkupParseContext* context = g_markup_parse_context_new
@@ -779,85 +793,57 @@ void proxy_request(lfmproxy* proxy, const lfmget* call, const lfmparametervalue*
 	code = curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, parse_xml);
 	//code = curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, TRUE);
 	code = curl_easy_setopt(easy_handle, CURLOPT_FAILONERROR, TRUE);
+	//code = curl_easy_setopt(easy_handle, CURLOPT_PROXY, &quot;127.0.0.1&quot;);	 
+	//code = curl_easy_setopt(easy_handle, CURLOPT_PROXYPORT, http_proxy_get_port());	
 		
 	code = curl_multi_add_handle(proxy-&gt;multi_handle, easy_handle);
-}                                                      
+}
 
-#define POST_PREFIX &quot;method=%s&amp;api_key=%s&amp;&quot;
+void cleanup_post(gpointer data, gpointer user_data)
+{
+	struct curl_httppost* post = user_data;
+	
+	curl_formfree(post);
+}
 
-void proxy_post(lfmproxy* proxy, const gchar* method_name, gchar** names, gchar** values)
+void proxy_post(lfmproxy* proxy, const lfmget* call, const lfmparametervalue** parameters, gpointer callback, gpointer user_data)
 {	
-	gchar* post = g_strdup_printf(&quot;method=%s&amp;api_key=&quot;API_KEY, method_name);
+	struct curl_httppost* post = NULL;
+	struct curl_httppost* last = NULL;
 	
-	gchar** name_iterator = names;
-	gchar** value_iterator = values;
-	 
-	const guint prefix_length = strlen(POST_PREFIX); 
-	guint length = prefix_length;
-	while(*name_iterator)
-	{
-		length += strlen(*name_iterator) + 1 /*=*/ + strlen(*value_iterator) + 1 /*&amp;*/;		
-		name_iterator++;
-		value_iterator++;
-	}
-		
-	gchar* buffer = g_newa(gchar, length);
-	
-	//fill prefix
-	strncpy(buffer, POST_PREFIX, prefix_length);
-	gchar* arguments = buffer + prefix_length;
+	CURLFORMcode code = curl_formadd(&amp;post, &amp;last, CURLFORM_COPYNAME, METHOD_KEY, CURLFORM_COPYCONTENTS, call-&gt;method-&gt;name, CURLFORM_END);
+
+	const lfmparametervalue** iterator = parameters;
 	
-	name_iterator = names;
-	value_iterator = values;
-	while(*name_iterator)
-	{
-		const guint name_length = strlen(*name_iterator);
-		
-		//fill name
-		strncpy(arguments, *name_iterator, name_length);
-		arguments += name_length;
-		
-		//fill =
-		strncpy(arguments, &quot;=&quot;, 1);
-		arguments += 1;
-		
-		//fill value
-		const guint value_length = strlen(*value_iterator);
-		strncpy(arguments, *value_iterator, value_length);
-		arguments += value_length;
-		
-		if(*(name_iterator + 1))
-		{
-			//fill &amp;
-			strncpy(arguments, &quot;&amp;&quot;, 1);
-			arguments += 1;
-		}
-		
-		name_iterator++;
-		value_iterator++;
-	}	
+	while(*iterator)
+	{	
+		code = curl_formadd(&amp;post, &amp;last, CURLFORM_COPYNAME, (*iterator)-&gt;name, CURLFORM_COPYCONTENTS, (*iterator)-&gt;value, CURLFORM_END);
+		iterator++;
+	}
 	
 	CURL* easy_handle = curl_easy_init();
-	CURLcode code = curl_easy_setopt(easy_handle, CURLOPT_POST, TRUE);
+	code = curl_easy_setopt(easy_handle, CURLOPT_HTTPPOST, post);
 	
 	gchar* url = build_post_url();
 	code = curl_easy_setopt(easy_handle, CURLOPT_URL, url);
 	g_free(url);
 	
-	code = curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDSIZE, length);
-	code = curl_easy_setopt(easy_handle, CURLOPT_COPYPOSTFIELDS, buffer);
-	code = curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, buffer);
+	struct xml_parser* parser = init_parser(call, callback, user_data, cleanup_post, post);
 	
 	//create new parse context
 	GMarkupParseContext* context = g_markup_parse_context_new
 		(
 			&amp;proxy-&gt;parser,
 			0, //GMarkupParseFlags
-			NULL, //user_data
+			parser, //user_data
 			NULL //GDestroyNotify
 		);	
+		
 	code = curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, context);
-
+	code = curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, parse_xml);
+	//code = curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, TRUE);
+	code = curl_easy_setopt(easy_handle, CURLOPT_FAILONERROR, TRUE);
+	
 	code = curl_multi_add_handle(proxy-&gt;multi_handle, easy_handle);
 }
 
@@ -878,14 +864,12 @@ void communication_destroy()
 	proxy_destroy(process_proxy);
 }
 
-void get_data_from_method(const lfmget* call, const lfmparametervalue** parameter, void* callback, void* user_data)
-{	
-	proxy_request(get_proxy(), call, parameter, callback, user_data);
-}
-
-void send_data_to_method(const gchar* method_name, gchar** names, gchar** values)
-{	
-	proxy_post(get_proxy(), method_name, names, values);
+void call_method(const lfmget* call, const lfmparametervalue** parameter, void* callback, void* user_data)
+{
+	if(call-&gt;method-&gt;type == GET_METHOD)
+		proxy_request(get_proxy(), call, parameter, callback, user_data);
+	else
+		proxy_post(get_proxy(), call, parameter, callback, user_data);
 }
 
 void fill_parameters(lfmparametervalue** values, const lfmmethod* method, va_list* vl)
@@ -913,16 +897,32 @@ void fill_parameters(lfmparametervalue** values, const lfmmethod* method, va_lis
 
 gchar* utf8_array2csl(gpointer data)
 {
-	gchar** array = data;
-	gchar** iterator = array;
+	const gchar** iterator = data;
 	
-	gchar* result = g_strdup(&quot;&quot;);
+	size_t size = 0;
 	
 	while(*iterator)
 	{
-		gchar* old = result;
-		result = g_strconcat(old, *iterator, NULL);
-		g_free(old);
+		size += strlen(*iterator) + 1;
+		iterator++;
+	}
+	
+	gchar* result = g_new(gchar, size);
+	iterator = data;
+	gchar* current = result;
+	
+	while(*iterator)
+	{
+		size_t size = strlen(*iterator);
+		
+		//write element
+		strncpy(current, *iterator, size);
+		current += size;
+		
+		//write comma
+		strncpy(current, &quot;,&quot;, 1);
+		current++;
+		
 		iterator++;
 	}
 	
@@ -935,7 +935,7 @@ gchar* uint2utf8(gpointer data)
 	return g_strdup_printf(&quot;%u&quot;, value);
 }
 
-G_GNUC_NULL_TERMINATED void get_info_with_parameters(const lfmget* call, gpointer callback, gpointer user_data, ...)
+G_GNUC_NULL_TERMINATED void call_method_with_parameters(const lfmget* call, gpointer callback, gpointer user_data, ...)
 {	
 	createv(lfmparametervalue, parameters);
 	
@@ -944,7 +944,7 @@ G_GNUC_NULL_TERMINATED void get_info_with_parameters(const lfmget* call, gpointe
 	
 	fill_parameters(parameters, call-&gt;method, &amp;vl);
 	
-	get_data_from_method(call, parameters, callback, user_data);
+	call_method(call, (const lfmparametervalue**)parameters, callback, user_data);
 	
 	va_end(vl);
 	destroyv(lfmparametervalue, parameters);</diff>
      <filename>communication.c</filename>
    </modified>
    <modified>
      <diff>@@ -48,9 +48,16 @@ struct lfmparameter
 
 typedef struct lfmparameter lfmparameter;
 
+enum method_type
+{
+	GET_METHOD,
+	POST_METHOD
+};
+
 struct lfmmethod
 {
 	const gchar* name;
+	const enum method_type type;
 	const lfmparameter parameters[2];
 	const lfmerror specific_errors[5];	
 };
@@ -61,7 +68,8 @@ enum data_type
 	DATA_URL,
 	DATA_DATE_TIME,
 	DATA_BOOLEAN,
-	DATA_UINT
+	DATA_UINT,
+	DATA_VOID
 };
 
 typedef struct lfmmethod lfmmethod;
@@ -70,7 +78,7 @@ struct lfmget
 {
 	const lfmmethod* method;
 	const gchar* path[5]; 
-	const enum data_type data_parser; 
+	const enum data_type data_parser;	 
 };
 
 typedef struct lfmget lfmget;
@@ -86,9 +94,10 @@ typedef struct lfmparametervalue lfmparametervalue;
 gchar* utf8_array2csl(gpointer array);
 gchar* uint2utf8(gpointer array);
 
+
 void fill_parameters(lfmparametervalue** values, const lfmmethod* method, va_list* vl);
 
-void get_data_from_method(const lfmget* call, const lfmparametervalue** parameter, void* callback, void* user_data);
-G_GNUC_NULL_TERMINATED void get_info_with_parameters(const lfmget* call, gpointer callback, gpointer user_data, ...);
+void call_method(const lfmget* call, const lfmparametervalue** parameter, void* callback, void* user_data);
+G_GNUC_NULL_TERMINATED void call_method_with_parameters(const lfmget* call, gpointer callback, gpointer user_data, ...);
 
 #endif /*COMMUNICATION_H_*/</diff>
      <filename>communication.h</filename>
    </modified>
    <modified>
      <diff>@@ -17,6 +17,23 @@ void decreaseCall()
 		g_cond_broadcast(cond);
 }
 
+void void_func(gpointer user_data, GError* error)
+{
+	const char* func_name = user_data;
+	if(error)
+	{
+		if(error-&gt;code == CALLBACK_EOF)
+		{
+			//g_print(&quot;%s: [DONE]\n&quot;, func_name);
+			decreaseCall();
+		}
+		else
+			g_printerr(&quot;%s: [ERROR] %s\n&quot;, func_name, error-&gt;message);
+	}
+	else
+		g_print(&quot;%s: [OK]\n&quot;, func_name);
+}
+
 void utf8_func(const gchar* string, gpointer user_data, GError* error)
 {
 	const char* func_name = user_data;
@@ -97,10 +114,13 @@ int main(int argc, const char* args[])
 	
 	cond = g_cond_new();
 	static const char atst[] = &quot;Nine Inch Nails&quot;;
-	artist_get_musicbrainz_id(atst, utf8_func, &quot;artist_get_musicbrainz_id&quot;);
+	
 	increaseCall();
+	artist_get_musicbrainz_id(atst, utf8_func, &quot;artist_get_musicbrainz_id&quot;);
+	
 	//artist_get_name(atst, utf8_func, &quot;artist_get_name&quot;);
-	//call++;	
+	//call++;
+	increaseCall();	
 	artist_get_url(atst, utf8_func, &quot;artist_get_url&quot;);
 	increaseCall();
 	artist_get_image_url(atst, IMAGE_LARGE, utf8_func, &quot;artist_get_image_url&quot;);
@@ -116,7 +136,37 @@ int main(int argc, const char* args[])
 	artist_get_description(atst, utf8_func, &quot;artist_get_description&quot;);
 	increaseCall();
 	artist_get_published_date_time(atst, dt_func, &quot;artist_get_published_date_time&quot;);
+	
+	increaseCall();
+	createv(gchar, tags);
+	addv(gchar, tags, &quot;test1&quot;);
+	addv(gchar, tags, &quot;test2&quot;);
+	artist_add_tags(atst, (const gchar**)tags, void_func, &quot;artist_add_tags&quot;);
+	destroyv(gchar, tags);
+	
+	increaseCall();
+	artist_remove_tag(atst, tags[0], void_func, &quot;artist_remove_tag&quot;);
+	increaseCall();
+	artist_remove_tag(atst, tags[1], void_func, &quot;artist_remove_tag&quot;);
+	
+	static const char albm[] = &quot;With Teeth&quot;;
+
+	increaseCall();
+	album_get_musicbrainz_id(atst, albm, utf8_func, &quot;album_get_musicbrainz_id&quot;);	
+	increaseCall(); 
+	//void album_get_artist_name(const gchar* musicbrainz_id, utf8_callback callback, gpointer user_data);
+
+	album_get_url(atst, albm, utf8_func, &quot;album_get_url&quot;);
+	increaseCall();
+	album_get_release_date_time(atst, albm, dt_func, &quot;album_get_release_date_time&quot;);
+	increaseCall();
+	album_get_image_url(atst, albm, IMAGE_LARGE, utf8_func, &quot;album_get_image_url&quot;);
+	increaseCall();
+	album_get_listener_count(atst, albm, uint_func, &quot;album_get_listener_count&quot;);
+	increaseCall();
+	album_get_play_count(atst, albm, uint_func, &quot;album_get_play_count&quot;);
 	increaseCall();
+	album_get_top_tags(atst, albm, utf8_func, &quot;album_get_top_tags&quot;);
 		
 	GMutex* mutex = g_mutex_new();   
 	g_cond_wait(cond, mutex);</diff>
      <filename>lastfm_test.c</filename>
    </modified>
    <modified>
      <diff>@@ -54,6 +54,7 @@ GString* get_request(int fd)
 	
 	while((status = g_io_channel_read_line_string(io, line, NULL, &amp;error)) == G_IO_STATUS_AGAIN)
 	{
+		http_proxy_print(&quot;TRYING AGAIN&quot;);	
 	}
 	
 	if(error)
@@ -65,6 +66,402 @@ GString* get_request(int fd)
 	return line;
 }
 
+gboolean check_socket_valid(int socket)
+{
+	if(socket != -1)
+		return TRUE;
+		
+	switch(errno)
+	{
+		case EAFNOSUPPORT:
+		{
+        	http_proxy_printerr(&quot;The implementation does not support the specified address family.&quot;);
+        	break;
+		}
+		case EMFILE:
+		{
+			http_proxy_printerr(&quot;No more file descriptors are available for this process.&quot;);
+        	break;
+		}
+        case ENFILE:
+        {
+			http_proxy_printerr(&quot;No more file descriptors are available for the system.&quot;);
+        	break;
+		}
+		case EPROTONOSUPPORT:
+		{
+			http_proxy_printerr(&quot;The protocol is not supported by the address family, or the protocol is not supported by the implementation.&quot;);
+        	break;
+		}
+		case EPROTOTYPE:
+		{
+			http_proxy_printerr(&quot;The socket type is not supported by the protocol.&quot;);
+        	break;
+		}
+		case EACCES:
+		{
+        	http_proxy_printerr(&quot;The process does not have appropriate privileges.&quot;);
+        	break;
+		}
+		case ENOBUFS:
+		{
+			http_proxy_printerr(&quot;Insufficient resources were available in the system to perform the operation.&quot;);
+        	break;
+		}
+		case ENOMEM:
+		{
+			http_proxy_printerr(&quot;Insufficient memory was available to fulfill the request.&quot;);
+        	break;
+		}
+		default:
+		{
+			http_proxy_printerr(&quot;Unrecognized error on socket allocation.&quot;);
+        	break;
+		}
+	}
+	
+	return FALSE;        
+}
+
+gboolean check_bind_valid(int socket, int bind)
+{
+	if(bind != -1)
+		return TRUE;
+		
+	switch(errno)
+	{
+		case EACCES:
+		{
+			http_proxy_printerr(&quot;The address is protected, and the user is not the superuser.&quot;);
+			break;
+		}
+		case EADDRINUSE:
+		{
+			http_proxy_printerr(&quot;The given address is already in use&quot;);
+			break;
+		}
+		case EBADF:
+		{
+			http_proxy_printerr(&quot;sockfd '%d' is not a valid descriptor. &quot;, socket);
+			break;
+		}
+		case EINVAL:
+		{
+			http_proxy_printerr(&quot;The socket '%d' is already bound to an address&quot;, socket);
+			break;
+		}
+		case ENOTSOCK:
+		{
+			http_proxy_printerr(&quot;sockfd '%d' is a descriptor for a file, not a socket.&quot;, socket);
+			break;
+		}
+		default:
+		{
+			http_proxy_printerr(&quot;Unrecognized error '%d' on socket '%d'&quot;, errno, socket);
+			break;
+		}
+	}
+	
+	return FALSE;
+}
+
+gboolean check_listen_valid(int listen)
+{
+	if(listen != -1)
+		return TRUE;
+		
+	switch(errno)
+	{
+		case EADDRINUSE:
+		{
+			http_proxy_printerr(&quot;Another socket is already listening on the same port.&quot;);
+			break;
+		} 
+		case EBADF:
+		{ 
+			http_proxy_printerr(&quot;The argument sockfd '%d' is not a valid descriptor.&quot;, the_proxy.in_socket); 
+			break;
+		}
+		case ENOTSOCK:
+		{
+			http_proxy_printerr(&quot;The argument sockfd '%d' is not a socket.&quot;, the_proxy.in_socket); 
+			break;
+		}
+		case EOPNOTSUPP:
+		{
+			http_proxy_printerr(&quot;The socket '%d' is not of a type that supports the listen () operation.&quot;, the_proxy.in_socket);
+			break; 
+		}
+		default:
+		{
+			http_proxy_printerr(&quot;Unrecognized error '%d' on listening on socket '%d'&quot;, errno, the_proxy.in_socket);
+			break;
+		}
+	}
+	
+	return FALSE;
+}
+
+gboolean check_connect_valid(int connect)
+{
+	if(connect != -1)
+		return TRUE;
+	
+	switch(errno)
+	{
+		case EADDRNOTAVAIL:
+		{
+			http_proxy_printerr(&quot;The specified address is not available from the local machine.&quot;);
+			break; 
+		}   
+		case EAFNOSUPPORT:
+		{
+			http_proxy_printerr(&quot;The specified address is not a valid address for the address family of the specified socket.&quot;);
+			break; 
+		}   
+		case EALREADY:
+		{
+			http_proxy_printerr(&quot;A connection request is already in progress for the specified socket.&quot;);
+			break; 
+		}    
+		case EBADF:
+		{
+			http_proxy_printerr(&quot;The socket argument is not a valid file descriptor.&quot;);
+			break; 
+		}    
+		case ECONNREFUSED:
+		{
+			http_proxy_printerr(&quot;The target address was not listening for connections or refused the connection request.&quot;);
+			break; 
+		}    
+		case EINPROGRESS:
+		{
+			http_proxy_printerr(&quot;O_NONBLOCK is set for the file descriptor for the socket and the connection cannot be immediately established; the connection shall be established asynchronously.&quot;);
+			break; 
+		}
+		case EINTR:
+		{
+			http_proxy_printerr(&quot;The attempt to establish a connection was interrupted by delivery of a signal that was caught; the connection shall be established asynchronously.&quot;);
+			break; 
+		}    
+		case EISCONN:
+		{
+			http_proxy_printerr(&quot;The specified socket is connection-mode and is already connected.&quot;);
+			break; 
+		}    
+		case ENETUNREACH:
+		{
+			http_proxy_printerr(&quot;No route to the network is present.&quot;);
+			break; 
+		}
+		case ENOTSOCK:
+		{
+			http_proxy_printerr(&quot;The socket argument does not refer to a socket.&quot;);
+			break; 
+		}    
+		case EPROTOTYPE:
+		{
+			http_proxy_printerr(&quot;The specified address has a different type than the socket bound to the specified peer address.&quot;);
+			break; 
+		}
+   		case ETIMEDOUT:
+		{
+			http_proxy_printerr(&quot;The attempt to connect timed out before a connection was made.&quot;);
+			break; 
+		}
+		case EACCES:
+		{
+			http_proxy_printerr(&quot;Search permission is denied for a component of the path prefix; or write access to the named socket is denied.&quot;);
+			break; 
+		}    
+		case EADDRINUSE:
+		{
+			http_proxy_printerr(&quot;Attempt to establish a connection that uses addresses that are already in use.&quot;);
+			break; 
+		}    
+		case ECONNRESET:
+		{
+			http_proxy_printerr(&quot;Remote host reset the connection request.&quot;);
+			break; 
+		}    
+		case EHOSTUNREACH:
+		{
+			http_proxy_printerr(&quot;The destination host cannot be reached (probably because the host is down or a remote router cannot reach it).&quot;);
+			break; 
+		}    
+		case EINVAL:
+		{
+			http_proxy_printerr(&quot;The address_len argument is not a valid length for the address family; or invalid address family in the sockaddr structure.&quot;);
+			break; 
+		}    
+		case ELOOP:
+		{
+			http_proxy_printerr(&quot;More than {SYMLOOP_MAX} symbolic links were encountered during resolution of the pathname in address.&quot;);
+			break; 
+		}  
+		case ENAMETOOLONG:
+		{
+			http_proxy_printerr(&quot;Pathname resolution of a symbolic link produced an intermediate result whose length exceeds {PATH_MAX}.&quot;);
+			break; 
+		}    
+		case ENETDOWN:
+		{
+			http_proxy_printerr(&quot;The local network interface used to reach the destination is down.&quot;);
+			break; 
+		}    
+		case ENOBUFS:
+		{
+			http_proxy_printerr(&quot;No buffer space is available.&quot;);
+			break; 
+		}    
+		case EOPNOTSUPP:
+		{
+			http_proxy_printerr(&quot;The socket is listening and cannot be connected.&quot;);
+			break; 
+		}
+		default:
+		{
+			http_proxy_printerr(&quot;Unrecognized connect error '%d'&quot;, errno);
+			break;
+		}     
+	}
+	
+	return FALSE;
+}
+
+gboolean connect_request(int request)
+{
+	uint16_t port;
+
+	struct sockaddr_in destination;
+	destination.sin_family = AF_INET;
+	destination.sin_port = htons(port);	
+
+	/* Lookup and return the address if possible */
+	//ret = lookup_domain(&amp;port_info.sin_addr, ip_addr);
+
+	int output = socket(AF_INET, SOCK_STREAM, 0);
+	
+	gboolean success = check_socket_valid(output);
+	
+	if(!success)
+		return FALSE;	
+
+/*
+	struct sockaddr_in bind_addr;
+	bind_addr.sin_family = AF_INET;
+	bind_addr.sin_addr.s_addr = inet_addr(config.bind_address);
+	ret = bind(sock_fd, (struct sockaddr *)&amp;bind_addr, sizeof(bind_addr));
+	*/
+
+	int passalong = connect(output, (struct sockaddr*)&amp;destination, sizeof(destination));
+	
+	success = check_connect_valid(passalong);
+	
+	if(!success)
+		return FALSE; 
+
+/*	
+	fd_set rset, wset;
+	struct timeval tv;
+	time_t last_access;
+	int ret;
+	double tdiff;
+	int maxfd = max(connptr-&gt;client_fd, connptr-&gt;server_fd) + 1;
+	ssize_t bytes_received;
+
+	socket_nonblocking(connptr-&gt;client_fd);
+	socket_nonblocking(connptr-&gt;server_fd);
+
+	last_access = time(NULL);
+
+	for (;;) {
+		FD_ZERO(&amp;rset);
+		FD_ZERO(&amp;wset);
+
+		tv.tv_sec =
+		    config.idletimeout - difftime(time(NULL), last_access);
+		tv.tv_usec = 0;
+
+		if (buffer_size(connptr-&gt;sbuffer) &gt; 0)
+			FD_SET(connptr-&gt;client_fd, &amp;wset);
+		if (buffer_size(connptr-&gt;cbuffer) &gt; 0)
+			FD_SET(connptr-&gt;server_fd, &amp;wset);
+		if (buffer_size(connptr-&gt;sbuffer) &lt; MAXBUFFSIZE)
+			FD_SET(connptr-&gt;server_fd, &amp;rset);
+		if (buffer_size(connptr-&gt;cbuffer) &lt; MAXBUFFSIZE)
+			FD_SET(connptr-&gt;client_fd, &amp;rset);
+
+		ret = select(maxfd, &amp;rset, &amp;wset, NULL, &amp;tv);
+
+		if (ret == 0) {
+			tdiff = difftime(time(NULL), last_access);
+			if (tdiff &gt; config.idletimeout) {
+				log_message(LOG_INFO,
+					    &quot;Idle Timeout (after select) as %g &gt; %u.&quot;,
+					    tdiff, config.idletimeout);
+				return;
+			} else {
+				continue;
+			}
+		} else if (ret &lt; 0) {
+			log_message(LOG_ERR,
+				    &quot;relay_connection: select() error \&quot;%s\&quot;. Closing connection (client_fd:%d, server_fd:%d)&quot;,
+				    strerror(errno), connptr-&gt;client_fd,
+				    connptr-&gt;server_fd);
+			return;
+		} else {
+			
+			// All right, something was actually selected so mark it.
+			last_access = time(NULL);
+		}
+
+		if (FD_ISSET(connptr-&gt;server_fd, &amp;rset)) {
+			bytes_received = read_buffer(connptr-&gt;server_fd, connptr-&gt;sbuffer);
+			if (bytes_received &lt; 0)
+				break;
+
+			connptr-&gt;content_length.server -= bytes_received;
+			if (connptr-&gt;content_length.server == 0)
+				break;
+		}
+		if (FD_ISSET(connptr-&gt;client_fd, &amp;rset)
+		    &amp;&amp; read_buffer(connptr-&gt;client_fd, connptr-&gt;cbuffer) &lt; 0) {
+			break;
+		}
+		if (FD_ISSET(connptr-&gt;server_fd, &amp;wset)
+		    &amp;&amp; write_buffer(connptr-&gt;server_fd, connptr-&gt;cbuffer) &lt; 0) {
+			break;
+		}
+		if (FD_ISSET(connptr-&gt;client_fd, &amp;wset)
+		    &amp;&amp; write_buffer(connptr-&gt;client_fd, connptr-&gt;sbuffer) &lt; 0) {
+			break;
+		}
+	}
+
+
+// Here the server has closed the connection... write the
+// remainder to the client and then exit.
+
+	socket_blocking(connptr-&gt;client_fd);
+	while (buffer_size(connptr-&gt;sbuffer) &gt; 0) {
+		if (write_buffer(connptr-&gt;client_fd, connptr-&gt;sbuffer) &lt; 0)
+			break;
+	}
+	shutdown(connptr-&gt;client_fd, SHUT_WR);
+
+
+// Try to send any remaining data to the server if we can.
+	socket_blocking(connptr-&gt;server_fd);
+	while (buffer_size(connptr-&gt;cbuffer) &gt; 0) {
+		if (write_buffer(connptr-&gt;server_fd, connptr-&gt;cbuffer) &lt; 0)
+			break;
+	}
+*/
+
+	return TRUE;
+}
+
 void process_request(gpointer data, gpointer user_data)
 {
 	int request = *((int*)user_data);
@@ -87,7 +484,7 @@ gpointer http_proxy_run(gpointer data)
 	while(success)
 	{
 		struct sockaddr_in address;
-		socklen_t address_size = 0;	
+		socklen_t address_size = sizeof(struct sockaddr_in);	
 		int request = accept(the_proxy.in_socket, (struct sockaddr*)&amp;address, &amp;address_size);
 			
 		success = (request == -1);
@@ -183,107 +580,22 @@ gpointer http_proxy_run(gpointer data)
 			}
 		}
 	}
+	
+	g_thread_pool_free(the_proxy.pool, TRUE, TRUE);
+	
+	http_proxy_print(&quot;Stopped listening&quot;);
+	return NULL;
 }
 
 gboolean http_proxy_init()
-{
-	/*
-	//setup output socket	
-	out_socket = socket(PF_INET, SOCK_STREAM, 0);
-	
-	struct sockaddr_in output_address;
-	output_address.sin_family = AF_INET;
-	output_address.sin_addr.s_addr = INADDR_LOOPBACK;
-	output_address.sin_port = 80;
- 		
- 	gboolean success = connect(out_socket, (struct sockaddr*)&amp;output_address, sizeof(struct sockaddr_in)) != -1;
- 	
- 	if(!success)
-	{
-		switch(errno)
-		{
-			case EACCES: 
-			case EPERM:
-			{
-				//For Unix domain sockets, which are identified by pathname: Write permission is denied on the socket file, or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)
-				http_proxy_printerr(&quot;The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the connection request failed because of a local firewall rule.&quot;);
-				break;
-			}
-			case EADDRINUSE:
-			{
-				http_proxy_printerr(&quot;Local address '%d' is already in use.&quot;, output_address.sin_addr.s_addr);
-				break; 
-			}
-			case EAFNOSUPPORT:
-			{
-				http_proxy_printerr(&quot;The passed address didn't have the correct address family in its sa_family field.&quot;); 
-				break;
-			}
-			case EAGAIN:
-			{
-				http_proxy_printerr(&quot;No more free local ports or insufficient entries in the routing cache. For PF_INET see the net.ipv4.ip_local_port_range sysctl in ip(7) on how to increase the number of local ports.&quot;);
-				break;
-			} 
-			case EALREADY:
-			{
-				http_proxy_printerr(&quot;The socket is non-blocking and a previous connection attempt has not yet been completed.&quot;);
-				break;
-			}
-			case EBADF:
-			{
-				http_proxy_printerr(&quot;The file descriptor '%d' is not a valid index in the descriptor table.&quot;, out_socket);
-				break;
-			}
-			case ECONNREFUSED:
-			{
-				http_proxy_printerr(&quot;No-one listening on the remote address.&quot;);
-				break;
-			}
-			case EFAULT:
-			{
-				http_proxy_printerr(&quot;The socket structure address is outside the user's address space.&quot;);
-				break;
-			}
-			case EINPROGRESS:
-			{
-				//should handle
-				http_proxy_printerr(&quot;The socket is non-blocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect () completed successfully ( SO_ERROR is zero) or unsuccessfully ( SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).&quot;);
-				break;
-			}
-			case EINTR:
-			{
-				http_proxy_printerr(&quot;The system call was interrupted by a signal that was caught.&quot;);
-				break;
-			}
-			case EISCONN:
-			{
-				http_proxy_printerr(&quot;The socket '%d' is already connected.&quot;, out_socket);
-				break;
-			}
-			case ENETUNREACH:
-			{
-				http_proxy_printerr(&quot;Network is unreachable.&quot;);
-				break;
-			} 
-			case ENOTSOCK:
-			{
-				http_proxy_printerr(&quot;The file descriptor '%d' is not associated with a socket. ETIMEDOUT Timeout while attempting connection. The server may be too busy to accept new connections. Note that for IP sockets the timeout may be very long when syncookies are enabled on the server.&quot;, out_socket);
-				break;
-			}
-			default:
-			{
-				http_proxy_printerr(&quot;Unrecognized error when connecting socket '%d'&quot;, out_socket);
-				break; 
-			}
-		}
-	}
-	
-	return FALSE;*/
-	
+{	
 	//AF_INET??
 	the_proxy.in_socket = socket(PF_INET, SOCK_STREAM, 0);
 	//fd_unblock(the_proxy.in_socket);
 	
+	if(!check_socket_valid(the_proxy.in_socket))
+		return FALSE;
+	
 	struct sockaddr_in in_address;
  	in_address.sin_family = AF_INET;
  	in_address.sin_addr.s_addr = INADDR_ANY;
@@ -293,7 +605,8 @@ gboolean http_proxy_init()
  	
  	while(!success) 	
  	{
-  		success = bind(the_proxy.in_socket, (struct sockaddr*)&amp;in_address, sizeof(struct sockaddr_in)) != -1; 
+ 		int result = bind(the_proxy.in_socket, (struct sockaddr*)&amp;in_address, sizeof(struct sockaddr_in)); 
+  		success = (result != -1); 
  		
  		if(!success)
  		{		
@@ -302,24 +615,14 @@ gboolean http_proxy_init()
 	 			case EACCES: //The address is protected, and the user is not the superuser.
 	 			case EADDRINUSE: //The given address is already in use
 					break; //ignore 
-				case EBADF:
-				{
-					http_proxy_printerr(&quot;sockfd '%d' is not a valid descriptor. &quot;, the_proxy.in_socket);
-					break;
-				}
 				case EINVAL:
 				{ 
 					success = TRUE; //The socket is already bound to an address
 					break;
 				}
-				case ENOTSOCK:
-				{
-					http_proxy_printerr(&quot;sockfd '%d' is a descriptor for a file, not a socket.&quot;, the_proxy.in_socket);
-					break;
-				}
 				default:
 				{
-					http_proxy_printerr(&quot;Unrecognized error '%d' on socket '%d'&quot;, errno, the_proxy.in_socket);
+					check_bind_valid(the_proxy.in_socket, result);
 					break;
 				}
 	 		}
@@ -327,7 +630,8 @@ gboolean http_proxy_init()
 	 	
 	 	if(success)
 		{
-			success = listen(the_proxy.in_socket, MAX_LISTENING_BUFFER) != -1;
+			result = listen(the_proxy.in_socket, MAX_LISTENING_BUFFER);
+			success = (result != -1);
 			
 			if(!success)
  			{
@@ -335,24 +639,9 @@ gboolean http_proxy_init()
 	 			{
 	 				case EADDRINUSE: //Another socket is already listening on the same port. 
 						break; //ignore
-					case EBADF:
-					{ 
-						http_proxy_printerr(&quot;The argument sockfd '%d' is not a valid descriptor.&quot;, the_proxy.in_socket); 
-						break;
-					}
-					case ENOTSOCK:
-					{
-						http_proxy_printerr(&quot;The argument sockfd '%d' is not a socket.&quot;, the_proxy.in_socket); 
-						break;
-					}
-					case EOPNOTSUPP:
-					{
-	    				http_proxy_printerr(&quot;The socket '%d' is not of a type that supports the listen () operation.&quot;, the_proxy.in_socket);
-	    				break; 
-					}
 					default:
 					{
-						http_proxy_printerr(&quot;Unrecognized error '%d' on listening on socket '%d'&quot;, errno, the_proxy.in_socket);
+						check_listen_valid(result);						
 						break;
 					}
 	 			}
@@ -468,8 +757,7 @@ guint get_peer_address(int fd)
 }
 
 void http_proxy_destroy()
-{		
-	g_thread_pool_free(the_proxy.pool, TRUE, TRUE);
+{
 	close(the_proxy.in_socket);
 	close(the_proxy.out_socket);
 }</diff>
      <filename>proxy.c</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-#ifndef PROXY_H_
+#ifndef PROXY_H_http_proxy_get_port
 #define PROXY_H_
 
 #include &lt;glib.h&gt;</diff>
      <filename>proxy.h</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>0d82fd4d8d2ccc2a0e5c1a5cbd20ccb515809c34</id>
    </parent>
  </parents>
  <author>
    <name>LCID Fire</name>
    <email>lcid-fire@gmx.net</email>
  </author>
  <url>http://github.com/LCID-Fire/liblastfm/commit/270cc092e720df49872b4db7ef4231dafa0b66b5</url>
  <id>270cc092e720df49872b4db7ef4231dafa0b66b5</id>
  <committed-date>2008-07-15T09:35:07-07:00</committed-date>
  <authored-date>2008-07-15T09:35:07-07:00</authored-date>
  <message>Prepare sending post to webservice</message>
  <tree>ab6b48cd016c98eb9630498e0b6527a8bbaab628</tree>
  <committer>
    <name>LCID Fire</name>
    <email>lcid-fire@gmx.net</email>
  </committer>
</commit>
