Index: output.h
===================================================================
--- output.h	(revision 17751)
+++ output.h	(working copy)
@@ -50,6 +50,6 @@
     int (*relation_delete)(int id);
 };
 
-unsigned int pgsql_filter_tags(enum OsmType type, struct keyval *tags, int *polygon);
+unsigned int pgsql_filter_tags(long long unsigned int, enum OsmType type, struct keyval *tags, int *polygon);
 
 #endif
Index: output-pgsql.c
===================================================================
--- output-pgsql.c	(revision 17751)
+++ output-pgsql.c	(working copy)
@@ -63,6 +63,7 @@
 #define FLAG_LINEAR  2    /* For lines table */
 #define FLAG_NOCACHE 4    /* Optimisation: don't bother remembering this one */
 #define FLAG_DELETE  8    /* These tags should be simply deleted on sight */
+#define FLAG_IGNORE  16   /* Store value of tag only *if* object is stored */
 static struct flagsname {
     char *name;
     int flag;
@@ -70,7 +71,8 @@
     { name: "polygon",    flag: FLAG_POLYGON },
     { name: "linear",     flag: FLAG_LINEAR },
     { name: "nocache",    flag: FLAG_NOCACHE },
-    { name: "delete",     flag: FLAG_DELETE }
+    { name: "delete",     flag: FLAG_DELETE },
+    { name: "ignore",     flag: FLAG_IGNORE }
 };
 #define NUM_FLAGS ((signed)(sizeof(tagflags) / sizeof(tagflags[0])))
 
@@ -535,19 +537,58 @@
     return 0;
 }
 
+#define uint64_t long long unsigned int
+static struct photo_s {
+	enum OsmType type;
+	uint64_t osmid;
+	const char *flickr;
+	const char *foursquare;
+	const char *dopplr;
+	const char *lastfm;
+	const char *upcoming;
+	const char *openplaques;
+	const char *openlibrary;
+} photos[] = {
+#include "../flickr-data"
+}, *photo_sorted[3];
+static int photos_num[3];
+
+static int photo_find_compare(const void *a, const void *b)
+{
+	const uint64_t *ap = a;
+	const struct photo_s *bp = b;
+
+	return *ap - bp->osmid;
+}
+
 /* Go through the given tags and determine the union of flags. Also remove
  * any tags from the list that we don't know about */
-unsigned int pgsql_filter_tags(enum OsmType type, struct keyval *tags, int *polygon)
+unsigned int pgsql_filter_tags(uint64_t id, enum OsmType type,
+                struct keyval *tags, int *polygon)
 {
     int i, filter = 1;
     int flags = 0;
     int add_area_tag = 0;
+    char *wp;
+    struct photo_s *pic;
 
     const char *area;
     struct keyval *item;
     struct keyval temp;
     initList(&temp);
 
+    pic = bsearch(&id, photo_sorted[type], photos_num[type],
+                    sizeof(*photos), photo_find_compare);
+    if (pic) {
+        addItem(tags, "flickr", pic->flickr, 0);
+        addItem(tags, "foursquare", pic->foursquare, 0);
+        addItem(tags, "dopplr", pic->dopplr, 0);
+        addItem(tags, "lastfm", pic->lastfm, 0);
+        addItem(tags, "upcoming", pic->upcoming, 0);
+        addItem(tags, "openplaques", pic->openplaques, 0);
+        addItem(tags, "openlibrary", pic->openlibrary, 0);
+    }
+
     /* We used to only go far enough to determine if it's a polygon or not, but now we go through and filter stuff we don't need */
     while( (item = popItem(tags)) != NULL )
     {
@@ -560,6 +601,21 @@
             continue;
         }    
 
+	if (!strncmp("wikipedia:", item->key, 10))
+        {
+            if (!getItem(tags, "url") && !getItem(&temp, "url"))
+            {
+                wp = malloc(strlen(item->value) + 50);
+                sprintf(wp, "http://%s.wikipedia.org/wiki/%s",
+                        item->key + 10, item->value);
+                addItem(tags, "url", wp, 0);
+                free(wp);
+            }
+
+            freeItem(item);
+            continue;
+        }
+
         for (i=0; i < exportListCount[type]; i++)
         {
             if( strcmp( exportList[type][i].name, item->key ) == 0 )
@@ -571,7 +627,9 @@
                     break;
                 }
 
-                filter = 0;
+                if( !(exportList[type][i].flags & FLAG_IGNORE) )
+                    filter = 0;
+
                 flags |= exportList[type][i].flags;
 
                 pushItem( &temp, item );
@@ -627,7 +685,7 @@
     if(exists)
         pgsql_delete_way_from_output(id);
 
-    if (pgsql_filter_tags(OSMTYPE_WAY, tags, &polygon) || add_z_order(tags, &roads))
+    if (pgsql_filter_tags(id, OSMTYPE_WAY, tags, &polygon) || add_z_order(tags, &roads))
         return 0;
 
     //compress_tag_name(tags);
@@ -835,7 +893,7 @@
         return 0;
     }
 
-    if (pgsql_filter_tags(OSMTYPE_WAY, &tags, &polygon) || add_z_order(&tags, &roads)) {
+    if (pgsql_filter_tags(id, OSMTYPE_WAY, &tags, &polygon) || add_z_order(&tags, &roads)) {
         resetList(&tags);
         resetList(&poly_tags);
         return 0;
@@ -933,6 +991,14 @@
     return 0;
 }
 
+static int photo_sort_compare(const void *a, const void *b)
+{
+	const struct photo_s *ap = a;
+	const struct photo_s *bp = b;
+
+	return (ap->type - bp->type) ?: (ap->osmid - bp->osmid);
+}
+
 static int pgsql_out_start(const struct output_options *options)
 {
     char *sql, tmp[128];
@@ -1072,6 +1138,14 @@
     }
     free(sql);
 
+    qsort(photos, sizeof(photos) / sizeof(*photos), sizeof(*photos),
+                    photo_sort_compare);
+    for (i = 0; i < (int) (sizeof(photos) / sizeof(*photos)); i ++) {
+        photos_num[photos[i].type] ++;
+        if (!photo_sorted[photos[i].type])
+            photo_sorted[photos[i].type] = photos + i;
+    }
+
     expire_tiles_init(options);
 
     options->mid->start(options);
@@ -1184,7 +1258,7 @@
 static int pgsql_add_node(int id, double lat, double lon, struct keyval *tags)
 {
   int polygon;
-  int filter = pgsql_filter_tags(OSMTYPE_NODE, tags, &polygon);
+  int filter = pgsql_filter_tags(id, OSMTYPE_NODE, tags, &polygon);
   
   Options->mid->nodes_set(id, lat, lon, tags);
   if( !filter )
@@ -1197,7 +1271,7 @@
   int polygon = 0;
 
   // Check whether the way is: (1) Exportable, (2) Maybe a polygon
-  int filter = pgsql_filter_tags(OSMTYPE_WAY, tags, &polygon);
+  int filter = pgsql_filter_tags(id, OSMTYPE_WAY, tags, &polygon);
 
   // If this isn't a polygon then it can not be part of a multipolygon
   // Hence only polygons are "pending"
