Commits

Anonymous committed 3611108

fix:
- wiki link error
- timesince
- style in html embedded (add attr)

new:
- now css and js are tagged with their date to help browser to know we change them.

  • Participants
  • Parent commits 4c8199c

Comments (0)

Files changed (11)

File couchit/application.py

                 response = self.views['couchit_%s' % cname](request, **request.args)
             else:
                 response = self.views['home'](request, cname=cname, alias=alias, **request.args)
-            
+        
+        args = {}
+        endpoint=''
         if response is None:
             request.site = site
 
 
         if hasattr(request, 'site'):
             if request.site.privacy == "private" and not authenticated and endpoint!='site_login' and endpoint!='forgot_password' and endpoint !='change_password':
-                response = redirect(url_for('site_login'))
+                back = ''
+                if endpoint:
+                    back = url_for(endpoint, **args)
+                response = redirect(url_for('site_login', back=back))
             elif not subdomain and request.site.alias:
                 redirect_url = "http://%s.%s/%s" % (request.site.alias, settings.SERVER_NAME, 
                                         path_info)

File couchit/contrib/markdown_extensions/wikilinks.py

             label = m.group(2).strip()
             label = re_page.sub("", label)
             url = '%s%s%s'% (base_url, label, end_url)
+            url = url.replace(" ", "_")
             a = markdown.etree.Element('a')
             a.text = markdown.AtomicString(label)
             a.set('href', url)

File couchit/utils/html.py

       'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'prompt', 'readonly',
       'rel', 'rev', 'rows', 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size',
       'span', 'src', 'start', 'summary', 'tabindex', 'target', 'title', 'type',
-      'usemap', 'valign', 'value', 'vspace', 'width']
+      'usemap', 'valign', 'value', 'vspace', 'width', 'style']
 
     unacceptable_elements_with_end_tag = ['script', 'applet']
     

File couchit/views.py

 from couchit.models import *
 from couchit.api import *
 from couchit.http import BCResponse
-from couchit.template import render_response, url_for, render_template, send_json
+from couchit.template import render_response, url_for, render_template, send_json, convert_markdown
 from couchit.utils import local, make_hash, datetime_tojson, to_str
 from couchit.utils.mail import send_mail
 
             redirect_url = local.site_url and local.site_url or "/"
             return redirect(redirect_url)
         return f(request, **kwargs)
-    return decorated            
-        
+    return decorated
+    
+    
 def not_found(request):
     return render_response("not_found.html")
 
     
     return redirect(url_for('show_page', pagename=pagename))
 
-@can_edit  
+@can_edit
+@login_required
 def delete_page(request, pagename):
     if pagename == 'Home': #security reason
         return redirect(url_for('show_page', pagename='Home'))
                     title = "\n".join(change['changed']['lines'])
                     title = do_truncate(do_striptags(title), 60)
             title = title and title or "Edited."
-            feed.add(title, escape(rev.content), 
+            feed.add(title, convert_markdown(rev.content), 
                 updated=rev.updated,
                 url=_url,
                 id=_url,
                 'id':rev.nb_revision
             })
         return send_json(json)
-    
 
 def site_changes(request, feedtype=None):
     pages = all_pages(local.db, request.site.id)
         )
         for rev in changes:
             _url = "%s%s" % (request.host_url, url_for("show_page", pagename=rev.title.replace(' ', '_')))
