Julio Montoya 12 years ago
parent
commit
5087be6bc3

+ 15 - 0
documentation/changelog.html

@@ -220,6 +220,21 @@ This version of Chamilo only includes new features:
   <li>Removed the "Use document title" option - now we force users to use a document title - this avoids many issues with documents names - see #3781</li>
 </ul>
 
+<h1>Chamilo 1.8.8.6 - Rottweil, 20th of July 2012</h1>
+
+<h3>Release notes - summary</h3>
+<p>Chamilo 1.8.8.6 is a minor security fix, stable version for version 1.8.8.4. If you are using Chamilo 1.8.8.4, we highly recommend you upgrade to this version, either by following the usual upgrade procedure, or by applying a very small patch, as explained on <a href="http://support.chamilo.org/projects/chamilo-18/wiki/Security_issues">our security issues listing page</a>. The security fixes are all considered "moderate". This means you could loose data (specifically dropbox tool data in this case) and your users might get tricked into providing credentials to potential hackers, but the integrity of your server will not be in direct danger. 1.8.8.6 was developed in a separate branch, but fixes were applied to the 1.9 branch, which means 1.9 can be considered as the follower of 1.8.8.6 as much as of 1.8.8.4. If you have 1.8.8.4, migrating to 1.9 will effectively remove the need for migrating to the intermediary step of 1.8.8.6</p>
+<h4>Why Rottweil?</h4>
+<p><a href="https://maps.google.com/maps?q=48.167352,8.627969&hl=fr&ll=48.167352,8.627969&spn=0.006054,0.016512&sll=48.167352,8.627969&sspn=0.006054,0.016512&t=h&z=17">Rottweil</a> is a <a href="http://en.wikipedia.org/wiki/Rottweil">small medieval German town</a> where the occasional tourist might feel very relaxed and secure. This feeling is increased by the obviously-difficult-to-attack strategical position. Considering the security-only aspect of this release, we wanted a small city name that would represent this more secure aspect. Rottweil has been visited by one of our team members in the past... that's all it takes.</p>
+
+<h3>Fixes</h3>
+<ul>
+  <li>Fixed long-standing e-mail sending bug (fixed in upstream and documented on the forum and all over the internet)</li>
+  <li>Fixed a reflected XSS PHP_SELF security flax in the phpdocx 3rd-party library - #5202</li>
+  <li>Fixed an unauthorized file deletion in dropbox by logged in users - #5202</li>
+  <li>Fixed XSS unfiltered input in dropbox - #5202</li>
+</ul>
+
 
 <h1>Chamilo 1.8.8.4 - La Molina, August 2011</h1>
 

+ 25 - 0
main/template/default/course_description/edit.tpl

@@ -0,0 +1,25 @@
+{{javascript}}
+
+{% for message in messages %}
+    {{ message }}
+{% endfor %}
+
+<div class="actions" >
+    <a href = "{{root}}&amp;action=listing" class = "course_description btn back"></a>
+    {% for type in types %}        
+        <a href="{{root}}&amp;action=add&amp;description_type={{type.id}}"> 
+            <img title="{{type.title}}" alt="type.title" src="{{type.icon|icon(32)}} ">
+        </a>    
+    {% endfor %}
+</div>
+
+{% if type.question %}	
+    <div class="normal-message">
+        <div>            
+            <strong>{{'QuestionPlan'|get_lang}}</strong>
+        </div>
+        {{type.question}}
+    </div>
+{% endif %}
+
+{{form.return_form()}}

+ 99 - 0
main/template/default/course_description/index.tpl

