diff options
Diffstat (limited to '2017')
-rw-r--r-- | 2017/netfilter-netdev2.2/netfilter-keynote.html | 5560 |
1 files changed, 5560 insertions, 0 deletions
diff --git a/2017/netfilter-netdev2.2/netfilter-keynote.html b/2017/netfilter-netdev2.2/netfilter-keynote.html new file mode 100644 index 0000000..59ffa42 --- /dev/null +++ b/2017/netfilter-netdev2.2/netfilter-keynote.html @@ -0,0 +1,5560 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<title>netfilter archeology: 18 years from 2.3 to 4.x</title>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="copyright" content="Copyright © 2017 by Harald Welte (License: CC-BY-SA)" />
+<meta name="generator" content="AsciiDoc 8.6.9" />
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ body.manpage div#toc { display: none; }
+}
+/* slidy.css
+
+ Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+ W3C liability, trademark, document use and software licensing
+ rules apply, see:
+
+ http://www.w3.org/Consortium/Legal/copyright-documents
+ http://www.w3.org/Consortium/Legal/copyright-software
+*/
+
+/*
+ SJR: 2010-09-29: Modified for AsciiDoc slidy backend.
+ Mostly just commented out stuff that is handled by AsciiDoc's CSS files.
+*/
+
+body
+{
+ margin: 0 0 0 0;
+ padding: 0 0 0 0;
+ width: 100%;
+ height: 100%;
+ color: black;
+ background-color: white;
+/*
+ font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
+*/
+ font-size: 14pt;
+}
+
+div.toolbar {
+ position: fixed; z-index: 200;
+ top: auto; bottom: 0; left: 0; right: 0;
+ height: 1.2em; text-align: right;
+ padding-left: 1em;
+ padding-right: 1em;
+ font-size: 60%;
+ color: red;
+ background-color: rgb(240,240,240);
+ border-top: solid 1px rgb(180,180,180);
+}
+
+div.toolbar span.copyright {
+ color: black;
+ margin-left: 0.5em;
+}
+
+div.initial_prompt {
+ position: absolute;
+ z-index: 1000;
+ bottom: 1.2em;
+ width: 90%;
+ background-color: rgb(200,200,200);
+ opacity: 0.35;
+ background-color: rgb(200,200,200, 0.35);
+ cursor: pointer;
+}
+
+div.initial_prompt p.help {
+ text-align: center;
+}
+
+div.initial_prompt p.close {
+ text-align: right;
+ font-style: italic;
+}
+
+div.slidy_toc {
+ position: absolute;
+ z-index: 300;
+ width: 60%;
+ max-width: 30em;
+ height: 30em;
+ overflow: auto;
+ top: auto;
+ right: auto;
+ left: 4em;
+ bottom: 4em;
+ padding: 1em;
+ background: rgb(240,240,240);
+ border-style: solid;
+ border-width: 2px;
+ font-size: 60%;
+}
+
+div.slidy_toc .toc_heading {
+ text-align: center;
+ width: 100%;
+ margin: 0;
+ margin-bottom: 1em;
+ border-bottom-style: solid;
+ border-bottom-color: rgb(180,180,180);
+ border-bottom-width: 1px;
+}
+
+div.slide {
+ z-index: 20;
+ margin: 0 0 0 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ padding-left: 20px;
+ padding-right: 20px;
+ border-width: 0;
+ clear: both;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ line-height: 120%;
+ background-color: transparent;
+}
+
+div.background {
+ display: none;
+}
+
+div.handout {
+ margin-left: 20px;
+ margin-right: 20px;
+}
+
+div.slide.titlepage {
+ text-align: center;
+}
+
+div.slide.titlepage.h1 {
+ padding-top: 10%;
+}
+
+div.slide h1 {
+ padding-left: 0;
+ padding-right: 20pt;
+ padding-top: 4pt;
+ padding-bottom: 4pt;
+ margin-top: 0;
+ margin-left: 0;
+ margin-right: 60pt;
+ margin-bottom: 0.5em;
+ display: block;
+ font-size: 160%;
+ line-height: 1.2em;
+ background: transparent;
+}
+
+div.toc {
+ position: absolute;
+ top: auto;
+ bottom: 4em;
+ left: 4em;
+ right: auto;
+ width: 60%;
+ max-width: 30em;
+ height: 30em;
+ border: solid thin black;
+ padding: 1em;
+ background: rgb(240,240,240);
+ color: black;
+ z-index: 300;
+ overflow: auto;
+ display: block;
+ visibility: visible;
+}
+
+div.toc-heading {
+ width: 100%;
+ border-bottom: solid 1px rgb(180,180,180);
+ margin-bottom: 1em;
+ text-align: center;
+}
+
+/*
+pre {
+ font-size: 80%;
+ font-weight: bold;
+ line-height: 120%;
+ padding-top: 0.2em;
+ padding-bottom: 0.2em;
+ padding-left: 1em;
+ padding-right: 1em;
+ border-style: solid;
+ border-left-width: 1em;
+ border-top-width: thin;
+ border-right-width: thin;
+ border-bottom-width: thin;
+ border-color: #95ABD0;
+ color: #00428C;
+ background-color: #E4E5E7;
+}
+*/
+
+/*
+li pre { margin-left: 0; }
+
+blockquote { font-style: italic }
+
+img { background-color: transparent }
+
+p.copyright { font-size: smaller }
+*/
+
+.center { text-align: center }
+.footnote { font-size: smaller; margin-left: 2em; }
+
+/*
+a img { border-width: 0; border-style: none }
+*/
+
+a:visited { color: navy }
+a:link { color: navy }
+a:hover { color: red; text-decoration: underline }
+a:active { color: red; text-decoration: underline }
+
+a {text-decoration: none}
+.navbar a:link {color: white}
+.navbar a:visited {color: yellow}
+.navbar a:active {color: red}
+.navbar a:hover {color: red}
+
+/*
+ul { list-style-type: square; }
+ul ul { list-style-type: disc; }
+ul ul ul { list-style-type: circle; }
+ul ul ul ul { list-style-type: disc; }
+li { margin-left: 0.5em; margin-top: 0.5em; }
+li li { font-size: 85%; font-style: italic }
+li li li { font-size: 85%; font-style: normal }
+*/
+
+div dt
+{
+ margin-left: 0;
+ margin-top: 1em;
+ margin-bottom: 0.5em;
+ font-weight: bold;
+}
+div dd
+{
+ margin-left: 2em;
+ margin-bottom: 0.5em;
+}
+
+
+/*
+p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
+ margin-left: 1em;
+ margin-right: 1em;
+}
+*/
+
+p.subhead { font-weight: bold; margin-top: 2em; }
+
+.smaller { font-size: smaller }
+.bigger { font-size: 130% }
+
+/*
+td,th { padding: 0.2em }
+*/
+
+ul {
+ margin: 0.5em 1.5em 0.5em 1.5em;
+ padding: 0;
+}
+
+ol {
+ margin: 0.5em 1.5em 0.5em 1.5em;
+ padding: 0;
+}
+
+ul { list-style-type: square; }
+ul ul { list-style-type: disc; }
+ul ul ul { list-style-type: circle; }
+ul ul ul ul { list-style-type: disc; }
+
+/*
+ul li {
+ list-style: square;
+ margin: 0.1em 0em 0.6em 0;
+ padding: 0 0 0 0;
+ line-height: 140%;
+}
+
+ol li {
+ margin: 0.1em 0em 0.6em 1.5em;
+ padding: 0 0 0 0px;
+ line-height: 140%;
+ list-style-type: decimal;
+}
+
+li ul li {
+ font-size: 85%;
+ font-style: italic;
+ list-style-type: disc;
+ background: transparent;
+ padding: 0 0 0 0;
+}
+li li ul li {
+ font-size: 85%;
+ font-style: normal;
+ list-style-type: circle;
+ background: transparent;
+ padding: 0 0 0 0;
+}
+li li li ul li {
+ list-style-type: disc;
+ background: transparent;
+ padding: 0 0 0 0;
+}
+
+li ol li {
+ list-style-type: decimal;
+}
+
+
+li li ol li {
+ list-style-type: decimal;
+}
+*/
+
+/*
+ setting class="outline" on ol or ul makes it behave as an
+ ouline list where blocklevel content in li elements is
+ hidden by default and can be expanded or collapsed with
+ mouse click. Set class="expand" on li to override default
+*/
+
+ol.outline li:hover { cursor: pointer }
+ol.outline li.nofold:hover { cursor: default }
+
+ul.outline li:hover { cursor: pointer }
+ul.outline li.nofold:hover { cursor: default }
+
+ol.outline { list-style:decimal; }
+ol.outline ol { list-style-type:lower-alpha }
+
+ol.outline li.nofold {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.unfolded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.folded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.unfolded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.folded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
+}
+
+ul.outline li.nofold {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.unfolded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.folded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.unfolded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.folded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
+}
+
+/* for slides with class "title" in table of contents */
+a.titleslide { font-weight: bold; font-style: italic }
+
+/*
+ hide images for work around for save as bug
+ where browsers fail to save images used by CSS
+*/
+img.hidden { display: none; visibility: hidden }
+div.initial_prompt { display: none; visibility: hidden }
+
+ div.slide {
+ visibility: visible;
+ position: inherit;
+ }
+ div.handout {
+ border-top-style: solid;
+ border-top-width: thin;
+ border-top-color: black;
+ }
+
+@media screen {
+ .hidden { display: none; visibility: visible }
+
+ div.slide.hidden { display: block; visibility: visible }
+ div.handout.hidden { display: block; visibility: visible }
+ div.background { display: none; visibility: hidden }
+ body.single_slide div.initial_prompt { display: block; visibility: visible }
+ body.single_slide div.background { display: block; visibility: visible }
+ body.single_slide div.background.hidden { display: none; visibility: hidden }
+ body.single_slide .invisible { visibility: hidden }
+ body.single_slide .hidden { display: none; visibility: hidden }
+ body.single_slide div.slide { position: absolute }
+ body.single_slide div.handout { display: none; visibility: hidden }
+}
+
+@media print {
+ .hidden { display: block; visibility: visible }
+
+/*
+ div.slide pre { font-size: 60%; padding-left: 0.5em; }
+*/
+ div.toolbar { display: none; visibility: hidden; }
+ div.slidy_toc { display: none; visibility: hidden; }
+ div.background { display: none; visibility: hidden; }
+ div.slide { page-break-before: always }
+ /* :first-child isn't reliable for print media */
+ div.slide.first-slide { page-break-before: avoid }
+}
+
+
+/* SJR: AsciiDoc slidy backend tweaks */
+
+ol, ul {
+ margin: 0.8em 1.5em 0.8em 1.8em;
+}
+li > ul, li > ol {
+ margin-top: 0.5em;
+}
+
+.outline > li.folded,
+.outline > li.unfolded {
+ color: #527bbd;
+}
+ul > li{ color: #aaa; }
+ul > li > *, ol > li > * { color: black; }
+
+li {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+/* slidy.js
+
+ Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+ W3C liability, trademark, document use and software licensing
+ rules apply, see:
+
+ http://www.w3.org/Consortium/Legal/copyright-documents
+ http://www.w3.org/Consortium/Legal/copyright-software
+*/
+
+// the slidy object implementation
+var w3c_slidy = {
+ // classify which kind of browser we're running under
+ ns_pos: (typeof window.pageYOffset!='undefined'),
+ khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false),
+ opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false),
+ ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false),
+ iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false),
+ ie: (typeof document.all != "undefined" && !this.opera),
+ ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1),
+ ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1),
+ ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1),
+ ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1),
+ keyboardless: (this.ipad || this.iphone),
+
+ // are we running as XHTML? (doesn't work on Opera)
+ is_xhtml: /xml/.test(document.contentType),
+
+ slide_number: 0, // integer slide count: 0, 1, 2, ...
+ slide_number_element: null, // element containing slide number
+ slides: [], // set to array of slide div's
+ notes: [], // set to array of handout div's
+ backgrounds: [], // set to array of background div's
+ toolbar: null, // element containing toolbar
+ title: null, // document title
+ last_shown: null, // last incrementally shown item
+ eos: null, // span element for end of slide indicator
+ toc: null, // table of contents
+ outline: null, // outline element with the focus
+ selected_text_len: 0, // length of drag selection on document
+ view_all: 0, // 1 to view all slides + handouts
+ want_toolbar: true, // user preference to show/hide toolbar
+ mouse_click_enabled: true, // enables left click for next slide
+ scroll_hack: 0, // IE work around for position: fixed
+ disable_slide_click: false, // used by clicked anchors
+
+ lang: "en", // updated to language specified by html file
+
+ help_anchor: null, // used for keyboard focus hack in showToolbar()
+ help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html",
+ help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " +
+ "or Pg Up and Pg Dn. Use S and B to change font size.",
+
+ size_index: 0,
+ size_adjustment: 0,
+ sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
+ "22pt", "24pt", "26pt", "28pt", "30pt", "32pt"),
+
+ // needed for efficient resizing
+ last_width: 0,
+ last_height: 0,
+
+
+ // Needed for cross browser support for relative width/height on
+ // object elements. The work around is to save width/height attributes
+ // and then to recompute absolute width/height dimensions on resizing
+ objects: [],
+
+ // attach initialiation event handlers
+ set_up: function () {
+ var init = function() { w3c_slidy.init(); };
+ if (typeof window.addEventListener != "undefined")
+ window.addEventListener("load", init, false);
+ else
+ window.attachEvent("onload", init);
+ },
+
+ hide_slides: function () {
+ if (document.body && !w3c_slidy.initialized)
+ document.body.style.visibility = "hidden";
+ else
+ setTimeout(w3c_slidy.hide_slides, 50);
+ },
+
+ // hack to persuade IE to compute correct document height
+ // as needed for simulating fixed positioning of toolbar
+ ie_hack: function () {
+ window.resizeBy(0,-1);
+ window.resizeBy(0, 1);
+ },
+
+ init: function () {
+ //alert("slidy starting test 10");
+ document.body.style.visibility = "visible";
+ w3c_slidy_i18n.init();
+ this.add_toolbar();
+ this.wrap_implicit_slides();
+ this.collect_slides();
+ this.collect_notes();
+ this.collect_backgrounds();
+ this.objects = document.body.getElementsByTagName("object");
+ this.patch_anchors();
+ this.slide_number = this.find_slide_number(location.href);
+ window.offscreenbuffering = true;
+ this.size_adjustment = this.find_size_adjust();
+ this.time_left = this.find_duration();
+ this.hide_image_toolbar(); // suppress IE image toolbar popup
+ this.init_outliner(); // activate fold/unfold support
+ this.title = document.title;
+
+ // work around for opera bug
+ this.is_xhtml = (document.body.tagName == "BODY" ? false : true);
+
+ if (this.slides.length > 0)
+ {
+ var slide = this.slides[this.slide_number];
+
+ if (this.slide_number > 0)
+ {
+ this.set_visibility_all_incremental("visible");
+ this.last_shown = this.previous_incremental_item(null);
+ this.set_eos_status(true);
+ }
+ else
+ {
+ this.last_shown = null;
+ this.set_visibility_all_incremental("hidden");
+ this.set_eos_status(!this.next_incremental_item(this.last_shown));
+ }
+
+ this.set_location();
+ this.add_class(this.slides[0], "first-slide");
+ w3c_slidy.show_slide(slide);
+ }
+
+ this.toc = this.table_of_contents();
+
+ this.add_initial_prompt();
+
+ // bind event handlers without interfering with custom page scripts
+ // Tap events behave too weirdly to support clicks reliably on
+ // iPhone and iPad, so exclude these from click handler
+
+ if (!this.keyboardless)
+ this.add_listener(document.body, "click", this.mouse_button_click);
+
+ this.add_listener(document, "keydown", this.key_down);
+ this.add_listener(document, "keypress", this.key_press);
+ this.add_listener(window, "resize", this.resized);
+ this.add_listener(window, "scroll", this.scrolled);
+ this.add_listener(window, "unload", this.unloaded);
+
+ if (!document.body.onclick)
+ document.body.onclick = function () { };
+
+ this.single_slide_view();
+
+ //this.set_location();
+
+ this.resized();
+
+ if (this.ie7)
+ setTimeout(w3c_slidy.ie_hack, 100);
+
+ this.show_toolbar();
+
+ // for back button detection
+ setInterval(function () { w3c_slidy.check_location(); }, 200);
+ w3c_slidy.initialized = true;
+ },
+
+ // create div element with links to each slide
+ table_of_contents: function () {
+ var toc = this.create_element("div");
+ this.add_class(toc, "slidy_toc hidden");
+ //toc.setAttribute("tabindex", "0");
+
+ var heading = this.create_element("div");
+ this.add_class(heading, "toc-heading");
+ heading.innerHTML = "Table of Contents".localize();
+
+ toc.appendChild(heading);
+ var previous = null;
+
+ for (var i = 0; i < this.slides.length; ++i)
+ {
+ var title = this.has_class(this.slides[i], "title");
+ var num = document.createTextNode((i + 1) + ". ");
+
+ toc.appendChild(num);
+
+ var a = this.create_element("a");
+ a.setAttribute("href", "#(" + (i+1) + ")");
+
+ if (title)
+ this.add_class(a, "titleslide");
+
+ var name = document.createTextNode(this.slide_name(i));
+ a.appendChild(name);
+ a.onclick = w3c_slidy.toc_click;
+ a.onkeydown = w3c_slidy.toc_keydown;
+ a.previous = previous;
+
+ if (previous)
+ previous.next = a;
+
+ toc.appendChild(a);
+
+ if (i == 0)
+ toc.first = a;
+
+ if (i < this.slides.length - 1)
+ {
+ var br = this.create_element("br");
+ toc.appendChild(br);
+ }
+
+ previous = a;
+ }
+
+ toc.focus = function () {
+ if (this.first)
+ this.first.focus();
+ }
+
+ toc.onmouseup = w3c_slidy.mouse_button_up;
+
+ toc.onclick = function (e) {
+ e||(e=window.event);
+
+ if (w3c_slidy.selected_text_len <= 0)
+ w3c_slidy.hide_table_of_contents();
+
+ w3c_slidy.stop_propagation(e);
+
+ if (e.cancel != undefined)
+ e.cancel = true;
+
+ if (e.returnValue != undefined)
+ e.returnValue = false;
+
+ return false;
+ };
+
+ document.body.insertBefore(toc, document.body.firstChild);
+ return toc;
+ },
+
+ is_shown_toc: function () {
+ return !w3c_slidy.has_class(w3c_slidy.toc, "hidden");
+ },
+
+ show_table_of_contents: function () {
+ w3c_slidy.remove_class(w3c_slidy.toc, "hidden");
+ var toc = w3c_slidy.toc;
+ toc.focus();
+
+ if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0)
+ setTimeout(w3c_slidy.ie_hack, 100);
+ },
+
+ hide_table_of_contents: function () {
+ w3c_slidy.add_class(w3c_slidy.toc, "hidden");
+
+ if (!w3c_slidy.opera)
+ w3c_slidy.help_anchor.focus();
+ },
+
+ toggle_table_of_contents: function () {
+ if (w3c_slidy.is_shown_toc())
+ w3c_slidy.hide_table_of_contents();
+ else
+ w3c_slidy.show_table_of_contents();
+ },
+
+ // called on clicking toc entry
+ toc_click: function (e) {
+ if (!e)
+ e = window.event;
+
+ var target = w3c_slidy.get_target(e);
+
+ if (target && target.nodeType == 1)
+ {
+ var uri = target.getAttribute("href");
+
+ if (uri)
+ {
+ //alert("going to " + uri);
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.last_shown = null;
+ w3c_slidy.set_location();
+ w3c_slidy.set_visibility_all_incremental("hidden");
+ w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
+ w3c_slidy.show_slide(slide);
+ //target.focus();
+
+ try
+ {
+ if (!w3c_slidy.opera)
+ w3c_slidy.help_anchor.focus();
+ }
+ catch (e)
+ {
+ }
+ }
+ }
+
+ w3c_slidy.hide_table_of_contents(e);
+ if (w3c_slidy.ie7) w3c_slidy.ie_hack();
+ w3c_slidy.stop_propagation(e);
+ return w3c_slidy.cancel(e);
+ },
+
+ // called onkeydown for toc entry
+ toc_keydown: function (event) {
+ var key;
+
+ if (!event)
+ var event = window.event;
+
+ // kludge around NS/IE differences
+ if (window.event)
+ key = window.event.keyCode;
+ else if (event.which)
+ key = event.which;
+ else
+ return true; // Yikes! unknown browser
+
+ // ignore event if key value is zero
+ // as for alt on Opera and Konqueror
+ if (!key)
+ return true;
+
+ // check for concurrent control/command/alt key
+ // but are these only present on mouse events?
+
+ if (event.ctrlKey || event.altKey)
+ return true;
+
+ if (key == 13)
+ {
+ var uri = this.getAttribute("href");
+
+ if (uri)
+ {
+ //alert("going to " + uri);
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.last_shown = null;
+ w3c_slidy.set_location();
+ w3c_slidy.set_visibility_all_incremental("hidden");
+ w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
+ w3c_slidy.show_slide(slide);
+ //target.focus();
+
+ try
+ {
+ if (!w3c_slidy.opera)
+ w3c_slidy.help_anchor.focus();
+ }
+ catch (e)
+ {
+ }
+ }
+
+ w3c_slidy.hide_table_of_contents();
+
+ if (self.ie7)
+ w3c_slidy.ie_hack();
+
+ return w3c_slidy.cancel(event);
+ }
+
+ if (key == 40 && this.next)
+ {
+ this.next.focus();
+ return w3c_slidy.cancel(event);
+ }
+
+ if (key == 38 && this.previous)
+ {
+ this.previous.focus();
+ return w3c_slidy.cancel(event);
+ }
+
+ return true;
+ },
+
+
+ // ### OBSOLETE ###
+ before_print: function () {
+ this.show_all_slides();
+ this.hide_toolbar();
+ alert("before print");
+ },
+
+ // ### OBSOLETE ###
+ after_print: function () {
+ if (!this.view_all)
+ {
+ this.single_slide_view();
+ this.show_toolbar();
+ }
+ alert("after print");
+ },
+
+ // ### OBSOLETE ###
+ print_slides: function () {
+ this.before_print();
+ window.print();
+ this.after_print();
+ },
+
+ // ### OBSOLETE ?? ###
+ toggle_view: function () {
+ if (this.view_all)
+ {
+ this.single_slide_view();
+ this.show_toolbar();
+ this.view_all = 0;
+ }
+ else
+ {
+ this.show_all_slides();
+ this.hide_toolbar();
+ this.view_all = 1;
+ }
+ },
+
+ // prepare for printing ### OBSOLETE ###
+ show_all_slides: function () {
+ this.remove_class(document.body, "single_slide");
+ this.set_visibility_all_incremental("visible");
+ },
+
+ // restore after printing ### OBSOLETE ###
+ single_slide_view: function () {
+ this.add_class(document.body, "single_slide");
+ this.set_visibility_all_incremental("visible");
+ this.last_shown = this.previous_incremental_item(null);
+ },
+
+ // suppress IE's image toolbar pop up
+ hide_image_toolbar: function () {
+ if (!this.ns_pos)
+ {
+ var images = document.getElementsByTagName("IMG");
+
+ for (var i = 0; i < images.length; ++i)
+ images[i].setAttribute("galleryimg", "no");
+ }
+ },
+
+ unloaded: function (e) {
+ //alert("unloaded");
+ },
+
+ // Safari and Konqueror don't yet support getComputedStyle()
+ // and they always reload page when location.href is updated
+ is_KHTML: function () {
+ var agent = navigator.userAgent;
+ return (agent.indexOf("KHTML") >= 0 ? true : false);
+ },
+
+ // find slide name from first h1 element
+ // default to document title + slide number
+ slide_name: function (index) {
+ var name = null;
+ var slide = this.slides[index];
+
+ var heading = this.find_heading(slide);
+
+ if (heading)
+ name = this.extract_text(heading);
+
+ if (!name)
+ name = this.title + "(" + (index + 1) + ")";
+
+ name.replace(/\&/g, "&");
+ name.replace(/\</g, "<");
+ name.replace(/\>/g, ">");
+
+ return name;
+ },
+
+ // find first h1 element in DOM tree
+ find_heading: function (node) {
+ if (!node || node.nodeType != 1)
+ return null;
+
+ if (node.nodeName == "H1" || node.nodeName == "h1")
+ return node;
+
+ var child = node.firstChild;
+
+ while (child)
+ {
+ node = this.find_heading(child);
+
+ if (node)
+ return node;
+
+ child = child.nextSibling;
+ }
+
+ return null;
+ },
+
+ // recursively extract text from DOM tree
+ extract_text: function (node) {
+ if (!node)
+ return "";
+
+ // text nodes
+ if (node.nodeType == 3)
+ return node.nodeValue;
+
+ // elements
+ if (node.nodeType == 1)
+ {
+ node = node.firstChild;
+ var text = "";
+
+ while (node)
+ {
+ text = text + this.extract_text(node);
+ node = node.nextSibling;
+ }
+
+ return text;
+ }
+
+ return "";
+ },
+
+ // find copyright text from meta element
+ find_copyright: function () {
+ var name, content;
+ var meta = document.getElementsByTagName("meta");
+
+ for (var i = 0; i < meta.length; ++i)
+ {
+ name = meta[i].getAttribute("name");
+ content = meta[i].getAttribute("content");
+
+ if (name == "copyright")
+ return content;
+ }
+
+ return null;
+ },
+
+ find_size_adjust: function () {
+ var name, content, offset;
+ var meta = document.getElementsByTagName("meta");
+
+ for (var i = 0; i < meta.length; ++i)
+ {
+ name = meta[i].getAttribute("name");
+ content = meta[i].getAttribute("content");
+
+ if (name == "font-size-adjustment")
+ return 1 * content;
+ }
+
+ return 1;
+ },
+
+ // <meta name="duration" content="20" /> for 20 minutes
+ find_duration: function () {
+ var name, content, offset;
+ var meta = document.getElementsByTagName("meta");
+
+ for (var i = 0; i < meta.length; ++i)
+ {
+ name = meta[i].getAttribute("name");
+ content = meta[i].getAttribute("content");
+
+ if (name == "duration")
+ return 60000 * content;
+ }
+
+ return null;
+ },
+
+ replace_by_non_breaking_space: function (str) {
+ for (var i = 0; i < str.length; ++i)
+ str[i] = 160;
+ },
+
+ // ### CHECK ME ### is use of "li" okay for text/html?
+ // for XHTML do we also need to specify namespace?
+ init_outliner: function () {
+ var items = document.getElementsByTagName("li");
+
+ for (var i = 0; i < items.length; ++i)
+ {
+ var target = items[i];
+
+ if (!this.has_class(target.parentNode, "outline"))
+ continue;
+
+ target.onclick = this.outline_click;
+/* ### more work needed for IE6
+ if (!this.ns_pos)
+ {
+ target.onmouseover = this.hover_outline;
+ target.onmouseout = this.unhover_outline;
+ }
+*/
+ if (this.foldable(target))
+ {
+ target.foldable = true;
+ target.onfocus = function () {w3c_slidy.outline = this;};
+ target.onblur = function () {w3c_slidy.outline = null;};
+
+ if (!target.getAttribute("tabindex"))
+ target.setAttribute("tabindex", "0");
+
+ if (this.has_class(target, "expand"))
+ this.unfold(target);
+ else
+ this.fold(target);
+ }
+ else
+ {
+ this.add_class(target, "nofold");
+ target.visible = true;
+ target.foldable = false;
+ }
+ }
+ },
+
+ foldable: function (item) {
+ if (!item || item.nodeType != 1)
+ return false;
+
+ var node = item.firstChild;
+
+ while (node)
+ {
+ if (node.nodeType == 1 && this.is_block(node))
+ return true;
+
+ node = node.nextSibling;
+ }
+
+ return false;
+ },
+
+ // ### CHECK ME ### switch to add/remove "hidden" class
+ fold: function (item) {
+ if (item)
+ {
+ this.remove_class(item, "unfolded");
+ this.add_class(item, "folded");
+ }
+
+ var node = item ? item.firstChild : null;
+
+ while (node)
+ {
+ if (node.nodeType == 1 && this.is_block(node)) // element
+ {
+ w3c_slidy.add_class(node, "hidden");
+ }
+
+ node = node.nextSibling;
+ }
+
+ item.visible = false;
+ },
+
+ // ### CHECK ME ### switch to add/remove "hidden" class
+ unfold: function (item) {
+ if (item)
+ {
+ this.add_class(item, "unfolded");
+ this.remove_class(item, "folded");
+ }
+
+ var node = item ? item.firstChild : null;
+
+ while (node)
+ {
+ if (node.nodeType == 1 && this.is_block(node)) // element
+ {
+ w3c_slidy.remove_class(node, "hidden");
+ }
+
+ node = node.nextSibling;
+ }
+
+ item.visible = true;
+ },
+
+ outline_click: function (e) {
+ if (!e)
+ e = window.event;
+
+ var rightclick = false;
+ var target = w3c_slidy.get_target(e);
+
+ while (target && target.visible == undefined)
+ target = target.parentNode;
+
+ if (!target)
+ return true;
+
+ if (e.which)
+ rightclick = (e.which == 3);
+ else if (e.button)
+ rightclick = (e.button == 2);
+
+ if (!rightclick && target.visible != undefined)
+ {
+ if (target.foldable)
+ {
+ if (target.visible)
+ w3c_slidy.fold(target);
+ else
+ w3c_slidy.unfold(target);
+ }
+
+ w3c_slidy.stop_propagation(e);
+ e.cancel = true;
+ e.returnValue = false;
+ }
+
+ return false;
+ },
+
+ add_initial_prompt: function () {
+ var prompt = this.create_element("div");
+ prompt.setAttribute("class", "initial_prompt");
+
+ var p1 = this.create_element("p");
+ prompt.appendChild(p1);
+ p1.setAttribute("class", "help");
+
+ if (this.keyboardless)
+ p1.innerHTML = "Tap footer to move to next slide";
+ else
+ p1.innerHTML = "Space or Right Arrow to move to next " +
+ "slide, click help below for more details";
+
+ this.add_listener(prompt, "click", function (e) {
+ document.body.removeChild(prompt);
+ w3c_slidy.stop_propagation(e);
+
+ if (e.cancel != undefined)
+ e.cancel = true;
+
+ if (e.returnValue != undefined)
+ e.returnValue = false;
+
+ return false;
+ });
+
+ document.body.appendChild(prompt);
+ this.initial_prompt = prompt;
+ setTimeout(function() {document.body.removeChild(prompt);}, 5000);
+ },
+
+ add_toolbar: function () {
+ var counter, page;
+
+ this.toolbar = this.create_element("div");
+ this.toolbar.setAttribute("class", "toolbar");
+
+ // a reasonably behaved browser
+ if (this.ns_pos || !this.ie6)
+ {
+ var right = this.create_element("div");
+ right.setAttribute("style", "float: right; text-align: right");
+
+ counter = this.create_element("span")
+ counter.innerHTML = "slide".localize() + " n/m";
+ right.appendChild(counter);
+ this.toolbar.appendChild(right);
+
+ var left = this.create_element("div");
+ left.setAttribute("style", "text-align: left");
+
+ // global end of slide indicator
+ this.eos = this.create_element("span");
+ this.eos.innerHTML = "* ";
+ left.appendChild(this.eos);
+
+ var help = this.create_element("a");
+ help.setAttribute("href", this.help_page);
+ help.setAttribute("title", this.help_text.localize());
+ help.innerHTML = "help?".localize();
+ left.appendChild(help);
+ this.help_anchor = help; // save for focus hack
+
+ var gap1 = document.createTextNode(" ");
+ left.appendChild(gap1);
+
+ var contents = this.create_element("a");
+ contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()");
+ contents.setAttribute("title", "table of contents".localize());
+ contents.innerHTML = "contents?".localize();
+ left.appendChild(contents);
+
+ var gap2 = document.createTextNode(" ");
+ left.appendChild(gap2);
+
+ var copyright = this.find_copyright();
+
+ if (copyright)
+ {
+ var span = this.create_element("span");
+ span.className = "copyright";
+ span.innerHTML = copyright;
+ left.appendChild(span);
+ }
+
+ this.toolbar.setAttribute("tabindex", "0");
+ this.toolbar.appendChild(left);
+ }
+ else // IE6 so need to work around its poor CSS support
+ {
+ this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute");
+ this.toolbar.style.zIndex = "200";
+ this.toolbar.style.width = "99.9%";
+ this.toolbar.style.height = "1.2em";
+ this.toolbar.style.top = "auto";
+ this.toolbar.style.bottom = "0";
+ this.toolbar.style.left = "0";
+ this.toolbar.style.right = "0";
+ this.toolbar.style.textAlign = "left";
+ this.toolbar.style.fontSize = "60%";
+ this.toolbar.style.color = "red";
+ this.toolbar.borderWidth = 0;
+ this.toolbar.className = "toolbar";
+ this.toolbar.style.background = "rgb(240,240,240)";
+
+ // would like to have help text left aligned
+ // and page counter right aligned, floating
+ // div's don't work, so instead use nested
+ // absolutely positioned div's.
+
+ var sp = this.create_element("span");
+ sp.innerHTML = " * ";
+ this.toolbar.appendChild(sp);
+ this.eos = sp; // end of slide indicator
+
+ var help = this.create_element("a");
+ help.setAttribute("href", this.help_page);
+ help.setAttribute("title", this.help_text.localize());
+ help.innerHTML = "help?".localize();
+ this.toolbar.appendChild(help);
+ this.help_anchor = help; // save for focus hack
+
+ var gap1 = document.createTextNode(" ");
+ this.toolbar.appendChild(gap1);
+
+ var contents = this.create_element("a");
+ contents.setAttribute("href", "javascript:toggleTableOfContents()");
+ contents.setAttribute("title", "table of contents".localize());
+ contents.innerHTML = "contents?".localize();
+ this.toolbar.appendChild(contents);
+
+ var gap2 = document.createTextNode(" ");
+ this.toolbar.appendChild(gap2);
+
+ var copyright = this.find_copyright();
+
+ if (copyright)
+ {
+ var span = this.create_element("span");
+ span.innerHTML = copyright;
+ span.style.color = "black";
+ span.style.marginLeft = "0.5em";
+ this.toolbar.appendChild(span);
+ }
+
+ counter = this.create_element("div")
+ counter.style.position = "absolute";
+ counter.style.width = "auto"; //"20%";
+ counter.style.height = "1.2em";
+ counter.style.top = "auto";
+ counter.style.bottom = 0;
+ counter.style.right = "0";
+ counter.style.textAlign = "right";
+ counter.style.color = "red";
+ counter.style.background = "rgb(240,240,240)";
+
+ counter.innerHTML = "slide".localize() + " n/m";
+ this.toolbar.appendChild(counter);
+ }
+
+ // ensure that click isn't passed through to the page
+ this.toolbar.onclick =
+ function (e) {
+ if (!e)
+ e = window.event;
+
+ var target = e.target;
+
+ if (!target && e.srcElement)
+ target = e.srcElement;
+
+ // work around Safari bug
+ if (target && target.nodeType == 3)
+ target = target.parentNode;
+
+ w3c_slidy.stop_propagation(e);
+
+ if (target && target.nodeName.toLowerCase() != "a")
+ w3c_slidy.mouse_button_click(e);
+ };
+
+ this.slide_number_element = counter;
+ this.set_eos_status(false);
+ document.body.appendChild(this.toolbar);
+ },
+
+ // wysiwyg editors make it hard to use div elements
+ // e.g. amaya loses the div when you copy and paste
+ // this function wraps div elements around implicit
+ // slides which start with an h1 element and continue
+ // up to the next heading or div element
+ wrap_implicit_slides: function () {
+ var i, heading, node, next, div;
+ var headings = document.getElementsByTagName("h1");
+
+ if (!headings)
+ return;
+
+ for (i = 0; i < headings.length; ++i)
+ {
+ heading = headings[i];
+
+ if (heading.parentNode != document.body)
+ continue;
+
+ node = heading.nextSibling;
+
+ div = document.createElement("div");
+ this.add_class(div, "slide");
+ document.body.replaceChild(div, heading);
+ div.appendChild(heading);
+
+ while (node)
+ {
+ if (node.nodeType == 1 && // an element
+ (node.nodeName == "H1" ||
+ node.nodeName == "h1" ||
+ node.nodeName == "DIV" ||
+ node.nodeName == "div"))
+ break;
+
+ next = node.nextSibling;
+ node = document.body.removeChild(node);
+ div.appendChild(node);
+ node = next;
+ }
+ }
+ },
+
+// return new array of all slides
+ collect_slides: function () {
+ var slides = new Array();
+ var divs = document.body.getElementsByTagName("div");
+
+ for (var i = 0; i < divs.length; ++i)
+ {
+ div = divs.item(i);
+
+ if (this.has_class(div, "slide"))
+ {
+ // add slide to collection
+ slides[slides.length] = div;
+
+ // hide each slide as it is found
+ this.add_class(div, "hidden");
+
+ // add dummy <br/> at end for scrolling hack
+ var node1 = document.createElement("br");
+ div.appendChild(node1);
+ var node2 = document.createElement("br");
+ div.appendChild(node2);
+ }
+ else if (this.has_class(div, "background"))
+ { // work around for Firefox SVG reload bug
+ // which otherwise replaces 1st SVG graphic with 2nd
+ div.style.display = "block";
+ }
+ }
+
+ this.slides = slides;
+ },
+
+ // return new array of all <div class="handout">
+ collect_notes: function () {
+ var notes = new Array();
+ var divs = document.body.getElementsByTagName("div");
+
+ for (var i = 0; i < divs.length; ++i)
+ {
+ div = divs.item(i);
+
+ if (this.has_class(div, "handout"))
+ {
+ // add note to collection
+ notes[notes.length] = div;
+
+ // and hide it
+ this.add_class(div, "hidden");
+ }
+ }
+
+ this.notes = notes;
+ },
+
+ // return new array of all <div class="background">
+ // including named backgrounds e.g. class="background titlepage"
+ collect_backgrounds: function () {
+ var backgrounds = new Array();
+ var divs = document.body.getElementsByTagName("div");
+
+ for (var i = 0; i < divs.length; ++i)
+ {
+ div = divs.item(i);
+
+ if (this.has_class(div, "background"))
+ {
+ // add background to collection
+ backgrounds[backgrounds.length] = div;
+
+ // and hide it
+ this.add_class(div, "hidden");
+ }
+ }
+
+ this.backgrounds = backgrounds;
+ },
+
+ // set click handlers on all anchors
+ patch_anchors: function () {
+ var self = w3c_slidy;
+ var handler = function (event) {
+ // compare this.href with location.href
+ // for link to another slide in this doc
+
+ if (self.page_address(this.href) == self.page_address(location.href))
+ {
+ // yes, so find new slide number
+ var newslidenum = self.find_slide_number(this.href);
+
+ if (newslidenum != self.slide_number)
+ {
+ var slide = self.slides[self.slide_number];
+ self.hide_slide(slide);
+ self.slide_number = newslidenum;
+ slide = self.slides[self.slide_number];
+ self.show_slide(slide);
+ self.set_location();
+ }
+ }
+ else if (this.target == null)
+ location.href = this.href;
+
+ this.blur();
+ self.disable_slide_click = true;
+ };
+
+ var anchors = document.body.getElementsByTagName("a");
+
+ for (var i = 0; i < anchors.length; ++i)
+ {
+ if (window.addEventListener)
+ anchors[i].addEventListener("click", handler, false);
+ else
+ anchors[i].attachEvent("onclick", handler);
+ }
+ },
+
+ // ### CHECK ME ### see which functions are invoked via setTimeout
+ // either directly or indirectly for use of w3c_slidy vs this
+ show_slide_number: function () {
+ var timer = w3c_slidy.get_timer();
+ w3c_slidy.slide_number_element.innerHTML = timer + "slide".localize() + " " +
+ (w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length;
+ },
+
+ // every 200mS check if the location has been changed as a
+ // result of the user activating the Back button/menu item
+ // doesn't work for Opera < 9.5
+ check_location: function () {
+ var hash = location.hash;
+
+ if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#"))
+ w3c_slidy.goto_slide(0);
+ else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")")
+ {
+ var num = parseInt(location.hash.substr(2));
+
+ if (!isNaN(num))
+ w3c_slidy.goto_slide(num-1);
+ }
+
+ if (w3c_slidy.time_left && w3c_slidy.slide_number > 0)
+ {
+ w3c_slidy.show_slide_number();
+
+ if (w3c_slidy.time_left > 0)
+ w3c_slidy.time_left -= 200;
+ }
+ },
+
+ get_timer: function () {
+ var timer = "";
+ if (w3c_slidy.time_left)
+ {
+ var mins, secs;
+ secs = Math.floor(w3c_slidy.time_left/1000);
+ mins = Math.floor(secs / 60);
+ secs = secs % 60;
+ timer = (mins ? mins+"m" : "") + secs + "s ";
+ }
+
+ return timer;
+ },
+
+ // this doesn't push location onto history stack for IE
+ // for which a hidden iframe hack is needed: load page into
+ // the iframe with script that set's parent's location.hash
+ // but that won't work for standalone use unless we can
+ // create the page dynamically via a javascript: URL
+ set_location: function () {
+ var uri = w3c_slidy.page_address(location.href);
+ var hash = "#(" + (w3c_slidy.slide_number+1) + ")";
+
+ if (w3c_slidy.slide_number >= 0)
+ uri = uri + hash;
+
+ if (w3c_slidy.ie && !w3c_slidy.ie8)
+ w3c_slidy.push_hash(hash);
+
+ if (uri != location.href) // && !khtml
+ location.href = uri;
+
+ if (this.khtml)
+ hash = "(" + (w3c_slidy.slide_number+1) + ")";
+
+ if (!this.ie && location.hash != hash && location.hash != "")
+ location.hash = hash;
+
+ document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
+ w3c_slidy.show_slide_number();
+ },
+
+ page_address: function (uri) {
+ var i = uri.indexOf("#");
+
+ if (i < 0)
+ i = uri.indexOf("%23");
+
+ // check if anchor is entire page
+
+ if (i < 0)
+ return uri; // yes
+
+ return uri.substr(0, i);
+ },
+
+ // only used for IE6 and IE7
+ on_frame_loaded: function (hash) {
+ location.hash = hash;
+ var uri = w3c_slidy.page_address(location.href);
+ location.href = uri + hash;
+ },
+
+ // history hack with thanks to Bertrand Le Roy
+ push_hash: function (hash) {
+ if (hash == "") hash = "#(1)";
+ window.location.hash = hash;
+
+ var doc = document.getElementById("historyFrame").contentWindow.document;
+ doc.open("javascript:'<html></html>'");
+ // PWL modified this string literal to break the close script tag
+ // which otherwise gets parsed when incorporated
+ doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+
+ (hash) + "');</" + "script></head><body>hello mum</body></html>");
+ doc.close();
+ },
+
+ // find current slide based upon location
+ // first find target anchor and then look
+ // for associated div element enclosing it
+ // finally map that to slide number
+ find_slide_number: function (uri) {
+ // first get anchor from page location
+
+ var i = uri.indexOf("#");
+
+ // check if anchor is entire page
+ if (i < 0)
+ return 0; // yes
+
+ var anchor = unescape(uri.substr(i+1));
+
+ // now use anchor as XML ID to find target
+ var target = document.getElementById(anchor);
+
+ if (!target)
+ {
+ // does anchor look like "(2)" for slide 2 ??
+ // where first slide is (1)
+ var re = /\((\d)+\)/;
+
+ if (anchor.match(re))
+ {
+ var num = parseInt(anchor.substring(1, anchor.length-1));
+
+ if (num > this.slides.length)
+ num = 1;
+
+ if (--num < 0)
+ num = 0;
+
+ return num;
+ }
+
+ // accept [2] for backwards compatibility
+ re = /\[(\d)+\]/;
+
+ if (anchor.match(re))
+ {
+ var num = parseInt(anchor.substring(1, anchor.length-1));
+
+ if (num > this.slides.length)
+ num = 1;
+
+ if (--num < 0)
+ num = 0;
+
+ return num;
+ }
+
+ // oh dear unknown anchor
+ return 0;
+ }
+
+ // search for enclosing slide
+
+ while (true)
+ {
+ // browser coerces html elements to uppercase!
+ if (target.nodeName.toLowerCase() == "div" &&
+ this.has_class(target, "slide"))
+ {
+ // found the slide element
+ break;
+ }
+
+ // otherwise try parent element if any
+
+ target = target.parentNode;
+
+ if (!target)
+ {
+ return 0; // no luck!
+ }
+ };
+
+ for (i = 0; i < slides.length; ++i)
+ {
+ if (slides[i] == target)
+ return i; // success
+ }
+
+ // oh dear still no luck
+ return 0;
+ },
+
+ previous_slide: function (incremental) {
+ if (!w3c_slidy.view_all)
+ {
+ var slide;
+
+ if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null)
+ {
+ w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown);
+ w3c_slidy.set_eos_status(false);
+ }
+ else if (w3c_slidy.slide_number > 0)
+ {
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+
+ w3c_slidy.slide_number = w3c_slidy.slide_number - 1;
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.set_visibility_all_incremental("visible");
+ w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
+ w3c_slidy.set_eos_status(true);
+ w3c_slidy.show_slide(slide);
+ }
+
+ w3c_slidy.set_location();
+
+ if (!w3c_slidy.ns_pos)
+ w3c_slidy.refresh_toolbar(200);
+ }
+ },
+
+ next_slide: function (incremental) {
+ if (!w3c_slidy.view_all)
+ {
+ var slide, last = w3c_slidy.last_shown;
+
+ if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1)
+ w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown);
+
+ if ((!incremental || w3c_slidy.last_shown == null) &&
+ w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
+ {
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+
+ w3c_slidy.slide_number = w3c_slidy.slide_number + 1;
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.last_shown = null;
+ w3c_slidy.set_visibility_all_incremental("hidden");
+ w3c_slidy.show_slide(slide);
+ }
+ else if (!w3c_slidy.last_shown)
+ {
+ if (last && incremental)
+ w3c_slidy.last_shown = last;
+ }
+
+ w3c_slidy.set_location();
+
+ w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
+
+ if (!w3c_slidy.ns_pos)
+ w3c_slidy.refresh_toolbar(200);
+ }
+ },
+
+ // to first slide with nothing revealed
+ // i.e. state at start of presentation
+ first_slide: function () {
+ if (!w3c_slidy.view_all)
+ {
+ var slide;
+
+ if (w3c_slidy.slide_number != 0)
+ {
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+
+ w3c_slidy.slide_number = 0;
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.last_shown = null;
+ w3c_slidy.set_visibility_all_incremental("hidden");
+ w3c_slidy.show_slide(slide);
+ }
+
+ w3c_slidy.set_eos_status(
+ !w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
+ w3c_slidy.set_location();
+ }
+ },
+
+ // goto last slide with everything revealed
+ // i.e. state at end of presentation
+ last_slide: function () {
+ if (!w3c_slidy.view_all)
+ {
+ var slide;
+
+ w3c_slidy.last_shown = null; //revealNextItem(lastShown);
+
+ if (w3c_slidy.last_shown == null &&
+ w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
+ {
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.slide_number = w3c_slidy.slides.length - 1;
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.set_visibility_all_incremental("visible");
+ w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
+
+ w3c_slidy.show_slide(slide);
+ }
+ else
+ {
+ w3c_slidy.set_visibility_all_incremental("visible");
+ w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
+ }
+
+ w3c_slidy.set_eos_status(true);
+ w3c_slidy.set_location();
+ }
+ },
+
+
+ // ### check this and consider add/remove class
+ set_eos_status: function (state) {
+ if (this.eos)
+ this.eos.style.color = (state ? "rgb(240,240,240)" : "red");
+ },
+
+ // first slide is 0
+ goto_slide: function (num) {
+ //alert("going to slide " + (num+1));
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.slide_number = num;
+ slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.last_shown = null;
+ w3c_slidy.set_visibility_all_incremental("hidden");
+ w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
+ document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
+ w3c_slidy.show_slide(slide);
+ w3c_slidy.show_slide_number();
+ },
+
+
+ show_slide: function (slide) {
+ this.sync_background(slide);
+ window.scrollTo(0,0);
+ this.remove_class(slide, "hidden");
+ },
+
+ hide_slide: function (slide) {
+ this.add_class(slide, "hidden");
+ },
+
+ // show just the backgrounds pertinent to this slide
+ // when slide background-color is transparent
+ // this should now work with rgba color values
+ sync_background: function (slide) {
+ var background;
+ var bgColor;
+
+ if (slide.currentStyle)
+ bgColor = slide.currentStyle["backgroundColor"];
+ else if (document.defaultView)
+ {
+ var styles = document.defaultView.getComputedStyle(slide,null);
+
+ if (styles)
+ bgColor = styles.getPropertyValue("background-color");
+ else // broken implementation probably due Safari or Konqueror
+ {
+ //alert("defective implementation of getComputedStyle()");
+ bgColor = "transparent";
+ }
+ }
+ else
+ bgColor == "transparent";
+
+ if (bgColor == "transparent" ||
+ bgColor.indexOf("rgba") >= 0 ||
+ bgColor.indexOf("opacity") >= 0)
+ {
+ var slideClass = this.get_class_list(slide);
+
+ for (var i = 0; i < this.backgrounds.length; i++)
+ {
+ background = this.backgrounds[i];
+
+ var bgClass = this.get_class_list(background);
+
+ if (this.matching_background(slideClass, bgClass))
+ this.remove_class(background, "hidden");
+ else
+ this.add_class(background, "hidden");
+ }
+ }
+ else // forcibly hide all backgrounds
+ this.hide_backgrounds();
+ },
+
+ hide_backgrounds: function () {
+ for (var i = 0; i < this.backgrounds.length; i++)
+ {
+ background = this.backgrounds[i];
+ this.add_class(background, "hidden");
+ }
+ },
+
+ // compare classes for slide and background
+ matching_background: function (slideClass, bgClass) {
+ var i, count, pattern, result;
+
+ // define pattern as regular expression
+ pattern = /\w+/g;
+
+ // check background class names
+ result = bgClass.match(pattern);
+
+ for (i = count = 0; i < result.length; i++)
+ {
+ if (result[i] == "hidden")
+ continue;
+
+ if (result[i] == "background")
+ continue;
+
+ ++count;
+ }
+
+ if (count == 0) // default match
+ return true;
+
+ // check for matches and place result in array
+ result = slideClass.match(pattern);
+
+ // now check if desired name is present for background
+ for (i = count = 0; i < result.length; i++)
+ {
+ if (result[i] == "hidden")
+ continue;
+
+ if (this.has_token(bgClass, result[i]))
+ return true;
+ }
+
+ return false;
+ },
+
+ resized: function () {
+ var width = 0;
+
+ if ( typeof( window.innerWidth ) == 'number' )
+ width = window.innerWidth; // Non IE browser
+ else if (document.documentElement && document.documentElement.clientWidth)
+ width = document.documentElement.clientWidth; // IE6
+ else if (document.body && document.body.clientWidth)
+ width = document.body.clientWidth; // IE4
+
+ var height = 0;
+
+ if ( typeof( window.innerHeight ) == 'number' )
+ height = window.innerHeight; // Non IE browser
+ else if (document.documentElement && document.documentElement.clientHeight)
+ height = document.documentElement.clientHeight; // IE6
+ else if (document.body && document.body.clientHeight)
+ height = document.body.clientHeight; // IE4
+
+ if (height && (width/height > 1.05*1024/768))
+ {
+ width = height * 1024.0/768;
+ }
+
+ // IE fires onresize even when only font size is changed!
+ // so we do a check to avoid blocking < and > actions
+ if (width != w3c_slidy.last_width || height != w3c_slidy.last_height)
+ {
+ if (width >= 1100)
+ w3c_slidy.size_index = 5; // 4
+ else if (width >= 1000)
+ w3c_slidy.size_index = 4; // 3
+ else if (width >= 800)
+ w3c_slidy.size_index = 3; // 2
+ else if (width >= 600)
+ w3c_slidy.size_index = 2; // 1
+ else if (width)
+ w3c_slidy.size_index = 0;
+
+ // add in font size adjustment from meta element e.g.
+ // <meta name="font-size-adjustment" content="-2" />
+ // useful when slides have too much content ;-)
+
+ if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment &&
+ w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length)
+ w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment;
+
+ // enables cross browser use of relative width/height
+ // on object elements for use with SVG and Flash media
+ w3c_slidy.adjust_object_dimensions(width, height);
+
+ if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index])
+ {
+ document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
+ }
+
+ w3c_slidy.last_width = width;
+ w3c_slidy.last_height = height;
+
+ // force reflow to work around Mozilla bug
+ if (w3c_slidy.ns_pos)
+ {
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.show_slide(slide);
+ }
+
+ // force correct positioning of toolbar
+ w3c_slidy.refresh_toolbar(200);
+ }
+ },
+
+ scrolled: function () {
+ if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7)
+ {
+ w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset();
+ // hide toolbar
+ w3c_slidy.toolbar.style.display = "none";
+
+ // make it reappear later
+ if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all)
+ {
+ setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000);
+ w3c_slidy.scrollhack = 1;
+ }
+ }
+ },
+
+ hide_toolbar: function () {
+ w3c_slidy.add_class(w3c_slidy.toolbar, "hidden");
+ window.focus();
+ },
+
+ // used to ensure IE refreshes toolbar in correct position
+ refresh_toolbar: function (interval) {
+ if (!w3c_slidy.ns_pos && !w3c_slidy.ie7)
+ {
+ w3c_slidy.hide_toolbar();
+ setTimeout(function () {w3c_slidy.show_toolbar(); }, interval);
+ }
+ },
+
+ // restores toolbar after short delay
+ show_toolbar: function () {
+ if (w3c_slidy.want_toolbar)
+ {
+ w3c_slidy.toolbar.style.display = "block";
+
+ if (!w3c_slidy.ns_pos)
+ {
+ // adjust position to allow for scrolling
+ var xoffset = w3c_slidy.scroll_x_offset();
+ w3c_slidy.toolbar.style.left = xoffset;
+ w3c_slidy.toolbar.style.right = xoffset;
+
+ // determine vertical scroll offset
+ //var yoffset = scrollYOffset();
+
+ // bottom is doc height - window height - scroll offset
+ //var bottom = documentHeight() - lastHeight - yoffset
+
+ //if (yoffset > 0 || documentHeight() > lastHeight)
+ // bottom += 16; // allow for height of scrollbar
+
+ w3c_slidy.toolbar.style.bottom = 0; //bottom;
+ }
+
+ w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden");
+ }
+
+ w3c_slidy.scrollhack = 0;
+
+
+ // set the keyboard focus to the help link on the
+ // toolbar to ensure that document has the focus
+ // IE doesn't always work with window.focus()
+ // and this hack has benefit of Enter for help
+
+ try
+ {
+ if (!w3c_slidy.opera)
+ w3c_slidy.help_anchor.focus();
+ }
+ catch (e)
+ {
+ }
+ },
+
+// invoked via F key
+ toggle_toolbar: function () {
+ if (!w3c_slidy.view_all)
+ {
+ if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden"))
+ {
+ w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden")
+ w3c_slidy.want_toolbar = 1;
+ }
+ else
+ {
+ w3c_slidy.add_class(w3c_slidy.toolbar, "hidden")
+ w3c_slidy.want_toolbar = 0;
+ }
+ }
+ },
+
+ scroll_x_offset: function () {
+ if (window.pageXOffset)
+ return self.pageXOffset;
+
+ if (document.documentElement &&
+ document.documentElement.scrollLeft)
+ return document.documentElement.scrollLeft;
+
+ if (document.body)
+ return document.body.scrollLeft;
+
+ return 0;
+ },
+
+ scroll_y_offset: function () {
+ if (window.pageYOffset)
+ return self.pageYOffset;
+
+ if (document.documentElement &&
+ document.documentElement.scrollTop)
+ return document.documentElement.scrollTop;
+
+ if (document.body)
+ return document.body.scrollTop;
+
+ return 0;
+ },
+
+ // looking for a way to determine height of slide content
+ // the slide itself is set to the height of the window
+ optimize_font_size: function () {
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+
+ //var dh = documentHeight(); //getDocHeight(document);
+ var dh = slide.scrollHeight;
+ var wh = getWindowHeight();
+ var u = 100 * dh / wh;
+
+ alert("window utilization = " + u + "% (doc "
+ + dh + " win " + wh + ")");
+ },
+
+ // from document object
+ get_doc_height: function (doc) {
+ if (!doc)
+ doc = document;
+
+ if (doc && doc.body && doc.body.offsetHeight)
+ return doc.body.offsetHeight; // ns/gecko syntax
+
+ if (doc && doc.body && doc.body.scrollHeight)
+ return doc.body.scrollHeight;
+
+ alert("couldn't determine document height");
+ },
+
+ get_window_height: function () {
+ if ( typeof( window.innerHeight ) == 'number' )
+ return window.innerHeight; // Non IE browser
+
+ if (document.documentElement && document.documentElement.clientHeight)
+ return document.documentElement.clientHeight; // IE6
+
+ if (document.body && document.body.clientHeight)
+ return document.body.clientHeight; // IE4
+ },
+
+ document_height: function () {
+ var sh, oh;
+
+ sh = document.body.scrollHeight;
+ oh = document.body.offsetHeight;
+
+ if (sh && oh)
+ {
+ return (sh > oh ? sh : oh);
+ }
+
+ // no idea!
+ return 0;
+ },
+
+ smaller: function () {
+ if (w3c_slidy.size_index > 0)
+ {
+ --w3c_slidy.size_index;
+ }
+
+ w3c_slidy.toolbar.style.display = "none";
+ document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.show_slide(slide);
+ setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
+ },
+
+ bigger: function () {
+ if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1)
+ {
+ ++w3c_slidy.size_index;
+ }
+
+ w3c_slidy.toolbar.style.display = "none";
+ document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+ w3c_slidy.hide_slide(slide);
+ w3c_slidy.show_slide(slide);
+ setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
+ },
+
+ // enables cross browser use of relative width/height
+ // on object elements for use with SVG and Flash media
+ // with thanks to Ivan Herman for the suggestion
+ adjust_object_dimensions: function (width, height) {
+ for( var i = 0; i < w3c_slidy.objects.length; i++ )
+ {
+ var obj = this.objects[i];
+ var mimeType = obj.getAttribute("type");
+
+ if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
+ {
+ if ( !obj.initialWidth )
+ obj.initialWidth = obj.getAttribute("width");
+
+ if ( !obj.initialHeight )
+ obj.initialHeight = obj.getAttribute("height");
+
+ if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
+ {
+ var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
+ var newW = width * (w/100.0);
+ obj.setAttribute("width",newW);
+ }
+
+ if ( obj.initialHeight &&
+ obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
+ {
+ var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
+ var newH = height * (h/100.0);
+ obj.setAttribute("height", newH);
+ }
+ }
+ }
+ },
+
+ // needed for Opera to inhibit default behavior
+ // since Opera delivers keyPress even if keyDown
+ // was cancelled
+ key_press: function (event) {
+ if (!event)
+ event = window.event;
+
+ if (!w3c_slidy.key_wanted)
+ return w3c_slidy.cancel(event);
+
+ return true;
+ },
+
+ // See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
+ key_down: function (event) {
+ var key;
+
+ w3c_slidy.key_wanted = true;
+
+ if (!event)
+ event = window.event;
+
+ // kludge around NS/IE differences
+ if (window.event)
+ key = window.event.keyCode;
+ else if (event.which)
+ key = event.which;
+ else
+ return true; // Yikes! unknown browser
+
+ // ignore event if key value is zero
+ // as for alt on Opera and Konqueror
+ if (!key)
+ return true;
+
+ // check for concurrent control/command/alt key
+ // but are these only present on mouse events?
+
+ if (event.ctrlKey || event.altKey || event.metaKey)
+ return true;
+
+ // dismiss table of contents if visible
+ if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40)
+ {
+ w3c_slidy.hide_table_of_contents();
+
+ if (key == 27 || key == 84 || key == 67)
+ return w3c_slidy.cancel(event);
+ }
+
+ if (key == 34) // Page Down
+ {
+ if (w3c_slidy.view_all)
+ return true;
+
+ w3c_slidy.next_slide(false);
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 33) // Page Up
+ {
+ if (w3c_slidy.view_all)
+ return true;
+
+ w3c_slidy.previous_slide(false);
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 32) // space bar
+ {
+ w3c_slidy.next_slide(true);
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 37) // Left arrow
+ {
+ w3c_slidy.previous_slide(!event.shiftKey);
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 36) // Home
+ {
+ w3c_slidy.first_slide();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 35) // End
+ {
+ w3c_slidy.last_slide();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 39) // Right arrow
+ {
+ w3c_slidy.next_slide(!event.shiftKey);
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 13) // Enter
+ {
+ if (w3c_slidy.outline)
+ {
+ if (w3c_slidy.outline.visible)
+ w3c_slidy.fold(w3c_slidy.outline);
+ else
+ w3c_slidy.unfold(w3c_slidy.outline);
+
+ return w3c_slidy.cancel(event);
+ }
+ }
+ else if (key == 188) // < for smaller fonts
+ {
+ w3c_slidy.smaller();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 190) // > for larger fonts
+ {
+ w3c_slidy.bigger();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 189 || key == 109) // - for smaller fonts
+ {
+ w3c_slidy.smaller();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
+ {
+ w3c_slidy.bigger();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 83) // S for smaller fonts
+ {
+ w3c_slidy.smaller();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 66) // B for larger fonts
+ {
+ w3c_slidy.bigger();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 90) // Z for last slide
+ {
+ w3c_slidy.last_slide();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 70) // F for toggle toolbar
+ {
+ w3c_slidy.toggle_toolbar();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 65) // A for toggle view single/all slides
+ {
+ w3c_slidy.toggle_view();
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 75) // toggle action of left click for next page
+ {
+ w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled;
+ var alert_msg = (w3c_slidy.mouse_click_enabled ?
+ "enabled" : "disabled") + " mouse click advance";
+
+ alert(alert_msg.localize());
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 84 || key == 67) // T or C for table of contents
+ {
+ if (w3c_slidy.toc)
+ w3c_slidy.toggle_table_of_contents();
+
+ return w3c_slidy.cancel(event);
+ }
+ else if (key == 72) // H for help
+ {
+ window.location = w3c_slidy.help_page;
+ return w3c_slidy.cancel(event);
+ }
+ //else alert("key code is "+ key);
+
+ return true;
+ },
+
+ // safe for both text/html and application/xhtml+xml
+ create_element: function (name) {
+ if (this.xhtml && (typeof document.createElementNS != 'undefined'))
+ return document.createElementNS("http://www.w3.org/1999/xhtml", name)
+
+ return document.createElement(name);
+ },
+
+ get_element_style: function (elem, IEStyleProp, CSSStyleProp) {
+ if (elem.currentStyle)
+ {
+ return elem.currentStyle[IEStyleProp];
+ }
+ else if (window.getComputedStyle)
+ {
+ var compStyle = window.getComputedStyle(elem, "");
+ return compStyle.getPropertyValue(CSSStyleProp);
+ }
+ return "";
+ },
+
+ // the string str is a whitespace separated list of tokens
+ // test if str contains a particular token, e.g. "slide"
+ has_token: function (str, token) {
+ if (str)
+ {
+ // define pattern as regular expression
+ var pattern = /\w+/g;
+
+ // check for matches
+ // place result in array
+ var result = str.match(pattern);
+
+ // now check if desired token is present
+ for (var i = 0; i < result.length; i++)
+ {
+ if (result[i] == token)
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ get_class_list: function (element) {
+ if (typeof element.className != 'undefined')
+ return element.className;
+
+ return element.getAttribute("class");
+ },
+
+ has_class: function (element, name) {
+ if (element.nodeType != 1)
+ return false;
+
+ var regexp = new RegExp("(^| )" + name + "\W*");
+
+ if (typeof element.className != 'undefined')
+ return regexp.test(element.className);
+
+ return regexp.test(element.getAttribute("class"));
+ },
+
+ remove_class: function (element, name) {
+ var regexp = new RegExp("(^| )" + name + "\W*");
+ var clsval = "";
+
+ if (typeof element.className != 'undefined')
+ {
+ clsval = element.className;
+
+ if (clsval)
+ {
+ clsval = clsval.replace(regexp, "");
+ element.className = clsval;
+ }
+ }
+ else
+ {
+ clsval = element.getAttribute("class");
+
+ if (clsval)
+ {
+ clsval = clsval.replace(regexp, "");
+ element.setAttribute("class", clsval);
+ }
+ }
+ },
+
+ add_class: function (element, name) {
+ if (!this.has_class(element, name))
+ {
+ if (typeof element.className != 'undefined')
+ element.className += " " + name;
+ else
+ {
+ var clsval = element.getAttribute("class");
+ clsval = clsval ? clsval + " " + name : name;
+ element.setAttribute("class", clsval);
+ }
+ }
+ },
+
+ // HTML elements that can be used with class="incremental"
+ // note that you can also put the class on containers like
+ // up, ol, dl, and div to make their contents appear
+ // incrementally. Upper case is used since this is what
+ // browsers report for HTML node names (text/html).
+ incremental_elements: null,
+ okay_for_incremental: function (name) {
+ if (!this.incremental_elements)
+ {
+ var inclist = new Array();
+ inclist["p"] = true;
+ inclist["pre"] = true;
+ inclist["li"] = true;
+ inclist["blockquote"] = true;
+ inclist["dt"] = true;
+ inclist["dd"] = true;
+ inclist["h2"] = true;
+ inclist["h3"] = true;
+ inclist["h4"] = true;
+ inclist["h5"] = true;
+ inclist["h6"] = true;
+ inclist["span"] = true;
+ inclist["address"] = true;
+ inclist["table"] = true;
+ inclist["tr"] = true;
+ inclist["th"] = true;
+ inclist["td"] = true;
+ inclist["img"] = true;
+ inclist["object"] = true;
+ this.incremental_elements = inclist;
+ }
+ return this.incremental_elements[name.toLowerCase()];
+ },
+
+ next_incremental_item: function (node) {
+ var br = this.is_xhtml ? "br" : "BR";
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+
+ for (;;)
+ {
+ node = w3c_slidy.next_node(slide, node);
+
+ if (node == null || node.parentNode == null)
+ break;
+
+ if (node.nodeType == 1) // ELEMENT
+ {
+ if (node.nodeName == br)
+ continue;
+
+ if (w3c_slidy.has_class(node, "incremental")
+ && w3c_slidy.okay_for_incremental(node.nodeName))
+ return node;
+
+ if (w3c_slidy.has_class(node.parentNode, "incremental")
+ && !w3c_slidy.has_class(node, "non-incremental"))
+ return node;
+ }
+ }
+
+ return node;
+ },
+
+ previous_incremental_item: function (node) {
+ var br = this.is_xhtml ? "br" : "BR";
+ var slide = w3c_slidy.slides[w3c_slidy.slide_number];
+
+ for (;;)
+ {
+ node = w3c_slidy.previous_node(slide, node);
+
+ if (node == null || node.parentNode == null)
+ break;
+
+ if (node.nodeType == 1)
+ {
+ if (node.nodeName == br)
+ continue;
+
+ if (w3c_slidy.has_class(node, "incremental")
+ && w3c_slidy.okay_for_incremental(node.nodeName))
+ return node;
+
+ if (w3c_slidy.has_class(node.parentNode, "incremental")
+ && !w3c_slidy.has_class(node, "non-incremental"))
+ return node;
+ }
+ }
+
+ return node;
+ },
+
+ // set visibility for all elements on current slide with
+ // a parent element with attribute class="incremental"
+ set_visibility_all_incremental: function (value) {
+ var node = this.next_incremental_item(null);
+
+ if (value == "hidden")
+ {
+ while (node)
+ {
+ w3c_slidy.add_class(node, "invisible");
+ node = w3c_slidy.next_incremental_item(node);
+ }
+ }
+ else // value == "visible"
+ {
+ while (node)
+ {
+ w3c_slidy.remove_class(node, "invisible");
+ node = w3c_slidy.next_incremental_item(node);
+ }
+ }
+ },
+
+ // reveal the next hidden item on the slide
+ // node is null or the node that was last revealed
+ reveal_next_item: function (node) {
+ node = w3c_slidy.next_incremental_item(node);
+
+ if (node && node.nodeType == 1) // an element
+ w3c_slidy.remove_class(node, "invisible");
+
+ return node;
+ },
+
+ // exact inverse of revealNextItem(node)
+ hide_previous_item: function (node) {
+ if (node && node.nodeType == 1) // an element
+ w3c_slidy.add_class(node, "invisible");
+
+ return this.previous_incremental_item(node);
+ },
+
+ // left to right traversal of root's content
+ next_node: function (root, node) {
+ if (node == null)
+ return root.firstChild;
+
+ if (node.firstChild)
+ return node.firstChild;
+
+ if (node.nextSibling)
+ return node.nextSibling;
+
+ for (;;)
+ {
+ node = node.parentNode;
+
+ if (!node || node == root)
+ break;
+
+ if (node && node.nextSibling)
+ return node.nextSibling;
+ }
+
+ return null;
+ },
+
+ // right to left traversal of root's content
+ previous_node: function (root, node) {
+ if (node == null)
+ {
+ node = root.lastChild;
+
+ if (node)
+ {
+ while (node.lastChild)
+ node = node.lastChild;
+ }
+
+ return node;
+ }
+
+ if (node.previousSibling)
+ {
+ node = node.previousSibling;
+
+ while (node.lastChild)
+ node = node.lastChild;
+
+ return node;
+ }
+
+ if (node.parentNode != root)
+ return node.parentNode;
+
+ return null;
+ },
+
+ previous_sibling_element: function (el) {
+ el = el.previousSibling;
+
+ while (el && el.nodeType != 1)
+ el = el.previousSibling;
+
+ return el;
+ },
+
+ next_sibling_element: function (el) {
+ el = el.nextSibling;
+
+ while (el && el.nodeType != 1)
+ el = el.nextSibling;
+
+ return el;
+ },
+
+ first_child_element: function (el) {
+ var node;
+
+ for (node = el.firstChild; node; node = node.nextSibling)
+ {
+ if (node.nodeType == 1)
+ break;
+ }
+
+ return node;
+ },
+
+ first_tag: function (element, tag) {
+ var node;
+
+ if (!this.is_xhtml)
+ tag = tag.toUpperCase();
+
+ for (node = element.firstChild; node; node = node.nextSibling)
+ {
+ if (node.nodeType == 1 && node.nodeName == tag)
+ break;
+ }
+
+ return node;
+ },
+
+ hide_selection: function () {
+ if (window.getSelection) // Firefox, Chromium, Safari, Opera
+ {
+ var selection = window.getSelection();
+
+ if (selection.rangeCount > 0)
+ {
+ var range = selection.getRangeAt(0);
+ range.collapse (false);
+ }
+ }
+ else // Internet Explorer
+ {
+ var textRange = document.selection.createRange ();
+ textRange.collapse (false);
+ }
+ },
+
+ get_selected_text: function () {
+ try
+ {
+ if (window.getSelection)
+ return window.getSelection().toString();
+
+ if (document.getSelection)
+ return document.getSelection().toString();
+
+ if (document.selection)
+ return document.selection.createRange().text;
+ }
+ catch (e)
+ {
+ }
+
+ return "";
+ },
+
+ // make note of length of selected text
+ // as this evaluates to zero in click event
+ mouse_button_up: function (e) {
+ w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length;
+ },
+
+ // right mouse button click is reserved for context menus
+ // it is more reliable to detect rightclick than leftclick
+ mouse_button_click: function (e) {
+ var rightclick = false;
+ var leftclick = false;
+ var middleclick = false;
+ var target;
+
+ if (!e)
+ var e = window.event;
+
+ if (e.target)
+ target = e.target;
+ else if (e.srcElement)
+ target = e.srcElement;
+
+ // work around Safari bug
+ if (target.nodeType == 3)
+ target = target.parentNode;
+
+ if (e.which) // all browsers except IE
+ {
+ leftclick = (e.which == 1);
+ middleclick = (e.which == 2);
+ rightclick = (e.which == 3);
+ }
+ else if (e.button)
+ {
+ // Konqueror gives 1 for left, 4 for middle
+ // IE6 gives 0 for left and not 1 as I expected
+
+ if (e.button == 4)
+ middleclick = true;
+
+ // all browsers agree on 2 for right button
+ rightclick = (e.button == 2);
+ }
+ else leftclick = true;
+/*
+ alert("you clicked over a " + target.nodeName + " element\n" +
+ "w3c_slidy.mouse_click_enabled = " + w3c_slidy.mouse_click_enabled + "\n" +
+ "leftclick = " + leftclick + "\n" +
+ "selected text length = " + w3c_slidy.selected_text_len);
+ //alert("selected text length = " + w3c_slidy.selected_text_len);
+*/
+ if (w3c_slidy.selected_text_len > 0)
+ {
+ w3c_slidy.stop_propagation(e);
+ e.cancel = true;
+ e.returnValue = false;
+ return false;
+ }
+
+ // dismiss table of contents
+ w3c_slidy.hide_table_of_contents();
+
+ // check if target is something that probably want's clicks
+ // e.g. a, embed, object, input, textarea, select, option
+ var tag = target.nodeName.toLowerCase();
+
+ if (w3c_slidy.mouse_click_enabled && leftclick &&
+ tag != "a" &&
+ tag != "embed" &&
+ tag != "object" &&
+ tag != "video" &&
+ tag != "input" &&
+ tag != "textarea" &&
+ tag != "select" &&
+ tag != "option" &&
+ !target.onclick)
+ {
+ w3c_slidy.next_slide(true);
+ w3c_slidy.stop_propagation(e);
+ e.cancel = true;
+ e.returnValue = false;
+ return false;
+ }
+ },
+
+ get_key: function (e)
+ {
+ var key;
+
+ // kludge around NS/IE differences
+ if (typeof window.event != "undefined")
+ key = window.event.keyCode;
+ else if (e.which)
+ key = e.which;
+
+ return key;
+ },
+
+ get_target: function (e) {
+ var target;
+
+ if (!e)
+ e = window.event;
+
+ if (e.target)
+ target = e.target;
+ else if (e.srcElement)
+ target = e.srcElement;
+
+ if (target.nodeType != 1)
+ target = target.parentNode;
+
+ return target;
+ },
+
+ // does display property provide correct defaults?
+ is_block: function (elem) {
+ var tag = elem.nodeName.toLowerCase();
+
+ return tag == "ol" || tag == "ul" || tag == "p" ||
+ tag == "li" || tag == "table" || tag == "pre" ||
+ tag == "h1" || tag == "h2" || tag == "h3" ||
+ tag == "h4" || tag == "h5" || tag == "h6" ||
+ tag == "blockquote" || tag == "address";
+ },
+
+ add_listener: function (element, event, handler) {
+ if (window.addEventListener)
+ element.addEventListener(event, handler, false);
+ else
+ element.attachEvent("on"+event, handler);
+ },
+
+ // used to prevent event propagation from field controls
+ stop_propagation: function (event) {
+ event = event ? event : window.event;
+ event.cancelBubble = true; // for IE
+
+ if (event.stopPropagation)
+ event.stopPropagation();
+
+ return true;
+ },
+
+ cancel: function (event) {
+ if (event)
+ {
+ event.cancel = true;
+ event.returnValue = false;
+
+ if (event.preventDefault)
+ event.preventDefault();
+ }
+
+ w3c_slidy.key_wanted = false;
+ return false;
+ }
+};
+
+// for each language define an associative array
+// and also the help text which is longer
+
+var w3c_slidy_i18n = {
+ strings_es: {
+ "slide":"pág.",
+ "help?":"Ayuda",
+ "contents?":"Índice",
+ "table of contents":"tabla de contenidos",
+ "Table of Contents":"Tabla de Contenidos",
+ "restart presentation":"Reiniciar presentación",
+ "restart?":"Inicio"
+ },
+ help_es:
+ "Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
+ "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.",
+
+ strings_ca: {
+ "slide":"pàg..",
+ "help?":"Ajuda",
+ "contents?":"Índex",
+ "table of contents":"taula de continguts",
+ "Table of Contents":"Taula de Continguts",
+ "restart presentation":"Reiniciar presentació",
+ "restart?":"Inici"
+ },
+ help_ca:
+ "Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
+ "o Re pàg y Av pàg. Usi S i B per canviar grandària de font.",
+
+ strings_cs: {
+ "slide":"snímek",
+ "help?":"nápověda",
+ "contents?":"obsah",
+ "table of contents":"obsah prezentace",
+ "Table of Contents":"Obsah prezentace",
+ "restart presentation":"znovu spustit prezentaci",
+ "restart?":"restart"
+ },
+ help_cs:
+ "Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " +
+ "šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " +
+ "dá zvětšit a zmenšit pomocí kláves B a S.",
+
+ strings_nl: {
+ "slide":"pagina",
+ "help?":"Help?",
+ "contents?":"Inhoud?",
+ "table of contents":"inhoudsopgave",
+ "Table of Contents":"Inhoudsopgave",
+ "restart presentation":"herstart presentatie",
+ "restart?":"Herstart?"
+ },
+ help_nl:
+ "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
+ "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.",
+
+ strings_de: {
+ "slide":"Seite",
+ "help?":"Hilfe",
+ "contents?":"Übersicht",
+ "table of contents":"Inhaltsverzeichnis",
+ "Table of Contents":"Inhaltsverzeichnis",
+ "restart presentation":"Präsentation neu starten",
+ "restart?":"Neustart"
+ },
+ help_de:
+ "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
+ "Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.",
+
+ strings_pl: {
+ "slide":"slajd",
+ "help?":"pomoc?",
+ "contents?":"spis treści?",
+ "table of contents":"spis treści",
+ "Table of Contents":"Spis Treści",
+ "restart presentation":"Restartuj prezentację",
+ "restart?":"restart?"
+ },
+ help_pl:
+ "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
+ "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.",
+
+ strings_fr: {
+ "slide":"page",
+ "help?":"Aide",
+ "contents?":"Index",
+ "table of contents":"table des matières",
+ "Table of Contents":"Table des matières",
+ "restart presentation":"Recommencer l'exposé",
+ "restart?":"Début"
+ },
+ help_fr:
+ "Naviguez avec la souris, la barre d'espace, les flèches " +
+ "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
+ "les touches S et B pour modifier la taille de la police.",
+
+ strings_hu: {
+ "slide":"oldal",
+ "help?":"segítség",
+ "contents?":"tartalom",
+ "table of contents":"tartalomjegyzék",
+ "Table of Contents":"Tartalomjegyzék",
+ "restart presentation":"bemutató újraindítása",
+ "restart?":"újraindítás"
+ },
+ help_hu:
+ "Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
+ "használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
+ "Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
+ "a szöveg méretét.",
+
+ strings_it: {
+ "slide":"pag.",
+ "help?":"Aiuto",
+ "contents?":"Indice",
+ "table of contents":"indice",
+ "Table of Contents":"Indice",
+ "restart presentation":"Ricominciare la presentazione",
+ "restart?":"Inizio"
+ },
+ help_it:
+ "Navigare con mouse, barra spazio, frecce sinistra/destra o " +
+ "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.",
+
+ strings_el: {
+ "slide":"σελίδα",
+ "help?":"βοήθεια;",
+ "contents?":"περιεχόμενα;",
+ "table of contents":"πίνακας περιεχομένων",
+ "Table of Contents":"Πίνακας Περιεχομένων",
+ "restart presentation":"επανεκκίνηση παρουσίασης",
+ "restart?":"επανεκκίνηση;"
+ },
+ help_el:
+ "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
+ "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
+ "το μέγεθος της γραμματοσειράς.",
+
+ strings_ja: {
+ "slide":"スライド",
+ "help?":"ヘルプ",
+ "contents?":"目次",
+ "table of contents":"目次を表示",
+ "Table of Contents":"目次",
+ "restart presentation":"最初から再生",
+ "restart?":"最初から"
+ },
+ help_ja:
+ "マウス左クリック ・ スペース ・ 左右キー " +
+ "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更",
+
+ strings_zh: {
+ "slide":"幻灯片",
+ "help?":"帮助?",
+ "contents?":"内容?",
+ "table of contents":"目录",
+ "Table of Contents":"目录",
+ "restart presentation":"重新启动展示",
+ "restart?":"重新启动?"
+ },
+ help_zh:
+ "用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
+ "用 S, B 改变字体大小.",
+
+ strings_ru: {
+ "slide":"слайд",
+ "help?":"помощь?",
+ "contents?":"содержание?",
+ "table of contents":"оглавление",
+ "Table of Contents":"Оглавление",
+ "restart presentation":"перезапустить презентацию",
+ "restart?":"перезапуск?"
+ },
+ help_ru:
+ "Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
+ "влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.",
+
+ strings_sv: {
+ "slide":"sida",
+ "help?":"hjälp",
+ "contents?":"innehåll",
+ "table of contents":"innehållsförteckning",
+ "Table of Contents":"Innehållsförteckning",
+ "restart presentation":"visa presentationen från början",
+ "restart?":"börja om"
+ },
+ help_sv:
+ "Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " +
+ "vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " +
+ "Använd tangenterna S och B för att ändra textens storlek.",
+
+// each such language array is declared in the localize array
+// which is set on string prototype and used as in "foo".localize();
+ localize: {
+ "es":this.strings_es,
+ "ca":this.strings_ca,
+ "cs":this.strings_cs,
+ "nl":this.strings_nl,
+ "de":this.strings_de,
+ "pl":this.strings_pl,
+ "fr":this.strings_fr,
+ "hu":this.strings_hu,
+ "it":this.strings_it,
+ "el":this.strings_el,
+ "jp":this.strings_ja,
+ "zh":this.strings_zh,
+ "ru":this.strings_ru,
+ "sv":this.strings_sv
+ },
+
+ init: function () {
+ var i18n = w3c_slidy_i18n;
+ var help_text = w3c_slidy.help_text;
+ i18n.strings_es[help_text] = i18n.help_es;
+ i18n.strings_ca[help_text] = i18n.help_ca;
+ i18n.strings_cs[help_text] = i18n.help_cs;
+ i18n.strings_nl[help_text] = i18n.help_nl;
+ i18n.strings_de[help_text] = i18n.help_de;
+ i18n.strings_pl[help_text] = i18n.help_pl;
+ i18n.strings_fr[help_text] = i18n.help_fr;
+ i18n.strings_hu[help_text] = i18n.help_hu;
+ i18n.strings_it[help_text] = i18n.help_it;
+ i18n.strings_el[help_text] = i18n.help_el;
+ i18n.strings_ja[help_text] = i18n.help_ja;
+ i18n.strings_zh[help_text] = i18n.help_zh;
+ i18n.strings_ru[help_text] = i18n.help_ru;
+ i18n.strings_sv[help_text] = i18n.help_sv;
+
+ w3c_slidy.lang = document.body.parentNode.getAttribute("lang");
+
+ if (!w3c_slidy.lang)
+ w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang");
+
+ if (!w3c_slidy.lang)
+ w3c_slidy.lang = "en";
+
+ // add localize method to all strings
+ // for use as in "contents".localize()
+ String.prototype.localize = function() {
+ if (this == "")
+ return this;
+
+ // try full language code, e.g. en-US
+ var s, lookup = w3c_slidy_i18n.localize[w3c_slidy.lang];
+
+ if (lookup)
+ {
+ s = lookup[this];
+
+ if (s)
+ return s;
+ }
+
+ // strip country code suffix, e.g.
+ // try en if undefined for en-US
+ var lg = w3c_slidy.lang.split("-");
+
+ if (lg.length > 1)
+ {
+ lookup = w3c_slidy_i18n.localize[lg[0]];
+
+ if (lookup)
+ {
+ s = lookup[this];
+
+ if (s)
+ return s;
+ }
+ }
+
+ // otherwise string as is
+ return this;
+ };
+ }
+};
+
+// hack for back button behavior
+if (w3c_slidy.ie6 || w3c_slidy.ie7)
+{
+ document.write("<iframe id='historyFrame' " +
+ "src='javascript:\"<html"+"></"+"html>\"' " +
+ "height='1' width='1' " +
+ "style='position:absolute;left:-800px'></iframe>");
+}
+
+// attach event listeners for initialization
+w3c_slidy.set_up();
+
+// hide the slides as soon as body element is available
+// to reduce annoying screen mess before the onload event
+setTimeout(w3c_slidy.hide_slides, 50);
+
+/*]]>*/
+</script>
+</head>
+<body class="article" style="max-width:45em">
+<div id="header" class="slide">
+<h1>netfilter archeology: 18 years from 2.3 to 4.x</h1>
+<span id="author">Harald Welte <laforge@gnumonks.org></span><br />
+</div>
+<div class="sect1 slide">
+<h1 id="_what_is_this_about">What is this about</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class=" incremental">
+<li>
+<span>
+netfilter history
+</span>
+</li>
+<li>
+<span>
+netfilter who-is-who
+</span>
+</li>
+<li>
+<span>
+netfilter anecdotes
+</span>
+</li>
+<li>
+<span>
+netfilter folklore
+</span>
+</li>
+<li>
+<span>
+netfilter world domination
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_context">Context</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class=" incremental">
+<li>
+<span>
+late 1990ies
+</span>
+</li>
+<li>
+<span>
+Internet was still new to many people
+</span>
+</li>
+<li>
+<span>
+Internet Security was still rather new
+</span>
+<ul class="">
+<li>
+<span>
+think e.g. of the "ping of death" problems.
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+no git, not even subversion, but: CVS(!)
+</span>
+<ul class="">
+<li>
+<span>
+even pre-bitkeeper, so no kernel global revision control
+</span>
+</li>
+<li>
+<span>
+Linus was applying patches and making "pre" releases as tar-ball every so often
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+no authorship annotation / commit history
+</span>
+</li>
+<li>
+<span>
+no virtual machines, testing on physical boxes, long boot cycles
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_pre_netfilter">pre-netfilter</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>The pre-netfilter days</p></div>
+<ul class=" incremental">
+<li>
+<span>
+Linux 1.2, 1.3 and 2.0 had <code>ipfwadm</code> (Jos Vos et al)
+</span>
+<ul class="">
+<li>
+<span>
+who in the audience has still used that? Raise your hand!
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+Linux 2.2 had <code>ipchains</code> (Rusty Russell)
+</span>
+<ul class=" incremental">
+<li>
+<span>
+who in the audience has still used that? Raise your hand!
+</span>
+</li>
+<li>
+<span>
+Rusty was doing some sysadmin work at an ISP and was doing his job so well that he had plenty of spare time
+</span>
+</li>
+<li>
+<span>
+He was <em>immensely</em> inspired by a talk by DaveM on beating the hell out of Solaris on SPARC
+</span>
+</li>
+<li>
+<span>
+wanted to do more Linux stuff, met WatchGuard
+</span>
+</li>
+<li>
+<span>
+proposed to do a proper redesign of the Linux firewall if they pay him for 6-12 months
+</span>
+</li>
+<li>
+<span>
+… which they did, so mid-1998 to mid-1999, he hacked away on it.
+</span>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_creation_timeline">Creation Timeline</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="quoteblock">
+<div class="content">Who the hell are you, and why are you playing with my kernel?
+I want to clear up some people’s misconceptions: I am <em>no kernel guru</em>. I know this, because my kernel work has brought me into contact with some of them: David S. Miller, Alexey Kuznetsov, Andi Kleen, Alan Cox. However, they’re all busy doing the deep magic, leaving me to wade in the shallow end where it’s safe.</div>
+<div class="attribution">
+— Rusty Russell
+</div></div>
+<ul class=" incremental">
+<li>
+<span>
+July 20, 1998: Rusty posts initial netfilter design to netdev list
+</span>
+</li>
+<li>
+<span>
+January 29, 1999: netfilter v0.1 released
+</span>
+</li>
+<li>
+<span>
+August 26, 1999: netfilter included in kernel 2.3.15
+</span>
+</li>
+<li>
+<span>
+November 1999: <em>core team</em> established with Marc Boucher + Rusty Russell
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_netfilter_v0_1">netfilter v0.1</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: 1999-01-29 10:36:34
+From: Paul Rusty Russell <Paul.Russell@rustcorp.com.au>
+Subject: [ipchains-dev] netfilter v0.1 released.
+
+Hi all,
+
+Just in case people are sick of all this "stable kernel" crap, and want their interesting behaviour back, here's the first alpha-quality cut of my new firewall/NAT/masquerading/transproxy/redirect/portforward framework, from
+ ftp://ftp.rustcorp.com/netfilter/netfilter-1999-01-29.tar.bz2
+
+This work is a result of the vast amount of user feedback I've had on things such as transparent proxying, masquerading, ipfwadm, ipchains, etc. Includes a 400k patch against 2.2.0. (84 files changed, 2509 insertions, 12097 deletions).
+
+It's all set in slush at this stage, so if you have any comments, please feel free to leap forward and abuse me...</code></pre>
+</div></div>
+<div class="paragraph"><p>In other news of January 1999:</p></div>
+<ul class="">
+<li>
+<span>
+Yahoo bought Geocities
+</span>
+</li>
+<li>
+<span>
+Clinton faced impeachemnt trial
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_netfilter_merged_in_kernel_2_3_15">netfilter merged in kernel 2.3.15</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code> From: Linus Torvalds <torvalds@transmeta.com>
+ Subject: Linux-2.3.15..
+ Date: Wed, 25 Aug 1999 16:36:10 -0700 (PDT)
+
+There's a rather huge patch-set out there now, taking the 2.3.x series to 2.3.15. [...]
+
+Other features that don't impact everybody, but are rather major:
+
+* firewalling is gone (again), replaced by an even more generic netfilter facility.
+[...]
+
+Have fun,
+ Linus</code></pre>
+</div></div>
+<div class="paragraph"><p>In other news:</p></div>
+<ul class="">
+<li>
+<span>
+East Timor becomes independent of Indonesia
+</span>
+</li>
+<li>
+<span>
+Vladimir Putin becomes Prime Minister of Russia for the first time
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_rusty_at_linux_beer_hike_2000">Rusty (at Linux Beer Hike 2000)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="rusty2000.jpg" alt="rusty2000.jpg" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_linux_beer_hike_2000">Linux Beer Hike 2000</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="lbw1.jpg" alt="lbw1.jpg" width="100%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_linux_beer_hike_2000_2">Linux Beer Hike 2000</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="lbw2.jpg" alt="lbw2.jpg" width="100%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_marc_boucher_at_ols_2000">Marc Boucher (at OLS 2000)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="marc-ols2000-zoom.png" alt="marc-ols2000-zoom.png" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_core_team_timeline">Core Team Timeline</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+November 1999: <em>core team</em> established with <em>Marc Boucher</em> + <em>Rusty Russell</em>
+</span>
+</li>
+<li>
+<span>
+Sydney Linux Expo: <em>James Morris</em> joins core team
+</span>
+</li>
+<li>
+<span>
+September 2000: <em>Harald Welte</em> joins core team
+</span>
+</li>
+<li>
+<span>
+November 2001: <em>Jozsef Kadlecsik</em> joins core tema
+</span>
+</li>
+<li>
+<span>
+August 2003: <em>Martin Josefsson</em> joins core team
+</span>
+<ul class="">
+<li>
+<span>
+Rusty, Marc and James become <em>emeritus</em> members
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+January 2004: <em>Patrick McHardy</em> joins core team
+</span>
+</li>
+<li>
+<span>
+October 2005: <em>Yasuyuki Kozakai</em> joins core team
+</span>
+</li>
+<li>
+<span>
+February 2007: <em>Pablo Neira</em> joins core team
+</span>
+</li>
+<li>
+<span>
+October 2012: <em>Eric Leblond</em> and <em>Florian Westphal</em> join core team
+</span>
+<ul class="">
+<li>
+<span>
+Harald, Martin and Yasuyuki enter <em>emeritus</em> status
+</span>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_james_morris_in_2008">James Morris (in 2008)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="james.jpg" alt="james.jpg" width="60%" />
+</span></p></div>
+<div class="paragraph"><p>(sorry, I have no earlier picture of him)</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_rustys_humor">(Rustys) Humor</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>From <a href="http://www.netfilter.org/about.html#history">http://www.netfilter.org/about.html#history</a></p></div>
+<div class="paragraph"><p>Following James' assimilation into the collective, our efforts were mainly directed towards preparations for
+the release of Netfilter as part of the upcoming 2.4 kernel.</p></div>
+<div class="paragraph"><p><em>It was the dawn of the third age of Linux firewalling; a time of great struggle and heroic deeds. It was our last, best hope for peace. Great communities were founded, old civilizations were lost, and new alliances were formed.</em></p></div>
+<div class="paragraph"><p>James' missions during this period included the <em>continued perversion of the networking code</em>, such that it was now possible to load an ASN.1 parser into the kernel and <em>inflict grave terror upon unsuspecting SNMP packets</em>; and to extend the IP stack into userspace with Perl.</p></div>
+<div class="paragraph"><p><em>Now peering squarely into the abyss, we noticed the good deeds of a young kernel warrior</em> named Harald Welte, who seemed to actually understand the NAT code. Accordingly, his distinctiveness was added to the collective. <em>With balance restored, the netfilter juggernaut was now free to accelerate into the brave new world of Linux 2.4 and face it’s greatest challenge: users.</em></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_rustys_humor_2">(Rustys) Humor</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Fri, 13 Oct 2000 16:26:06 +1100
+From: Rusty Russell <rusty@linuxcare.com.au>
+To: netfilter@lists.samba.org, netfilter-devel@lists.samba.org
+Subject: [CORE TEAM] New Member Announce
+
+The Netfilter Core Team is proud to welcome Harald Welte into its hallowed botherhood.
+
+Harald Welte has frequently answered user questions on the mailing list, and authored the IRC connection tracking and NAT modules. He even documented what he'd done! And then fixed some of the bugs!
+
+This shocking and revolutionary approach to software development will fill a much-needed void in the Netfilter Team. Assuming he survives the inauguration ceremony.</code></pre>
+</div></div>
+<div class="paragraph"><p>Meanwhile, in other news:</p></div>
+<ul class=" incremental">
+<li>
+<span>
+Bill Gates steps down as CEO of Microsoft
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2000_harald_welte">2000: Harald Welte</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="laforge-hat.jpg" alt="laforge-hat.jpg" />
+</span></p></div>
+<ul class="">
+<li>
+<span>
+active in German BBS community and pre-internet offline e-mail networking
+</span>
+</li>
+<li>
+<span>
+sysadmin work at first German <em>online bistro</em> later turning into first <em>internet cafe</em>
+</span>
+</li>
+<li>
+<span>
+volunteer sysadmin at volunteer-based non-profit ISP from 1994 onwards
+</span>
+</li>
+<li>
+<span>
+interest: packet filtering and IT security in general
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2001_jozsef_kadlecsik">2001: Jozsef Kadlecsik</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Fri, 7 Dec 2001 21:19:57 +1100 (EST)
+From: James Morris <jmorris@intercode.com.au>
+Subject: [netfilter-announce] [ANNOUNCE] New Core Team Member - Jozsef Kadlecsik
+
+The Netfilter Core Team is proud to announce the addition Jozsef Kadlecsik as a new member.
+
+Jozsef joins us as a dedicated and talented member of the Netfilter development community.
+
+His demonstrated insight and high coding standards will be highly valuable assets to the project as development focus shifts to the 2.5 kernel series.
+
+Welcome Jozsef!
+
+- James, on behalf of the Netfilter Core Team.
+--
+James Morris <jmorris@intercode.com.au></code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2001_jozsef_kadlecsik_2">2001: Jozsef Kadlecsik</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="jozsef.jpg" alt="jozsef.jpg" width="30%" />
+</span></p></div>
+<div class="paragraph"><p>Jozsef joins netfilter core team in December 2001</p></div>
+<ul class="">
+<li>
+<span>
+Physicist at Hungarian Physics Research Institute KFKI
+</span>
+<ul class="">
+<li>
+<span>
+does lots of sysadmin work there, including firewalling
+</span>
+</li>
+<li>
+<span>
+btw: what’s it with physicists and Linux networking, just like Alexey Kuznetsov?
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+focus on connection tracking (he added TCP window tracking)
+</span>
+</li>
+<li>
+<span>
+still active in the project ever since (longest standing core team member)
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2001_jozsef_kadlecsik_3">2001: Jozsef Kadlecsik</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Prior to Jozsef joining, but note-worthy:</p></div>
+<ul class="">
+<li>
+<span>
+Kernel 2.4.0 is released in January 2001 (with netfilter/iptables)
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Meanwhile in December 2001:</p></div>
+<ul class=" incremental">
+<li>
+<span>
+Enron files for Chapter 11 bankruptcy
+</span>
+</li>
+<li>
+<span>
+UN authorizes ISAF in Afghanistan (post 9’11 attacks)
+</span>
+</li>
+<li>
+<span>
+President Karzai is selected to lead Afghan Interim Administration
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_documentation">Documentation</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>One key aspect was lots of good, easy to read documentation</p></div>
+<ul class="">
+<li>
+<span>
+netfilter hacking HOWTO
+</span>
+</li>
+<li>
+<span>
+netfilter extensions HOWTO
+</span>
+</li>
+<li>
+<span>
+Linux 2.4 Packet Filtering HOWTO
+</span>
+</li>
+<li>
+<span>
+Linux Networking-concepts HOWTO
+</span>
+</li>
+<li>
+<span>
+NAT HOWTO
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Getting into the project as both a user or developer was helped enormously by the HOWTOs.</p></div>
+<div class="paragraph"><p>The original versions of those documents were all created in early 2000.</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_the_netfilter_scoreboard">The netfilter scoreboard</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+a <em>scoreboard</em> was established
+</span>
+<ul class="">
+<li>
+<span>
+high-score for number of patches/contributions
+</span>
+</li>
+<li>
+<span>
+counts not only code but also documentation updates
+</span>
+</li>
+<li>
+<span>
+manually maintained by scoreboard
+</span>
+</li>
+<li>
+<span>
+bonus points for patches that apply to correct version
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+motivation for developers, particularly junior ones!
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Remember, this was the pre-git and even pre-bitkeeper days!</p></div>
+<div class="paragraph"><p>Guess these days, people would count this as <em>gamification</em>?</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_the_netfilter_scoreboard_april_2002">The netfilter scoreboard (April 2002)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="netfilter-scoreboard-20020408.png" alt="netfilter-scoreboard-20020408.png" width="100%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_the_netfilter_scoreboard_april_2002_2">The netfilter scoreboard (April 2002)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="netfilter-scoreboard-andras.png" alt="netfilter-scoreboard-andras.png" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_modularity_extensibility">modularity / extensibility</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+netfilter is just a set of hooks for call-back functions
+</span>
+</li>
+<li>
+<span>
+iptables matches and targets are just plug-ins for both kernel and userspace
+</span>
+</li>
+<li>
+<span>
+good documentation on the APIs and how to write one
+</span>
+</li>
+<li>
+<span>
+get people involved, implement their favorite feature
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Problem: How to distribute / maintain them?</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_patch_o_matic">patch-o-matic</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>1) The netfilter core team is maintaining a set of extensions / new·features which are not yet committed to the mainstream kernel tree.
+
+They are a collection of maybe-broken maybe-cool third-party extensions.
+
+Please note that you cannot apply any combination of any of those patches. Some of them are incompatible...·
+
+If you want to try some extensions, and be sure that they don't break each other, you can do the following:
+
+ % ./runme base KERNEL_DIR=<<where-you-built-your-kernel>>
+
+It will modify you kernel source (so back it up first!). You will have to recompile / rebuild your kernel and modules.
+
+Alternatively, if you really know what your are doing, you can use the following command in order to offer you the full list of choices. Be aware that we don't prevent you from shooting yourself in the foot.
+
+ % ./runme extra KERNEL_DIR=<<where-you-built-your-kernel>></code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_patch_o_matic_2">patch-o-matic</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Mon, 30 Oct 2000 14:28:30 +1100
+From: Rusty Russell <rusty@linuxcare.com.au>
+To: Netfilter Development Mailinglist <netfilter-devel@us4.samba.org>
+
+On Mon, Oct 23, 2000 at 09:15:23PM -1100, Daniel Stone wrote:
+> This, to me, reflects a problem. Basically, I can only see two things causing this:
+> a) no testing at all, or
+> b) a mis-paste. Please tell me it was the latter.
+
+Completely untested. I looked at the patch as I threw it into patch-o-matic.
+
+That's what patch-o-matic is for: to get stuff out there without waiting for the Rusty Linus planet alignment thing...
+
+Rusty.
+--
+Hacking time.</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_early_success">Early Success</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>What contributed to the early success with lots of developers writing netfilter/iptables code:</p></div>
+<ul class="">
+<li>
+<span>
+loads of good documentation
+</span>
+</li>
+<li>
+<span>
+modular framework with
+</span>
+<ul class="">
+<li>
+<span>
+netfilter hooks
+</span>
+</li>
+<li>
+<span>
+pluggable iptables targets + matches
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+system for maintaining non-mainline code + merging it
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>⇒ Everyone could easily write his favorite match/target/plugin</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2003_martin_josefsson">2003: Martin Josefsson</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="video-not-available-youtube-error.png" alt="video-not-available-youtube-error.png" width="50%" />
+</span></p></div>
+<div class="paragraph"><p>Martin Josefsson joins core team in August 2003</p></div>
+<ul class="">
+<li>
+<span>
+mainly optimizations e.g. on connection tracking hash tables
+</span>
+</li>
+<li>
+<span>
+he worked at large ISP where that performance actually mattered
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Historical Context:</p></div>
+<ul class="">
+<li>
+<span>
+kernel 2.6.x released in December 2003
+</span>
+</li>
+<li>
+<span>
+DPRK withdraws from nuclear non-proliferation treaty
+</span>
+</li>
+<li>
+<span>
+The US space shuttle Columbia crahes
+</span>
+</li>
+<li>
+<span>
+US launches war on Iraq; Saddam Hussein is captured
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2003_pablos_first_messages">2003: Pablos first messages</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Wed, 12 Nov 2003 00:06:11 +0100
+From: pablo neira <pablo@eurodev.net>
+To: netfilter-devel@lists.netfilter.org
+Subject: ip_conntrack_get
+
+Hi everyone,
+
+I've been for almost two weeks trying to understand netfilter code, at this point I'm trying to understand conntrack table code.
+
+I have a problem with how conntrack manages the ip_conntrack_info stuff.
+[...]
+
+Don't blame me if it's obvious for you, I'm just a guy trying to understand a *really really nice piece of code*. Thanks!
+
+cheers,
+Pablo</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_pablos_first_messages">Pablos first messages</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Wed, 03 Dec 2003 15:23:39 +0100
+From: pablo neira <pablo@eurodev.net>
+To: netfilter-devel@lists.netfilter.org
+Subject: sending event to user space
+
+Hi list!
+
+I programmed a dummy module for netfilter which tries to match a packet and if it does, it will do nothing (NF_ACCEPT) but I would want it to send an event to a program in user space to do something, how can I do that?
+
+So something like:
+
+a) packet gets my hook and do NF_ACCEPT.
+b) modules sends an event to user space.
+c) program in user space does something.
+
+Thanks!
+Pablo
+
+P.S: thanks for this *great piece of code*!!</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2004_patrick_mchardy">2004: Patrick McHardy</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="patrick-zoom.png" alt="patrick-zoom.png" width="40%" />
+</span></p></div>
+<div class="paragraph"><p>Patrick joins core team in January 2004</p></div>
+<ul class="">
+<li>
+<span>
+lots of good work in many areas; moved beyond netfilter and even entered the iproute2/tc lands ;)
+</span>
+</li>
+<li>
+<span>
+most recently suspended from core team due to questionable practises in copyright/license enforcement
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Historical Context:</p></div>
+<ul class="">
+<li>
+<span>
+Facebook was born
+</span>
+</li>
+<li>
+<span>
+Bluetooth 2.0 EDR spec released
+</span>
+</li>
+<li>
+<span>
+Skype becomes really popular
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_core_team_emeritus_members">core team emeritus members</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Fri, 09 Jan 2004 15:17:19 +1100
+From: Rusty Russell <rusty@rustcorp.com.au>
+Subject: [ANNOUNCE] Core Team Announces Emeritus Members
+
+The Netfilter Core Team has long discussed the issue of Core Team members who are no longer active. Dismissing them from the Core Team would deny them the benefits of such a prestigious title, should any become apparent.
+
+Hence the conclusion is that Marc Boucher, James Morris and Rusty Russell are now "emeritus"[1] members of the Netfilter Core Team.
+
+[...]
+
+[1] Latin for "burnt-out freeriding slacker", I believe.</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_the_story_behind_rustys_departure">the story behind Rustys departure</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class=" incremental">
+<li>
+<span>
+Until recently, I thought
+</span>
+<ul class="">
+<li>
+<span>
+Rusty simply had too many other tempting distracting projects (kernel module loader, qemu,
+paravirtualization, …)
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+Recently, Rusty told me
+</span>
+<ul class=" incremental">
+<li>
+<span>
+it was a deliberate decision to leave netfilter
+</span>
+</li>
+<li>
+<span>
+the new core team and maintainers should run the project without interference from the project father
+</span>
+</li>
+<li>
+<span>
+kids have to stand on their own feet
+</span>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2005_yasuyuki_kozakai_joins_core_team">2005: Yasuyuki Kozakai joins core team</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Yasuyuki Kozakai joins netfilter core team</p></div>
+<ul class="">
+<li>
+<span>
+member of Japanese USAGI project for Linux IPv6
+</span>
+</li>
+<li>
+<span>
+Main contribution: IPv6 connection tracking, including
+</span>
+<ul class="">
+<li>
+<span>
+nf_conntrack generalization
+</span>
+</li>
+<li>
+<span>
+conntrack estensions
+</span>
+</li>
+<li>
+<span>
+nf_nat for IPv6
+</span>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2007_pablo_neira_ayuso_joins_core_team">2007: Pablo Neira Ayuso joins core team</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Thu, 15 Feb 2007 14:02:03 +0900 (JST)
+From: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
+Subject: [ANNOUNCE]: New Coreteam Member Pablo Neira Ayuso
+
+The Netfilter Core Team is proud to announce the addition of Pablo Neira Ayuso as a new member.
+
+He has repeatedly demonstrated high insight and coding standards, and has already been responsible for several parts of the codebase, especially ctnetlink, conntrack and conntrackd.
+
+By joining the Core Team, Pablo will definitely help advance the development of the Netfilter project to a higher level.
+
+Welcome Pablo!
+
+Yasuyuki,
+on behalf of the Netfilter Core Team.</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_pablo_2009">Pablo (2009)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="pablo-2009-zoom.jpg" alt="pablo-2009-zoom.jpg" width="40%" />
+</span></p></div>
+<ul class="">
+<li>
+<span>
+initially known for work on ctnetlink and conntrackd
+</span>
+</li>
+<li>
+<span>
+later known for a jack of all [netfilter] trades
+</span>
+</li>
+<li>
+<span>
+official head of core team since 2013, already more or less de-facto before
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_harald_2009">Harald (2009)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>As I’m showing various old pictures of other people, for fairness' sake…</p></div>
+<div class="paragraph"><p>Historical Context:</p></div>
+<ul class="">
+<li>
+<span>
+President Obama is inaugurated
+</span>
+</li>
+<li>
+<span>
+Conficker virus infects 9.5 million PCs
+</span>
+</li>
+<li>
+<span>
+Michael Jackson died
+</span>
+</li>
+<li>
+<span>
+Google starts ChromeOS
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nftables_2009">nftables (2009)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Wed, 18 Mar 2009 05:29:42 +0100
+From: Patrick McHardy <kaber@trash.net>
+To: Netfilter Development Mailinglist <netfilter-devel@vger.kernel.org>
+CC: Linux Netdev List <netdev@vger.kernel.org>
+Subject: [ANNOUNCE]: First release of nftables
+
+Finally, with a lot of delay, I've just released the first full public
+version of my nftables code (including userspace), which is intended to
+become a successor to iptables. Its written from scratch and there are
+numerous differences to iptables in both features and design, so I'll
+start with a brief overview.
+
+There are three main components:
+
+- the kernel implementation
+- libnl netlink communication
+- nftables userspace frontend</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_2012_eric_leblond_and_florian_westphal">2012: Eric Leblond and Florian Westphal</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>In October 2012, Eric Leblond and Florian Westphal join core team</p></div>
+<ul class="">
+<li>
+<span>
+Eric: nf_nat port randomization, lots of nfnetlink* fixes, later also nftables
+</span>
+</li>
+<li>
+<span>
+Florian: NFQUEUE load balancing, NFQUEUE fixes and improvements, later pretty much every area
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>Also in October 2012: Harald, Martin and Yasuyuki finally enter emeritus state</p></div>
+<div class="paragraph"><p>Historical Context:</p></div>
+<ul class="">
+<li>
+<span>
+US begins retaliation action against embassy attack in Libya
+</span>
+</li>
+<li>
+<span>
+Turkey retaliates against Syria
+</span>
+</li>
+<li>
+<span>
+Windows 8 makes its debut
+</span>
+</li>
+<li>
+<span>
+Great Patent war Apple vs. Samsung
+</span>
+</li>
+<li>
+<span>
+Megaupload gets shut down
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nftables_2013">nftables (2013)</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Pablo picked up a lot of the loose ends left by Patrick after some time
+and in 2013, nftables finally goes mainline!</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>commit 96518518cc417bb0a8c80b9fb736202e28acdf96
+Author: Patrick McHardy <kaber@trash.net>
+Date: Mon Oct 14 11:00:02 2013 +0200</code></pre>
+</div></div>
+<div class="paragraph"><p><span class="image">
+<img src="pablo-iptables-bye-zoom.png" alt="pablo-iptables-bye-zoom.png" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_bugs">bugs</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Mon, 14 Jan 2002 22:33:16 +1100
+From: Rusty Russell <rusty@rustcorp.com.au>
+To: "David S. Miller" <davem@redhat.com>
+Subject: Re: Kernel 2.4.16: NetFilter Bug Report
+
+In message <20020113.231425.73653921.davem@redhat.com> you write:
+> Any ideas on that NAT timer one from cat@zip.com.au? I've for now asked Marcelo to revert that 2.4.17 change until a different fix is obtained.
+
+I am a fucking retard.
+
+I was looking at what was wrong with the code, and came up with *five* separate problems. I know the compat layer was a hack, but what the *fuck* was I doing?
+
+Read and weep,
+Rusty.
+--
+ Anyone who quotes me in their sig is an idiot. -- Rusty Russell.</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testsuite">nfsim / testsuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Big problem with lots of code, including netfilter: Lack of automatic testing.</p></div>
+<div class="paragraph"><p>Rusty returns to netfilter with <em>nfsim</em>, a netfilter simulator, co-authored with Jeremy Kerr.</p></div>
+<ul class="">
+<li>
+<span>
+nfsim runs netfilter kernel code in userspace against test suite
+</span>
+</li>
+<li>
+<span>
+emulates kernel environment in userspace
+</span>
+</li>
+<li>
+<span>
+imports netfilter kernel code + builds it in userspace
+</span>
+</li>
+<li>
+<span>
+{get,set}sockopt() wrapper for userspace tools
+</span>
+</li>
+<li>
+<span>
+can simulate allocation failures
+</span>
+</li>
+<li>
+<span>
+manual control over time (important for conntrack state tables)
+</span>
+</li>
+</ul>
+<div class="paragraph"><p>⇒ Great Idea, and lots of useful work</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testsuite_2">nfsim / testsuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Reality sucks:</p></div>
+<ul class="">
+<li>
+<span>
+very few contributions
+</span>
+</li>
+<li>
+<span>
+very few users beyond Rusty + Jeremy
+</span>
+</li>
+<li>
+<span>
+very limited adoption/use by netfilter developers
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testsuite_3">nfsim / testsuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Tue, 31 May 2005 23:48:24 +1000
+From: Rusty Russell <rusty@rustcorp.com.au>
+To: Patrick McHardy <kaber@trash.net>
+
+On Tue, 2005-05-31 at 15:02 +0200, Patrick McHardy wrote:
+> Second of all, I spent like 10 hours to verify the proposed fixes, and I am still convinced that it is correct.
+
+Which shows exactly *why* we have a testsuite. Dammit, I didn't spend all those hours on it for fun.
+
+You spent *10* hours, and the testsuite runs in 5 seconds (60 seconds counting build time the first time).
+
+<sigh></code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testsuite_4">nfsim / testsuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Reality sucks:</p></div>
+<ul class="">
+<li>
+<span>
+patches get validated only in test suite, not real kernel
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testsuite_5">nfsim / testsuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Sun, 23 Jan 2005 20:15:17 -0800
+From: "David S. Miller" <davem@davemloft.net>
+Subject: Re: [PATCH 3/2] Fix compile with NAT but without modules
+
+On Mon, 24 Jan 2005 01:33:47 +0100 Patrick McHardy <kaber@trash.net> wrote:
+
+> I'll apply your patches and push them to Dave tomorrow, bkbkits.com
+> is unreachable currently so I can't resync my tree.
+
+To be frank, this is one of several severe fallouts from Rusty's patches. I really think they were not ready for submission when he sent them to me. It even broke the build if you had modules enabled in any
+way.
+
+I'm only mentioning this because it appears that nfsim is becomming partially a crutch, because I know this is what Rusty and others use heavily for testing. Which is fine, but if your patches break the build in many ways in the real kernel tree you're relying too heavily on the userland simulator IMHO.</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testsuite_6">nfsim / testsuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>Reality sucks:</p></div>
+<ul class="">
+<li>
+<span>
+very few contributions
+</span>
+</li>
+<li>
+<span>
+very limited adoption/use by netfilter developers
+</span>
+</li>
+<li>
+<span>
+bit-rot of kernel environment simulation
+</span>
+</li>
+<li>
+<span>
+constant lag in terms of completeness
+</span>
+<ul class="">
+<li>
+<span>
+no netlink simulation, i.e. no nfnetlink/ctnetlink/nf_queue/nf_log
+</span>
+</li>
+</ul>
+</li>
+</ul>
+<div class="paragraph"><p>⇒ no replacement / successor, till today :(</p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_nfsim_testuite">nfsim / testuite</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>So all we can do is join DaveM and pray for code correctness</p></div>
+<div class="paragraph"><p><span class="image">
+<img src="davem-praying-zoom.png" alt="davem-praying-zoom.png" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_humor">humor</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Wed, 26 Feb 2003 11:54:59 +1100
+From: Rusty Russell <rusty@rustcorp.com.au>
+To: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+Subject: [netfilter-core] Re: conntrack patches
+
+> Hi Rusty,
+>
+> Last year I started to go trough all of your unpublished conntrack related patches. [...]
+
+> Are you working on the patches or plan to finish them? Or can I go back and complete the half-done job on the patches?
+
+Jozsef,
+ Let me put it this way: take over those patches and I will name my first child after you.
+
+How many beers did I owe you now?
+Rusty.</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_harald_and_ipv6_nat">Harald and IPv6 NAT</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="listingblock">
+<div class="content">
+<pre><code>Date: Thu, 20 Nov 2003 14:40:42 +0100
+From: Harald Welte <laforge@netfilter.org>
+Cc: netfilter-devel@lists.netfilter.org
+Subject: Re: NAT for IPv6
+
+On Wed, Nov 19, 2003 at 01:38:47PM +0100, Maciej Soltysiak wrote:
+> out of curiousity - are there plans to incorporate NAT into ip6tables or future pkttables ?
+
+over my dead body. NAT is what broke ipv4 end-to-end. Let's not do the same with ipv6.
+
+The only reasonable application is ipv4-to-ipv6 transition-nat.
+
+--
+- Harald Welte <laforge@netfilter.org> http://www.netfilter.org/
+============================================================================
+ "Fragmentation is like classful addressing -- an interesting early
+ architectural error that shows how much experimentation was going
+ on while IP was being designed." -- Paul Vixie</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_netfilter_workshops">netfilter Workshops</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+1998/1999/2000: Informal meetings of some of the people involved
+</span>
+<ul class="">
+<li>
+<span>
+like James + Marc + Rusty at Sydney Linux Expo
+</span>
+</li>
+<li>
+<span>
+like Harald + Rusty at Linux Beer Hike
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+<em>workshop</em> established from 2001 onwards to get developers meet up
+</span>
+</li>
+<li>
+<span>
+not every year, but almost: 13 workshops in 18 years
+</span>
+</li>
+<li>
+<span>
+invitation-only
+</span>
+</li>
+<li>
+<span>
+organization done by community for community
+</span>
+</li>
+<li>
+<span>
+sponsors typically among commercial netfilter users
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_netfilter_workshops_2">netfilter Workshops</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+2001: Enschede, Netherlands
+</span>
+</li>
+<li>
+<span>
+2003: Budapest, Hungary
+</span>
+</li>
+<li>
+<span>
+2004: Erlangen, Germany
+</span>
+</li>
+<li>
+<span>
+2005: Seville, Spain
+</span>
+</li>
+<li>
+<span>
+2007: Karlsruhe, Germany
+</span>
+</li>
+<li>
+<span>
+2008: Paris, France
+</span>
+</li>
+<li>
+<span>
+2010: Seville, Spain
+</span>
+</li>
+<li>
+<span>
+2011: Freiburg im Breisgau, Germany
+</span>
+</li>
+<li>
+<span>
+2013: Copenhagen, Denmark
+</span>
+</li>
+<li>
+<span>
+2014: Montpellier, France
+</span>
+</li>
+<li>
+<span>
+2015: Budapest, Hungary
+</span>
+</li>
+<li>
+<span>
+2016: Amsterdam, Netherlands
+</span>
+</li>
+<li>
+<span>
+2017: Faro, Portugal
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_workshop_2003_group_picture">Workshop 2003: Group Picture</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="nfws2003_group.png" alt="nfws2003_group.png" width="100%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_workshop_2005_fun_fact">Workshop 2005: Fun fact</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="unix-extinguisher-2005.jpg" alt="unix-extinguisher-2005.jpg" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_workshop_2013">Workshop 2013</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="nfws2013.jpg" alt="nfws2013.jpg" width="100%" />
+</span></p></div>
+<ul class="">
+<li>
+<span>
+2011: Kernel 3.0 is released, with netfilter/iptables
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_workshop_2014">Workshop 2014</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="nfws2014.jpg" alt="nfws2014.jpg" width="100%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_workshop_2015">Workshop 2015</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="nfws2015.jpg" alt="nfws2015.jpg" width="100%" />
+</span></p></div>
+<ul class="">
+<li>
+<span>
+Kernel 4.0 is relesaed, with netfilter/iptables and nftables
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_workshop_2016">Workshop 2016</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p><span class="image">
+<img src="nfws2016.jpg" alt="nfws2016.jpg" width="100%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_interesting_challenges">Interesting Challenges</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+iptables kernel code used to never verify ruleset integrity
+</span>
+<ul class="">
+<li>
+<span>
+you could crash kernel using malicious ruleset
+</span>
+</li>
+<li>
+<span>
+believed to be non-issue due to NET_CAP_ADMIN requirement
+</span>
+</li>
+<li>
+<span>
+assumption broke horribly when unprivileged containers appeared
+</span>
+</li>
+</ul>
+</li>
+</ul>
+<div class="paragraph"><p><span class="image">
+<img src="pablo-finger-zoom.png" alt="pablo-finger-zoom.png" width="50%" />
+</span></p></div>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_netfilter_org_infrastructure">netfilter.org infrastructure</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+self-hosted physical servers for web/svn/bugzilla/git (and even lists) for long time
+</span>
+<ul class="">
+<li>
+<span>
+lists moved to vger.kernel.org eventually
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+firewall machine in front of netfilter.org for many years: iptables on UltraSPARC
+</span>
+<ul class="">
+<li>
+<span>
+because we can, and because script kiddies don’t do SPARC assembly
+</span>
+</li>
+</ul>
+</li>
+<li>
+<span>
+netfilter.org servers for many years Linux on PPC (G5 Clusternode)
+</span>
+<ul class="">
+<li>
+<span>
+because we can, and because script kiddies don’t do PPC assembly
+</span>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_summary_why_sucessful">Summary: Why sucessful?</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class=" incremental">
+<li>
+<span>
+smart people got funded to implement things the way they want
+</span>
+</li>
+<li>
+<span>
+extensible architecture from day one
+</span>
+</li>
+<li>
+<span>
+good documentation for developers and users from day one
+</span>
+</li>
+<li>
+<span>
+passionate developers who picked netfilter as their own topic of interest
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_regrets">Regrets?</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class=" incremental">
+<li>
+<span>
+not having time for netfilter work anymore :/
+</span>
+</li>
+<li>
+<span>
+not officially stepping down sooner, giving Pablo + Patrick more credit
+</span>
+</li>
+<li>
+<span>
+conntrack/nat helpers are still in kernel space
+</span>
+</li>
+<li>
+<span>
+people think they need dynamic IPv6-to-IPv6 NA(P)T
+</span>
+</li>
+<li>
+<span>
+nfsim without replacement; netfilter kernel code remains largely without tests
+</span>
+</li>
+<li>
+<span>
+with the size and relevance of the Linux industry in 2017, why don’t people invest in automatic testsuites for netfilter (and other kernel networking code)?
+</span>
+</li>
+<li>
+<span>
+not having pushed for more ulogd adoption. Lots of people still use LOG, 17 years after ULOG and ulogd
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_thanks">Thanks</h1>
+<div class="sectionbody" style="max-width:45em">
+<ul class="">
+<li>
+<span>
+to the audience, for bearing with me
+</span>
+</li>
+<li>
+<span>
+to the netdev 2.2 committee, for inviting me
+</span>
+</li>
+<li>
+<span>
+to Rusty, for being my hero
+</span>
+</li>
+<li>
+<span>
+to Pablo, for picking up the pieces when I left
+</span>
+</li>
+<li>
+<span>
+to Dave, for being everyone’s hero
+</span>
+</li>
+<li>
+<span>
+to Jesper, for group (and other) pictures
+</span>
+</li>
+<li>
+<span>
+to every single netfilter contributor out there
+</span>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect1 slide">
+<h1 id="_eof">EOF</h1>
+<div class="sectionbody" style="max-width:45em">
+<div class="paragraph"><p>End of File</p></div>
+</div>
+</div>
+</body>
+</html>
|