-            feed.add(rev.title, escape(rev.content), 
+            feed.add(rev.title, convert_markdown(rev.content), 
                 updated=rev.updated,
                 url=_url,
                 id=_url,
     return render_response('site/forgot_password.html', back=back)
 
 @can_edit
+@login_required
 def site_design(request):
     DEFAULT_COLORS = dict(
         background_color = 'E7E7E7',

File maintenance.html

+<!DOCTYPE html>
+
+<html lang="en">
+
+<head>
+    <meta charset="utf-8" />
+    <title>couchit.net maintenance</title>
+    <link rel="icon" type="image/png" href="/static/img/favicon.png" />
+    
+
+    <link rel="stylesheet" href="/static/css/screen.css" type="text/css" media="screen, projection" />
+    <link rel="stylesheet" href="/static/css/theme.css" type="text/css" media="screen, projection" />
+    <link rel="stylesheet" href="/static/css/print.css" type="text/css" media="print" /> 
+    <!--[if IE]>
+      <link rel="stylesheet" href="/static/css/ie.css" type="text/css" media="screen, projection" />
+    <![endif]-->
+  
+</head>
+<body>
+  
+
+    
+    <div id="container">
+
+         <header id="site_header">
+             
+         </header>   
+
+        
+        
+        <div id="page_wrapper">
+            <section id="pgeneric">
+            <h1>Maintenance</h1>
+           <p>2008-09-21 - 18:40 (CEST)</p>
+           <p>We are updating couchit. Will be back in 5 minutes.</p>
+           </section>
+        </div>
+        
+        <footer class="footer_wrapper">
+
+            
+            <p class="powered">Powered by <a href="http://couchit.net">CouchIt</a>.</p>
+        </footer>
+        
+
+        
+    </div>
+</body>
+</html>

File static/js/couchit-application.js

-if(!document.createElementNS){document.createElement("section");document.createElement("audio");document.createElement("video");document.createElement("article");document.createElement("aside");document.createElement("footer");document.createElement("header");document.createElement("nav");document.createElement("time")}Date.parseRFC3339=function(C){var B=new Date(0);var A=C.match(/(\d{4})-(\d\d)-(\d\d)\s*(?:[\sT]\s*(\d\d):(\d\d)(?::(\d\d))?(\.\d*)?\s*(Z|([-+])(\d\d):(\d\d))?)?/);if(!A){return }if(A[2]){A[2]--}if(A[7]){A[7]=(A[7]+"000").substring(1,4)}var E=[null,"FullYear","Month","Date","Hours","Minutes","Seconds","Milliseconds"];for(var D=1;D<=7;D++){if(A[D]){B["setUTC"+E[D]](A[D])}}if(A[9]){B.setTime(B.getTime()+(A[9]=="-"?1:-1)*(A[10]*3600000+A[11]*60000))}return B.getTime()};function localizeDates(){var B="";var A=new Date();$$("time").each(function(E,D){if(E.getAttribute("title")=="GMT"){var C=new Date(Date.parseRFC3339(E.getAttribute("datetime")));if(!C.getTime()){return }diff=((A.getTime()-C.getTime())/1000),day_diff=Math.floor(diff/86400);if(isNaN(day_diff)||day_diff<0||day_diff>=31){return }var G=C.toLocaleString();var F=C.toLocaleString();if(day_diff==0){G=(diff<60&&"Just Now"||diff<120&&"1 minute ago"||diff<3600&&Math.floor(diff/60)+" minutes ago"||diff<7200&&"1 hour ago"||diff<86400&&Math.floor(diff/3600)+" hours ago");F=C.toLocaleTimeString()}else{G=(day_diff=1&&"Yesterday"||day_diff<7&&day_diff+" days ago");F=C.toLocaleString()}E.setAttribute("title",F);E.textContent="posted "+G}})}var Page={};var Site={url:"",name:""};var FORBIDDEN_PAGES=["site","delete","edit","create","history","changes"];var Create=Class.create({initialize:function(){var A=this;this.Form=$("fnewpage");this.doCreate=$("doCreate");this.Form.addClassName("hidden");Event.observe(this.doCreate,"click",function(B){Event.stop(B);A.show();return false},false);Event.observe($$("a.cancelCreate")[0],"click",function(B){Event.stop(B);A.cancel();return false},false);$("screate").observe("click",function(B){Event.stop(B);A.submit();return false},false)},show:function(){this.doCreate.addClassName("hidden");this.Form.removeClassName("hidden")},cancel:function(){this.Form.addClassName("hidden");this.doCreate.removeClassName("hidden")},submit:function(){var B=$("title");if(!B.value.match(/^[ \w\u00A1-\uFFFF]+$/i)||FORBIDDEN_PAGES.indexOf(B.value)>=0){alert("Page title invalid");return false}var A=B.value.replace(/ /g,"_");document.location.href=Site.url+"/"+A+"#pedit"},});var Compare=Class.create({nb_selected:0,selected:false,initialize:function(){var A=this;this.Form=$("fhistory");$$("input.c").each(function(B){B.observe("click",function(C){A.check(this)},false)})},check:function(A){row=A.parentNode.parentNode;row.toggleClassName("rselected");if(!A.checked){this.nb_selected-=1;A.removeClassName("selected")}else{this.nb_selected+=1;A.addClassName("selected")}if(this.nb_selected==2){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled="disabled"}});this.selected=true}else{if(this.selected){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled=null}});this.selected=false}}}});var Diff=Class.create({initialize:function(){var A=this;this.rev_from=$("rev_from");this.rev_to=$("rev_to");$("scompare").observe("click",function(B){Event.stop(B);A.get_diff();return false})},get_diff:function(){var B=this.rev_from.getValue();var A=this.rev_to.getValue();if(B==A){alert("Why would you want compare same version ...");return }url=$("fdiff").action+"?r="+B+"&r="+A;new Ajax.Request(url,{method:"get",contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){data=C.responseText.evalJSON(true);if(data.ok){Element.remove($("tableDiff"));$("pdiff").insert(data.diff)}}})}});var Settings=Class.create({initialize:function(){var A=this;this.observer=null;this.title=$("site_header").select("h1 a")[0];this.subtitle=$("site_header").select("h2")[0];$$("input").each(function(B){new Form.Element.Observer(B,0.2,function(C,D){if(C.id=="site_title"){A.title.update(D);document.title=D+" - settings"}if(C.id=="site_subtitle"){A.subtitle.update(D)}if(A.observer){clearTimeout(A.observer)}A.observer=setTimeout(A.save.bind(A),400)})})},save:function(){var A={};try{A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue(),email:$("email").getValue(),privacy:$$('input:checked[type="radio"][name="privacy"]').pluck("value")[0],allow_javascript:$("allow_javascript").getValue()}}catch(B){A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue()}}url=$("fsettings").action;new Ajax.Request(url,{method:"post",postBody:Object.toJSON(A),contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){A=C.responseText.evalJSON(true)}})}});var SiteAddress=Class.create({initialize:function(){var A=this;if(!$("error").innerHTML){$("error").hide()}new Form.Element.Observer("alias",0.2,function(B,C){if(C.length>3&&!C.match(/^(\w+)$/)){$("error").update("<strong>Error:</strong> "+$("alias").value+" is invalid, only use letters and numbers.");$("error").show()}else{$("error").hide()}});$("faddress").observe("submit",function(D){Event.stop(D);var B=null;var C=$("alias").getValue();if(C.length<=3){B="length < 3"}else{if(!C.match(/^(\w+)$/)){B=C+" is invalid, only use letters and numbers."}}if(B){$("error").update("<strong>Error:</strong> "+B);$("error").show();return false}else{A.valid_name()}},false)},valid_name:function(){url=$("faddress").action;new Ajax.Request(url,{method:"get",contentType:"application/json",parameters:{alias:$("alias").getValue()},requestHeaders:{Accept:"application/json"},onSuccess:function(A){data=A.responseText.evalJSON(true);if(data.ok){$("faddress").submit()}else{$("error").update("<strong>Error:</strong> "+data.error);$("error").show()}}})}});var Claim=Class.create({initialize:function(){var A=this;this.email=$("email");this.password=$("password");$("fclaim").observe("submit",function(B){Event.stop(B);if(A.validate()){this.submit()}},false)},validate:function(){$$(".help_error").each(function(B){B.remove()});$$(".errors").each(function(B){B.removeClassName("errors")});nb_errors=0;if(!this.email.value.match(/(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*")@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i)){var A=new Element("div",{"class":"help_error"}).update("Invalid email address.");this.email.parentNode.insert(A);$("row_email").addClassName("errors");nb_errors+=1}if(this.password.value.length<=0){var A=new Element("div",{"class":"help_error"}).update("You should set a password.");this.password.parentNode.insert(A);$("row_password").addClassName("errors");nb_errors+=1}if(nb_errors>0){return false}return true}});document.observe("dom:loaded",function(){localizeDates()});
+if(!document.createElementNS){document.createElement("section");document.createElement("audio");document.createElement("video");document.createElement("article");document.createElement("aside");document.createElement("footer");document.createElement("header");document.createElement("nav");document.createElement("time")}Date.parseRFC3339=function(C){var B=new Date(0);var A=C.match(/(\d{4})-(\d\d)-(\d\d)\s*(?:[\sT]\s*(\d\d):(\d\d)(?::(\d\d))?(\.\d*)?\s*(Z|([-+])(\d\d):(\d\d))?)?/);if(!A){return }if(A[2]){A[2]--}if(A[7]){A[7]=(A[7]+"000").substring(1,4)}var E=[null,"FullYear","Month","Date","Hours","Minutes","Seconds","Milliseconds"];for(var D=1;D<=7;D++){if(A[D]){B["setUTC"+E[D]](A[D])}}if(A[9]){B.setTime(B.getTime()+(A[9]=="-"?1:-1)*(A[10]*3600000+A[11]*60000))}return B.getTime()};function localizeDates(){var B="";var A=new Date();$$("time").each(function(E,D){if(E.getAttribute("title")=="GMT"){var C=new Date(Date.parseRFC3339(E.getAttribute("datetime")));if(!C.getTime()){return }diff=((A.getTime()-C.getTime())/1000),day_diff=Math.floor(diff/86400);if(isNaN(day_diff)||day_diff<0||day_diff>=31){return }var G=C.toLocaleString();var F=C.toLocaleString();if(day_diff==0){G=(diff<60&&"Just Now"||diff<120&&"1 minute ago"||diff<3600&&Math.floor(diff/60)+" minutes ago"||diff<7200&&"1 hour ago"||diff<86400&&Math.floor(diff/3600)+" hours ago");F=C.toLocaleTimeString()}else{hours=C.getHours();minutes=C.getMinutes();hours=(hours<10)&&"0"+hours||hours;minutes=(minutes<10)&&"0"+minutes||minutes;G=(day_diff==1&&"Yesterday at "+hours+":"+minutes||E.textContent);F=C.toLocaleString()}E.setAttribute("title",F);E.textContent="posted "+G}})}var Page={};var Site={url:"",name:""};var FORBIDDEN_PAGES=["site","delete","edit","create","history","changes"];var Create=Class.create({initialize:function(){var A=this;this.Form=$("fnewpage");this.doCreate=$("doCreate");this.Form.addClassName("hidden");Event.observe(this.doCreate,"click",function(B){Event.stop(B);A.show();return false},false);Event.observe($$("a.cancelCreate")[0],"click",function(B){Event.stop(B);A.cancel();return false},false);$("screate").observe("click",function(B){Event.stop(B);A.submit();return false},false)},show:function(){this.doCreate.addClassName("hidden");this.Form.removeClassName("hidden")},cancel:function(){this.Form.addClassName("hidden");this.doCreate.removeClassName("hidden")},submit:function(){var B=$("title");if(!B.value.match(/^[ \w\u00A1-\uFFFF]+$/i)||FORBIDDEN_PAGES.indexOf(B.value)>=0){alert("Page title invalid");return false}var A=B.value.replace(/ /g,"_");document.location.href=Site.url+"/"+A+"#pedit"},});var Compare=Class.create({nb_selected:0,selected:false,initialize:function(){var A=this;this.Form=$("fhistory");$$("input.c").each(function(B){B.observe("click",function(C){A.check(this)},false)})},check:function(A){row=A.parentNode.parentNode;row.toggleClassName("rselected");if(!A.checked){this.nb_selected-=1;A.removeClassName("selected")}else{this.nb_selected+=1;A.addClassName("selected")}if(this.nb_selected==2){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled="disabled"}});this.selected=true}else{if(this.selected){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled=null}});this.selected=false}}}});var Diff=Class.create({initialize:function(){var A=this;this.rev_from=$("rev_from");this.rev_to=$("rev_to");$("scompare").observe("click",function(B){Event.stop(B);A.get_diff();return false})},get_diff:function(){var B=this.rev_from.getValue();var A=this.rev_to.getValue();if(B==A){alert("Why would you want compare same version ...");return }url=$("fdiff").action+"?r="+B+"&r="+A;new Ajax.Request(url,{method:"get",contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){data=C.responseText.evalJSON(true);if(data.ok){Element.remove($("tableDiff"));$("pdiff").insert(data.diff)}}})}});var Settings=Class.create({initialize:function(){var A=this;this.observer=null;this.title=$("site_header").select("h1 a")[0];this.subtitle=$("site_header").select("h2")[0];$$("input").each(function(B){new Form.Element.Observer(B,0.2,function(C,D){if(C.id=="site_title"){A.title.update(D);document.title=D+" - settings"}if(C.id=="site_subtitle"){A.subtitle.update(D)}if(A.observer){clearTimeout(A.observer)}A.observer=setTimeout(A.save.bind(A),400)})})},save:function(){var A={};try{A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue(),email:$("email").getValue(),privacy:$$('input:checked[type="radio"][name="privacy"]').pluck("value")[0],allow_javascript:$("allow_javascript").getValue()}}catch(B){A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue()}}url=$("fsettings").action;new Ajax.Request(url,{method:"post",postBody:Object.toJSON(A),contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){A=C.responseText.evalJSON(true)}})}});var SiteAddress=Class.create({initialize:function(){var A=this;if(!$("error").innerHTML){$("error").hide()}new Form.Element.Observer("alias",0.2,function(B,C){if(C.length>3&&!C.match(/^(\w+)$/)){$("error").update("<strong>Error:</strong> "+$("alias").value+" is invalid, only use letters and numbers.");$("error").show()}else{$("error").hide()}});$("faddress").observe("submit",function(D){Event.stop(D);var B=null;var C=$("alias").getValue();if(C.length<=3){B="length < 3"}else{if(!C.match(/^(\w+)$/)){B=C+" is invalid, only use letters and numbers."}}if(B){$("error").update("<strong>Error:</strong> "+B);$("error").show();return false}else{A.valid_name()}},false)},valid_name:function(){url=$("faddress").action;new Ajax.Request(url,{method:"get",contentType:"application/json",parameters:{alias:$("alias").getValue()},requestHeaders:{Accept:"application/json"},onSuccess:function(A){data=A.responseText.evalJSON(true);if(data.ok){$("faddress").submit()}else{$("error").update("<strong>Error:</strong> "+data.error);$("error").show()}}})}});var Claim=Class.create({initialize:function(){var A=this;this.email=$("email");this.password=$("password");$("fclaim").observe("submit",function(B){Event.stop(B);if(A.validate()){this.submit()}},false)},validate:function(){$$(".help_error").each(function(B){B.remove()});$$(".errors").each(function(B){B.removeClassName("errors")});nb_errors=0;if(!this.email.value.match(/(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*")@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i)){var A=new Element("div",{"class":"help_error"}).update("Invalid email address.");this.email.parentNode.insert(A);$("row_email").addClassName("errors");nb_errors+=1}if(this.password.value.length<=0){var A=new Element("div",{"class":"help_error"}).update("You should set a password.");this.password.parentNode.insert(A);$("row_password").addClassName("errors");nb_errors+=1}if(nb_errors>0){return false}return true}});document.observe("dom:loaded",function(){localizeDates()});

File static/js/src/application.js

                 return;
             var text = date.toLocaleString();
             var title = date.toLocaleString();
+            
             if (day_diff == 0) {
                 text = (diff < 60 && "Just Now" ||
                 diff < 120 && "1 minute ago" ||
                 diff < 86400 && Math.floor( diff / 3600 ) + " hours ago");
                 title = date.toLocaleTimeString();
             } else {
-                text = (day_diff = 1 && "Yesterday" ||
-                day_diff < 7 && day_diff + " days ago");
+                hours = date.getHours();
+                minutes = date.getMinutes();
+                hours = (hours < 10) && "0" + hours || hours;
+                minutes = (minutes < 10) && "0" + minutes || minutes;
+                text = (day_diff == 1 && "Yesterday at " +  hours + ":" + minutes ||
+                el.textContent);
                 title = date.toLocaleString();
             }
             el.setAttribute('title', title);

File templates/base.html

     <meta charset="utf-8" />
     <title>{% if site and site.title %}{{ site.title }} - {% endif %}{% block title %}{% endblock %}</title>
     <link rel="icon" type="image/png" href="/static/img/favicon.png" />
+    <link rel="shortcut icon" href="/static/img/favicon.png" type="image/png" />
     
     {% if DEBUG %}
     <link rel="stylesheet" href="/static/css/src/debug.css" type="text/css" />
     <script src="/static/js/lib/slider.js" type="text/javascript"></script>
     <script src="/static/js/src/application.js" type="text/javascript"></script>
     {% else %}
-    <link rel="stylesheet" href="/static/css/screen.css" type="text/css" media="screen, projection" />
-    <link rel="stylesheet" href="/static/css/theme.css" type="text/css" media="screen, projection" />
-    <link rel="stylesheet" href="/static/css/print.css" type="text/css" media="print" /> 
+    <link rel="stylesheet" href="/static/css/screen.css?20080925" type="text/css" media="screen, projection" />
+    <link rel="stylesheet" href="/static/css/theme.css?20080925" type="text/css" media="screen, projection" />
+    <link rel="stylesheet" href="/static/css/print.css?20080925" type="text/css" media="print" /> 
     <!--[if IE]>
-      <link rel="stylesheet" href="/static/css/ie.css" type="text/css" media="screen, projection" />
+      <link rel="stylesheet" href="/static/css/ie.css?20080925" type="text/css" media="screen, projection" />
     <![endif]-->
     {% if site %}
 
-    <script src="/static/js/prototype.js" type="text/javascript"></script>
-    <script src="/static/js/scriptaculous.js" type="text/javascript"></script>
-    <script src="/static/js/couchit-application.js" type="text/javascript"></script>
+    <script src="/static/js/prototype.js?20080925" type="text/javascript"></script>
+    <script src="/static/js/scriptaculous.js?20080925" type="text/javascript"></script>
+    <script src="/static/js/couchit-application.js?20080925" type="text/javascript"></script>
     {% endif %}
     
     {% endif %}

File templates/page/show.html

 <script src="/static/js/lib/showdown.js" type="text/javascript"></script>
 <script src="/static/js/src/page.js" type="text/javascript"></script>
 {% else %}
-<script src="/static/js/livepipe.js" type="text/javascript"></script>
-<script src="/static/js/couchit-page.js" type="text/javascript"></script>
+<script src="/static/js/livepipe.js?20080925" type="text/javascript"></script>
+<script src="/static/js/couchit-page.js?20080925" type="text/javascript"></script>
 {% endif %}
 
 {% endblock %}

File templates/site/design.html

 <script src="/static/js/lib/yahoo.color.js" type="text/javascript"></script>
 <script src="/static/js/lib/colorPicker.js" type="text/javascript"></script>
 {% else %}
-<script src="/static/js/colorpicker.js" type="text/javascript"></script>
+<script src="/static/js/colorpicker.js?20080925" type="text/javascript"></script>
 {% endif %}
 
 

File templates/site/login.html

         {% if notify %}
         <p class="notify">{{ notify }}</p>
         {% endif %}
-        <p><input type="password" name="password" id="password" value="password" /> <a href="{{ site_url }}/site/forgot-password?back={{ back }}">(I forgot the password)</a></p>
+        <p><input type="password" name="password" id="password" value="" /> <a href="{{ site_url }}/site/forgot-password?back={{ back }}">(I forgot the password)</a></p>
         <p><input type="checkbox" id="remerber" name="remember" /><label for="remember">Remember me</label></p>
         <p><input type="submit" id="spassword" name="spassword" value="Login"></p>
     </form>