@@ -0,0 +1,99 @@
+{{javascript}}
+
+<script type="text/javascript">
+
+{% if is_allowed_to_edit %}
+    var sec_token = '{{sec_token}}';
+{% endif %}
+
+    
+ function delete_entry(name, btn){   
+    if(!confirm("{{'ConfirmYourChoice'|get_lang}}")){
+        return false;
+    } 
+
+    var item = $('#'+name);
+    var id = item.attr('data-id'); 
+    var c_id = item.attr('data-c_id'); 
+
+    var f = function(data){
+        if(data.success){
+            item.remove();
+        }
+        message.update(data);
+        $(btn).removeClass("loading");
+    };
+    CourseDescription.del(c_id, id, f);
+    $(btn).addClass("loading");
+ }
+
+ function delete_all(){
+    if(!confirm("{{'ConfirmYourChoice'|get_lang}}")){
+        return false;
+    } 
+    
+    var f = function(data){
+        if(data.success){
+            var item = $('.course_descriptions');
+            item.remove();
+        }
+        message.update(data);
+    };
+    CourseDescription.delete_by_course({{c_id}}, {{session_id}}, f);
+    
+ }
+ 
+</script>
+
+{% for message in messages %}
+    {{ message }}
+{% endfor %}
+
+{% if is_allowed_to_edit %}
+    <div class="actions" >
+        {% for type in types %}        
+            <a href="{{root}}&amp;action=add&amp;description_type={{type.id}}"> 
+                <img title="{{type.title}}" alt="{{type.title}}" src="{{type.icon|icon(32)}} ">
+            </a>    
+        {% endfor %}
+        <a href="{{root}}&amp;action=import_csv" class="btn import_csv" title="{{'ImportCSV'|get_lang}}"></a>
+        <a href="{{root}}&amp;action=export_csv" class="btn export_csv" title="{{'ExportAsCSV'|get_lang}}"></a>
+        <a href="javascript:void(0)" onclick="delete_all();return false;" class="btn delete_all" title="{{'DeleteAll'|get_lang}}"></a>
+    </div>
+{% endif %}
+
+<ul style="list-style: none; margin-left:0;" class="course_descriptions">
+{% for description in descriptions %}
+    <li id="description_{{description.id}}" class="course_description" data-id="{{description.id}}" data-c_id="{{description.c_id}}" data-type="course_description">
+        <div class="title sectiontitle">
+            {% if is_allowed_to_edit %}
+                <div style="float:right;">
+                {% if session_id == description.session_id %}                    
+                    <a href="{{root}}&amp;action=delete&amp;id={{description.id}}" 
+                       onclick="delete_entry('description_{{description.id}}', this); return false;"
+                       class="btn delete"
+                       title="{{'Delete'|get_lang}}">
+                    </a>
+
+                    <a href="{{root}}&amp;action=edit&amp;id={{description.id}}" 
+                       class="btn edit"
+                       title="{{'Edit'|get_lang}}">
+                    </a>
+                {% else %}
+                    <img title="{{'EditionNotAvailableFromSession'|get_lang}}" 
+                         alt="{{'EditionNotAvailableFromSession'|get_lang}}" 
+                         src="{{'edit_na.png'|icon(22)}}" 
+                         style="vertical-align:middle;">
+                {% endif %}
+                </div>
+            {% endif %}
+            
+            <img title="{{description.type.title}}" alt="{{description.type.title}}" src="{{description.type.icon|icon(32)}}" class="icon">
+            {{description.title}}
+        </div>
+        <div class="sectioncomment">
+            {{description.content}}
+        </div>
+    </li>
+{% endfor %}
+</ul>

+ 11 - 0
main/template/default/course_description/upload.tpl

@@ -0,0 +1,11 @@
+{{javascript}}
+
+{% for message in messages %}
+    {{ message }}
+{% endfor %}
+
+<div class="actions" >
+    <a href = "{{root}}&amp;action=listing" class = "course_description btn back"></a>
+</div>
+
+{{form.return_form()}}

+ 0 - 0
main/template/default/glossary/csv.tpl


+ 8 - 0
main/template/default/glossary/edit.tpl

@@ -0,0 +1,8 @@
+
+{% include 'default/glossary/header.tpl' %}
+
+<div class="actions" >
+    <a href = "{{root}}&amp;action=index" class = "glossary btn back"></a>
+</div>
+
+{{form.return_form()}}

+ 7 - 0
main/template/default/glossary/header.tpl

@@ -0,0 +1,7 @@
+{{javascript}}
+
+<div id="messages">
+    {% for message in messages %}
+        {{ message }}
+    {% endfor %}
+</div>

