{ claus.conrad }Claus Conrad2021-10-24T12:10:41Zhttps://www.clausconrad.com/Claus ConradPersonal knowledge management tools and methodologies2021-10-24T12:10:41Zhttps://www.clausconrad.com/blog/personal-knowledge-management-tools-and-methodologies/<h2 id="hierarchical-knowledge-silos" tabindex="-1">Hierarchical knowledge silos</h2>
<h3 id="strengths" tabindex="-1">Strengths</h3>
<ul>
<li>Easy to get started; user-friendly, intuitive UX</li>
<li>Built-in synchronization</li>
<li>Freemium</li>
</ul>
<h3 id="weaknesses" tabindex="-1">Weaknesses</h3>
<ul>
<li>Hard to get data out (proprietary XML etc.)</li>
<li>Do not impose/enforce structured note taking</li>
</ul>
<h3 id="examples" tabindex="-1">Examples</h3>
<ul>
<li>Microsoft OneNote (<a href="https://www.microsoft.com/en-us/p/onenote-for-windows-10/9wzdncrfhvjl?activetab=pivot:overviewtab">for Windows 10+</a>, <a href="https://www.onenote.com/Download">for Office 365/2019+</a>)
<ul>
<li>Proprietary software and storage format</li>
<li>Limited API available (Office version only)</li>
<li>Primary copy stored in the cloud (OneDrive or SharePoint)</li>
<li>Collaborate on “Notebook” level</li>
</ul>
</li>
<li><a href="https://evernote.com/">Evernote</a>
<ul>
<li>Proprietary software and storage format</li>
</ul>
</li>
<li><a href="https://www.atlassian.com/software/confluence">Atlassian Confluence</a>
<ul>
<li>Proprietary software and storage format</li>
<li>Collaborate on “Space” or “Page” (item) level</li>
</ul>
</li>
<li><a href="https://www.microsoft.com/en-us/microsoft-365/sharepoint/collaboration">Microsoft SharePoint</a>
<ul>
<li>Proprietary software and storage format</li>
<li>Collaborate on “Space” or “Page” (item) level</li>
</ul>
</li>
<li><a href="https://keep.google.com/">Google Keep</a>
<ul>
<li>Proprietary software and storage format</li>
<li>Stored in the cloud (only)</li>
</ul>
</li>
</ul>
<h2 id="graph-based-knowledge-silos" tabindex="-1">Graph-based knowledge silos</h2>
<h3 id="examples-1" tabindex="-1">Examples</h3>
<ul>
<li><a href="https://www.notion.so/">Notion</a></li>
<li><a href="https://www.thebrain.com/">The Brain</a></li>
<li><a href="https://coda.io/">Coda</a></li>
</ul>
<h2 id="local-first%2C-graph-based-knowledge-management-apps" tabindex="-1">Local-first, graph-based knowledge management apps</h2>
<h3 id="usual-features" tabindex="-1">Usual features</h3>
<ul>
<li>Notes often stored locally in a non-XML text format (Markdown etc.)</li>
<li>Graph-based navigation (links, tags)</li>
<li>Block references</li>
</ul>
<h3 id="examples-2" tabindex="-1">Examples</h3>
<ul>
<li><a href="https://www.dendron.so/">Dendron</a>
<ul>
<li>Open-source (<a href="https://github.com/dendronhq/dendron/blob/master/LICENSE.md">AGPL 3.0</a>)</li>
<li>Based on <a href="https://code.visualstudio.com/">VS Code</a></li>
<li>Selective publication
<ul>
<li>Static pages, probably hydrated as Next.js app?</li>
<li>Not SEO-friendly URLs (UUIDs)</li>
</ul>
</li>
<li>Opinionated: Hierarchy-first (canonical addresses with optional schemas), graph-based second</li>
<li>No built-in synchronization (could use Git (<a href="https://www.github.com/">GitHub</a>, <a href="https://www.gitlab.com/">Gitlab</a>, <a href="https://www.bitbucket.org/">Atlassian Bitbucket</a> etc.), <a href="https://syncthing.net/">Syncthing</a>, <a href="https://www.dropbox.com/">Dropbox</a>, etc.)</li>
</ul>
</li>
<li><a href="https://roamresearch.com/">Roam Research</a>
<ul>
<li>Proprietary, subscription-based</li>
</ul>
</li>
<li><a href="https://foambubble.github.io/foam/">Foam</a>
<ul>
<li>Based on <a href="https://code.visualstudio.com/">VS Code</a></li>
</ul>
</li>
<li><a href="https://athens-research.webflow.io/">Athens Research</a>
<ul>
<li>Open-source (<a href="https://github.com/athensresearch/athens/blob/main/LICENSE">Eclipse Public License 1.0</a>) (open-core?)</li>
<li>Stores notes in a datascript database</li>
<li>Freemium</li>
</ul>
</li>
<li><a href="https://obsidian.md/">Obsidian</a></li>
<li><a href="https://www.orgroam.com/">Org-roam</a>
<ul>
<li>Open-source (<a href="https://github.com/org-roam/org-roam/blob/master/LICENSE">GPL 3.0</a>)</li>
<li>Based on Emacs</li>
</ul>
</li>
</ul>
<h2 id="methodologies" tabindex="-1">Methodologies</h2>
<ul>
<li><a href="https://zettelkasten.de/posts/overview/">Zettelkasten</a></li>
<li><a href="https://fortelabs.co/blog/para/">PARA</a></li>
<li>Linking Your Thinking (LYT) (<a href="https://www.linkingyourthinking.com/">workshop</a>, <a href="https://www.linkingyourthinking.com/lyt-kit">kit</a>, <a href="https://www.youtube.com/channel/UC85D7ERwhke7wVqskV_DZUA/featured">YouTube</a>)</li>
<li><a href="https://www.kevinslin.com/notes/3dd58f62-fee5-4f93-b9f1-b0f0f59a9b64/">Hierarchy-first</a></li>
<li>Building a Second Brain (<a href="https://www.buildingasecondbrain.com/">workshop</a>)</li>
</ul>
Embracing Salt2021-10-17T16:51:41Zhttps://www.clausconrad.com/blog/embracing-salt/<p><img src="/assets/img/salt-2021-10-17_18-01-49.png" alt="salt" /></p>
<p>I don’t know whether to be happy or embarassed ;-)</p>
Analyzing OngoingWorlds posts2017-07-15T14:16:35Zhttps://www.clausconrad.com/blog/analyzing-ongoingworlds-posts/<p>The <a href="/blog/scrapy-example-posts-from-ongoingworlds/">previous post</a> used Scrapy to extract post data from the website OngoingWorlds. Here are a few conclusions from that spider crawl:</p>
<p>I collected the game ID, post ID and date/time for each post from the play-by-email roleplaying community OngoingWorlds into an Sqlite3 database. Even with this very limited dataset, some interesting queries can be run:</p>
<h2 id="most-popular-games-(by-number-of-posts)" tabindex="-1">Most popular games (by number of posts)</h2>
<pre><code class="language-sql">SELECT game_id, COUNT(*) FROM post GROUP BY game_id ORDER BY COUNT(*) DESC LIMIT 10;
</code></pre>
<table>
<thead>
<tr>
<th>Rank</th>
<th>Game</th>
<th>Total posts</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><a href="http://www.ongoingworlds.com/games/270">Blue Dwarf</a></td>
<td>15040</td>
</tr>
<tr>
<td>2</td>
<td><a href="http://www.ongoingworlds.com/games/1021">Hero High</a></td>
<td>3453</td>
</tr>
<tr>
<td>3</td>
<td><a href="http://www.ongoingworlds.com/games/2027">2778 A.D.</a></td>
<td>2894</td>
</tr>
<tr>
<td>4</td>
<td><a href="http://www.ongoingworlds.com/games/2242">The Land of Ecilith</a></td>
<td>2276</td>
</tr>
<tr>
<td>5</td>
<td><a href="http://www.ongoingworlds.com/games/1343">The Avengers~Lower Levels</a></td>
<td>2111</td>
</tr>
<tr>
<td>6</td>
<td><a href="http://www.ongoingworlds.com/games/2321">Heroes Association</a></td>
<td>1288</td>
</tr>
<tr>
<td>7</td>
<td><a href="http://www.ongoingworlds.com/games/1353">Hunted</a></td>
<td>1265</td>
</tr>
<tr>
<td>8</td>
<td><a href="http://www.ongoingworlds.com/games/2068">Circle of Nine</a></td>
<td>1176</td>
</tr>
<tr>
<td>9</td>
<td><a href="http://www.ongoingworlds.com/games/2455">Fairy Tail ZERO</a></td>
<td>1125</td>
</tr>
<tr>
<td>10</td>
<td><a href="http://www.ongoingworlds.com/games/1703">MLP fans!</a></td>
<td>1118</td>
</tr>
</tbody>
</table>
<h2 id="most-popular-games-(per-hour-of-the-day)" tabindex="-1">Most popular games (per hour of the day)</h2>
<pre><code class="language-sql">SELECT
game_id AS GameID,
(
SELECT strftime("%H", timestamp) AS Hour
FROM post AS inner
WHERE inner.game_id = outer.game_id
GROUP BY Hour
ORDER BY COUNT(*) DESC
LIMIT 1) AS MostPopularHour,
COUNT(*) TotalPosts
FROM post AS outer
GROUP BY GameID
ORDER BY MostPopularHour, TotalPosts DESC
</code></pre>
<p>For easier viewing I exported the result to a CSV spreadsheet, as follows:</p>
<pre><code class="language-shell">sqlite3 -header -csv results.db 'SELECT game_id AS GameID, (SELECT strftime("%H", timestamp) AS Hour FROM post AS inner WHERE inner.game_id = outer.game_id GROUP BY Hour ORDER BY COUNT(*) DESC LIMIT 1) AS MostPopularHour, COUNT(*) TotalPosts FROM post AS outer GROUP BY GameID ORDER BY MostPopularHour, TotalPosts DESC' > results-agg.csv
</code></pre>
<table>
<thead>
<tr>
<th>Hour of the day (CEST)</th>
<th>Game</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td><a href="http://www.ongoingworlds.com/games/1671">The Elite Club</a></td>
</tr>
<tr>
<td>1</td>
<td><a href="http://www.ongoingworlds.com/games/3012">The Hotel</a></td>
</tr>
<tr>
<td>2</td>
<td><a href="http://www.ongoingworlds.com/games/1021">Hero High</a></td>
</tr>
<tr>
<td>3</td>
<td><a href="http://www.ongoingworlds.com/games/1343">The Avengers~Lower Levels</a></td>
</tr>
<tr>
<td>4</td>
<td><a href="http://www.ongoingworlds.com/games/2242">The Land of Ecilith</a></td>
</tr>
<tr>
<td>5</td>
<td><a href="http://www.ongoingworlds.com/games/1403">Redwill Home for Unusual and Odd Children</a></td>
</tr>
<tr>
<td>6</td>
<td><a href="http://www.ongoingworlds.com/games/1409">Cure</a></td>
</tr>
<tr>
<td>7</td>
<td><a href="http://www.ongoingworlds.com/games/1521">Advanced</a></td>
</tr>
<tr>
<td>8</td>
<td><a href="http://www.ongoingworlds.com/games/1385">Battle of the Bands</a></td>
</tr>
<tr>
<td>9</td>
<td><a href="http://www.ongoingworlds.com/games/2962">Vale of Shadows</a></td>
</tr>
<tr>
<td>10</td>
<td><a href="http://www.ongoingworlds.com/games/2022">Pokemon Azure</a></td>
</tr>
<tr>
<td>11</td>
<td><a href="http://www.ongoingworlds.com/games/2191">The open trail</a></td>
</tr>
<tr>
<td>12</td>
<td><a href="http://www.ongoingworlds.com/games/2287">BRAIN GAMES: Raido Ravens</a></td>
</tr>
<tr>
<td>13</td>
<td><a href="http://www.ongoingworlds.com/games/1015">Bloody Gifts</a></td>
</tr>
<tr>
<td>14</td>
<td><a href="http://www.ongoingworlds.com/games/2068">Circle of Nine</a></td>
</tr>
<tr>
<td>15</td>
<td><a href="http://www.ongoingworlds.com/games/2922">Academy for Super Humans</a></td>
</tr>
<tr>
<td>16</td>
<td><a href="http://www.ongoingworlds.com/games/1703">MLP fans!</a></td>
</tr>
<tr>
<td>17</td>
<td><a href="http://www.ongoingworlds.com/games/1734">Gakuen Statalia</a></td>
</tr>
<tr>
<td>18</td>
<td><a href="http://www.ongoingworlds.com/games/2519">The Verse - Other Adventures in the Firefly Universe</a></td>
</tr>
<tr>
<td>19</td>
<td><a href="http://www.ongoingworlds.com/games/2573">Magic Agents</a></td>
</tr>
<tr>
<td>20</td>
<td><a href="http://www.ongoingworlds.com/games/270">Blue Dwarf</a></td>
</tr>
<tr>
<td>21</td>
<td><a href="http://www.ongoingworlds.com/games/1386">Another West</a></td>
</tr>
<tr>
<td>22</td>
<td><a href="http://www.ongoingworlds.com/games/2321">Heroes Association</a></td>
</tr>
<tr>
<td>23</td>
<td><a href="http://www.ongoingworlds.com/games/2200">Day After, Hero’s Past</a></td>
</tr>
</tbody>
</table>
<h2 id="most-popular-posting-hours-(cest)" tabindex="-1">Most popular posting hours (CEST)</h2>
<p><img src="/assets/img/s9Tr8zKTcp.png" alt="Graph showing total posts per hour of the day" /></p>
Scrapy example: posts from OngoingWorlds2017-07-15T13:26:11Zhttps://www.clausconrad.com/blog/scrapy-example-posts-from-ongoingworlds/<p>Note: Some knowledge of Python, databases, HTML and CSS recommended.</p>
<p>Scrapy is a software framework that allows one to write spiders and other components, which then crawl a website for the data one is interested in. It is not a graphical, point-and-click application; some programming is required. However, Scrapy’s learning curve is not steep and the documentation is excellent. Scrapy is also free, open-source, and can be run on a number of services, or simply on ones computer.</p>
<p>For this example, I am going to scrape OngoingWorlds, a community of “play-by-email” (PBEM) roleplayers. The name is a bit of a misnomer, as these games are played through the web these days, at least on OngoingWorlds. Also called “interactive storytelling”, PBEM are roleplaying games where a number of people collaborate to tell a story by alternately posting (usually) a few paragraphs, each post from the view of (one of) their character(s) in the game. Because these games depend on people interacting without too much delay, I wanted to find one where the majority of posting happened during the evening in my timezone. This information does not appear on the OngoingWorlds website, but could be answered quite easily with a database of all posts. This is where Scrapy comes in.</p>
<h2 id="installation" tabindex="-1">Installation</h2>
<p>The first step is of course to install it. Scrapy can be run using Python 2.7, 3.3 or newer. For this “crawl” I decided on Python 3.5. On Ubuntu 16.04 the commands to install everything were:</p>
<pre><code class="language-shell">sudo apt install -y python3-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev pip3 install ipython scrapy
</code></pre>
<p>For other operating systems or in case of problems, there is an extensive <a href="https://doc.scrapy.org/en/latest/intro/install.html">installation guide</a>.<br />
(Note: I did not make a virtual environment for my installation, but that would probably be a good idea and their guide recommends it.)</p>
<h2 id="project-creation" tabindex="-1">Project creation</h2>
<p>There are several terms in Scrapy that may need some explanation:</p>
<ul>
<li>
<p>A <strong>spider</strong> is the code that does most of the actual heavy-lifting, extracting the interesting data and links to follow from the pages’ HTML code.</p>
</li>
<li>
<p>An <strong>item</strong> is the daper month: 1
On the following day: 18ta that makes up one set of extracted information. In this example, I want to scrape posts. Each overview page on OngoingWorlds lists up to 15 “post items”.</p>
</li>
<li>
<p>Once the spider has extracted data from a page and created an item from it, you probably want to do something with it. In my case I decided to store it in a simple database (Sqlite3). Scrapy feeds each extracted item through an <strong>item pipeline</strong>, a fancy word for the code that contains the logic about what to do with each item: in the pipeline, one could do further cleaning or validation on the extracted data, discard it (for example if duplicates were scraped), store it or otherwise process it.</p>
</li>
</ul>
<p>While one could probably store the code of the spider(s), item(s) and item pipeline(s) as well as configuration all in one file, it is easier to have them in separate files. Scrapy has a handy feature to create some boilerplate (i.e. mostly blank) files, which make getting started quicker than having to create all of these files from scratch:</p>
<pre><code class="language-shell">scrapy startproject ow
</code></pre>
<h2 id="defining-the-post-data" tabindex="-1">Defining the post data</h2>
<p>For each post I wanted to store the following:</p>
<ul>
<li>
<p>The <strong>unique ID of the post</strong>, to avoid accidentally scraping the same post twice.</p>
</li>
<li>
<p>The <strong>game’s ID</strong>, since each post belongs to exactly one game.</p>
</li>
<li>
<p>And of course the <strong>date/time</strong> of the post, to be able to create statistics about the most popular posting time per game.</p>
</li>
</ul>
<p>Our new project has a file for item definitions, aptly called <em><a href="http://items.py">items.py</a></em>, where I placed my item definition:</p>
<pre><code class="language-python">class OwPost(scrapy.Item):
id = scrapy.Field()
game_id = scrapy.Field()
timestamp = scrapy.Field()
</code></pre>
<h2 id="storing-the-extracted-posts" tabindex="-1">Storing the extracted posts</h2>
<p>Storing the posts in a database is done in an item pipeline. Using <em>scrapy startproject</em> already created the file <em><a href="http://pipelines.py">pipelines.py</a></em>. Since I wanted to use the simple Sqlite3 database, I inserted the following line at the top of this
file:</p>
<pre><code class="language-python">import sqlite3
</code></pre>
<p>I want to open a connection to my database when the spider starts running, and close it when the spider stops. In an item pipeline, one can define some code that runs at these times. I added the following method to the pipeline class to open the database connection at the start:</p>
<pre><code class="language-python">def open_spider(self, spider):
self.conn = sqlite3.connect("results.db")
self.conn.execute("CREATE TABLE IF NOT EXISTS post (id INT NOT NULL, game_id INT NOT NULL, timestamp DATETIME NOT NULL, UNIQUE(game_id, id))").close()
self.conn.commit()
</code></pre>
<p>SQL is not really within the scope of this article, but this code simply creates a table with a column for each of the fields from the items, unless that table already exists in the database, like it would on subsequent runs of the spider.</p>
<p>And to close the connection at the end, I added this method to the pipeline created by Scrapy:</p>
<pre><code class="language-python">def close_spider(self, spider):
self.conn.close()
</code></pre>
<p>The most important task of this file is to insert the scraped post into the database. This is done by adding by adding a bit of SQL code to the already created method <em>process_item</em>:</p>
<pre><code class="language-python">def process_item(self, item, spider):
self.conn.execute("INSERT OR IGNORE INTO post (id, game_id, timestamp) VALUES (?, ?, ?)", (item["id"], item["game_id"], item["timestamp"])).close()
self.conn.commit()
return item
</code></pre>
<p>This method is called once for each item extracted by the spider, and it simply inserts a new row in the database table. The “OR IGNORE” instructs Sqlite3 to ignore duplicate posts without an error.</p>
<h2 id="implementing-the-spider" tabindex="-1">Implementing the spider</h2>
<p>The meat of the code goes into the file <em>spiders/ow_spider.py</em>. I am going to use regular expressions to find the URLs that the spider should follow, so I added this at the top:</p>
<pre><code class="language-python">import re
</code></pre>
<p>My spider also needs to parse the post dates (which are in the format “Jul 15, 2017, 2:36pm”) into “real” dates (which are easier to store and compare), let’s use the <em>datetime</em> module for that:</p>
<pre><code class="language-python">from datetime import datetime
</code></pre>
<p>And another line for the top, so the spider can create the <em>OwPost</em> items:</p>
<pre><code class="language-python">from ow.items import OwPost
</code></pre>
<p>When I yet was unsure how I would implement the logic for following links, I wanted to make sure that Scrapy never follows links that point outside of OngoingWorlds, such as to Facebook. Spiders have a property <em>allowed_domains</em>, which I configured right below the auto-created <em>name = ‘ow’</em>:</p>
<pre><code class="language-python">allowed_domains = [
"www.ongoingworlds.com"
]
</code></pre>
<p>From browsing the website I knew that all the posts could be reached via links from a specific starting point, which can be configured using the <em>start_urls</em> property of the spider:</p>
<pre><code class="language-python">start_urls = [
"http://www.ongoingworlds.com/games"
]
</code></pre>
<p>The spider has two main tasks:</p>
<ol>
<li>
<p>Extracting the items (structured data) from the pages’ HTML code</p>
</li>
<li>
<p>Identifying further links that should be followed (i.e. also downloaded and parsed, in addition to the <em>start_urls</em>) ) and adding these to the crawl</p>
</li>
</ol>
<p>To implement both of these tasks, the <em>shell</em> feature of Scrapy is extremely useful. Using the shell one can interactively try out various code for extracting the desired data from a page’s HTML code. To run the interactive shell I entered:</p>
<pre><code class="language-shell">scrapy shell "http://www.ongoingworlds.com/games"
</code></pre>
<p>Any Python code can be run from the shell, and the HTML from the downloaded page is available with the <em>response</em> variable.</p>
<p>After some experimentation I came up with the following method for my spider, which identifies the “interesting” links on the current page and instructs Scrapy to add them to its download queue. I suspect that there are easier ways to do this, but this worked for me:</p>
<pre><code class="language-python">def collect_links(self, response):
for url in response.xpath('//a/@href').extract():
url = response.urljoin(url)
# /games/page/NNNN
if re.match(r"^http:\/\/www\.ongoingworlds\.com\/games\/page\/\d+$", url):
yield scrapy.Request(url)
# /games/NNNN
if re.match(r"^http:\/\/www\.ongoingworlds\.com\/games\/\d+$", url):
yield scrapy.Request(url + "/posts", callback=self.parse_posts)
# /games/NNNN/posts/page/NNNN
if re.match(r"^http:\/\/www\.ongoingworlds\.com\/games\/\d+\/posts\/page\/\d+", url):
yield scrapy.Request(url, callback=self.parse_posts)
</code></pre>
<p>The code uses XPath to extract all link targets ([). Because some of the links could be relative (not starting with the full domain name), the third line converts them to absolute URLs. The three <em>if</em> statements use regular expressions to match different types of links that I am interested in:</p>
<ol>
<li>
<p>_Yield_ing a <em>Request</em> adds the link to Scrapy’s queue. The first “if” statement matches links to listings of games. These pages do not contain any posts themselves, but I need their content to find links to the actual games (and thus, listings of their posts). By <strong>not</strong> specifying a <em>callback</em>, Scrapy will default to parse these URLs with the method <em>parse</em> in the spider. I’ll define the contents of this method shortly.</p>
</li>
<li>
<p>The second “if” matches links to actual games. From browsing OngoingWorlds manually, I know that the list of posts for each game can be reached by adding <em>/posts</em> to these URLs. I have added the callback <em>parse_posts</em> to the request so that I can extract posts from these pages.</p>
</li>
<li>
<p>If a game has more than 15 posts, the older ones are separated onto further listing pages. The third “if” finds the URLs to these listing pages, with the same callback as before, since posts should be extracted here too.</p>
</li>
</ol>
<p>The default callback is called <em>parse</em> and this method needs to exist, because it will be run for the <em>start_urls</em> and the listings of games. Since there is no data to scrape from these pages, this method simply delegates to the <em>collect_links</em> method defined above:</p>
<pre><code class="language-python">def parse(self, response):
"""Used for pages that only contain links to follow, but no data to scrape"""
yield from self.collect_links(response)
</code></pre>
<p>Two of the <em>if</em> statements above referred to the callback <em>parse_posts</em>. This method has the following code:</p>
<pre><code class="language-python">def parse_posts(self, response):
"""Used to scrape data about posts"""
# Extract game ID from URL. Should always exist because this parser is only used for matching URLs
game_id = int(re.match(r"^http:\/\/www\.ongoingworlds\.com\/games\/(\d+)\/posts", response.url).groups()[0])
### Parse posts (post_id, timestamp)
post_summary_selectors = response.css(".post-summary")
if len(post_summary_selectors):
for post_summary_selector in post_summary_selectors:
post_id = None
timestamp = None
links = post_summary_selector.css("a.post-summary__link::attr(href)")
if len(links):
link = links.extract_first()
post_id = int(re.match(r"^http:\/\/www\.ongoingworlds\.com\/games\/\d+\/posts\/(\d+)$", response.urljoin(link)).groups()[0])
dates = post_summary_selector.css(".date::text")
if len(dates):
date = dates.extract_first()
timestamp = datetime.strptime(date, "%b %d, %Y, %I:%M%p")
if post_id and timestamp:
yield OwPost(game_id=game_id, id=post_id, timestamp=timestamp)
else:
self.logger.info("No post summaries found: %s" % (response.url, ))
# Add further pages to scrape
yield from self.collect_links(response)
</code></pre>
<p>Some notes about <em>parse_posts</em>:</p>
<ul>
<li>
<p>Line 5 has a regular expression that extracts the game’s ID from the URL.</p>
</li>
<li>
<p>Line 9 identifies all the DIV elements which contain post summaries. Chrome’s developer console and Scrapy’s shell were useful for finding the right CSS selector for these.</p>
</li>
<li>
<p>To make debugging the spider easier, I added an if/else to output some information in case the page did not have any post summaries on it. This was expected as some games simply have not had any posts to them yet.</p>
</li>
<li>
<p>Two more CSS selectors extract the post ID and date/time from elements inside the post summaries.</p>
</li>
<li>
<p>If this extraction was successful, the method then yields (returns) this data, converted to an OwPost item.</p>
</li>
<li>
<p>Finally, I also want to collect further links to follow from the post listing pages.</p>
</li>
</ul>
<h2 id="spider-configuration" tabindex="-1">Spider configuration</h2>
<p>Scrapy has lots of configuration options, e.g. to limit the crawl rate (to avoid being banned), for logging, and so on. To enable my item pipeline, I simply had to uncomment this code in the automatically generated <em><a href="http://settings.py">settings.py</a></em>:</p>
<pre><code class="language-python">ITEM_PIPELINES = {
'ow.pipelines.OwPipeline': 300,
}
</code></pre>
<p>To avoid too much noisy output during the actual crawl, I added the following configuration at the bottom:</p>
<pre><code class="language-python">LOG_SHORT_NAMES = True
LOG_LEVEL = "INFO"
</code></pre>
<h2 id="starting-the-crawl" tabindex="-1">Starting the crawl</h2>
<p>Now that all the code is in place, the scraper could be started with the following command (with “ow” being the name defined in <em>ow_spider.py</em>):</p>
<pre><code class="language-shell">scrapy crawl ow
</code></pre>
<p>Because I wanted to run this from my laptop and did not want having to start over in case of e.g. connection issues, I used the “jobs” feature of Scrapy to be able to restart from the point of failure. For that you have to create an empty directory and tell scrapy to use it:</p>
<pre><code class="language-shell">mkdir crawls
scrapy crawl ow -s JOBDIR=crawls/20170715
</code></pre>
<h2 id="summing-up" tabindex="-1">Summing up</h2>
<p>After some time, Scrapy is finished and shows some statistics about the crawl:</p>
<pre><code class="language-text">2017-07-15 12:34:11 [scrapy] INFO: Crawled 6092 pages (at 79 pages/min), scraped 84004 items (at 1185 items/min)
2017-07-15 12:35:07 [scrapy] INFO: Closing spider (finished)
2017-07-15 12:35:07 [scrapy] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 2154032,
'downloader/request_count': 6165,
'downloader/request_method_count/GET': 6165,
'downloader/response_bytes': 43682979,
'downloader/response_count': 6165,
'downloader/response_status_count/200': 6165,
'dupefilter/filtered': 53515,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2017, 7, 15, 10, 35, 7, 43800),
'item_scraped_count': 85099,
'log_count/INFO': 148,
'memusage/max': 98533376,
'memusage/startup': 50962432,
'request_depth_max': 504,
'response_received_count': 6165,
'scheduler/dequeued': 6164,
'scheduler/dequeued/disk': 6164,
'scheduler/enqueued': 6164,
'scheduler/enqueued/disk': 6164,
'start_time': datetime.datetime(2017, 7, 15, 9, 46, 11, 54206)}
2017-07-15 12:35:07 [scrapy] INFO: Spider closed (finished)
</code></pre>
<p>And the post data is in the Sqlite3 database:</p>
<pre><code class="language-shell">sqlite3 results.db "SELECT COUNT(*) FROM post"
# 80239
</code></pre>
<p>There you have it, a simple web crawler that would have taken much longer to develop and run without Scrapy. Analyzing the collected posts might be an idea for another article. I hope this was useful to someone :)</p>
Page constantly reloads after logging in to Outlook on the web2016-10-08T11:52:16Zhttps://www.clausconrad.com/blog/page-constantly-reloads-after-logging-in-to-outlook-on-the-web/<ol>
<li>
<p>Click “Settings” in the menu, or enter “chrome://settings” into the address bar:</p>
</li>
<li>
<p>Scroll down and click “Show advanced settings…”:</p>
<p><img src="/assets/img/Selection_340.png" alt="Screenshot showing the link 'Show advanced settings...'" /></p>
</li>
<li>
<p>Under “Privacy”, click “Content settings…”:</p>
<p><img src="/assets/img/Selection_341.png" alt="Screenshot showing the button 'Content settings'" /></p>
</li>
<li>
<p>Under “Cookies”, click “All cookies and site data…”:</p>
<p><img src="/assets/img/Selection_339.png" alt="Screenshot showing the button 'All cookies and site data...'" /></p>
</li>
<li>
<p>Enter “office” into the search box, then click “Remove all shown”:</p>
<p><img src="/assets/img/Selection_338.png" alt="Screenshot showing 'office' typed into the search box" /></p>
</li>
</ol>
<p>You might or might not have to login again after following these steps, but Outlook finished loading after I did this.</p>
Using the GPG renderer to protect Salt pillar items2016-05-21T16:01:43Zhttps://www.clausconrad.com/blog/using-the-gpg-renderer-to-protect-salt-pillar-items/<h2 id="note-about-virtual-machines" tabindex="-1">Note about virtual machines</h2>
<p>In order to generate a key pair, entropy (“randomness”) is required. Entropy is usually generated from user input via the keyboard and mouse, which are not available inside virtual machines. Key pair generation might thus fail in a virtual machine, unless we generate some entropy beforehand.</p>
<p>If you are using a VM and experience long delays when generating a key pair (see below), run the following two commands first:</p>
<pre><code class="language-shell"># For Debian and Ubuntu, otherwise install _rng- tools_ using the system's package manager
sudo apt install rng-tools
sudo rngd -r /dev/urandom
</code></pre>
<p>Alternatively, you can create the key pair on a physical machine and copy the directory to the master.</p>
<h2 id="notes-for-freebsd" tabindex="-1">Notes for FreeBSD</h2>
<p>The salt master looks for the GnuPG private key(s), to decrypt pillar items, in the location <em>/etc/salt/gpgkeys</em> on Linux and in <em>/usr/local/etc/salt/gpgkeys</em> on FreeBSD. I could not find any documentation on configuring this path. If you use FreeBSD, change any references to “/etc/salt/gpgkeys” below to “/usr/local/etc/salt/gpgkeys”.</p>
<p>The package “rng-tools” mentioned above does not appear to exist on FreeBSD. Interestingly, I did not have entropy problems when generating a GnuPG key pair on a virtualized FreeBSD instance.</p>
<p>To install GnuPG version 1 (version 2 does not work, SaltStack expects the executable to be called “gpg”) under FreeBSD, run <code>sudo pkg install gnupg1</code>.</p>
<h2 id="creating-a-key-pair" tabindex="-1">Creating a key pair</h2>
<p>On the salt master, complete the following steps to create a GnuPG key pair.</p>
<p>Create a directory to hold the private key:</p>
<pre><code class="language-shell">sudo mkdir -p /etc/salt/gpgkeys
</code></pre>
<p>Set appropriate permissions for the directory holding the private key:</p>
<pre><code class="language-shell">sudo chmod 0700 /etc/salt/gpgkeys
</code></pre>
<p>Create a GnuPG key pair in the created directory:</p>
<pre><code class="language-shell">sudo gpg --gen-key --homedir /etc/salt/gpgkeys
</code></pre>
<p>When asked for the type of key you want, enter 1 and press Enter.</p>
<p>When asked for a keysize, the default of 2048 should be safe enough for the next decades, though 4096 is becoming a more popular choice these days.</p>
<p>The key validity is not really relevant, as you probably won’t need to publish this key pair to a key server - I’d go with “0” (key does not expire) or a long validity, say “10y” for 10 years. If you choose a shorter period here, you can always extend the key validity later.</p>
<p>The “real name” would be something that let’s you, and any other persons managing pillar data for the salt master, identify the salt master - for example its hostname. E-mail and comment can be left empty.</p>
<p>In the next step, make sure <strong>not</strong> to use a password, since the salt master is unable to supply the password when it uses gpg non-interactively.</p>
<h2 id="key-pair-backup-and-distribution" tabindex="-1">Key pair backup and distribution</h2>
<p>We can now export the secret key, and keep it in a safe place:</p>
<pre><code class="language-shell">sudo gpg --homedir /etc/salt/gpgkeys --export-secret-keys --armor > /media/usbstick/salt-master.key
</code></pre>
<p>…and the public key, which can be distributed to other administrators and even kept in version control:</p>
<pre><code class="language-shell">sudo gpg --homedir /etc/salt/gpgkeys --export --armor > /git/salt-master/salt-master.pub
</code></pre>
<p>The public key can be imported on workstations as follows:</p>
<pre><code class="language-shell">gpg --import /git/salt-master/salt-master.pub
</code></pre>
<h2 id="encrypting-secrets" tabindex="-1">Encrypting secrets</h2>
<p>If we want to encrypt a password, say for MySQL, we can encrypt it as follows:</p>
<pre><code class="language-shell">echo -n "my-super-secret-password" | gpg --armor --encrypt -r KEYNAME
</code></pre>
<p>…where KEYNAME is the name of the salt master chosen during key creation, for example the hostname.</p>
<p>If we have some secret pillar data in a file, say a private key for SSH, we can encrypt it like this:</p>
<pre><code class="language-shell">cat private.key | gpg --armor --encrypt -r KEYNAME
</code></pre>
<p>…again, KEYNAME here is the name of the salt master’s GnuPG key entered as “Real name” during the key creation.</p>
<p>Either of the above command spits out a long “message”, which contains the encrypted version of our secret pillar item. To use this in a pillar SLS file, add the following line to the top of the SLS file:</p>
<p><code>#!yaml|gpg</code></p>
<p><strong>Note:</strong> One can mix and match both encrypted and non-encrypted pillars in one YAML file, as long as it has the above line at the top.</p>
<p>…and insert the output from GnuPG like any other long string in the SLS file:</p>
<pre><code class="language-yaml">mysql_server:
password: |
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
LsmXesQMUpdqCZQL1zzzoMYWGeU7mERsXFIv43y0gwt55CfZi8RTrQMhaNiJiJcM
... (snip) ...
=A2K/
-----END PGP MESSAGE-----
</code></pre>
<p>On the salt master, we can test decryption of the encrypted pillar data:</p>
<pre><code class="language-shell">sudo salt mysql-server pillar.items
</code></pre>
<p>…which outputs the decrypted pillars, as they would be used when referenced from state SLS files:</p>
<pre><code class="language-text"> mysql_server:
----------
password:
my-super-secret-password
</code></pre>
<p>Now we can safely commit secret pillar data to version control.</p>
<p><strong>Don’t forget to backup the key pair!</strong></p>
Updating to latest "pass" on Ubuntu 14.042016-05-02T19:11:38Zhttps://www.clausconrad.com/blog/updating-to-latest-pass-on-ubuntu-14-04/<p>To get the latest and greatest version:</p>
<ol>
<li>
<p>Install <a href="https://launchpad.net/ubuntu/xenial/amd64/tree/1.7.0-3">tree v1.7.0</a></p>
</li>
<li>
<p>Download <a href="https://www.passwordstore.org/">pass v1.6.5</a> (tarball)</p>
</li>
<li>
<p><code>unxz password-store-1.6.5.tar.xz</code></p>
</li>
<li>
<p><code>tar xf password-store-1.6.5.tar</code></p>
</li>
<li>
<p><code>cd password-store-1.6.5</code></p>
</li>
<li>
<p><code>sudo make install</code></p>
</li>
</ol>
Create a FreeBSD GCE instance with salt-cloud2016-04-16T07:18:37Zhttps://www.clausconrad.com/blog/create-a-freebsd-gce-instance-with-salt-cloud/<ul>
<li>
<p>Assuming we have a working command line such as this:</p>
<pre><code class="language-shell">gcloud compute instances create my-freebsd-host --image freebsd-10-3-release-amd64 --image-project=freebsd-org-cloud-dev
</code></pre>
</li>
<li>
<p>First we have to find the URI of the public image:</p>
<pre><code class="language-shell">gcloud compute images list --project freebsd-org-cloud-dev --uri --regexp freebsd-10-3-release-amd64
</code></pre>
<p>…which gives the following URI in this case:</p>
<p><em><a href="https://www.googleapis.com/compute/v1/projects/freebsd-org-cloud-dev/global/images/freebsd-10-3-release-amd64">https://www.googleapis.com/compute/v1/projects/freebsd-org-cloud-dev/global/images/freebsd-10-3-release-amd64</a></em></p>
</li>
<li>
<p>Now the URI can be used in a salt-cloud profile instead of the image name, for example:</p>
<pre><code class="language-shell">sudo nano /etc/salt/cloud.profiles.d/my-freebsd-host.conf
</code></pre>
<pre><code class="language-text">my-freebsd-host:
image: "https://www.googleapis.com/compute/v1/projects/freebsd-org-cloud-dev/global/images/freebsd-10-3-release-amd64"
size: n1-standard-2
location: europe-west1-b
network: default
provider: gce
ssh_username: freebsd
</code></pre>
</li>
</ul>
<p>Note to self: remember to escape the URI string using quotation marks ;-)</p>
<h2 id="summary" tabindex="-1">Summary</h2>
<p>When an instance is created from an image using either <code>gcloud compute instance create</code> or <code>salt-cloud -p profile create</code>, both utilities search for the image in the same project as the instance as well as the “well-known image projects”, which are “centos-cloud, coreos-cloud, debian-cloud, google-containers, opensuse-cloud, rhel-cloud, suse-cloud, ubuntu-os-cloud, windows-cloud”.</p>
<p><code>gcloud</code> let’s you use images from other projects by specifying the <code>--image-project</code> parameter, while <code>salt-cloud</code> does not (presumably because <em>libcloud</em> does not support it either, this Apache library is used by <code>salt-cloud</code> under the hood). However, by using <code>gcloud</code> to find the URI of the public image we want to use, we can get <code>salt-cloud</code> to use any publicly available image for our instances.</p>
<p>Kudos to <a href="https://agam.github.io/post/2015/08/19/freebsd-on-gce-the-last-post/">Agam</a> for pointing me at the freebsd-org-cloud-dev image repository in the first place.</p>
Shutdown HTPC from Vera controller2016-03-17T19:31:45Zhttps://www.clausconrad.com/blog/shutdown-htpc-from-vera-controller/<ol>
<li>
<p>Make sure that the HTPC can always be reached from Vera, by giving it a static IP address or a DHCP reservation (using the DHCP server/router).</p>
</li>
<li>
<p>Install EventGhost on the HTPC.</p>
</li>
<li>
<p>In the Options of EventGhost, enable it to start automatically.</p>
</li>
<li>
<p>Create an empty folder somewhere and an empty HTML file inside (I created C:\Users\USERNAME\eventghost\eventghost.html).</p>
</li>
<li>
<p>Click “Add plugin” > “Webserver” (at the bottom of the list, in my case).</p>
</li>
<li>
<p>Configure the plugin to listen on a port (e.g. 8123) and set the document root to the folder containing the HTML file (e.g. C:\Users\USERNAME\eventghost).</p>
</li>
<li>
<p>Right-click the top of the “Configuration tree” in EventGhost and add a macro.</p>
</li>
<li>
<p>Select “Power Management” > “Turn off computer”, optionally check the box to force turning off (in case some program does not stop correctly or other users are logged on - data loss may occur though).</p>
</li>
<li>
<p>Right-click the macro folder and add an event. Name it “HTTP.Shutdown”. (“Shutdown” can really be anything, as long as it is the same in the luup code used in Vera.)</p>
</li>
<li>
<p>Find or create a suitable scene in Vera’s UI7 and in step 3, select to run some luup code. Enter the following command:</p>
<pre><code class="language-lua">luup.inet.wget("http://IP-OF-THE-HTPC/eventghost.html?Shutdown")
</code></pre>
</li>
</ol>
Installing tarsnap on Linux Mint 17.32015-12-31T18:23:33Zhttps://www.clausconrad.com/blog/installing-tarsnap-on-linux-mint-17-3/<h2 id="downloading-and-verifying-tarsnap" tabindex="-1">Downloading and verifying tarsnap</h2>
<ol>
<li>
<p>Visit the <a href="https://www.tarsnap.com/download.html">Tarsnap download page</a> to find the latest version (look for “source tarball”). At the time of writing, this command downloads the latest version for Linux:</p>
<pre><code class="language-shell">wget https://www.tarsnap.com/download/tarsnap-autoconf-1.0.36.1.tgz
</code></pre>
</li>
<li>
<p>Visit the <a href="https://www.tarsnap.com/download.html">Tarsnap download page</a> to find the latest version of the “signed SHA256 hash file”. At the time of writing, this command downloads the latest version of the signed SHA256 hash file:</p>
<pre><code class="language-shell">wget https://www.tarsnap.com/download/tarsnap-sigs-1.0.36.1.asc
</code></pre>
</li>
<li>
<p>Visit the <a href="https://www.tarsnap.com/compiling.html">Tarsnap compiling page</a> to find the latest version of the signing key (look for “Tarsnap 20XX code signing GPG key”). At the time of writing, this command downloads the latest version of the signing key:</p>
<pre><code class="language-shell">wget https://www.tarsnap.com/tarsnap-signing-key-2015.asc
</code></pre>
</li>
<li>
<p>If you have never run “gpg” before (or are not sure whether you have), run it once:</p>
<pre><code class="language-shell">gpg
</code></pre>
<p>…then press CTRL+C to exit gpg.</p>
</li>
<li>
<p>Import the previously downloaded signing key into gpg. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">gpg --import tarsnap-signing-key-2015.asc
</code></pre>
</li>
<li>
<p>Verify the signature of the SHA256 hash file. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">gpg --decrypt tarsnap-sigs-1.0.36.1.asc
</code></pre>
</li>
<li>
<p>Verify that the output of the previous command included a line similar to the following (with emphasis on the word “Good”):</p>
<p><em>gpg: <strong>Good</strong> signature from “Tarsnap source code signing key (Colin Percival)”</em></p>
<p>You will likely also see this warning:</p>
<p><em>gpg: WARNING: This key is not certified with a trusted signature!</em></p>
<p>Ignoring this warning is a slight security risk, unfortunately avoiding it requires knowledge of the “web of trust” and GnuPG which is outside the scope of this document. Ignore it at your own peril or see the <a href="https://www.tarsnap.com/compiling.html">Tarsnap compiling page</a> for more links in the section “Download verification”.</p>
</li>
<li>
<p>Verify the hash (signature) of the “source tarball” you downloaded during the first step. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">shasum -a 256 tarsnap-autoconf-1.0.36.1.tgz
</code></pre>
<p>Now compare the output of this command with the output of the previous command and make sure that the hash (long string of digits and characters) matches. At the time of writing, the displayed hash was “a2909e01e2f983179d63ef2094c42102c92c716032864e66ef25ae341ea28690”.</p>
</li>
</ol>
<h2 id="building-tarsnap" tabindex="-1">Building tarsnap</h2>
<ol>
<li>
<p>Install a couple of software packages that are required to build tarsnap from the downloaded source code:</p>
<pre><code class="language-shell">sudo apt-get install -y gcc libc6-dev make libssl-dev zlib1g-dev e2fslibs-dev
</code></pre>
</li>
<li>
<p>Extract the source code from the downloaded file, replacing the file name with the one you downloaded during the first step. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">tar -xf tarsnap-autoconf-1.0.36.1.tgz
</code></pre>
</li>
<li>
<p>Change to the directory with the same name as the file downloaded during the first step. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">cd tarsnap-autoconf-1.0.36.1/
</code></pre>
</li>
<li>
<p>Prepare for building the source code:</p>
<pre><code class="language-shell">./configure
</code></pre>
</li>
<li>
<p>Build the source code:</p>
<pre><code class="language-shell">make all
</code></pre>
</li>
<li>
<p>Install the binary (application) to the default directories:</p>
<pre><code class="language-shell">sudo make install
</code></pre>
</li>
<li>
<p>Change to the parent directory:</p>
<pre><code class="language-shell">cd ..
</code></pre>
</li>
<li>
<p>Optionally clean up (delete the downloaded and extracted files); replace the file names in the commands with those matching the files you downloaded. At the time of writing, the following commands were valid:</p>
<pre><code class="language-shell">rm tarsnap-autoconf-1.0.36.1.tgz
rm tarsnap-signing-key-2015.asc*
rm tarsnap-sigs-1.0.36.1.asc*
rm -r tarsnap-autoconf-1.0.36.1
</code></pre>
</li>
</ol>
<h2 id="configuring-tarsnap" tabindex="-1">Configuring tarsnap</h2>
<ol>
<li>
<p>Move the sample configuration file to the location of the “real” configuration file:</p>
<pre><code class="language-shell">sudo mv /usr/local/etc/tarsnap.conf.sample /usr/local/etc/tarsnap.conf
</code></pre>
</li>
<li>
<p>If you haven’t already, create a tarsnap account and deposit some funds (tarsnap is a prepaid service). Visit the <a href="https://www.tarsnap.com/gettingstarted.html">Tarsnap Getting started page</a> for more details. If you already have an account (i.e. you are using tarsnap on another machine or server), this can be skipped. One tarsnap account can be used to backup multiple devices.</p>
</li>
<li>
<p>Create a key file for this machine. In the command below, replace “<a href="mailto:me@example.com">me@example.com</a>” with your e-mail address (the one used when you registered on the tarsnap web site) and replace “mybox” with a name that helps you identify this machine (hostname or IP recommended):</p>
<pre><code class="language-shell">sudo tarsnap-keygen --keyfile /root/tarsnap.key --user me@example.com --machine mybox
</code></pre>
<p>When asked, enter the password for your tarsnap account (the one you used when registering on the tarsnap web site).</p>
</li>
<li>
<p>Copy the generated key file (path “/root/tarsnap.key”) to another machine and keep it safe. <strong>The importance of this step cannot be stretched enough!</strong> Remember, you are setting up a backup for this machine because something bad might happen to it. If it does, you will need your key file to restore your backup from the tarsnap servers. Some suggestions for possible methods of backing up your key file are mentioned in the section “Keep your key file safe” of the <a href="https://www.tarsnap.com/gettingstarted.html">Getting started with tarsnap</a> page. <em>If you don’t backup the key file now, you might as well skip the remaining steps.</em></p>
</li>
</ol>
<h2 id="downloading-and-installing-acts" tabindex="-1">Downloading and installing acts</h2>
<p>Tarsnap follows the UNIX philosophy of keeping things simple, it tries to do only a few things (namely encrypting, decrypting and transferring backups) and do them well. Scheduling backups and removing old backups are not features included in tarsnap itself. Fortunately a number of helper scripts/applications exist for those tasks. I recommend acts (short for “Another Calendar-based Tarsnap Script”).</p>
<ol>
<li>
<p>Visit the <a href="https://github.com/alexjurkiewicz/acts/releases/latest">Latest acts release page</a> to find the link to the latest stable version of acts.</p>
</li>
<li>
<p>Download acts using the link at the bottom of the page you just opened. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">wget https://github.com/alexjurkiewicz/acts/archive/1.2.tar.gz
</code></pre>
</li>
<li>
<p>Extract the contents of the downloaded archive. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">tar xzf 1.2.tar.gz
</code></pre>
</li>
<li>
<p>Change to the directory containing the extracted files. At the time of writing, this was achieved using the following command:</p>
<pre><code class="language-shell">cd acts-1.2
</code></pre>
</li>
<li>
<p>Move the sample configuration to the location of the “real” configuration file:</p>
<pre><code class="language-shell">sudo mv acts.conf.sample /etc/acts.conf
</code></pre>
</li>
<li>
<p>Move acts (the script itself) to a more permanent location:</p>
<pre><code class="language-shell">sudo mv acts /usr/local/bin/
</code></pre>
</li>
</ol>
<h2 id="configuring-acts" tabindex="-1">Configuring acts</h2>
<ol>
<li>
<p>Edit acts’ configuration file:</p>
<pre><code class="language-shell">sudo nano /etc/acts.conf
</code></pre>
<p>Find the line starting with “backuptargets” and delete everything between the two double quotes on that line, so that it reads:<br />
<em>backuptargets=“”</em></p>
<p>Now add the directories you want to backup inside those double quotes. Each path is relative to the root path of the machine, but should <em>not</em> start with a forward slash.<br />
However, forward slashes can be used to backup only specific directories, even though the sample does not use them. For example, to backup the directories “/root” and “/home/claus”, you would edit the line as follows:<br />
<em>backuptargets=“root home/claus”</em></p>
</li>
<li>
<p>Schedule a task to run acts daily:</p>
<pre><code class="language-shell">sudo crontab -u root -e
</code></pre>
<p>If the dialog “Select an editor” appears, press Enter to select “nano”.</p>
<p>At the bottom of the file, add these lines, replacing “<a href="mailto:me@example.com">me@example.com</a>” with your email address:</p>
<pre><code class="language-crontab">PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=me@example.com
0 2 * * * acts
</code></pre>
<p>This would run acts every day at 2:00 AM and send an email with the result to “<a href="mailto:me@example.com">me@example.com</a>”.</p>
<p>Save and close the file to activate the scheduled task. When using nano as your text editor, this could be achieved by pressing CTRL+X followed by Y and followed by pressing Enter.</p>
</li>
</ol>
Manjaro XFCE default display manager2015-10-17T17:15:13Zhttps://www.clausconrad.com/blog/manjaro-xfce-default-display-manager/<p>To <a href="https://wiki.archlinux.org/index.php/Display_manager#Loading_the_display_manager">find the active display manager</a> on a distribution using systemd, try:</p>
<pre><code class="language-shell">ls -l /etc/systemd/system/display-manager.service
</code></pre>
<p>More links:</p>
<ul>
<li><a href="https://wiki.manjaro.org/index.php/Install_Display_Managers">Installing display managers on Manjaro</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Display_manager">ArchWiki entry for “Display manager”</a></li>
</ul>
Running PostgreSQL in iocage-managed jail on FreeBSD 10.2-RELEASE2015-08-22T16:05:30Zhttps://www.clausconrad.com/blog/running-postgresql-in-iocage-managed-jail-on-freebsd-10-2-release/<pre><code class="language-shell">iocage set allow_sysvipc=1 JAILNAME
iocage stop JAILNAME
iocage start JAILNAME
</code></pre>
<p>Using <code>iocage restart JAILNAME</code> did <strong>not</strong> work, a stop and start was necessary for me. After that, PostgreSQL started without problems.</p>
<p>The full error message this time - using the latest release of PostgreSQL and FreeBSD - was:</p>
<pre><code class="language-text">FATAL: could not create shared memory segment: Function not implemented
DETAIL: Failed system call was shmget(key=5432001, size=48, 03600).
pg_ctl: could not start server
Examine the log output.
</code></pre>
Installing LastPass on FreeBSD2015-03-28T13:09:20Zhttps://www.clausconrad.com/blog/installing-lastpass-on-freebsd/<p>Firefox: Version from the store cannot be installed, but <a href="https://lastpass.com/dlpre">this
one</a> works.</p>
<p>Thanks to <a href="https://forums.freebsd.org/threads/laspass-plugin-not-working-in-firefox.48048/">poobrain</a> for sharing the link.</p>
FreeBSD hangs on reboot on DigitalOcean2015-02-10T18:29:33Zhttps://www.clausconrad.com/blog/freebsd-hangs-on-reboot-on-digitalocean/<p><code>Timecounters tick every 10.000 msec</code></p>
<p>I am not sure about this, but the problem might be related to the hostname I gave to the droplets using DigitalOcean’s web interface.</p>
<p>It appeared seemingly reliably when naming them like “abc-def”, but disappeared when naming them “abcdef.local” or similar, i.e. avoiding dashes and using a domain name.</p>
TypeError: Cannot read property 'browserify' of undefined2015-02-10T11:17:37Zhttps://www.clausconrad.com/blog/typeerror-cannot-read-property-browserify-of-undefined/<p>It was caused by a syntax error in the <code>package.json</code> file of a node module that was required by my code - the file did not contain valid JSON.</p>
Toggl command line on Windows2015-01-25T09:00:05Zhttps://www.clausconrad.com/blog/toggl-command-line-on-windows/<ol>
<li>
<p>Make a directory for user binaries:</p>
<pre><code class="language-shell">mkdir -p ~/bin
</code></pre>
</li>
<li>
<p>…and change to it:</p>
<pre><code class="language-shell">cd ~/bin
</code></pre>
</li>
<li>
<p>Clone the repository into the subdirectory “toggl-cli”:</p>
<pre><code class="language-shell">git clone https://github.com/drobertadams/toggl-cli.git
</code></pre>
</li>
<li>
<p>Install prerequisites (“requests” was not mentioned in the <a href="https://github.com/drobertadams/toggl-cli/blob/master/README.md">README</a>, but did need to be installed on my system with ActiveState Python 2.7):</p>
<pre><code class="language-shelll">pip install iso8601 pytz requests
</code></pre>
</li>
<li>
<p>Run the program once, don’t be afraid when it crashes, this is expected because of the missing configuration file (which it creates during this run):</p>
<pre><code class="language-shell">python ~/bin/toggl-cli/toggl.py
</code></pre>
</li>
<li>
<p>Edit the configuration file:</p>
<pre><code class="language-shell">vim ~/.togglrc
</code></pre>
</li>
<li>
<p>Update the line “username” with the “E-mail” and the line “apitoken” with the API token from <a href="https://www.toggl.com/app/profile">your Toggl profile</a>, e.g.:</p>
<p><img src="/assets/img/2015-01-25_0941.png" alt="Screenshot of a text editor with the file '~/.togglrc' opened and the sections 'auth' and 'options' visible" /></p>
</li>
<li>
<p>Save and close the configuration file.</p>
</li>
</ol>
<p>toggl-cli is now ready for use (you might want to add it to your PATH and change the shebang line to your Python interpreter for ease of use). Some usage examples:</p>
<ul>
<li>
<p>Start working on a task:</p>
<pre><code class="language-shell">python ~/bin/toggl-cli/toggl.py start Blogging
</code></pre>
</li>
<li>
<p>Stop working on a task:</p>
<pre><code class="language-shell">python ~/bin/toggl-cli/toggl.py stop
</code></pre>
</li>
<li>
<p>Continue working on a task:</p>
<pre><code class="language-shell">python ~/bin/toggl-cli/toggl.py continue Blogging
</code></pre>
</li>
<li>
<p>View more advanced syntax examples:</p>
<pre><code class="language-shell">python ~/bin/toggl-cli/toggl.py -h
</code></pre>
</li>
</ul>
Percona server not starting in jail after upgrading FreeBSD host from 9.2 to 9.32014-12-23T16:57:45Zhttps://www.clausconrad.com/blog/percona-server-not-starting-in-jail-after-upgrading-freebsd-host-from-9-2-to-9-3/<ol>
<li>
<p><code>service mysql-server start</code> returned, but <code>service mysql-server status</code> showed that it was not started successfully.</p>
</li>
<li>
<p>The log file <em>/var/db/mysql/mysql-error.log</em> warned that writing a file to <em>/var/db/mysql</em> failed.</p>
</li>
<li>
<p>Checking the permissions on <em>/var/db/mysql</em> showed that existing files in the folder were owned by user <em>mysql</em> and group <em>mysql</em>, but the directory itself was owned by user <em>root</em> and group <em>wheel</em>.</p>
</li>
<li>
<p>After granting user <em>mysql</em> and group <em>mysql</em> ownership of the folder (<code>chown mysql:mysql /var/db/mysql</code>) the server could be started successfully with <code>service mysql-server start</code>.</p>
</li>
</ol>
Saving space on hybrids: how to move the Documents or profile folder2014-12-15T18:08:21Zhttps://www.clausconrad.com/blog/saving-space-on-hybrids-how-to-move-the-documents-or-profile-folder/<p>Before using any of the methods described below, consider:</p>
<h3 id="general-advantages" tabindex="-1">General advantages</h3>
<ul>
<li>
<p>Reinstalling Windows is easier if you can simply format the internal drive and know that your data is safe on the SD card.</p>
</li>
<li>
<p>Moving a portable drive between computers is a fast way of transferring lots of data.</p>
</li>
<li>
<p>The SD card is less likely to break in an accident than the internal drive.</p>
</li>
</ul>
<h3 id="general-disadvantages" tabindex="-1">General disadvantages</h3>
<ul>
<li>Your SD card is likely slower than your hard drive (even eMMC type drives), so if your documents are large or you frequently sync/copy them elsewhere, you might have to live with a decrease in performance.</li>
</ul>
<p>Okay, so you have decided to move (some of) your data to an SD card or other portable drive. These are the four common approaches to do this:</p>
<h2 id="add-more-folders-to-your-library%2Flibraries" tabindex="-1">Add more folders to your library/libraries</h2>
<p>This is one of the easiest ways to regain space on your C: drive, and the one best supported by Microsoft.</p>
<p>To do this, you simply create a folder for either documents, music, pictures or videos on the SD card, then include the new location in the library.</p>
<h3 id="advantages" tabindex="-1">Advantages</h3>
<ul>
<li>
<p>Good support - the way the operating system is meant to be used</p>
</li>
<li>
<p>Easy</p>
</li>
</ul>
<h3 id="disadvantages" tabindex="-1">Disadvantages</h3>
<ul>
<li>
<p>You need to remember to save new files in the right location</p>
</li>
<li>
<p>Only works for documents, music, pictures and videos (libraries)</p>
</li>
</ul>
<h2 id="redirect-folders-from-your-profile-to-other-locations" tabindex="-1">Redirect folders from your profile to other locations</h2>
<p>This method works for a few more folders than the one above. It is also pretty well supported by Microsoft and has existed since the days of Windows XP.</p>
<p>To use this method, you right-click one or more folders inside your user profile (e. g. “My Documents”), select the Location tab, and select a new folder located on the portable drive.</p>
<p>To read more about this approach, see <a href="https://docs.microsoft.com/en-us/windows-server/storage/folder-redirection/folder-redirection-rup-overview">Redirect a folder to a new location</a> at <a href="http://microsoft.com">microsoft.com</a>.</p>
<h3 id="advantages-1" tabindex="-1">Advantages</h3>
<ul>
<li>
<p>Easy</p>
</li>
<li>
<p>Good support - has been in Windows for a long time</p>
</li>
</ul>
<h3 id="disadvantages-1" tabindex="-1">Disadvantages</h3>
<ul>
<li>Only works for some folders beneath the user profile directory, not all of them</li>
</ul>
<h2 id="the-registry-hack" tabindex="-1">The registry hack</h2>
<p>This method is not really a hack, but I call it this way because it isn’t supported by Microsoft, as far as I know.</p>
<p>This involves editing the registry and is likely to go wrong, if you already have data in your user profile directory.</p>
<p>To read more about this approach, <a href="https://www.nextofwindows.com/how-to-change-user-profile-default-location-in-windows-7/">click
here</a>. While it says “Windows 7” in the linked article, this should also work on newer versions - but be sure to read the disadvantages below before considering it.</p>
<h3 id="advantages-2" tabindex="-1">Advantages</h3>
<ul>
<li>
<p>Moves all user profiles at the same time - no need to repeat for each user, if several people use your PC</p>
</li>
<li>
<p>Also moves application data etc.</p>
</li>
</ul>
<h3 id="disadvantages-2" tabindex="-1">Disadvantages</h3>
<ul>
<li>
<p>Not supported by Microsoft</p>
</li>
<li>
<p>Can break security updates, regular updates, hotfixes, service packs and upgrading to new versions of Windows</p>
</li>
</ul>
<h2 id="symbolic-links" tabindex="-1">Symbolic links</h2>
<p>This method involves moving the directory with all user profiles (e.g. <em>C:\Users</em>) outside of Windows (e.g. in rescue mode) and creating a symbolic link from the old directory to the new one.</p>
<p>To read more about this approach, see <a href="https://www.nextofwindows.com/how-to-change-user-profile-location-in-windows-8-without-registry-hack/">How To Change User Profile Location in Windows 8 without Registry Hack</a>. While the linked article refers to Windows 8, it should also work with earlier versions of
Windows, down to Vista.</p>
<p><strong>Tip:</strong></p>
<p>If you decide to use this method and the xcopy command (as detailed in the post linked to above) fails for some reason, you will have to fix the problem, restart the copy process and overwrite all the files that had already been copied until the point of failure. Instead of using the command <em>xcopy /e /k
/o /h /b</em> from the article, I used this similar command (which skips already copied files when run again, saving potentially lots of time):</p>
<pre><code class="language-shell">robocopy c:\users d:\users /mir /copyall /sl /x /v
</code></pre>
<h3 id="advantages-3" tabindex="-1">Advantages</h3>
<ul>
<li>
<p>Can move all user profiles at the same time - no need to repeat for each user, if several people use your PC</p>
</li>
<li>
<p>Also moves application data etc.</p>
</li>
</ul>
<h3 id="disadvantages-3" tabindex="-1">Disadvantages</h3>
<ul>
<li>
<p>Not supported by Microsoft</p>
</li>
<li>
<p>Needs to be run from the command line during rescue mode, or similar</p>
</li>
</ul>
<p>I hope this post was helpful when deciding on whether to move (some of) the data from your tablet, hybrid or other device running Windows to a portable drive and selecting the right approach for your purpose. Please let me know by commenting below what worked for you (or didn’t).</p>
Uninstall "Asus Screen Saver"2014-11-24T19:29:59Zhttps://www.clausconrad.com/blog/uninstall-asus-screen-saver/<p>The reason I chose this machine instead of the main competitor (in my country of residence, Sweden) Lenovo MiiX 2 was the battery lifetime and my previous experience with Asus; I own one of their Ultrabooks, which has never let me down and still now, approx. 3-4 years after purchasing it, feels like the fastest and most stable computer I ever owned.</p>
<p>So when I purchased my Transformer I was flabbergasted to find that one of the included applications, called “Asus Screen Saver”, required a password, otherwise I was unable to uninstall it!</p>
<p>Thanks to some googling and <a href="http://www.transformerforums.com/forum/asus-transformer-book-t100-general-discussions/45023-asus-screen-saver-password.html#post332536">a friendly user on transformerforums.com</a>, I finally found the password, which is <strong>8777</strong>.</p>
Repairing Outlook PST files2014-10-08T06:08:37Zhttps://www.clausconrad.com/blog/repairing-outlook-pst-files/<p>The first challenge, however, might be finding this life-saving tool. It is called <em>scanpst.exe</em> and its location depends on the version of Office:</p>
<ul>
<li>
<p>For Office 2010 (32-bit) on Windows (32-bit), it is located in <em>C:\Program Files\Microsoft Office\Office14</em>.</p>
</li>
<li>
<p>When running the 32-bit version of Office 2010 on Windows (64-bit), the folder would be <em>C:\Program Files (x86)\Microsoft Office\Office14</em>.</p>
</li>
<li>
<p>The (rare) 64-bit version of Office 2010 on Windows (also 64-bit) hides it in <em>C:\Program Files\Microsoft Office\Office14</em>.</p>
</li>
<li>
<p>For Office 2013, the paths are similar to those for Office 2010, but replace “Office14” with “Office15”.</p>
</li>
<li>
<p>However, the “Click-to-run” (CTR) editions of Office 2013 - which includes most versions of Office 365 - install scanpst.exe in <em>C:\Program Files\Microsoft Office 15\root\Office15</em> or <em>C:\Program Files (x86)\Microsoft Office 15\root\Office15</em>.</p>
</li>
</ul>
<p>When running the Inbox Repair Tool, make sure that Outlook is completely closed (no icon in the tray either). Also, it is probably a good idea to let the tool create a backup of the *.pst file before trying to repair it. Either way the file will be repaired “in place”, so you can simply open Outlook after the message “Repair complete” is displayed to check whether the repair was indeed successful.</p>
Positive passwords2014-10-06T05:42:04Zhttps://www.clausconrad.com/blog/positive-passwords/<p>I believe in a couple of principles:</p>
<ul>
<li>Long passwords can be both strong and memorizable.</li>
<li>Positive affirmations do work to improve habits and self esteem.</li>
<li>Writing or typing something is a better way to remember it than just reading it.</li>
</ul>
<p>Here’s how I might combine these beliefs:</p>
<ol>
<li>
<p>Start with an affirmation that makes sense for you, here is a generic cliche:<br />
<em>Today is going to be the best day of my life.</em></p>
</li>
<li>
<p>Change some words to make the sentence illogical:<br />
<em>Today was gonna be the super day of my lifes.</em></p>
</li>
<li>
<p>Introduce some more spelling and grammar mistakes:<br />
<em>Todei wass gonna bee teh supahst dai ov my lifez.</em></p>
</li>
<li>
<p>Add digits and special characters:<br />
<em>T0dei/wass\gonna B33_teh-supahst-dai,ov;my?lifez!1</em></p>
</li>
</ol>
<p>There is a pass phrase that should be pretty secure against brute force and rainbow attacks and makes one think of the initially selected affirmation whenever it is entered.</p>
Gamify your life2014-10-05T20:02:48Zhttps://www.clausconrad.com/blog/gamify-your-life/<p>While listening to a podcast about Angular (a front-end JavaScript framework I am using) I came across this “game”: <a href="https://www.habitrpg.com/">HabitRPG</a>. HabitRPG is not so much a RPG but very much a todo list and habit tracker, with some gamification elements appealing to old-school RPG connoisseurs (or nerds) like myself. It combines some (and unfortunately only some) of the features of to-do lists such as <a href="https://www.rmilk.com/">Remember The Milk</a> with some elements of RPGs. That sounds somewhat crazy, but I wouldn’t dismiss it that easily, so I am trying it out right now for self-improvement and -development purposes.</p>
<p>If you don’t know what the abbreviation RPG means, I’d suggest to stay away from HabitRPG, because it very much looks like a tool by nerds for nerds, but if you do, and are interested in improving your real-life habits, giving it a try can’t harm you. I would suggest every new “player”/user to read “<a href="https://habitica.fandom.com/wiki/Establishing_Your_Tasks">Establishing your tasks</a>”.</p>
Running BackupPC with lighttpd instead of Apache2014-09-28T18:10:35Zhttps://www.clausconrad.com/blog/running-backuppc-with-lighttpd-instead-of-apache/<p>I was under the mistaken impression that BackupPC’s frontend only worked with Apache, so when I found <a href="https://wiki.archlinux.org/index.php/BackupPC#Alternative_lighttpd_configuration">instructions on the ArchLinux wiki</a> to run it on <a href="https://www.lighttpd.net/">lighttpd</a> instead, I gave it a try on FreeBSD, and with these few changes to the configuration it runs just fine:</p>
<ol>
<li>
<p>Delete Apache:</p>
<pre><code class="language-shell">pkg delete backuppc apache22
</code></pre>
</li>
<li>
<p>Delete dependencies installed for Apache:</p>
<pre><code class="language-shell">pkg autoremove
</code></pre>
</li>
<li>
<p>Install lighttpd:</p>
<pre><code class="language-shell">pkg install lighttpd
</code></pre>
</li>
<li>
<p>Edit lighttpd’s configuration:</p>
<pre><code class="language-shell">vi /usr/local/etc/lighttpd/lighttpd.conf
</code></pre>
<pre><code class="language-text">server.port = 81
server.username = "backuppc"
server.groupname = "backuppc"
server.document-root = "/usr/local/www/data/"
server.errorlog = "/var/log/lighttpd/error.log"
dir-listing.activate = "enable"
index-file.names = ( "index.html", "index.cgi" )
server.modules = ("mod_alias", "mod_cgi", "mod_auth", "mod_access")
server.pid-file = "/var/run/lighttpd/lighttpd.pid"
alias.url = ("/BackupPC_Admin" => "/usr/local/www/cgi-bin/BackupPC_Admin")
alias.url += ("/backuppc" => "/usr/local/www/backuppc" )
cgi.assign += (".cgi" => "/usr/bin/perl" )
cgi.assign += ("BackupPC_Admin" => "/usr/bin/perl")
server.event-handler = "freebsd-kqueue"
server.network-backend = "writev"
server.max-fds = 2048
server.stat-cache-engine = "simple"
server.max-connections = 1024
url.access-deny = ( "~", ".inc" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".scgi" )
</code></pre>
</li>
<li>
<p>Edit <em>rc.conf</em>:</p>
<pre><code class="language-shell">vi /etc/rc.conf
</code></pre>
<pre><code class="language-text">lighttpd_enable="YES"
lighttpd_pidfile="/var/run/lighttpd/lighttpd.pid"
# ... other lines, such as (obviously) ...
backuppc_enable="YES"
</code></pre>
</li>
<li>
<p>Give backuppc user access to log and pid directories:</p>
<pre><code class="language-shell">mkdir /var/run/lighttpd
chown -R backuppc: /var/log/lighttpd
chown -R backuppc: /var/run/lighttpd
</code></pre>
</li>
<li>
<p>Start lighttpd:</p>
<pre><code class="language-shell">service lighttpd start
</code></pre>
</li>
</ol>
Set environment variable for one command with csh2014-09-23T17:34:26Zhttps://www.clausconrad.com/blog/set-environment-variable-for-one-command-with-csh/<p>TL;DR: Run this:</p>
<pre><code class="language-shell">env ENV_VAR_NAME=ENV_VAR_VALUE command
</code></pre>
<p>On most machines I use, bash is the default shell, or at least available (yes, also on the Windows box where I am typing this post). I am not a fanatic bash user, most shells work just fine. But being used to “the bash way”, where setting environment variables for the next run command is pretty easy (<em>KEY=VALUE command</em>), it tricks me up each time I have to use csh on FreeBSD. (Sure, I could just install bash there too, but I prefer using included tools and installing as few dependencies as necessary.) So each time I use FreeBSD, I have to look this up on Google. This being Unix, there are of course several solutions. The one I found earlier today and which worked fine for me was this:</p>
<pre><code class="language-shell">env KEY=VALUE command
</code></pre>
portmaster -a upgrades db48 repeatedly2014-09-22T16:55:58Zhttps://www.clausconrad.com/blog/portmaster-a-upgrades-db48-repeatedly/<pre><code class="language-shell">portmaster -o databases/db48 databases/db42
</code></pre>
<p>Thanks to <a href="https://www.stephen-scotter.net/computers/freebsd/databasesdb48-installed-upgraded-repeatedly">Stephen Scotter</a> for pointing me in the right direction with his blog entry, I just had to replace <em>db47</em> with <em>db42</em> to get it to work on my machine. After the above command, <em>portmaster -a</em> only installed <em>db48</em> once more, then stopped with the message <em>===>>> All ports are up to date</em>.</p>
"Bad gateway" with nginx, PHP-FPM using FreeBSD socket2014-08-30T13:58:40Zhttps://www.clausconrad.com/blog/bad-gateway-with-nginx-php-fpm-using-freebsd-socket/<p>Apparently there is a <a href="https://bugs.php.net/bug.php?id=67244">bug</a> in the PHP version shipped with FreeBSD; ServerFault user MafiaInc kindly provided <a href="https://serverfault.com/questions/593272/nginx-php-fpm-permission">the solution</a>:</p>
<ol>
<li>
<p>Edit the file /usr/local/etc/php-fpm.conf</p>
</li>
<li>
<p>Note the values of the user/group lines, e.g.:</p>
<pre><code class="language-text">user = www
group = www
</code></pre>
</li>
<li>
<p>Add these lines with the same values as the user/group lines:</p>
<pre><code class="language-text">listen.owner = www
listen.group = www
</code></pre>
</li>
<li>
<p>Restart PHP-FPM using this command:</p>
<pre><code class="language-shell">service php-fpm restart
</code></pre>
</li>
</ol>
Running Plunker in IE92014-08-25T07:25:56Zhttps://www.clausconrad.com/blog/running-plunker-in-ie9/<p>Even though I made my plunk public, IE9 would always load an empty file into the editor, when I pasted the URL into it.</p>
<p>The solution I found <a href="https://stackoverflow.com/questions/20959088/angularjs-1-2-7-ie8-resource-bug">here</a> is simple: Use a modern browser to write the code, then paste the “Run” preview iframe’s URL into IE to run it. Unfortunately live update won’t work this way, but it’s better than not being able to test plunks in older Internet Explorer browsers at all.</p>
Customer service done right2014-08-24T11:04:10Zhttps://www.clausconrad.com/blog/customer-service-done-right/<p>What I expected from my experience with similar mails to other companies, except some small start-ups, was this:</p>
<ol>
<li>
<p>I would receive an automatic reply confirming the receipt of my request.</p>
</li>
<li>
<p>After a couple of days or even weeks I would receive something along the lines of:</p>
</li>
</ol>
<blockquote>
<p>Thanks for your feedback, we will add it to a list for future consideration.</p>
</blockquote>
<p>Here’s what happened instead:</p>
<ol>
<li>
<p>A (useless) automatic reply never arrived.</p>
</li>
<li>
<p>After a couple of <em>hours</em> I received this mail from Airbnb:</p>
<blockquote>
<p>Hello Claus,
I hope you’re having a wonderful day. My name is Mai and it is a pleasure to assist you today. I see that you are currently on a trip in Denmark. That’s awesome! How are you enjoying it? Do you like your listing? I hope that you have had and will continue to have awesome travelling experiences here on Airbnb. I see that this is your first time writing in to us. I would like to take the time to personally welcome you to the Airbnb community! There are so many opportunities to meet new, exciting people and I’m happy that you will be able to experience that.</p>
<p>At this time, there isn’t an option [like you asked for]. I think that is a very excellent idea. I will submit your feedback to the department that is in charge of making changes on our site.</p>
<p>We are always working to improve our products and policies, and we encourage our users to provide their feedback. Even when unable to accommodate all requests, Airbnb truly values user feedback – your voice is both powerful and essential.</p>
<p>Also, I would like to mention our blog where you can provide your feedback as well. As recently as July 25th, we moved forward and made changes thanks to the feedback of our users and the Airbnb team. Here is the link to the blog as well as some posts I think you would like to read:</p>
<p>Blog: <a href="http://blog.airbnb.com/">http://blog.airbnb.com/</a><br />
Moving forward with your feedback: <a href="http://blog.airbnb.com/moving-forward-feedback/">http://blog.airbnb.com/moving-forward-feedback/</a></p>
<p>Once again, welcome! Airbnb is full of interesting and wonderful people from all walks of life, and we’re always happy to hear from you. Your feedback is on its way! If you have any further questions or concerns, please feel free to reach out to me and I will be more than happy to assist you.</p>
<p>Maiphuong N<br />
<a href="https://www.airbnb.com/help">www.airbnb.com/help</a></p>
<p>TO RESPOND TO THIS TICKET, REPLY TO THIS EMAIL</p>
</blockquote>
</li>
</ol>
<p>Now, I don’t assume their representatives spend a lot of time writing all this by hand, obviously most of these snippets can be fully automated and inserted with a couple of clicks. But does it matter? To me, and I guess their average customer too, this mail is so much more of a positive “wow!” experience than the boring example at the top of this post.</p>
<p>What I think Airbnb is doing right here:</p>
<ul>
<li>Greet the customer by name</li>
<li>Relate to recent activity</li>
<li>Ask general questions about satisfaction</li>
<li>Acknowledge that this is the first contact with customer service</li>
<li>Make sure the mail is legible on both desktop and mobile devices</li>
<li>Greet the customer by name</li>
<li>Relate to recent activity</li>
<li>Ask general questions about satisfaction</li>
<li>Acknowledge that this is the first contact with customer service</li>
<li>Make sure the mail is legible on both desktop and mobile devices</li>
<li>Paragraph lengths that make sense and improve readability</li>
<li>Provide relevant links</li>
<li>Allow the customer to respond by mail instead of having to click a link to a form (or even worse, make them log in to reply)</li>
<li>Mention the representative’s name at the beginning and end of the mail</li>
<li>Paragraph lengths that make sense and improve readability</li>
<li>Provide relevant links</li>
<li>Allow the customer to respond by mail instead of having to click a link to a form (or even worse, make them log in to reply)</li>
<li>Mention the representative’s name at the beginning and end of the mail</li>
</ul>
<p>I think a lot of companies, small or large, could improve their customer’s experience by following just some of these simple steps, which might contribute to longer customer retention, improved conversion rates and more recommendations, likes and shares.</p>
Inspecting a Kendo UI Datepicker for theming2014-08-21T13:24:15Zhttps://www.clausconrad.com/blog/inspecting-a-kendo-ui-datepicker-for-theming/<p>We can catch the close event and prevent it like this:</p>
<pre><code class="language-javascript">var datepicker = $("#datepicker").data("kendoDatePicker");
datepicker.bind("close", function(e) {
e.preventDefault();
});
</code></pre>
Power management under i3 on Arch Linux2014-03-10T16:14:41Zhttps://www.clausconrad.com/blog/power-management-under-i3-on-arch-linux/<ol>
<li>
<p><code>sudo pacman -S xfce4-power-manager</code></p>
</li>
<li>
<p><code>xfce4-power-manager-settings</code></p>
<p>Make the necessary configuration settings, such as suspending upon closing the lid</p>
</li>
<li>
<p><code>vi .config/i3/config</code></p>
<p>Add this at the bottom:</p>
<pre><code class="language-shell">exec --no-startup-id sleep 3 &amp;&amp; xfce4-power-manager
</code></pre>
</li>
</ol>
Add Manjaro Openbox flavor to Manjaro XFCE2014-03-09T20:51:23Zhttps://www.clausconrad.com/blog/add-manjaro-openbox-flavor-to-manjaro-xfce/<ol>
<li>
<p><code>sudo pacman -S openbox obmenu-generator nitrogen geany compton tint2 pnmixer conky lxappearance lxappearance-obconf hardinfo htop leafpad lesstif libtimezonemap libwbclient libxp lxinput lxrandr manjarobox-evolution-themes pam_encfs parcellite prebootloader printproto py3parted rlog slim tintwizard xautolock xlockmore synapse gnome-alsamixer</code></p>
</li>
<li>
<p>Install Manjaro Openbox in VirtualBox</p>
</li>
<li>
<p>Copy these files/directories over to the host:</p>
<ol>
<li>~/.config/executables</li>
<li>~/.config/gtk-3.0/settings.ini</li>
<li>~/.config/nitrogen</li>
<li>~/.config/obmenu-generator</li>
<li>~/.config/openbox</li>
<li>~/.config/pnmixer</li>
<li>~/.config/tint2</li>
<li>~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-notifyd.xml</li>
<li>~/.conkyrc</li>
<li>/usr/share/conkypic/lsd.png</li>
</ol>
</li>
<li>
<p>Log out and choose Openbox from your display manager’s session menu</p>
</li>
</ol>
Error 404 updating Kali Linux2014-02-16T11:49:47Zhttps://www.clausconrad.com/blog/error-404-updating-kali-linux/<p>While updating a new installation of Kali Linux, I received the error message <code>Err http://http.kali.org/kali/ kali/non-free metasploit amd64 4.8.2-2014012201-1kali0 404 Not Found</code>.</p>
<p>Apparently, the hostname <em><a href="http://http.kali.org">http.kali.org</a></em> points to a CDN and not all of its mirrors contain updated packages. In order to solve this I went to the Kali <a href="https://http.kali.org/README.mirrorlist">mirror list</a> and chose another mirror from my continent. I then updated the file <em>/etc/apt/sources.list</em> accordingly (replace with your chosen mirror):</p>
<ul>
<li>
<p>Uncomment this line:</p>
<pre><code class="language-text"># deb http://http.kali.org/kali kali main non-free contrib
</code></pre>
</li>
<li>
<p>Insert line with the mirror URL below:</p>
<pre><code class="language-text">deb http://mirror.pcextreme.nl/kali kali main non-free contrib
</code></pre>
</li>
</ul>
<p>Make sure to choose a mirror from your continent, if possible.</p>
<p>Finally, update the package database, then try to upgrade Kali Linux again:</p>
<ul>
<li><code>apt-get update</code></li>
<li><code>apt-get upgrade</code></li>
</ul>
<p>If the update succeeds but the upgrade still fails, try with another mirror.</p>
<p>If the update fails, make sure you have entered the mirror address correctly into <em>/etc/apt/sources.list</em>. Don’t include the trailing <em>/README</em>.</p>
Running Postgresql 9.3 in an ezjail2014-01-26T17:34:55Zhttps://www.clausconrad.com/blog/running-postgresql-9-3-in-an-ezjail/<p><strong>On the host:</strong></p>
<ol>
<li>
<p><code>sudo echo 'security.jail.sysvipc_allowed=1' >> /etc/sysctl.conf</code></p>
</li>
<li>
<p><code>sudo echo 'jail_sysvipc_allow="YES"' >> /etc/rc.conf</code></p>
</li>
<li>
<p><code>sudo vi /usr/local/etc/ezjail/JAILNAME</code></p>
<p>Change this line:</p>
<p><code>export jail_JAILNAME_parameters=""</code></p>
<p>to:</p>
<p><code>export jail_JAILNAME_parameters="allow.sysvipc=1"</code></p>
</li>
<li>
<p>Restart the jail:</p>
<p><code>sudo ezjail-admin restart JAILNAME</code></p>
</li>
</ol>
Django app as Facebook canvas app2014-01-21T18:37:29Zhttps://www.clausconrad.com/blog/django-app-as-facebook-canvas-app/<p>When you load a website through a Facebook canvas URL
(<a href="https://apps.facebook.com/your_app_name">https://apps.facebook.com/your_app_name</a>), the request to your app is POSTed. By default, Django apps reject POST requests that don’t contain a “csrf_token” with a “403 Forbidden” error.</p>
<p>To disable this behavior, remove ‘django.middleware.csrf.CsrfViewMiddleware’ from your INSTALLED_APPS list. Obviously this will open your app up to XSS attacks, so make sure to use the <a href="https://docs.djangoproject.com/en/dev/ref/contrib/csrf/">csrf_protect</a> decorator on views that accept POST requests from your own app.</p>
<p>After “fixing” the above problem I expected things to just work.
Unfortunately, Django provides another <s>hurdle</s> protection in the form of its clickjacking protection. By default, Django apps send a response header like “X-Frame-Options: SAMEORIGIN”. This forces modern browsers to not embed the Django app in a frame or iframe, such as inside the Facebook canvas. Even though the HTTP request to your Django app returns “200 OK”, modern browsers
just won’t display its contents inside Facebook’s frame.</p>
<p>Fortunately there is an easy way to disable this, too - just remove “django.middleware.clickjacking.XFrameOptionsMiddleware” from your MIDDLEWARE_CLASSES.</p>
<p>Once again, I cannot stress enough that removing any of these middlewares opens your app up to potential attacks, so consider the consequences carefully before resorting to these solutions.</p>
Easy firewall setup for Manjaro Linux2014-01-09T18:08:56Zhttps://www.clausconrad.com/blog/easy-firewall-setup-for-manjaro-linux/<p>After installing Manjaro on my notebook, I was astounded to see that unlike numerous other distributions of Linux it did not enable a firewall by default - especially since it ships with iptables <em>and</em> its user-friendly frontend, <a href="https://launchpad.net/ufw">ufw</a>.</p>
<p>Admittedly, this would not be too big of a deal if I did not run services on my laptop nor connected to public networks once in a while, but even then, having a firewall configured let’s me work more soundly. Here is how I set up and enabled iptables on Manjaro using ufw:</p>
<ol>
<li>
<p>ufw is a command line application. Don’t let that scare you though, its commands are pretty easy to understand and type in. If in doubt, just enter the lines highlighted below into a terminal.</p>
</li>
<li>
<p>Tell ufw to deny incoming requests by default:</p>
<pre><code class="language-shell">sudo ufw default deny
</code></pre>
</li>
<li>
<p>In my case, I wanted to be able to access my computer via SSH from anywhere, so I ran this line:</p>
<pre><code class="language-shell">sudo ufw allow SSH
</code></pre>
</li>
<li>
<p>Now enable ufw itself:</p>
<pre><code class="language-shell">sudo ufw enable
</code></pre>
</li>
<li>
<p>Enable ufw as a systemd service (so it starts together with Linux):</p>
<pre><code class="language-shell">sudo systemctl enable ufw
</code></pre>
</li>
<li>
<p>The firewall will be active after the next boot, but let’s start it immediately without restarting the computer:</p>
<pre><code class="language-shell">sudo systemctl start ufw
</code></pre>
</li>
<li>
<p>Finally we can check the status of ufw:</p>
<pre><code class="language-shell">sudo ufw status
</code></pre>
</li>
</ol>
<p>That command should output something similar to this:</p>
<pre><code class="language-text"> Status: active
To Action From
-- ------ ----
SSH ALLOW Anywhere
SSH (v6) ALLOW Anywhere (v6)
</code></pre>
FreeBSD hangs during boot with USB drives attached2013-12-30T19:47:30Zhttps://www.clausconrad.com/blog/freebsd-hangs-during-boot-with-usb-drives-attached/<p>Adding the following line to <code>/boot/loader.conf</code> seemed to mitigate the issue:</p>
<pre><code class="language-text">hw.usb.no_boot_wait="1"
</code></pre>
<p>In my case I had to create this file.</p>
Using BackupPC to archive backups via SFTP2013-12-29T16:20:55Zhttps://www.clausconrad.com/blog/using-backuppc-to-archive-backups-via-sftp/<pre><code class="language-shell">#!/usr/bin/env csh
# Create temporary directory
mkdir -p /tmp/backuppc-archive
# Clean previous archive, if any
rm "/tmp/backuppc-archive/$4.$5.tar$7"
# Call BackupPC_archiveHost
BackupPC_archiveHost "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "/tmp/backuppc-archive" "${10}" "${11}"
# Copy to SFTP
scp "/tmp/backuppc-archive/$4.$5.tar$7" user@host:/
# Remove temporary archive
rm "/tmp/backuppc-archive/$4.$5.tar$7"
</code></pre>
<p>To use this, save the script, set its executable flag, and configure BackupPC to use it instead of the default script - either in the global <em><a href="http://config.pl">config.pl</a></em> or a client-specific config:</p>
<pre><code class="language-perl">$Conf{ArchiveClientCmd} = '/path/to/script/above.sh $tarCreatePath $splitpath $parpath $host $backupnumber $compression $compext $splitsize $archiveloc $parfile *';
</code></pre>
Backing up FreeBSD jails using Amanda2013-12-26T16:16:15Zhttps://www.clausconrad.com/blog/backing-up-freebsd-jails-using-amanda/<p>While looking for open-source backup solutions for jails on a FreeBSD box, I came across Amanda and Bacula. At first glance Amanda seemed easier to configure, so I tried to install it from ports. There were some hiccups, especially with regards to permissions and missing directories, so I documented the steps I needed to get it running below.</p>
<p>Amanda uses a server/client architecture, although not in the traditional sense where an application is running all the time. The “Amanda server” is the box that runs and keeps the backups, a process that can be scheduled using cron. Amanda “clients” are the machines that have data that needs to be backed up. It is entirely possible to run the server and client on the same device (VM, jail, etc.). In the configuration described here I am running Amanda server in one jail and an Amanda client in another jail.</p>
<p><strong>On the Amanda server</strong></p>
<ol>
<li>
<p>If this is the first time using <em>pkg</em> on the server, install it:</p>
<pre><code class="language-shell">sudo pkg
</code></pre>
<p>Press “Y” to confirm.</p>
</li>
<li>
<p>Here I am building <em>amanda-server</em> from ports because I plan on using S3 functionality in amanda-server, which is not enabled in the binary packages. If you don’t need S3 (or don’t know what it is), feel free to save some time by skipping to “To install binaries” below.</p>
</li>
<li>
<p>Install portmaster:</p>
<pre><code class="language-shell">sudo pkg install portmaster
</code></pre>
</li>
<li>
<p>Install amanda-server:</p>
<pre><code class="language-shell">sudo portmaster --packages-build misc/amanda-server
</code></pre>
</li>
<li>
<p>Follow the prompts, most settings should be self-explanatory.</p>
</li>
<li>
<p>Install amcrypt:</p>
<pre><code class="language-shell">sudo portmaster --packages-build security/aespipe
</code></pre>
</li>
<li>
<p>Install pinentry-curses:</p>
<pre><code class="language-shell">sudo portmaster -P security/pinentry-curses
</code></pre>
</li>
<li>
<p>To install binaries, use this command instead of those containing <em>portmaster</em> above:</p>
<pre><code class="language-shell">sudo pkg install amanda-server aespipe pinentry-curses
</code></pre>
</li>
<li>
<p>Enable sendmail, so Amanda can mail backup reports:</p>
<pre><code class="language-shell">sudo echo 'sendmail_enable="YES"' >> /etc/rc.conf
</code></pre>
</li>
<li>
<p>Start sendmail:</p>
<pre><code class="language-shell">sudo service sendmail start
</code></pre>
</li>
</ol>
<p><strong>On the Amanda clients</strong></p>
<ol>
<li>
<p>If this is the first time using <em>pkg</em> on the server, install it:</p>
<pre><code class="language-shell">sudo pkg
</code></pre>
<p>Press “Y” to confirm.</p>
</li>
<li>
<p>Install <em>amanda-client</em>, <em>amcrypt</em> and <em>pinentry-curses</em>:</p>
<pre><code class="language-shell">pkg install amanda-client aespipe pinentry-curses
</code></pre>
</li>
</ol>
<p><strong>On the Amanda server</strong></p>
<ol>
<li>
<p>Amanda has been around for a long time, so it calls disk backups for “virtual tapes”. Create a directory for these files:</p>
<pre><code class="language-shell">sudo mkdir -p /data/amanda/vtape/DailySet1
sudo chown amanda:amanda /data/amanda/vtape/DailySet1
sudo chmod -R 750 /data/amanda/vtape/DailySet1
</code></pre>
</li>
<li>
<p>Create configuration directory:</p>
<pre><code class="language-shell">sudo mkdir -p /usr/local/etc/amanda
sudo chown -R amanda:amanda /usr/local/etc/amanda
</code></pre>
</li>
<li>
<p>Create var directory:</p>
<pre><code class="language-shell">sudo mkdir -p /usr/local/var/lib/amanda
sudo chown -R amanda:amanda /usr/local/var/lib/amanda
</code></pre>
</li>
<li>
<p>Assign a shell to user <em>amanda</em>:</p>
<pre><code class="language-shell">sudo chsh -s /bin/csh amanda
</code></pre>
</li>
<li>
<p>Change to the amanda user:</p>
<pre><code class="language-shell">sudo su - amanda
</code></pre>
</li>
<li>
<p>Create public/private key pair to access clients:</p>
<pre><code class="language-shell">ssh-keygen -t rsa
</code></pre>
<p>Press Enter at all prompts to create it without a passphrase.</p>
</li>
<li>
<p>Create a vtape configuration:</p>
<pre><code class="language-shell">amserverconfig DailySet1 --template harddisk --tapedev /data/amanda/vtape/DailySet1 --mailto EMAIL_RECIPIENT_GOES_HERE --dumpcycle 1week --runspercycle 5 --tapecycle 12 --runtapes 1
</code></pre>
</li>
<li>
<p>Add hosts configuration file:</p>
<pre><code class="language-shell">touch /usr/local/var/lib/amanda/.amandahosts
</code></pre>
</li>
</ol>
<p><strong>On the Amanda clients</strong></p>
<ol>
<li>
<p>Assign a shell to user <em>amanda</em>:</p>
<pre><code class="language-shell">sudo chsh -s /bin/csh amanda
</code></pre>
</li>
<li>
<p>Append or copy <em>~/.ssh/id_rsa.pub</em> from server to <em>~/.ssh/authorized_keys</em> on clients</p>
</li>
<li>
<p>Create directories/files and assign permissions:</p>
<pre><code class="language-shell">sudo mkdir -p /usr/local/var/lib/amanda
sudo touch /usr/local/var/lib/amanda/.amandahosts
sudo mkdir -p /usr/local/etc/amanda
sudo mkdir -p /usr/local/var/amanda/gnutar-lists
sudo chown -R amanda:amanda /usr/local/etc/amanda
sudo chown -R amanda:amanda /usr/local/var/lib/amanda
sudo chown -R amanda:amanda /usr/local/var/amanda
</code></pre>
</li>
<li>
<p>Create <em>/etc/fstab</em> file:</p>
<pre><code class="language-shell">sudo touch /etc/fstab
</code></pre>
</li>
</ol>
<p><strong>Amanda server</strong></p>
<ol>
<li>
<p>Change to the amanda user:</p>
<pre><code class="language-shell">sudo su - amanda
</code></pre>
</li>
<li>
<p>Add a client (backup job):<br />
In this example, I am backing up the directory <em>/var/www</em> from the client - replace as necessary.</p>
<pre><code class="language-shell">amaddclient --config DailySet1 --client CLIENT_HOSTNAME_GOES_HERE --diskdev /var/www --dumptype comp-user-tar
</code></pre>
</li>
<li>
<p>Edit the file <em>/usr/local/etc/amanda/DailySet1/amanda.conf</em>:</p>
<pre><code class="language-shell">vi /usr/local/etc/amanda/DailySet1/amanda.conf
</code></pre>
<p>Find this section (line):</p>
<pre><code>define dumptype global {
</code></pre>
<p>In the section, change:</p>
<pre><code>auth "bsdtcp"
</code></pre>
<p>to:</p>
<pre><code>auth "ssh"
</code></pre>
</li>
<li>
<p>Test configuration:</p>
<pre><code class="language-shell">amcheck DailySet1
</code></pre>
<p>Fix any problems before continuing.</p>
</li>
<li>
<p>Initiate the first full backup:</p>
<pre><code class="language-shell">amdump DailySet1
</code></pre>
</li>
<li>
<p>Check that a backup summary is received by e-mail.</p>
</li>
<li>
<p>Automate this backup using cron:</p>
<pre><code class="language-shell">crontab -e
</code></pre>
<p>Add this line to the file to run backups daily Monday through Friday at 1 AM:</p>
<pre><code>0 1 * * 1-5 /usr/local/sbin/amdump DailySet1
</code></pre>
</li>
</ol>
<p>That’s it, you should now receive a daily mail shortly after 1AM, informing you of a successful backup of /var/www from the client to the server. The first report (hopefully received during the test run above) should be about a full backup and the next couple of reports will only do an incremental backup, with a new full backup every week (as specified in the vtape configuration command).</p>
<p>Some other opensource backup solutions that should work on FreeBSD:</p>
<ul>
<li><a href="https://backuppc.github.io/backuppc/">BackupPC</a> (<a href="https://www.freshports.org/sysutils/backuppc/">port</a>)</li>
<li><a href="https://www.bacula.org/">Bacula</a> (ports: <a href="https://www.freshports.org/sysutils/bacula-client/">client</a>/<a href="https://www.freshports.org/sysutils/bacula-server/">server</a>)</li>
<li><a href="https://rsnapshot.org/">rsnapshot</a> (<a href="https://www.freshports.org/sysutils/rsnapshot/">port</a>)</li>
</ul>
Manjaro Openbox right-click menu as root2013-12-25T15:21:33Zhttps://www.clausconrad.com/blog/manjaro-openbox-right-click-menu-as-root/<ul>
<li>
<p>Edit <em>/root/.config/obmenu-generator/schema.pl</em>:</p>
<pre><code class="language-shell">leafpad /root/.config/obmenu-generator/schema.pl
</code></pre>
</li>
<li>
<p>Find the line that says:</p>
<pre><code class="language-perl">require '/home/root/.config/obmenu-generator/config.pl';
</code></pre>
<p>and change it to read:</p>
<pre><code class="language-perl">require '/root/.config/obmenu-generator/config.pl';
</code></pre>
</li>
<li>
<p>Save the file</p>
</li>
</ul>
<p>Thanks to <em>rfk1ll</em> on the Manjaro forum for this invaluable hint.</p>
Using Windows key combinations in Xfce2013-12-25T12:09:43Zhttps://www.clausconrad.com/blog/using-windows-key-combinations-in-xfce/<p>If you like me are coming to Xfce from a Windows background, you are likely used to opening the applications menu using your meta key (often called Windows key because of its symbol). This can easily be achieved in Xfce like so:</p>
<ul>
<li>You need to use “Whisker menu”, a plugin for Xfce4, NOT the applications menu that ships with Xfce. Fortunately this is easy to install using your package manager, and several distributions now install Whisker menu as the default menu for Xfce4 (Manjaro, Mint, probably others). After installing the plugin, add it to a panel like you would with any other panel item, and remove the original applications menu.</li>
<li>In the keyboard settings applet, bind the command “xfce4-popup-whiskermenu” to the Windows key (which will show as “Super L” - that’s fine).</li>
</ul>
<p>So far, so good - but what about combinations? Personally I like to launch my file manager using Win+E and so on. We can bind the applications using the keyboard applet as with the shortcut above, but this leaves one problem: the initial keypress of the Windows key, followed by the letter defined for the application shortcut, will open the Whisker menu AND the application bound to
the key combination.</p>
<p>Whisker menu can be closed by pressing Escape, but it’s a bit of a hassle and feels weird. In order to resolve this, create a shell script that launches your application, followed by running the command “xfce4-popup-whiskermenu”. Yes, this is the same command used above to open the menu - with the menu already open, this command will instead close Whisker menu.</p>
<h2 id="examples" tabindex="-1">Examples</h2>
<h3 id="launching-a-calculator-with-win%2Bc" tabindex="-1">Launching a calculator with Win+C</h3>
<p>~/bin/whisker-calculator.sh</p>
<pre><code class="language-shell">galculator &
xfce4-popup-whiskermenu &
</code></pre>
<h3 id="launching-a-file-manager-with-win%2Be" tabindex="-1">Launching a file manager with Win+E</h3>
<p>~/bin/whisker-filemanager.sh</p>
<pre><code class="language-shell">spacefm &
xfce4-popup-whiskermenu &
</code></pre>
<h3 id="launching-a-terminal-with-win%2Br" tabindex="-1">Launching a terminal with Win+R</h3>
<p>cat ~/bin/whisker-terminal.sh</p>
<pre><code class="language-shell">lxterminal &
xfce4-popup-whiskermenu &
</code></pre>
<p>Don’t forget that you need to bind your new script to the desired shortcut, as described above for opening the Whisker menu.</p>
Troubleshooting Linux sound problems2013-12-23T19:33:36Zhttps://www.clausconrad.com/blog/troubleshooting-linux-sound-problems/<ul>
<li>
<p>Unmuting outputs:</p>
<pre><code class="language-shell">alsamixer
</code></pre>
</li>
<li>
<p>Testing speaker channels:</p>
<pre><code class="language-shell">speaker-test -c 5 -D default -t wav
</code></pre>
</li>
<li>
<p>Disabling automatic suspension of sink in Pulseaudio:</p>
<pre><code class="language-shell">sudo vi /etc/pulse/default.pa
</code></pre>
<p>Comment this line out:</p>
<pre><code class="language-text"># load-module module-suspend-on-idle
</code></pre>
<p>Then restart Pulseaudio (probably easiest by logging out and in to X again?)</p>
</li>
</ul>
Deactivate xscreensaver via SSH2013-12-23T17:58:23Zhttps://www.clausconrad.com/blog/deactivate-xscreensaver-via-ssh/<pre><code class="language-shell">xscreensaver-command -deactivate
</code></pre>
<p>If you happen to use gnome-screensaver (default in Ubuntu), the following command might help (not tested):</p>
<pre><code class="language-shell">DISPLAY=:0 gnome-screensaver-command -p
</code></pre>
<p>Thanks to YaronSh on the <a href="https://ubuntuforums.org/showthread.php?t=632580">Ubuntu forums</a>.</p>
Restarting SpiderOak after switching networks2013-12-10T12:07:15Zhttps://www.clausconrad.com/blog/restarting-spideroak-after-switching-networks/<pre><code class="language-shell">env kill -s 1 SpiderOak
SpiderOak &
</code></pre>
<p>Not much to it and call me lazy, but it’s easier to click a launcher to run this script than having to right-click the SpiderOak tray icon, choose Quit, then restart it from the start menu ;-)</p>
Faster iPhone tethering with Manjaro2013-12-10T08:41:34Zhttps://www.clausconrad.com/blog/faster-iphone-tethering-with-manjaro/<p>I have a couple of connections in my Network Manager, most of which are set to auto-connect - e. g. my home network, wifi at work, and my iPhone. I noticed that Manjaro detects those regular wireless routers at home and work pretty quickly and connects to them almost immediately.</p>
<p>Not so with the iPhone. Although I go to the “Personal hotspot” settings on the iPhone (which I believe is necessary for the iPhone to accept new wireless clients) it can take 10 or more seconds, before Network Manager detects the new hotspot and connects to it. Here’s what I did to shorten that wait:</p>
<ol>
<li>
<p>In a terminal, verify that the iPhone’s hotspot is registered with NetworkManager and that it is set to auto-connect by entering:</p>
<pre><code class="language-shell">nmcli -f name,autoconnect con list
</code></pre>
<p>Make sure the name of your iPhone’s hotspot is listed and that it says “yes” in the AUTOCONNECT column.</p>
</li>
<li>
<p>Now create a shell script or a launcher (depending on your desktop environment) with the following command:</p>
<pre><code class="language-shell">nmcli con up id "John's iPhone"
</code></pre>
<p>…where “John’s iPhone” obviously should be replaced by the name of your hotspot ;-)</p>
</li>
<li>
<p>Simply run the script or click the launcher icon whenever you want to connect to the iPhone, and it should come up after about a second. Unfortunately it is still necessary to go to the “Personal hotspot” settings page on the iPhone before this will work, but at least you’re online faster than having to wait for auto-connect.</p>
</li>
</ol>
Fix for python path on SmartOS2013-11-09T17:58:31Zhttps://www.clausconrad.com/blog/fix-for-python-path-on-smartos/<ol>
<li>
<p>Create a symlink:</p>
<pre><code class="language-shell">pfexec ln -s /opt/local/bin/python2.7 /opt/local/bin/python
</code></pre>
</li>
</ol>
<p>(Yes, seriously… I forget this all too often, so I wrote it down for my own sake…)</p>
"Try this search on Google" for startpage.com2013-11-09T13:27:30Zhttps://www.clausconrad.com/blog/try-this-search-on-google-for-startpage-com/<p>I tried DuckDuckGo once and it had this nice “Try this search on…” menu to repeat your search on other, more common or specialized, search engines. Unfortunately Startpage / ixQuick doesn’t have a similar function, so I made a small user script to achieve the same functionality (assuming you run Chrome
or Chromium - other browsers are not currently supported).</p>
<p>How to install:</p>
<ol>
<li>Right-click and save <a href="https://github.com/cconrad/userscripts/raw/master/startpagecom-google.user.js">startpagecom-google.user.js</a></li>
<li>Open Extension settings</li>
<li>Drag-and-drop the script from the download bar at the bottom of Chrome/Chromium into the Extension settings</li>
<li>Allow access to your data on <a href="http://startpage.com">startpage.com</a></li>
</ol>
<p>How to use:</p>
<ol>
<li>To repeat a search on Google, click the “Enhanced by Google” logo to the right of the search box on any results page on <a href="http://startpage.com">startpage.com</a>.</li>
</ol>
Use root PATH for sudo on FreeBSD2013-11-03T20:12:13Zhttps://www.clausconrad.com/blog/use-root-path-for-sudo-on-freebsd/<ol>
<li>
<p><code>sudo vi /usr/local/etc/sudoers.d/secure_path</code></p>
</li>
<li>
<p>Enter this text on one line (changing the value as desired):</p>
<pre><code class="language-text">Defaults secure_path = "/usr/local/share/pcbsd/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/root/bin"
</code></pre>
</li>
<li>
<p>Save the file</p>
</li>
</ol>
<p>For more information see the <a href="https://linux.die.net/man/5/sudoers">sudoers</a> man page. Note, however, that there are <a href="https://askubuntu.com/questions/146869/why-does-sudo-not-add-roots-path-with-ubuntu-12-04/147905#147905">good reasons to keep the invoking user’s PATH</a>.</p>
Keyboard shortcut to delete files in Nautilus2013-10-08T15:02:34Zhttps://www.clausconrad.com/blog/keyboard-shortcut-to-delete-files-in-nautilus/<p>Simply press CTRL+DEL to move the selected file(s) to the trash (without any confirmation dialog). Pressing SHIFT+DEL deletes the selected files immediately (with a confirmation dialog).</p>
Installing Couchbase 2.1.1 on CentOS 6.42013-09-23T12:03:12Zhttps://www.clausconrad.com/blog/installing-couchbase-2-1-1-on-centos-6-4/<p>When downloading Couchbase Server 2.1.1 Community Edition (the latest release at this time) for RHEL and CentOS from <a href="http://couchbase.com">couchbase.com</a>, the installation instructions simply state to “download the RPM and run rpm -i couchbase-server-enterprise_x86_64_2.1.1.rpm”. However, this resulted in an error about missing libcrypto and other libraries on my off-the-shelf CentOS 6.4 server.</p>
<p><a href="https://tapasmishra.wordpress.com/2013/05/03/how-to-install-couchbase-2-0-1-enterprise-server-on-centos-with-php-ext-couchbase/">Tapamishra</a> provided some helpful hints:</p>
<ol>
<li>
<p>First install the Development Tools group meta-package:</p>
<pre><code class="language-shell">sudo yum -y groupinstall "Development Tools"
</code></pre>
</li>
<li>
<p>Second, install this older version of OpenSSL:</p>
<pre><code class="language-shell">sudo yum -y install openssl098e
</code></pre>
</li>
<li>
<p>At this point, the RPM installation should succeed:</p>
<pre><code class="language-shell">sudo rpm --install couchbase-server-community_x86_64_2.1.1.rpm
</code></pre>
</li>
</ol>
<p>Remember to open port 8091 (if required) to continue setup using a web browser from another machine.</p>
Converting Mercurial repositories to Git2013-09-23T09:06:13Zhttps://www.clausconrad.com/blog/converting-mercurial-repositories-to-git/<ol>
<li>
<p>Install Mercurial 1.7.5. Later versions may work, but that’s what I use.</p>
</li>
<li>
<p>Install <a href="https://hg-git.github.io/">hg-git</a> (a Mercurial extension). I’m not exactly sure what version I use, all I can say is that the version does matter, different hg-git versions work (or not) with different Mercurial versions. A link to more information about finding the right combination is at the bottom of the hg-git page.</p>
</li>
<li>
<p>Install git (latest version is fine).</p>
</li>
<li>
<p>Create a “bare” git repository, like this:</p>
<pre><code class="language-shell">git init --bare myrepo.git
</code></pre>
</li>
<li>
<p>“Push” the hg repo to the git repo:</p>
<pre><code class="language-shell">hg push /path/to/myrepo.git
</code></pre>
</li>
<li>
<p>If everything went well, you can now clone the Git repo to get your files back:</p>
<pre><code class="language-shell">git clone /path/to/myrepo.git myrepo
</code></pre>
</li>
</ol>
Using the Windows key to open Xfce application menu2013-09-22T15:37:04Zhttps://www.clausconrad.com/blog/using-the-windows-key-to-open-xfce-application-menu/<ol>
<li>
<p>Click the Application menu > “Settings” > “Keyboard”:
<img src="/assets/img/xfce-win-1_9876326223_o.png" alt="xfce-win-1" /></p>
</li>
<li>
<p>Click the “Application Shortcuts” tab, click the “+ Add” button, enter “xfce4-popup-applicationsmenu” into the “Command” field, and click “OK”:<br />
<img src="/assets/img/xfce-win-2_9876226874_o.png" alt="xfce-win-2" /></p>
</li>
<li>
<p>When this window appears, press the Windows key (or whatever other shortcut you prefer) and click OK:<br />
<img src="/assets/img/xfce-win-3_9876325363_o.png" alt="xfce-win-3" /></p>
</li>
</ol>
<p>Note that the left Windows key will be shown as “Super_L”, this is okay.</p>
Installing software on PC-BSD 9.2 - for dummies2013-09-22T01:02:12Zhttps://www.clausconrad.com/blog/installing-software-on-pc-bsd-9-2-for-dummies/<p>I have used most types of operating systems throughout the years. For those interested in a little history, see <a href="/blog/my-hardware-and-os-history/">my hardware and OS history</a>. For those just interested in the package installation process on PC-BSD, please skip the next paragraphs until after the horizontal line.</p>
<p>At the moment, I am evaluating PC-BSD 9.2 in a virtual machine. Why am I going to this extent, you might ask? Some time ago, I researched web server performance and made the switch from Apache (2.2 or 2.4) to nginx for most of the websites I run or develop, which has resulted in a significantly positive impact on web site perfornance, as well as easier administration. As described in the article mentioned above, my main operating system is Windows 8. Unfortunately nginx does not run easily on that operating system (I realize that it can be done, but it requires some serious tinkering to make it behave the way other Windows services work).</p>
<p>Since I currently develop a website meant to run on nginx on CentOS, the differences between running Apache on my development machine and nginx on the staging/production servers soon became apparent. At that moment, I switched to developing in a VM using the latest version of Fedora, which closely resembled the final environment and made debugging easier (I tried CentOS in a VM, but VMWare didn’t support it with any paravirtualized drivers (“VMWare Tools”), so performance was sub-standard.) However, due to the specs of my development laptop, I can’t afford to run multiple virtual machines efficiently at the same time. Most of my development sites are hosted on SmartOS (also running nginx as the server). So the most logical decision seemed to be to try PC-BSD 9.2 (which has ZFS and *BSD commands, like SmartOS, and supports nginx and related dependencies, like CentOS). The following paragraphs describe my experience with this operating system.</p>
<hr />
<p>PC-BSD is based on FreeBSD. Most importantly, these *BSD distributions use 2 different software installation methods;</p>
<ul>
<li>
<p><a href="https://docs.freebsd.org/en/books/handbook/ports/#pkgng-intro">pkgng</a><br />
The “new” binary installation method. Installs binary (pre-compiled) packages.
As far as I know, these are the same packages provided by <em>pkg_add</em> and related tools. To switch to pkgng, run the <em>pkg</em> bootstrap command. Once you go pkgng, you can’t go back to using the pkg_add etc, commands anymore.</p>
</li>
<li>
<p><a href="https://docs.freebsd.org/en/books/handbook/ports/#ports-using">ports</a><br />
The ports collection offers more packages than the binary alternatives described above. The disadvantage is that these packages need to be compiled from source code locally, potentially taking a lot more time. However, the ports system supposedly uses the same database as the binary packaging systems, so stuff doesn’t get out of sync, and it handles dependencies just like the other commands.</p>
</li>
</ul>
My hardware and OS history2013-09-22T00:10:39Zhttps://www.clausconrad.com/blog/my-hardware-and-os-history/<p>I started with C64 Basic and GEOS on a Commodore 64.</p>
<p>After having broken several C64s, I used a Amstrad PCW 8256. This was my first computer with a printer attached, a spectacular loud 9-needle printer. It ran CP/M, but I mostly used the native word processing software, which was
actually quite good for writing letters. But although the Amstrad’s hardware was more sophisticated than the Commodore 64’s, it wasn’t as versatile, barely more than an electronic typewriter on steroids.</p>
<p>When I got my first PC, an IBM 8088, I used MS-DOS and Caldera’s PC-DOS; my most used applications at that time probably were Leisure Suit Larry and Terminate 5 (for accesing BBSes). While slow for PC standards, this system felt more powerful than what I had before, mostly due to its ability to use a 14.4K modem to connect with the world.</p>
<p>Upon upgrading to a 386 and a 56.6k modem, and then a Pentium (and Athlon, Celeron, P4, etc. later on), PC-DOS got replaced by Windows 3.11 for Workgroups, then 95, NT 4, 98, ME (RIP), 2000, XP, 2003, 7, Vista and 8, in that order (I heard too many bad things about Vista to consider upgrading to it from XP; the downgrade from 7 to Vista on a home “server” was due to
licensing issues). For a while I also tried BeOS 5 and 6 and OS/2 Warp on my workstation.</p>
<p>On my Macs (I had a Mac Mini, a hackintosh, and currently own an older Macbook), I have been running OS X versions from 10.3 to 10.7.</p>
<p>On different hardware, I have been running quite a few Linux distributions (Suse, CentOS, Ubuntu, Debian, Fedora, MintOS and probably others I can’t remember) as well as Solaris 7, 9, 10, OpenSolaris and Solaris Express.</p>
<p>All of these are mostly obsolete now and no longer in use by me, with the exception of Windows 8, which I use on my main laptop. (The Macbook runs OS X 10.7 as far as I remember, but it is quite old and I only keep it around as a backup system).</p>
<p>Then there’s the netbook that came with Asus EEE Linux (based on some commercial Linux distribution), which I reformatted with Jolicloud, Ubuntu Netbook Remix and later ChromiumOS (the open-source version of ChromeOS).</p>
<p>Haven’t powered that one up for a while, but it’s probably still running Chromium OS.</p>
<p>Oh well, getting all nostalgic here. So what about today? At the moment, I don’t own what I would consider a workstation (i.e. a stationary computer). Although some of my boxes at home are stationary, they are only serving some specific purpose and are running those tasks 24/7, so I consider them to be “servers” - even though we are not talking about server-grade hardware at all - to me a “server” is a device that runs most of the time in order to provide specific services.</p>
<p>My main computer is a laptop that is much more powerful than my previously owned workstations, with the exception of the amount of internal storage. I run Windows 8 as its main operating system, which I am quite happy with. To me, Windows 8 is the best consumer OS at the moment. It’s not based on UNIX/POSIX unfortunately, but it is flexible and customizable enough to create most desired environments (not without some heavy tinkering though). Arguably, Mac OS X is a “better” developer operating system from my perspective, as it is based on FreeBSD and other UNIXes, but it only runs on expensive Apple hardware and seems to become a walled garden at this time, unlike Windows.</p>
<p>Apart from this laptop, there is the mentioned Macbook as a standby backup, and the netbook I haven’t used for a while. Another workstation runs Windows 7 and serves as a HTPC (multimedia playback for the TV). Yet another workstation runs OmniOS (see below) and serves as a NAS device/server. Finally, my girlfriend and her kids use a couple of laptops with Mac OS X 10.6, Windows 7 and Windows 8.</p>
<p>Outside my home, and apart from several shared webhosts that I don’t control, I am administering a dedicated SmartOS server that hosts several websites and related services. If you read the previous paragraphs carefully, you’ll remember that I tinkered with Solaris 9 and its successors. At that time, I was extremely impressed by the stability and performance of Solaris,
OpenSolaris and the Solaris-like OpenNevada (ON or OS/Net), as compared to my experiences with Linux distributions. Ever since using Solaris 10 and the Open Web Stack provided by Sun Microsystems at that time to run Apache, MySQL and PHP on it (“SAMP”), I have preferred operating systems based on Solaris’ (or its derivatives) kernels for any serious web hosting, due to its ability to run separate zones (similar to jails in FreeBSD and containers in Linux), DTrace and most importantly, the superior ZFS file system. Sun Microsystems made some serious attempts to open-source Solaris’ code and attract developers
to it in much of the same way Linux gets developed. Unfortunately, Sun Microsystems got aquired by Oracle, who all but stopped the community efforts to work on Solaris. When Oracle acquired Sun, OpenSolaris didn’t receive updates anymore, and the operating system soon became obsolete. For some years, the future looked dark for open-source Solaris - while Oracle didn’t stop working on the operating system, they made further developments proprietary and began requiring (paid) support contracts for any server running Solaris (unless you only wanted to run it at home). Then, without much fanfare, the Illumos project was created, forking the remaining (and still free) OpenSolaris code and adding new features and userland software to it. While this was a great development, Illumos wasn’t a whole operating system,
just like GNU isn’t a Linux distribution. Fortunately several vendors recognized the potential of Illumos and built distributions around it. The most known at this time are probably SmartOS (a server operating system sponsored by the cloud hosting company Joyent), OmniOS (another server operating system sponsored by Omniti), Nexenta (a NAS appliance available in a stripped-down Community Edition and a commercial offering) and OpenIndiana (a hobbyist developers’ approach to create a more modern operating system resembling OpenSolaris on top of the Illumos kernel).</p>
<p>All of these developments are - in my opinion - good for Illumos, since all of these companies more or less kindly contribute their development efforts back to the kernel project. Without a single vendor behind it, unfortunately Illumos hasn’t (yet) received the publicity it deserves. Hopefully this will change as the system matures and more cost-conscious companies are making the switch from Oracle hardware and Solaris 10 to Illumos-based distributions (which are binary compatible with Solaris 10, so no recompilation of code is required to run legacy Solaris applications on it).</p>
<p>Joyent is one of the smaller cloud hosting companies mostly trying to compete with Amazon AWS. AWS is running a (very customized) version of Xen as their hypervisor. Xen runs paravirtualized guest OS’s and I am sure Amazon has done a great job at optimizing it for their needs, but there still has to be some overhead to emulate physical hardware, meaning they can run fewer VMs on a physical host than without any emulation. Solaris/SmartOS zones, like FreeBSD’s jails, Linux’ containers and OpenVZ containers, provide a separation between virtual machines that creates less overhead than paravirtualized guests, such as those used in Xen, KVM, VMWare and other hypervisors. Unlike the mentioned approaches, the virtualization overhead of a Solaris/SmartOS zone is barely measurable (although it exists, of course - nobody should claim to run at 100% of bare-metal speed if anything gets virtualized). So while Joyent tries to compete with AWS on price, in my opinion they should really try to compete on the performance achievable for the same cost as on AWS. Anyway, Joyent kindly open-sourced their SmartOS operating system (based on the Illumos kernel and the basic building block of all their physical hosts), so that’s what I am running on my own dedicated server. FreeBSD’s jails and Linux’ containers (and Parallels’ OpenVZ) might be better supported, but ever since using Solaris 9 and especially 10 (and the successing OpenSolaris releases) I’ve been too impressed with that kernel’s performance to consider anything else. My dedicated server running SmartOS has 16 GB of RAM, which is plenty to support at least 64 totally isolated web server environments for
smaller sites. Mind you, these are not 64 websites like on a shared webhost, but totally separate operating environments, with impenetrable TCP/IP boundaries between each other, having their own server processes, ports and IP addresses - in essence much more secure than your standard shared webhost.</p>
<p>So in my opinion SmartOS is a great operating system for physical hosts dedicated to web serving and the like, but there is one drawback to it - SmartOS somewhat forces you to run mostly anything in zones. Again, this is a plus instead of a drawback for web servers, but what if you only want to run a single server with a single purpose? It is possible to install additional packages in a SmartOS “global” zone, but the system isn’t really designed to be used that way. Another distribution based on the Illumos kernel is OmniOS, which is better suited to be run as a single-zone server. When I set up my home NAS server, the only requirements I had were “no licensing costs”, “open source” and “ZFS file system” (so I could take snapshots and have self-healing mirrors). OpenSolaris fits that description (which is why I used it previously for that purpose), but that isn’t updated anymore; SmartOS makes it a little difficult to use that OS for this purpose. I tried FreeNAS, but got less than stellar performance (including some random crashes) from it (to be fair, this might be because my hardware didn’t fulfill its system requirements). In the end, I installed OmniOS and never looked back. It behaves very much like
SmartOS, except everything runs perfectly fine in the global zone by default and the system requirements were more acceptable than those of Solaris 10/11. I believe I never had to reboot that server after installing and configuring the necessary components.</p>
<p>If you’ve read this far, you might wonder what my point is in writing all of this. To be honest, I don’t try to convince you to try all of the operating systems I have used, nor do I want to dissuade you from using any of them. Neither do I intend to convince you to use the operating systems I use now, even though they fulfill my requirements for the time being. I am simply trying to tell my experiences and hope that you will make your own decisions when it comes to running laptops, desktops, workstations, home/virtual/dedicated servers. My point could probably be summarized by “choose the right tool for the right job”. That pretty much sums up my overall philosophy - no tool (in this case “operating system”) is perfect, it all depends on what you want to achieve.</p>
<h2 id="see-also" tabindex="-1">See also</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Commodore_64">Commodore 64</a></li>
<li><a href="https://en.wikipedia.org/wiki/GEOS_(8-bit_operating_system)">GEOS</a></li>
<li><a href="https://en.wikipedia.org/wiki/Amstrad_PCW#PCW_8256_and_8512">Amstrad PCW 8256</a></li>
<li><a href="https://en.wikipedia.org/wiki/CP/M">CP/M</a></li>
<li><a href="https://en.wikipedia.org/wiki/MS-DOS">MS-DOS</a></li>
<li><a href="https://en.wikipedia.org/wiki/PC-DOS">PC-DOS</a></li>
<li><a href="https://en.wikipedia.org/wiki/Terminate_(software)">Terminate</a></li>
<li><a href="https://en.wikipedia.org/wiki/BeOS">BeOS</a></li>
<li><a href="https://en.wikipedia.org/wiki/OS/2#1994-1996:_The_.22Warp.22_years">OS/2 Warp</a></li>
<li><a href="https://en.wikipedia.org/wiki/SmartOS">SmartOS</a></li>
</ul>
A nicer "vmadm list" for SmartOS2013-09-17T07:44:38Zhttps://www.clausconrad.com/blog/a-nicer-vmadm-list-for-smartos/<p>Screenshot:</p>
<p><a href="/assets/img/vmlist_9782574613_o.jpg"><img src="/assets/img/vmlist_9782574613_o.jpg" alt="vmlist" /></a></p>
<p>This displays the Alias at the top left, the UUID at the top right, and the first IP address and RAM allocation on a second line. Stopped zones (if any) are displayed below the running ones.</p>
<p>Code follows:</p>
<pre><code class="language-python">#!/usr/bin/env python2.7
from subprocess import check_output
def list_vms(state):
vlr = check_output([
"vmadm",
"list",
"-p",
"-o",
"alias,max_physical_memory,nics.0.ip,uuid",
"state=%s" % state
])
vlr = [vm for vm in vlr.split("\n") if len(vm)]
if len(vlr):
print state.capitalize().center(80)
print "=" * 80
for vm in vlr:
vm = vm.split(":")
print "%s%s" % (
vm[0],
vm[3].rjust(80 - len(vm[0]))
)
print "%s%s" % (
"IP: %s" % vm[2],
("Memory: %s MB" % vm[1]).rjust(80 - 4 - len(vm[2]))
)
print
if __name__ == "__main__":
list_vms("running")
list_vms("stopped")
</code></pre>
<p>I hope this proves helpful to someone else. Of course this requires installing Python 2.7 in the global zone where <code>pkgin</code> isn’t available by default, see here <a href="https://pkgsrc.joyent.com/install-on-illumos/">how to install pkgin in the global zone</a>, after that you can simply do a <code>pkgin in python27</code>.</p>
Can't leave EQ2 Dungeon Maker?2013-07-25T10:08:56Zhttps://www.clausconrad.com/blog/can-t-leave-eq2-dungeon-maker/<ol>
<li>In the Dungeon Maker Toolbox, scroll down to Effects.</li>
<li>Double-click the “Dungeon Exit” item and place it.</li>
<li>Right-click the dungeon exit you placed and choose “Leave” from the context menu.</li>
</ol>
<p>Thanks to <a href="https://forums.station.sony.com/eq2/index.php?members/afista.78/">Afista</a> for <a href="https://forums.station.sony.com/eq2/index.php?threads/bug-leave-dungeon-button-on-housing-window-is-broken.536174/">this solution</a>.</p>
OmniOS/OpenIndiana IPS repository2013-06-03T08:46:18Zhttps://www.clausconrad.com/blog/omnios-openindiana-ips-repository/<ul>
<li>pkg set-authority -O <a href="http://pkg.openindiana.org/dev/">http://pkg.openindiana.org/dev/</a> <a href="http://openindiana.org">openindiana.org</a></li>
</ul>
<p>I am not affiliated with this repository and you have to decide for yourself whether to trust it or not. You have been warned ;-)</p>
Cheaper than locally: ordering food online in Sweden2013-04-19T12:49:36Zhttps://www.clausconrad.com/blog/cheaper-than-locally-ordering-food-online-in-sweden/<p>When I was visiting the US i frequently shopped food at <a href="http://Amazon.com">Amazon.com</a>. Since that time I have always been jealous of the assortment, prices and delivery speed of Amazon’s grocery department, advantages that haven’t been available to Swedish residents - until recently, that is.</p>
<p>Amazon has local sites in many larger countries around the world, though none in the Scandinavian countries. Still, many Swedes are used to ordering books from <a href="http://Amazon.co.uk">Amazon.co.uk</a> or one of the other Amazon branches inside the European Union (in order to avoid customs). However, the delivery of grocery items has traditionally been restricted to the primary country of each Amazon branch - e.g. their UK site would only deliver groceries to the UK and possibly Northern Ireland.</p>
<p>Thus I was pretty excited when I recently discovered that <a href="http://Amazon.de">Amazon.de</a> had loosened their restrictions and now offered to ship some groceries to Sweden and other countries. Our kids just love Chili con carne and when time is of the essence (as I guess it is for most parents), Knorr’s “Chili con Carne” is a tasty and not-too-unhealthy way to save time while preparing the childrens’ favorite dinner. If you are asked to prepare the same dish once in a while, buying it in bulk through <a href="http://Amazon.de">Amazon.de</a> can save you money despite the additional shipping costs.</p>
<p>Here’s an example based on the above product as an example:</p>
<table>
<thead>
<tr>
<th>Shop</th>
<th>Item</th>
<th>Price</th>
<th>Shipping</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>LIDL</td>
<td>25 x Knorr Chili con Carne</td>
<td>25 x SEK 11.90 = SEK 297.50</td>
<td>SEK 0</td>
<td>SEK 297.50</td>
</tr>
<tr>
<td><a href="http://Amazon.de">Amazon.de</a></td>
<td>25 x Knorr Chili con Carne</td>
<td>EUR 20.68 = SEK 176.03</td>
<td>EUR 5.90 = SEK 50.22</td>
<td>SEK 226.25</td>
</tr>
</tbody>
</table>
<p>So even a “small” order of 25 bags of Knorr products can save you SEK 71.25 (not taking the time for going to the nearest LIDL shop versus going to the nearest post office into account).</p>
<p>Now SEK 71.25 doesn’t sound like a huge amount, but if you order several products together the savings can easily mean a couple of hundred SEK more in your pocket. Of course, whether this way of shopping is worth it for you depends on a couple of factors, such as the variation of dinner dishes you prepare, your distance to the supermarkets versus your distance to the post office etc., but I hope this idea is helpful to somebody.</p>
Zend OPcache for PHP on SmartOS2013-04-10T19:14:12Zhttps://www.clausconrad.com/blog/zend-opcache-for-php-on-smartos/<p>Zend OPcache (previously known as Zend Optimizer+) is one of several opcode caches for PHP, the other most well-known being APC and eAccelerator. Zend Optimizer Plus has been available in binary form together with Zend Server (CE) for some time, but Zend recently decided to contribute the code to the PHP project. Thus it can now be used on platforms such as SmartOS, where Zend Server isn’t an option. Thank you Zend! :)</p>
<p>Zend OPcache will be part of PHP from the upcoming 5.5 version, but the <a href="https://github.com/zend-dev/ZendOptimizerPlus">source code</a> is compatible with PHP 5.2 and later versions. See below for installation steps.</p>
<h2 id="manual-installation" tabindex="-1">Manual installation</h2>
<ol>
<li>
<p>Update your package database:<br />
<code>pkgin up</code></p>
</li>
<li>
<p>Install prerequisites for building Zend OPcache:<br />
<code>pkgin in unzip php54-pear gmake gcc47 autoconf</code></p>
</li>
<li>
<p>Download and unpack the code:<br />
<code>wget --no-check-certificate https://github.com/zend-dev/ZendOptimizerPlus/archive/master.zip unzip master rm master</code></p>
</li>
<li>
<p>Build the extension:<br />
<code>cd ZendOptimizerPlus-master/ phpize ./configure --with-php-config=/opt/local/bin/php-config make make test make install</code></p>
</li>
</ol>
<h2 id="activating-the-extension" tabindex="-1">Activating the extension</h2>
<ol>
<li>
<p>Edit your php.ini:<br />
<code>vi /opt/local/etc/php.ini</code></p>
</li>
<li>
<p>Add the following line at the bottom of the file and save it:<br />
<code>zend_extension=/opt/local/lib/php/20120301/opcache.so</code></p>
</li>
<li>
<p>If you are using PHP-FPM, restart it:<br />
<code>svcadm restart php54-fpm</code></p>
</li>
</ol>
<p><em>Checked and updated on September 17, 2013.</em></p>
Backup Jenkins configuration to S32013-04-09T13:33:16Zhttps://www.clausconrad.com/blog/backup-jenkins-configuration-to-s3/<h2 id="dependencies" tabindex="-1">Dependencies</h2>
<ul>
<li><a href="https://wiki.jenkins-ci.org/display/JENKINS/S3+Plugin">S3 Plugin</a></li>
</ul>
<h2 id="global-configuration" tabindex="-1">Global configuration</h2>
<ol>
<li>Set up a S3 profile at <a href="#">jenkinshost/configure</a>.</li>
</ol>
<h2 id="job-configuration" tabindex="-1">Job configuration</h2>
<ol>
<li>
<p><span style="line-height: 13px;">Create a new free-style project and give it a name.</span></p>
</li>
<li>
<p>(Optional) I recommend to check “Discard Old Builds” and choose the following settings to save disk space:<br />
<span style="text-decoration: underline;">Strategy:</span> Log Rotation<br />
<span style="text-decoration: underline;">Days to keep builds:</span> (empty)<br />
<span style="text-decoration: underline;">Max # of builds to keep:</span> (empty)<br />
<span style="text-decoration: underline;">Days to keep artifacts:</span> 1<br />
<span style="text-decoration: underline;">Max # of builds to keep with artifacts:</span> 1</p>
</li>
<li>
<p>Set a build trigger of your choice; I use this:<br />
<span style="text-decoration: underline;">Build periodically - Schedule:</span> H H(0-5) * * *</p>
</li>
<li>
<p>Add an “Execute shell” build step with the following command:</p>
<pre><code class="language-shell"># Delete all files in the workspace
rm -rf *
# Create a directory for the job definitions
mkdir -p $BUILD_ID/jobs
# Copy global configuration files into the workspace
cp $JENKINS_HOME/*.xml $BUILD_ID/
# Copy keys and secrets into the workspace
cp $JENKINS_HOME/identity.key $BUILD_ID/
cp $JENKINS_HOME/secret.key $BUILD_ID/
cp $JENKINS_HOME/secret.key.not-so-secret $BUILD_ID/
cp -r $JENKINS_HOME/secrets $BUILD_ID/
# Copy user configuration files into the workspace
cp -r $JENKINS_HOME/users $BUILD_ID/
# Copy job definitions into the workspace
rsync -am --include='config.xml' --include='*/' --prune-empty-dirs --exclude='*' $JENKINS_HOME/jobs/ $BUILD_ID/jobs/
# Create an archive from all copied files (since the S3 plugin cannot copy folders recursively)
tar czf $BUILD_ID.tar.gz $BUILD_ID/
# Remove the directory so only the archive gets copied to S3
rm -rf $BUILD_ID
</code></pre>
</li>
<li>
<p>Create a post-build action of type “Publish artifacts to S3 Bucket” and configure as follows:<br />
<span style="text-decoration: underline;">S3 profile:</span> Choose the profile from the global configuration<br />
<span style="text-decoration: underline;">Source:</span> **<br />
<span style="text-decoration: underline;">Destination bucket:</span> Enter the name of the bucket where you want the archive to go<br />
Note: Even though it says “Destination bucket”, it is possible to enter a bucket name AND path, the S3 plugin will create the directory or use it if it already exists.</p>
</li>
</ol>
<h2 id="s3-configuration" tabindex="-1">S3 configuration</h2>
<p>The setup described above creates a new backup each day. I like being able to go back in history, e. g. if the accidental deletion of a job was discovered after several days. I’d recommend to use a lifecycle policy on the bucket to remove old backups after a desired number of days.</p>
<p>Alternatively one could achieve a similar effect by enabling versioning on the bucket and change the archive’s file name to a fixed value by changing the <em>tar</em> command in the shell script:<br />
<code>tar czf jenkins-configuration.tar.gz $BUILD_ID/</code></p>
Diigo backup script2013-04-07T17:05:53Zhttps://www.clausconrad.com/blog/diigo-backup-script/<p>Download/contribute: <a href="https://github.com/cconrad/diigo-backup">https://github.com/cconrad/diigo-backup</a></p>
Check for WordPress updates from the outside2013-03-31T16:45:07Zhttps://www.clausconrad.com/blog/check-for-wordpress-updates-from-the-outside/<p>It provides a secret URL to check for updates to the WordPress core, plugins and themes, without requiring cookie-based authentication. It is meant to be used from external monitoring or continous integration systems.</p>
<p>A simple usage example for Jenkins (requires the Python plugin for Jenkins) is given in the docs directory.</p>
<p><a href="https://github.com/cconrad/wp-external-update-check">Download/contribute</a></p>
My first open source commit2013-03-11T11:42:57Zhttps://www.clausconrad.com/blog/my-first-open-source-commit/<p><a href="https://bugs.dojotoolkit.org/ticket/15669">https://bugs.dojotoolkit.org/ticket/15669</a></p>
AutoHotkey MouseMove not working in Virtualbox2013-03-06T11:22:46Zhttps://www.clausconrad.com/blog/autohotkey-mousemove-not-working-in-virtualbox/<p>A simple solution for me was to disable mouse integration (Host key + I).</p>
Weekly review: Week ending February 16, 20132013-02-16T13:28:08Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-february-16-2013/<p><span style="text-decoration: underline;">Work</span></p>
<ul>
<li>Launched a customized Magento shop</li>
</ul>
<p><span style="text-decoration: underline;">Relationships</span></p>
<ul>
<li>Borrowed childrens books at the library</li>
<li>Ordered new prescriptions for the kids</li>
<li>Commented on the city’s family evaluation plan</li>
</ul>
<p><span style="text-decoration: underline;">Life</span></p>
<ul>
<li>Tried out new contact lenses</li>
</ul>
<p>No concrete plans for next week yet.</p>
SmartOS configuration notes2013-01-15T13:07:37Zhttps://www.clausconrad.com/blog/smartos-configuration-notes/<ul>
<li>
<p><strong>Change keymap</strong><br />
Default is US, to change, add a line to /usbkey/config like this:<br />
<em>default_keymap=denmark</em><br />
<a href="https://wiki.smartos.org/extra-configuration-options/#extraconfigurationoptions-Console%2FLogin%2FSSHkeys">Source</a></p>
<p><a href="https://wiki.smartos.org/extra-configuration-options/#extraconfigurationoptions-Console%2FLogin%2FSSHkeys"></a></p>
</li>
<li>
<p><strong>VirtualBox networking</strong></p>
<ul>
<li>Set VirtualBox NIC to NAT mode</li>
<li>Set SmartOS configuration (during install) to:<br />
IP: 10.0.2.15<br />
Netmask: 255.255.255.0<br />
Default gateway: 10.0.2.2<br />
<a href="https://blogs.oracle.com/fatbloke/entry/networking_in_virtualbox1#NAT">Source</a></li>
</ul>
<p><a href="https://blogs.oracle.com/fatbloke/entry/networking_in_virtualbox1#NAT"></a></p>
</li>
<li>
<p><strong>Installing a Joyent VM (zone)</strong><br />
<em>imgadm update</em><br />
<em>dsadm avail</em><br />
<em>dsadm import fdea06b0-3f24-11e2-ac50-0b645575ce9d</em><br />
Create JSON configuration file for new VM<br />
<a href="https://terramagnus.com/discovering-smartos/">Source</a></p>
<p><a href="https://terramagnus.com/discovering-smartos/"></a></p>
</li>
<li>
<p><strong>NAT for zones</strong><br />
<a href="https://wiki.smartos.org/extra-configuration-options/#extraconfigurationoptions-Console%2FLogin%2FSSHkeys">Source</a></p>
</li>
</ul>
Minimize (almost) any window to the systray2013-01-13T14:14:27Zhttps://www.clausconrad.com/blog/minimize-almost-any-window-to-the-systray/<p>This is a nice tool that runs perfectly well on Windows 8 with minimal resource usage. It works with any window I tried yet, doesn’t require administrative rights as far as I know, has no cumbersome installation/setup process, and the code is open source (C++).</p>
<p>Give it a try if you use Windows :)</p>
<p><a href="https://sourceforge.net/projects/rbtray/">Download RBTray</a></p>
Installing Caldecott on Windows2012-11-30T13:12:07Zhttps://www.clausconrad.com/blog/installing-caldecott-on-windows/<p>I wrote this because I received the following error trying to establish a tunnel to a MySQL instance on AppFog:</p>
<pre><code class="language-text">To use `af tunnel', you must first install Caldecott:
gem install caldecott
Note that you'll need a C compiler. If you're on OS X, Xcode
will provide one. If you're on Windows, try DevKit.
This manual step will be removed in the future.
Error: Caldecott is not installed.
</code></pre>
<p>To solve this problem, follow these steps:</p>
<ol>
<li>
<p>You need a Ruby distribution from <a href="https://rubyinstaller.org/">rubyinstaller.org</a> for this.<br />
You probably already have that, otherwise go <a href="https://rubyinstaller.org/downloads/">download the newest RubyInstaller from the top of this page</a>.</p>
</li>
<li>
<p><a href="https://rubyinstaller.org/downloads/">Download the latest DevKit</a> (Development Kit) from the same page, it is right below the heading “Development Kit”.</p>
</li>
<li>
<p>Run the DevKit executable (it is just a self-extracting 7Z archive and can be unpacked with other tools, if necessary) and extract it somewhere. <strong>Be sure to specify a new or empty directory as the destination.</strong></p>
</li>
<li>
<p>Rename the directory extracted in the previous step to <em>devkit</em> and move it to your Ruby’s installation folder, e. g. <em>C:\Ruby193</em>.</p>
</li>
<li>
<p>Open a command prompt as an administrator (e. g. by pressing the Start button, typing <em>cmd</em>, right-clicking the link to the command prompt and choosing “Run as Administrator”).</p>
</li>
<li>
<p>Change to the devkit folder by typing e. g. <em>cd C:\Ruby194\devkit</em> (depends on your Ruby installation folder of course).</p>
</li>
<li>
<p>Run the following command:</p>
<pre><code class="language-ruby">ruby dk.rb init
</code></pre>
</li>
<li>
<p>Run the following command:</p>
<pre><code class="language-ruby">ruby dk.rb install
</code></pre>
</li>
<li>
<p>Finally, to install Caldecott, run the following command:</p>
<pre><code class="language-shell">gem install caldecott --platform=ruby
</code></pre>
</li>
</ol>
<p>In case of problems check these <a href="https://github.com/oneclick/rubyinstaller/wiki/Development-Kit">instructions on GitHub</a>. Good luck!</p>
AppFog command line tool support for Jetbrains IDEs2012-11-26T10:06:08Zhttps://www.clausconrad.com/blog/appfog-command-line-tool-support-for-jetbrains-ides/<p>The next version of IntelliJ IDEA (v12) will have integrated support for CloudFoundry and I guess that means AppFog too, however the current version 11 has no such feature. Fortunately all Jetbrains IDEs have support for command line tools, so I don’t have to switch to a terminal or command prompt to run “af” commands - this works out of the box. Since I can’t remember all command line options and their syntax, I made a configuration file to enable auto-complete of “af” commands in the Jetbrains IDE command line. If you want to use this, here’s how to install it:</p>
<ol>
<li>
<p>I assume you already have AppFog’s command line tool installed; if not, follow these <a href="https://docs.appfog.com/getting-started/af-cli#installation">simple instructions</a>.</p>
</li>
<li>
<p>Make sure the “Command Line Tool Support” plugin is enabled in your IDE:<br />
<img src="/assets/img/11.26.2012-10.38.png" alt="Screenshot of 'Plugins' with checked 'Command Line Tool Support'" /></p>
</li>
<li>
<p>Go to “Command Line Tools Support” in the “Project Settings” area of your IDE settings; click the + icon to add a new framework and choose “Custom Framework” from the dropdown that appears. Enter a name for the framework (e. g. “AppFog”) and <em>af</em> for both of the “Tool path” and “Alias” fields. (If <em>af</em> is not in your path, you could also enter the full path into the “Tool path” field.) Finally, click “OK” in the dialog and “Apply” at the bottom of the Settings dialog:<br />
<img src="/assets/img/11.26.2012-10.44.png" alt="Screenshot of 'Framework Settings' with name 'AppFog CLI', tool path 'af' and alias 'af'" /></p>
</li>
<li>
<p>With the “af” line selected, click the “Edit” icon at the right of the Settings dialog, then <strong>close</strong> the Settings dialog:<br />
<img src="/assets/img/11.26.2012-10.50.png" alt="Screenshot of the 'Settings' dialog with highlighted 'pencil' (edit) icon and highlighted 'Close' button" /></p>
</li>
<li>
<p>The IDE has opened an editor window with an XML file describing the new “custom framework”. Replace all contents of this file with the following XML, then save and close the file:</p>
<pre><code class="language-xml"><?xml version="1.0" encoding="UTF-8"?>
<framework xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schemas/frameworkDescriptionVersion1.1.xsd" name="AppFog" invoke="af" alias="af" enabled="true" version="1">
<command>
<name>target</name>
<help>Reports current target or sets a new target</help>
<params>url[=null]</params>
</command>
<command>
<name>login</name>
<help>Login</help>
<params>email[=null] --email[=null] --passwd[=null]</params>
</command>
<command>
<name>info</name>
<help>System and account information</help>
</command>
<command>
<name>apps</name>
<help>List deployed applications</help>
</command>
<command>
<name>push</name>
<help>Create, push, map, and start a new application</help>
<params>appname[=null]</params>
</command>
<command>
<name>push</name>
<help>Push application to specificed infrastructure</help>
<params>appname --infra[=null]</params>
</command>
<command>
<name>push</name>
<help>Push application from specified path</help>
<params>appname --path[=null]</params>
</command>
<command>
<name>push</name>
<help>Set the url for the application</help>
<params>appname --url[=null]</params>
</command>
<command>
<name>push</name>
<help>Set the expected number &lt;N&gt; of instances</help>
<params>appname --instances N</params>
</command>
<command>
<name>push</name>
<help>Set the memory reservation for the application</help>
<params>appname --mem M</params>
</command>
<command>
<name>push</name>
<help>Do not auto-start the application</help>
<params>appname --no-start</params>
</command>
<command>
<name>pull</name>
<help>Download last pushed source of &lt;appname&gt; to [path]</help>
<params>appname path[=null]</params>
</command>
<command>
<name>start</name>
<help>Start the application</help>
<params>appname</params>
</command>
<command>
<name>stop</name>
<help>Stop the application</help>
<params>appname</params>
</command>
<command>
<name>restart</name>
<help>Restart the application</help>
<params>appname</params>
</command>
<command>
<name>delete</name>
<help>Delete the application</help>
<params>appname</params>
</command>
<command>
<name>update</name>
<help>Update the application bits</help>
<params>appname --path[=null]</params>
</command>
<command>
<name>mem</name>
<help>Update the memory reservation for an application</help>
<params>appname memsize[=null]</params>
</command>
<command>
<name>map</name>
<help>Register the application to the url</help>
<params>appname url</params>
</command>
<command>
<name>unmap</name>
<help>Unregister the application from the url</help>
<params>appname url</params>
</command>
<command>
<name>instances</name>
<help>Scale the application instances up or down</help>
<params>appname num|delta</params>
</command>
<command>
<name>crashes</name>
<help>List recent application crashes</help>
<params>appname</params>
</command>
<command>
<name>crashlogs</name>
<help>Display log information for crashed applications</help>
<params>appname</params>
</command>
<command>
<name>logs</name>
<help>Display log information for the application</help>
<params>appname --all[=null]</params>
</command>
<command>
<name>files</name>
<help>Display directory listing or file download for path</help>
<params>appname path[=null] --all[=null]</params>
</command>
<command>
<name>stats</name>
<help>Display resource usage for the application</help>
<params>appname</params>
</command>
<command>
<name>instances</name>
<help>List application instances</help>
<params>appname</params>
</command>
<command>
<name>env</name>
<help>List application environment variables</help>
<params>appname</params>
</command>
<command>
<name>env-add</name>
<help>Add an environment variable to an application</help>
<params>appname variable value</params>
</command>
<command>
<name>env-del</name>
<help>Delete an environment variable from an application</help>
<params>appname variable</params>
</command>
<command>
<name>services</name>
<help>Lists of services available and provisioned</help>
</command>
<command>
<name>create-service</name>
<help>Create a provisioned service</help>
<params>service --name[=null] --bind[=null]</params>
</command>
<command>
<name>create-service</name>
<help>Create a provisioned service on a specified infrastructure</help>
<params>service --infra[=null]</params>
</command>
<command>
<name>create-service</name>
<help>Create a provisioned service and assign it &lt;name&gt;</help>
<params>service name</params>
</command>
<command>
<name>create-service</name>
<help>Create a provisioned service and assign it &lt;name&gt;, and bind to &lt;app&gt;</help>
<params>service name app</params>
</command>
<command>
<name>delete-service</name>
<help>Delete a provisioned service</help>
<params>servicename[=null]</params>
</command>
<command>
<name>bind-service</name>
<help>Bind a service to an application</help>
<params>servicename appname</params>
</command>
<command>
<name>unbind-service</name>
<help>Unbind service from the application</help>
<params>servicename appname</params>
</command>
<command>
<name>clone-services</name>
<help>Clone service bindings from &lt;src-app&gt; application to &lt;dest-app&gt;</help>
<params>src-app dest-app</params>
</command>
<command>
<name>user</name>
<help>Display user account information</help>
</command>
<command>
<name>passwd</name>
<help>Change the password for the current user</help>
</command>
<command>
<name>logout</name>
<help>Logs current user out of the target system</help>
</command>
<command>
<name>add-user</name>
<help>Register a new user (requires admin privileges)</help>
<params>--email[=null] --passwd[=null]</params>
</command>
<command>
<name>delete-user</name>
<help>Delete a user and all apps and services (requires admin privileges)</help>
<params>user</params>
</command>
<command>
<name>runtimes</name>
<help>Display the supported runtimes of the target system</help>
</command>
<command>
<name>frameworks</name>
<help>Display the recognized frameworks of the target system</help>
</command>
<command>
<name>infras</name>
<help>Display the available infrastructures</help>
</command>
<command>
<name>aliases</name>
<help>List aliases</help>
</command>
<command>
<name>alias</name>
<help>Create an alias for a command</help>
<params>alias command</params>
</command>
<command>
<name>unalias</name>
<help>Remove an alias</help>
<params>alias</params>
</command>
<command>
<name>targets</name>
<help>List known targets and associated authorization tokens</help>
</command>
<command>
<name>help</name>
<help>Get general help or help on a specific command</help>
<params>command[=null]</params>
</command>
<command>
<name>help options</name>
<help>Get help on available options</help>
</command>
</framework>
</code></pre>
</li>
<li>
<p>Click “Tools” > “Run Command…” to open the command line pane:<br />
<img src="/assets/img/11.26.2012-10.59.png" alt="Screenshot of expanded 'Tools' menu with menu item 'Run Command...' highlighted" /></p>
</li>
<li>
<p>Type <em>af</em> and press Space to get a list of AppFog commands. The list narrows down as you continue typing, or you can choose the desired command from the list using the mouse or arrow and Enter keys:<br />
<img src="/assets/img/11.26.2012-11.02.png" alt="Screenshot of 'Run Command...' box with 'af' entered and autocomplete items appearing" /></p>
</li>
</ol>
Apache segmentation fault after enabling SSL2012-11-22T16:18:14Zhttps://www.clausconrad.com/blog/apache-segmentation-fault-after-enabling-ssl/<p>The easiest solution is to disable the curl extension, if you don’t need it (by default, this can be done by commenting the first line in <em>/usr/local/zend/etc/ext.d/curl.ini</em>).</p>
<p>Thanks to <a href="https://stackoverflow.com/questions/10831772/apache-2-segmentation-fault-when-zend-php-53-installed-with-curl">Sirex</a> for this answer! Unfortunately I am not allowed to upvote his/her answer on StackOverflow yet. I hope this link helps someone else.</p>
Weekly review: Week ending July 14, 20122012-07-13T22:00:37Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-july-14-2012/<p>Shame on me, but I am sitting in a train bound back home, after returning 3 of our special needs kids back to their father - they have been with us for 2 weeks - 'nough said?</p>
<p>Okay, probably not - though it was a hard time trying to get work done while avoiding the constant lingering tantrums from untreated children :(</p>
<p>So, in a kindof new format, here’s what I accomplished anyway:</p>
<p>Work</p>
<ul>
<li>Changed almost all page templates to load JavaScript using the AMD standard (a progressiv style of coding that allows developers to modularize code instead of copy/pasting, while retaining functionality and performance due to the ability to bundle modules together in .js files) (MM)</li>
<li>Inlined some ads to avoid the last synchronous iframe loading on the frontpage (MM)</li>
<li>Noticed Google Page Speed go down about 30% (i.e. faster loading of pages) due to switching from synchronously loaded ads to ads loaded in “friendly iframes” (with both of our ad servers, Emediate and Google DFP Small Business) (MM)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Had some good talks with Mikkel</li>
<li>Supported Birgit in branding herself personally</li>
</ul>
<p>Life</p>
<ul>
<li>Paid some overdue invoices</li>
<li>Sent an invoice to MM that hopefully will be paid in time so that I don’t get overdue again on payments next month</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p>Work</p>
<ul>
<li>Fix JavaScript and CSS bugs tue do the previous refactoring (MM)</li>
<li>Recreate functionality that existed before the switch to the new design (MM)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Reestablish a better relationship with my girlfriend after the last weeks’ stress</li>
</ul>
<p>Life</p>
<ul>
<li>Improve my personal finances by declaring company expenses as such</li>
<li>Improve my personal finances by settling debts with my girlfriend</li>
</ul>
<p><strong>Please feel free to hold me accountable to the above goals in 1 week from now - i’d appreciate it :)</strong></p>
Hiring on freelance sites2012-06-11T18:53:28Zhttps://www.clausconrad.com/blog/hiring-on-freelance-sites/<p>A “catch phrase” can be as simple as adding the sentence “Please mention ‘yellow dragon’ in your application” to your job description - which can be used to wield out the applicants who didn’t really read your job offering, but just decided to spam you with a cover letter template. In most cases, you don’t want to employ this kind of contractors.</p>
<p>I kept this job open for 9 days (which is indeed a long time - otherwise the number of withdrawals would have been a lot smaller). Either way, this method allowed me to narrow my search down to less than 1/5th of the applications in a short timeframe. If you can spend that time, or just start using catch phrases, you can avoid spending some time during the hiring process, especially for smaller jobs.</p>
Weekly review: Week ending August 5, 20112011-08-06T21:50:14Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-august-5-2011/<p>Work</p>
<ul>
<li>[X] Frontend design on new subscription pages - still in progress (MM)</li>
<li>[X] Taxes (CC)</li>
<li>Switched from Amazon to SendGrid for transactional mails (MM)</li>
<li>Verified backup scripts - tracked a problem with JungleDisk down to a failing post-backup script due to an expired license (Amino, MM)</li>
<li>Changed WYSIWYG editor in the control panel, integrated it with the old media browser (MM)</li>
<li>Tried to solve a nasty proxying problem (MM)</li>
<li>Fixed bugs in main CSS and converted it to LESS (MM)</li>
<li>RSS and gallery troubleshooting (WR)</li>
<li>Small task on oDesk for fun</li>
</ul>
<p>Relationships</p>
<ul>
<li>Went fishing with Birgit</li>
</ul>
<p>Life</p>
<ul>
<li>[X] Updated servers and CMS</li>
<li>Played with TeamViewer, set it up for unattended access</li>
<li>Wrote more personal diary entries again</li>
<li>Used my fakir mat again</li>
<li>Bought an insane amount of sweets at a cash&carry (engros) shop</li>
<li>Put a few old items up for sale on QXL (local eBay competitor)</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p>Work</p>
<ul>
<li>Taxes (CC)</li>
<li>Finish frontend design for subscription pages (MM)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Family bookkeeping</li>
<li>Lots of doctor’s appointments with the kids</li>
</ul>
<p>Life</p>
<ul>
<li>Get used to a regular rhythm again, now that the kids are back from their holidays</li>
<li>Update servers and CMS</li>
</ul>
<p>Location:<a href="https://www.google.com/maps/place/55%C2%B035'06.9%22N+12%C2%B056'28.8%22E/@55.585246,12.9391313,17z/data=!3m1!4b1!4m5!3m4!1s0x0:0x0!8m2!3d55.585246!4d12.94132">Rabygatan,Malmö Municipality,Sweden</a></p>
Skype as a SIP gateway2011-08-06T12:27:52Zhttps://www.clausconrad.com/blog/skype-as-a-sip-gateway/<p>A new business product, Skype Connect is a regular SIP gateway, albeit one that is connected to the Skype network. For 4.95 a line/month professional users and enterprises can receive calls from Skype users on regular phones (connected to a SIP VoIP router or software/hardware SIP PBX), receive calls from Skype landline numbers (“Skype-In numbers”) and route their outgoing calls at cheap Skype rates.</p>
<p>For more information, visit <a href="https://www.skype.com/en/features/skype-connect/">Skype Connect</a>.</p>
Personalize your Google+ URL2011-07-09T18:00:18Zhttps://www.clausconrad.com/blog/personalize-your-google-url/<p>Credits for this idea should go to <a href="https://www.concept-i.dk/">Thomas Rosenstand</a> instead of me. Redirect <a href="http://www.yourdomain.com/+">www.yourdomain.com/+</a> to your Google+ profile - if your web server runs Apache, this can be achieved by inserting the following line in the domains <code>.htaccess</code> file or the servers <code>httpd.conf</code> (<code>apache2.conf</code> on Debian-based operating systems, such as Ubuntu):</p>
<p><code>Redirect permanent /+ https://plus.google.com/107098868976669747695/posts</code></p>
<p>If you had to use the <code>.htaccess</code> file, that should be all. If you used a server-wide configuration file (and I would recommend so for better performance), remember to reload the settings. This can be achieved by restarting Apache, for example:</p>
<p><code>sudo apache2ctl restart</code></p>
Flickr backup tools2011-06-27T19:10:40Zhttps://www.clausconrad.com/blog/flickr-backup-tools/<ul>
<li><a href="https://sunkencity.org/flickredit">FlickrEdit</a><br />
A free, cross-platform GUI tool written in Java.</li>
<li><a href="https://getbulkr.com/">Bulkr / Bulkr Pro</a><br />
A cross-platform tool written in Adobe Air. Both versions can download all your photos incrementally. The paid Pro version supports more features, such as downloading the original sizes and metadata (tags, titles, descriptions, etc.).</li>
</ul>
<p>There are a couple of handfuls more applications claiming to being able to create Flickr backups. I chose these two because they are cross-platform - I don’t want to be forced to use a specific operating system in the future or to re-download all my pictures using another tool. In the end, I decided to try Bulkr Pro as its website looked more polished (shame on me) and, being a developer, I prefer Flash over Java any time. On a more objective note, Bulkr Pro features an impressive list of testimonials and does only thing (backing up Flickr photos) instead of a whole list of features - something that always makes me assume it does that thing better than other multi-purpose tools. I guess I am really biased :/</p>
<p>Suffice it to say that Bulkr worked really well and fast, so I purchased the Pro version and it didn’t let me down, downloading my 2,823 photos in a couple of hours. I would have prefered an option to generate XML files (instead of plain text files) with metadata for each image, but the format generated by Bulkr Pro seems easy enough to parse, if I ever need to restore to Flickr.</p>
CoffeeScript support for JetBrains PhpStorm/WebStorm/PyCharm2011-06-27T09:18:03Zhttps://www.clausconrad.com/blog/coffeescript-support-for-jetbrains-phpstorm-webstorm-pycharm/<p>To get the same level of support for CoffeeScript in PhpStorm (and probably in similar JetBrains IDEs such as WebStorm and PyCharm), simply copy the CoffeeScript plugin directory from a trial version of the latest version of RubyMine:</p>
<ol>
<li>Install <a href="https://confluence.jetbrains.com/display/RUBYDEV/RubyMine+Preview+and+RC+builds">RubyMine EAP</a></li>
<li>Copy the <em>coffeescript</em> directory from _C:\Program Files (x86)\JetBrains\RubyMine 107.261\plugins_ to _C:\Program Files (x86)\JetBrains\PhpStorm 2.1\plugins_</li>
</ol>
<p>A third-party plugin exist and is officially available for the other IDEs, although they probably come with just as little support as the solution described above. Notice that the following plugin is not being actively developed.</p>
<ul>
<li><a href="https://github.com/netzpirat/coffee-brew#readme">CoffeeBrew</a></li>
</ul>
Rsync between network drives?2011-04-27T11:08:36Zhttps://www.clausconrad.com/blog/rsync-between-network-drives/<p>Use the <code>--size-only</code> flag to avoid downloading remote files for checksum generation.</p>
Weekly review: Week ending April 8, 20112011-04-09T15:09:36Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-april-8-2011/<p>Work</p>
<ul>
<li>[X] Worked at the office every day to introduce and answer questions from new developer (MM)</li>
<li>[X] Retagged site for new DFP account (MM)</li>
<li>[X] Fixed huge SEO problem (MM)</li>
<li>[X] Fixed VIP subscription problem (MM)</li>
<li>Flighted rotating product ads (MM)</li>
<li>Fixed aggregated article list problem (MM)</li>
<li>Researched the new EU cookie directive (MM)</li>
<li>Updated sites to WordPress 3.1.1 (CC, MM, Amino)</li>
<li>Reorganized source code in version control (CC)</li>
<li>[-] Taxes (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>[X] Shared pictures more often</li>
<li>[X] Went to kids birthday party with Mathias</li>
<li>Rescheduled kids’ doctor’s appointments</li>
<li>Called my mom</li>
<li>Played Little Big Planet 1 with Birgit</li>
<li>Ate at Burger King with kids (a mistake not to repeat)</li>
<li>Drew a map of bus stops for Birgit</li>
<li>[-] Family bookkeeping</li>
</ul>
<p>Life</p>
<ul>
<li>[X] Continued moving own blogs to Drupal - didn’t have a lot of non-worktime though, so didn’t finish</li>
<li>[X] Some blogging</li>
<li>[X] Updated servers and CMS</li>
<li>Researched and ordered surveillance cam</li>
<li>Read a lot more RSS feeds and blog articles, thanks to increased travel time</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p>Work</p>
<ul>
<li>Taxes (CC)</li>
<li>Teach new developer more about Redpitt (MM)</li>
<li>Meeting with old acquaintance about possible project (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Family bookkeeping</li>
<li>Call my mom</li>
<li>Accompany kids on the way to their granny in Denmark</li>
</ul>
<p>Life</p>
<ul>
<li>Finish moving first personal blog to Drupal 7</li>
<li>Participate in a research study</li>
<li>Update servers and CMS</li>
</ul>
Colour Catcher review2011-04-07T09:23:26Zhttps://www.clausconrad.com/blog/colour-catcher-review/<p>I didn’t want to take a lot of risk for the first wash, so I mixed only red and blue colors of clothes that all had already been washed several times previously together with one “sheet” of Colour Catcher. The result was as usual, though the once white Colour Catcher had taken on a reddish note after the run, absorbing at least some of the clothes’ color.</p>
<p>My next run were towels, and this time I decided to mix the two most opposite colors, black and white towels together. I used one sheet of Colour Catcher with about 8 towels of different sizes and detergent for colored clothes. Mixing these kinds of colors, even with towels only, isn’t something I’d usually try, nor have I ever used color detergent for white garments before. The result seemed very acceptable to me, as the Colour Catcher had gone completely black during the wash. While the white towels still were very much so after the wash, it’s hard to say whether they had taken on a tiny bit of color from the black ones. Using Colour Catcher I feel secure enough to retry a similar experiment, but judging from the amount of color it had absorbed I’d probably use two sheets next time, just to be sure.</p>
<p>For the remaining washes in my “trial period” I always had enough similar colored garments available, so I had no reason to experiment any further, but I always used one sheet of Colour Catcher and each of these took on lots of color from the clothes, so it seems indeed to work as promised.</p>
<p>Some of the advantages of Colour Catcher that I see include:</p>
<ul>
<li>Environmentally friendly - one can more often wash with a full machine</li>
<li>Economical - clothes live longer by not being discolored early on</li>
<li>Decreased risk of washing a red sock in a bunch of white towels</li>
</ul>
<p>Would I buy Colour Catcher? I’m not completely sure, but I probably will. The only reason that complicates the decision is the fact that I can’t easily compare washing with or without Colour Catcher: I wouldn’t want to try the experiments without it because I would be too afraid of ruining our clothes.</p>
The workplace of the future2011-04-05T16:55:30Zhttps://www.clausconrad.com/blog/the-workplace-of-the-future/<p>While this is presumably a US based survey I guess the situation here in Scandinavia is comparable, and I believe this is a trend that will continue over the next years and decades. In my opinion the trend to work remotely, which became a possibility thanks to technology such as Skype and the Internet in general, goes hand in hand with two other trends in the industry: specialization and loose groups of people working together on a project basis rather than a company basis.</p>
<p>Let me give an example of what I mean by an increase in specialization. When I first studied software development at a business college in Denmark, we were taught Java initially and like many of my “classmates” I chose .NET as a secondary class (back then, this framework was the new kid on the block). Upon graduation I felt I had some rudimentary skills in these major frameworks but nothing really ready for production use. The first job I applied for was at a small but great software company that had plans to switch to .NET, but mostly still worked with older technologies (VB6 and Classic ASP). Two facts amaze me today: how broad the spectrum covered by my classes was, and that I got the job.</p>
<p>Comparing this to today’s software world, I believe the game has already changed tremendously in the 7 years since I graduated. Yesterday, I came across a job ad by a company looking for someone with experience in Pylons and PHP. Now, PHP is a major language of course, but Pylons is only one among many Python web frameworks. The same day, on some other blog, a 20 year-old web developer considered whether he should specialize on WordPress or Drupal development (two content management systems written in PHP). All this might show nothing except that me and my class mates weren’t very ambitious back then, of course, but to me stuff like this becomes a sign of a trend towards more specialization among developers. If I’m right, then these are certainly exciting times, but on the other hand the trend also worries me. While I’d like to drill down into and become an expert on certain technologies, I also enjoy having basic knowledge about a multitude of technologies and thus, many tools to choose from depending on the task at hand. If all you have is a hammer, everything becomes a nail, and this approach sounds futile to solving the many tasks at today’s agile startups. Except of course if…</p>
<p>…the practice of having all (development) jobs in a small company solved by (the same set of) employees also was on the decline, which I believe it is. I’ve never worked for an enterprise so I can’t compare to large workplaces at all, but at all the small companies I’ve worked for development job requirements were - at least to some extent - designed for the skills of the staff. One database exchanged for another because 1-2 people had experience using or administering it, workarounds for not-so-optimum programming languages because other projects already used them and so on This might sound logical, but I’m afraid that if companies continue to follow this pattern they’ll be outsmarted by companies hiring groups of specialists for each individual project, who’ll enjoy a faster time-to-market.</p>
<p>Enough predictions from me for today…</p>
Weekly review: Week ending March 25, 20112011-03-26T21:08:04Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-march-25-2011/<p>Work</p>
<ul>
<li>[X] Last preparations for new employee (order hardware etc.) (MM)</li>
<li>[X] Consolidated to-do lists in FogBugz (MM)</li>
<li>[X] Set up local development environment for CMS sources (MM)</li>
<li>[X] Moved two servers to new environment (MM)</li>
<li>[X] Declared EU taxes (CC)</li>
<li>[X] Invoiced customers (CC)</li>
<li>Licensed PHPStorm and BeyondCompare Pro (CC)</li>
<li>Fixed a Javascript bug due to IE9 RTM (MM)</li>
<li>Deployed DNSSEC for 17 domains (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>[X] Brought the kids to the train for the weekend with their dad</li>
</ul>
<p>Life</p>
<ul>
<li>[X] Backed up PS3</li>
<li>Backed up DVDs</li>
<li>Wrote a small motivational app that displays daily work hours statistics</li>
<li>Translated a web app for a personal site</li>
<li>Learned more about SEO</li>
<li>Moved my e-book library into the cloud</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p>Work</p>
<ul>
<li>Welcome new employee (MM)</li>
<li>Improve SEO (MM)</li>
<li>Improve VIP subscriptions (MM)</li>
<li>Get to know CMS source code better (MM)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Family finances</li>
<li>Go to the doctor with kid</li>
</ul>
<p>Life</p>
Why don't browsers ship with jQuery?2011-03-18T11:21:52Zhttps://www.clausconrad.com/blog/why-don-t-browsers-ship-with-jquery/<p>Years ago, browser vendors competed over JavaScript engine features, nowadays they compete over JavaScript engine performance. Thanks to cross-browser frameworks (with jQuery being the most prominent) features and compatibility are no longer an issue. Isn’t it time for browser vendors to compete on features such as pre-loading different JS framework versions and replacing remote loads of these with already cached versions?</p>
<p>In the meantime, I hope every web developer sticks to a CDN-hosted version of these libraries. The <a href="https://developers.google.com/speed/libraries?csw=1">Google Libraries API</a> is a well-known jQuery host by now, but Microsoft also hosts a couple of libraries for you at their <a href="https://docs.microsoft.com/en-us/aspnet/ajax/cdn/overview">ASP.NET CDN</a>. Beware though that using one of these CDN’s just for one or two requests might result in yet another DNS query upon loading your site. To me, the caching advantage is worth it.</p>
Is Linux Mint adware?2011-03-03T00:09:09Zhttps://www.clausconrad.com/blog/is-linux-mint-adware/<p>While I don’t use Linux on the desktop, I run a couple of servers on Ubuntu and other distributions. My interest in Linux on the desktop roots in friends and relatives sometimes asking me for advice on cheap/free operating systems for older boxes and laptops, which is why I try to keep a little informed on developments in this area as well.</p>
<p>Linux Mint presents itself as a more user-friendly variant of the well-known Ubuntu distribution of Linux. My first impression of the website was utter astonishment - I’ve never before seen so many paid ads on the website of any other open-source project.</p>
<p>The real shocker however came when I booted the latest version (Linux Mint 10) up in a virtual machine and tried surfing the web using Linux Mint’s included Firefox browser. Any and all searches done through the search field are directed to a Google Custom Search Engine, which makes the project money from clicks on ads.</p>
<p>Now, I am quite sure there is nothing illegal in this approach to funding the project, but I find this highly unethical for a popular open-source project. First of all, a Custom Search Engine allows them to filter out certain searches, bordering censorship. More important to me is the question “If somebody modifies one application to make money, what else did they change in the system?”.</p>
<p>Notwithstanding the arguable improvements for newbie Linux users in Linux Mint, to me this approach is piggy-bagging on the success and effort of the Ubuntu developers in order to raise money for unknown causes, so I will continue recommending official Ubuntu versions to friends and relatives looking for a free operating system.</p>
List of source code hosting services2011-02-28T20:04:48Zhttps://www.clausconrad.com/blog/list-of-source-code-hosting-services/<table>
<thead>
<tr>
<th>Name</th>
<th>Supported VCS</th>
<th>Other features</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://www.assembla.com/">Assembla</a></td>
<td>Subversion, Git, Perforce</td>
<td>Wiki, Issue tracking</td>
<td></td>
</tr>
<tr>
<td><a href="https://bitbucket.org/">Atlassian Bitbucket</a></td>
<td>Mercurial</td>
<td>Wiki, Issue tracking</td>
<td></td>
</tr>
<tr>
<td><a href="https://www.github.com/">Github</a></td>
<td>Git</td>
<td>Wiki, Issue tracking, Code review</td>
<td></td>
</tr>
<tr>
<td><a href="https://sourceforge.net/">SourceForge</a></td>
<td>Subversion, Git, Mercurial</td>
<td>Wiki, Issue tracking, Forums</td>
<td>Open-source only</td>
</tr>
</tbody>
</table>
Weekly review: Week ending February 25, 20112011-02-26T10:04:52Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-february-25-2011/<p>Work</p>
<ul>
<li>[X] Automate processing 2 new forms; auto-upgrade users membership status (MM)</li>
<li>[X] Declare EU taxes (CC)</li>
<li>[-] Fix design for expert blogs (MM)</li>
<li>[-] Declare delayed taxes (CC)</li>
<li>Updated list of active backup jobs for all servers (Amino)</li>
<li>Created a small mail sending script (MM)</li>
<li>Extracted lists of leads manually due to the CMS still failing (MM)</li>
<li>Attended job interview with a new developer (MM)</li>
<li>Wrote a background script to update link lists for user blogs (MM)</li>
<li>Design changes for expert blogs (MM)</li>
<li>Contacted Google support to get VAT number updated in time for apps renewal (CC)</li>
<li>Created a one-page Pyramid app to serve as a proxy to FogBugz’ XML API (CC, MM)</li>
<li>Migrated web and DB servers from Debian Lenny to Ubuntu 10.04 (CC)</li>
<li>Set up more monitoring for physical and cloud servers (CC, MM)</li>
<li>Set up backup for PostgreSQL server (CC)</li>
<li>Invoiced customers (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>[X] Help Birgit with MacBook Pro ticket</li>
<li>[-] Update/work with family bookkeeping</li>
<li>Planned summer vacation</li>
<li>Helped Birgit with DNS configuration, computer warranty and software installations</li>
</ul>
<p>Life</p>
<ul>
<li>[-] Migrate 1 personal blog to Drupal 7</li>
<li>Improved my knowledge of Python by reading source code and trying lots of stuff I read about</li>
<li>Got better at using Mercurial, even for small/personal projects</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p>Work</p>
<ul>
<li>Fix design for expert blogs (MM)</li>
<li>Declare delayed taxes (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Update/work with family bookkeeping</li>
<li>Company party at the casino</li>
</ul>
<p>Life</p>
<ul>
<li>Migrate 1 personal blog to Drupal 7</li>
</ul>
Weekly review: Week ending February 18, 20112011-02-19T17:06:07Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-february-18-2011/<p>Work</p>
<ul>
<li>[X] Assisted with server move (Amino)</li>
<li>[X] Evaluated offer for new servers and accepted a custom configuration (MM)</li>
<li>[X] Installed updates to all servers and CMS sites under own administration (CC)</li>
<li>[X] Extracted lots of lead data (MM)</li>
<li>Deployed an update to notification service with bugfix and new feature (MM)</li>
<li>General administration of backup jobs (Amino)</li>
<li>Upgraded sites to WordPress 3.0.5 (Amino, MM)</li>
<li>Researched several too early escalated error reports (MM)</li>
<li>Initiated installation of more RAM in web server (MM)</li>
<li>Fixed some small errors on website (MM)</li>
<li>Configured firewall for PostgreSQL server (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Helped Birgit with DNS administration</li>
<li>Ordered train tickets for kids</li>
<li>Finished building new bed for kid</li>
</ul>
<p>Life</p>
<ul>
<li>Received and paid office supplies</li>
<li>Migrated file collection from SFTP to Jungle Disk</li>
<li>Cleaned bathroom, threw out old drugs and hygiene items</li>
<li>Replaced avast! Home with Microsoft Security Essentials</li>
<li>Repaired door to children’s room</li>
<li>Bought new crickets for spider</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p>Work</p>
<ul>
<li>Automate processing 2 new forms; auto-upgrade users membership status (MM)</li>
<li>Fix design for expert blogs (MM)</li>
<li>Declare EU taxes (CC)</li>
<li>Declare delayed taxes (CC)</li>
</ul>
<p>Relationships</p>
<ul>
<li>Help Birgit with MacBook Pro ticket</li>
<li>Update/work with family bookkeeping</li>
</ul>
<p>Life</p>
<ul>
<li>Migrate 1 personal blog to Drupal 7</li>
</ul>
Microsoft online services2011-02-19T12:02:28Zhttps://www.clausconrad.com/blog/microsoft-online-services/<h2 id="document-centric-services" tabindex="-1">Document-centric services</h2>
<h3 id="office-live-workspace" tabindex="-1">Office Live Workspace</h3>
<p>Microsoft’s first try at online editing of documents, Office Live Workspace was free for all kinds of users. The service has been discontinued in January 2011 and was replaced with “Office Web Apps on SkyDrive”.</p>
<h3 id="office-web-apps-on-skydrive" tabindex="-1">Office Web Apps on SkyDrive</h3>
<p>Targeted towards home users and students, this free solution allows users to view and edit documents through most web browsers, share them and collaborate on Office documents with others.</p>
<p>Documents from SkyDrive can easily be opened in the full versions of Word, Excel and PowerPoint, if the user has them installed, but purchasing these applications is not required to use Office Web Apps on SkyDrive.</p>
<p>Go to <a href="https://www.office.com/">Office Web Apps on SkyDrive</a></p>
<h3 id="office-web-apps-on-premises" tabindex="-1">Office Web Apps on-premises</h3>
<p>Business users who purchase Office 2010 through volume licensing can run Office Web Apps for their users on own servers by installing SharePoint 2010.</p>
<p>Learn more about <a href="https://docs.microsoft.com/en-us/previous-versions/office/office-2010/ee855124(v=office.14)?redirectedfrom=MSDN">deploying Office Web Apps</a></p>
<h2 id="e-mail-centric-services" tabindex="-1">E-mail centric services</h2>
<h3 id="windows-live-hotmail" tabindex="-1">Windows Live Hotmail</h3>
<p>One of the world’s most popular e-mail services for personal use, Hotmail gives users a huge inbox accessible through most web browsers and the choice of an address under one of <a href="http://hotmail.com">hotmail.com</a> or several other domains.</p>
<p>Go to <a href="https://www.hotmail.com/">Windows Live Hotmail</a></p>
<h3 id="office-365" tabindex="-1">Office 365</h3>
<p>Currently in beta, Office 365 seems to be meant to replace the functionality currently offered through Office Live Small Business and Microsoft Online Services. It is going to offer hosted Exchange, SharePoint and Lync services together with licenses to run Office Professional Plus on customer workstations at different service levels priced between $2 and $27 per user and month.</p>
<p>Go to <a href="https://www.microsoft.com/en-us/microsoft-365?ms.url=office365com&rtc=1">Office 365</a></p>
Weekly review: Week ending February 11, 20112011-02-12T18:51:16Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-february-11-2011/<p><span style="text-decoration: underline">Work</span></p>
<ul>
<li>[X] Developed content for right side of templates (MM)</li>
<li>[X] Inserted new content, search function and changed order in right side of templates (MM)</li>
<li>[X] Evaluated offer for new servers (MM)</li>
<li>[X] Finalized specs and accepted offer for development of new newsletter type (MM)</li>
<li>[X] Began work on user data extraction script (MM)</li>
<li>[X] Finished migration to Google Apps (MM)</li>
<li>Troubleshooting of Pinq leads (MM)</li>
<li>Processed lots of error reports (MM)</li>
<li>Server reconfiguration and other work to troubleshoot performance problems (MM)</li>
<li>Extracted lots of lead data (MM)</li>
<li>Installed a Mercurial server (MM)</li>
<li>Set up a new web server for troubleshooting purposes (MM)</li>
<li>Installed updates to all servers and CMS sites under own administration (CC)</li>
<li>Bought a PyCharm license and started using it on small projects – converting from Komodo IDE (CC, MM)</li>
</ul>
<p><span style="text-decoration: underline">Relationships</span></p>
<ul>
<li>Continued trying to improve my social networking by double-sharing family pictures and other content on Flickr, Facebook, Diigo, Amplify and other sites</li>
</ul>
<p><span style="text-decoration: underline">Life</span></p>
<ul>
<li>Went to the doctor with Trine</li>
<li>Routine test of smoke detectors</li>
<li>Booked dentist appointments for all kids</li>
</ul>
Online mindmapping services compared2011-02-02T17:57:06Zhttps://www.clausconrad.com/blog/online-mindmapping-services-compared/<p>| Name | Price | Sharing | Real-time collaboration | Offline use | iOS | Android | API | Import/Export |
|-
| <a href="https://bubbl.us/">bubbl.us</a> | $0 to $6/month | Yes | No | No | No | No | No | -/JPG, PNG |
| <a href="https://www.mindmeister.com/">MindMeister</a> | $0 to $9/month | Yes | Yes | Yes | Yes | No | Yes | FreeMind, MindManager/GIF, JPG, PNG, PDF, FreeMind, MindManager |
| <a href="https://www.mindomo.com/">Mindomo</a> | $0 to $8/month | Yes | No | Yes | No | No | No | MMAP, FreeMind/GIF, JPG, PNG, PDF, MMAP, XLS, HTML, MPX |
| <a href="https://mind42.com/">Mind42</a> | Free | Yes | Yes | No | No | No | No | FreeMind, MindManager/PDF, JPG, PNG, FreeMind, MindManager |
| <a href="https://www.mapul.com/">MAPMYself</a> | $0 to $4.6/month | Yes | No | Yes | No | No | No | -/iMindMap, JPG, DOCX |</p>
Debugging Pyramid with PyCharm2011-01-30T18:45:10Zhttps://www.clausconrad.com/blog/debugging-pyramid-with-pycharm/<p>PyCharm is made by JetBrains, the developers of IntelliJ IDEA and ReSharper - these guys have proven their ability to create full-featured, developer-friendly IDEs in the past and its obvious they used their knowledge to create PyCharm, too.</p>
<p>While PyCharm supports Django and GAE out of the box, it can certainly be used for other frameworks. Sean has written some excellent <a href="https://byatool.com/python/how-to-debug-pylons-with-pycharm/">instructions to debug Pylons with PyCharm</a> and the steps required to debug Pyramid are exactly the same:</p>
<ol>
<li>Click “Run” > “Edit Configurations”</li>
<li>Press “Insert” and choose “Python”</li>
<li>Give the configuration a name, e. g. <em>Pyramid</em></li>
<li>Insert the script to <em>paster</em>:<br />
<code>C:\Python27\Scripts\paster-script.py</code></li>
<li>Insert the script parameters WITHOUT <em>–reload</em>:<br />
<code>serve C:\path\to\development.ini</code></li>
<li>Choose the right Python interpreter from the dropdown</li>
</ol>
A workaround for Jungle Disk restore problems2011-01-21T09:51:50Zhttps://www.clausconrad.com/blog/a-workaround-for-jungle-disk-restore-problems/<pre><code class="language-text">Could not download and open the backup vault database
Error Details (Jungle Disk Desktop 3.12 Win64)
------------------------
xOverwriteFailed - Failed to rename backup database to final name (file in use?): C:\ProgramData\JungleDisk\cache\cfjd2-us-mmdb\XXXXXXXXXXXXXXXXXXXX-backup.db
Exception Code: xOverwriteFailed (144)
Time: 20-01-2011 21:09:03 (GMT+1)
Detailed Message: Failed to rename backup database to final name (file in use?): C:\ProgramData\JungleDisk\cache\cfjd2-us-mmdb\XXXXXXXXXXXXXXXXXXXX-backup.db
Error Location: BlockBackupManager.cpp:1062 BlockBackupManager::ExecuteDownloadAndOpenDatabase
via BlockBackupManager.cpp:1098 BlockBackupManager::ExecuteDownloadAndOpenDatabase
</code></pre>
<p>To solve this problem I had to follow these steps:</p>
<ol>
<li>Stop the Jungle Disk service on the restore machine</li>
<li>Rename/delete the “cache” folder from C:\ProgramData\JungleDisk</li>
<li>Start the Jungle Disk service</li>
<li>Click “Restore files” in the vault’s menu in Jungle Disk monitor</li>
<li>The vault database is downloaded - twice. During the second download, click “Cancel”.</li>
<li>Click “Restore files” again.</li>
</ol>
Weekly review: Week ending December 31, 20102011-01-01T23:35:00Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-december-31-2010/<p><strong>Plans from last week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>[X] Weekly server maintenance/controlled update (CC)</li>
<li>[X] Declare VAT (CC)</li>
<li>[X] Invoice customers (CC)</li>
<li>[X] Develop a replacement notifications service (MM)</li>
<li>[-] Connect CSE with AdSense (MM)</li>
<li>[-] Order banners (MM)</li>
<li>[-] Declare company taxes (CC)</li>
<li>[-] Communicate with Redpitt (MM)</li>
<li>[-] Fix error message on barnloeshed.htm (MM)</li>
<li>[-] Change news rotation feature (MM)</li>
<li>[-] Fix share links (MM)</li>
<li>Partner campaign lists (MM)</li>
<li>Bought some WP themes (CC)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>[-] Verify children’s bank accounts have been created</li>
<li>[-] Finish calculation of family accounting since Aug 12, 2010</li>
<li>Met up with some old friends in Copenhagen</li>
<li>Booked bowling</li>
<li>Helped a friend cancel his mobile broadband plan</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>[X] Relax</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Weekly server maintenance/controlled update (CC)</li>
<li>Connect CSE with AdSense (MM)</li>
<li>Order banners (MM)</li>
<li>Declare company taxes (CC)</li>
<li>Communicate with Redpitt (MM)</li>
<li>Fix error message on barnloeshed.htm (MM)</li>
<li>Change news rotation feature (MM)</li>
<li>Fix share links (MM)</li>
<li>Look into performance problems (MM)</li>
<li>Change website theme (CC)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>Finish calculation of family accounting since Aug 12, 2010</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Read more about Python programming</li>
</ul>
Weekly review: Week ending Dec 19, 20102010-12-19T20:49:45Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-dec-19-2010/<p><u>Work</u></p>
<ul>
<li><del>Declared personal taxes (CC)</del></li>
<li><del>Weekly server maintenance/controlled update (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Found a date to fetch Birgit’s and the kids’ remaning stuff from Vejen</del></li>
<li><del>Went to the school nurse with Mads</del></li>
<li><del>Sent christmas cards to some relatives</del></li>
<li><del>Called municipality to press for updates about Trine’s kindergarten queue status</del></li>
<li><del>Went to the orthopedic hospital with Mathias</del></li>
<li><del>Shopped christmas presents for/with the Danish kids</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Contribute to the kindergarten parents’ christmas present</del></li>
<li><del>Drove to Denmark to fetch kids’ train trickets</del></li>
<li><del>Went bowling with the family</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><del>Wash floor</del></li>
<li><del>Ordered insurance for the kids online, chose Skandia who are a bit more expensive, but they were helpful - Länsforsäkringar apparently didn’t want us as customers, their customer service was nonexistent</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Brought used clothes to the second-hand container</del></li>
<li><del>Bought Tassimo T40 for the kitchen</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Connect CSE with AdSense (MM)</li>
<li>Order banners (MM)</li>
<li>Weekly server maintenance/controlled update (CC)</li>
<li>Declare VAT (CC)</li>
<li>Declare company taxes (CC)</li>
<li>Invoice customers (CC)</li>
<li>Communicate with Redpitt (MM)</li>
<li>Develop a replacement notifications service (MM)</li>
<li>Fix error message on barnloeshed.htm (MM)</li>
<li>Change news rotation feature (MM)</li>
<li>Fix share links (MM)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>Verify children’s bank accounts have been created</li>
<li>Finish calculation of family accounting since Aug 12, 2010</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Relax</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from last week</strong></li>
<li>All other items are new</li>
</ul>
Weekly review: Week ending November 14, 20102010-11-14T22:48:46Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-november-14-2010/<p><u>Work</u></p>
<ul>
<li><del>Update own servers and websites (CC)</del></li>
<li><del>Implement new design (MM)</del></li>
<li><del>Project management with Redpitt and 1902 (MM)</del></li>
<li><del>News articles slideshow function using WP (MM)</del></li>
<li><del>Declared VAT and EU sales (CC)</del></li>
<li><del>Sent daily work report (MM)</del></li>
<li><strong>Declare other taxes (CC)</strong></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Fix Emediate pop-up through DFP (MM)</del></li>
<li><del>Automatic caching of dynamic content pages (MM)</del></li>
</ul>
<p><u>Relationships</u></p>
<p>Also:</p>
<ul>
<li><del>Mail correspondance with my Dad</del></li>
<li><del>Baked a home-made pizza with the kids</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><strong>Go to the gym daily</strong></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Checked home servers backup plan</del></li>
<li><del>Deleted old backups from AWS S3</del></li>
<li><strong>Fix washing machine</strong></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li><strong>Declare other taxes (CC)</strong></li>
<li>Implement new design (MM)</li>
<li>Order further mockups for subpages (MM)</li>
<li>Collect ideas for redesign of this site (CC)</li>
</ul>
<p><u>Relationships</u></p>
<p><u>Life</u></p>
<ul>
<li><strong>Go to the gym daily</strong></li>
<li><strong>Fix washing machine</strong></li>
<li>Deep-clean apartment</li>
<li>Order new nutritional supplements</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from last week</strong></li>
<li>All other items are new</li>
</ul>
CommunityServer 2008.5 Blogs API reference2010-10-18T16:39:10Zhttps://www.clausconrad.com/blog/communityserver-2008-5-blogs-api-reference/<h3 id="blogs" tabindex="-1">Blogs</h3>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F" tabindex="-1"><strong>GET /api/blogs.ashx/blogs/</strong></h4>
<p>Returns a paged list of all blogs visible to the current user.</p>
<h4 id="response" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<bloglist>
<blog>...</blog>
...
</bloglist>
</code></pre>
<h4 id="parameters" tabindex="-1">Parameters</h4>
<p>| PageSize | Integer | Number of blogs per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D" tabindex="-1"><strong>GET /api/blogs.ashx/blogs/</strong>{blogId}</h4>
<p>Returns data about a specific blog.</p>
<h4 id="response-1" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<blog>...</blog>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogkey%7D" tabindex="-1"><strong>GET /api/blogs.ashx/blogs/</strong>{blogKey}</h4>
<p>Returns data about a specific blog.</p>
<h4 id="response-2" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<blog>...</blog>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogquery%7D" tabindex="-1"><strong>GET /api/blogs.ashx/blogs/</strong>{blogQuery}</h4>
<p>Returns a paged list of blogs matching the query parameter(s) visible to the current user.</p>
<h4 id="response-3" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<bloglist>
<blog>...</blog>
...
</bloglist>
</code></pre>
<h4 id="parameters-1" tabindex="-1">Parameters</h4>
<p>| Name | String | Name or part of the name of the blog. Wildcard character is “%”. | Optional |
| IsActive | Boolean | Whether the blog is active | Optional |
| AccessLevel | Enum | “View”, “Post” | Optional |
| Ids | Integer[] | Comma-separated list of blog IDs. | Optional |
| Keys | String[] | Comma-separated list of blog keys. | Optional |
| GroupIDs | Integer[] | Comma-separated list of blog group IDs | Optional |
| SortBy | String | Can be set to “Name”, “LastPost”, “Post”, “SortOrder” or “Thread” | Optional |
| Order | String | The sort order for the “SortBy” parameter. Can be set to “Ascending” or “Descending”. | Optional |
| PageSize | Integer | Number of blogs per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fmembers" tabindex="-1"><strong>GET /api/blogs.ashx/blogs/</strong>{blogId}/members</h4>
<p>Returns a list of members of the specified blog.</p>
<h4 id="response-4" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<membershiplist>
<member>...</member>
...
</membershiplist>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fmembers%2F%7Buserid%7D" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/members/{userId}</h4>
<p>Returns the specified member of the specified blog.</p>
<h4 id="response-5" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<member>...</member>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts</h4>
<p>Returns a paged list of posts in the specified blog.</p>
<h4 id="response-6" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<blogpostlist>
<blogpost>...</blogpost>
...
</blogpostlist>
</code></pre>
<h4 id="parameters-2" tabindex="-1">Parameters</h4>
<p>| PageSize | Integer | Number of posts per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}</h4>
<p>Returns the specified post in the specified blog.</p>
<h4 id="response-7" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<blogpost>...</blogpost>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D%2Fcomments" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}/comments</h4>
<p>Returns a paged list of comments for the specified post in the specified blog.</p>
<h4 id="response-8" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<commentlist>
<comment>...</comment>
...
</commentlist>
</code></pre>
<h4 id="parameters-3" tabindex="-1">Parameters</h4>
<p>| PageSize | Integer | Number of comments per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D%2Fcomments%2F%7Bblogpostcommentid%7D" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}/comments/{blogPostCommentId}</h4>
<p>Returns the specified comment for the specified post in the specified blog.</p>
<h4 id="response-9" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<comment>...</comment>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D%2Ftrackbacks" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}/trackbacks</h4>
<p>Returns a paged list of trackbacks for the specified post in the specified blog.</p>
<h4 id="response-10" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<trackbacklist>
<trackback>...</trackback>
...
</trackbacklist>
</code></pre>
<h4 id="parameters-4" tabindex="-1">Parameters</h4>
<p>| PageSize | Integer | Number of trackbacks per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D%2Ftrackbacks%2F%7Btrackbackid%7D" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}/trackbacks/{trackbackId}</h4>
<p>Returns the specified trackback for the specified post in the specified blog.</p>
<h4 id="response-11" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<trackback>...</trackback>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D%2Fratings" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}/ratings</h4>
<p>Returns a list of ratings for the specified post in the specified blog.</p>
<h4 id="response-12" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<ratinglist sum="X" average="Y">
<rating>...</rating>
...
</ratinglist>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fblogs%2F%7Bblogid%7D%2Fposts%2F%7Bblogpostid%7D%2Fratings%2F%7Busername%7D" tabindex="-1">GET /api/blogs.ashx/blogs/{blogId}/posts/{blogPostId}/ratings/{username}</h4>
<p>Returns rating by user with {username} for the specified post in the specified blog.</p>
<p>If the user doesn’t exist or didn’t rate the post, the whole list of ratings for the specified post is returned!</p>
<h4 id="response-13" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<int>
X
</int>
</code></pre>
<h3 id="blog-posts" tabindex="-1">Blog Posts</h3>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fposts%2F%7Bblogpostid%7D" tabindex="-1">GET /api/blogs.ashx/posts/{blogPostId}</h4>
<p>Returns the specified post.</p>
<h4 id="response-14" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<blogpost>...</blogpost>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fposts%2F%7Bblogpostquery%7D" tabindex="-1"><strong>GET /api/blogs.ashx/posts/{blogPostQuery}</strong></h4>
<p>Returns a paged list of posts matching the query parameter(s) visible to the current user.</p>
<h4 id="response-15" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<blogpostlist>
<blogpost>...</blogpost>
...
</blogpostlist>
</code></pre>
<h4 id="parameters-5" tabindex="-1">Parameters</h4>
<p>| IsActive | Boolean | Whether the post is active | Optional |
| BlogIds | Integer[] | Comma-separated list of blog IDs. | Optional |
| Keywords | String[] | Comma-separated list of keywords. All keywords must be matched. | Optional |
| SortBy | String | Can be set to “MostComments”, “MostRecent” or “MostViewed” | Optional |
| Order | String | The sort order for the “SortBy” parameter. Can be set to “Ascending” or “Descending”. | Optional |
| PageSize | Integer | Number of posts per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fposts%2F%7Bblogpostid%7D%2Fcomments" tabindex="-1">GET /api/blogs.ashx/posts/{blogPostId}/comments</h4>
<p>Returns a paged list of comments for the specified post.</p>
<h4 id="response-16" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<commentlist>
<comment>...</comment>
...
</commentlist>
</code></pre>
<h4 id="parameters-6" tabindex="-1">Parameters</h4>
<p>| PageSize | Integer | Number of comments per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fposts%2F%7Bblogpostid%7D%2Ftrackbacks" tabindex="-1">GET /api/blogs.ashx/posts/{blogPostId}/trackbacks</h4>
<p>Returns a paged list of trackbacks for the specified post.</p>
<h4 id="response-17" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<trackbacklist>
<trackback>...</trackback>
...
</trackbacklist>
</code></pre>
<h4 id="parameters-7" tabindex="-1">Parameters</h4>
<p>| PageSize | Integer | Number of trackbacks per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h3 id="blog-comments" tabindex="-1">Blog Comments</h3>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fcomments%2F%7Bblogpostcommentid%7D" tabindex="-1">GET /api/blogs.ashx/comments/{blogPostCommentId}</h4>
<p>Returns the specified comment.</p>
<h4 id="response-18" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<comment>...</comment>
</code></pre>
<h4 id="" tabindex="-1"></h4>
<p>PUT /api/blogs.ashx/comments/</p>
<p>Creates the sent comment.</p>
<h4 id="request" tabindex="-1">Request</h4>
<pre><code><comment>...</comment>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Fcomments%2F%7Bblogpostcommentquery%7D" tabindex="-1"><strong>GET /api/blogs.ashx/comments/{blogPostCommentQuery}</strong></h4>
<p>Returns a paged list of comments matching the query parameter(s) visible to the current user.</p>
<h4 id="response-19" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<commentlist>
<comment>...</comment>
...
</commentlist>
</code></pre>
<h4 id="parameters-8" tabindex="-1">Parameters</h4>
<p>| IsActive | Boolean | Whether the comment is active | Optional |
| PostId | Integer | ID of a blog post. If specified, only comments for that post are shown. | Optional |
| Keywords | String[] | Comma-separated list of keywords. All keywords must be matched. | Optional |
| PageSize | Integer | Number of comments per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h3 id="blog-trackbacks" tabindex="-1">Blog Trackbacks</h3>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Ftrackbacks%2F%7Btrackbackid%7D" tabindex="-1">GET /api/blogs.ashx/trackbacks/{trackbackId}</h4>
<p>Returns the specified trackback.</p>
<h4 id="response-20" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<trackback>...</trackback>
</code></pre>
<h4 id="get-%2Fapi%2Fblogs.ashx%2Ftrackbacks%2F%7Btrackbackquery%7D" tabindex="-1"><strong>GET /api/blogs.ashx/trackbacks/{trackbackQuery}</strong></h4>
<p>Returns a paged list of trackbacks matching the query parameter(s) visible to the current user.</p>
<h4 id="response-21" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<trackbacklist>
<trackback>...</trackback>
...
</trackbacklist>
</code></pre>
<h4 id="parameters-9" tabindex="-1">Parameters</h4>
<p>| PostId | Integer | ID of a blog post. If specified, only trackbacks for that post are shown. | Optional |
| Keywords | String[] | Comma-separated list of keywords. All keywords must be matched. | Optional |
| PageSize | Integer | Number of trackbacks per page | Optional |
| PageIndex | Integer | Page number | Optional |</p>
<h3 id="blog-groups" tabindex="-1">Blog Groups</h3>
<p><strong>GET /api/blogs.ashx/bloggroups/</strong></p>
<p>Returns a list of all blog groups visible to the current user.</p>
<h4 id="response-22" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<bloggrouplist>
<bloggroup>...</bloggroup>
...
</bloggrouplist>
</code></pre>
<p><strong>GET /api/blogs.ashx/bloggroups/{blogGroupId}</strong></p>
<p>Returns data about the specified blog group.</p>
<h4 id="response-23" tabindex="-1">Response</h4>
<pre><code>Status: 200 OK
<bloggroup>...</bloggroup>
</code></pre>
Weekly review: Week ending July 25, 20102010-07-29T10:43:39Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-july-25-2010/<p><u>Work</u></p>
<ul>
<li><del>Renew Microsoft subscription (CC)</del></li>
<li><em>Educational meeting with Redpitt (MM)</em></li>
<li><strong>Improve SEO (Amino)</strong></li>
<li><strong>Declare taxes (CC)</strong></li>
<li><strong>Improve sign-up and partner feature (MM)</strong></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Brought notebook to repair shop (MM)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Meet B in Copenhagen</del></li>
<li><del>Group meetup in Finland</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><del>Ride bicycle approx. 65 miles</del></li>
<li><del>Write a Wikipedia article</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Wrote a blog article</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li><strong>Improve SEO (Amino)</strong></li>
<li><strong>Declare taxes (CC)</strong></li>
<li><strong>Improve sign-up and partner feature (MM)</strong></li>
<li>Book meeting with Redpitt (MM)</li>
<li>Send invitational mails (MM)</li>
<li>Prepare offer for KP project (CC)</li>
<li>Continue work on VC project (CC)</li>
<li>First phase of search engine implementation (MM)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>Post a review of the meetup</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Ride bicycle approx. 65 miles</li>
<li>Replace balcony flowers</li>
<li>Review long-term goals</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from last week</strong></li>
<li>All other items are new</li>
</ul>
Weekly review: Week ending July 18, 20102010-07-19T14:39:29Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-july-18-2010/<p><u>Work</u></p>
<ul>
<li><del>Learn about Redpitt CMS (MM)</del></li>
<li><del>Small changes to forums (Amino)</del></li>
<li><strong>Improve sign-up and partner feature (MM)</strong></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Meeting about sign-up improvements (MM)</del></li>
<li><del>Troubleshot dead notebook (MM)</del></li>
<li><del>Discontinued shared office space lease (CC)</del></li>
<li><del>Implemented share buttons on some blogs (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Change late summer holiday ticket</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Showed B & M around Malmö</del></li>
<li><del>Booked hotel room near the airport for next week</del></li>
<li><del>Mailed dad for birthday</del></li>
</ul>
<p><u>Life</u></p>
<p>Also:</p>
<ul>
<li><del>Upgraded <a href="http://hyggebajer.dk">hyggebajer.dk</a> to WP 3.0 and Thesis 1.8 b1</del></li>
<li><del>Canceled membership at apartment rental association</del></li>
<li><del>Rode bicycle approx. 62 miles</del></li>
<li><del>Bought/ordered fans, t-shirts, contact lenses, office supplies and supplements</del></li>
<li><del>Rearranged kitchen devices for easier access/cleaning</del></li>
<li><del>Suggested improvement possibilities to cab companies and gym</del></li>
<li><del>Overall improvements to my health/living routines and discipline</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li><strong>Improve sign-up and partner feature (MM)</strong></li>
<li>Improve SEO (Amino)</li>
<li>Educational meeting with Redpitt (MM)</li>
<li>Declare taxes (CC)</li>
<li>Renew Microsoft subscription (CC)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>Meet B in Copenhagen</li>
<li>Group meetup in Finland</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Ride bicycle approx. 65 miles</li>
<li>Write a Wikipedia article</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from last week</strong></li>
<li>All other items are new</li>
</ul>
Weekly review: Week ending July 11, 20102010-07-13T15:35:49Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-july-11-2010/<p><u>Work</u></p>
<ul>
<li><del>Finished “Ignore user” function (Amino)</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Helped with a few small tasks (Amino)</del></li>
<li><del>Cleaned my inboxes of old mails (Amino, CC)</del></li>
<li><del>Helped Nico with a little CSS (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Show mom & sister around Malmö, Lund and Ystad</del></li>
</ul>
<p><u>Life</u></p>
<p>Also:</p>
<ul>
<li><del>Planted Tagetes on balcony</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Improve sign-up and partner feature (MM)</li>
<li>Learn about Redpitt CMS (MM)</li>
<li>Small changes to forums (Amino)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>Change late summer holiday ticket</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from last week</strong></li>
<li>All other items are new</li>
</ul>
Migrating a bunch of WordPress blogs to a single WordPress 3.0 multi-site installation2010-06-12T23:22:38Zhttps://www.clausconrad.com/blog/migrating-a-bunch-of-wordpress-blogs-to-a-single-wordpress-3-0-multi-site-installation/<h2 id="general-setup%3A" tabindex="-1">General setup:</h2>
<ol>
<li><span style="font-family: Helvetica, Verdana, sans-serif;">Set up WordPress as usual</span></li>
<li><span style="font-family: Helvetica, Verdana, sans-serif;">Follow</span> <a href="https://wptheming.com/2010/03/wordpress-3-0-enable-network/">https://wptheming.com/2010/03/wordpress-3-0-enable-network/</a> to enable multi-site; use sub-directory config</li>
<li>Change wp-config.php and .htaccess as described in the admin</li>
<li>Follow <a href="http://ottopress.com/2010/wordpress-3-0-multisite-domain-mapping-tutorial/">http://ottopress.com/2010/wordpress-3-0-multisite-domain-mapping-tutorial/</a> to enable domain mapping</li>
</ol>
<h2 id="for-each-site%3A" tabindex="-1">For each site:</h2>
<ol>
<li>Log in to the control panel</li>
<li>Upgrade site to 3.0 by copying files over and reloading the control panel</li>
<li>Add the site on the WPMU installation</li>
<li>Map the domains</li>
<li>Add domain to hosts file</li>
<li>Export database to a file</li>
<li>Edit the file, remove wp_options, wp_usermeta and wp_users tables from dump</li>
<li>Rename prefixes from wp_ to wp_X_ where X is the blog id</li>
<li>Import SQL into new database</li>
<li>UPDATE wp_{ID}_posts SET post_author = 1</li>
<li>Switch theme</li>
<li>Move uploads and change post image path</li>
<li>Reenable plugins</li>
<li>Reenable widgets</li>
<li>Restore options</li>
<li>Check no broken Media</li>
</ol>
<h2 id="especially-in-case-of-thesis-1.7%3A" tabindex="-1">Especially in case of Thesis 1.7:</h2>
<p>For Thesis, also see <a href="/blog/thesis-customizations-i-like/">how to fix thumbs and post images</a>.</p>
<p><a href="https://kristarella.blog/2009/09/using-thesis-with-wpmu/">https://kristarella.blog/2009/09/using-thesis-with-wpmu/</a></p>
<ol>
<li>Restore Thesis options</li>
<li>Copy rotator images (if used)</li>
<li>Copy custom.css</li>
<li>Restore OpenHook</li>
<li>chmod 666 custom/blog-name/custom.css</li>
<li>chmod 775 custom/blog-name/cache</li>
</ol>
Lease .NET development tools2010-06-02T13:29:50Zhttps://www.clausconrad.com/blog/lease-net-development-tools/<p>Now the software giant introduced a similar discount for self-employed developers, featuring some of the same software that makes up the regular MAPS subscription as well as valuable MSDN subscriptions with Visual Studio and other pricey development tools. The new program called “Action Pack Development and Design” is available immediately for web development and design companies through <a href="https://partner.microsoft.com/global/program/40132997">https://partner.microsoft.com/global/program/40132997</a>.</p>
Why I avoid sugar2010-05-30T01:53:25Zhttps://www.clausconrad.com/blog/why-i-avoid-sugar/<ol>
<li>
<p>It’s a sure-fire way to get acne (pimples) for me. I am about 90% likely to have a lot less clean skin for a couple of days the day after drinking a 16 oz. bottle of coke, for example. I’m not happy with my body to begin with and don’t see any reason to make it worse.</p>
</li>
<li>
<p>It affects my immune system as much as skiing nude. Seriously, I’m not guaranteed to get a cold or individual cold symptoms after eating a piece of chocolate, but I’m much more likely to after going on a sugar binge.</p>
</li>
</ol>
<p>Now, to debunk a few common reactions I get regarding my choice:</p>
<ol>
<li>
<p>I am not a closet diabetic. That is the most common assumption I hear - if you are wary of consuming lots of sugar you must be diabetic. As far as I know I’m not and I don’t have reason to believe I am.</p>
</li>
<li>
<p>I happen to like sugar, I mean come on, who doesn’t like sweet foods?</p>
</li>
<li>
<p>I have experienced both effects hundreds if not thousands of times, so yes I’m pretty sure I don’t imagine it. For example, once in a while my craving for sugary foods wins and when that happens I might eat 5 oz. of chocolate or 5 bars on one occasion. When I do, I am more likely than not to end up with cold symptoms after 36 to 48 hours. Also, eating sugar during a cold usually prolongs it for me.</p>
</li>
<li>
<p>I’m not fanatic about this. Once in a while I do drink or eat sugary foods because I like them or for social reasons. Not every day but maybe like once a week or so.</p>
</li>
<li>
<p>I’m not trying to proselytize. My body is not yours, sugar likely doesn’t have these effects on you. If it doesn’t, good for you, go ahead and have that cake. Whether I’m around or not, I probably don’t care what you consume anyway. All I’m asking is that you respect my choice and don’t try to convince me that MY body needs sugar. Thanks for reading.</p>
</li>
</ol>
Thesis customizations I like2010-05-17T21:08:29Zhttps://www.clausconrad.com/blog/thesis-customizations-i-like/<h2 id="making-post-images-work-with-my-multi-site-installation" tabindex="-1">Making post images work with my multi-site installation</h2>
<p><em>/wp-content/themes/thesis_17/lib/functions/post_images.php</em>:</p>
<pre><code class="language-php">// BEGIN Claus 20100609 Multi-site
// if (@getimagesize($image_path)) {
// END Claus 20100609 Multi-site
$image['class'] = thesis_get_image_classes($post_image);
$image['attributes'] = thesis_image_attributes($post_image);
if ($post_image['alt'] != '')
$image['alt'] = $post_image['alt'];
elseif ($type == 'thumb')
$image['alt'] = 'Thumbnail image for ' . get_the_title();
else
$image['alt'] = 'Post image for ' . get_the_title();
if (is_single() || is_page()) {
$open_link = '';
$close_link = '';
}
else {
$open_link = '[';
$close_link = '](' . get_permalink() . ' "Permanent link to ' . get_the_title() . '")';
}
$post_image['output'] = $open_link . '' . $close_link . "\n";
// BEGIN Claus 20100609 Multi-site
// }
// END Claus 20100609 Multi-site
</code></pre>
<p><em>/wp-content/themes/thesis_17/lib/scripts/thumb.php</em>:</p>
<pre><code class="language-php">// BEGIN Claus 20100610 Multi-site
function cleanSource($src) {
// remove http/ https/ ftp
$src = preg_replace("/^((ht|f)tp(s|):\/\/)/i", "", $src);
// remove domain name from the source url
$host = $_SERVER["HTTP_HOST"];
$src = str_replace($host, "", $src);
$host = str_replace("www.", "", $host);
$src = str_replace($host, "", $src);`
// don't allow users the ability to use '../'
// in order to gain access to files below document root
$src = preg_replace("/\.\.+\//", "", $src);
// remove slash from start of string
if (strpos($src, "/") == 0)
$src = substr($src, -(strlen($src) - 1));
// remove "files/" from start of string
if (strpos($src, "files/") == 0)
$src = substr($src, -(strlen($src) - 6));
if( !is_multisite() )
die( 'Multisite support not enabled' );
ms_file_constants();
error_reporting( 0 );
if ( $current_blog->archived == '1' || $current_blog->spam == '1' || $current_blog->deleted == '1' ) {
// status_header( 404 );
die( '404 — File not found.' );
}
$src = BLOGUPLOADDIR . str_replace( '..', '', $src);
return $src;
}
// END Claus 20100610 Multi-site
</code></pre>
Drop caps in Thesis2010-05-17T20:36:14Zhttps://www.clausconrad.com/blog/drop-caps-in-thesis/<p>Apparently, Thesis has a built-in CSS class called “drop_cap” that can be manually added to posts. Adding this class to the first letter of posts manually isn’t a viable solution, Miguel writes, and I couldn’t agree more - it’s prone to be forgotten as well as ugly, because it violates the rule of separation of content and layout.</p>
<p>Miguel’s suggested solution has the advantage of requiring only a single change and can even be done through the web (assuming one uses the fabulous Thesis theme and OpenHook plugin). I don’t like the fact that it increases bandwidth on each page though. This could be remedied by including an external CSS file instead of inline CSS in Miguel’s code, but doing so would increase frontpage loading time and - unless properly cached - probably use up even more bandwidth on subsequent page loads.</p>
<p>What I would suggest instead is to add a CSS class such as “single” to the element in the hook code (see Miguel’s post for that) and then target these pages from the regular <em>custom.css</em> file, like this:</p>
<p><code>body.single div.entry-content > p:first-child:first-letter { /* ... */ }</code></p>
<p>Unfortunately I don’t know how to add a class to the body element programmatically in WordPress, I just assume it is possible judging from my knowledge of other CMS. Thus I came up with this alternate CSS-only solution instead, which works for me:</p>
<p><code>.custom .post:not(.teaser) .entry-content > p:first-child:first-letter{font-size:3.3em;line-height:.76em;padding:.05em .12em 0 0;color:#ccc;float:left}</code></p>
<p>While this snippet has the advantage of not requiring any PHP, it has some other shortcomings one needs to be aware of. Unlike Miguel’s solution it targets all posts that aren’t teasers, whether these are on single post pages or not. Second, it uses the CSS3 <em>:not</em> selector, which isn’t supported in Internet Explorer 8, but works in the current versions of the other 4 major browsers (Firefox, Safari, Chrome and Opera). That’s okay for my purposes, there’s no rush (to support IE users), but your mileage may vary.</p>
A user-friendly and fast Linux for netbooks?2010-05-17T16:15:46Zhttps://www.clausconrad.com/blog/a-user-friendly-and-fast-linux-for-netbooks/<p>For the last year or so I had given up on using my Asus Eee 900 for anything more than the occasional recipe surfing in the kitchen, it was simply too slow to open tabs or do any normal computer work. The original Linux wasn’t too slow, but nothing near fabulous either. I tried Ubuntu Netbook Remix, which felt even more unresponsive to me. Some months ago I switched to Windows 7 just to get disappointed once more.</p>
<p>Apart from the slow performance, all of these operating systems suffered from stability problems; for example, Windows 7 would usually come up with a black screen after waking up from suspend mode. Thanks to Jolicloud, this problem is gone and my Eee feels actually usable for the first time. Installation was child’s play and everything, including sound, wifi, stand-by mode and the webcam worked out of the box.</p>
<p>But I think what surprises me most is not the ease of use of Jolicloud, but that it changed my view on Linux in general - I had this connotation that Linux was an OS that could only be either stable, user-friendly or powerful, not all of them at the same time. Unlike most other distributions (versions of Linux) their website is quite sexy, probably inspired from Apple - in a good way. Thanks to the developers for combining the speed of Windows XP with the usability of Ubuntu Netbook Remix!</p>
Weekly review: Week ending May 02, 20102010-05-03T09:27:00Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-may-02-2010/<p><a id="last-week"></a><strong>Plans from last week:</strong></p>
<p><u>Work</u></p>
<p>Also:</p>
<ul>
<li><del>Helped with a few small tasks (Amino)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Look at exotic animals</del></li>
<li><del>Watch movies</del></li>
<li><del>Relax</del></li>
<li><strong>Walk at beach</strong></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><del>Small treatment at GP</del></li>
<li><del>Order cleaning assistance</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Bought some polo shirts</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Implement new community features (Amino)</li>
<li>Answer delayed mails (Amino)</li>
<li>Evaluate SEO measures for beer site (CC)</li>
<li>Answer delayed mails (CC)</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><strong>Walk at beach</strong></li>
<li>Relax</li>
<li>Watch “Red Dragon”</li>
<li>Buy ticket to go visit mom for her birthday</li>
<li>Meet sister in Helsingborg</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Buy fan</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from last week</strong></li>
<li>All other items are new</li>
</ul>
Meta description do's and don'ts2010-04-02T16:26:49Zhttps://www.clausconrad.com/blog/meta-description-do-s-and-don-ts/<h3 id="do%3A" tabindex="-1">Do:</h3>
<ul>
<li>Include your keywords.</li>
<li>Write compelling, informative and concise.</li>
<li>Describe your content honestly.</li>
<li>If there are different sections in the description, identify and separate them clearly.</li>
</ul>
<h3 id="don%E2%80%99t%3A" tabindex="-1">Don’t:</h3>
<ul>
<li>Reuse the same “boilerplate” description on several pages.</li>
<li>Duplicate information from the page title.</li>
<li>Use more than 160 characters.</li>
<li>Simply reuse AdWords ads.</li>
<li>Write a meta description in every case. For example, a page listing dozens of blog entries targeting many different keywords might be better of with the SE-generated snippet of text surrounding the users search phrase.</li>
</ul>
Export Exchange mailbox to PST2010-03-12T11:04:56Zhttps://www.clausconrad.com/blog/export-exchange-mailbox-to-pst/<ol>
<li>
<p>Prerequisites:<br />
You will need a machine with a 32-bit version of Windows (Windows 7 is fine) and Outlook 2003 or 2007.<br />
Join the machine to the domain that contains the Exchange server.<br />
Log on as a domain administrator.<br />
Install Exchange Server Management Tools 2007 SP1. To achieve this, insert the Exchange disc, do a custom installation, and only select the Management Tools.</p>
</li>
<li>
<p>Open Exchange Management Shell.</p>
</li>
<li>
<p>Give the current user permissions to the mailbox you want to export:</p>
<pre><code class="language-powershell">Add-MailboxPermission -Identity <email> -User <domain\currentuser> -AccessRights FullAccess
</code></pre>
<p>- where EMAIL is the e-mail address of the mailbox you want to export, and DOMAIN\CURRENTUSER is the name of the user you are logged on with.</p>
</li>
<li>
<p>Export the mailbox to a PST file:</p>
<pre><code class="language-powershell">Export-Mailbox -Identity <email> -PSTFolderPath <c:\some_path>
</code></pre>
<p>- where EMAIL is the e-mail address of the mailbox you want to export, and C:\SOME_PATH is some path (doesn’t have to be on C: of course).</p>
</li>
</ol>
<p>Good luck!</p>
Map of Fitness24Seven locations2010-01-26T19:11:11Zhttps://www.clausconrad.com/blog/map-of-fitness24seven-locations/<p>Show <a href="https://www.google.com/maps/d/u/0/edit?mid=1U7Int-plNPKr4gXDoK2UjSqTero&ie=UTF8&msa=0&ll=57.42562921950885%2C15.11046&spn=3.99226%2C6.297249&source=embed&z=9">Fitness 24 Seven locations</a> on a map</p>
The Last Year Of Your Life2010-01-25T12:19:20Zhttps://www.clausconrad.com/blog/the-last-year-of-your-life/<ol>
<li>Decide this is the last year of your life.</li>
<li>Write down what you want to achieve.</li>
<li>Share your goals with a community of people.</li>
<li>Create a system where you hold yourself accountable.</li>
<li>Congratulate yourself when you achieve your goal.</li>
</ol>
<p>My own unedited notes from the show:</p>
<ul>
<li>Goal of the program: to get everything you possibly can out of each day.</li>
<li>The most important part is to make the decision (that this is the last year of your life).</li>
<li>Stop drinking caffeine.</li>
<li>You don’t have time to indulge in self-pity.</li>
<li>Wake up with the feeling “Today is the last (January 24th or whatever day it is) of my life”.</li>
<li>Realize that with your limited time, there will be things you are no longer willing to tolerate.</li>
<li>Don’t become a slave to your watch, but before doing anything, ask yourself if it’s important enough to be part of your last year on earth.</li>
<li>78% of all new years resolutions are abandoned before the end of January.</li>
<li>Break tasks into smaller steps to make them achievable.</li>
<li>Reward yourself for successes.</li>
<li>Focus on the benefits of the goals, that you can reap once you achieved them.</li>
<li>Share goals with at least 5 others who are supportive.</li>
<li>Write goals for the whole year down, simply thinking or saying them is not powerful enough.</li>
<li>Schedule regular review times, e. g. each week, where you go through your goals and cross the achieved ones of.</li>
<li>Affirmations are powerful tools to affect the subconscious.</li>
<li>Celebrate achieved goals.</li>
<li>Break any habits of criticizing yourself.</li>
<li>Even though you’re breaking bigger goals into doable parts, always focus on how having the larger goal finally achieved will feel.</li>
<li>“If you are afraid (of something), you must (do it)” (Tony Robbins)</li>
<li>Know what you want, what’s really important to you.</li>
<li>First week: Start with loving and acknowledging yourself.</li>
<li>Second week: Acknowledge goals you achieved previously in your life.</li>
<li>With the right mindset lots of things can be achieved in one year, but there is basically nothing you can’t achieve in 5 years with the same mindset.</li>
<li>Don’t unfriend everybody who isn’t supportive of your goals, because different-minded people are part of the richness of life, but maximize time spent with people who think as big or bigger than you. Be aware of the fact that listening to others negative beliefs WILL influence your subconscious, and tell yourself that you don’t want anyone else to run your life.</li>
<li>Doing something 99% is easy, the last percent is the hard part. If you only convince your subconscious to do something to 99%, e. g. working out each day, it becomes easy to convince yourself to skip a day and soon you will have stopped the activity altogether.</li>
<li>The huge amount of belief that Clint Arthur seems to have in his own ability to achieve his goals is part of why his motivational speech works</li>
<li>Using affirmations many times a day is an integral part of why this program works.</li>
<li>The more goals you have, the more results are you going to achieve. Whether you have few or many goals for the year, some will fall away. If you look closely at those you didn’t achieve, you might realize that they weren’t important to you in the first place.</li>
<li>Tips for successful mantras (affirmations): Make them time-based and specific. Include clear-cut goals and the timeline to achieve them in. Example: “It is now Dec. 31st, 2010 and I’m earning XXX/year. I am proud of my income, I inspire those around me, and I’m grateful to be a man who can earn XXX/year.”</li>
<li>Quitting smoking is one of the most important things one can do.</li>
<li>He recommends Tony Robbins “Unleash the power within” program.</li>
<li>If you have a hard time asking others for help, realize that many people love to help others</li>
<li><strong>Finding your passion:</strong> Do what you really love. What makes you excited? What did you enjoy as a child, when you were 6-7 years old? Cut back on unneccesary expenses, focus instead on what really excites you. Look for inspiration from your inner child.</li>
<li>Your goals need to be realistic. Tripling your income is possible with the right attitude, going from zero to a million in 1 year is not. You have to be able to belief your goals if you want to be able to program your subconscious.</li>
<li>You will make as much money as the value you provide to other people. The more real value you provide, the more you earn. Sitting on the couch watching TV is not providing value to anybody.</li>
<li>The way a warrior lives: Today is a great day to die, because I lived all days before just the way I wanted to.</li>
</ul>
Finding small freelance translation jobs2010-01-19T10:15:50Zhttps://www.clausconrad.com/blog/finding-small-freelance-translation-jobs/<h3 id="use-your-(social)-network" tabindex="-1">Use your (social) network</h3>
<ul>
<li>
<p>This might go without saying, but it is no secret that many positions are announced solely on social networks nowadays. I would imagine people who successfully hired full-time employees using their networks to continue using the same channels for smaller tasks.</p>
</li>
<li>
<p>People you know might be aware of your skills, but not consider them simply because you don’t seem to be looking for opportunities. So get out there and announce your willingness on your <a href="https://www.linkedin.com/">LinkedIn</a> profile, <a href="https://www.facebook.com/">Facebook</a> <a>and</a> <a href="https://www.twitter.com/">Twitter</a>.</p>
</li>
</ul>
<h3 id="specialized-sites" tabindex="-1">Specialized sites</h3>
<p>A couple of freelance sites specialize on translation jobs. I would imagine these to have better-paid jobs and more professional buyers than the general sites (see below), but I don’t have personal experience with any of these.</p>
<ul>
<li><a href="https://www.proz.com/">ProZ.com</a><br />
Claims to be the world’s largest database of freelance translators.</li>
<li><a href="https://www.translatorsbase.com/">Translatorsbase.com</a></li>
<li><a href="https://www.traduguide.com/">TRADU_guide_</a></li>
</ul>
<h3 id="general-freelance-sites" tabindex="-1">General freelance sites</h3>
<p>I have used most of these and all of them are large, user-friendly sites. There is also a lot of competition going on, but if you manage to establish a decent profile there, it can be worth its weight in gold.</p>
<ul>
<li><a href="https://www.freelancer.com/">Freelancer.com</a></li>
<li><a href="https://www.upwork.com/">Upwork</a><br />
Not many Western providers here, but the site is growing rapidly, so it can’t harm to have a profile there. They have a payment guarantee for providers, which is kind-of like traditional escrow.</li>
<li><a href="https://www.guru.com/">Guru.com</a><br />
A smaller site that I used once.</li>
</ul>
<p>Are you a freelancer, translator or otherwise? What are your experiences in the current economy and with the sites I listed? Know of any better ones? Please let me and others know below!</p>
Slow Amazon EC2 rsync / SCP / SFTP upload speeds?2010-01-13T18:51:27Zhttps://www.clausconrad.com/blog/slow-amazon-ec2-rsync-scp-sftp-upload-speeds/<p>By simply switching the SSHd listening port to http (80), speeds went up to 1,4 MB/sec. Why Amazon would throttle the SSH port (22) I don’t know, but I hope this helps somebody else out there.</p>
Backing up to Amazon AWS2010-01-11T03:52:23Zhttps://www.clausconrad.com/blog/backing-up-to-amazon-aws/<p>I recommend that you are at least slightly familiar with the <a href="https://aws.amazon.com/">AWS services</a> before continuing to read this walkthrough.</p>
<h3 id="choosing-an-aws-backup-method" tabindex="-1">Choosing an AWS backup method</h3>
<p>There are many variations of using Amazon Web Services to back up your data. In the following I will shortly describe the methods I know of and the pros and cons I see with each of them.</p>
<h4 id="backing-up-directly-to-s3" tabindex="-1">Backing up directly to S3</h4>
<p>For backing up directly to S3, several tools exist.</p>
<ul>
<li>
<p><strong><a href="https://jets3t.s3.amazonaws.com/applications/applications.html#synchronize">JetS3t synchronize</a></strong></p>
<p>Synchronize is part of a larger suite of S3-tools called “JetS3t”. It is a command-line based tool written in Java and so it requires a Java runtime, but otherwise it can be run like any other CLI application and doesn’t require a GUI. Don’t let the simple name fool you - it is one of the better tools for backing up data to S3. Apart from Synchronize, JetS3t also contains a GUI to manage files on S3 called “Cockpit” and a SDK for Java developers to integrate S3 into their software. I have used Synchronize on several servers and continue to use it. One problem I experienced several times with this tool was its huge memory consumption when backing up large numbers of files. My server with the largest number of files currently needs to back up over 700,000 files and even though I increased the memory for Java to 2 GB it still ran out of RAM. This might not be due to Synchronize or JetS3t itself, but made me look for other solutions for this server, such as the one presented below. However I still consider Synchronize to be very well-written and user-friendly, and if the number of files you need to back up is small (like in “below 50,000 files”) it is a very reliable application. (Please also consider my general comments about backing up directly to S3 below though.)</p>
</li>
<li>
<p><strong><a href="https://s3sync.net/wiki.html">s3sync.rb</a></strong></p>
<p>Another popular solution I tried, s3sync.rb is a Ruby-based script that works kind-of like rsync. Unlike JetS3t it had no problems backing up my collection of 700,000 small files. However, it created an enourmous number of requests to S3, resulting in a huge bill from Amazon, so I don’t use it anymore. Apart from that it worked well though. (Please also consider my general comments about backing up directly to S3 below.)</p>
</li>
<li>
<p><strong><a href="https://www.jungledisk.com/">JungleDisk</a></strong></p>
<p>I am reluctant to include this here because I haven’t had a chance to try it, but JungleDisk appears to be a popular solution for backing up data to S3 and it looks pretty good on paper. I didn’t use it because it seems to require a GUI.</p>
</li>
</ul>
<p>A general problem with backing up to S3, not caused by any of the above-mentioned tools, is that S3 requires you to copy whole files. So if you have a 500 MB file where only 1 byte changed, the whole 500 MB have to be uploaded each time, and you will be charged current S3 incoming transfer fees for that. This reason alone made me disregard all S3-based solutions for larger/more frequent backups.</p>
<h4 id="using-ec2-local-storage" tabindex="-1">Using EC2 local storage</h4>
<p>You could use the (currently 160 GB) local storage of EC2 instances for backups. However, if the instance is shutdown for any reason, all data is lost. Even if you don’t shutdown the instance ever, the host could lose its power or the host’s hard drive could crash, resulting in a total data loss.</p>
<p>This problem can be overcome by snapshotting the local instance storage to S3 in frequent intervals. I just found this solution to be too complex and expensive for my purposes.</p>
<h4 id="using-an-ec2-attached-ebs-volume" tabindex="-1">Using an EC2 attached EBS volume</h4>
<p>It is possible to use an EC2 instance and attach a EBS volume to it. Even though the EC2 instance is shut down or crashes, the EBS volume will be preserved, and even though the EBS host should crash, its data is backed up automatically. While S3 data is backed up about several data centers, EBS data is only being backed up in the same data center. So the safety level of data on attached EBS volumes can be considered to lie somewhere between instance-local storage and S3.</p>
<p>For increased security, EBS volumes can be snapshotted to S3 as often and with as many concurrent copies as desired.</p>
<p>This is certainly a viable backup solution. Depending on how important your data is, you might want to take S3 snapshots in addition to your EBS backups. While I tried it, I found it too complex to administer and also kind-of expensive.</p>
<h4 id="using-an-ec2-root-ebs-volume" tabindex="-1">Using an EC2 root EBS volume</h4>
<p>For increased security, EBS volumes can be snapshotted to S3 as often and with as many concurrent copies as desired.</p>
<h3 id="my-guide" tabindex="-1">My guide</h3>
<p>Based on the determined importance of my data, the fact that this is a second site (in addition to on-site backup) and budgetary constraints, I chose to use an EBS volume as an EC2 instance root without snapshotting the volume to S3. This is the method I am going to describe in detail in the rest of this walkthrough. Before cloning this process I invite you to study the <a href="https://docs.aws.amazon.com/index.html">AWS documentation</a> to determine its fitness for your purposes.</p>
<h3 id="signing-up-for-amazon-aws" tabindex="-1">Signing up for Amazon AWS</h3>
<p>If you don’t have an AWS account yet, <a href="https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fportal.aws.amazon.com%2Fbilling%2Fhome%3Fstate%3DhashArgs%2523%252Fdevpay%26isauthcode%3Dtrue&client_id=arn%3Aaws%3Aiam%3A%3A934814114565%3Auser%2Fportal-aws-auth&forceMobileApp=0&code_challenge=xph9Oqd5JRTW5GW2EATrYIcjs9dVCQAgEyNwi7Jrw1g&code_challenge_method=SHA-256">sign up here</a> using your Amazon login (or create one using the same link, if you aren’t an Amazon customer yet). Even if you’ve already ordered books and stuff from Amazon, signup for AWS services is separate from that. However, the only AWS service you need for this guide is EC2.</p>
<h3 id="choosing-an-aws-region" tabindex="-1">Choosing an AWS region</h3>
<p>Amazon AWS currently has server farms in three regions: US-West (Northern California), US-East (Virginia) and EU-West (Ireland). Usually, you want to use the one closest to the location of your servers. Depending on the type of data you want to back up, you might even have a legal obligation not to move it outside of your own country or region. In my case this means I have to use the EU-West region.</p>
<h3 id="choosing-an-ami" tabindex="-1">Choosing an AMI</h3>
<p>TBD</p>
<h3 id="preparing-your-environment-(installation)" tabindex="-1">Preparing your environment (installation)</h3>
<p>TBD</p>
<h4 id="downloading-your-cert-and-private-key" tabindex="-1">Downloading your cert and private key</h4>
<p>TBD</p>
<h4 id="creating-an-ec2-key-pair" tabindex="-1">Creating an EC2 key pair</h4>
<p>TBD</p>
<h4 id="other-tools" tabindex="-1">Other tools</h4>
<p>Download and unpack the Amazon EC2 API tools.</p>
<p>Set the following environment variables:</p>
<pre><code class="language-shell">EC2_HOME=/path/to/ec2-api-tools
JAVA_HOME=/path/to/java
PATH=/path/to/ec2-api-tools/bin:$PATH
</code></pre>
<p>Download and install the latest version of <a href="https://github.com/boto/boto">boto</a>.</p>
<p>Configure your region in ~/.boto.</p>
<h3 id="setting-up-the-instance" tabindex="-1">Setting up the instance</h3>
<p>TBD</p>
<p>I want to clarify this part further, but as a short note, in the following command you will most likely want to change:</p>
<ul>
<li>
<p>The number 100 in the “block-device-mapping” argument is the size of the EBS root volume in GB</p>
</li>
<li>
<p>ami-13042f67 is the ID of the AMI you want to use, find it at <a href="https://console.aws.amazon.com/">https://console.aws.amazon.com/</a></p>
</li>
</ul>
<pre><code class="language-shell">ec2-run-instances --private-key /path/to/private-key.pem --cert /path/to/cert.pem -H --region <regionname> --availability-zone <availibilityzone> --block-device-mapping /dev/sda1=:100:false --instance-initiated-shutdown-behavior stop --key <keyname> ami-13042f67
ssh -i /path/to/keypair-private-key.pem root@<instance public dns name>
</code></pre>
<p>Now connected to the instance, resize the root volume to its full size:<sup><a href="#footnote-1">1</a></sup>:</p>
<p><code>sudo resize2fs /dev/sda1</code></p>
<h3 id="running-a-backup" tabindex="-1">Running a backup</h3>
<p>TBD</p>
<h4 id="starting-the-instance" tabindex="-1">Starting the instance</h4>
<pre><code class="language-conn.start_instances([instance_id])">res = conn.get_all_instances([instance_id])[0]
while not res.instances[0].state == u'running': wait
ip = res.instances[0].public_dns_name
</code></pre>
<h4 id="running-rsync" tabindex="-1">Running rsync</h4>
<p>TBD</p>
<h4 id="putting-it-all-together" tabindex="-1">Putting it all together</h4>
<p>TBD</p>
<h3 id="foot-notes" tabindex="-1">Foot notes</h3>
<p><a id="footnote-1"></a>1: Thanks to <a href="https://alestic.com/2009/12/ec2-ebs-boot-resize/">Alestic</a></p>
Weekly review: Week ending Dec 27, 20092009-12-29T15:41:41Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-dec-27-2009/<p><a id="last-week"></a><strong>Plans from last week:</strong></p>
<p><u>Work</u></p>
<ul>
<li><del>Help with technical support (Amino)</del></li>
<li><del>Prepare VAT returns 11/2009 (CC)</del></li>
<li><strong>Resell software (CC)</strong></li>
<li><strong>Implement new community features (Amino)</strong></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Scanned and sorted expense invoices (CC)</del></li>
<li><del>Reestablished backup script on claus2 (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Celebrate christmas</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Mailed my dad</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><em>Continue work on arcade clone</em></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Started moving pension account to cheaper bank</del></li>
<li><del>Washed blankets</del></li>
<li><del>Ordered contact lenses</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li><strong>Implement new community features (Amino)</strong></li>
<li><strong>Resell software (CC)</strong></li>
<li>Choose mobile development team (Amino)</li>
<li>Publish a couple of content articles (CC)</li>
<li>Negotiate mailing contract (CC)</li>
<li>Evaluate SEO measures for hyponotherapist website (CC)</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Read 2 books</li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from next week</strong></li>
<li>All other items are new</li>
</ul>
Sort ls output by date ascending2009-12-29T14:33:39Zhttps://www.clausconrad.com/blog/sort-ls-output-by-date-ascending/<pre><code class="language-shell">ls -latr
</code></pre>
<ul>
<li><em>l</em><br />
Long list with more details</li>
<li><em>a</em><br />
Include hidden files</li>
<li><em>t</em><br />
Sort by date descending</li>
<li><em>r</em><br />
Reverse sort order</li>
</ul>
Richard Bach - Out of My Mind2009-12-28T16:07:33Zhttps://www.clausconrad.com/blog/richard-bach-out-of-my-mind/<p>In this short story, the unnamed narrator (the author himself?) starts out with a couple of problems - design flaws on his small and rather antique airplane, while not critical, continue to dim the enjoyment of his flight sessions. One day he goes to sleep, exhausted after having spent hours at his computer trying to construct a better lock for the plane’s window without succeeding. On awakening the next morning a solution has suddenly appeared in his mind, he jots it down and it works perfectly.</p>
<p>Another problem presents itself and this time, the solution comes to him just as sudden, but in bright daylight - and it doesn’t come alone. At the time he visualizes the new construction in his mind, he also receives a minute glimpse of an unknown woman, who appears to see him and looks just as surprised as the narrator himself. He gets the impression that this woman sent him the idea from another time and place, and his mission changes from improving his aircraft to finding and talking to the woman he “saw”. By using relaxation techniques and his imagination he manages to visit a parallel universe in his mind, where he actually discovers the woman and the aircraft company she works for. He only talks to her for a few minutes, but is being shown the company hangars of her employer for about an hour by a manager.</p>
<p>This is my first novel by Richard Bach and a very short one too, but hopefully not the last. I like the pace of his telling the story, it enabled me to visualize the events better than in most other fiction I have read. While it could be classified as new-agey or fantastic I would prefer to view it as a philosophical story; the reality (or imagination) of the narrators experiences doesn’t really matter to the story’s intention. I don’t know whether Richard Bach intended for the unnamed narrator to resemble him, but I would imagine it simply from reading the passionate descriptions of the antique aircrafts he discovers through the rest of the story. His excitement over having found this other-dimensional place, where everybody loves antique planes just like he does, shines through every single word and manages to capture me too - even though I don’t consider myself interested in the actual topic.</p>
<p>I don’t agree with other reviewers who claim the story is stretched, and found its length to be just right for the situations it covers, but then again I generally prefer to read about narrators’ thoughts in stories in order to feel like really knowing what makes them tick. This is certainly not your kind of book if you are looking for suspense and action ;-) I don’t agree with other reviews claiming the story is too short or ends to abruptly either - it is true that it leaves a lot of questions open, but I consider that to be part of a writer’s freedom. Some books leave you with more questions than answers and make you feel bad about not knowing more, but this one just left me with a positive feeling and a smile inside.</p>
Weekly review: Week ending Dec 20, 20092009-12-22T16:19:03Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-dec-20-2009/<p><u>Work</u></p>
<ul>
<li><del>Implemented new community features (Amino)</del></li>
<li><del>Updated all sites to new Drupal version (CC)</del></li>
<li><del>Helped with technical support (Amino)</del></li>
<li><strong>Prepare VAT returns 11/2009 (CC)</strong></li>
<li><strong>Resell software (CC)</strong></li>
<li><em>Implement new design on <a href="http://ghostwriters.dk">ghostwriters.dk</a> (CC)</em></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Published requirements for iPhone app (Amino)</del></li>
<li><del>Shopped 20 lbs sweets for office (Amino)</del></li>
<li><del>Implemented changes to partner signup pages (Amino)</del></li>
<li><del>Improved SEO on blogs (Amino)</del></li>
<li><del>Ordered bookkeeping application (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<p>Also:</p>
<ul>
<li><del>Shopped for cashmas gifts</del></li>
<li><del>Got interesting mail from new mentor - blogging more soon</del></li>
<li><del>Invited old friend to visit me 2010H1</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><del>Went to regression at hypnotherapist</del></li>
<li><del>Paid pension money for tax deductions</del></li>
<li><strong>Continue work on arcade clone</strong></li>
<li><em>Prepare taxation predictions for 2010</em></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Updated balance sheet over financial accounts</del></li>
<li><del>Cancelled Barnes&Noble membership - need to manage this better to avoid unnecessary auto-renewals</del></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><del>Planned, completed</del></li>
<li><strong>Planned, not completed, rescheduled for next week</strong></li>
<li><em>Planned, not completed, not rescheduled for next week</em></li>
<li><u>Also</u> items: not planned, but completed</li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Implement new community features (Amino)</li>
<li>Help with technical support (Amino)</li>
<li><strong>Prepare VAT returns 11/2009 (CC)</strong></li>
<li><strong>Resell software (CC)</strong></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>Celebrate christmas</li>
</ul>
<p><u>Life</u></p>
<ul>
<li><strong>Continue work on arcade clone</strong></li>
</ul>
<p><u>Legend</u></p>
<ul>
<li><strong>Rescheduled from next week</strong></li>
<li>All other items are new</li>
</ul>
Weekly review: Week ending Dec 13, 20092009-12-14T14:47:52Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-dec-13-2009/<p><u>Work</u></p>
<ul>
<li><del>Improved SEO on forums, blogs & wikis (Amino)</del></li>
<li><del>Implemented new community features (Amino)</del></li>
<li>Implement design on “Codename ldk” (CC)</li>
<li>Implement new design on <a href="http://ghostwriters.dk">ghostwriters.dk</a> (CC)</li>
</ul>
<p>Also:</p>
<ul>
<li><del>Tested restore of backup (Amino)</del></li>
<li><del>Helped with technical support (Amino)</del></li>
<li><del>Added more data to partner lead mails (Amino)</del></li>
<li><del>Contacted affiliate network about missing leads (KC)</del></li>
<li><del>Updated Drupal and WordPress sites (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<p>Also:</p>
<ul>
<li><del>Washed sleeping bag for christmas party</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Prepare taxation predictions for 2010</li>
</ul>
<p>Also:</p>
<ul>
<li><del>Moved money between accounts to avoid paying interest</del></li>
<li><del>Paid pension for 2009</del></li>
<li><del>Published my <a href="https://www.urbandictionary.com/define.php?term=catural">first word</a> in Urban Dictionary</del></li>
<li><del>Tested fire alarms at home</del></li>
<li><del>Repaired 2 inside doors of my apartment</del></li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Implement new community features (Amino)</li>
<li>Prepare VAT returns 11/2009 (CC)</li>
<li>Implement new design on <a href="http://ghostwriters.dk">ghostwriters.dk</a> (CC)</li>
<li>Help with technical support (Amino)</li>
<li>Resell software (CC)</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Prepare taxation predictions for 2010</li>
<li>Continue work on arcade clone</li>
<li>Regression session</li>
</ul>
Weekly review: Week ending Dec 6, 20092009-12-07T01:22:33Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-dec-6-2009/<p><u>Work</u></p>
<ul>
<li><del>Rented a shared office space at Midzone (CC)</del></li>
<li><del>Finished development of <a href="http://nissehue.dk">nissehue.dk</a> (KC)</del></li>
<li><del>Improved forums with new features (Amino)</del></li>
<li><del>Sent invoice (Amino)</del></li>
<li><del>Put some unused domain names up for auction (CC)</del></li>
<li><del>Ordered some hardware for auctions (CC)</del></li>
<li>Implement new design on <a href="http://ghostwriters.dk">ghostwriters.dk</a> (CC)</li>
</ul>
<p>Also:</p>
<ul>
<li><del>Researched possible statistical values for a mail job (Amino)</del></li>
<li><del>Updates on partner lead page (Amino)</del></li>
<li><del>Deleted spam profiles and prevented this problem from recurring (Amino)</del></li>
<li><del>Reviewed and documented backup strategy (Amino)</del></li>
<li><del>Answered request from taxation authorities (CC)</del></li>
<li><del>Updated CV</del></li>
<li><del>Hired content writers (CC)</del></li>
<li><del>Checked all sites for software updates (CC)</del></li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li><del>Attended my sisters birthday party</del></li>
</ul>
<p>Also:</p>
<ul>
<li><del>Skyped with my mom a couple of times</del></li>
<li><del>Made plans for Xmas eve 2009</del></li>
</ul>
<p><u>Life</u></p>
<ul>
<li><del>Used fakir mat more often</del></li>
<li><del>Bought exotic foods at Asian shops</del></li>
<li><del>Got hair cut</del></li>
<li>Prepare taxation predictions for 2010</li>
</ul>
<p>Also:</p>
<ul>
<li><del>Went for a run more often</del></li>
<li><del>Bought new suit</del></li>
<li><del>Bought pet food</del></li>
<li><del>Updated and documented taxation status in Denmark</del></li>
<li><del>Reviewed long-time plans</del></li>
</ul>
<p><a id="next-week"></a><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Improve SEO on forums (Amino)</li>
<li>Implement new design on <a href="http://ghostwriters.dk">ghostwriters.dk</a> (CC)</li>
<li>New features for forums (Amino)</li>
<li>Implement design on “Codename ldk” (KC)</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Prepare taxation predictions for 2010</li>
</ul>
Get metadata about MySQL databases2009-12-05T08:06:07Zhttps://www.clausconrad.com/blog/get-metadata-about-mysql-databases/<pre><code class="language-sql">SHOW DATABASES;
SHOW TABLES;
SHOW CREATE TRIGGER <trigger-name>
SHOW CREATE PROCEDURE <procedure-name>
</code></pre>
Does your CommunityServer have spam profiles?2009-12-03T19:25:17Zhttps://www.clausconrad.com/blog/does-your-communityserver-have-spam-profiles/<p>These user profiles pollute your authority and you probably want to delete them, but first you have to identify them. I found the following query helpful for this purpose:</p>
<pre><code class="language-sql">SELECT
U.UserName
FROM
aspnet_users U
JOIN
aspnet_profile P
ON
U.UserID = P.UserID
JOIN
CS_Users CSU
ON
CSU.MembershipID = U.UserID
WHERE (
P.PropertyValuesString LIKE '%<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %<a %' OR
P.PropertyValuesString LIKE '%position:absolute%'
OR
P.PropertyValuesString LIKE '%overflow:hidden%'
)
AND
(SELECT COUNT(*) FROM CS_Posts P WHERE P.UserID = CSU.UserID) = 0</a>
</code></pre>
<p><strong>Make sure to check your results for false positives!</strong> Once you are sure you got all the culprits and nobody else, iterate over it and delete each spammer e. g. by running</p>
<p><code>CommunityServer.Users.DeleteUser(CommunityServer.Users.GetUser(userName));</code></p>
<p>While the code is simple the reason I don’t include it here is because I want you to think about what you are doing and not blindly copy/paste it and accidentally delete “real” users - you will likely have to customize the above SQL snippet to achieve this.</p>
Weekly review: Week ending Nov 29, 20092009-11-30T21:26:25Zhttps://www.clausconrad.com/blog/weekly-review-week-ending-nov-29-2009/<p><u>Work</u></p>
<ul>
<li><del>Create a page with partner leads and integrate it into the sign-up process (Amino)</del></li>
<li><del>Create administration pages for partner leads (Amino)</del></li>
<li><del>Create a win-win agreement for further work with Martin (Amino)</del></li>
<li><del>Track leads through a banner rotation/tracking solution (Own sites)</del></li>
<li><del>Updated WordPress blogs to 2.8.6</del></li>
<li>Finish development of <a href="http://nissehue.dk">nissehue.dk</a> (KC)</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>
<p><del>Cancel a cell phone subscription I haven’t used for months</del></p>
</li>
<li>
<p><del>Washed more clothes than in any other week before in this life</del></p>
</li>
</ul>
<p><strong>Plans for next week:</strong></p>
<p><u>Work</u></p>
<ul>
<li>Improve forums (Amino)</li>
<li>Finish development of <a href="http://nissehue.dk">nissehue.dk</a> (KC)</li>
<li>Implement new design on <a href="http://ghostwriters.dk">ghostwriters.dk</a></li>
<li>Invoice Amino</li>
<li>Auction some unused stock domains</li>
</ul>
<p><u>Relationships</u></p>
<ul>
<li>My sisters birthday party</li>
</ul>
<p><u>Life</u></p>
<ul>
<li>Prepare taxation predictions for 2010</li>
<li>Use fakir mat more often</li>
<li>Buy exotic foods at Asian shops</li>
<li>Visit barber</li>
</ul>
ERROR 1307 (HY000): Failed to CREATE PROCEDURE2009-11-28T18:07:18Zhttps://www.clausconrad.com/blog/error-1307-hy000-failed-to-create-procedure/<p>To resolve it, run <code>mysql_upgrade</code> as Administrator/root.</p>
"The application cannot start" running Visual Studio as Administrator2009-11-12T15:39:55Zhttps://www.clausconrad.com/blog/the-application-cannot-start-running-visual-studio-as-administrator/<p>Thanks to <a href="https://www.21concepts.com/Blog/EntryId/10/Visual-Studio-2005-2008-The-application-cannot-start.aspx">Howard Little</a>.</p>
Installing updates on Solaris 10 from the command line2009-10-29T17:11:35Zhttps://www.clausconrad.com/blog/installing-updates-on-solaris-10-from-the-command-line/<ol>
<li>
<p>Check for available updates (optional):</p>
<pre><code class="language-shell">smpatch analyze
</code></pre>
</li>
<li>
<p>Download and install the updates:</p>
<pre><code class="language-shell">smpatch update
</code></pre>
</li>
<li>
<p>If the system requires a reboot, do this as soon as possible by running:</p>
<pre><code class="language-shell">init 6
</code></pre>
</li>
</ol>
Improve your iPhone 3G's battery life2009-10-14T23:21:58Zhttps://www.clausconrad.com/blog/improve-your-iphone-3g-s-battery-life/<p>Don’t despair - by following a few simple rules you can make its battery last the time you need to, and that doesn’t mean having to turn your gadget into an unused brick.</p>
<p>Let’s be honest - we all know the main energy hogs of the iPhone. The trick is of course to learn how much the use of each component costs in terms of battery capacity and use this knowledge to plan ahead for the day, and avoiding the use of costly features that don’t give a high enough return in increased usability. Here are some ways you could implement this:</p>
<ul>
<li>
<p><em>Prefer applications that cache and fetch instead of pushing</em><br />
Many applications leave you the choice between pushed and fetched data. Do you really need that RSS feed more often than every 15 minutes? Disabling Push for every non-critical communication channel is one of the best ways to improve battery life.</p>
</li>
<li>
<p><em>YouTube - an enormous battery drainer</em><br />
Streaming YouTube videos, especially over WAN connections like 3G, can take your battery from full to empty in less than 3 hours, so try to avoid those “couples of celeb vids” unless you know you’ll be able to charge soon.</p>
</li>
<li>
<p><em>Charge your battery right</em><br />
Let it completely charge, then completely dry out at least once a month.</p>
</li>
<li>
<p><em>Lower the auto-lock value</em><br />
This value found under “Settings” > “General” tells your iPhone how long to wait before it goes into standby when you are finished using it. The lowest possible value of 1 minute conserves the most battery, but if it disturbs your regular usage, just set this one higher and remember to press the stand-by button after each use.</p>
</li>
<li>
<p><em>Lower the brightness</em><br />
While the new iPhone’s screen is even brighter than before, using it fully is still an energy hog. I would try to balance usability and performance by setting brightness as low as possible and keeping “auto-brightness” turned on.</p>
</li>
<li>
<p><em>Transfer as much data as possible via cable</em><br />
- not only will this increase your battery life by charging it concurrently, transferring large files (such as apps, songs and attachments) through the USB port can also be a lot faster.</p>
</li>
<li>
<p><em>Toggle WiFi scanning as needed</em><br />
Unless you’re a real hotspot hopper, chances are the extra hours you can get out of toggling WiFi on and off are worth it.</p>
</li>
<li>
<p><em>Switch off A-GPS unless needed</em><br />
The same goes for Location Services (A-GPS) - a lot more apps than you think might otherwise use your location to “improve their functionality”, and suck your battery dry at the same time.</p>
</li>
<li>
<p><em>If everything else fails, bring more power with you</em><br />
- by carrying a power-extending case, an emergency charger, a travel charger or simply by having compatible chargers in as many places you frequent as possible, including your car.</p>
</li>
</ul>
Monitoring open network connections and listening ports on Debian Lenny2009-09-23T01:16:22Zhttps://www.clausconrad.com/blog/monitoring-open-network-connections-and-listening-ports-on-debian-lenny/<pre><code class="language-shell">sudo lsof -Pi
</code></pre>
<p>If this doesn’t work, you might have to install <code>lsof</code> by running the following command:</p>
<pre><code class="language-shell">sudo apt-get install lsof
</code></pre>
Disable port 5353 usage on Debian Lenny after installing Sun Java JRE2009-09-23T01:08:14Zhttps://www.clausconrad.com/blog/disable-port-5353-usage-on-debian-lenny-after-installing-sun-java-jre/<p>This appears to be a GPL implementation of the Apple Zeroconf protocol, allowing devices to detect each other in a LAN environment. Since I don’t have a need for detecting printers etc. on my server, I disabled it using the following command:</p>
<p><code>sudo update-rc.d -f avahi-daemon remove sudo /etc/init.d/avahi-daemon stop</code></p>
<h3 id="steps-leading-to-this-problem" tabindex="-1">Steps leading to this problem</h3>
<p>In order to run a Java application on a Debian Lenny server, I installed Sun’s newest JRE (Java Runtime Environment) like this:</p>
<p><code>sudo apt-get install sun-java6-jre</code></p>
<p>This installed many dependencies, including the mentioned <em>avahi-deamon</em>. I hope disabling this service doesn’t interfere with my ability to run Java applications, until now it doesn’t look like it though.</p>
<p>For more information about the associated protocol, visit <a href="http://www.multicastdns.org/">multicastdns.org</a>.</p>
File copy error after activating Drupal translation2009-09-11T14:34:44Zhttps://www.clausconrad.com/blog/file-copy-error-after-activating-drupal-translation/<ul>
<li>If you are on Windows: check the temporary folder setting under <em>admin/settings/file-system</em>. If it is set to <em>/tmp</em>, change it to an existing path.</li>
<li>If it is set to a valid path, make sure the PHP/web server user can write to it.</li>
</ul>
Comparing Content Delivery Networks2009-09-07T14:56:33Zhttps://www.clausconrad.com/blog/comparing-content-delivery-networks/<p>| Network | Type | Origin | Edges | Storage $/GB/mo. | Delivery $/GB | Support $/mo. | CNAME |
|-
| Amazon S3 | - | EU | 1 | 0.18 | 0.17 | 400 | no |
| Amazon S3 with CloudFront | Edge cache | EU | 14 | 0.18 | 0.17 - 0.221 | 400 | yes |
| Amazon S3 | - | US | 1 | 0.15 | 0.17 | 400 | no |
| Amazon S3 with CloudFront | Edge cache | US | 14 | 0.15 | 0.17 - 0.221 | 400 | yes |
| CacheFly | Edge mirror | US | 14 | 15.00 | 0.49 | 0 | ? |
| Rackspace Cloud Files | - | US | 1 | 0.15 | 0.22 | 0 | no |
| Rackspace Cloud Files with Limelight | Edge delivery | US | 17 | 0.15 | 0.22 | 0 | no |
| SimpleCDN | Edge cache | US/ own | 13 | 0.75 | 0.039 | ? | $5 |</p>
<p>Please note:</p>
<ul>
<li>Prices are based on the lowest usage range or contract, and might be significantly cheaper with higher commitment and/or usage.</li>
<li>Prices do not include upload bandwidth/bandwidth to pull from origin server or requests or other fees (where applicable).</li>
</ul>
Convert SSL certificate from Apache to IIS2009-07-06T09:19:26Zhttps://www.clausconrad.com/blog/convert-ssl-certificate-from-apache-to-iis/<h2 id="problem%3A" tabindex="-1">Problem:</h2>
<p>You have generated a CSR using OpenSSL and submitted it to a CA. Your certificate has been issued, but you now want to import it into Windows for use with IIS.</p>
<h2 id="solution%3A" tabindex="-1">Solution:</h2>
<ol>
<li>Convert the received public key from its PKCS7 format to PEM format:<br />
<code>openssl pkcs7 -outform PEM -in public.p7b -out public.pem -print_certs</code></li>
<li>Combine the public keys and the private key into a password-protected PKCS12 file:<br />
<code>openssl pkcs12 -export -out publicandprivate.pfx -in public.pem -inkey private.key</code></li>
</ol>
<p>Hope this helps someone (or at least me next year…).</p>
Programming and productivity publications2009-06-25T18:25:39Zhttps://www.clausconrad.com/blog/programming-and-productivity-publications/<p>Instead of trying to add to his list, here I think a little broader than just programming: which books and other media have had an impact on my professional or general productivity?</p>
<ul>
<li><a href="https://basecamp.com/books/getting-real">Getting Real - the smarter, faster, easier way to build a successful web application</a> by 37signals (they ought to know).<br />
One of these books with short, precise, right-to-the-point chapters - fortunately most of them are real gems. Its message boils down to “the easiest way to achieve something is often the right one”.</li>
<li><a href="https://www.43folders.com/izero">Inbox Zero</a><br />
I was one of those persons using the inbox as my mailbox, calendar and to-do list. Inbox Zero retaught me the joy of e-mail - by using it less. Highly recommended.</li>
</ul>
<p>The following books are still unread on my shelf, so I can’t really recommend them yet - but from what I heard, they are quite popular (and I really need to get those for my reader!):</p>
<ul>
<li><a href="https://www.amazon.com/gp/product/1400082471?ie=UTF8&tag=clausconrad-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1400082471">Dreaming in Code</a></li>
<li><a href="https://www.amazon.com/gp/product/0142000280?ie=UTF8&tag=clausconrad-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0142000280">Getting Things Done</a></li>
</ul>
What's new in Telligent Community 5.0?2009-06-25T09:35:15Zhttps://www.clausconrad.com/blog/what-s-new-in-telligent-community-5-0/<h2 id="groups" tabindex="-1">Groups</h2>
<ul>
<li>Joinless groups</li>
<li>Group wiki</li>
<li>Multiple forums, blogs, media/file galleries, and wikis (with advanced functionality)</li>
<li>Sub-group hierarchy support</li>
<li>Configurable group role permissions</li>
<li>Group messages</li>
<li>Follow or unfollow groups</li>
<li>Quick post functionality with Ajax</li>
<li>Highlight featured content</li>
<li>Group-driven navigation and browse groups</li>
</ul>
<h2 id="membership" tabindex="-1">Membership</h2>
<ul>
<li>Tag myself and find other like-minded people</li>
<li>Admin-configurable user profile fields and layout</li>
<li>Reply to user status messages</li>
<li>Follow user activity</li>
</ul>
<h2 id="blogs" tabindex="-1">Blogs</h2>
<ul>
<li>Support for multiple images and attachments</li>
</ul>
<h2 id="forums" tabindex="-1">Forums</h2>
<ul>
<li>RSS for all forum content in a group</li>
<li>Capture forum thread to wiki</li>
</ul>
<h2 id="wikis" tabindex="-1">Wikis</h2>
<ul>
<li>Add wiki or wiki page to favorites</li>
<li>Default wiki for a group and default page for a wiki</li>
<li>Wiki editing conflict resolution</li>
<li>Capture from forum thread</li>
<li>Multi-level table of contents</li>
<li>In-page table of contents with anchors and anchor linking</li>
<li>Move wikis between groups and sub-groups</li>
</ul>
<h2 id="customization" tabindex="-1">Customization</h2>
<ul>
<li>Configurable “widgets” (components) across the site on every page</li>
<li>Dynamic theming with widgeted UI</li>
<li>Highlighted featured content on site home and group home pages</li>
<li>User-configurable dashboard</li>
<li>Move wikis between groups and sub-groups</li>
<li>Editable key site terms for “group(s)” and “friends(s)”</li>
</ul>
<h2 id="search" tabindex="-1">Search</h2>
<ul>
<li>Word wheel for search results based on what you’re typing</li>
<li>Search for groups</li>
<li>Search by all user profile fields</li>
<li>Search results show forum thread status</li>
<li>Weighted ranking for answers</li>
<li>Advanced search</li>
<li>View users by role</li>
</ul>
<h2 id="tools" tabindex="-1">Tools</h2>
<ul>
<li>Configurable auto-delete task for activity messages</li>
</ul>
Disable "Most visited" in new tabs in Firefox 32009-05-30T04:58:22Zhttps://www.clausconrad.com/blog/disable-most-visited-in-new-tabs-in-firefox-3/<p>To disable the “most visited” pages in Firefox with Google Toolbar, simply:</p>
<ul>
<li>Go to <a href="about:config">about:config</a></li>
<li>Confirm the security question, if asked</li>
<li>There’s a search bar at the top, enter “tab” here</li>
<li>Scroll down to google.toolbar.newTab</li>
<li>Double-click that line and notice that the right-side column has been changed to “False” and the row is now written in bold</li>
<li>Close the about:config tab</li>
</ul>
Count files in a folder recursively2009-05-29T22:29:18Zhttps://www.clausconrad.com/blog/count-files-in-a-folder-recursively/<pre><code class="language-shell">find . -type f | wc -l
</code></pre>
<p>To count the number of files <strong>and folders</strong> in the current folder and in all of its subfolders (recursively):</p>
<pre><code class="language-shell">find . | wc -l
</code></pre>
How to build a DB9-to-RJ45 serial cable2009-05-25T20:13:54Zhttps://www.clausconrad.com/blog/how-to-build-a-db9-to-rj45-serial-cable/<table>
<thead>
<tr>
<th>RJ45 pin</th>
<th>RJ45 color</th>
<th>DB9 pin</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><span style="color: Blue">Blue</span></td>
<td>8</td>
</tr>
<tr>
<td>2</td>
<td><span style="color: Orange">Orange</span></td>
<td>6</td>
</tr>
<tr>
<td>3</td>
<td>Black</td>
<td>2</td>
</tr>
<tr>
<td>4</td>
<td><span style="color: Red">Red</span></td>
<td>5</td>
</tr>
<tr>
<td>5</td>
<td><span style="color: Green">Green</span></td>
<td>5*</td>
</tr>
<tr>
<td>6</td>
<td><span style="color: Yellow">Yellow</span></td>
<td>3</td>
</tr>
<tr>
<td>7</td>
<td><span style="color: Brown">Brown</span></td>
<td>4</td>
</tr>
<tr>
<td>8</td>
<td><span style="color: White; background-color: Black">White/gray</span></td>
<td>7</td>
</tr>
</tbody>
</table>
<p>* According to official Sun manuals this pin ALSO needs to be connected to pin 5 on the DB9 end. According to some other documentation I found it is not necessary to connect it at all. I didn’t connect it and the cable works fine for me.</p>
<p>For the ethernet cable, it is important to use a regular one. This is also called a patch cable or straight-through cable. It is the type you would usually use between a server and a switch, for example.</p>
Accidentally removed user login block in Drupal?2009-04-07T20:50:15Zhttps://www.clausconrad.com/blog/accidentally-removed-user-login-block-in-drupal/<p>Second, just go to “<a href="https://WWW.YOURSITE.COM/index.php?q=user">https://WWW.YOURSITE.COM/index.php?q=user</a>”. This is where you can login to or request a new password from your Drupal site, whether or not the login block is visible.</p>
Inbox Zero2009-04-04T19:46:14Zhttps://www.clausconrad.com/blog/inbox-zero/<ul>
<li>Time and attention are finite. <em>Demands</em> on your time and attention are infinite.</li>
<li>Email’s just a medium. It’s not a purpose in itself.</li>
<li>Have a place for anything - thoughts, ideas, pictures, business cards etc. - so you don’t use your inbox for storage or as a to-do list.</li>
<li>Don’t <em>check</em> your mail, process it. Avoid skimming/reading the same mail twice.</li>
<li>Actions, in order of desirability: Delete/Archive; Delegate; Respond; Defer; Do</li>
<li>Process mails less often. Consider closing e-mail app once in a while.</li>
<li>Use templates to automate frequent responses.</li>
</ul>
Less verbose Server: response header from Apache2009-03-10T23:33:05Zhttps://www.clausconrad.com/blog/less-verbose-server-response-header-from-apache/<p>In your <code>httpd.conf</code>, change (or add) these lines:</p>
<pre><code>ServerTokens Prod
ServerSignature Off
</code></pre>
<p>The first line changes the Server: header to only say “Apache” and nothing else. The second line disables the module listing on Apache-generated error pages.</p>
Run a command in all non-global Solaris zones2009-03-10T23:23:18Zhttps://www.clausconrad.com/blog/run-a-command-in-all-non-global-solaris-zones/<p>Obviously it only works from the global zone :-)</p>
<pre><code class="language-shell">#!/usr/bin/sh
# zonerun - run a command on all non global zones. Solaris 10.
# 10-Mar-2005, ver 0.80
# USAGE: zonerun [-v] command
# eg,
# zonerun uname -a
# zonerun -v uptime
# Standard Disclaimer: This is freeware, use at your own risk.
# 10-Mar-2005 Brendan Gregg Created this.
PATH=/usr/bin:/usr/sbin
verbose=0
if [ "$1" = "-v" ]; then
shift; verbose=1
fi
for zone in `zoneadm list`
do
if [ "$zone" = "global" ]; then continue; fi
if [ $verbose -eq 1 ]; then
echo $zone,
zlogin -S $zone "$*" | sed 's/^/ /'
else
zlogin -S $zone "$*"
fi
done
</code></pre>
Configuring sendmail on Solaris 10 to use a smart host2009-03-10T23:09:44Zhttps://www.clausconrad.com/blog/configuring-sendmail-on-solaris-10-to-use-a-smart-host/<p>Wondering what I need this setup for? I have a couple of web servers which generate mail to external addresses, and my ISP blocks port 25 - except to its own mail server. I don’t have a need to process internal mails in the LAN or incoming mail from the internet, as mails for me and my users are hosted externally.</p>
<p>If that’s your scenario too, here’s what you have to do:</p>
<ul>
<li><strong>Check that the mail server machine has a valid hostname.</strong><br />
Do this by running:<br />
<code>/usr/sbin/check-hostname</code><br />
If it tells you the machine has a valid FQDN, everything’s fine. Otherwise, just follow the suggestion to edit <em>/etc/hosts</em> (instructions are given by the program, if applicable).</li>
<li><strong>Edit /etc/mail/cf/cf/local.mc, e. g. by running:</strong><br />
<code>vi /etc/mail/cf/cf/local.mc</code><br />
Replace the line <em>define(<code>confFALLBACK_SMARTHOST', </code>mailhost$?m.$m$.')dnl</em> with:<br />
<code>define(</code>SMART_HOST’, <code>YOUR_ISP_MAIL_SERVER')dnl</code><br />
Make sure not to change the apostrophs - the opening one always points to the upper left, while the closing one is a vertical one.<br />
Remove the line <em>MAILER(`local’)dnl</em>.<br />
Remove the line <em>LOCAL_NET_CONFIG</em>.<br />
Remove the last line, which says something like <em>R$* < @ $* .$m. > $* $#esmtp $@ $2.$m $: $1 < @ $2.$m. > $3</em>.</li>
<li>We want to listen to any IP address, so remove the following lines too:<br />
<em>DAEMON_OPTIONS(<code>NAME=NoMTA4, Family=inet, Addr=127.0.0.1')dnl DAEMON_OPTIONS(</code>Name=MSA4, Family=inet, Addr=127.0.0.1, Port=587, M=E’)dnl</em><br />
<strong>If you did this step, make sure to protect your mail server from abuse by configuring your firewall appropriately.</strong></li>
<li>Change directory to <em>/etc/mail/cf/cf</em>, e. g. by running:<br />
<code>cd /etc/mail/cf/cf</code></li>
<li>Compile and deploy the changed configuration file by running:<br />
<code>/usr/ccs/bin/m4 ../m4/cf.m4 local.mc > /etc/mail/sendmail.cf</code></li>
<li>If you made sendmail listen to any IP address above, you probably want to allow your other servers in the LAN to relay mails through it. Enable this by editing <em>/etc/mail/relay-domains</em>, e. g. by running:<br />
<code>vi /etc/mail/relay-domains</code><br />
The file might not exist yet.<br />
I’m not sure of the correct syntax for this file, so I entered two lines like this:<br />
<code>192.168.101.0/24 192.168.101.</code><br />
I don’t know which one is correct and don’t really care since it works. <strong>Of course use the correct address and subnetmask for your LAN here!</strong></li>
<li>Finally, make sendmail aware of the configuration changes by running:<br />
<code>svcadm restart sendmail</code></li>
</ul>
Removing "Search this site" from the search block in Drupal 62009-01-25T07:45:25Zhttps://www.clausconrad.com/blog/removing-search-this-site-from-the-search-block-in-drupal-6/<pre><code class="language-php">function phptemplate_preprocess_search_block_form(&$variables) {
unset($variables['form']['search_block_form']['#title']);
unset($variables['form']['search_block_form']['#printed']);
$variables['search']['search_block_form'] = drupal_render($variables['form']['search_block_form']);
$variables['search_form'] = implode($variables['search']);
}
</code></pre>
<p>The variable <code>$variables['form']['search_block_form']['#title']</code> contains the string <em>Search this site:</em> or its translation, but gets rendered as a label - fortunately simply unsetting it removes the label altogether! I am not sure why <code>$variables['form']['search_block_form']['#printed']</code> also needs to be unset, but if that line is omitted, the text box (input field) won’t show up.</p>
Swedish language2008-01-17T13:38:19Zhttps://www.clausconrad.com/blog/swedish-language/<p>Whenever possible I try to link to the English version of the pages, but some of them are in Swedish only. Just try to use the dictionaries from my list or ask in the forums or me if you have trouble understanding something :-)</p>
<p><strong>Language</strong><br />
The Swedish language is not as hard as it might look at first glance! For me it bears a lot of resemblance to Danish and to a lesser extent also to German. The best part though is that you’ll hardly find another country where you can expect almost anybody to understand and speak fluent English than Sweden.</p>
<ul>
<li><a href="https://folkets-lexikon.csc.kth.se/folkets/folkets.en.html">Swedish-English dictionary and vice-versa</a>. This page is in English.</li>
<li><a href="https://deutsch-schwedisches-woerterbuch.elch.nu/lexikon.php">Swedish-German dictionary and vice-versa</a>. Page in German and Swedish.</li>
</ul>
Living in Sweden2008-01-17T13:36:23Zhttps://www.clausconrad.com/blog/living-in-sweden/<p>Whenever possible I try to link to the English version of the pages, but some of them are in Swedish only. Just try to use the dictionaries from my list (see my story “Links: Swedish language”) or ask in the forums or me if you have trouble understanding something :-)</p>
<p>There are many possibilities if you want to reside in Sweden for a longer time: you can rent an apartment directly from the owner (which might be hard to get in many places, especially as a foreigner). You can rent on a so-called second-hand contract from someone who temporarily leaves his apartment for some months or a year. You can buy a so-called “bostadsrätt”, a concept not found in most countries: it is an apartment that you own, but you need to pay a monthly fee to the association the building belongs to. On the positive side that makes the purchase price a lot cheaper. You can also buy a “villa” (houses of all sizes) that you own completely, or buy a “tomt” (building site) to build your own house.</p>
<p>Did you know? In Sweden, real estate agents are required by law to work for both the seller and prospective buyer. That means a lawyer is usually not required when buying a “bostadsrätt”, unlike some other countries.</p>
<ul>
<li>
<p><a href="https://www.boplatssverige.se/">Boplats Sverige</a><br />
Helps you find somebody to switch apartment with - if you already have a place. Page in Swedish.</p>
</li>
<li>
<p><a href="https://www.blocket.se/">Blocket.se</a><br />
Classifieds where you can buy and sell everything between heaven and earth. Also apartments for rent. If you are looking for something, start by choosing a region, then a city from the map on the frontpage. After that, choose what you are interested in from the menu. If you are looking for a place to live you might want to look for:<br />
Lägenheter = Apartments<br />
Fritidsboende = A kind of holiday or summer house.<br />
Tomter & Gårdar = Empty grounds and farm/country estates<br />
Villar & Radhus = Larger and smaller houses<br />
Säljes = For sale<br />
Uthyres = For rental<br />
Bytes = For exchange<br />
Köpes = Want to buy<br />
önskes hyra = Want to rent</p>
</li>
<li>
<p><a href="https://sv.wikipedia.org/wiki/Kategori:Svenska_fastighetsbolag">Swedish housing companies</a><br />
Every larger town has at least one housing company that rents out apartments. Here you’ll find a list of them (in Swedish).</p>
</li>
<li>
<p><a href="https://www.hotels.com/">Hotels.com</a><br />
Has many hotel offers in Sweden, though not necessarily the cheapest. Page in English and others.</p>
</li>
<li>
<p><a href="https://www.skatteverket.se/">Skatteverket</a><br />
The Swedish tax office. Moving to Sweden doesn’t mean you avoid this aspect of life, though you might just agree that you get a lot of value for your money. Page in English, Swedish and others.</p>
</li>
<li>
<p><a href="https://www.nordisketax.net/">Nordisk eTax</a><br />
About taxation rules in the Nordic countries. Page in English, Swedish and others.</p>
</li>
</ul>
Moving to Sweden, mostly for Danes2008-01-17T13:34:58Zhttps://www.clausconrad.com/blog/moving-to-sweden-mostly-for-danes/<ul>
<li><a href="https://www.oresunddirekt.com/">ØresundDirekt</a>
Mostly for Danes and Swedes from the border region (Copenhagen/Skåne). Information about the differences between the countries, living in one country and working in the other etc. Page in Swedish and Danish.</li>
</ul>
Everyday shopping in Sweden2008-01-17T13:32:57Zhttps://www.clausconrad.com/blog/everyday-shopping-in-sweden/<p>Sweden is one of the more expensive countries in Europe, but it is also on the forefront of new technologies and services. For example, supermarkets are starting to offer home delivery and internet shopping! Chains and smaller immigrant-driven shops offer rich asortments of food from all over the globe at affordable prices.</p>
<h2 id="larger-supermarket-chains" tabindex="-1">Larger supermarket chains</h2>
<ul>
<li><a href="https://www.coop.se/">Coop</a></li>
<li><a href="https://www.hemkop.se/">Hemköp</a></li>
<li><a href="https://www.ica.se/">ICA</a></li>
<li><a href="https://www.lidl.se/">LIDL</a></li>
<li><a href="https://www.netto.se/">Netto</a></li>
<li><a href="https://www.willys.se/">Willy’s</a></li>
</ul>
<h2 id="specialized-price-comparison-sites" tabindex="-1">Specialized price comparison sites</h2>
<ul>
<li><a href="https://www.bokfynd.nu/">bokfynd.nu</a><br />
This site compares book prices from different vendors. Save some money on those books for your study.</li>
<li><a href="https://www.matsmart.se/">Matsmart</a>
Sells food and other goods that are surplus or about to expire, but still good, at solid discounts</li>
<li><a href="https://www.prisjakt.nu/">Prisjakt</a>
This site compares prices for almost anything you can buy online in Sweden.</li>
</ul>
Holiday in Sweden2008-01-17T13:31:42Zhttps://www.clausconrad.com/blog/holiday-in-sweden/<p>Whenever possible I try to link to the English version of the pages, but some of them are in Swedish only. Just try to use the dictionaries from my list (see my story “Links: Swedish language”) or ask in the forums or me if you have trouble understanding something :-)</p>
<p>Unfortunately I haven’t really been on holiday in Sweden for more than a weekend, so if you have some good links, please add a comment!</p>
<ul>
<li>
<p><a href="https://www.visitstockholm.com/">Visit Stockholm</a><br />
For tourists, in English and Swedish.</p>
</li>
<li>
<p><a href="https://yasuragi.se/">Yasuragi</a><br />
This is a Zen-buddhistic inspired wellness place near Stockholm. I haven’t visited it, but been recommended it by friends. Page in English and Swedish.</p>
</li>
</ul>
News and radio from Sweden2008-01-17T13:30:11Zhttps://www.clausconrad.com/blog/news-and-radio-from-sweden/<p>I hope there is something of interest to you, whether you are thinking of moving to Sweden or just need some help for your vacation!</p>
<p>Whenever possible I try to link to the English version of the pages, but some of them are in Swedish only. Just try to use the dictionaries from my list (see my story <a href="../swedish-language/">Swedish language</a>) or ask in the forums or me if you have trouble understanding something :-)</p>
<p>If you have some good links, please add a comment!</p>
<ul>
<li>
<p><a href="https://www.thelocal.se/">The Local</a><br />
Swedish news in English.</p>
</li>
<li>
<p><a href="https://sverigesradio.se/">SR</a><br />
Largest Swedish radio broadcaster. Page in English and Swedish.</p>
</li>
</ul>
Public transport in Sweden2008-01-17T13:27:06Zhttps://www.clausconrad.com/blog/public-transport-in-sweden/<p>Whenever possible I try to link to the English version of the pages, but some of them are in Swedish only. Just try to use the dictionaries from my list (see my story “Links: Swedish language”) or ask in the forums or me if you have trouble understanding something :-)</p>
<p>Getting around using public transportation is easy and fast in Sweden, although it might be a tad expensive, depending on where you come from.</p>
<ul>
<li>
<p><a href="https://www.sj.se/en/home.html#/">SJ</a><br />
Swedish Railways. In English and Swedish.</p>
</li>
<li>
<p><a href="https://www.sas.se/">SAS</a><br />
Popular airline from/to and in Sweden. Page in English and Swedish.</p>
</li>
<li>
<p><a href="https://www.swedavia.com/arlanda/">Stockholm-Arlanda airport</a><br />
Timetables etc. Page in English and Swedish.</p>
</li>
<li>
<p><a href="https://www.swedavia.com/malmo/">Malmö airport</a><br />
Timetables etc. Page in English and Swedish.</p>
</li>
<li>
<p><a href="https://www.oresundsbron.com/en/start">Øresund Bridge</a><br />
About the bridge between Sweden and Denmark. Page in English, Swedish and others.</p>
</li>
</ul>