From 92dcb0a23d35b88704c7cc0729ed46409a7fc30e Mon Sep 17 00:00:00 2001 From: Dave Page Date: Wed, 30 Nov 2016 17:48:35 +0900 Subject: [PATCH] Handle symlinks properly in the directory browser. This change properly handles symlinks by expanding any it finds in the path and issuing a redirect to the canonical location. Whilst we're here, display links as such on the pages, sort directory listings so the parent link is always at the top, and avoid unnecessary redirects caused by missing /'s on URLs. --- media/img/ftp/symlink.png | Bin 0 -> 906 bytes pgweb/downloads/views.py | 42 ++++++++++++++++++++++++---- pgweb/util/misc.py | 2 +- templates/downloads/ftpbrowser.html | 6 +++- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 media/img/ftp/symlink.png diff --git a/media/img/ftp/symlink.png b/media/img/ftp/symlink.png new file mode 100644 index 0000000000000000000000000000000000000000..bff40cfd23033f83fbfdb692e6be583c69fc7357 GIT binary patch literal 906 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz0!3HD`IPL*aEa{HEjtmSN`?>!lvI6;>1s;*b z3=G`DAk4@xYmNj117l=nNJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8Erc zlUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1A zfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf| zi<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{ z)XKjoGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1bPPZ!4! z3&FEf_Ifcp3LH=OclJTxfiFWF0OUBaOhCO zT=xwZui4FTGCcU~+{~M|KYz@$|d5=l*=Nw=NcBlc!i?(x;9xJ!x4#cXdmMmXKAEd|gf5!FxA#S)BMixe{9$ zPfXjnqq^5``-V?fJg2E1_+DG_CGNqpt8GVjDw%9s{i6N1z>;-d%VfSic=%HEzN^bp zgFDIz>#sN0?dLx}-8Uk3M&qw%Mqk;*gO~ai1|{BzpX;Z7?$Wa>QeR4T$7=XKt?;Wn znkaI>VWz=>=IRE|6ZY~}%?$hW@6TSFZn1M;`{!ePIcugm>lhlbqFVdQ&MBb@07494SO5S3 literal 0 HcmV?d00001 diff --git a/pgweb/downloads/views.py b/pgweb/downloads/views.py index d1ac61b5..d15810d7 100644 --- a/pgweb/downloads/views.py +++ b/pgweb/downloads/views.py @@ -1,3 +1,4 @@ +from django.core.urlresolvers import reverse from django.shortcuts import render_to_response, get_object_or_404 from django.http import HttpResponse, Http404, HttpResponseRedirect from pgweb.util.decorators import login_required @@ -40,16 +41,45 @@ def ftpbrowser(request, subpath): except Exception, e: return HttpServerError("Failed to load ftp site information: %s" % e) - if not allnodes.has_key(subpath): - raise Http404 + # An incoming subpath may either be canonical, or have one or more elements + # present that are actually symlinks. For each element of the path, test to + # see if it is present in the pickle. If not, look for a symlink entry with + # and if present, replace the original entry with the symlink target. + canonpath = '' + if subpath != '': + parent = '' + for d in subpath.split('/'): + # Check if allnodes contains a node matching the path + if allnodes[parent].has_key(d): + if allnodes[parent][d]['t'] == 'd': + canonpath = os.path.join(canonpath, d) + elif allnodes[parent][d]['t'] == 'l': + canonpath = os.path.join(canonpath, allnodes[parent][d]['d']) + else: + # There's a matching node, but it's not a link or a directory + raise Http404 + + parent = canonpath + else: + # There's no matching node + raise Http404 + + # If we wound up with a canonical path that doesn't match the original request, + # redirect the user + canonpath = canonpath.strip('/') + if subpath != canonpath: + return HttpResponseRedirect('/ftp/' + canonpath) node = allnodes[subpath] del allnodes # Add all directories - directories = [{'link': k, 'url': k} for k,v in node.items() if v['t'] == 'd'] - # Add all symlinks (only directoreis supported) - directories.extend([{'link': k, 'url': v['d']} for k,v in node.items() if v['t'] == 'l']) + directories = [{'link': k, 'url': k, 'type': 'd'} for k,v in node.items() if v['t'] == 'd'] + # Add all symlinks (only directories supported) + directories.extend([{'link': k, 'url': v['d'], 'type': 'l'} for k,v in node.items() if v['t'] == 'l']) + + # A ittle early sorting wouldn't go amiss, so .. ends up at the top + directories.sort(key = version_sort, reverse=True) # Add a link to the parent directory if subpath: @@ -80,7 +110,7 @@ def ftpbrowser(request, subpath): return render_to_response('downloads/ftpbrowser.html', { 'basepath': subpath.rstrip('/'), - 'directories': sorted(directories, key = version_sort, reverse=True), + 'directories': directories, 'files': sorted(files), 'breadcrumbs': breadcrumbs, 'readme': file_readme, diff --git a/pgweb/util/misc.py b/pgweb/util/misc.py index d06d24d6..a7e2c154 100644 --- a/pgweb/util/misc.py +++ b/pgweb/util/misc.py @@ -41,7 +41,7 @@ def version_sort(l): """ map a directory name to a format that will show up sensibly in an ascii sort """ - mkey = l['url'] + mkey = l['link'] m = re.match('v([0-9]+)\.([0-9]+)\.([0-9]+)$',l['url']) if m: mkey = m.group(1) + '%02d' % int(m.group(2)) + '%02d' % int(m.group(3)); diff --git a/templates/downloads/ftpbrowser.html b/templates/downloads/ftpbrowser.html index a9b4ce9f..ad8f6866 100644 --- a/templates/downloads/ftpbrowser.html +++ b/templates/downloads/ftpbrowser.html @@ -9,7 +9,11 @@
{%for dir in directories%} - + {% if dir.type == 'd' or dir.link = '[Parent Directory]' %} + + {%else%} + + {%endif%} {%endfor%}
{{dir.link}} {{dir.link}}
{{dir.link}} {{dir.link}}
{{dir.link}} -> {{dir.url}} {{dir.link}} -> {{dir.url}}