+ 23 - 0
main/template/default/glossary/index.tpl

@@ -0,0 +1,23 @@
+{% include 'default/glossary/header.tpl' %}
+{% include 'default/glossary/javascript.tpl' %}
+
+<div class="actions" >
+    {% if is_allowed_to_edit %}
+        <a href="{{root}}&amp;action=add" class=" glossary btn new term" title="{{'Add'|get_lang}}"></a>
+        <a href="{{root}}&amp;action=import_csv" class="btn import_csv" title="{{'ImportCSV'|get_lang}}"></a>
+        <a href="{{root}}&amp;action=export_csv" class="btn export_csv" title="{{'ExportAsCSV'|get_lang}}"></a>
+        <a href="javascript:void(0)" onclick="ui.remove_by_course('entries', this);return false;" class="btn delete_all" title="{{'DeleteAll'|get_lang}}"></a>
+    {% endif %}    
+    {% if view == 'table' %}
+        <a href="{{root}}&amp;view=list" class="btn view text" title="{{'ExportAsCSV'|get_lang}}"></a>
+    {% else %}
+        <a href="{{root}}&amp;view=table" class="btn view detailed" title="{{'ExportAsCSV'|get_lang}}"></a>
+    {% endif %}
+    
+</div>
+
+{% if view == 'table' %}
+    {% include 'default/glossary/table.tpl' %}
+{% else %}
+    {% include 'default/glossary/list.tpl' %}
+{% endif %}

+ 28 - 0
main/template/default/glossary/javascript.tpl

@@ -0,0 +1,28 @@
+<script type="text/javascript" src="{{www}}/main/glossary/resources/js/proxy.js"></script>
+<script type="text/javascript" src="{{www}}/main/glossary/resources/js/ui.js"></script>
+<script type="text/javascript" src="{{www}}/main/glossary/resources/js/jquery.dataTables.js"></script>
+
+<script type="text/javascript">
+    
+$(function() {
+
+    ui.proxy = glossary;
+
+    window.context = {};
+    
+    context.sec_token = '{{sec_token}}';
+    context.c_id = '{{c_id}}';
+    context.session_id = '{{session_id}}';
+    context.www = '{{www}}';
+    context.ajax = '{{www}}/main/inc/ajax/glossary.ajax.php';
+    
+    if(typeof(lang) == "undefined")
+    {
+        window.lang = {};
+    }
+    
+    lang.ConfirmYourChoice = "{{'ConfirmYourChoice'|get_lang}}";  
+    
+});
+
+</script>

+ 35 - 0
main/template/default/glossary/list.tpl

@@ -0,0 +1,35 @@
+
+<ul id="entries" style="list-style: none; margin-left:0;" class="glossary entries" data-c_id="{{c_id}}" data-session_id="{{session_id}}" >
+{% for item in items %}
+    <li id="glossary_{{item.id}}" class="glossary term" data-id="{{item.id}}" data-c_id="{{item.c_id}}" data-type="glossary">
+        <div class="title sectiontitle">
+            {% if is_allowed_to_edit %}
+                <div style="float:right;">
+                {% if session_id == item.session_id %}
+                    <a href="{{root}}&amp;action=edit&amp;id={{item.id}}" 
+                       class="btn edit"
+                       title="{{'Edit'|get_lang}}">
+                    </a>                    
+                    <a href="{{root}}&amp;action=delete&amp;id={{item.id}}" 
+                       onclick="ui.remove('glossary_{{item.id}}', this); return false;"
+                       class="btn delete"
+                       title="{{'Delete'|get_lang}}">
+                    </a>
+                
+                {% else %}
+                    <img title="{{'EditionNotAvailableFromSession'|get_lang}}" 
+                         alt="{{'EditionNotAvailableFromSession'|get_lang}}" 
+                         src="{{'edit_na.png'|icon(22)}}" 
+                         style="vertical-align:middle;">
+                {% endif %}
+                </div>
+            {% endif %}
+            
+            {{item.name}}
+        </div>
+        <div class="sectioncomment">
+            {{item.description}}
+        </div>
+    </li>
+{% endfor %}
+</ul>

