diff --git a/contrib/README b/contrib/README
index 773b0e30c3be677a8452f64d0dbeac9beaa17ae7..7dcd1ca1fe9fefbd043fa78e350d63224cdcc5d7 100644
--- a/contrib/README
+++ b/contrib/README
@@ -60,6 +60,9 @@ mSQL-interface -
 noupdate -
 	trigger to prevent updates on single columns
 
+pg_dumplo -
+	Dump large objects
+
 soundex -
 	Prototype for soundex function
 
diff --git a/contrib/pg_dumplo/Makefile b/contrib/pg_dumplo/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..0d4fb834243d987d03a21195b9445e025c7b1069
--- /dev/null
+++ b/contrib/pg_dumplo/Makefile
@@ -0,0 +1,26 @@
+
+PROGRAM	= pg_dumplo
+	
+OBJECTS	= pg_dumplo.o
+
+CFLAGS 	= -Wall -fpic -g
+CC	= gcc
+RM	= rm -f
+INCLUDE = -I/usr/include/postgresql
+LIBS	=-lpq
+
+COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDE)
+LINK    = $(CC) $(CFLAGS) -o $@ $(LIBS)
+
+
+all: $(PROGRAM) 	
+
+$(PROGRAM): $(OBJECTS)
+	$(LINK) $(OBJECTS)
+
+.c.o: $<
+	$(COMPILE) -c $<
+
+clean:
+	$(RM) -f *~ $(OBJECTS) $(PROGRAM)
+
diff --git a/contrib/pg_dumplo/README b/contrib/pg_dumplo/README
new file mode 100644
index 0000000000000000000000000000000000000000..b36cdd01d0bb14fc0a2c3b04672f53204aac174c
--- /dev/null
+++ b/contrib/pg_dumplo/README
@@ -0,0 +1,18 @@
+
+	pg_dumplo - PostgreSQL large object dumper
+        
+
+	Hmm... documentation is not available. For more information
+	see the help ( pg_dumplo -h ) and examples in this help.
+
+	Compilation:
+			- you need the PostgreSQL's devel. libs 
+			- and type: 'make'
+
+					
+				        Karel Zak <zakkr@zf.jcu.cz>		
+		
+				
+
+	
+
diff --git a/contrib/pg_dumplo/VERSION b/contrib/pg_dumplo/VERSION
new file mode 100644
index 0000000000000000000000000000000000000000..05b19b1f76ec50c8a0345dbd528fa3defd3cbecc
--- /dev/null
+++ b/contrib/pg_dumplo/VERSION
@@ -0,0 +1 @@
+0.0.4
\ No newline at end of file
diff --git a/contrib/pg_dumplo/pg_dumplo.c b/contrib/pg_dumplo/pg_dumplo.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e6a20bef55b1496a843434537ce918809bb8e0b
--- /dev/null
+++ b/contrib/pg_dumplo/pg_dumplo.c
@@ -0,0 +1,379 @@
+
+#include <stdio.h>	
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>                            
+#include <time.h>
+
+#include <libpq-fe.h>
+#include <libpq/libpq-fs.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+        
+extern int 	errno;        
+        
+#define QUERY_BUFSIZ	(8*1024)
+#define DIR_UMASK	0755
+#define FILE_UMASK	0666 
+
+#define	TRUE		1
+#define FALSE		0
+#define RE_OK		0
+#define RE_ERROR	1
+
+typedef struct { 
+	char	*table,
+		*attr;
+	long	lo_oid;
+} lo_attr;
+
+void usage()
+{
+	printf("\nPostgreSQL large objects dump");
+	printf("\npg_lo_dump <option>\n\n");
+	printf("-h --help			this help\n");	
+	printf("-u --user='username'		username for connection to server\n");	
+	printf("-p --password='password'	password for connection to server\n");	
+	printf("-d --db='database'		database name\n");	
+	printf("-t --host='hostname'		server hostname\n");		
+	printf("-l <table.attr ...>		dump attribute (columns) with LO to dump tree\n");
+	printf("-i --import			import large obj dump tree to DB\n");
+	printf("-s --space=<dir>		directory with dupm tree (for dump/import)\n");
+	printf("\nExample (dump):   pg_lo_dump -d my_db -s /my_dump/dir/ -l t1.a t1.b t2.a\n");	
+	printf("Example (import): pg_lo_dump -i -d my_db -s /my_dump/dir/\n");	
+	printf("\nNote:  * option '-l' must be last option!\n");	
+	printf("       * option '-i' (--import) make new large obj in DB, not rewrite old,\n");	
+	printf("         import UPDATE oid numbers in table.attr only.\n");	
+	printf("\n\n"); 
+}
+
+typedef enum {
+	ARG_USER,
+	ARG_PWD,
+	ARG_DB,
+	ARG_HELP,
+	ARG_HOST
+} _ARG_;
+
+/*-----
+ *	Init and allocate lo_attr structs
+ *
+ *	!	data is **argv 
+ *-----
+ */
+lo_attr *init_loa(char **data, int max, int start)
+{
+	lo_attr 	*l, 
+			*ll;
+	char		**d, 
+			*loc,
+			buff[128];
+
+	if ((l = (lo_attr *) malloc(max * sizeof(lo_attr))) == NULL) {
+		fprintf(stderr, "%s: can't allocate memory\n", data[0]);
+		exit(RE_ERROR);
+	}
+	for(d=data+start, ll=l; *d != NULL; d++, ll++) {
+		strncpy(buff, *d, 128);
+		if ((loc = strchr(buff, '.')) == NULL) {
+			fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", data[0], buff);
+			exit(RE_ERROR);	
+		}
+		*loc = '\0';
+		ll->table = strdup(buff);
+		ll->attr = strdup(++loc);
+	}
+	ll++;
+	ll->table = ll->attr = (char *) NULL;
+	return l;
+}
+
+/*-----
+ *	Check PG result
+ *-----
+ */
+int check_res(PGresult *res, PGconn *conn) 
+{
+	if (!res && PQresultStatus(res) != PGRES_COMMAND_OK) {
+        	fprintf(stderr, "%s\n",PQerrorMessage(conn));
+                PQclear(res);
+                return FALSE;
+        }
+        if (PQresultStatus(res) != PGRES_TUPLES_OK) {
+                fprintf(stderr, "Tuples is not OK.\n");
+                PQclear(res);
+                return FALSE;
+        }
+        return TRUE;        
+}
+
+
+/*-----
+ *	LO dump
+ *-----
+ */
+ void dump_lo(PGconn *conn, char *space, lo_attr *loa, char *db, char *prog)
+ {
+	PGresult	*res;		
+	lo_attr		*ploa;
+	FILE		*majorfile;
+	char		*dir,
+			path[BUFSIZ],
+			Qbuff[QUERY_BUFSIZ];
+	
+	dir = space ? space : getenv("PWD");		
+	sprintf(path, "%s/%s", dir, db); 
+	if (mkdir(path, DIR_UMASK) == -1) {
+		if (errno != EEXIST) {
+			perror(path);
+			exit(RE_ERROR);					
+		}	
+	}
+	
+	sprintf(path, "%s/lo_dump.index", path);          
+	if ((majorfile = fopen(path, "w")) == NULL) {
+		perror(path);
+		exit(RE_ERROR);
+	} else {
+		time_t	t;
+		time(&t);
+		fprintf(majorfile, "#\n# This is the PostgreSQL large object dump index\n#\n");
+		fprintf(majorfile, "#\tDate:     %s", ctime(&t));
+		fprintf(majorfile, "#\tHost:     %s\n", PQhost(conn) ? PQhost(conn) : "localhost");
+		fprintf(majorfile, "#\tDatabase: %s\n", db);
+		fprintf(majorfile, "#\tUser:     %s\n", PQuser(conn));
+		fprintf(majorfile, "#\n# oid\ttable\tattribut\tinfile\n");
+	}
+
+	for(ploa=loa; ploa->table != NULL; ploa++) {
+	
+		/* query */
+		sprintf(Qbuff, "SELECT %s FROM %s WHERE %s!=0", 
+			ploa->attr, ploa->table, ploa->attr);
+			
+		res = PQexec(conn, Qbuff);
+	
+		if (check_res(res, conn)) {
+			int	tuples	= PQntuples(res),
+				t;
+			char	*val;
+	
+			/* Make DIR/FILE */
+			if (tuples) {
+				sprintf(path, "%s/%s/%s", dir, db, ploa->table);          
+				if (mkdir(path, DIR_UMASK) == -1) {
+					if (errno != EEXIST) {
+						perror(path);
+						exit(RE_ERROR);					
+					}	
+				}
+				sprintf(path, "%s/%s", path, ploa->attr);          
+				if (mkdir(path, DIR_UMASK) == -1) {
+					if (errno != EEXIST) {
+						perror(path);
+						exit(RE_ERROR);					
+					}	
+				}
+				fprintf(stderr, "%s: dump %s.%s (%d lagre obj)\n", prog, 
+					ploa->table, ploa->attr, tuples);
+			}
+
+			for(t=0; t<tuples; t++) {
+				val = PQgetvalue(res, t, 0);
+				if (!val)
+					continue;
+				
+				sprintf(path, "%s/%s/%s/%s/%s", dir, db, ploa->table, ploa->attr, val);
+				
+				if (lo_export(conn, (Oid) atol(val), path) < 0) 
+					fprintf(stderr, "%s\n", PQerrorMessage(conn));
+				else
+					fprintf(majorfile, "%s\t%s\t%s\t%s/%s/%s/%s\n", val, 
+						ploa->table, ploa->attr, db, ploa->table, ploa->attr, val);
+			}
+		}
+	}	
+	fclose(majorfile);
+ }
+
+
+/*-----
+ *	LO import
+ *-----
+ */
+ void import_lo(PGconn *conn, char *space, char *db, char *prog)
+ {
+	PGresult	*res;		
+	lo_attr		loa;
+	FILE		*majorfile;
+	long 		new_oid;
+	char		*dir,
+			tab[128], attr[128],
+			path[BUFSIZ], lo_path[BUFSIZ],
+			Qbuff[QUERY_BUFSIZ];
+	
+	dir = space ? space : getenv("PWD");
+	sprintf(path, "%s/%s", dir, db);          
+
+	sprintf(path, "%s/lo_dump.index", path);          
+	if ((majorfile = fopen(path, "r")) == NULL) {
+		perror(path);
+		exit(RE_ERROR);
+	} 
+
+	while(fgets(Qbuff, QUERY_BUFSIZ, majorfile)) {
+		
+		if (*Qbuff == '#')
+			continue;
+
+		fprintf(stdout, Qbuff);
+		
+		sscanf(Qbuff, "%ld\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path); 
+		loa.table = tab;
+		loa.attr  = attr;
+
+		sprintf(lo_path, "%s/%s", dir, path); 
+				
+		/* import large obj */
+		if ((new_oid = lo_import(conn, lo_path)) <= 0) {
+			fprintf(stderr, "%s\n",PQerrorMessage(conn));
+			PQexec(conn, "ROLLBACK");
+			fprintf(stderr, "\nROLLBACK\n");
+			exit(RE_ERROR);
+		}
+	
+		/* query */
+		sprintf(Qbuff, "UPDATE %s SET %s=%ld WHERE %s=%ld", 
+			loa.table, loa.attr, new_oid, loa.attr, loa.lo_oid);
+
+		/*fprintf(stderr, Qbuff);*/
+			
+		res = PQexec(conn, Qbuff);
+	
+		if (!res && PQresultStatus(res) != PGRES_COMMAND_OK) {
+        		fprintf(stderr, "%s\n",PQerrorMessage(conn));
+                	PQclear(res);
+                	PQexec(conn, "ROLLBACK");
+			fprintf(stderr, "\nROLLBACK\n");
+			exit(RE_ERROR);
+        	}	
+        	
+	}	
+	fclose(majorfile);
+ }
+
+/*-----
+ *	The mother of all C functions
+ *-----
+ */
+int main(int argc, char **argv)
+{
+	PGconn		*conn;
+	lo_attr		*loa	=NULL;
+	char		*user	=NULL, 
+			*pwd	=NULL, 
+			*db	=NULL,
+			*host	=NULL,	
+			*space	=NULL;
+	int		import	=FALSE;
+
+	/* Parse argv */
+	if (argc) {
+      		int	arg, l_index=0;
+      		extern int optind;
+      		typedef enum {
+			ARG_USER,
+			ARG_PWD,
+			ARG_DB,
+			ARG_HELP,
+			ARG_IMPORT,
+			ARG_SPACE,
+			ARG_HOST
+		} _ARG_;
+      		
+      		struct option l_opt[] = {
+      			{ "help",	0, 0, ARG_HELP	 	},		
+			{ "user",	1, 0, ARG_USER 		},
+			{ "pwd",	1, 0, ARG_PWD 		},
+			{ "db",		1, 0, ARG_DB 		},
+			{ "host",	1, 0, ARG_HOST 		},
+			{ "space",	1, 0, ARG_SPACE		},
+			{ "import",	0, 0, ARG_IMPORT	},
+			{ NULL, 0, 0, 0 }
+      		};     	
+
+		while((arg = getopt_long(argc, argv, "hu:p:d:l:t:is:", l_opt, &l_index)) != -1) {
+        		switch(arg) {
+      			case ARG_HELP:
+      			case 'h':
+      				usage();
+        		    	exit(RE_OK);
+        		case ARG_USER:
+        		case 'u':    	
+        			user = strdup(optarg);
+        			break;	 
+        		case ARG_HOST:
+        		case 't':    	
+        			host = strdup(optarg);
+        			break;	 	
+        		case ARG_PWD:
+        		case 'p':    	
+        			pwd = strdup(optarg);
+        			break;	          		
+        		case ARG_DB:
+        		case 'd':    	
+        			db = strdup(optarg);
+        			break;
+        		case ARG_SPACE:
+        		case 's':    	
+        			space = strdup(optarg);
+        			break;	
+        		case ARG_IMPORT:
+        		case 'i':    	
+        			import = TRUE;
+        			break;	
+        		case 'l':
+        			loa = init_loa(argv, argc-1, optind-1);
+        			break;		        		
+        		}
+		}	
+	}  	
+
+	if (!space && !getenv("PWD")) {
+		fprintf(stderr, "%s: can't set directory (not set '-s' or $PWD).\n", argv[0]);
+		exit(RE_ERROR);
+	}
+
+	/* Make PG connection */
+	conn = PQsetdbLogin(host, NULL, NULL, NULL, db, user, pwd);
+        
+	/* check to see that the backend connection was successfully made */
+        if (PQstatus(conn) == CONNECTION_BAD) {
+                fprintf(stderr, "%s\n",PQerrorMessage(conn));
+                exit(RE_ERROR);
+        }
+
+	PQexec(conn, "BEGIN");
+
+	if (import) {
+		/* import obj */
+		import_lo(conn, space, db, argv[0]);
+	} else if (loa)	{
+		/* Dump obj */
+		dump_lo(conn, space, loa, db, argv[0]);
+	} else {
+		fprintf(stderr, "%s: ERROR: bad arg!\n", argv[0]);
+		usage();
+	}	
+
+	PQexec(conn, "COMMIT");
+	
+	/* bye PG */ 
+	PQfinish(conn);	
+	exit(RE_OK);
+}
\ No newline at end of file