Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'address-test'

  • Loading branch information...
commit 0b56b71e9641a3e79ec7fec5a3e05858719270f2 2 parents e42562b + 9cc37d6
@koopa authored
View
10 courses/course-template.phps
@@ -6,22 +6,22 @@ require("courseheader.php");
<div id="coursenavigation">
<ol class="tree">
- <li class="file"><a href="#" onClick="selectPart('default')">Introduction</a></li>
+ <li class="file"><a data-contentid="default" href="#/course/General/Introduction">Introduction</a></li>
<li>
<label for="theory">Theory</label><input type="checkbox" checked id="theory" />
<ol>
- <li class="file"><a href="#" onClick="selectPart('chapter1')">Chapter 1</a></li>
+ <li class="file"><a data-contentid="chapter1" href="#/course/General/Chapter+1">Chapter 1</a></li>
*** add more chapter links here ***
</ol>
</li>
<li>
<label for="exercises">Exercises</label> <input type="checkbox" checked id="exercises" />
<ol>
- <li class="file"><a href="#" onClick="selectPart('exercise1')">Exercise 1</a></li>
+ <li class="file"><a data-contentid="exercise1" href="#/course/General/Exercise+1">Exercise 1</a></li>
*** add more exercise links here ***
</ol>
</li>
- <li class="file"><a href="#" onClick="selectPart('examn')">Exam</a></li>
+ <li class="file"><a data-contentid="examn" href="#/course/General/Exam">Exam</a></li>
</ol>
</div>
@@ -29,7 +29,7 @@ require("courseheader.php");
<div id="default">
Default
- <p class="center"><a href="#" onClick="selectPart('chapter1')">>> Next Chapter >></a></p>
+ <p class="center"><a href="#/course/General/[nextChapterName]">>> Next Chapter >></a></p>
</div>
<div id="chapter1">
View
66 courses/course.php
@@ -27,20 +27,62 @@
// Description: Load the course file specified by the GET variable 'id'
//
- $courseid = isset($_GET['id']) ? $_GET['id'] : 0;
- $errorstring = "<p class=\"center\"><img alt=\"Y U NO GIVE ID\" src=\"images/yuno.png\" /><br /><br />No active course, select a valid course from the overview!</p>";
- $filename = "courses/course".$courseid.".php";
+ if(isset($_GET['id'])){
+
+ }
+
+ $errorstring = "<p class=\"center\"><img alt=\"Y U NO GIVE ID\" src=\"images/yuno.png\" /><br /><br />No active course, select a valid course from the navigation on the left!
+ </p>";
+
$mincourseid = 0;
$maxcourseid = 100000;
- if(!isset($courseid)||!is_numeric($courseid)||$courseid<$mincourseid||$courseid>$maxcourseid)
- echo $errorstring;
- else
- {
- if(is_readable($filename))
- include($filename);
- else
- echo $errorstring;
- }
+ echo '<div id="coursenavigation">
+ <ol class="tree">';
+
+ foreach($categories as $id => $name){
+ echo '<li><a href="/course/'.urlencode($name).'"><label for="'.urlencode($name).'">
+ '.$name.'</label></a>
+ <input type="checkbox" id="'.urlencode($name).'" />';
+ if(count($tree[$id]) > 0){
+ echo '<ol>';
+ }
+ foreach($tree[$id] as $course){
+ echo '<li><a href="/course/'.urlencode($name)
+ .'/'.urlencode($course['title']).'"><label for="'.urlencode($course['title']).'">
+ '.$course['title'].'</label></a>
+ <input type="checkbox" id="'.urlencode($course['title']).'" />
+ <ol>';
+ $filename = "courses/course".$course['id'].".php";
+ if(is_readable($filename)){
+ $courseData = include($filename);
+ }
+ if($courseData['nav']) foreach($courseData['nav'] as $chapterType => $chapters){
+ if($chapters) foreach($chapters as $contentId => $chapterName){
+ //$chapterType class to style icons
+ echo '<li class="file '.$chapterType.'"><a
+ data-contentid="'.$contentId.'"
+ data-chapterid="'.$chapterName.'_'.$course['id'].'"
+ href="/course/'.urlencode($name)
+ .'/'.urlencode($course['title'])
+ .'/'.urlencode($chapterName).'">'.$chapterName.'
+ </a>
+ <script type="text/html" id="'.$chapterName.'_'.$course['id'].'">
+ '.$courseData['content'][$chapterType][$contentId].'
+ </script>
+ </li>';
+ }
+ }
+ echo '</ol></li>';
+ }
+ if(count($tree[$id]) > 0){
+ echo '</ol>';
+ }
+ echo '</li>';
+ }
+ echo '</ol><!-- end ol class tree -->
+ </div><!-- end div id="coursenavigation" -->';
+
?>
+ <div id="coursecontent"><?php echo $errorstring; ?></div>
</div>
View
12 courses/courseheader.php
@@ -20,16 +20,13 @@
// //
///////////////////////////////////////////////////////////////////////////////////
-require("../getsmfuser.php");
+require_once("../getsmfuser.php");
$notloggedintext = "<p class=\"warning\">Warning: You aren't logged in to the Hackits forum, submitting this exam will only count if you are logged in!</p>";
+$courseid = isset($_GET['id']) ? $_GET['id'] : 0;
?>
<script type="text/javascript">
-
- // shows the specified div and hides all others
- function selectPart(part){ $("#"+part).show().siblings().hide(); }
-
// when the examn form is submitted, show the results in a dialog window
$(document).ready(function(){
$("#examnform").submit( function () {
@@ -37,8 +34,7 @@ function selectPart(part){ $("#"+part).show().siblings().hide(); }
'examnhandler.php?id=<? echo $courseid; ?>',
$(this).serialize(),
function(data){
- $("#examnresult").empty().append( data );
- $("#examnresult").dialog("open");
+ $("#examnresult").empty().append(data).dialog("open");
}
);
return false;
@@ -51,4 +47,4 @@ function(data){
</script>
-<div id="examnresult" title="Exam Results"></div>
+<div id="examnresult" title="Exam Results"></div>
View
187 courses/courses/course1.php
@@ -1,93 +1,96 @@
<?php
- require("courseheader.php");
-?>
-<div id="coursenavigation">
- <ol class="tree">
- <li class="file"><a href="#" onClick="selectPart('default')">Introduction</a></li>
- <li>
- <label for="theory">Theory</label><input type="checkbox" checked id="theory" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('chapter1')">Hackits Courses</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter2')">More about courses</a></li>
- </ol>
- </li>
- <li>
- <label for="exercises">Exercises</label> <input type="checkbox" checked id="exercises" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('exercise1')">Exercise 1</a></li>
- </ol>
- </li>
- <li class="file"><a href="#" onClick="selectPart('examn')">Exam</a></li>
- </ol>
-</div>
-<div id="coursecontent">
- <div id="default">
- <h1>Welcome</h1>
- <p>Thanks for checking out the Hackits Courses! These courses will help you to learn a lot about a wide variety of topics related to hacking, computer security, and a lot more. They will help you tackle the Hackits challenges and lift your general skill as a hacker to a higher level.</p>
- <p>Click on the skull to continue to the first chapter of this introduction course!</p>
- <p class="center"><a href="#" onClick="selectPart('chapter1')"><img alt="skull" src="images/course1skull.jpg" /></a></p>
- </div>
- <div id="chapter1">
- <h1>Hackits Courses</h1>
- <h2>Course structure</h2>
- <p>All courses consist of one or more theory chapters, usually followed by some exercises that allow you to test your understanding of the theory. These exercises are always optional. Finally there is an exam for each course, which will show that you master the course contents and will earn you Hackits points! There is no time limit or penalty for reading a course or doing an exam, so no need to stress.</p>
- <p>At the left of the screen you see how the course is structured, and you can select a chapter/exercise to display and an exam link at the bottom of the list. Usually you will find links to the next part at the bottom of a page as well. At the top of the screen you see some tabs, currently you are in the 'Current Course' tab of the Courses system. At any time you can click on another tab to check out its contents, as long as you dont select a different course from the overview or refresh the page, your 'Current Course' tab will stay the same as when you left it.</p>
- <h2>Logging in</h2>
- <p>We advise that you first log in to the <a href="http://www.hackits.be/forum/" target="new">Hackits forum</a> before using the Courses system, because it will allow you to view which courses you completed in the overview, and it will allow the courses system to award you personally with points when completing an exam. You can see if you are logged in by checking out the top bar of the Courses page, which should say 'Logged in as: ' followed by your forum account name. If you submit an exam without being logged in, a warning will be displayed telling you to log in to the forum in a different browser tab or window, no need to fill in the exam again.</p>
- <h2>Difficulty</h2>
- <p>Each course has a difficulty level assigned to it by the Hackits team, the higher the difficulty the higher the score thats rewarded by completing the exam. Also at the start of a course there might be links to other courses as prerequisites listed, we advise that you complete those courses so you will have a much smoother learning curve. </p>
- <p>If you think you already know the contents of a course and want to skip right to the exam, feel free to do so, but keep in mind that there might be details in the theory that you didn't know about, or can use some refreshing in your brain. </p>
- <h2>Disclaimer</h2>
- <p>All information given to you in these courses is to be used for educational purposes only, and the hacking/cracking techniques described should be performed on your own systems, or on systems where you have explicit permission from its owner to use them for these purposes. Not following these rules can result in very large fines or even jailtime in some countries.</p>
- <p class="center"><a href="#" onClick="selectPart('chapter2')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter2">
- <h1>More about courses</h1>
- <h2>Getting help</h2>
- <p>The best place to get help on a course is the <a href="http://www.hackits.be/forum/index.php?board=12.0">Courses Help section</a> in the forum. In here, other hackits members and staff can help you out and think along. The questions and remarks you give us, can help us make the courses better for everybody!</p>
- <p>If you need realtime communication then IRC might be a good choice instead, but keep in mind that the author of the course might not be available or on IRC at all.</p>
- <h2>Feedback</h2>
- <p>If something about the Course system is not working like it should, or isn't being displayed properly in your browser, or the actual content of the course is outdated or false, there are a few ways to get in contact with the Hackits team.</p>
- <p>First of all, security-related issues should always be communicated privately to one of the Hackits <a href="http://www.hackits.be/forum/index.php?action=mlist;sort=id_group;start=0">Administrators</a>, either trough a private message on the forum, or a query on IRC.</p>
- <p>Technical issues or styling (HTML/CSS) issues are probably best discussed with the author of the Courses system, Sling. He is usually available on IRC but you can of course <a href="http://www.hackits.be/forum/index.php?action=pm;sa=send;u=2">PM</a> him on the Forum as well.</p>
- <p>All other feedback can be given publically in the <a href="http://www.hackits.be/forum/index.php?board=11.0">right section in the Forum</a>.</p>
- <h2>Submitting your own course</h2>
- <p>If you want to share your knowledge about a certain topic that hasn't already been covered in a course, feel free to submit your own tutorial on it to <a href="http://www.hackits.be/forum/index.php?topic=11.0">the forum</a>. Staff will check it out and if it meets the quality standards for a course, we will try to get in contact with you to create a new course! If you aren't sure if the topic has been covered or if your idea is suitable for a course, just join us on IRC and we can have a chat!</p>
- <h2>Final words</h2>
- <p>This is all we have to tell you about the courses system itself, head over to the <a href="#" onClick="selectPart('exercise1')">exercise</a> to see how an example exercise looks.</p>
- <p>Welcome again and have a great learning experience!</p>
- </div>
- <div id="exercise1">
- <h3>Exercise 1:</h3>
- <p>Exercises are small tests you can do yourself to see if you understood the contents of the course. Each exercise has an answer that can be revealed by clicking on the 'Reveal Answer' button.</p>
- <p>Now it would be a bit silly to have an exercise for this course, but we can at least show you how an exercise would look like. So here it goes: the exercise for this course is to reveal the answer to this exercise!</p>
- <div class="revealbutton" onClick="$('#answer1').show(); $('.revealbutton').hide(); ">Reveal Answer</div>
- <div class="answer" id="answer1">
- <p>Well done, you revealed the answer!</p>
- <p>This is the only exercise for this course, think you are ready for the exam? <a href="#" onClick="selectPart('examn')">Click here</a> to check it out!</p>
- </div>
- </div>
- <div id="examn">
- <h2>Exam Time!</h2><br />
- <? if(!$loggedin) echo $notloggedintext; ?>
- <form id="examnform" name="examnform" method="post" action="">
- <div class="question">
- <h3>Question 1</h3><br />
- <p>Why should I do any courses?</p>
- <input type="radio" value="A" id="radio1" name="1" /><label for="radio1">For fun and for learning</label><br />
- <input type="radio" value="B" id="radio2" name="1" /><label for="radio2">They help me with challenges and give Hackits points</label><br />
- <input type="radio" value="C" id="radio3" name="1" /><label for="radio3">All of the above!</label><br />
- </div>
- <div class="question">
- <h3>Question 2</h3><br />
- <p>What should I do when I find a security vulnerability that allows me to complete any course?</p>
- <input type="radio" value="A" id="radio1" name="2" /><label for="radio1">Dont mention it, I could get the highest score in the ranking!</label><br />
- <input type="radio" value="B" id="radio2" name="2" /><label for="radio2">Make a new topic on the forum to warn everybody</label><br />
- <input type="radio" value="C" id="radio3" name="2" /><label for="radio3">Send a private message to one of the Administrators</label><br />
- </div>
- <div id="examnsubmit">
- <button>Submit</button>
- </div>
- </form>
- </div>
-</div>
+$msg = !$loggedin ? $notloggedintext : '';
+return array(
+ 'nav' => array(
+ 'default' => array(
+ 'chapter1' => 'Hackits Courses',
+ 'chapter2' => 'More about courses',
+ ),
+ 'exercises' => array(
+ 'exercise1' => 'Exercise 1',
+ ),
+ 'exam' => array(
+ 'exam1' => 'Exam',
+ )
+ ),
+ 'content' => array(
+ 'default' => array(
+ 'index' => <<<°
+ <h1>Welcome</h1>
+ <p>Thanks for checking out the Hackits Courses! These courses will help you to learn a lot about a wide variety of topics related to hacking, computer security, and a lot more. They will help you tackle the Hackits challenges and lift your general skill as a hacker to a higher level.</p>
+ <p>Click on the skull to continue to the first chapter of this introduction course!</p>
+ <p class="center"><a href="#"><img alt="skull" src="images/course1skull.jpg" /></a></p>
+°
+ ,
+ 'chapter1' => <<<°
+ <h1>Hackits Courses</h1>
+ <h2>Course structure</h2>
+ <p>All courses consist of one or more theory chapters, usually followed by some exercises that allow you to test your understanding of the theory. These exercises are always optional. Finally there is an exam for each course, which will show that you master the course contents and will earn you Hackits points! There is no time limit or penalty for reading a course or doing an exam, so no need to stress.</p>
+ <p>At the left of the screen you see how the course is structured, and you can select a chapter/exercise to display and an exam link at the bottom of the list. Usually you will find links to the next part at the bottom of a page as well. At the top of the screen you see some tabs, currently you are in the 'Current Course' tab of the Courses system. At any time you can click on another tab to check out its contents, as long as you dont select a different course from the overview or refresh the page, your 'Current Course' tab will stay the same as when you left it.</p>
+ <h2>Logging in</h2>
+ <p>We advise that you first log in to the <a href="http://www.hackits.be/forum/" target="new">Hackits forum</a> before using the Courses system, because it will allow you to view which courses you completed in the overview, and it will allow the courses system to award you personally with points when completing an exam. You can see if you are logged in by checking out the top bar of the Courses page, which should say 'Logged in as: ' followed by your forum account name. If you submit an exam without being logged in, a warning will be displayed telling you to log in to the forum in a different browser tab or window, no need to fill in the exam again.</p>
+ <h2>Difficulty</h2>
+ <p>Each course has a difficulty level assigned to it by the Hackits team, the higher the difficulty the higher the score thats rewarded by completing the exam. Also at the start of a course there might be links to other courses as prerequisites listed, we advise that you complete those courses so you will have a much smoother learning curve. </p>
+ <p>If you think you already know the contents of a course and want to skip right to the exam, feel free to do so, but keep in mind that there might be details in the theory that you didn't know about, or can use some refreshing in your brain. </p>
+ <h2>Disclaimer</h2>
+ <p>All information given to you in these courses is to be used for educational purposes only, and the hacking/cracking techniques described should be performed on your own systems, or on systems where you have explicit permission from its owner to use them for these purposes. Not following these rules can result in very large fines or even jailtime in some countries.</p>
+ <p class="center"><a href="#/course/General/Internet+Relay+Chat+%28IRC%29">>> Next Chapter >></a></p>
+°
+ ,
+ 'chapter2' => <<<°
+ <h1>More about courses</h1>
+ <h2>Getting help</h2>
+ <p>The best place to get help on a course is the <a href="http://www.hackits.be/forum/index.php?board=12.0">Courses Help section</a> in the forum. In here, other hackits members and staff can help you out and think along. The questions and remarks you give us, can help us make the courses better for everybody!</p>
+ <p>If you need realtime communication then IRC might be a good choice instead, but keep in mind that the author of the course might not be available or on IRC at all.</p>
+ <h2>Feedback</h2>
+ <p>If something about the Course system is not working like it should, or isn't being displayed properly in your browser, or the actual content of the course is outdated or false, there are a few ways to get in contact with the Hackits team.</p>
+ <p>First of all, security-related issues should always be communicated privately to one of the Hackits <a href="http://www.hackits.be/forum/index.php?action=mlist;sort=id_group;start=0">Administrators</a>, either trough a private message on the forum, or a query on IRC.</p>
+ <p>Technical issues or styling (HTML/CSS) issues are probably best discussed with the author of the Courses system, Sling. He is usually available on IRC but you can of course <a href="http://www.hackits.be/forum/index.php?action=pm;sa=send;u=2">PM</a> him on the Forum as well.</p>
+ <p>All other feedback can be given publically in the <a href="http://www.hackits.be/forum/index.php?board=11.0">right section in the Forum</a>.</p>
+ <h2>Submitting your own course</h2>
+ <p>If you want to share your knowledge about a certain topic that hasn't already been covered in a course, feel free to submit your own tutorial on it to <a href="http://www.hackits.be/forum/index.php?topic=11.0">the forum</a>. Staff will check it out and if it meets the quality standards for a course, we will try to get in contact with you to create a new course! If you aren't sure if the topic has been covered or if your idea is suitable for a course, just join us on IRC and we can have a chat!</p>
+ <h2>Final words</h2>
+ <p>This is all we have to tell you about the courses system itself, head over to the <a href="#">exercise</a> to see how an example exercise looks.</p>
+ <p>Welcome again and have a great learning experience!</p>
+°
+ ),
+ 'exercises' => array(
+ 'exercise1' => <<<°
+ <h3>Exercise 1:</h3>
+ <p>Exercises are small tests you can do yourself to see if you understood the contents of the course. Each exercise has an answer that can be revealed by clicking on the 'Reveal Answer' button.</p>
+ <p>Now it would be a bit silly to have an exercise for this course, but we can at least show you how an exercise would look like. So here it goes: the exercise for this course is to reveal the answer to this exercise!</p>
+ <div class="revealbutton" onClick="$('#answer1').show(); $('.revealbutton').hide(); ">Reveal Answer</div>
+ <div class="answer" id="answer1">
+ <p>Well done, you revealed the answer!</p>
+ <p>This is the only exercise for this course, think you are ready for the exam? <a href="#/course/General/Intro+to+Hackits+Courses/Exam">Click here</a> to check it out!</p>
+ </div>
+°
+ ,
+ ),
+ 'exam' => array(
+ 'exam1' => <<<°
+ <h2>Exam Time!</h2><br />
+ $msg
+ <form id="examnform" name="examnform" method="post" action="">
+ <div class="question">
+ <h3>Question 1</h3><br />
+ <p>Why should I do any courses?</p>
+ <input type="radio" value="A" id="radio11" name="1" /><label for="radio1">For fun and for learning</label><br />
+ <input type="radio" value="B" id="radio12" name="1" /><label for="radio2">They help me with challenges and give Hackits points</label><br />
+ <input type="radio" value="C" id="radio13" name="1" /><label for="radio3">All of the above!</label><br />
+ </div>
+ <div class="question">
+ <h3>Question 2</h3><br />
+ <p>What should I do when I find a security vulnerability that allows me to complete any course?</p>
+ <input type="radio" value="A" id="radio21" name="2" /><label for="radio1">Dont mention it, I could get the highest score in the ranking!</label><br />
+ <input type="radio" value="B" id="radio22" name="2" /><label for="radio2">Make a new topic on the forum to warn everybody</label><br />
+ <input type="radio" value="C" id="radio23" name="2" /><label for="radio3">Send a private message to one of the Administrators</label><br />
+ </div>
+ <div id="examnsubmit">
+ <button>Submit</button>
+ </div>
+ </form>
+°
+ ),
+ )
+);
View
330 courses/courses/course2.php
@@ -1,166 +1,170 @@
<?php
- require("courseheader.php");
-?>
-<div id="coursenavigation">
- <ol class="tree">
- <li class="file"><a href="#" onClick="selectPart('default')">Introduction</a></li>
- <li>
- <label for="theory">Theory</label><input type="checkbox" checked id="theory" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('chapter1')">DHCP</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter2')">Firewalling</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter3')">DNS</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter4')">NTP</a></li>
- </ol>
- </li>
- <li>
- <label for="exercises">Exercises</label> <input type="checkbox" checked id="exercises" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('exercise1')">Exercise 1</a></li>
- </ol>
- </li>
- <li class="file"><a href="#" onClick="selectPart('examn')">Exam</a></li>
- </ol>
-</div>
-<div id="coursecontent">
- <div id="default">
- <h1>Welcome to Practical Networks!</h1>
- <p>This course's objective is to help you managing your home network with the standard unix tools.</p>
- <p>While I will skip the technical details and strip these guides to the essential, some understanding of the underlying protocols will greatly help you though.</p><br />
- <p>In this course, we will be considering working on the following example network</p>
- <img alt="example network 1" src="images/example_network.png" />
- <p>It is connected to the internet through a Modem. Most nowadays ADSL and cable modems have a dhcp server configured trough a limited "clicky friendly" web interface (I don't like this). The box we will be configuring is the Router/Firewall (in the middle), it has 4 network interfaces:</p>
- <p>eth0 - 192.168.1.2 - This interface receives it's IP by dhcp.</p>
- <p>eth1 - 172.25.3.1 (statically declared) - Is our internal network.</p>
- <p>eth2 - 10.192.168.1 (statically declared) - Is our wifi.</p>
- <p>eth3 - 10.20.30.1 (statically declared) - Is a DMZ with a server accessible from the internet.</p><br />
- <p>The first chapter will explain you how to set a DHCP server, shaping your networks in zones.</p>
- <p>The second chapter will guide you trough the setup of the routing and filtering</p>
- <p>The third and fourth chapters will help you setup NTP and DNS on your network</p>
- <p class="center"><a href="#" onClick="selectPart('chapter1')"> to chapter 1</a></p>
- </div>
- <div id="chapter1">
- <h1>Dynamic Host Configuration Protocol</h1>
- <h2>Theory</h2><br />
- <p>DHCP stands for Dynamic Host Configuration Protocol and is used for automated/centralized configuration of IP addresses.</p>
- <p>This tutorial's objective is to cover the 1% of dhcp capabilities that is sufficient in 99% of it's uses, and to get your dhcp server running.</p>
- <p>If you want a deeper understanding of DHCP, please consult <a href=http://tools.ietf.org/html/rfc2131>RFC2131</a></p><br />
- <p>Basically, when you connect your computer to a network cable or a wifi network and things just work, it is thanks to DHCP, it gives your computer a free IP address in the right range, the submask, default gateway, DNS server it's supposed to use (and some other things too).</p>
- <ul>
- <li> You plug the cable in the computer </li>
- <li> The DHCP client sends out a DHCPDISCOVER</li>
- <li> The DHCP server receives it and sends a DHCPOFFER</li>
- <li> The DHCP client confirms responding with a DHCPREQUEST</li>
- <li> The DHCP server confirms with a DHCPACK to confirm the settings</li>
- <li> Your computer now has an IP address, knows it's network submask and default gateway, as well as the DNS server it's supposed to use (and maybe some other things too).</li>
- <li> When leaving the network, the DHCP client sends a DHCPRELEASE.</li>
- </ul><br />
- <h2>Practice</h2><br />
- <h3>Client setup</h3>
- <p>To configure the client in windows, set your interface on automatic configuration.</p>
- <p>To configure the interface un *nix, use "dhclient [interface]" as root in a console.</p><br />
- <p><strong>Now the interesting part: let's configure the server on a *nix.</strong></p><br />
- <p>First install the dhcpd package - it's name varies according to distributions ("net-misc/dhcp" in gentoo, "dhcp" in redhat, "dhcp3-server" in debian, installed by default on OpenBSD, ...)</p>
- <p>Then configure it : everything happens in the /etc/dhcpd.conf file</p><br />
- <p class="code">#dhcpd.conf file - lines starting with # are comments.<br />
- #enter your domain here - if you don't have one, you can use quite anything unreal, like "thisis.local"<br />
- &nbsp;&nbsp;option domain-name "hackits.be";<br />
- #DNS server your clients should use by default (here google's)<br />
- &nbsp;&nbsp;option domain-name-servers 8.8.8.8;<br />
- #options on the lease time<br />
- &nbsp;&nbsp;default-lease-time 86000;<br />
- &nbsp;&nbsp;max-lease-time 100000;<br />
- #authoritative should be used on your networks primary dhcp.<br />
- &nbsp;&nbsp;authoritative;<br /><br />
- #now we go to subnet declarations - thes override global settings<br />
- # dhcpd automaticaly uses the subnet on the appropriate interface: <br />
- # eth1 has 172.25.3.1, thus dhcpd will automaticaly use this subnet on this interface<br />
- &nbsp;&nbsp;&nbsp;&nbsp; subnet 172.25.3.0 netmask 255.255.255.0 {<br />
- #the range defines a pool of random adresses, the computers defined lower should NOT be in the range!<br />
- &nbsp;&nbsp;&nbsp;&nbsp; range 172.25.3.50 172.25.3.229;<br />
- #custom domain for this zone, the computers will then be PC1.lan.hackits.be and so on.<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name "lan.hackits.be";<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option broadcast-address 172.25.3.255;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option routers 172.25.3.1;<br />
- #use a different name server for this zones.<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name-servers 172.25.3.1;<br />
+ $msg = !$loggedin ? $notloggedintext : '';
+ return array(
+ 'nav' => array(
+ 'default' => array(
+ 'chapter1' => 'DHCP',
+ 'chapter2' => 'Firewalling',
+ ),
+ 'exercises' => array(
+ 'exercise1' => 'Exercise 1',
+ ),
+ 'exam' => array(
+ 'exam1' => 'Exam',
+ )
+ ),
+ 'content' => array(
+ 'default' => array(
+ 'index' => <<<°
+ <h1>Welcome to Practical Networks!</h1>
+ <p>This course's objective is to help you managing your home network with the standard unix tools.</p>
+ <p>While I will skip the technical details and strip these guides to the essential, some understanding of the underlying protocols will greatly help you though.</p><br />
+ <p>In this course, we will be considering working on the following example network</p>
+ <img alt="example network 1" src="images/example_network.png" />
+ <p>It is connected to the internet through a Modem. Most nowadays ADSL and cable modems have a dhcp server configured trough a limited "clicky friendly" web interface (I don't like this). The box we will be configuring is the Router/Firewall (in the middle), it has 4 network interfaces:</p>
+ <p>eth0 - 192.168.1.2 - This interface receives it's IP by dhcp.</p>
+ <p>eth1 - 172.25.3.1 (statically declared) - Is our internal network.</p>
+ <p>eth2 - 10.192.168.1 (statically declared) - Is our wifi.</p>
+ <p>eth3 - 10.20.30.1 (statically declared) - Is a DMZ with a server accessible from the internet.</p><br />
+ <p>The first chapter will explain you how to set a DHCP server, shaping your networks in zones.</p>
+ <p>The second chapter will guide you trough the setup of the routing and filtering</p>
+ <p>The third and fourth chapters will help you setup NTP and DNS on your network</p>
+ <p class="center"><a href="#"> to chapter 1</a></p>
+°
+ ,
+ 'chapter1' => <<<°
+ <h1>Dynamic Host Configuration Protocol</h1>
+ <h2>Theory</h2><br />
+ <p>DHCP stands for Dynamic Host Configuration Protocol and is used for automated/centralized configuration of IP addresses.</p>
+ <p>This tutorial's objective is to cover the 1% of dhcp capabilities that is sufficient in 99% of it's uses, and to get your dhcp server running.</p>
+ <p>If you want a deeper understanding of DHCP, please consult <a href=http://tools.ietf.org/html/rfc2131>RFC2131</a></p><br />
+ <p>Basically, when you connect your computer to a network cable or a wifi network and things just work, it is thanks to DHCP, it gives your computer a free IP address in the right range, the submask, default gateway, DNS server it's supposed to use (and some other things too).</p>
+ <ul>
+ <li> You plug the cable in the computer </li>
+ <li> The DHCP client sends out a DHCPDISCOVER</li>
+ <li> The DHCP server receives it and sends a DHCPOFFER</li>
+ <li> The DHCP client confirms responding with a DHCPREQUEST</li>
+ <li> The DHCP server confirms with a DHCPACK to confirm the settings</li>
+ <li> Your computer now has an IP address, knows it's network submask and default gateway, as well as the DNS server it's supposed to use (and maybe some other things too).</li>
+ <li> When leaving the network, the DHCP client sends a DHCPRELEASE.</li>
+ </ul><br />
+ <h2>Practice</h2><br />
+ <h3>Client setup</h3>
+ <p>To configure the client in windows, set your interface on automatic configuration.</p>
+ <p>To configure the interface un *nix, use "dhclient [interface]" as root in a console.</p><br />
+ <p><strong>Now the interesting part: let's configure the server on a *nix.</strong></p><br />
+ <p>First install the dhcpd package - it's name varies according to distributions ("net-misc/dhcp" in gentoo, "dhcp" in redhat, "dhcp3-server" in debian, installed by default on OpenBSD, ...)</p>
+ <p>Then configure it : everything happens in the /etc/dhcpd.conf file</p><br />
+ <p class="code">#dhcpd.conf file - lines starting with # are comments.<br />
+ #enter your domain here - if you don't have one, you can use quite anything unreal, like "thisis.local"<br />
+ &nbsp;&nbsp;option domain-name "hackits.be";<br />
+ #DNS server your clients should use by default (here google's)<br />
+ &nbsp;&nbsp;option domain-name-servers 8.8.8.8;<br />
+ #options on the lease time<br />
+ &nbsp;&nbsp;default-lease-time 86000;<br />
+ &nbsp;&nbsp;max-lease-time 100000;<br />
+ #authoritative should be used on your networks primary dhcp.<br />
+ &nbsp;&nbsp;authoritative;<br /><br />
+ #now we go to subnet declarations - thes override global settings<br />
+ # dhcpd automaticaly uses the subnet on the appropriate interface: <br />
+ # eth1 has 172.25.3.1, thus dhcpd will automaticaly use this subnet on this interface<br />
+ &nbsp;&nbsp;&nbsp;&nbsp; subnet 172.25.3.0 netmask 255.255.255.0 {<br />
+ #the range defines a pool of random adresses, the computers defined lower should NOT be in the range!<br />
+ &nbsp;&nbsp;&nbsp;&nbsp; range 172.25.3.50 172.25.3.229;<br />
+ #custom domain for this zone, the computers will then be PC1.lan.hackits.be and so on.<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name "lan.hackits.be";<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option broadcast-address 172.25.3.255;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option routers 172.25.3.1;<br />
+ #use a different name server for this zones.<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name-servers 172.25.3.1;<br />
- #now we bind some mac addresses to IP's, so that those computers always receive the same address.<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host PC1 {<br />
- #to get the hardware ethernet, use "ifconfig" with *nix or "ipconfig /all" with windows (cmd).<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:11:22:33:44:55;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 172.25.3.2;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
-<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host PC2 {<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:22:33:44:55:66;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 172.25.3.3;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
-<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host Printer {<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:33:44:55:66:77;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 172.25.3.4;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
-<br />
-#and we close the subnet<br />
- &nbsp;&nbsp;&nbsp;&nbsp;}<br />
-<br />
- #our wifi and dmz networks are similar, but with less comments<br />
- <br />
- &nbsp;&nbsp;&nbsp;&nbsp;subnet 10.192.168.0 netmask 255.255.255.0 {<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;range 10.192.168.50 10.192.168.254;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name "wifi.hackits.be";<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option broadcast-address 10.192.168.255;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option routers 10.192.168.1;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;}<br />
-<br />
- &nbsp;&nbsp;&nbsp;&nbsp;subnet 10.20.30.0 netmask 255.255.255.0 {<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;range 10.20.30.100 10.20.30.254;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name "dmz.hackits.be";<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option broadcast-address 10.20.30.255;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option routers 10.20.30.1;<br />
- #Here you could also declare a tftp server.<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option tftp-server-name "10.20.30.1";<br />
-<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host web1 {<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:11:55:77:99:BB;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 10.20.30.40;<br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
- &nbsp;&nbsp;&nbsp;&nbsp;}<br />
- </p><br />
+ #now we bind some mac addresses to IP's, so that those computers always receive the same address.<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host PC1 {<br />
+ #to get the hardware ethernet, use "ifconfig" with *nix or "ipconfig /all" with windows (cmd).<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:11:22:33:44:55;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 172.25.3.2;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ <br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host PC2 {<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:22:33:44:55:66;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 172.25.3.3;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ <br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host Printer {<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:33:44:55:66:77;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 172.25.3.4;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ <br />
+ #and we close the subnet<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ <br />
+ #our wifi and dmz networks are similar, but with less comments<br />
+ <br />
+ &nbsp;&nbsp;&nbsp;&nbsp;subnet 10.192.168.0 netmask 255.255.255.0 {<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;range 10.192.168.50 10.192.168.254;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name "wifi.hackits.be";<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option broadcast-address 10.192.168.255;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option routers 10.192.168.1;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ <br />
+ &nbsp;&nbsp;&nbsp;&nbsp;subnet 10.20.30.0 netmask 255.255.255.0 {<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;range 10.20.30.100 10.20.30.254;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option domain-name "dmz.hackits.be";<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option broadcast-address 10.20.30.255;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option routers 10.20.30.1;<br />
+ #Here you could also declare a tftp server.<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option tftp-server-name "10.20.30.1";<br />
+ <br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host web1 {<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hardware ethernet 00:11:55:77:99:BB;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixed-address 10.20.30.40;<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ &nbsp;&nbsp;&nbsp;&nbsp;}<br />
+ </p><br />
- <p>Once your configuration is done, save it as /etc/dhcpd.conf, restart dhcpd and things should be working :)</p>
- <p>Carefull with the "{ }" and ";" If you miss one, dhcpd will not run!</p><br />
- <p>It's nice to have zones... my next tutorial will explain how to enable networking between those zones.</p><br />
- <p class="center"><a href="#" onClick="selectPart('chapter2')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter2">
- <h1>Firewalling</h1>
- <h2>With Linux</h2>
- <p>This course hasn't been written yet.</p>
- <h2>With OpenBSD</h2>
- <p>This course hasn't been written yet.</p>
- </div>
- <div id="exercise1">
- <h3>Exercise 1:</h3>
- <p>Nothingyet</p>
- <div class="revealbutton" onClick="$('#answer1').show(); $('.revealbutton').hide(); ">Reveal Answer</div>
- <div class="answer" id="answer1">
- <p>Well done, you revealed the answer but there's no question yet :)</p>
- <p>no exam yet... <a href="#" onClick="selectPart('examn')">Click here</a> to check out the void!</p>
- </div>
- </div>
- <div id="examn">
- <h2>No Exam Time yet!</h2><br />
- <? if(!$loggedin) echo $notloggedintext; ?>
- <form id="examnform" name="examnform" method="post" action="">
- <div class="question">
- <h3>Question 1</h3><br />
- <p>Nothing yet</p>
- <input type="radio" value="A" id="radio1" name="1" /><label for="radio1">bla</label><br />
- <input type="radio" value="B" id="radio2" name="1" /><label for="radio2">bla</label><br />
- <input type="radio" value="C" id="radio3" name="1" /><label for="radio3">bla</label><br />
- </div>
- </form>
- </div>
-</div>
+ <p>Once your configuration is done, save it as /etc/dhcpd.conf, restart dhcpd and things should be working :)</p>
+ <p>Carefull with the "{ }" and ";" If you miss one, dhcpd will not run!</p><br />
+ <p>It's nice to have zones... my next tutorial will explain how to enable networking between those zones.</p><br />
+ <p class="center"><a href="#">>> Next Chapter >></a></p>
+°
+ ,
+ 'chapter2' => <<<°
+ <h1>Firewalling</h1>
+ <h2>With Linux</h2>
+ <p>This course hasn't been written yet.</p>
+ <h2>With OpenBSD</h2>
+ <p>This course hasn't been written yet.</p>
+
+°
+ ,
+ ),
+ 'exercises' => array(
+ 'exercise1' => <<<°
+ <h3>Exercise 1:</h3>
+ <p>Nothingyet</p>
+ <div class="revealbutton" onClick="$('#answer1').show(); $('.revealbutton').hide(); ">Reveal Answer</div>
+ <div class="answer" id="answer1">
+ <p>Well done, you revealed the answer but there's no question yet :)</p>
+ <p>no exam yet... <a href="#">Click here</a> to check out the void!</p>
+ </div>
+
+°
+ ,
+ ),
+ 'exam' => array(
+ 'exam1' => <<<°
+ <h2>No Exam Time yet!</h2><br />
+ <? if(!$loggedin) echo $notloggedintext; ?>
+ <form id="examnform" name="examnform" method="post" action="">
+ <div class="question">
+ <h3>Question 1</h3><br />
+ <p>Nothing yet</p>
+ <input type="radio" value="A" id="radio1" name="1" /><label for="radio1">bla</label><br />
+ <input type="radio" value="B" id="radio2" name="1" /><label for="radio2">bla</label><br />
+ <input type="radio" value="C" id="radio3" name="1" /><label for="radio3">bla</label><br />
+ </div>
+ </form>
+°
+ ),
+ )
+ );
View
152 courses/courses/course3.php
@@ -1,99 +1,55 @@
<?php
- require("courseheader.php");
-?>
-<div id="coursenavigation">
- <ol class="tree">
- <li class="file"><a href="#" onClick="selectPart('default')">Introduction</a></li>
- <li>
- <label for="clients">IRC Clients</label><input type="checkbox" checked id="clients" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('chapter1')">Webclients</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter2')">Windows</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter3')">Linux</a></li>
- </ol>
- </li>
- <li>
- <label for="background">Technical Background</label><input type="checkbox" checked id="background" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('chapter4')">How IRC works</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter5')">IRC Security</a></li>
- <li class="file"><a href="#" onClick="selectPart('chapter6')">Installing an IRCd</a></li>
- </ol>
- </li>
- <li>
- <label for="exercises">Exercises</label> <input type="checkbox" checked id="exercises" />
- <ol>
- <li class="file"><a href="#" onClick="selectPart('exercise1')">Exercise 1</a></li>
- </ol>
- </li>
- <li class="file"><a href="#" onClick="selectPart('examn')">Exam</a></li>
- </ol>
-</div>
-<div id="coursecontent">
- <div id="default">
- <h1>Internet Relay Chat (IRC)</h1>
- <p>Under construction!</p>
- <p class="center"><a href="#" onClick="selectPart('chapter1')">>> Let's start! >></a></p>
- </div>
- <div id="chapter1">
- <h1>Webclients</h1>
- <p></p>
- <p class="center"><a href="#" onClick="selectPart('chapter2')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter2">
- <h1>Windows Clients</h1>
- <p></p>
- <p class="center"><a href="#" onClick="selectPart('chapter3')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter3">
- <h1>Linux Clients</h1>
- <p></p>
- <p class="center"><a href="#" onClick="selectPart('chapter4')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter4">
- <h1>How IRC works</h1>
- <p></p>
- <p class="center"><a href="#" onClick="selectPart('chapter5')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter5">
- <h1>IRC Security</h1>
- <p></p>
- <p class="center"><a href="#" onClick="selectPart('chapter6')">>> Next Chapter >></a></p>
- </div>
- <div id="chapter6">
- <h1>Installing an IRCd</h1>
- <p></p>
- <p class="center"><a href="#" onClick="selectPart('exercise1')">>> Next Chapter >></a></p>
- </div>
- <div id="exercise1">
- <h3>Exercise 1:</h3>
- <p>Exercise text</p>
- <div class="revealbutton" onClick="$('#answer1').show(); $('.revealbutton').hide(); ">Reveal Answer</div>
- <div class="answer" id="answer1">
- <p>Answer</p>
- </div>
- </div>
- <div id="examn">
- <h2>Exam Time!</h2><br />
- <? if(!$loggedin) echo $notloggedintext; ?>
- <form id="examnform" name="examnform" method="post" action="">
- <div class="question">
- <h3>Question 1</h3><br />
- <p>X</p>
- <input type="radio" value="A" id="radio1" name="1" /><label for="radio1"></label><br />
- <input type="radio" value="B" id="radio2" name="1" /><label for="radio2"></label><br />
- <input type="radio" value="C" id="radio3" name="1" /><label for="radio3"></label><br />
- </div>
- <div class="question">
- <h3>Question 2</h3><br />
- <p>Y</p>
- <input type="radio" value="A" id="radio1" name="2" /><label for="radio1"></label><br />
- <input type="radio" value="B" id="radio2" name="2" /><label for="radio2"></label><br />
- <input type="radio" value="C" id="radio3" name="2" /><label for="radio3"></label><br />
- </div>
- <div id="examnsubmit">
- <button>Submit</button>
- </div>
- </form>
- </div>
-</div>
+$msg = !$loggedin ? $notloggedintext : '';
+return array(
+ 'nav' => array(
+ 'default' => array(
+ 'chapter1' => 'How IRC works',
+ 'chapter2' => 'IRC Security',
+ ),
+ 'exercises' => array(
+ 'exercise1' => 'Exercise 1',
+ ),
+ 'exam' => array(
+ 'exam1' => 'Exam',
+ )
+ ),
+ 'content' => array(
+ 'default' => array(
+ 'index' => <<<°
+ <h1>Internet Relay Chat (IRC)</h1>
+ <p>Under construction!</p>
+°
+ ,
+ 'chapter1' => <<<°
+ <p class="center">How IRC works</p>
+°
+ ,
+ 'chapter2' => <<<°
+ <p class="center">IRC Security</p>
+°
+ ,
+ ),
+ 'exercises' => array(
+ 'exercise1' => <<<°
+ <h3>Exercise 1:</h3>
+ <p>Nothing yet</p>
+°
+ ,
+ ),
+ 'exam' => array(
+ 'exam1' => <<<°
+ <h2>No Exam Time yet!</h2><br />
+ <form id="examnform" name="examnform" method="post" action="">
+ <div class="question">
+ <h3>Question 1</h3><br />
+ <p>Nothing yet</p>
+ <input type="radio" value="A" id="radio1" name="1" /><label for="radio1">bla</label><br />
+ <input type="radio" value="B" id="radio2" name="1" /><label for="radio2">bla</label><br />
+ <input type="radio" value="C" id="radio3" name="1" /><label for="radio3">bla</label><br />
+ </div>
+ </form>
+°
+ ),
+ )
+);
+
View
154 courses/css/hackits-courses.css
@@ -61,11 +61,13 @@ a:hover {
float: left;
width: 20%;
min-width: 185px;
+ margin-left: -45px;
}
#coursenavigation a {
font-weight: normal;
font-size: 10pt;
+ width: 100%;
}
#coursecontent {
@@ -229,70 +231,88 @@ a:hover {
/* Course Tree CSS */
- li.tab {
- font-size: 12pt;
- }
- ol.tree
- {
- margin-top: 0px;
- margin-left: 10px;
- padding: 0 0 0 0px;
- width: 175px;
- }
- li
- {
- position: relative;
- margin-left: -15px;
- list-style: none;
- }
- li.file
- {
- margin-left: -1px !important;
- }
- li.file a
- {
- background: url(images/document.png) 0 0 no-repeat;
- color: #fff;
- padding-left: 21px;
- text-decoration: none;
- display: block;
- }
- li.file a[href *= '.pdf'] { background: url(images/document.png) 0 0 no-repeat; }
- li.file a[href *= '.html'] { background: url(images/document.png) 0 0 no-repeat; }
- li.file a[href $= '.css'] { background: url(images/document.png) 0 0 no-repeat; }
- li.file a[href $= '.js'] { background: url(images/document.png) 0 0 no-repeat; }
- li input
- {
- position: absolute;
- left: 0;
- margin-left: 0;
- opacity: 0;
- z-index: 2;
- cursor: pointer;
- height: 1em;
- width: 1em;
- top: 0;
- }
- li input + ol
- {
- background: url(images/toggle-small-expand.png) 40px 0 no-repeat;
- margin: -0.938em 0 0 -44px; /* 15px */
- height: 1em;
- }
- li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; }
- li label
- {
- background: url(images/folder-horizontal.png) 15px 1px no-repeat;
- cursor: pointer;
- display: block;
- padding-left: 37px;
- }
- li input:checked + ol
- {
- background: url(images/toggle-small.png) 40px 5px no-repeat;
- margin: -1.25em 0 0 -44px; /* 20px */
- padding: 1.563em 0 0 80px;
- height: auto;
- }
- li input:checked + ol > li { display: block; margin: 0 0 0.125em; /* 2px */}
- li input:checked + ol > li:last-child { margin: 0 0 0.063em; /* 1px */ }
+li.tab {
+font-size: 12pt;
+}
+ol.tree
+{
+ margin-top: 0px;
+ margin-left: 48px;
+ padding: 0 0 0 0px;
+ width: 258px;
+}
+li
+{
+ position: relative;
+ margin-left: -15px;
+ list-style: none;
+}
+li.file.selected a{
+ background-color: #444;
+}
+li a{
+ color: #fff;
+ padding-left: 2px;
+ padding-bottom: 0px;
+ padding-top: 0px;
+ text-decoration: none;
+ display: block;
+ background-repeat: no-repeat;
+}
+li.file a { background-image: url(images/document.png); }
+li.exercises a { background-image: url(images/exercise.png); }
+li.exam a { background-image: url(images/exam.png); }
+li.file a, li.exercises a, li.exam a {
+ padding-left: 18px;
+ margin-left: 0px;
+}
+li.file a[href *= '.pdf'] { background-image: url(images/document.png); }
+li.file a[href *= '.html'] { background-image: url(images/document.png); }
+li.file a[href $= '.css'] { background-image: url(images/document.png); }
+li.file a[href $= '.js'] { background-image: url(images/document.png); }
+li input
+{
+ position: absolute;
+ left: 0;
+ margin-left: 0;
+ opacity: 0;
+ z-index: 2;
+ cursor: pointer;
+ height: 1em;
+ width: 1em;
+ top: 0;
+}
+li input + ol
+{
+ background: url(images/toggle-small-expand.png) 42px -3px no-repeat;
+ margin: -0.938em 0 0 -44px; /* 15px */
+ height: 1em;
+}
+li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; }
+li label
+{
+ background: url(images/folder-horizontal.png) 15px 1px no-repeat;
+ cursor: pointer;
+ display: block;
+ padding-left: 37px;
+}
+li input:checked + ol
+{
+ background: url(images/toggle-small.png) 42px 1px no-repeat;
+ margin: -1.25em 0 0 -44px; /* 20px */
+ padding: 1.563em 0 0 80px;
+ height: auto;
+}
+li input:checked + ol > li { display: block; margin: 0 0 0.125em; /* 2px */}
+li input:checked + ol > li:last-child { margin: 0 0 0.063em; /* 1px */ }
+
+#ranking table{
+ width: 100%;
+ border-style: none;
+ border-collapse: collapse;
+}
+
+#ranking table th{
+ color: #050;
+ background-color: #111;
+}
View
BIN  courses/css/images/exam.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  courses/css/images/exercise.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
109 courses/index.php
@@ -1,5 +1,4 @@
<?
-
///////////////////////////////////////////////////////////////////////////////////
// 888 888 d8888 .d8888b. 888 d8P 8888888 88888888888 .d8888b. //
// 888 888 d88888 d88P Y88b 888 d8P 888 888 d88P Y88b //
@@ -23,13 +22,6 @@
require("../getsmfuser.php");
-// If an id is passed as argument, load course directly
-if(isset($_GET['id']))
-{
- $id = htmlspecialchars($_GET['id']);
- $loadcourse = "$(document).ready(function() { $(\"#course\").load(\"course.php?id=\"+".$id."); $(\"#tabs\").tabs(\"select\" , \"tab-course\") } )";
-}
-
// format date for display in header bar
$showdate = date('F d, o, h:i:s A');
@@ -40,7 +32,7 @@
<title>Hackits.be - Courses</title>
<link rel="stylesheet" href="css/jquery-ui-1.8.17.custom.css">
<link rel="stylesheet" href="css/hackits-courses.css">
- <script src="js/jquery-1.7.1.min.js"></script>
+ <script src="js/jquery-1.8.2.js"></script>
<script src="js/jquery.ui.core.js"></script>
<script src="js/jquery.ui.widget.js"></script>
<script src="js/jquery.ui.button.js"></script>
@@ -48,11 +40,79 @@
<script src="js/jquery.ui.tabs.js"></script>
<script src="js/jquery.ui.dialog.js"></script>
<script src="js/jquery.ui.accordion.js"></script>
+ <script src="js/jquery.address.js"></script>
+<!-- <script src="js/jquery.history.js"></script>-->
<script>
$(function() {
- $( "#tabs" ).tabs();
- $( "#courses" ).accordion({ autoHeight: false });
- });
+ var tabStates = { //default states
+ overview: '/overview/General',
+ course: '/course/General/Intro+to+Hackits+Courses/Hackits+Courses',
+ ranking: '/ranking',
+ help: '/help'
+ },
+ selectPart = function(part){
+ var part = $("#"+part);
+ part.show().siblings().hide();
+ },
+ getPanelIndex = function(str){
+ return $('.ui-accordion-header a').filter(function(){
+ return (new RegExp(str)).test($(this).text())
+ }).parent().index() / 2;
+ },
+ updateState = function(e){
+ var parts = e.path.split('/')
+ , tab = parts[1]
+ , panel = parts[2] || ''
+ , course = parts[3] || ''
+ , chapter = parts[4] || '';
+ if(tab.length){ //select tab
+ $("#tabs").tabs("select", '#'+tab.replace(/^#/,''));
+ }
+ if(panel.length){ //select accordion panel
+ $("#courses").accordion("activate", getPanelIndex(panel));
+ $('a[href$="/course/'+panel+'"]').siblings('input').attr('checked', true);
+ }
+ if(course.length){ //select course
+ $('a[href$="/course/'+panel+'/'+course+'"]').siblings('input').attr('checked', true);
+ }
+ if(chapter.length){ //select chapter
+ $('#coursenavigation li.file a').each(function(){
+ $(this).closest('li').toggleClass('selected',
+ (new RegExp(e.path.replace(/\+/g, '\\+')+'$', 'i'))
+ .test($(this).attr('href')));
+ });
+ $('#coursecontent').html(
+ $('[id="'
+ + $('a[href$="/course/'+panel+'/'+course+'/'+chapter+'"]:not([rel=overview])').data('chapterid')
+ + '"]').html());
+ }
+ };
+
+ $("#tabs").tabs({
+ select: function(event, ui){
+ var oldSelected = $('#tabs .ui-tabs-selected a').attr('href').replace(/^#/, '')
+ , newSelected = ui.tab.hash.replace(/^#/, '');
+ if((new RegExp('^/'+newSelected, 'i')).test($.address.path())){ return; }
+ tabStates[oldSelected] = $.address.path();
+ $.address.path(tabStates[newSelected]);
+ }
+ });
+ $("#courses").accordion({
+ autoHeight: false
+ });
+
+ $.address.init(function(e){
+ if($.address.path() === '/'){
+ $.address.path(tabStates.overview); //default to overview
+ }
+ $('#coursenavigation .file a[data-chapterid]').address(function() {
+ return $(this).attr('href');
+ });
+ tabStates[$.address.path().match(/^\/([^\/]+)/)[0].substr(1)] = $.address.path();
+ }).change(updateState)
+ .internalChange({}, updateState)
+ .externalChange({}, updateState);
+ });
</script>
</head>
<body>
@@ -76,25 +136,28 @@
<div id="tabs">
<ul>
- <li class="tab"><a href="#tab-overview">Course Overview</a></li>
- <li class="tab"><a href="#tab-course">Current Course</a></li>
- <li class="tab"><a href="#tab-ranking">Ranking List</a></li>
- <li class="tab"><a href="#tab-help">Help</a></li>
+ <li class="tab"><a rel="address:/overview" href="#overview">Course Overview</a></li>
+ <li class="tab"><a rel="address:/course" href="#course">Current Course</a></li>
+ <li class="tab"><a rel="address:/ranking" href="#ranking">Ranking List</a></li>
+ <li class="tab"><a rel="address:/help" href="#help">Help</a></li>
</ul>
- <div id="tab-overview">
+ <div id="overview">
<? include("overview.php"); ?>
</div>
- <div id="tab-course">
- <? include("course.php"); ?>
+ <div id="course">
+ <?
+ require_once("courseheader.php");
+ include("course.php");
+ ?>
</div>
- <div id="tab-ranking">
+ <div id="ranking">
<? include("ranking.php"); ?>
</div>
- <div id="tab-help">
+ <div id="help">
<? include("help.php"); ?>
</div>
@@ -103,10 +166,6 @@
</div> <!-- end-of-container -->
<script>
- function showCourse(id){
- $("#course").load("course.php?id="+id);
- $("#tabs").tabs( "select" , "tab-course" )
- }
<? echo isset($loadcourse) ? $loadcourse : ''; ?>
</script>
<?php Utils::queryLog(); ?>
View
9,440 courses/js/jquery-1.8.2.js
9,440 additions, 0 deletions not shown
View
683 courses/js/jquery.address.js
@@ -0,0 +1,683 @@
+/*
+ * jQuery Address Plugin v${version}
+ * http://www.asual.com/jquery/address/
+ *
+ * Copyright (c) 2009-2010 Rostislav Hristov
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Date: ${timestamp}
+ */
+(function ($) {
+
+ $.address = (function () {
+
+ var _trigger = function(name) {
+ var ev = $.extend($.Event(name),
+ (function() {
+ var parameters = {},
+ parameterNames = $.address.parameterNames();
+ for (var i = 0, l = parameterNames.length; i < l; i++) {
+ parameters[parameterNames[i]] = $.address.parameter(parameterNames[i]);
+ }
+ return {
+ value: $.address.value(),
+ path: $.address.path(),
+ pathNames: $.address.pathNames(),
+ parameterNames: parameterNames,
+ parameters: parameters,
+ queryString: $.address.queryString()
+ };
+ }).call($.address)
+ );
+
+ $($.address).trigger(ev);
+ return ev;
+ },
+ _array = function(obj) {
+ return Array.prototype.slice.call(obj);
+ },
+ _bind = function(value, data, fn) {
+ $().bind.apply($($.address), Array.prototype.slice.call(arguments));
+ return $.address;
+ },
+ _unbind = function(value, fn) {
+ $().unbind.apply($($.address), Array.prototype.slice.call(arguments));
+ return $.address;
+ },
+ _supportsState = function() {
+ return (_h.pushState && _opts.state !== UNDEFINED);
+ },
+ _hrefState = function() {
+ return ('/' + _l.pathname.replace(new RegExp(_opts.state), '') +
+ _l.search + (_hrefHash() ? '#' + _hrefHash() : '')).replace(_re, '/');
+ },
+ _hrefHash = function() {
+ var index = _l.href.indexOf('#');
+ return index != -1 ? _crawl(_l.href.substr(index + 1), FALSE) : '';
+ },
+ _href = function() {
+ return _supportsState() ? _hrefState() : _hrefHash();
+ },
+ _window = function() {
+ try {
+ return top.document !== UNDEFINED && top.document.title !== UNDEFINED ? top : window;
+ } catch (e) {
+ return window;
+ }
+ },
+ _js = function() {
+ return 'javascript';
+ },
+ _strict = function(value) {
+ value = value.toString();
+ return (_opts.strict && value.substr(0, 1) != '/' ? '/' : '') + value;
+ },
+ _crawl = function(value, direction) {
+ if (_opts.crawlable && direction) {
+ return (value !== '' ? '!' : '') + value;
+ }
+ return value.replace(/^\!/, '');
+ },
+ _cssint = function(el, value) {
+ return parseInt(el.css(value), 10);
+ },
+
+ // Hash Change Callback
+ _listen = function() {
+ if (!_silent) {
+ var hash = _href(),
+ diff = decodeURI(_value) != decodeURI(hash);
+ if (diff) {
+ if (_msie && _version < 7) {
+ _l.reload();
+ } else {
+ if (_msie && !_hashchange && _opts.history) {
+ _st(_html, 50);
+ }
+ _old = _value;
+ _value = hash;
+ _update(FALSE);
+ }
+ }
+ }
+ },
+
+ _update = function(internal) {
+ var changeEv = _trigger(CHANGE),
+ xChangeEv = _trigger(internal ? INTERNAL_CHANGE : EXTERNAL_CHANGE);
+
+ _st(_track, 10);
+
+ if (changeEv.isDefaultPrevented() || xChangeEv.isDefaultPrevented()){
+ _preventDefault();
+ }
+ },
+
+ _preventDefault = function(){
+ _value = _old;
+
+ if (_supportsState()) {
+ _h.popState({}, '', _opts.state.replace(/\/$/, '') + (_value === '' ? '/' : _value));
+ } else {
+ _silent = TRUE;
+ if (_webkit) {
+ if (_opts.history) {
+ _l.hash = '#' + _crawl(_value, TRUE);
+ } else {
+ _l.replace('#' + _crawl(_value, TRUE));
+ }
+ } else if (_value != _href()) {
+ if (_opts.history) {
+ _l.hash = '#' + _crawl(_value, TRUE);
+ } else {
+ _l.replace('#' + _crawl(_value, TRUE));
+ }
+ }
+ if ((_msie && !_hashchange) && _opts.history) {
+ _st(_html, 50);
+ }
+ if (_webkit) {
+ _st(function(){ _silent = FALSE; }, 1);
+ } else {
+ _silent = FALSE;
+ }
+ }
+
+ },
+
+ _track = function() {
+ if (_opts.tracker !== 'null' && _opts.tracker !== NULL) {
+ var fn = $.isFunction(_opts.tracker) ? _opts.tracker : _t[_opts.tracker],
+ value = (_l.pathname + _l.search +
+ ($.address && !_supportsState() ? $.address.value() : ''))
+ .replace(/\/\//, '/').replace(/^\/$/, '');
+ if ($.isFunction(fn)) {
+ fn(value);
+ } else if ($.isFunction(_t.urchinTracker)) {
+ _t.urchinTracker(value);
+ } else if (_t.pageTracker !== UNDEFINED && $.isFunction(_t.pageTracker._trackPageview)) {
+ _t.pageTracker._trackPageview(value);
+ } else if (_t._gaq !== UNDEFINED && $.isFunction(_t._gaq.push)) {
+ _t._gaq.push(['_trackPageview', decodeURI(value)]);
+ }
+ }
+ },
+ _html = function() {
+ var src = _js() + ':' + FALSE + ';document.open();document.writeln(\'<html><head><title>' +
+ _d.title.replace(/\'/g, '\\\'') + '</title><script>var ' + ID + ' = "' + encodeURIComponent(_href()).replace(/\'/g, '\\\'') +
+ (_d.domain != _l.hostname ? '";document.domain="' + _d.domain : '') +
+ '";</' + 'script></head></html>\');document.close();';
+ if (_version < 7) {
+ _frame.src = src;
+ } else {
+ _frame.contentWindow.location.replace(src);
+ }
+ },
+ _options = function() {
+ if (_url && _qi != -1) {
+ var i, param, params = _url.substr(_qi + 1).split('&');
+ for (i = 0; i < params.length; i++) {
+ param = params[i].split('=');
+ if (/^(autoUpdate|crawlable|history|strict|wrap)$/.test(param[0])) {
+ _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1], 10) !== 0));
+ }
+ if (/^(state|tracker)$/.test(param[0])) {
+ _opts[param[0]] = param[1];
+ }
+ }
+ _url = NULL;
+ }
+ _old = _value;
+ _value = _href();
+ },
+ _load = function() {
+ if (!_loaded) {
+ _loaded = TRUE;
+ _options();
+ var complete = function() {
+ _enable.call(this);
+ _unescape.call(this);
+ },
+ body = $('body').ajaxComplete(complete);
+ complete();
+ if (_opts.wrap) {
+ var wrap = $('body > *')
+ .wrapAll('<div style="padding:' +
+ (_cssint(body, 'marginTop') + _cssint(body, 'paddingTop')) + 'px ' +
+ (_cssint(body, 'marginRight') + _cssint(body, 'paddingRight')) + 'px ' +
+ (_cssint(body, 'marginBottom') + _cssint(body, 'paddingBottom')) + 'px ' +
+ (_cssint(body, 'marginLeft') + _cssint(body, 'paddingLeft')) + 'px;" />')
+ .parent()
+ .wrap('<div id="' + ID + '" style="height:100%;overflow:auto;position:relative;' +
+ (_webkit && !window.statusbar.visible ? 'resize:both;' : '') + '" />');
+ $('html, body')
+ .css({
+ height: '100%',
+ margin: 0,
+ padding: 0,
+ overflow: 'hidden'
+ });
+ if (_webkit) {
+ $('<style type="text/css" />')
+ .appendTo('head')
+ .text('#' + ID + '::-webkit-resizer { background-color: #fff; }');
+ }
+ }
+ if (_msie && !_hashchange) {
+ var frameset = _d.getElementsByTagName('frameset')[0];
+ _frame = _d.createElement((frameset ? '' : 'i') + 'frame');
+ _frame.src = _js() + ':' + FALSE;
+ if (frameset) {
+ frameset.insertAdjacentElement('beforeEnd', _frame);
+ frameset[frameset.cols ? 'cols' : 'rows'] += ',0';
+ _frame.noResize = TRUE;
+ _frame.frameBorder = _frame.frameSpacing = 0;
+ } else {
+ _frame.style.display = 'none';
+ _frame.style.width = _frame.style.height = 0;
+ _frame.tabIndex = -1;
+ _d.body.insertAdjacentElement('afterBegin', _frame);
+ }
+ _st(function() {
+ $(_frame).bind('load', function() {
+ var win = _frame.contentWindow;
+ _old = _value;
+ _value = win[ID] !== UNDEFINED ? win[ID] : '';
+ if (_value != _href()) {
+ _update(FALSE);
+ _l.hash = _crawl(_value, TRUE);
+ }
+ });
+ if (_frame.contentWindow[ID] === UNDEFINED) {
+ _html();
+ }
+ }, 50);
+ }
+ _st(function() {
+ _trigger('init');
+ _update(FALSE);
+ }, 1);
+ if (!_supportsState()) {
+ if ((_msie && _version > 7) || (!_msie && _hashchange)) {
+ if (_t.addEventListener) {
+ _t.addEventListener(HASH_CHANGE, _listen, FALSE);
+ } else if (_t.attachEvent) {
+ _t.attachEvent('on' + HASH_CHANGE, _listen);
+ }
+ } else {
+ _si(_listen, 50);
+ }
+ }
+ if ('state' in window.history) {
+ $(window).trigger('popstate');
+ }
+ }
+ },
+ _enable = function() {
+ var el,
+ elements = $('a'),
+ length = elements.size(),
+ delay = 1,
+ index = -1,
+ sel = '[rel*="address:"]',
+ fn = function() {
+ if (++index != length) {
+ el = $(elements.get(index));
+ if (el.is(sel)) {
+ el.address(sel);
+ }
+ _st(fn, delay);
+ }
+ };
+ _st(fn, delay);
+ },
+ _popstate = function() {
+ if (decodeURI(_value) != decodeURI(_href())) {
+ _old = _value;
+ _value = _href();
+ _update(FALSE);
+ }
+ },
+ _unload = function() {
+ if (_t.removeEventListener) {
+ _t.removeEventListener(HASH_CHANGE, _listen, FALSE);
+ } else if (_t.detachEvent) {
+ _t.detachEvent('on' + HASH_CHANGE, _listen);
+ }
+ },
+ _unescape = function() {
+ if (_opts.crawlable) {
+ var base = _l.pathname.replace(/\/$/, ''),
+ fragment = '_escaped_fragment_';
+ if ($('body').html().indexOf(fragment) != -1) {
+ $('a[href]:not([href^=http]), a[href*="' + document.domain + '"]').each(function() {
+ var href = $(this).attr('href').replace(/^http:/, '').replace(new RegExp(base + '/?$'), '');
+ if (href === '' || href.indexOf(fragment) != -1) {
+ $(this).attr('href', '#' + encodeURI(decodeURIComponent(href.replace(new RegExp('/(.*)\\?' +
+ fragment + '=(.*)$'), '!$2'))));
+ }
+ });
+ }
+ }
+ },
+ UNDEFINED,
+ NULL = null,
+ ID = 'jQueryAddress',
+ STRING = 'string',
+ HASH_CHANGE = 'hashchange',
+ INIT = 'init',
+ CHANGE = 'change',
+ INTERNAL_CHANGE = 'internalChange',
+ EXTERNAL_CHANGE = 'externalChange',
+ TRUE = true,
+ FALSE = false,
+ _opts = {
+ autoUpdate: TRUE,
+ crawlable: FALSE,
+ history: TRUE,
+ strict: TRUE,
+ wrap: FALSE
+ },
+ _browser = $.browser,
+ _version = parseFloat(_browser.version),
+ _msie = !$.support.opacity,
+ _webkit = _browser.webkit || _browser.safari,
+ _t = _window(),
+ _d = _t.document,
+ _h = _t.history,
+ _l = _t.location,
+ _si = setInterval,
+ _st = setTimeout,
+ _re = /\/{2,9}/g,
+ _agent = navigator.userAgent,
+ _hashchange = 'on' + HASH_CHANGE in _t,
+ _frame,
+ _form,
+ _url = $('script:last').attr('src'),
+ _qi = _url ? _url.indexOf('?') : -1,
+ _title = _d.title,
+ _silent = FALSE,
+ _loaded = FALSE,
+ _juststart = TRUE,
+ _updating = FALSE,
+ _listeners = {},
+ _value = _href();
+ _old = _value;
+
+ if (_msie) {
+ _version = parseFloat(_agent.substr(_agent.indexOf('MSIE') + 4));
+ if (_d.documentMode && _d.documentMode != _version) {
+ _version = _d.documentMode != 8 ? 7 : 8;
+ }
+ var pc = _d.onpropertychange;
+ _d.onpropertychange = function() {
+ if (pc) {
+ pc.call(_d);
+ }
+ if (_d.title != _title && _d.title.indexOf('#' + _href()) != -1) {
+ _d.title = _title;
+ }
+ };
+ }
+
+ if (_h.navigationMode) {
+ _h.navigationMode = 'compatible';
+ }
+ if (document.readyState == 'complete') {
+ var interval = setInterval(function() {
+ if ($.address) {
+ _load();
+ clearInterval(interval);
+ }
+ }, 50);
+ } else {
+ _options();
+ $(_load);
+ }
+ $(window).bind('popstate', _popstate).bind('unload', _unload);
+
+ return {
+ bind: function(type, data, fn) {
+ return _bind.apply(this, _array(arguments));
+ },
+ unbind: function(type, fn) {
+ return _unbind.apply(this, _array(arguments));
+ },
+ init: function(data, fn) {
+ return _bind.apply(this, [INIT].concat(_array(arguments)));
+ },
+ change: function(data, fn) {
+ return _bind.apply(this, [CHANGE].concat(_array(arguments)));
+ },
+ internalChange: function(data, fn) {
+ return _bind.apply(this, [INTERNAL_CHANGE].concat(_array(arguments)));
+ },
+ externalChange: function(data, fn) {
+ return _bind.apply(this, [EXTERNAL_CHANGE].concat(_array(arguments)));
+ },
+ baseURL: function() {
+ var url = _l.href;
+ if (url.indexOf('#') != -1) {
+ url = url.substr(0, url.indexOf('#'));
+ }
+ if (/\/$/.test(url)) {
+ url = url.substr(0, url.length - 1);
+ }
+ return url;
+ },
+ autoUpdate: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.autoUpdate = value;
+ return this;
+ }
+ return _opts.autoUpdate;
+ },
+ crawlable: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.crawlable = value;
+ return this;
+ }
+ return _opts.crawlable;
+ },
+ history: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.history = value;
+ return this;
+ }
+ return _opts.history;
+ },
+ state: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.state = value;
+ var hrefState = _hrefState();
+ if (_opts.state !== UNDEFINED) {
+ if (_h.pushState) {
+ if (hrefState.substr(0, 3) == '/#/') {
+ _l.replace(_opts.state.replace(/^\/$/, '') + hrefState.substr(2));
+ }
+ } else if (hrefState != '/' && hrefState.replace(/^\/#/, '') != _hrefHash()) {
+ _st(function() {
+ _l.replace(_opts.state.replace(/^\/$/, '') + '/#' + hrefState);
+ }, 1);
+ }
+ }
+ return this;
+ }
+ return _opts.state;
+ },
+ strict: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.strict = value;
+ return this;
+ }
+ return _opts.strict;
+ },
+ tracker: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.tracker = value;
+ return this;
+ }
+ return _opts.tracker;
+ },
+ wrap: function(value) {
+ if (value !== UNDEFINED) {
+ _opts.wrap = value;
+ return this;
+ }
+ return _opts.wrap;
+ },
+ update: function() {
+ _updating = TRUE;
+ this.value(_value);
+ _updating = FALSE;
+ return this;
+ },
+ title: function(value) {
+ if (value !== UNDEFINED) {
+ _st(function() {
+ _title = _d.title = value;
+ if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {
+ _frame.contentWindow.document.title = value;
+ _juststart = FALSE;
+ }
+ }, 50);
+ return this;
+ }
+ return _d.title;
+ },
+ value: function(value) {
+ if (value !== UNDEFINED) {
+ value = _strict(value);
+ if (value == '/') {
+ value = '';
+ }
+ if (_value == value && !_updating) {
+ return;
+ }
+ _old = _value;
+ _value = value;
+ if (_opts.autoUpdate || _updating) {
+ _update(TRUE);
+ if (_supportsState()) {
+ _h[_opts.history ? 'pushState' : 'replaceState']({}, '',
+ _opts.state.replace(/\/$/, '') + (_value === '' ? '/' : _value));
+ } else {
+ _silent = TRUE;
+ if (_webkit) {
+ if (_opts.history) {
+ _l.hash = '#' + _crawl(_value, TRUE);
+ } else {
+ _l.replace('#' + _crawl(_value, TRUE));
+ }
+ } else if (_value != _href()) {
+ if (_opts.history) {
+ _l.hash = '#' + _crawl(_value, TRUE);
+ } else {
+ _l.replace('#' + _crawl(_value, TRUE));
+ }
+ }
+ if ((_msie && !_hashchange) && _opts.history) {
+ _st(_html, 50);
+ }
+ if (_webkit) {
+ _st(function(){ _silent = FALSE; }, 1);
+ } else {
+ _silent = FALSE;
+ }
+ }
+ }
+ return this;
+ }
+ return _strict(_value);
+ },
+ path: function(value) {
+ if (value !== UNDEFINED) {
+ var qs = this.queryString(),
+ hash = this.hash();
+ this.value(value + (qs ? '?' + qs : '') + (hash ? '#' + hash : ''));
+ return this;
+ }
+ return _strict(_value).split('#')[0].split('?')[0];
+ },
+ pathNames: function() {
+ var path = this.path(),
+ names = path.replace(_re, '/').split('/');
+ if (path.substr(0, 1) == '/' || path.length === 0) {
+ names.splice(0, 1);
+ }
+ if (path.substr(path.length - 1, 1) == '/') {
+ names.splice(names.length - 1, 1);
+ }
+ return names;
+ },
+ queryString: function(value) {
+ if (value !== UNDEFINED) {
+ var hash = this.hash();
+ this.value(this.path() + (value ? '?' + value : '') + (hash ? '#' + hash : ''));
+ return this;
+ }
+ var arr = _value.split('?');
+ return arr.slice(1, arr.length).join('?').split('#')[0];
+ },
+ parameter: function(name, value, append) {
+ var i, params;
+ if (value !== UNDEFINED) {
+ var names = this.parameterNames();
+ params = [];
+ value = value === UNDEFINED || value === NULL ? '' : value.toString();
+ for (i = 0; i < names.length; i++) {
+ var n = names[i],
+ v = this.parameter(n);
+ if (typeof v == STRING) {
+ v = [v];
+ }
+ if (n == name) {
+ v = (value === NULL || value === '') ? [] :
+ (append ? v.concat([value]) : [value]);
+ }
+ for (var j = 0; j < v.length; j++) {
+ params.push(n + '=' + v[j]);
+ }
+ }
+ if ($.inArray(name, names) == -1 && value !== NULL && value !== '') {
+ params.push(name + '=' + value);
+ }
+ this.queryString(params.join('&'));
+ return this;
+ }
+ value = this.queryString();
+ if (value) {
+ var r = [];
+ params = value.split('&');
+ for (i = 0; i < params.length; i++) {
+ var p = params[i].split('=');
+ if (p[0] == name) {
+ r.push(p.slice(1).join('='));
+ }
+ }
+ if (r.length !== 0) {
+ return r.length != 1 ? r : r[0];
+ }
+ }
+ },
+ parameterNames: function() {
+ var qs = this.queryString(),
+ names = [];
+ if (qs && qs.indexOf('=') != -1) {
+ var params = qs.split('&');
+ for (var i = 0; i < params.length; i++) {
+ var name = params[i].split('=')[0];
+ if ($.inArray(name, names) == -1) {
+ names.push(name);
+ }
+ }
+ }
+ return names;
+ },
+ hash: function(value) {
+ if (value !== UNDEFINED) {
+ this.value(_value.split('#')[0] + (value ? '#' + value : ''));
+ return this;
+ }
+ var arr = _value.split('#');
+ return arr.slice(1, arr.length).join('#');
+ }
+ };
+ })();
+
+ $.fn.address = function(fn) {
+ var sel;
+ if (typeof fn == 'string') {
+ sel = fn;
+ fn = undefined;
+ }
+ if (!$(this).attr('address')) {
+ var f = function(e) {
+ if (e.shiftKey || e.ctrlKey || e.metaKey || e.which == 2) {
+ return true;
+ }
+ if ($(this).is('a')) {
+ e.preventDefault();
+ var value = fn ? fn.call(this) :
+ /address:/.test($(this).attr('rel')) ? $(this).attr('rel').split('address:')[1].split(' ')[0] :
+ $.address.state() !== undefined && !/^\/?$/.test($.address.state()) ?
+ $(this).attr('href').replace(new RegExp('^(.*' + $.address.state() + '|\\.)'), '') :
+ $(this).attr('href').replace(/^(#\!?|\.)/, '');
+ $.address.value(value);
+ }
+ };
+ $(sel ? sel : this).live('click', f).live('submit', function(e) {
+ if ($(this).is('form')) {
+ e.preventDefault();
+ var action = $(this).attr('action'),
+ value = fn ? fn.call(this) : (action.indexOf('?') != -1 ? action.replace(/&$/, '') : action + '?') +
+ $(this).serialize();
+ $.address.value(value);
+ }
+ }).attr('address', true);
+ }
+ return this;
+ };
+
+})(jQuery);
View
18 courses/overview.php
@@ -47,6 +47,7 @@
// Make database connection
+ $tree = array();
// Display the courses
foreach($categories as $id => $name) {
@@ -54,7 +55,7 @@
$nrcompleted