+ 72 - 0
main/template/default/glossary/table.tpl

@@ -0,0 +1,72 @@
+<script type="text/javascript">
+    
+$(document).ready(function() {
+    $('#entries').dataTable( {
+        "oLanguage": {
+            "sLengthMenu": "_MENU_ " + "{{'DataTableLengthMenu'|get_lang}}",
+            "sZeroRecords": "{{'DataTableZeroRecords'|get_lang}}",
+            "sInfo": "{{'DataTableInfo'|get_lang}}",
+            "sInfoEmpty": "{{'DataTableInfoEmpty'|get_lang}}",
+            "sInfoFiltered": "{{'DataTableInfoFiltered'|get_lang}}",
+            "sSearch": "{{'DataTableSearch'|get_lang}}",
+            "oPaginate": {
+                "sPrevious": "",
+                "sNext": ""
+            }
+        }
+     });
+} );
+
+</script>
+
+<table id="entries" class="data_table glossary entries" data-c_id="{{c_id}}" data-session_id="{{session_id}}" >
+    <thead>
+        <tr>
+            <th class="sorting">
+                {{'TermName'|get_lang}}
+            </th>
+            <th class="sorting">                
+                {{'TermDefinition'|get_lang}}
+            </th>
+            {% if is_allowed_to_edit %}
+                <th>
+                    {{'Actions'|get_lang}}
+                </th>
+            {% endif %}
+        </tr>
+    </thead>
+    <tbody>
+        {% for item in items %}
+            <tr id="glossary_{{item.id}}" class="glossary term" data-id="{{item.id}}" data-c_id="{{item.c_id}}" data-type="glossary">
+                <td class="title">
+                    {{item.name}}
+                </td>
+                <td class="">
+                    {{item.description}}
+                </td>
+                {% if is_allowed_to_edit %}
+                    <td class="td_actions">
+                        {% if session_id == item.session_id %}
+                            <a  href="{{root}}&amp;action=edit&amp;id={{item.id}}" 
+                                class="btn edit"
+                                title="{{'Edit'|get_lang}}">
+                            </a>                    
+                            <a  href="{{root}}&amp;action=delete&amp;id={{item.id}}" 
+                                onclick="ui.remove('glossary_{{item.id}}', this); return false;"
+                                class="btn delete"
+                                title="{{'Delete'|get_lang}}">
+                            </a>
+                        {% else %}
+                            <img    title="{{'EditionNotAvailableFromSession'|get_lang}}" 
+                                    alt="{{'EditionNotAvailableFromSession'|get_lang}}" 
+                                    src="{{'edit_na.png'|icon(22)}}" 
+                                    style="vertical-align:middle;">
+                        {% endif %}
+                    </td>
+                {% endif %}
+            </tr>
+        {% endfor %}
+    </tbody>
+</table>
+<div style="clear:both"></div>
+

+ 8 - 0
main/template/default/glossary/upload.tpl

@@ -0,0 +1,8 @@
+{% include 'default/glossary/header.tpl' %}
+
+
+<div class="actions" >
+    <a href = "{{root}}&amp;action=index" class = "course_description btn back"></a>
+</div>
+
+{{form.return_form()}}

+ 12 - 0
main/template/default/link/edit_category.tpl

@@ -0,0 +1,12 @@
+
+{{javascript}}
+
+<div class = "actions" >
+    <a href = "{{root}}&amp;action=listing" class = "announce btn back"></a>
+</div>
+
+{% for message in messages %}
+    {{ message }}
+{% endfor %}
+
+{{form.return_form()}}

+ 12 - 0
main/template/default/link/edit_link.tpl

@@ -0,0 +1,12 @@
+
+{{javascript}}
+
+<div class = "actions" >
+    <a href = "{{root}}&amp;action=listing" class = "announce btn back"></a>
+</div>
+
+{% for message in messages %}
+    {{ message }}
+{% endfor %}
+
+{{form.return_form()}}

+ 309 - 0
main/template/default/link/index.tpl

@@ -0,0 +1,309 @@
+
+{{javascript}}
+
+<script type="text/javascript">
+    
+    {% if is_allowed_to_edit %}
+        var sec_token = '{{sec_token}}';
+    {% endif %}
+    
+$(function() {
+	$('.collapsible .head').click(function(e) {
+        $(this).toggleClass('collapsed');
+        $(this).next().toggle();
+		return true;
+	});
+    
+    {% if is_allowed_to_edit %}
+        $(".categories.sortable" ).sortable({
+            axis: 'y',
+            handle: '.handle',
+            //placeholder: 'ui-state-highlight',
+            update: function(event, ui) { 
+                var c_id = 0;
+                var ids = [];
+                var items;
+                items = $(this).children('li');
+                items.each(function(index, li){
+                    li = $(li);
+                    var id;
+                    id = li.attr('data-id'); 
+                    c_id = li.attr('data-c_id'); 
+                    ids.push(id);
+                });
+
+                LinkCategory.sort(c_id, ids, message.update);
+            }
+        });
+        $(".categories.sortable" ).disableSelection();
+
+        $(".links.sortable" ).sortable({
+            axis: 'y',
+            placeholder: 'ui-state-highlight',
+            update: function(event, ui) { 
+                var c_id = 0;
+                var ids = [];
+                var items;
+                items = $(this).children('li');
+                items.each(function(index, li){
+                    li = $(li);
+                    var id;
+                    id = li.attr('data-id'); 
+                    c_id = li.attr('data-c_id'); 
+                    ids.push(id);
+                });
+
+                Link.sort(c_id, ids, message.update);
+            }
+        });
+        $(".links.sortable" ).disableSelection();
+    
+    {% endif %}
+    
+});
+ 
+ function expand_all(){
+    $('.collapsible .head').removeClass('collapsed').next().show();
+ }
+ 
+ function collapse_all(){     
+    $('.collapsible .head').addClass('collapsed').next().hide();
+ }
+ 
+ function delete_category(name){   
+    if(!confirm("{{'ConfirmYourChoice'|get_lang}}")){
+        return false;
+    } 
+
+    var item = $('#'+name);
+    var id = item.attr('data-id'); 
+    var c_id = item.attr('data-c_id'); 
+
+    var f = function(data){
+        if(data.success){
+            item.remove();
+        }
+        message.update(data);
+    };
+    LinkCategory.del(c_id, id, f);
+ }
+ 
+ function delete_all(){
+    if(!confirm("{{'ConfirmYourChoice'|get_lang}}")){
+        return false;
+    } 
+    
+    var f = function(data){
+        if(data.success){
+            var item = $('.data');
+            item.remove();
+        }
+        message.update(data);
+    };
+    Link.delete_by_course({{c_id}}, {{session_id}}, f);
+    
+ }
+ 
+ function delete_link(name, btn){   
+    if(!confirm("{{'ConfirmYourChoice'|get_lang}}")){
+        return false;
+    } 
+
+    var item = $('#'+name);
+    var id = item.attr('data-id'); 
+    var c_id = item.attr('data-c_id'); 
+
+    var f = function(data){
+        if(data.success){
+            item.remove();
+        }else{            
+            $(btn).removeClass("loading");
+        }
+        message.update(data);
+    };
+    $(btn).addClass("loading");
+    Link.del(c_id, id, f);
+ }
+ 
+function switch_li_visibility(name, btn)
+{
+    var li = $('#'+name);
+    var id = li.attr('data-id'); 
+    var c_id = li.attr('data-c_id'); 
+
+    var is_visible = !li.hasClass('invisible')
+
+    var f = function(data){
+        if(data.success){
+            var btn =  $('.btn.visibility', li);
+            if(is_visible){
+                btn.addClass('show');
+                btn.removeClass('hide');
+                li.addClass('invisible');
+                li.removeClass('visible');
+            }else{
+                btn.removeClass('show');
+                btn.addClass('hide');
+                li.removeClass('invisible');
+                li.addClass('visible');
+            }
+        }
+        message.update(data);
+        $(btn).removeClass("loading");
+    };
+    if(is_visible){
+        Link.hide(c_id, id, f);
+    }else{
+        Link.show(c_id, id, f);
+    }
+    $(btn).addClass("loading");
+}
+
+function validate_link(name, btn){
+    var li = $('#'+name);
+    var id = li.attr('data-id'); 
+    var c_id = li.attr('data-c_id'); 
+    
+    var f = function(data){
+        if(data.success){
+            li.addClass('valid');
+            li.removeClass('invalid');
+        }else{
+            li.addClass('invalid');
+            li.removeClass('valid');
+        }
+        message.update(data);
+        $(btn).removeClass("loading");
+    };
+    $(btn).addClass("loading");
+    Link.validate(c_id, id, f);
+}
+
+</script>
+
+<div id="messages">
+{% for message in messages %}
+    {{ message }}
+{% endfor %}
+</div>
+
+<div class="actions" >
+    {% if is_allowed_to_edit %}
+        <a href="{{root}}&amp;action=add_category" class="btn new_folder" title="{{'AddCategory'|get_lang}}"></a>
+        <a href="{{root}}&amp;action=add_link" class="btn new_link" title="{{'AddLink'|get_lang}}"></a>
+        <a href="javascript:void(0)" onclick="delete_all();return false;" class="btn delete_all" title="{{'DeleteAll'|get_lang}}"></a>
+        <a href="{{root}}&amp;action=import_csv" class="btn import_csv" title="{{'ImportCSV'|get_lang}}"></a>
+    {% endif %}
+    <a href="{{root}}&amp;action=export_csv" class="btn export_csv" title="{{'ExportAsCSV'|get_lang}}"></a>
+    <a href="javascript:void(0)" onclick="expand_all();return false;" class="btn expand" title="{{'showall'|get_lang}}"></a>
+    <a href="javascript:void(0)" onclick="collapse_all();return false;" class="btn collapse" title="{{'shownone'|get_lang}}"></a>
+</div>
+
+<div class="data">
+    <ul style="list-style: none; margin-left:0;" class="links sortable">
+        {% for link in links %}
+            {% set link_class %}
+                {% if loop.first %}first{% endif %}
+                {% if loop.last %}last{% endif %}
+                {% if loop.index is odd %}odd{% else %}even{% endif %}
+                {% if link.is_visible() %}visible{% else %}invisible{% endif %}
+            {% endset %}
+
+            <li id="link_{{link.id}}" class="link {{link_class}}" data-id="{{link.id}}" data-c_id="{{link.c_id}}" data-type="link" >
+                <a class="icon" target="{{link.target}}" href="{{root}}&amp;action=go&amp;id={{link.id}}&amp;c_id={{link.c_id}}">
+                    <img alt="{{'Links'|get_lang}}" src="../../main/img/link.gif" />        
+                </a>
+                <a class="title" target="{{link.target}}" href="{{root}}&amp;action=go&amp;id={{link.id}}&amp;c_id={{link.c_id}}">
+                    {%if link.title %}{{link.title}}{% else %}{{link.url}}{%endif%}                
+                </a>
+                {% if link.session_id %}
+                    {{session_image}}
+                {% endif %}
+                <div class="status" style="display:inline-block;">&nbsp;</div>
+                {% if is_allowed_to_edit %}
+                    <div style="float:right;">
+                        <a href="javascript:void(0)" onclick="validate_link('link_{{link.id}}', this);return false;" 
+                        title="{{'CheckURL'|get_lang}}" 
+                        class="btn validate_link"></a>   
+                        <a href="{{root}}&amp;action=edit_link&amp;id={{link.id}}&amp;c_id={{link.c_id}}" 
+                        title="{{'Edit'|get_lang}}" 
+                        class="btn edit"></a>   
+                        <a href="javascript:void(0)" onclick="switch_li_visibility('link_{{link.id}}', this);return false;" 
+                        class="btn visibility {%if link.visibility == 1%}hide{%else%}show{%endif%}"></a>
+                        <a href="javascript:void(0)" onclick="delete_link('link_{{link.id}}', this);return false;" title="{{'Delete'|get_lang}}" class="btn delete"></a>
+                    </div>
+                {% endif %}
+                <div class="description">{{link.description}}</div>
+            </li>
+        {% endfor%}
+    </ul>
+
+    <ul id="link_categories" class="categories sortable" style="list-style: none; margin-left:0;">
+    {% for category in categories %}
+        <li id="category_{{category.id}}" class="link_category collapsible" data-id="{{category.id}}" data-c_id="{{category.c_id}}" data-type="category" >
+            <div class="head handle collapsed">    
+                {% if is_allowed_to_edit %}
+                    <div style="float:right;">
+                        <a href="{{root}}&amp;action=edit_category&amp;id={{category.id}}&amp;c_id={{category.c_id}}" 
+                        onclick="event.stopPropagation();" 
+                        title="{{'Edit'|get_lang}}"
+                        class="btn edit"></a>            
+                        <a href="javascript:void(0)" 
+                        onclick="delete_category('category_{{category.id}}');event.stopPropagation();return false;" 
+                            title="{{'Delete'|get_lang}}"
+                            class="btn delete"></a>
+                    </div>
+                {% endif %}
+                <h3>
+                    <a href="{{root}}&amp;action=view&amp;id={{category.id}}&amp;c_id={{category.c_id}}">{{category.category_title|escape}}</a>
+                </h3>
+                {{category.description}}
+            </div>
+            <div class="body" style="display:none;"> 
+                <ul style="list-style: none; margin-left:0;" class="links sortable">
+                    {% for link in category.links %}
+                    {% set link_class %}
+                        {% if loop.first %}first{% endif %}
+                        {% if loop.last %}last{% endif %}
+                        {% if loop.index is odd %}odd{% else %}even{% endif %}
+                        {% if link.is_visible() %}visible{% else %}invisible{% endif %}
+                    {% endset %}
+
+                        <li id="link_{{link.id}}" class="link {{link_class}}" data-id="{{link.id}}" data-c_id="{{link.c_id}}" data-type="link" >
+                            <a class="icon" target="{{link.target}}" href="{{root}}&amp;action=go&amp;id={{link.id}}&amp;c_id={{link.c_id}}">
+                                <img alt="{{'Links'|get_lang}}" src="../../main/img/link.gif" />        
+                            </a>
+                            <a class ="title" target="{{link.target}}" href="{{root}}&amp;action=go&amp;id={{link.id}}&amp;c_id={{link.c_id}}">
+                                {%if link.title %}{{link.title}}{% else %}{{link.url}}{%endif%}                
+                            </a>
+                            {% if link.session_id %}
+                                {{session_image}}
+                            {% endif %}
+                            <div class="status" style="display:inline-block;">&nbsp;</div>
+                            {% if is_allowed_to_edit %}
+                                <div style="float:right;">
+                                    <a href="javascript:void(0)" onclick="validate_link('link_{{link.id}}', this);return false;" 
+                                    title="{{'CheckURL'|get_lang}}" 
+                                    class="btn validate_link"></a>   
+                                    <a href="{{root}}&amp;action=edit_link&amp;id={{link.id}}&amp;c_id={{link.c_id}}" 
+                                    onclick="" 
+                                    title="{{'Edit'|get_lang}}"
+                                    class="btn edit"></a>   
+                                    <a href="javascript:void(0)" 
+                                    onclick="switch_li_visibility('link_{{link.id}}', this);return false;" 
+                                    class="btn visibility {%if link.visibility == 1%}hide{%else%}show{%endif%}"></a>
+                                    <a href="javascript:void(0)" 
+                                    onclick="delete_link('link_{{link.id}}', this);return false;" 
+                                    title="{{'Delete'|get_lang}}"
+                                    class="btn delete"></a>
+                                </div>
+                            {% endif %}
+                        </li>
+                    {% endfor%}
+                </ul>
+            </div>
+            <div class="details "></div>
+        </li>
+    {% endfor%}
+    </ul>
+</div>