Opinionated LogicPersonal thoughts, (il)logically considered.Zola2024-02-16T13:01:00-05:00https://orville.thebennettproject.com/atom.xmlHow Akamai Linode helped me find a better hosting deal2024-02-16T13:01:00-05:002024-02-16T13:01:00-05:00
Unknown
https://orville.thebennettproject.com/articles/how-akamai-linode-helped-me-find-better-hosting/<p>While writing up my previous post on <a href="https://orville.thebennettproject.com/articles/fix-apple-mail-invalid-email-address-error/">fixing a terrible Apple Mail bug</a>, I stumbled into a rant. It blossomed from a throwaway line, to become a reference, which turned into a paragraph, and finally birthed a full blown post. So here it is. My explanation of why I moved on from Linode's <q>really quite good</q> hosting, and why, perhaps, you should too.</p>
<p>To start, this is not a story about how terrible Linode as a company is, or how horrible their service has become under Akamai stewardship. What's that you say? You didn't know that <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.linode.com/blog/linode/linode-and-akamai/">Akamai acquired Linode</a> a few years ago? Yeah man, for almost <a rel="noopener nofollow noreferrer" target="_blank" href="https://archive.nytimes.com/dealbook.nytimes.com/2012/04/09/facebook-buys-instagram-for-1-billion/">a whole Instagram</a>. Congrats to caker on the exit by the way. </p>
Fix Apple Mail's 'Invalid Email addres. Please enter a valid email address for this account' error2024-02-16T11:52:00-05:002024-02-16T11:52:00-05:00
Unknown
https://orville.thebennettproject.com/articles/fix-apple-mail-invalid-email-address-error/<p>Having finished a recent migration to a new email server (goodbye, Linode) I started the process of updating my email clients. I had a wide swath of clients to update: K9 for android, Mail for iPadOS, Mail for Mac, Canary for iOS.</p>
Fix FreeBSD 'Address family not supported by protocol' error at dovecot startup2024-02-15T16:39:00-05:002024-02-15T16:39:00-05:00
Unknown
https://orville.thebennettproject.com/articles/resolve-address-family-not-supported-by-protocol/<p>I ran into an interesting error while rebuilding our e-mail infrastructure recently. Dovecot would not start in its FreeBSD 14.0 jail, even though the ports it was trying to listen on weren't being used.</p>
Presentation: I spent a year learning Rust to avoid a 5 minute PHP job2024-01-01T14:01:00-05:002024-01-01T14:01:00-05:00
Unknown
https://orville.thebennettproject.com/articles/i-spent-a-year-learning-rust-to-avoid-php-video/<p>This is a video of an <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.youtube.com/watch?v=_WKdR67-N7o">old talk</a>, based an on <a href="https://orville.thebennettproject.com/articles/i-spent-a-year-learning-rust-to-avoid-php/">older blog post</a>. </p>
<p>I'm posting a version here so I have it in case YT ever dies.</p>
Get serious about rust, by writing more rust2023-12-31T15:12:00-05:002023-12-31T15:12:00-05:00
Unknown
https://orville.thebennettproject.com/articles/getting-serious-about-rust/<h2 id="prologue">Prologue</h2>
<p>A few years ago I was working on a design system with a team that was in the midst of implementing a new color system. The system was mostly complete and what was left was documentation and tooling to ease working with, generating or modifying color tokens. We'd chosen to write these tools in <em>JavaScript</em> (JS).</p>
Relay emails from alpine container using SMTPHOST.2023-03-20T21:25:00-05:002023-03-20T21:25:00-05:00
Unknown
https://orville.thebennettproject.com/articles/send-emails-in-alpine-docker-container-by-using-smtphost/<p>I've been making more changes to my <a rel="noopener nofollow noreferrer" target="_blank" href="https://crates.io/crates/formulate">form API backend</a> recently, migrating the deployment environment from FreeBSD jails to <a rel="noopener nofollow noreferrer" target="_blank" href="https://code.orbitsolutions.dev/orb-it-solutions/formulate/src/branch/master/Dockerfile">Docker containers</a>. This isn't a post about that migration though. In the process of migrating I lost access to a fully featured sendmail binary. </p>
<p>If you'd like to see why sendmail specifically is so important to me, feel free to check out <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.youtube.com/watch?v=_WKdR67-N7o">this talk I gave last year</a> where I go through why I wrote the API in the first place, and how I tested it (which involves sendmail). </p>
<p>In Alpine Linux, which is what I use for <code>formulate</code>'s base docker image<sup class="footnote-reference"><a href="#1">1</a></sup>, sendmail is a part of <code>busybox</code><sup class="footnote-reference"><a href="#2">2</a></sup>. This means limited functionality for that version of sendmail, and this affected its ability to relay mail from within the docker container. When I tried using the built-in <code>sendmail</code> I was seeing a message similar to the following:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>sendmail: can't connect to remote host (127.0.0.1): Connection refused
</span></code></pre>
<p>The gist of that message is that sendmail is trying to send mail by connecting to localhost, which it's treating as a remote mail server. But there is no mail server listening on localhost.</p>
<p>One thing I could have done was install a separate application to handle relaying mail in the container. In fact, in my FreeBSD jail that is exactly what I did. The <code>sendmail</code> binary exists but does not get used. Instead, I configured <code>opensmtpd</code> to handle mail serving duties. I didn't want my docker image any bigger though, it was already <code>10.5 MB</code> and I was hoping to get to single digit sizes.<sup class="footnote-reference"><a href="#3">3</a></sup></p>
<p>I found out that instead of a configuration file I could use an environment variable—<code>SMTPHOST</code>—to point to an actual mail server to handle messages. That allowed me to use docker to set this environment variable and get form submissions sending via email again.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>docker run -it --rm -e SMTPHOST="mail.host.domain" -p 80:8000 formulate
</span></code></pre>
<hr />
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>Used as the base docker image primarily for its smaller attack surface.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="https://www.busybox.net/about.html">BusyBox</a> combines tiny versions of many common UNIX utilities into a single small executable.</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>I actually started off at <code>14.4 MB</code> but was able to shave some size off the rust binary by following some tips for creating smaller rust executables from the <a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/johnthagen/min-sized-rust">min-sized-rust</a> repository.</p>
</div>
Using MariaDB's binary log to restore a database after overwriting with old backup.2023-03-17T23:45:00-05:002023-03-17T23:45:00-05:00
Unknown
https://orville.thebennettproject.com/articles/how-to-use-mariadb-10-binlog-to-restore-database/<p>You've deleted your database. <strong>The</strong> database. Well, not <em>delete</em> per se, just unintentionally rolled it back to an almost year old backup. The specifics of how you managed such a tragically foolish thing aren't important (though it involved a very cute toddler and command line history). Unfortunately the deed is been done, and now you're left with the fallout. It's OK though. I've been there too, and I'm here to help. Actually, I've been there and the <code>binlog</code> was there to help. I'm just here to let you know about it. What even is a <em>binlog</em>, you ask? Keep reading dear traveller. Details 👇🏾</p>
<p>The binlog is the binary log. As I understand it, it is a file that describes database changes as a series of events. A main goal of the binary log is to allow replication to another database. An important consequence of the binary log's existence is that it makes certain kinds of data recovery possible. This particular recovery method will be available to <a rel="noopener nofollow noreferrer" target="_blank" href="https://mariadb.com/kb/en/overview-of-the-binary-log/">MariaDB</a> and <a rel="noopener nofollow noreferrer" target="_blank" href="https://dev.mysql.com/doc/refman/8.0/en/binary-log.html">MySQL users</a>. This information is in a binary format and not visible via a text editor, but there is the <code>mysqlbinlog</code> command that allows you to get at this data.</p>
<p>So here is the scenario I found myself in. I had migrated a database from one server to another at an earlier point in time. The database was backed up using the <code>mysqldump</code> command, sent to the new server, and imported using the <code>mysql</code> command. Successive database changes would create new binlog entries which would get added to the binlog index<sup class="footnote-reference"><a href="#1">1</a></sup>.</p>
<p>Some sample binlog entries are shown below.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>4.5K /var/db/mysql/mysql-bin.000067
</span><span>4.5K /var/db/mysql/mysql-bin.000068
</span><span>4.5K /var/db/mysql/mysql-bin.000069
</span><span>4.5K /var/db/mysql/mysql-bin.000070
</span><span>4.5K /var/db/mysql/mysal-bin.000071
</span><span>4.5K /var/db/mysql/mysql-bin.000072
</span><span>4.5K /var/db/mysql/mysql-bin.000073
</span><span>4.5K /var/db/mysql/mysql-bin.index
</span></code></pre>
<p>So a year or so passes after this database import occurs, and I decide its time to do another backup, but botch it. Binlogs generated during this time shown below:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>user@dbserver:~ $ du -sh /var/db/mysql/*
</span><span>231M databasic
</span><span>4.5K aria_log.00000001
</span><span>512B aria_log_control
</span><span>4.5K ib_buffer_pool
</span><span> 20M ib_logfile0
</span><span> 20M ib_logfile1
</span><span>4.7M ibdata1
</span><span> 77K ibtmp1
</span><span>512B multi-master.info
</span><span>878K mysql
</span><span>4.5K mysql-bin.000001
</span><span> 25K mysql-bin.000002
</span><span> 17K mysql-bin.000003
</span><span>4.5K mysql-bin.000004
</span><span> 49K mysql-bin.000005
</span><span>8.5K mysql-bin.000006
</span><span> 93K mysql-bin.000007
</span><span>573K mysql-bin.000008
</span><span>4.5K mysql-bin.000009
</span><span>4.5K mysql-bin.000010
</span><span>4.5K mysql-bin.000011
</span><span>353K mysql-bin.000012
</span><span> 85K mysql-bin.000013
</span><span>4.5K mysql-bin.000014
</span><span>4.5K mysql-bin.000015
</span><span>4.5K mysql-bin.000016
</span><span>4.5K mysql-bin.000017
</span><span>4.5K mysql-bin.000018
</span><span>4.5K mysql-bin.000019
</span><span>4.5K mysql-bin.000020
</span><span>4.5K mysql-bin.000021
</span><span>122M mysql-bin.000022
</span><span>4.5K mysql-bin.000023
</span><span>4.5K mysql-bin.000024
</span></code></pre>
<p><code>mysql-bin.000022</code> (binlog 22, <code>122M</code>) is where the initial database import happened, and every binlog entry larger than <code>4.5K</code> is where a database change of note was recorded in the binary log. I know this because the date of the database dump I accidentally imported roughly matches the creation time of binlog 22. The remaining binary logs are shown below:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span> 13M mysql-bin.000025
</span><span> 15M mysql-bin.000026
</span><span>129K mysql-bin.000027
</span><span>4.5K mysql-bin.000028
</span><span>4.5K mysql-bin.000029
</span><span>4.5K mysql-bin.000030
</span><span>4.5K mysql-bin.000031
</span><span>1.2M mysql-bin.000032
</span><span>177K mysql-bin.000033
</span><span> 77M mysql-bin.000034
</span><span> 56M mysql-bin.000035
</span><span> 50M mysql-bin.000036
</span><span> 94M mysql-bin.000037
</span><span> 47M mysql-bin.000038
</span><span> 50M mysql-bin.000039
</span><span> 10M mysql-bin.000040
</span><span>138M mysql-bin.000041
</span><span>118M mysql-bin.000042
</span><span> 97M mysql-bin.000043
</span><span> 70M mysql-bin.000044
</span><span> 85M mysql-bin.000045
</span><span> 81M mysql-bin.000046
</span><span> 60M mysql-bin.000047
</span><span> 45M mysql-bin.000048
</span><span> 10M mysql-bin.000049
</span><span>231M mysql-bin.000050
</span><span>4.5K mysql-bin.index
</span></code></pre>
<p>binlog 50 is where I goofed. </p>
<p>This meant I had a database created, a database dump imported, and binary logs of all the transactions of that initial import, and all transactions after it (up to and including my fateful import that reset things). </p>
<p>Now I'm no database guru or mariadb/mysql expert but once I learned about the binlog's existence, it was like gold to this man in the desert. Based on my understanding, I could (in theory) go through successive binlogs and recreate the database up to a certain point. Armed with a hypothesis I set out to test it. I've outlined the steps I took below.</p>
<ol>
<li>
<p>Take backup of existing state. (Yes, it's too late but it can't hurt).</p>
</li>
<li>
<p>Log in to database</p>
<ul>
<li><code>mysql -u root -p</code></li>
</ul>
</li>
<li>
<p>Check if binlog is enabled with <code>SHOW variables like '%bin%';</code></p>
<ul>
<li><code>log_bin</code> should be set to 'ON'.</li>
</ul>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>MariaDB [(none)]> show variables like '%bin%';
</span><span>+-----------------------------------------+-------------------------------+
</span><span>| Variable_name | Value |
</span><span>+-----------------------------------------+-------------------------------+
</span><span>| bind_address | xxx.xxx.x.xn |
</span><span>| binlog_annotate_row_events | ON |
</span><span>| binlog_cache_size | 32768 |
</span><span>| binlog_checksum | CRC32 |
</span><span>| binlog_commit_wait_count | 0 |
</span><span>| binlog_commit_wait_usec | 100000 |
</span><span>| binlog_direct_non_transactional_updates | OFF |
</span><span>| binlog_file_cache_size | 16384 |
</span><span>| binlog_format | MIXED |
</span><span>| binlog_optimize_thread_scheduling | ON |
</span><span>| binlog_row_image | FULL |
</span><span>| binlog_stmt_cache_size | 32768 |
</span><span>| encrypt_binlog | OFF |
</span><span>| gtid_binlog_pos | 0-1-3193671 |
</span><span>| gtid_binlog_state | 0-1-3193671 |
</span><span>| innodb_locks_unsafe_for_binlog | OFF |
</span><span>| log_bin | ON |
</span><span>| log_bin_basename | /var/db/mysql/mysql-bin |
</span><span>| log_bin_compress | OFF |
</span><span>| log_bin_compress_min_len | 256 |
</span><span>| log_bin_index | /var/db/mysql/mysql-bin.index |
</span><span>| log_bin_trust_function_creators | OFF |
</span><span>| max_binlog_cache_size | 18446744073709547520 |
</span><span>| max_binlog_size | 1073741824 |
</span><span>| max_binlog_stmt_cache_size | 18446744073709547520 |
</span><span>| read_binlog_speed_limit | 0 |
</span><span>| sql_log_bin | ON |
</span><span>| sync_binlog | 0 |
</span><span>| wsrep_forced_binlog_format | NONE |
</span><span>+-----------------------------------------+-------------------------------+
</span><span>29 rows in set (0.010 sec)
</span></code></pre>
</li>
<li>
<p>Delete existing database</p>
<ul>
<li><code>DROP DATABASE databasic;</code></li>
</ul>
</li>
<li>
<p>Create new database</p>
<ul>
<li><code>CREATE DATABASE databasic CHARACTER SET utf8 COLLATE utf8_general_ci;</code></li>
</ul>
</li>
<li>
<p>Log out of the database</p>
</li>
</ol>
<p>Next came the tricky part. I'd determined that <code>mysql-bin.000022</code> was where I needed to start but I wanted to start from the very start of the dump from a year ago. You don't actually know where the binlog entries start though, <em>until you check</em>. There's a <code>--start-position</code> flag to <code>mysqlbinlog</code> that allows you to pass a position.</p>
<p>To know what position to start at, you view the binlog and scroll through looking for the beginning transaction. Since there were a lot of database transactions I needed to pipe the output to a pager like <code>more</code>.
e.g. <code>mysqlbinlog -d databasic mysql-bin.000022 | more</code>.</p>
<p>After a long bit of searching I found the start position and started rebuilding the database with the following steps:</p>
<ol>
<li>
<p>Pipe output of <code>mysqlbinlog</code> to <code>mysql</code> for your database of choice.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>mysqlbinlog -d databasic mysql-bin.000022 --start-position=2904 | mysql -u root -p databasic
</span><span>mysqlbinlog -d databasic mysql-bin.000023 | mysql -u root -p databasic
</span><span>mysqlbinlog -d databasic mysql-bin.000024 | mysql -u root -p databasic
</span><span> ...
</span><span>mysqlbinlog -d databasic mysql-bin.000047 | mysql -u root -p databasic
</span></code></pre>
</li>
<li>
<p>If any of the commands fail (as they did for me) because some database columns already existed, view that binlog, find the transaction that its complaining about and note the position. Then start the import into the database at the transaction <em>after</em> that one. <sup class="footnote-reference"><a href="#2">2</a></sup></p>
</li>
</ol>
<p>Now there's a better way to do this sort of thing. It's to back up your data and I don't even have an excuse for not backing it up automatically because I've written a script that does this (and verifies that the backup is good using docker). I just didn't set it up 😬.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>The binlog index is a file which allows <code>mariab</code>/<code>mysql</code> to know what the next created binlog number should be. </p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>This worked well for me until binlog 47. I started getting more errors so I called it a day and went to bed. Losing a two days of data was far more acceptable than a year. I'm no database guru as I said, so there may be an even better way to do this. If you know one, feel free to share using the <a href="https://orville.thebennettproject.com/contact/">contact page</a> or <a rel="noopener nofollow noreferrer" target="_blank" href="https://social.vivaldi.net/@illogical">mastodon</a>.</p>
</div>
I spent a year learning Rust to avoid a 5 minute PHP job2022-03-03T18:01:00-05:002022-03-03T18:01:00-05:00
Unknown
https://orville.thebennettproject.com/articles/i-spent-a-year-learning-rust-to-avoid-php/<p>Welcome, dear traveller. Today I will regale you with a tale of perseverance, triumph over the odds, but mostly a tale of laziness that was enabled by the <a rel="noopener nofollow noreferrer" target="_blank" href="https://doc.Rust-lang.org/stable/book/">Rust programming language</a>.</p>
GatsbyJS v4 no longer allows directly modifying or mutating nodes in onCreateNode2021-12-05T22:09:00-05:002021-12-05T22:09:00-05:00
Unknown
https://orville.thebennettproject.com/articles/gatsby-v4-directly-changing-nodes-in-oncreatenode-fails/<p>Wooooo buddy! Did I have some debugging fun this weekend guys. Let's talk about Gatsby—the React framework for building single page web applications, not the literary novel.</p>
<p>I had occasion recently to start upgrading a project from Gatsby version 3 to version 4. The upgrade was going fine until I started querying Gatsby's <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.gatsbyjs.com/docs/glossary/graphql/">GraphQl API</a> for image nodes that it should have been creating <sup class="footnote-reference"><a href="#1">1</a></sup>. The way the project is set up, custom image nodes should have been getting created by a plugin based on the <code>featured_image</code>s set for a post. </p>
<p>What was happening instead was that after an initial run of <code>gatsby clean</code> and <code>gatsby develop</code> commands the images would be present. On subsequent <code>gatsby develop</code> runs the images would <em>not</em> be there. Crap. </p>
<p>I had read the upgrade guide before starting and it sounded similar to something I saw in there, so I went back to check. <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.gatsbyjs.com/docs/reference/release-notes/migrating-source-plugin-from-v3-to-v4/#2-data-mutations-need-to-happen-during-sourcenodes-or-oncreatenode">There <em>was</em> a section</a> mentioning that while directly modifying nodes would work, it was never an <em>intended</em> way to make these changes. Unfortunately, <em>it did work</em> and became a popular way to do these kind of changes. In version 4 this was no longer allowed though. Oops.</p>
<p>I decided it was time to go looking directly at the plugin I was using for how it was changing nodes. <a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/styxlab/gatsby-theme-try-ghost/blob/961dff3d4d1ca64c352eda8f8462c1db6607f196/packages/gatsby-plugin-ghost-images/src/gatsby-node.js#L74">Sure enough</a> it was directly modifying nodes in the <code>onCreateNode()</code> API method. This seemed like a great place to make some changes, so I did but ... that didn't fix things!</p>
<p>Fortunately I wasn't very far off. A bit more spelunking in Gatsby's discord channel (where they have a room specifically for v4 upgrades) and I found <a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/gatsbyjs/gatsby/discussions/33831">an issue</a> that led me down the correct path. What I had missed was modifications to the the custom type that was created along with the node in the <code>createSchemaCustomization()</code> API method.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>Sigh. This is an entire rabbit hole in and of itself. You see, Gatsby provides data on the backend via a <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.gatsbyjs.com/docs/why-gatsby-uses-graphql/">GraphQL API</a>.</p>
</div>
How TypeScript (JavaScript) and Rust helped me become a better Swift developer2021-09-14T20:10:00-05:002021-09-14T20:10:00-05:00
Unknown
https://orville.thebennettproject.com/articles/how-typescript-javascript-rust-helped-me-become-a-better-swift-developer/<p>I've had this idea floating around in my head for a while on how knowledge of, and familiarity with, one programming language can help you learn another. Maybe something to give as a presentation. Before that I need to get the idea down, so that's this post. Below I list the languages and the features from them, that helped me learn comparable (to my mind) concepts in Swift. Let's jump in.</p>
Assessing whether my teen should get the SARS-Cov2 (COVID-19) vaccine2021-08-14T22:55:00-05:002021-08-14T22:55:00-05:00
Unknown
https://orville.thebennettproject.com/articles/assessing-whether-my-teen-should-get-the-sars-cov2-vaccine/<p>My wife tasked me with reading up on COVID-19 vaccines to see if they were safe for our oldest to take. I, not being one to shy away from the opportunity to spend a day or so reading papers, jumped at the opportunity!</p>
My life: the early years2021-04-21T19:13:00-05:002021-04-21T19:13:00-05:00
Unknown
https://orville.thebennettproject.com/articles/my-life-the-early-years/<p>Hey there kiddo. So I feel like telling a story. Would you like to hear a story? I'm going to tell you a story. This particular story though is all mine. <strong>C'est</strong>, <em>l'histoire de moi</em>. I'll start it off with my earliest, favoritest, most pleasant memory. It's of my dad.</p>
Fix git-lfs smudge error: Error downloading file, object does not exist on server2021-04-02T19:13:00-05:002021-04-19T10:00:00-05:00
Unknown
https://orville.thebennettproject.com/articles/git-lfs-smudge-error/<p>I ran into this problem recently, when attempting to migrate a repository (repo) from my personal gitea instance to github. It started innocently enough. I had a git repository and wanted to test parallel test runs with <a rel="noopener nofollow noreferrer" target="_blank" href="https://cypress.io">cypress</a>. The CI provider I was using (<a rel="noopener nofollow noreferrer" target="_blank" href="https://www.drone.io">drone</a>), did not support this feature and, after speaking with the cypress folks, they suggested trying with github actions. Sure. Why not. Should be easy. Little did I know this would lead me down a <a rel="noopener nofollow noreferrer" target="_blank" href="https://git-lfs.github.com">git-lfs</a> sized rabbit hole.</p>
Mac apps I love2021-03-17T01:11:24-05:002021-03-17T01:11:24-05:00
Unknown
https://orville.thebennettproject.com/articles/mac-apps-i-love/<p>It's listicle time! What follows is a list of software I keep coming back to on my macs. You could call them essential. You could call them important. You <em>could</em> even go so far as to say that I ❤️ them.</p>
Command line nirvana2021-03-16T01:19:00-05:002021-03-16T01:19:00-05:00
Unknown
https://orville.thebennettproject.com/articles/command-line-nirvana/<p>I've been using command line interface (CLI) applications for quite some time, but I feel like with the emergence of the <a rel="noopener nofollow noreferrer" target="_blank" href="https://golang.org/">Go</a> and <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.rust-lang.org/">Rust</a> programming language communities we are currently in a golden age of command line usage.</p>
My week with Coronavirus (SARS-Cov2)2021-02-06T17:52:00-05:002021-03-13T12:29:00-05:00
Unknown
https://orville.thebennettproject.com/articles/my-week-with-coronavirus/<p>Hello there online traveller! I have not written in a long time, so it is good to see you're still here! It has certainly been a wild ride since we last corresponded. Like many of you, I made it through 2020 without contracting SARS-CoV2. (yay us!). </p>
What to do after you blow your (git) stash2020-04-25T23:37:00-05:002020-04-25T23:37:00-05:00
Unknown
https://orville.thebennettproject.com/articles/what-to-do-after-you-blow-your-git-stash/<h2 id="i-just-blew-my-stash">I just blew my stash!</h2>
<p>So I had occasion to be doing some code cleanup late at night and I accidentally deleted some git stashes I had around. Now the code was super important, I didn't actually remember what was in those stashes. But this was git so I figured I could get it back.</p>
<p>My first thought was to use the reflog, but a <code>git reflog</code> didn't show any signs of my stashes. That's when I went to DuckDuckGo to find out! My search to <em>recover deleted git stash</em> took me to s <a rel="noopener nofollow noreferrer" target="_blank" href="https://stackoverflow.com/questions/89332/how-to-recover-a-dropped-stash-in-git">stackoverflow answer</a>. </p>
<p>The solution was using a git command I was not yet familiar with (but now have a lot more reason to find out more about).</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>git fsck --no-reflog | awk '/dangling commit/ {print $3}'
</span></code></pre>
<p>The important part was the <code>awk</code> command searching for the "dangling" string along with the <code>--no-reflog</code>.</p>
Functional Faith: Week 32018-10-08T15:30:00-05:002018-10-08T15:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/functional-faith-week-3/<p>The next sermon in the Functional Faith series is up. Enjoy! (Still no subtitles).</p>
<video class="img-responsive" preload="metadata"
controls
poster="/images/functional_faith.jpg" width="100%" height="100%">
<source src="/videos/2018_10_07_functional_faith_week3.mp4" type="video/mp4; codecs="avc1.42E01E, mp4a.40.2"" />
<source src="/videos/2018_10_07_functional_faith_week3.webm" type="video/webm; codecs=vp8, vorbis" />
</video>
The proper way to update FreeBSD jails between point releases2018-10-08T01:03:00-05:002018-10-08T01:03:00-05:00
Unknown
https://orville.thebennettproject.com/articles/the-proper-way-to-update-freebsd-jails/<p>As I've mentioned before, FreeBSD has this concept of a <q>jail</q> which allows you to isolate an environment from the host operating system. This isolation keeps the rest of the system safe from whatever is being run inside of the jail. You can liken it to running an application in a virtual machine, but without the overhead of emulating a computer within another computer. </p>
<p>I thought it would be useful to document using the <code>ezjail-admin</code> application to update jails <q>the right way</q>. And, while we're at it, show how to recover from doing it <q>the wrong way</q>. So without further ado:</p>
<h2 id="updating-jails-between-point-releases">Updating jails between point releases</h2>
<p>Run the following steps to get the jail host updated to the next point release of FreeBSD. For example, if you are on FreeBSD 11.1 and are trying to update to FreeBSD 11.2.</p>
<ol>
<li>freebsd-update fetch</li>
<li>freebsd-update install</li>
<li>Reboot.</li>
<li>Repeat steps 1-3 until no more updates are available.</li>
<li>freebsd-update upgrade -r 11.2-RELEASE</li>
<li>Merge any configs that need to be merged.<sup class="footnote-reference"><a href="#1">1</a></sup></li>
<li>Reboot.</li>
<li>freebsd-update fetch</li>
<li>freebsd-update install</li>
</ol>
<p>Once the host machine has been updated, the <em>next</em> step is to update your jails. The simplest way to do this is using the <code>ezjail-admin update -U -s $FREEBSD_VERSION</code> command. BUT. It's very easy to mess up the upgrade by glossing over the instructions in the ezjail-admin manual.</p>
<blockquote>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span> -U Use freebsd-update(8) to upgrade the basejail to the hosts
</span></code></pre>
</blockquote>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span> operating system version, or a version you may pass freebsd-
</span><span> update's call to “uname -r” via the UNAME_r environment variable.
</span><span> Since there currently is no way of inferring the osversion
</span><span> currently installed in the basejail, you need to remember the
</span><span> original osversion and pass it to this script using the -s
</span><span> option.
</span></code></pre>
<blockquote>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span> -s sourcedir | sourceosversion
</span></code></pre>
</blockquote>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span> In the -b and -i case: Use the sources in sourcedir instead of
</span><span> /usr/src. Variable: “$ezjail_sourcetree”.
</span><span> In the -U case: Pass this release tag to freebsd-update(8) as the
</span><span> source OS version of the basejail.
</span></code></pre>
<p>You might be tempted to pass the version you want to upgrade to as the parameter to <code>-s</code>. This would be wrong. Instead, you need to pass the version that you are <strong>upgrading from</strong>. So, if your jail is currently on FreeBSD 11.1 the command to upgrade to FreeBSD 11.2 is as follows:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ezjail-admin update -U -s 11.1-RELEASE
</span></code></pre>
<p>After finishing this update you should be able to finish upgrading the packages within your jail using these steps: </p>
<ol start="7">
<li><code>ezjail-admin console $name_of_jail_here</code></li>
<li><code>pkg upgrade</code></li>
<li>Say yes to prompts as is necessary.</li>
<li>Restart running services as necessary
<ul>
<li>Or, restart the entire jail via <code>ezjail-admin restart $name_of_jail_here</code></li>
</ul>
</li>
<li>Verify that services are still running.</li>
</ol>
<p>After that everything should be up to date and you'll be ready to move on to other tasks.</p>
<h2 id="recovering-after-updating-jails-between-point-releases-incorrectly">Recovering after updating jails between point releases incorrectly</h2>
<p>So you screwed up. You didn't read the manual closely enough<sup class="footnote-reference"><a href="#2">2</a></sup>. And instead you ran this <strong>incorrect command</strong>:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ezjail-admin update -U -s 11.2-RELEASE
</span></code></pre>
<p>Now when you try to do a <code>pkg upgrade</code> in your jail(s) you get a message saying you need to set some environment variable because userland and kernel are out of sync. Or when you try to build a port, your jail will think you are still on a previous version of FreeBSD and give you the following message:</p>
<blockquote>
<p>Ports Collection support for your FreeBSD version has ended, and no ports are guaranteed to build on this system. Please upgrade to a supported release.</p>
</blockquote>
<p>I <em>could</em> have solved this by using ZFS' facilities to roll back the basejail to its previous state, and then run the correct command. I was short on time however. Instead I just used the <code>ezjail-admin install</code> command to overwrite the existing basejail with the correct version. </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ezjail-admin install -r 11.2-RELEASE
</span></code></pre>
<p>After doing that, I was able to run the following commands to update my jails:</p>
<ol start="7">
<li><code>ezjail-admin console $name_of_jail_here</code></li>
<li><code>pkg upgrade</code></li>
<li>Say yes to prompts as is necessary.</li>
<li>Restart running services as necessary
<ul>
<li>Or, restart the entire jail via <code>ezjail-admin restart $name_of_jail_here</code></li>
</ul>
</li>
<li>Verify that services are still running.</li>
</ol>
<h2 id="beadm-a-better-way-to-update-freebsd">beadm: A better way to update FreeBSD?</h2>
<p>FreeBSD comes with ZFS support baked in and I've heard that Solaris admins use this thing called <code>beadm</code> to help update their ZFS systems. It's also available in FreeBSD, so next time I might try using <code>beadm</code> when updating. Instructions on <a rel="noopener nofollow noreferrer" target="_blank" href="https://dan.langille.org/2015/03/13/upgrading-from-freebsd-9-3-to-freebsd-10-1-using-beadm-and-freebsd-update/">how to update FreeBSD using beadm and freebsd-update</a> are given in Dan Langille's Other Diary.</p>
<p>Have questions? Comments? @reply to @opinion8d_logic on twitter with the hashtag #therightway.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>This is actually the tricky part in the whole thing. If you are not familiar with merging , take your time and do it carefully.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>All credit for finding the correct solution goes to <a rel="noopener nofollow noreferrer" target="_blank" href="https://forums.freebsd.org/threads/ports-in-jail-after-upgrade-ports-collection-support-for-your-freebsd-version-has-ended.64620/">this guy on the FreeBSD forums</a>.</p>
</div>
Guatemala Mission Trip 2018: Day 22018-09-30T23:30:00-05:002018-09-30T23:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/guatemala-mission-trip-2018-day-2/<p>Breakfast! That's a wonderful way to start of your day if you can manage it. And I did on the second day here. Before we came to Guatemala we sort of had an itinerary of what was going to be done. It's always emphasized by the leaders that we've got to be flexible though, because once we get to the village plans can change at any point. </p>
<p>I had "signed up" for construction of a wall by the church structure. When we got to Los Chilitos though, that was no longer a feasible project. The construction project was going to be in the other village we were serving: "The 46".<sup class="footnote-reference"><a href="#1">1</a></sup> Instead of a wall we'd be putting the roof on top of a church structure. But before that could be done supplies had to be gathered. Those lucky few chosen for that task were up and out 6 a.m. Poor guys. After grabbing supplies, they headed off to <em>The 46</em> to start on the roof. </p>
<p>The rest of the "construction crew" and everyone else, were taken to <em>Los Chilitos</em> and helped with the medical clinic and Kids Fest <sup class="footnote-reference"><a href="#2">2</a></sup> activities, that were already planned. After a very bumpy bus ride up we got out and I started walking around while other people did useful things. I noticed some pigs and goats on the hill overlooking the church property. The pigs I saw here were the skinniest pigs I had ever seen in the history of ever. Someone explained that this was actually a sign of things improving in the village. This meant that they could afford to buy animals to raise and, I can only assume, eat. </p>
<p>I didn't occur to me to ask about the purpose as I was still focused on how decrepit and malnourished these pigs looked. I mean, standard operating procedure for a pig is "to be fat". If pigs were to give out resumes to prospective owners under goals they'd have: "Getting fat. By any means necessary". Pigs, eat almost anything. But this thing was <em>gaunt</em>. Just look at it:</p>
<p><img src="/images/img_20180619_village_ham.jpg" alt="Village Ham" /></p>
<p>On somewhat related note, I also saw malnourished goats. Goats <em><strong>literally</strong></em> eat anything. Seriously. When I was a kid my grandfather brought a goat home once. I took it upon myself to feed the goat by hand every now and then, and this thing ate every kind of leaf I gave it. I started wondering if there was anything this goat <em>wouldn't</em> eat. Being the inquisitive type, I took some mango leaves, rolled up some of its poop pellets and fed 'em right to it. And you know what? It ate them. Pellets and all.<sup class="footnote-reference"><a href="#3">3</a></sup> But I digress.</p>
<p>After leaving the bus we started to make our way up to the school where Kids Fest would take place. Some of the kids came out to greet the team and ham it up for pictures. They were really cute.</p>
<p><img src="/images/img_20180619_kids_smile.jpg" alt="Kids Welcoming Team" /></p>
<p>This particular band of brothers couldn't wait to be in front of the camera. </p>
<video class="img-responsive" preload="metadata"
controls
poster="/images/img_20180619_band_of_brothers.jpg" width="100%" height="100%">
<source src="/videos/20180619_band_of_brothers.mp4" type="video/mp4; codecs="avc1.42E01E, mp4a.40.2"" />
<source src="/videos/20180619_band_of_brothers.webm" type="video/webm; codecs=vp8, vorbis" />
</video>
<p>Eventually, most of the kids were corralled into the hallway of the school and the Kids Fest Team began by reading a bible story, which was then translated (into Spanish) for the children by the translators who accompanied us.</p>
<p><img src="/images/img_20180619_kids_fest.jpg" alt="Kids Fest" /></p>
<p>We did a few other activities with the kids in their classrooms, and then broke for lunch. When we returned I was conscripted into the prayer team. At this point you might be wondering, <q>What's a prayer team doing at a clinic?</q> Well, I'm glad you asked. The folks in Los Chilitos are poor, sure (see pig above). And, while it's easy to focus on their material poverty,<sup class="footnote-reference"><a href="#4">4</a></sup> <strong>that's not the point of a mission trip</strong>. </p>
<p>The goal was not to feed the body—though the church does give to provide school lunches for the children—but to feed the spirit. We went hoping, <em>and praying</em>, to get opportunities to introduce these people to Christ. To open their eyes to a <em>relationship</em> with <strong>a God who cares about them, loves them, and wishes to see them living a life free of sin</strong>. This is a departure from the empty rituals of religion which do nothing to draw us closer to God or please him. </p>
<p>The clinic provided another avenue for us to show this. People came with medical needs, and we had nurses and nurse practitioners who were able to do whatever it is that nurses and nurse practitioners do. (I'm fairly certain it involved medicine and the like.) But once they left the clinic, there was also someone present to ask if they had anything they wanted/needed prayer for. Having addressed the physical body, we also tried to address the spiritual needs, by praying for them, and pointing them (back) to Jesus. To me, it seemed very appreciated and needed.</p>
<p>Shortly before the clinic ended we were called over to the high school to help out with The Uprising <sup class="footnote-reference"><a href="#5">5</a></sup> activities. After that we attended another church service and, I really wish I had recorded it. To say that God's presence could be felt in that place is an understatement. </p>
<p>Following this, most of the team went back to the hotel to clean up and eat, but a few of us hung around for a "workshop". The original pitch is that we were asked to teach them how to be missionaries. Different individuals were tasked with preparing something in that vein. I chose to use specific moments from the early Acts church for guidance on how to deal with various things those early missionaries encountered; things all missionaries likely still encounter today. </p>
<p>I didn't use any of that though. Ultimately, I didn't prepare well enough to bring that message so instead I just wung it. In the end it was really just a few of us sharing our stories of how God had changed our lives, leading us down the path to where we were able to be doing missions in Guatemala. Maybe I'll post what I <em>planned</em> to say in my next blog. </p>
<p>At the end of experience we prayed, left our hosts, drove back to our hotel in Cuilapa, grabbed some food then called it a night.</p>
<p>Also, check out this cute baby.</p>
<p><img src="/images/img_20180619_all_smiles.jpg" alt="Cute baby" /></p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p><em>Interesting name for a village</em>, Amirite?</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>Kids Fest is essentially our church's term for "Group activities designed to engage kids and introduce them to the gospel in a, hopefully fun, but also relevant way."</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>Hands down; this is my favorite goat story. I'm glad I got to share it with you.</p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">4</sup>
<p>It's oh so easy to focus on that. Look how long I spent talking about a starving pig.</p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">5</sup>
<p>The Uprising is the churches teen ministry. They have an age range but I couldn't tell you what it is. It's for the teens to the college aged kids.</p>
</div>
NPM can't verify certificate after man-in-the-middle tls inspection enabled2018-09-30T22:30:00-05:002018-09-30T22:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/npm-having-trouble-verifying-cert-after-ssl-inspection-enabled/<p>So, I have TLS <sup class="footnote-reference"><a href="#1">1</a></sup> inspection happening for some machines on my home network, including my development machine are among the machines where I allow this to happen.</p>
<p>While trying to install an <code>npm</code> package the other day I ran into some errors. After I checked the log file at <code>~/.npm/_logs/2018-09-22T04_08_03_137Z-debug.log</code> I found out some a potential culprit. The failure led to the following message being printed out::</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>silly fetchPackageMetaData error for gatsby-cli@latest request to https://registry.npmjs.org/gatsby-cli failed, reason: unable to verify the first certificate
</span></code></pre>
<p>Apparently <code>npm</code> was unable to verify the certificate. This makes sense as <code>npm</code> has it’s own certificate store, which my intercepting root certificate<sup class="footnote-reference"><a href="#2">2</a></sup> did not get added to. While I could have tried adding my root certificate to npm's global store, I decided to use npm's built in facilities to do the job.
I moved my root certificate file to <code>~/.certs</code> and pointed <code>npm</code> at it like so:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>npm config set cafile ~/.certs/root.pem
</span></code></pre>
<p>All credit to the <a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/npm/npm/wiki/Troubleshooting#ssl-error">NPM Wiki</a> for this solution.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>TLS stands for Transport Layer Security and the successor to SSL (Secure Socket Layer). TLS encryption is commonly used to protect web traffic from eavedropping.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>I can't even begin to do this justice in a sentence, so I'll just <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.quora.com/What-is-a-root-certificate">refer you to here</a> <a rel="noopener nofollow noreferrer" target="_blank" href="https://en.wikipedia.org/wiki/Root_certificate">and here</a>.</p>
</div>
Functional Faith: Week 22018-09-30T15:30:00-05:002018-09-30T15:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/functional-faith-week-2/<p>I decided to share this week's sermon from New Life Chapel while messing with autogenerated subtitles. The subtitle generation didn't work very well. But hey, this is a good message, so enjoy!</p>
<video class="img-responsive" preload="metadata"
controls
poster="/images/functional_faith.jpg" width="100%" height="100%">
<source src="/videos/2018_09_30_functional_faith_week2.mp4" type="video/mp4; codecs="avc1.42E01E, mp4a.40.2"" />
<source src="/videos/2018_09_30_functional_faith_week2.webm" type="video/webm; codecs=vp8, vorbis" />
</video>
Guatemala Mission Trip 2018: Day 12018-08-01T20:30:00-05:002018-08-01T20:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/guatemala-mission-trip-2018-day-1/<h2 id="day-1">Day 1!</h2>
<h3 id="wake-up">Wake up</h3>
<p>The 1st Day of a mission trip is always interesting. I say "always" even though I've only been one other time. <em>This</em> time, the interesting thing was that I seem to have gotten used to the sharp, piercing pain that I usually have on the right side of my face during take off and landing (yay!). I assume it's happens because of the change in altitude and maybe, barometric pressure <sup class="footnote-reference"><a href="#0">1</a></sup>. Something one would certainly want to get checked out after experiencing it once; let alone multiple times. The problem is by the time I've gotten home, not only is the pain gone, but everything else that's happened on the Mission trip is so much more important, that I just forget about it. Until it happens the next time.</p>
<p>The day began innocently enough with me getting out of bed at 3 a.m. for my 6 a.m. flight and blowing my nose. I brought along a box of tissues which served me well throughout the entirety of the trip. My wife was also intentional enough to get me kleenex packets to use whenever a giant box of tissues (which I carried with me the entire flight) wasn't so practical. The airport process was pretty boring. I opted for the cavity search, pardon me, "pat down" instead of the cancer machine<sup class="footnote-reference"><a href="#1">2</a></sup> as I typically do. </p>
<h3 id="layover-of-doom">Layover of Doom</h3>
<p>Enough about the mundane though, let's get back to why I'm writing here: documenting <strong>my <em>second</em> ever Missions Trip</strong>. I, along with the rest of the team from church <sup class="footnote-reference"><a href="#3">3</a></sup> boarded the plane at 6 a.m. EST. We then traveled from Dayton to Atlanta and had a 2-ish hour layover. We left Atlanta around 10 a.m. EST. Not exactly ideal for someone who, by this time, <strong>really</strong> wanted to sleep. But these are the kinds of sacrifices you make when you doing something more important than yourself. I suppose.</p>
<p>I mean, think about it, CEOs and salespeople do things like this all the time to get business. We were going out there to spread the Gospel; to change lives! What's a few sleepless hours compared to the opportunity to make and eternal impact in someone's life? Not a bad price to pay if you ask me. So yeah,I didn't like the layover, but it's OK. </p>
<h3 id="to-the-skies">To the skies!</h3>
<p>The flight to Guatemala was pretty standard, boring stuff. No one died. I did start to feel the beginnings of that tell-tale pain on the right side of my face. To my surprise, this time it didn't get so bad that the stewardess had to come to my seat asking if I was OK. I'm calling that a win! Either I was getting used to the pain or God had decided to grant me a reprieve. Whatever the reason, all I had to deal with was a stuffed up right ear for the remainder of the flight (and the first night in Guatemala).</p>
<p>By the way, one of the nice things about flying is you can see really cool things like the picture below. We were literally flying between the clouds. God's creation <sup class="footnote-reference"><a href="#4">4</a></sup> truly is a site to behold. Look at it!</p>
<p><img src="/images/img_20180618_wing_clouds.jpg" alt="Flying between the clouds" /></p>
<h3 id="we-re-alive">We're alive!</h3>
<p>We finally landed in Guatemala at around 12 p.m. local time. The customs rigoramole lasted about an hour and when we all got through we packed onto our chartered bus and made our way to lunch! The weather outside was perfect. The sun was out and as soon as we stepped out of the airport we were greeted by heat. Glorious heat. It was as if I was being welcomed back by the country with open arms. Well, that's how I felt at least. </p>
<p>Lunch was somewhere in Guatemala City. It was at a Bakery/Restaurant which was, if I recall correctly, San Martin. It was at the strip mall where the bakery was located that I violated my first piece of Guatemalan artwork. I'm pretty sure this was OK, no one said to stop...</p>
<p><img src="/images/img_20180618_giddyup.jpg" alt="Riding my first donkey" /></p>
<h3 id="to-the-village">To the Village</h3>
<p>After refueling (our bodies) it was time to head to the village in the city of Cuilapa where we would be serving: <em>Los Chilitos</em>. Arriving at the village in Los Chiitos was somewhat bittersweet. On one hand you saw this beautiful countryside. On the other you were faced with the people living in—what I'd consider—squalid conditions. Worse than that was the trash, and accompanying the poor sanitation was (of course) some completely avoidable sicknesses. </p>
<p>After a short stretch of the legs we went to the house of one of the first families that accepted Christ in the village. The conditions there were better than most, but it reminded me of visiting family in the rural parts of Jamaica when I was a kid: little to no electricity, unsophisticated home structures built using mainly wood and galvanized zinc roofing. But they were lived in and taken care of nonetheless. </p>
<p>There was a pride and contentment I would not have expected. In retrospect, it shouldn't have been unexpected. When you don't have the niceties of a first world country to compare yourself to, and you are focused on your most basic of needs, contentment, joy even, comes easily. They had already accepted Christ, fellow brothers in Christ had come to visit and assist in the mission. <em>What more did they need</em>?</p>
<h3 id="off-to-church">Off to church</h3>
<p>The answer, as ever, is Jesus! After a brief tour of the village we went across to the church and waited for others to show up for the church service. Apparently, we arrived on the same day a Cuban missionary pastor was scheduled to preach. Those of us who wished to stayed for the church service did so, while others went to the kids service at the house we had just come from. Below you can see the church building before it was set up.</p>
<p><img src="/images/img_20180618_church.jpg" alt="Church building" /></p>
<p>Set up was merely the addition of plastic chairs and a battery powered keyboard and, most importantly, people. People hungry for the <em>Word of God</em>. People who were being given hope, where previously there was none. While taking it all in it was important to keep in mind that the instrument of this change was not us. <strong>It was Jesus</strong>. We were merely tools being used to reach others and spread the word. Many had come before us, and it's likely that many would follow after we had left <sup class="footnote-reference"><a href="#5">5</a></sup>.</p>
<p>To the left of the church was a field with kids playing football<sup class="footnote-reference"><a href="#2">6</a></sup>. Not on a football field mind you. This was merely a dirt patch with makeshift goals and the jungle as the far border. It was amazing to be a part of a church service where you could see and hear people praise Jesus in spite of living conditions that, to me at least, are not very amenable to praise. </p>
<h3 id="resting-up-for-the-days-ahead">Resting up for the days ahead</h3>
<p>After the service ended we headed back to the hotel and the vast majority of folks headed to bed. Our hotel had some pretty flowers btw. Enjoy:</p>
<p><img src="/images/img_20180619_080637.jpg" alt="Yellow Flowers at Hotel in Cuilapa" /></p>
<p>Our hotel also had a pretty nice pool, in additions to the lizards in our rooms. It also had some pretty neat floral displays.</p>
<p><img src="/images/img_20180619_080653.jpg" alt="Partial pool shot at Hotel in Cuilapa" /></p>
<p>I was still partially deaf in my right ear so I figured sleep would do me some good and packed it in myself. That was pretty much how day one ended. </p>
<div class="footnote-definition" id="0"><sup class="footnote-definition-label">1</sup>
<p>And other sciencey weather words.</p>
</div>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">2</sup>
<p>I don't know that these (radiation) backscatter machines that I'm referring increase your chances of any kind of cancer. But given that they use radiation, which does increase your chances with each exposure, I'm just going to keep on skipping that instead of becoming a part of the eventual class action lawsuit should studies actually confirm my suspicions. I mean, it is essentially a game of math right? More exposure == increased likelhood.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">6</sup>
<p>Or, soccer for all the Americans in attendance.</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>New Life Chapel, which meets at Lakota West High School in West Chester, Ohio.</p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">4</sup>
<p>I'm referring to the Earth here, not mankind. This time.</p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">5</sup>
<p>We actually found out exactly how true that would be. The day we were flying out our guides stayed at the airport to get another (unaffiliated) group coming in. I've no idea what they were doing, but I know this: God had, and still does have a plan.</p>
</div>
Reset garbled terminal window on OS X2018-02-17T18:05:00-05:002018-02-17T18:05:00-05:00
Unknown
https://orville.thebennettproject.com/articles/reset-garbled-terminal/<p>I use the ruby program <code>rak</code> to recursively search directories for a text pattern. Occassionally when <code>rak</code> is done returning results it will scramble the terminal output into unreadable garbage. </p>
<p>The solution for this on OS X is to issue the following command:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>tput rmacs
</span></code></pre>
<p>Found this solution somewhere else initially, but now I've found it again <a rel="noopener nofollow noreferrer" target="_blank" href="https://superuser.com/questions/197764/reset-garbled-terminal-window-on-os-x#197783">at stackoverflow</a>.</p>
Robbing Peter (VZW) to pay Paul (T-Mobile)2017-11-25T22:35:00-05:002017-11-25T22:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/robbing-peter-to-pay-paul/<p>I like technology. It's kind of my thing. I do believe human use of computers will be the downfall of mankind but (besides that minor drawback), what computers—especially networked computers—allow us to accomplish as a civilization is actually quite amazing. After the release of the first iPhone there was something of revolution in the capabilities of tiny little networked computers. They could make phone calls—which I didn't particularly care about. They could be used for multimedia—like playing or listening to music. They could also access the internet at ever faster speeds, on increasingly larger screens. Information was literally at your fingertips. And that, more or less, is where this story begins.</p>
<h1 id="the-problem">The Problem</h1>
<p>I used to be a Verizon Wireless (VZW) customer. Through my employer I had a 20% discount on VZW cellphone service. I had just switched employers and my discount was about to expire. My wife and I would have gone from paying <code>$145</code>/month for 2 phones with unlimited talk, text, and 4 GB of shared data to paying ~<code>$170</code>/month for the same. Given our financial situation I had a choice to make: either give up a phone line, or find a better (or at the very least, cheaper) plan. After doing some research I went with the latter option.</p>
<h1 id="the-solution">The Solution</h1>
<p>We switched to <code>$30</code> per month T-Mobile prepaid plans. With 2 lines, we would end up saving at least <code>$1320</code> per year.</p>
<h1 id="the-math">The Math</h1>
<p>At <code>$170</code>/month our bill for the coming year would be $170 * 12 = $2040; an increase of <code>$300</code>/year.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>$170 * 12 = $2040
</span><span>$145 * 12 = $1740
</span><span>2040 - 1740 = 300
</span></code></pre>
<p>Instead of accepting that increase or moving down to 1 phone line between two people, I investigated switching to T-Mobile’s <code>$30</code>/month plan. At first this plan seemed only slightly inferior to VZW’s plan. It got us good enough service, unlimited texts and 5 Gb<sup class="footnote-reference"><a href="#1">1</a></sup> of 4G data per month, but only provided <em>100 minutes</em> of talk time per month.</p>
<p>Contrast that with just one line on Verizon and I would get unlimited minutes, unlimited texts and 2 Gb of 4G data for ~<code>$80</code>/month. <code>$80</code>/month for less data was not very appealing. And it became even less appealing once we realized we would get <strong>TWO</strong> <code>$30</code>/month lines with T-Mobile for <em>less than the cost of <strong>ONE</strong></em> line with Verizon.</p>
<h1 id="the-hickup">The Hickup</h1>
<p>The T-Mobile plan definitely seemed like the better deal. Still, 100 minutes is <em>not</em> a whole lot. I don’t actually speak to many people on the phone so the minutes didn’t matter as much for me; my wife ... not so much. I did have a solution for that as well though: Google Voice and an Android app called Talkatone. I had already been testing out T-Mobile <sup class="footnote-reference"><a href="#2">2</a></sup> and knew I could set up Talkatone with my Google Voice account to do VOIP calls. These are essentially phone calls that are made over the internet, which allow you to avoid using your cell phone minutes. I outline how I set this up below:</p>
<ul>
<li>Sign up for Google Voice</li>
<li>Order and recieve a T-Mobile SIM online</li>
<li>Activate SIM online</li>
<li>Choose the $30 plan</li>
<li>Get Talk-a-tone from the Google Play/ iOs App Store ($0.99/month)</li>
<li>Sign in with Google Voice</li>
<li>Makes calls with Talk-a-tone</li>
</ul>
<p>Having set up Talkatone with Google Voice, we could then enjoy free calls using our 4G data instead of cell service.<sup class="footnote-reference"><a href="#3">3</a></sup></p>
<h1 id="the-fallout">The Fallout</h1>
<p>I still had 18 months left on my own contract and about 4-5 on the other line so ETFs for both were quite sizeable: totalling <code>$370</code>. Add that to the <code>$145</code> for the current bill and I’d have to pony up <code>$515</code> before leaving VZW for good. Since the <code>$145</code> was already in the budget I’d have to find an extra <code>$370</code> or put it on a credit card, which is what I ended up doing. Nowadays T-Mobile even pays early termination fees when coming from competitors so this may not even be a cost you need to worry about.</p>
<h1 id="do-the-math">Do the Math</h1>
<p>This seemed like a heavy cost to pay, but based on savings for the first year of the plan, it was actually fine. <code>$1320</code> in savings minus the <code>$370</code> ETF was still <code>$950</code> saved over the course of a year. I decided it was worth it.</p>
<p>Based on anticipated savings we bought a new T-Mobile compatible phone. T-Mobile has 0% interest payment plans for those who qualify (depends on credit check). What we did at the time though was purchase a <code>$200</code> Moto G, and used that as the second line.</p>
<h1 id="setting-up-the-plan">Setting up the Plan</h1>
<p>After you've recieved your new <a rel="noopener nofollow noreferrer" target="_blank" href="https://prepaid-phones.t-mobile.com/prepaid-phone/t-mobile-prepaid-3-in-1-sim-starter-kit?icid=WMD_PD_Q317HOWTOJ_4HH9OW8FZO9552">T-Mobile prepaid SIM card</a>, you'll have to activate it with your new plan. Unfortunately, finding the <code>$30</code> plan on T-Mobile's site is a challenge. After receiving your SIM card and setting up service online at t-mobile.com, only then can you choose the <code>$30</code>/month plan.</p>
<h1 id="update">Update</h1>
<p>Three years later, I've actually switched again to a T-Mobile MVNO called <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.mintsim.com">Mintsim</a>. Our current monthly bill? <code>$20</code> per month for each person. This plan provides unlimited talk, unlimited text and 5 Gb of 4G data. If you think it's too good to be true, there is a catch. I pay for a year's worth of service to get that price. Compared to <code>$170</code>/month for less than half the data, I don't mind at all though. It's still more affordable to pay for a full year for both of us. That's still less expensive than 3 months of VZW's plan.</p>
<p>The links below are resources I used both writing this post and actually switching service providers. Feel free to check them out.
<a rel="noopener nofollow noreferrer" target="_blank" href="http://www.youneedabudget.com/blog/2013/how-im-saving-1828-per-year-on-my-cellphone-bill/">This post</a> was <a rel="noopener nofollow noreferrer" target="_blank" href="http://news.cnet.com/8301-33620_3-57587175-278/is-this-the-best-smartphone-plan-ever/">one of</a> <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.thetechblock.com/get-unlimited-talk-text-data-30-iphone/">the inspirations</a> to make the switch, and I'm happy I did.</p>
<h1 id="new-phones-ya-ll">New phones ya'll</h1>
<p>As a nice little bonus, these cutbacks have made it possible to purchase new phones outright and off contract. If you're smarter than me, you'll probably be able to put that money to better use. Me? I like those pocket computers with access to the internet at ever faster speeds, with increasingly larger screens.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>After 5 Gb you get slow data speeds. </p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>I was trying to get my rooted, VZW Droid Razr M working on a <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.jefftk.com/p/3g-and-hspa-on-the-razr-m-with-att-or-t-mobile">non-CDMA network</a>. <a rel="noopener nofollow noreferrer" target="_blank" href="https://forum.xda-developers.com/showthread.php?t=2166542">I actually did get this working</a>.</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>This worked great for a while until google came out with their Hangouts app. We had to switch to using Hangouts to make calls which required my wife to change the way she did things. There was no longer that <code>$0.99</code> fee per month though; like most of Google's consumer facing services, you pay with the information you allow Google to collect about you, not in dollars.</p>
</div>
Prevent iTerm2 Profile window from showing up each startup2017-09-26T22:26:00-05:002017-09-26T22:26:00-05:00
Unknown
https://orville.thebennettproject.com/articles/prevent-iterm-profile-showing-up/<p>So this is an annoying one. After finally updating to iTerm2 version 3.0 one of the things that really annoyed me was a <strong>Profiles</strong> window that showed up each startup. I ignored this for about a year because it would only be an intermittent problem<sup class="footnote-reference"><a href="#1">1</a></sup>. </p>
<p>I've been restarting this MacBook much more frequently these past few weeks so I finally took to <a rel="noopener nofollow noreferrer" target="_blank" href="https://encrypted.google.com/search?hl=en&q=iterm2%20profiles%20windows%20on%20startup">google</a> to find a solution. Turns out this one was pretty easy. There is <a rel="noopener nofollow noreferrer" target="_blank" href="https://gitlab.com/gnachman/iterm2/issues/2611">a setting in the Preferences window</a> that turns this feature off. All you need to do is:</p>
<ol>
<li>Go to <code>Preferences > General</code></li>
<li>Uncheck <code>[x] Open profiles window</code>.</li>
</ol>
<p>Et voila!</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>I'd restart after months, close it manually, then forget about for another few months until I restarted/the battery in the laptop died.</p>
</div>
Homebrew Dynamic DNS with the Linode API2017-09-18T21:52:00-05:002017-09-18T21:52:00-05:00
Unknown
https://orville.thebennettproject.com/articles/homebrew-dyndns-with-linode/<p>Over the years I've set up a variety of private cloud services. In addition to gaining expertise in these services for clients who would rather rely on their own infrastructure, it's also made me less dependent on web company services which could (<a rel="noopener nofollow noreferrer" target="_blank" href="http://mashable.com/2014/01/24/google-gmail-outage-response/#qnTpKg.s1iqw">and have</a>) <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.pcworld.com/article/3120644/internet/gmail-outage-for-business-users-continues-over-12-hours-later.html">disappeared</a> at <a rel="noopener nofollow noreferrer" target="_blank" href="https://venturebeat.com/2014/01/13/after-dropbox-outage-users-are-calling-in-cloud-storage-competitors/">inconvenient times</a>. This desire for virtual independence has led to me learning how to set up, run and administer my own mail server (goodbye gmail!), git server, read-it-later server (goodbye Pocket!), rss feed sync server (goodbye Feedly), and even a document sync server (goodbye Dropbox). I want some of these services to always be accessible. Those services I host with <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.linode.com/?r=63b4311120ddd88b8817c4d7e84eb164ee3afb60">Linode</a>. </p>
<p>Others—the sync servers—may contain private information I don't want on someone else's infrastructure (e.g. Linode). Luckily, these are also services I don't always need access to, "most of the time" is more than good enough. If a sync server is not available when a sync action is requested, the sync client will simply try again later.</p>
<p>I host those sync services from a server under my control, with a residential connection. The problem with this setup is that the IP address may potentially change at any time. As I don't want to go into every device and change settings whenever an IP address changes, I've assigned this IP address a domain name. This way IP address changes only have to be updated in one location<sup class="footnote-reference"><a href="#1">1</a></sup>.</p>
<p>I <strong>could</strong> do better though. I was still waiting for things to break before I act. I could be a bit more proactive. There is such a thing as dynamic DNS which will detect when a change to an IP address for a domain happens, and then update the DNS entry. There is one gotcha to this plan, and it's that Linode has a very functional, but very basic DNS manager. They have no dynamic DNS client that I know of so that seemed to be out of the question. Or it was, until I happened across a very useful article on the interwebs. One Travis Maynard wrote a post on how to <a rel="noopener nofollow noreferrer" target="_blank" href="https://travismaynard.com/writing/dynamic-dns-using-the-linode-api">get Dynamic DNS working with the Linode API</a>. </p>
<p>Below are my modified instructions on how to get it working with my home-grown opnsense firewall/router. Before you ask: Yes, I <em>could</em> set it up on any machine. However, the router is the only one that is guaranteed to be connected to the internet all the time.</p>
<p>So let's get to it. As explained in the article, if you're using a <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.linode.com/?r=63b4311120ddd88b8817c4d7e84eb164ee3afb60">Linode</a> there is some information you'll need to find out before you can get this all to work.</p>
<h2 id="create-a-new-user">Create a new user</h2>
<ol>
<li>Login to your Linode account and navigate to <strong>Accounts</strong> and then select the <strong>Users and Permissions</strong> tab.</li>
<li>Create another user by selecting the <strong>Add a User</strong> option.</li>
<li>Make sure that the <strong>Yes - this user can only do what I specify</strong> option is selected and then <strong>Save Changes</strong> to create the user.</li>
</ol>
<h2 id="give-new-user-specific-permissions-on-desired-domains">Give new user specific permissions on desired domains</h2>
<blockquote>
<p>The next screen will display all of the options that you have to grant or restrict to the user. In this case, all you want to do is check the "All Privs" checkbox on the domain that you've added underneath the <em>DNS Zone Grants</em> section. This will prevent the user (and consequentially the API key) from making changes to anything but the domain we have specified.
<br/>— Travis Maynard</p>
</blockquote>
<h2 id="create-a-linode-api-key-for-the-new-user">Create a Linode API key for the new user</h2>
<ol>
<li>Login to your Linode as the new user and go to <strong>My Profile</strong>.</li>
<li>Select the <strong>API Keys</strong> tab.</li>
<li>Create a new API Key.</li>
<li>Record the API Key for later use.</li>
</ol>
<h2 id="find-out-domainid-and-resourceid">Find out DOMAINID and RESOURCEID</h2>
<p>To find the domain ID:</p>
<ol>
<li>
<p>In a browser, navigate to the URL<sup class="footnote-reference"><a href="#2">2</a></sup>: <code>https://api.linode.com/?api_key=MY_API_KEY&api_action=domain.list</code> replacing the <code>MY_API_KEY</code> portion with your actual API Key.</p>
</li>
<li>
<p>Locate the <code>DOMAINID</code> for the domain that will have its IP address updated dynamically.</p>
</li>
<li>
<p>Using the newly obtained <code>DOMAINID</code>, modify the URL to the form <code>https://api.linode.com/?api_key=MY_API_KEY&api_action=domain.resource.list&domainid=DOMAIN_ID</code> and navigate to it in a browser again.</p>
</li>
<li>
<p>Search for the subdomain you want to update based on the <code>NAME</code> property, and copy the <code>RESOURCEID</code>.</p>
</li>
<li>
<p>Modify the URL, and add the new <code>RESOURCEID</code> to the end of it: <code>&resourceid=RESOURCE_ID</code></p>
</li>
<li>
<p>Navigate to this URL in a browser to check that it's correct.</p>
</li>
</ol>
<p>To build the full URL neccessary we need some more changes. The near final form is:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>https://api.linode.com/?api_key=MY_API_KEY&api_action=domain.resource.update&domainid=DOMAIN_ID&resourceid=RESOURCE_ID&target=[remote_addr]
</span></code></pre>
<p>What we've done is to change the <code>domain.resource.list</code> portion of the URL to <code>domain.resource.update</code>, while appending <code>&target=[remote_addr]</code> to the end of the URL. </p>
<ul>
<li>The <code>&target=[remote_addr]</code> addition will obtain the external IP address of the machine making the request (your computer/router).</li>
<li>The <code>domain.resource.update</code> will cause the changes to be recorded in Linode's DNS manager.</li>
</ul>
<p>After visting the URL in the browser you'll be able to verify that an actual update happened when you check the <strong>Last Modified</strong> date for the affected Domain Zone in the <strong>DNS Manager</strong>.</p>
<h2 id="setup-cron-to-run-command-periodically">Setup cron to run command periodically</h2>
<p>Once you have verified that the update does in fact happen, it's time to automate this. I'll be using the tool <code>cron</code> to periodically execute a script that visits the URL we crafted above. The script will use the <code>curl</code> command to access the URL. </p>
<p>For use with curl, we have to escape the <code>target</code> value's square brackets, and put the entire URL in quotes. Here is the complete URL: </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>https://api.linode.com/?api_key=MY_API_KEY&api_action=domain.resource.update&domainid=DOMAIN_ID&resourceid=RESOURCE_ID&target=\[remote_addr\]
</span></code></pre>
<p>This is the command cron will run:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>curl 'https://api.linode.com/?api_key=MY_API_KEY&api_action=domain.resource.update&domainid=DOMAIN_ID&resourceid=RESOURCE_ID&target=\[remote_addr\]'
</span></code></pre>
<p>And finally, here is what we paste into the crontab file, after accessing it with the command <code>crontab -e</code> in a terminal:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>*/30 * * * * /bin/echo `/bin/date`: `curl 'https://api.linode.com/?api_key=MY_API_KEY&api_action=domain.resource.update&domainid=DOMAIN_ID&resourceid=RESOURCE_ID&target=\[remote_addr\]'` >> /var/log/linode_dyndns.log
</span></code></pre>
<p>The cron settings above will run the curl command every 30 minutes and log the result to the <code>linode_dyndns.log</code> file in the <code>/var/log</code> directory. Or rather, it will if the user running this cron job has write access to the directory. If not, create the file and make it accessible to the user. Alternatively, change the file path to somewhere the user has permission to write to.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>A wonderful side effect of this system is that it takes my downtime from multiple hours after <em>I've noticed</em> there is a problem with the server (i.e. IP address has changed), to maybe an hour after <em>I've noticed</em> there is a problem.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>Uniform Resource Locator, i.e. a website address.</p>
</div>
Troubleshooting Piwik database errors.2017-08-30T14:30:00-05:002017-08-30T14:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/troubleshooting-piwik-database-errors/<p>Do you know what's not fun? Troubleshooting database errors. Imagine <a href="https://orville.thebennettproject.com/articles/piwik-installer-has-php-fatal-error/">you've set up piwik on a client's server</a>. You have everything installed, configured, and running. You're testing out various features, you know, to make sure they work as advertised before handing off to the client. Not required, but it's that little extra icing on top that makes your service just a touch above the rest. </p>
<p>Then you find that a feature isn't working properly. And you have a deadline. That is quickly approaching. Sigh. </p>
<p>I had just such a problem "recently" and was unable to get any useful error info from the server's logs. It was absolutely maddening, until I recalled something else I do before turning over a final project: I turn off all debug logging to the rendered webpages. I typically do this fairly early in the process so that I don't have to worry about it later. </p>
<p>Having remembered that, I re-enabled php's debug output, but was still not getting any useful debug info back. The reason, again, was me.
In the nginx config I set up generic error pages to be served when a server-side error was encountered. In order to troubleshoot I had to disable generic pages first.</p>
<p>That required editing <code>/usr/local/etc/nginx/nginx.conf</code> and commenting out the line </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>error_page 500 502 503 504 /50x.html;
</span></code></pre>
<p>changing it to</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>#error_page 500 502 503 504 /50x.html;
</span></code></pre>
<p>This allowed me to see the
<a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/piwik/piwik/issues/9666">Unknown column `use_12_hour_clock` on update from 2.15.0 to 2.15.1-b2 or later</a> error.</p>
<p>This was a bug in piwik code that, thankfully, I didn't have to solve myself. The solution <a rel="noopener nofollow noreferrer" target="_blank" href="https://issues.piwik.org/9666">had already been found</a>. All that was required was to run the following code on the piwik database:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ALTER TABLE `piwik_user_language` ADD COLUMN `use_12_hour_clock` TINYINT(1) NOT NULL DEFAULT 0 AFTER `language`
</span></code></pre>
<p>You'd think that now I could be done with this project and hand it off. But you'd be wrong! More testing found more issues; this time when <a rel="noopener nofollow noreferrer" target="_blank" href="https://github.com/piwik/piwik/issues/11327">editing Goals which existed before Piwik v3</a>:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Key "description" for array with keys "idsite, idgoal, name, match_attribute, pattern, pattern_type, case_sensitive, allow_multiple, revenue, deleted" does not exist.
</span></code></pre>
<p>The solution was to run this code on the database:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ALTER TABLE piwik_goal ADD description VARCHAR(255) NOT NULL DEFAULT '';
</span></code></pre>
<p>Finally, I finished verifying that things worked as expected, with the client none the wiser. Interesting thing isn't it, the better I you are at your job the less recognition you get. It's a good thing I actually like it that way. ;-)</p>
Piwik installer has PHP Fatal error: Allowed memory size exhausted (tried to allocate 20480 bytes) in core/FrontController.php2017-08-30T12:41:00-05:002017-08-30T12:41:00-05:00
Unknown
https://orville.thebennettproject.com/articles/piwik-installer-has-php-fatal-error/<p>For three nights I struggled with trying to figure out why I could not get <a rel="noopener nofollow noreferrer" target="_blank" href="https://piwik.org/">Piwik's web analytics software</a> to load it's installation page successfully. I was attempting to migrate it from a FreeBSD 10 <em>server</em> to a FreeBSD 11 <em>jail</em> and nothing, <strong>nothing</strong> I did was working. I kept on getting the following two errors in my php logs:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>PHP Fatal error: Allowed memory size of xxxx bytes exhausted (tried to allocate 20480 bytes) in /usr/local/www/piwik/core/FrontController.php on line 416
</span><span>PHP Fatal error: Allowed memory size of xxxx bytes exhausted (tried to allocate 20480 bytes) in /usr/local/www/piwik/core/FrontController.php on line 227
</span></code></pre>
<p>This message seemed to be telling me that my php process was running out of memory. The reason this was so puzzling is that I took my PHP configuration files from another jail running different PHP software, that had worked! I could not fathom why the same files would not successfully serve (with minor modifications) piwik.</p>
<p>As it turns out, the php configuration files were not the problem. It was missing php <strong>modules</strong> that caused the issue. How did I figure this out? Well, in desperation I decided to just go back in time (one piwik version at a time) to see if any would work. I eventually saw a different error with version 3.0.0. Even better, I knew what this one meant.</p>
<p>The error was:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Error in Piwik: Call to undefined function Piwik\ctype_alnum()
</span></code></pre>
<p>This indicated that I was missing the php ctype module, so I installed it with <code>pkg install php71-ctype</code>. Then I received another error:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Error in Piwik: Call to undefined function hash()
</span></code></pre>
<p>This indicated that I was missing the hash module. A quick <code>pkg install php71-hash</code> later and I finally had what I needed: the Piwik installer. Having found success, I then went back to the latest Piwik version. And lo, It worked!</p>
<p>Here is the final list of php module packages I installed:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>php71
</span><span>php71-pdo
</span><span>php71-pdo_mysql
</span><span>php71-curl
</span><span>php71-filter
</span><span>php71-hash
</span><span>php71-ctype
</span><span>php71-session
</span><span>php71-json
</span></code></pre>
<p>Hope this saves you 3 days. </p>
Redemption2017-06-28T01:35:00-05:002017-06-28T01:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/vacation-sermon/<blockquote>
<p>My family and I go to church together. It's one "our things" I guess. On our most recent vacation we were going to miss being in church so <a rel="noopener nofollow noreferrer" target="_blank" href="https://laura.thebennettproject.com">my wife</a> suggested we just do church with all the family at the vacation site. She planned the songs, got the music and words for those songs; planned activities for the kids to do during the sermon; and of course, planned to have someone preach the message. That lucky stud was me. The following is, more or less, the sermon I did—because my wife made me do it—for our family vacation. Because I think all sermons should have catchy titles I'm calling it "Redeemed". And here it is below:</p>
</blockquote>
<p>For those of you who don't know me: I'm Orville, Laura's husband. And I will be bringing the word today.</p>
<p>True story time. So I got baptized at 16, but witnessed my first ever miracle some time before that, in prep school. Now in <em>my</em> prep school all children were required to say the Lord's Prayer right before the day's first class began. I remember a time, around grades 3 or 4 when we were doing our daily prayer and one of the students did not want to participate. This was actually a recurring issue with this particular child. She <em>never</em> wanted to say the prayer. </p>
<p>On this particular occasion she decided she would not simply mumble her way through. Instead she would not say any of it at all. When pressed as to why, she boldly proclaimed it was because she did not believe God existed. This brazen "I don't believe in God." declaration caused quite a stir in classroom. Now being goodly little boys and girls, I'm sure you can guess what we did next: we teased her mercilessly <sup class="footnote-reference"><a href="#1">1</a></sup>. Predictably, the commotion we created earned us the teacher's scrutiny. When she inquired as to what was going on we—dutiful cherubs that we were <sup class="footnote-reference"><a href="#2">2</a></sup>—graciously pointed out the unbeliever in our midst (to deflect blame and save our skins) <sup class="footnote-reference"><a href="#3">3</a></sup>. </p>
<p>After finding out what was going on our teacher decided to take the girl "out back" which, as we all knew meant: "You in troublllllle." Now, I don't recall what happened later in the morning, or day, or even the next day. But what has stuck with me all these years, is what happened a few weeks later. A completely different child arrived at school, same body as that girl we got in trouble, but <strong>completely</strong> different attitude and outlook on life. I bet you're dying to know what happened (as were we all). </p>
<p>Turns out, the teacher that took her outside was an <em>actual</em> christian. So instead of punishing her, our teacher spoke to her, found out why she didn't want to say the prayer, and why she didn't believe in God. The little girl told her she was adopted and wanted to know who her real father was. In response, our teacher told her about our Heavenly Father. Our teacher also prayed with her that she would find her biological father. </p>
<p>And you know what? She did. And from that point forward she believed in God. One answered prayer changed a whole life. And let me tell you, it was a drastic change. A complete reversal in character, you could tell that she had been changed deeply and profoundly by this experience. Instead of declaring that there was no God, she was now boldly declaring there <em>was</em> and proclaiming his goodness. </p>
<p>So. What's the point of this story, besides "We have an awesome God?" To me, this story is a story of redemption. God redeemed <sup class="footnote-reference"><a href="#4">4</a></sup> <em>Himself</em> in this girls eyes, and in doing so redeemed<sup class="footnote-reference"><a href="#5">5</a></sup> this little girl.</p>
<p>I shared this story because while preparing for this sermon I was drawn to the topic of redemption. By finding her earthly father, a little girl opened her heart to her heavenly father, and was saved from her sins. But wait, there is more! I even found bible verses about redemption.</p>
<p>Ephesians 1:7 says
>"In him we have redemption through his blood, the forgiveness of our trespasses, according to the riches of his grace,".</p>
<p>According to Ephesians 1:7 then we are redeemed by Christ's blood—blood which was shed by His death on the cross—and his forgiveness of our trespasses.</p>
<p>So what are trespasses? Today trespassing means intruding; unlawful entry. In the context of this verse though, a trespass is a wrong that you have committed, a transgression; sin, if you will.</p>
<p>Jesus' redemption (saving us by paying for our sin) comes from the abundance of God's grace and love for us. One of the most well known Bible verses is John 3:16 which explains how much God loves us:</p>
<blockquote>
<p>"For God so loved the world, that he gave his only Son, that whoever believes in him should not perish but have eternal life."</p>
</blockquote>
<p>Now that much love requires some serious sacrifice. I don't know about you guys, but if your lives depended on me allowing one of my sons to die, you would all be dead. God on the other hand—since the fall of Adam and Eve—has been lining up the pieces, setting the stage for Jesus to do just that.</p>
<p>To drive home the lengths to which God will go to save one person, let me tell you another story.</p>
<p>So I grew up in Jamaica, had a mom and dad, but was raised by my grandparents. My grandparents were christians so they went to church and took me with them. Eventually, I was saved and baptized as a teenager.</p>
<p>I moved to the US, met a girl, invited this girl to church, and then, thanks to the influence of her grandparents she also got saved. This girl had a little boy. Due to the influence of me and my wife, this little boy got saved. This little boy had a father who was not me. He wasn't a very good father though: did drugs, sold drugs, got arrested, etc.</p>
<p>The thing is, after a while the little boy wondered why his <em>other</em> dad wasn't around anymore and he asked. My wife and I told him his father had some issues and needed prayer, so he should pray for him "to make better choices" because that's the only thing he could do to help right now. And pray the little boy did. A few years passed and we heard that his dad was sent to jail. My response was, "Well that's the end of that!". Our boy didn't stop praying though and a few weeks ago, we got a call saying that his biological father had giving his life to Christ. He too had been saved. </p>
<p>God it seems, has a plan for all of us. We all have a purpose that we may not understand, but it ties into God's desire to redeem us all.</p>
<p>If God can set in motion a plan where a kid in Jamaica gets saved, which leads to a child in the US getting saved, whose prayers help a man from Cambodia get saved, then what else can His steadfast love accomplish?</p>
<p>What complicated domino effect has God set in motion to ensure <em>your</em> redemption, or the redemption of those close to you? Maybe today is the day to topple that last domino as you decide to ask forgiveness and give your life to him.</p>
<p>You may be wondering, how do we get forgiveness? According to Romans 10:10: </p>
<blockquote>
<p>"For with the heart one believes and is justified, and with the mouth one confesses and is saved."</p>
</blockquote>
<p>Confess your sins and believe that you're saved. So before we go, if anyone would like to be saved all that's needed is to say this prayer, "Lord, I'm a sinner in need of a savior, and I recieve your gift of forgiveness. Amen."</p>
<p>Now that you've confessed your sins, all that's left, is to believe. </p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>Kids can be so horrible.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>Can you taste the sarcasm?</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>I'd like to point out that, while nothing we said was untrue, it certainly didn't paint a complete picture of what was going on. We, after all, were the aggressors here. This is something you should always keep in mind when dealing with kids.</p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">4</sup>
<p>vindicated, shown or proven to be right.</p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">5</sup>
<p>saved, in this case, from sin.</p>
</div>
Running dovecot and opensmtpd inside a jail2017-06-14T07:30:00-05:002017-06-14T07:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/running-dovecot-and-opensmtpd-inside-a-jail/<p>This is is going to be short and sweet. If you are running opensmtpd or dovecot inside FreeBSD jails you may need specific changes for this configuration, depending on your jail setup.</p>
<p>For dovecot I had to add <code>listen = *</code> to the config.</p>
<p>For opensmtpd I needed to have <code>listen on localhost port <portnumber></code> instead of <code>listen on lo0 port <portnumber></code> for smtpd.conf.</p>
Solution for fatal error in dovecot configuration file2017-06-14T01:35:00-05:002017-06-14T01:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/fatal-error-in-dovecot-configuration-file/<p>While setting up a mail server, I ran into a curious issue which I have documented below for posterity. After modifying the dovecot configuration and attempting to start the dovecot service I received the following error:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>doveconf: Fatal: Error in configuration file /etc/dovecot/conf.d/10-mail.conf line 31: Unknown setting: mail_location
</span></code></pre>
<p>The error is not actually in the file <code>10-mail.conf</code> at at all. As it turns out <em>I</em> caused this problem when I edited the file <code>/etc/dovecot/conf.d/auth-system.conf.ext</code> and did not put a closing brace on the last line. More accurately, I did not uncomment the closing brace for the section I edited. My broken config change looked like this: </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span># Static settings generated from template <doc/wiki/UserDatabase.Static.txt>
</span><span>userdb {
</span><span> driver = static
</span><span> # Can return anything a userdb could normally return. For example:
</span><span> #
</span><span> args = uid=mail gid=mail home=/var/mail/%d/%n
</span><span>#}
</span></code></pre>
<p>Since the closing curly brace isn't uncommented, and my configuration is broken up over several files, dovecot tries to set <code>mail_location</code> in the <strong>userdb</strong> section. That's not a valid <strong>userdb</strong> option and so it fails. If you run into this class of error you may see a different file referenced and a different setting, but the general solution should still apply. Close your braces properly.</p>
<p>The correct version—with <code>#</code> removed from before the closing curly brace—is below.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span># Static settings generated from template <doc/wiki/UserDatabase.Static.txt>
</span><span>userdb {
</span><span> driver = static
</span><span> # Can return anything a userdb could normally return. For example:
</span><span> #
</span><span> args = uid=mail gid=mail home=/var/mail/%d/%n
</span><span>}
</span></code></pre>
<p>Details. Amirite?</p>
Configure TP-LINK Archer C9 for access point mode with opnsense2017-06-11T03:24:00-05:002017-06-11T03:24:00-05:00
Unknown
https://orville.thebennettproject.com/articles/configure-tplink-archer-c9-for-access-point-mode/<p>Want to hear something boring? I built myself a router last year using a <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.amazon.com/ZOTAC-Quad-Core-Graphics-Barebones-ZBOX-CI323NANO-U/dp/B0179S50UU/ref=as_li_ss_tl?ie=UTF8&linkCode=ll1&tag=orbitsolution-20&linkId=8dff60cd0171dabb922f6584bb737b0f">Zotac ZBOX CI323 nano</a> and the opnsense firewall distribution. It works fairly well. The primary problem I have with it now is that ever since the 17.x updates (I started with 16.x), the <strong>CI323 nano</strong> will shut down randomly. When this happens I, predictably, lose internet service and need to restart the CI323. Now I haven't troubleshot this issue yet but this post has absolutely nothing to do with <em>that</em>. </p>
<p><em>This</em> post is documenting what I needed to do to get the <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.amazon.com/TP-Link-AC1900-Wireless-Wi-Fi-Router/dp/B00PDLRHFW/ref=as_li_ss_tl?ie=UTF8&linkCode=ll1&tag=orbitsolution-20&linkId=cd2e529e39504b215fbb1b543db68306">TP-LINK Archer C9</a> to work as a wireless access point behind the CI323 nano.</p>
<p>I found the solution on <a rel="noopener nofollow noreferrer" target="_blank" href="https://nicholasgerasimatos.wordpress.com/2015/12/03/configure-tp-link-archer-c9-or-c7-c8-for-access-point-mode/">another site</a> which I'm documenting here for (my) ease of use/reference. </p>
<p>So to get my Archer C9 to play nicely behind the CI323 nano's opnsense firewall, I:</p>
<ol>
<li>Disabled DHCP in Archer C9.</li>
<li>Then, and this is the important bit that I was missing, <strong>I plugged the C9 into my opnsense router but did <em>not</em> use the TP-LINK's WAN port</strong>.</li>
</ol>
How I learned to stop worrying about systemd and use something better: FreeBSD2017-05-31T00:30:00-05:002017-05-31T00:30:00-05:00
Unknown
https://orville.thebennettproject.com/articles/how-i-learned-to-stop-worrying-about-systemd/<p>Some have asked why I switched from Linux to FreeBSD on my servers. This post's sole reason for existence is to explain why. TLDR; once I realized that Ubuntu 16.04 was using systemd as the init system I decided to start looking at other operating systems to use for my servers. Systemd is, in my opinion, a massively invasive piece of software.</p>
<p>It has gone from being merely a new init system implementation to being a blackhole: consuming ever more pieces of system functionality which needn't be a part of an init tool. </p>
<p>My main problem with systemd is that it violates the "Do one thing, and do it well" principle that I believe great software needs to adhere to. Well, that's the main <em>philosophical</em> problem. If it had multiple pieces doing their own one thing well I would have let it slide (à la git). </p>
<p>Thing is, it doesn't do anything <em>well</em>. Sadly, even if that were the <em>only</em> issue I'd still be using Ubuntu on my servers. Practically, however, I've had too many inexplicable problems traced back to systemd on on my desktop systems to trust it with my mission critical servers.</p>
<p>Systemd is certainly great for Redhat (whose employees created it) and those willing to pay Redhat's support fees. I do find it makes some common administrative tasks simpler once you get used to it (which is why I tolerate it on desktop systems). </p>
<p>However, for those looking to administer Linux servers without paying support fees to a company, I believe it's a raw deal. I have different priorities with servers; a "set it, and forget it" mentality. As such, once a server is properly set up, I don't want to deal with running out of space on a partition because of a systemd bug where <a rel="noopener nofollow noreferrer" target="_blank" href="https://bbs.archlinux.org/viewtopic.php?pid=1235392#p1235392">corrupted log files were not deleted</a> using up all space on a partition. </p>
<p>I know what you're thinking, I should be monitoring the servers anyway. And I do, but I have no intention of doing extra work in order to facilitate a tool doing <em>its</em> job poorly.</p>
<p>I see no good reason for the init system to be tied to the system log. Furthermore, there is no reason that, if <em>you</em> believe that setup to be beneficial why <em>I</em> should have to use it. I already have logging software I know and trust and it's never had a bug like that in the time I used it. But if it did, I could just switch to something else. </p>
<p>Systemd's <strong>intentional</strong> tight coupling between its programs makes it difficult, if not impossible, to use something else for it's fucntionality. Want to use a different logger? Good luck finding someone that know how their <em><strong>binary</strong></em> log format works. That's merely one example of systemd causing problems that I personally experienced and had to troubleshoot. </p>
<p>Not world ending but annoying enough that I don't want to encounter it on my servers. And who's to say I wouldn't? On Linux servers I put <code>/var</code> on it's own partition. <code>/var</code> happens to be where the system stores not just logs, but also files being served by the web server or database. Databases grow. When databases try to grow and run out of space bad things happen with your application.</p>
<p>I could mitigate this particular issue by giving the database access to more space which it doesn't need (remember, <a rel="noopener nofollow noreferrer" target="_blank" href="https://bbs.archlinux.org/viewtopic.php?pid=1235392#p1235392">this is a systemd bug</a>). I could keep monitoring the journald logs. Or I could just use a system that doesn't require all that mitigation to have some peace of mind in the first place. That was just one issue I ran into. There were others.</p>
<p>So what was my solution to "the systemd problem"? I learned how to use some entirely new operating sytems. At first I started looking at non-systemd Linux distributions like Alpine Linux. Things which would also be good for containerization. </p>
<p>Then I remembered I wanted to look into FreeBSD to become more familiar with it. I had also been messing around with ZFS on OS X and knew that FreeBSD had it built into the OS, and was able to use it on the root (main) file system. I also knew FreeBSD had really good documentation from earlier forays into that foreign land. The only strike I had against using it was my unfamiliarity with their firewall solution (as it turns out, there are many) so I would have to be learning that as well.</p>
<p>So I started some R&D. I moved a web server at first and looked at performance. This was on a VM with very little memory so I was surprised at how well FreeBSD handled that. Pleasantly surprised. Then I gradually tested other things: a php app server, a git server, a mail server. </p>
<p>For the mail server I initially tried out another BSD—OpenBSD—and liked it a lot. OpenBSD is a simple to configure, well documented operating system which I would highly recommend for single purpose servers. Want to set up just a mail server? Go with OpenBSD. Just a firewall server? OpenBSD.</p>
<p>In the end, FreeBSD's ZFS functionality and the ability to have jails (containers!) won me over from my brief foray into the OpenBSD waters. Thanks to that time with OpenBSD though, I was introduced to software that I was unfamiliar but preferred, or found superior to what I was using when on Linux. </p>
<p>OpenSMTPD for instance is a really simple to configure mail server. doas is a nice, simple sudo replacement. pf is a really nice firewall. acme-client (née letskencrypt) is a not-so-simple acme client (certbot) implementation in C. </p>
<p>I prefer acme-client to the simpler certbot as I believe it's more secure. Why? acme-client is now a part of the OpenBSD base system. acme-client does not have a long list of dependencies and code I'm realistically not ever going to look at. I have actually gone browsing in the acme-client source code already. Also, as a part of the base OpenBSD code, I trust that it's being audited for security and code quality.</p>
<p>I had actually learned ipfw before using OpenBSD, and then was introduced to pf. I then tried to stick with ipfw when setting up the actual servers, and could not, for the life of me, get my jails talking to each other on their own network properly, until I tried setting up the firewall with pf. So now I'm using that.</p>
<p>Between systemd leaving a bad taste in my mouth (too complex, too fragile) and the BSDs making a very good impression performance, simplicity and security-wise I made the switch and have no regrets. </p>
git show: my hero2017-05-30T16:05:00-05:002017-05-30T16:05:00-05:00
Unknown
https://orville.thebennettproject.com/articles/git-show-my-hero/<p>This post is about a git learning I had some time ago. The codebase that I was hired to work on had diverged from the main branch at some point in the past (months earlier). A few months into the project I took on the responsibility of merging the diverged branches together. It took me a really long time (hours) to finish, but all seemed to go well.</p>
<p>The problem: after doing the merge we kept working and making further commits, but then needed to get a diff of the files in the merge commit.</p>
<p>The solution: git show. I found the commit hash of the merge and then executed <code>git show --stat COMMIT_HASH</code>.</p>
<p>Here's some sample output:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>git show --stat 76e4db39e5a344dd2353e68b6
</span><span>commit 76e4db39e5a344dd2353e68b6f8e67fc745568a6
</span><span>Merge: 7b8965f 327dfe4
</span><span>Author: Master Bennett <lol@thebennettproject.com>
</span><span>Date: Mon May 29 00:48:30 2017 -0400
</span><span>
</span><span> Merge branch 'ob-pages'
</span><span>
</span><span> # Conflicts:
</span><span> # _config.yml
</span><span>
</span><span> .gitignore | 1 +
</span><span> _site/404.html | 2 +-
</span><span> _site/about/index.html | 2 +-
</span><span> _site/archives/index.html | 18 +-
</span><span> .../index.html | 4 +-
</span><span> _site/articles/android/index.html | 2 +-
</span><span> .../apple-gcc-4.2-and-amarok-beginning/index.html | 11 +-
</span><span> _site/articles/baby-stuff/index.html | 2 +-
</span><span> _site/articles/building-a-better-zombie/index.html | 8 +-
</span><span> _site/articles/bundling-fool-too/index.html | 8 +-
</span><span> _site/atom.xml | 196 +++++++++++----------
</span><span> _site/css/font-awesome.css.map | 7 +
</span><span> _site/index.html | 2 +-
</span><span> _site/page2/index.html | 2 +-
</span><span> _site/page3/index.html | 2 +-
</span><span> _site/page4/index.html | 2 +-
</span><span> _site/page5/index.html | 2 +-
</span><span> _site/page6/index.html | 2 +-
</span><span> _site/page7/index.html | 2 +-
</span><span> _site/page8/index.html | 2 +-
</span><span> _site/page9/index.html | 2 +-
</span><span> _site/sitemap.xml | 6 +-
</span></code></pre>
<p>The <code>--stat</code> flag was a quick and dirty way to see whether there were additions and deletions to a file, or whether just the permissions were changing. That was a critical piece of information that saved us a <strong>LOOOOOT</strong> of time on something that was very time sensitive. </p>
<p>Knowing that allowed me to ignore files which only had permissions change and narrow the search down to those files which actually had substantial changes. So here's to git, it's one of the good ones.</p>
Fix Ghost init script not starting automatically in FreeBSD jail2017-05-05T16:35:00-05:002017-05-05T16:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/freebsd-ghost-init-script-not-starting-automatically/<p>I've been redoing the infrastructure for the web servers here at the bennett project—migrating from Ubuntu 12.04 to FreeBSD 11. I've <a href="https://orville.thebennettproject.com/articles/how-i-learned-to-stop-worrying-about-systemd/">shared the reasons for that</a> elsewhere. Today I wanted to document an issue I ran into when setting up the <a rel="noopener nofollow noreferrer" target="_blank" href="https://ghost.org">Ghost blogging platform</a> inside a <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.freebsd.org/doc/handbook/jails.html">FreeBSD Jail</a>.</p>
<p>I wanted the ghost application to start automatically on boot; to do this I needed to create a custom <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.freebsd.org/doc/en/articles/rc-scripting/">FreeBSD init script</a>. I found some examples of FreeBSD init scripts for ghost online and modified a few to suit my purposes. </p>
<p>After I was done this is what my init script looked like:</p>
<pre data-lang="bash" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#7f8989;">#!/bin/sh
</span><span>
</span><span style="color:#7f8989;"># PROVIDE: ghost
</span><span style="color:#7f8989;"># KEYWORD: shutdown
</span><span>
</span><span style="color:#5597d6;">PATH</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
</span><span>
</span><span style="color:#b39f04;">.</span><span> /etc/rc.subr
</span><span>
</span><span style="color:#5597d6;">name</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost"
</span><span style="color:#5597d6;">rcvar</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_enable"
</span><span style="color:#5597d6;">extra_commands</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"status"
</span><span style="color:#5597d6;">load_rc_config </span><span>${</span><span style="color:#5597d6;">name</span><span>}
</span><span style="color:#b39f04;">: </span><span>${</span><span style="color:#5597d6;">ghost_enable</span><span style="color:#72ab00;">:=</span><span style="color:#d07711;">"NO"</span><span>}
</span><span>
</span><span style="color:#5597d6;">status_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_status"
</span><span style="color:#5597d6;">start_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_start"
</span><span style="color:#5597d6;">stop_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_stop"
</span><span style="color:#5597d6;">restart_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_restart"
</span><span>
</span><span style="color:#5597d6;">ghost</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"/usr/local/www/ghost"
</span><span>
</span><span style="color:#c23f31;">ghost_start</span><span>() {
</span><span style="color:#5597d6;">su</span><span> ghost</span><span style="color:#5597d6;"> -c </span><span style="color:#d07711;">"NODE_ENV=production forever start -al $</span><span style="color:#acb3c2;">ghost</span><span style="color:#d07711;">/ghost.log $</span><span style="color:#acb3c2;">ghost</span><span style="color:#d07711;">/index.js"
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 start $ghost/index.js --name $name"
</span><span>}
</span><span style="color:#c23f31;">ghost_stop</span><span>() {
</span><span style="color:#5597d6;">su</span><span> ghost</span><span style="color:#5597d6;"> -c </span><span style="color:#d07711;">"NODE_ENV=production forever stop $</span><span style="color:#acb3c2;">ghost</span><span style="color:#d07711;">/index.js"
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 stop $name"
</span><span>}
</span><span>
</span><span style="color:#c23f31;">ghost_status</span><span>() {
</span><span style="color:#5597d6;">su</span><span> ghost</span><span style="color:#5597d6;"> -c </span><span style="color:#d07711;">"NODE_ENV=production forever list"
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 list"
</span><span>}
</span><span>
</span><span style="color:#c23f31;">ghost_restart</span><span>() {
</span><span style="color:#5597d6;">ghost_stop</span><span style="color:#72ab00;">;
</span><span style="color:#5597d6;">ghost_start</span><span style="color:#72ab00;">;
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 restart $name"
</span><span>}
</span><span>
</span><span style="color:#5597d6;">run_rc_command </span><span style="color:#d07711;">"$</span><span style="color:#acb3c2;">1</span><span style="color:#d07711;">"
</span></code></pre>
<p>After testing it out using <code>service ghost start</code> I rebooted the jail, but my service didn't start up. After much searching around on the internet I did not find a solution. That's when I decided to <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.freebsd.org/doc/en/articles/rc-scripting/rcng-hookup.html">Read The FreeBSD Manual</a> for RC scripting. </p>
<p>Turns out I needed to add <code># REQUIRE: LOGIN cleanvar</code> to the init script in order to get the service started the way I wanted. The final ghost init script then, looked like this:</p>
<pre data-lang="bash" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#7f8989;">#!/bin/sh
</span><span>
</span><span style="color:#7f8989;"># PROVIDE: ghost
</span><span style="color:#7f8989;"># REQUIRE: LOGIN cleanvar
</span><span style="color:#7f8989;"># KEYWORD: shutdown
</span><span>
</span><span style="color:#5597d6;">PATH</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
</span><span>
</span><span style="color:#b39f04;">.</span><span> /etc/rc.subr
</span><span>
</span><span style="color:#5597d6;">name</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost"
</span><span style="color:#5597d6;">rcvar</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_enable"
</span><span style="color:#5597d6;">extra_commands</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"status"
</span><span style="color:#5597d6;">load_rc_config </span><span>${</span><span style="color:#5597d6;">name</span><span>}
</span><span style="color:#b39f04;">: </span><span>${</span><span style="color:#5597d6;">ghost_enable</span><span style="color:#72ab00;">:=</span><span style="color:#d07711;">"NO"</span><span>}
</span><span>
</span><span style="color:#5597d6;">status_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_status"
</span><span style="color:#5597d6;">start_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_start"
</span><span style="color:#5597d6;">stop_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_stop"
</span><span style="color:#5597d6;">restart_cmd</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"ghost_restart"
</span><span>
</span><span style="color:#5597d6;">ghost</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">"/usr/local/www/ghost"
</span><span>
</span><span style="color:#c23f31;">ghost_start</span><span>() {
</span><span style="color:#5597d6;">su</span><span> ghost</span><span style="color:#5597d6;"> -c </span><span style="color:#d07711;">"NODE_ENV=production forever start -al $</span><span style="color:#acb3c2;">ghost</span><span style="color:#d07711;">/ghost.log $</span><span style="color:#acb3c2;">ghost</span><span style="color:#d07711;">/index.js"
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 start $ghost/index.js --name $name"
</span><span>}
</span><span style="color:#c23f31;">ghost_stop</span><span>() {
</span><span style="color:#5597d6;">su</span><span> ghost</span><span style="color:#5597d6;"> -c </span><span style="color:#d07711;">"NODE_ENV=production forever stop $</span><span style="color:#acb3c2;">ghost</span><span style="color:#d07711;">/index.js"
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 stop $name"
</span><span>}
</span><span>
</span><span style="color:#c23f31;">ghost_status</span><span>() {
</span><span style="color:#5597d6;">su</span><span> ghost</span><span style="color:#5597d6;"> -c </span><span style="color:#d07711;">"NODE_ENV=production forever list"
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 list"
</span><span>}
</span><span>
</span><span style="color:#c23f31;">ghost_restart</span><span>() {
</span><span style="color:#5597d6;">ghost_stop</span><span style="color:#72ab00;">;
</span><span style="color:#5597d6;">ghost_start</span><span style="color:#72ab00;">;
</span><span style="color:#7f8989;">#su ghost -c "NODE_ENV=production pm2 restart $name"
</span><span>}
</span><span>
</span><span style="color:#5597d6;">run_rc_command </span><span style="color:#d07711;">"$</span><span style="color:#acb3c2;">1</span><span style="color:#d07711;">"
</span></code></pre>
<p>FreeBSD has <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.freebsd.org/doc/handbook/">good documentation</a>. When in doubt, always read the FreeBSD manuals.</p>
Set up an Ubuntu 16.04 LTS (Xenial Xerus) virtual private server2016-02-09T16:35:00-05:002016-02-09T16:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/set-up-an-ubuntu-16-04-lts-vps/<h1 id="update">Update</h1>
<p>This is how-to guide is essentially unfinished. Reason? Systemd. Once I realized that Ubuntu 16.04 was using systemd as the init system I decided to start looking at other operating systems to use for my servers. If you care about this sort of thing I written down <a href="https://orville.thebennettproject.com/articles/how-i-learned-to-stop-worrying-about-systemd/">my reasons for doing so</a>.</p>
<h1 id="original-post">Original Post</h1>
<p>This post will list the steps I took to set up an Ubuntu 16.04 LTS (16.04 LTS) virtual private server (VPS). As 16.04 hasn't actually been released yet, I had to do some extra work to get this going. </p>
<h2 id="install-ubuntu-15-10">Install Ubuntu 15.10</h2>
<p>First we'll install Ubuntu 15.10. After that is installed, we will immediately upgrade to 16.04 LTS via apt.</p>
<h2 id="upgrade-ubuntu-15-10-to-ubuntu-16-04-lts">Upgrade Ubuntu 15.10 to Ubuntu 16.04 LTS</h2>
<p>Upgrading to the unreleased version of Ubuntu's LTS was not diffiuclt, but it did require some specialized knowledge of how Ubuntu works. Below, I've listed the avenue I took in to get 16.04 LTS on my server.</p>
<h3 id="modify-sources-list">Modify sources.list</h3>
<ol>
<li>Edit <code>/etc/apt/sources.list</code> and change the URLs to point to an official 16.04 mirror.
<ul>
<li>e.g. I changed all lines in my <code>/etc/apt/sources.list</code> file from <code>mirrors.digitalocean.com</code> to <code>us.archive.ubuntu.com</code> — because I get faster speeds from the US mirrors</li>
</ul>
</li>
<li>Save the file and exit <code>/etc/apt/sources.list</code>.</li>
<li>Begin the upgrade process by executing the command <code>do-release-upgrade -d</code>.<sup class="footnote-reference"><a href="#1">1</a></sup></li>
</ol>
<p>Read carefully and follow instructions. Once the upgrade is complete you'll be asked to reboot, do so.</p>
<h3 id="install-any-software-you-ll-need">Install any software you'll need</h3>
<p>Ater you upgrade and reboot, the 1st login to your new 16.04 LTS system is a good time to install any software you believe you may need. I like to install <code>zsh</code> and <code>htop</code>. It is also time to <em>uninstall</em> any software you may not think is necessary to the functioning of a server. I removed laptop-detect and os-prober.</p>
<h3 id="add-a-new-user">Add a new user</h3>
<p>Run the following command and fill out the information requested. Remember to choose a secure password and add the user to the wheel group so that they can get admin privileges with <code>sudo</code>.</p>
<pre data-lang="bash" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#5597d6;">adduser</span><span> USERNAME
</span></code></pre>
<h3 id="setup-ssh-keys-for-logging-into-the-remote-server">Setup SSH keys for logging into the remote server</h3>
<p>After that's all done, create an SSH key on your local machine. After creating this SSH key we'll copy it to your server. You will be asked to enter a password when creating your SSH keys. Be aware that one is not necessary, and as long as no one else has access to your private key, access will be secure. If you don't wish to add a password for your ssh key, you may hit enter and not type any passwords when prompted.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ssh-keygen -b 4096 -t rsa
</span><span>scp ~/.ssh/id_rsa.pub REMOTE_SERVER:~
</span><span>ssh USERNAME@REMOTE_SERVER
</span></code></pre>
<p>You should now be prompted to enter the password for the user you created with <code>adduser</code> on the REMOTE_SERVER. After entering the correct password, you'll be logged in to the remote server. Now we'll copy your ssh pubkey to your remote user's list of authorized keys. This will allow you to use pubkey authentication to log into the server.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
</span><span>exit
</span></code></pre>
<h3 id="test-ssh-keys">Test SSH keys</h3>
<p>To test that this was successful, try to log in to the remote server again. If you created an SSH key without a password, you will be logged in automatically. If you created an SSH key password, enter the password and you will be logged in.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ssh USERNAME@REMOTE_SERVER
</span></code></pre>
<p>If this was successful we'll change some server-side SSH settings to improve security, such as preventing logins by the root user.</p>
<h3 id="change-ssh-port-number">Change SSH port number</h3>
<p>To make it harder for random scanners to pick up my server, I always change the default SSH port. It is insane how many cracking attempts I avoid by simply not using the default SSH port. If you wish to change the default SSH port as well, edit the <code>/etc/ssh/sshd_config</code> file and change the <code>Port</code> directive. I've also modified the other lines listed below.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Port SSH_PORT
</span><span>LoginGraceTime 25
</span><span>PermitRootLogin no
</span><span>PasswordAuthentication no
</span><span>X11Forwarding no
</span></code></pre>
<p>After making the changes reload the ssh server and check to see that it's listening on our new port.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>sudo systemctl restart ssh
</span><span>sudo systemctl status ssh
</span></code></pre>
<p>You should see output similar to the following:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>REMOTE_SERVER sshd: Server listening on 0.0.0.0 port SSH_PORT.
</span><span>REMOTE_SERVER sshd: Server listening on :: port SSH_PORT.
</span></code></pre>
<p>Now all that's left is to open another terminal on your local computer and verify that you can, in fact ssh into your remote server.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ssh -p SSH_PORT USERNAME@REMOTE_SERVER
</span></code></pre>
<h3 id="set-up-firewall-rules">Set up firewall rules <sup class="footnote-reference"><a href="#2">2</a></sup></h3>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>sudo ufw SSH_PORT/tcp
</span></code></pre>
<h2 id="install-web-server">Install web server</h2>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>sudo aptitude install nginx openssl
</span><span>
</span><span>sudo ufw 80/tcp
</span><span>sudo ufw 443/tcp
</span></code></pre>
<p>Strengthen the security of your web server by obtaining an SSL cert and following the instructions at <a rel="noopener nofollow noreferrer" target="_blank" href="https://weakdh.org/sysadmin.html">weakdh.org</a>.</p>
<h2 id="list-of-files-edited">List of files edited</h2>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>/etc/ssh/sshd_config
</span><span>/etc/nginx/nginx.conf
</span></code></pre>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>The <code>-d</code> flag will look for development releases as well which, as of writing, the unreleased Ubuntu 16.04 LTS is.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>Replace SSH_PORT with the actual port that you are using for openssh.</p>
</div>
Yosemite OpenSSH is too old to read ECDSA SSH keys2015-12-15T09:06:00-05:002017-08-30T12:53:00-05:00
Unknown
https://orville.thebennettproject.com/articles/yosemite-ssh-too-old-for-ecdsa/<h1 id="yosemite-ssh-is-too-old-to-read-ecdsa-ssh-keys">Yosemite SSH is too old to read ecdsa SSH keys?</h1>
<p>As you may, or may not know, I am a Front-end user interface engineer.<sup class="footnote-reference"><a href="#1">1</a></sup> I got a new <a rel="noopener nofollow noreferrer" target="_blank" href="https://www.amazon.com/Apple-MacBook-MGXC2LL-15-4-Inch-Display/dp/B00G2MB7KW/ref=as_li_ss_tl?ie=UTF8&qid=1496039406&sr=8-3&keywords=macbook+pro+15+2015+retina&linkCode=ll1&tag=orbitsolution-20&linkId=3557aa7e195b7bc99b2ab7af3fb62ba3">Macbook Pro</a> from work recently, to better facilitate my developer duties.<sup class="footnote-reference"><a href="#2">2</a></sup> Prior to this I was working on my personal machine with Arch Linux installed.<sup class="footnote-reference"><a href="#3">3</a></sup> Since linux and the BSDs (on which OS X is based) are so similar, I was able to transfer large portions of my linux environment to OS X with minimal downtime.</p>
<p>Or would have, had I not run into problems with SSH. After copying my <code>~/.ssh</code> directory from my linux box to OS X, I tried to log in to some remote machines. Much to my chagrin, I recieved the following prompt from our gitolite server indicating problems with SSH pubkey:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>ssh -T git@gitserver
</span><span>git@10.44.91.15's password:
</span></code></pre>
<p>After some searching on the internet I re-ran the command with the -vvv switch as <code>ssh -T git@gitserver</code>:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>debug1: Next authentication method: publickey
</span><span>debug1: Trying private key: /Users/obennett/.ssh/id_ecdsa
</span><span>debug1: key_parse_private_pem: PEM_read_PrivateKey failed
</span><span>debug1: read PEM private key done: type <unknown>
</span><span>Saving password to keychain failed
</span><span>debug1: key_parse_private_pem: PEM_read_PrivateKey failed
</span><span>debug1: read PEM private key done: type <unknown>
</span><span>debug1: Next authentication method: password
</span></code></pre>
<p>My interpretation of this debug output was that OS X Yosemite didn't support ECDSA SSH keys. Not intending to debug this any further I generated some RSA keys and went along my merry way. The RSA keys worked fine. We call that kind of thing a workaround.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>This is the official job title bestowed upon me, but simple Front-end developer will suffice. Although, I do perform a fair bit of server backend (dev ops) duties as well -- e.g. setting up and maintaining our gitolite server.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>Well, that and I didn't like the Dell machine I had. It was a nice machine, but it wasn't a mac. As I <a href="https://orville.thebennettproject.com/articles/installing-ubuntu-14-04-lts-on-a-2011-macbook-pro/">mentioned previously</a> I'd put Ubuntu linux on my macbook pro to work around some <em>very</em> nasty hardware issues in the dedicated video car--issues which rendered my display useless.</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>Going with Arch Linux and and there rolling release allows me to have to most up to date packages available.</p>
</div>
Enable repeating keys in OSX Yosemite2015-09-18T14:39:00-05:002015-09-18T14:39:00-05:00
Unknown
https://orville.thebennettproject.com/articles/enable-repeating-keys-in-osx-yosemite/<p>Newer versions of OS X have opted to disable a feature I use quite a lot, in order to retain consistent with behavior on iOS. That feature is the ability to hold down on a keyboard key and have it repeat until you stop pressing. To enable repeating keys in OS X yosemite enter the following command in Terminal.app.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
</span></code></pre>
<p>After pressing enter you'll need to quit and relaunch any programs that you want repeating keys enabled in.</p>
<p>I'm not sure when it happened, but this is a change from the previous method of enabling repeating keys which, as of OS X Lion was:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>defaults write -g ApplePressAndHoldEnabled -bool false
</span></code></pre>
Globbing in Zsh doesn't work with scp2015-09-18T13:59:00-05:002015-09-18T13:59:00-05:00
Unknown
https://orville.thebennettproject.com/articles/globbing-in-zsh-with-scp/<p>Since <a href="https://orville.thebennettproject.com/articles/changing-the-default-shell-in-os-x/">switching to zsh</a> I've run into a variety of issues with globbing<sup class="footnote-reference"><a href="#1">1</a></sup> <a href="https://orville.thebennettproject.com/articles/working-with-octopress-2-and-zsh/">and other features not working the way I was used to with bash</a>. This post is about resolving another of those issues. Today I was trying to <code>scp</code> some cachegrind files from a remote box and got the following error:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>scp server-local:/var/www/server/cacheg* ~/Documents/cachegrinds
</span><span>usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
</span><span> [-l limit] [-o ssh_option] [-P port] [-S program]
</span><span> [[user@]host1:]file1 ... [[user@]host2:]file2
</span></code></pre>
<p>Basically scp is telling me I was using it wrong. After doing some searching around I found the following information on the <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.zsh.org/mla/users/2004/msg00753.html">zsh mailing list</a>.</p>
<blockquote>
<p>I suspect that you just want <code>setopt no_nomatch</code> so that the glob pattern
is left unexpanded when it doesn't find any matching files. (You may have
to <code>unsetopt null_glob csh_null_glob</code> as well.) That's the only way I can
think of that this would do as you seem to expect in bash but not in zsh.</p>
</blockquote>
<p>After trying the first option—<code>setopt no_nomatch</code>—my command still errored out. The second one—<code>unsetopt null_glob csh_null_glob</code>— did allow me to type in my unmodified scp command and download my cachegrind files. I never like the idea of just typing in random commands without knowing what they do however. Before making the change persistent in my zsh config files I decided to <a rel="noopener nofollow noreferrer" target="_blank" href="http://unix.stackexchange.com/questions/204803/why-is-nullglob-not-default">do a little reading</a> on the <code>null_glob</code> option. After doing that I didn't really think turning this on was the best option, so I decided to use the other alternative I found in the mailing list post.</p>
<blockquote>
<p>I could just put single quotes around the server path to get it to
work with globbing but after many years of bash I am having trouble
getting into the habbit of using single quotes with scp and it get's
pretty frustrating.</p>
</blockquote>
<p>That's what I decided to do, and lo, it paid off. Globbing worked as expected.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>scp server-local:'/var/www/server/cacheg*' ~/Documents/cachegrinds
</span><span>cachegrind.out.1426 100% 2578 2.5KB/s 00:00
</span><span>cachegrind.out.1427 100% 2574 2.5KB/s 00:00
</span><span>cachegrind.out.1428 100% 9233KB 9.0MB/s 00:00
</span><span>cachegrind.out.1430 100% 2574 2.5KB/s 00:00
</span><span>cachegrind.out.1598 100% 2574 2.5KB/s 00:00
</span><span>cachegrind.out.1600 100% 3021KB 3.0MB/s 00:00
</span><span>cachegrind.out.1602 100% 2174KB 2.1MB/s 00:00
</span><span>cachegrind.out.1604 100% 30KB 30.4KB/s 00:00
</span><span>cachegrind.out.1605 100% 2575 2.5KB/s 00:00
</span><span>cachegrind.out.1778 100% 235 0.2KB/s 00:00
</span><span>cachegrind.out.1919 100% 9190KB 9.0MB/s 00:00
</span><span>cachegrind.out.1927 100% 2174KB 2.1MB/s 00:00
</span><span>cachegrind.out.2021 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.2157 100% 2574 2.5KB/s 00:00
</span><span>cachegrind.out.2293 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.2302 100% 2578 2.5KB/s 00:00
</span><span>cachegrind.out.2346 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.2393 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.2428 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.2445 100% 2443 2.4KB/s 00:00
</span><span>cachegrind.out.2954 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.3139 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.3170 100% 233 0.2KB/s 00:00
</span><span>cachegrind.out.3278 100% 233 0.2KB/s 00:00
</span></code></pre>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="https://en.wikipedia.org/wiki/Glob_%28programming%29">Globbing</a> is a process that expands patterns to filenames. </p>
</div>
Grace: for computer programmers2015-08-08T21:41:00-05:002015-08-08T21:41:00-05:00
Unknown
https://orville.thebennettproject.com/articles/grace-for-computer-programmers/<p>A few years ago my son and I were talking about what he learned in church that Sunday. The end result of that conversation was that I was going to do some reading and then teach him about Grace. Not just any old grace mind you, but God's grace. Fast forward a few years and he still didn't have his lesson (I hadn't done my reading).</p>
<p>Fast forward to this year, and I was invited to facilitate a small group at church. My wife and I got to pick the topic and together we'd lead the discussion of a yet to be determined topic. Seeing the opportunity to kill two birds with the proverbial single stone, I asked her to look up books about grace. That way I'd be able to do some reading about it (being forced to do it to prepare for group) and then be able to go over what I'd learned with my son. And so a plan was born.</p>
<p>That's how I ended up reading Max Lucado's <em>Grace: more than we deserve, greater than we imagine</em>. I've only just started reading, but at the end of the first chapter Lucado gives an illustration of God's grace. Me being me, my mind gave me a more nerd relevant illustration to work with.</p>
<blockquote>
<p>Grace is God as heart surgeon, cracking open your chest, removing your heart—poisoned as it is with pride and pain—and replacing it with his own. Rather than tell you to change, he creates the change. Do you clean up so he can accept you? No, he accepts you and begins cleaning you up.</p>
</blockquote>
<ul>
<li><small>Max Lucado, Grace: more than we deserve, greater than we imagine, p. 10</small></li>
</ul>
<p>This reminded me of one of the tasks I do at work for the Junior Developer I work with. At work we use git to manage our source code, and each feature is developed in a separate branch. Once a feature is ready, the junior dev will let me know his branch is ready so that I can merge it in with the rest of our code.</p>
<p>Sometimes the code isn't up to my personal standard and instead of having the the junior developer redo the task I'll clean up the code myself and then commit it. As I was reading the section quoted above I thought to myself <q>That's just like doing a <code>git cherry-pick</code> and cleaning it up before I commit it!</q></p>
<p>So here's my explanation of grace, for nerds. God is like the Project Lead and you're a Junior Dev. When your code isn't up to God's standard he shows grace by rewriting it and making it better. He makes small changes—and sometimes, big, sweeping changes—instead of making <em>you</em> rewrite the code until it's up to his standard. And when God's all done and commits the code, he gives you credit for the work anyway.</p>
<p>So at a glance people who don't know your code would think, "Wow, nice job! How'd you come up with that?" People who do know how you code would be like, "Hey, the quality of your code's gotten way better. How'd you pull that off?" And that dear junior dev, will be your opportunity to tell people that it's not you that's been doing all this great work, but God.</p>
Configuring Xorg on a Brix Mini PC to work with the Mitsubishi WS-55513 HD1080 rear projection TV2015-03-28T16:35:00-05:002021-03-14T04:10:00-05:00
Unknown
https://orville.thebennettproject.com/articles/working-xorg-config-for-the-mitsubishi-ws55513-tv/<p>I recently bought a barebones mini PC system with the intent of setting it up as a video game and video streaming server. After <em>a lot</em> of searching and reading of reviews, I settled on an AMD based Brix PC from Gigabyte, the <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.amazon.com/gp/product/B00I0G7E7S/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Gigabyte AMD A8-5545M</a>. Unfortunately, by the time I was ready to purchase it, the AMD Brix was out of stock. That's how I ended up with the <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.amazon.com/gp/product/B00FP4MWUW/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Gigabyte GB-BXI3-4010</a>.</p>
<p>After successfully getting Manjaro Linux on a USB drive and installing it, I booted up the Brix box with my Dell monitor connected. As video output was fine with my monitor I assumed all was well with this installation. Intending to hook this up to our old Mitsubishi DLP TV—a Mitsubishi WS-55513 HD1080—I took the Brix box downstairs, connected it to the TV. However, after started it I saw ... nothin'. For some reason I couldn't get video output to the TV. </p>
<p>After <em><strong>much</strong></em> searching on the internets and, one HDMI cable switch, I eventually got video from the Brix box to output video to my TV. I also had to use some custom modelines for Xorg to get rid of some massive overscan<sup class="footnote-reference"><a href="#1">1</a></sup>. The modeline that finally worked was <code>ModeLine "in1080i" 74.5 1760 1888 2096 2208 960 1012 1028 1126 -hsync -vsync interlace </code>. I found this info on the <a rel="noopener nofollow noreferrer" target="_blank" title="Mitsubishi section of the MythTV Modeline Database" href="https://www.mythtv.org/wiki/Modeline_Database#Mitsubishi">MythTV wiki</a>.</p>
<p>I also found myself at the <a rel="noopener nofollow noreferrer" target="_blank" title="Gentoo Wiki Archives site" href="http://www.gentoo-wiki.info/HOWTO_Xorg_HDTV">Gentoo Wiki Archives</a> site which provided these 1080i modelines, along with the 1760 modeline that I found worked.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>#ModeLine "My1080i2" 74.52 1920 1952 2016 2208 1080 1084 1096 1126 -hsync -vsync interlace
</span><span>#ModeLine "Another1080i" 74.250 1920 1960 2008 2200 1080 1084 1096 1126 interlace -hsync -vsync
</span><span>#Modeline "My1920x1080_i" 74.52 1920 1952 2016 2208 1080 1084 1096 1126 -HSync -VSync Interlace
</span><span>#Modeline "in1080_i" 74.52 1760 1888 2096 2208 960 1012 1028 1126 -HSync -VSync Interlace
</span><span>#Modeline "1920x1080_59i" 76.11 1920 1952 2240 2272 1080 1104 1110 1135 interlace
</span><span>#Modeline "1920x1080_60i" 77.60 1920 1952 2240 2272 1080 1104 1110 1135 interlace
</span><span>#Modeline "1920x1080_61i" 79.08 1920 1952 2248 2280 1080 1104 1110 1135 interlace
</span><span>#Modeline "1776x1000_60i" 65.91 1776 1808 2056 2088 1000 1023 1028 1051 interlace
</span></code></pre>
<p>Finding the proper Modeline was half the battle though. I now had to add this information to the Xorg configuration file to get it used. I added this information to the "Monitor" and "Screen" sections of <code>/etc/X11/xorg.conf.d/10-monitor.conf</code> file which you can see below.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Section "Monitor"
</span><span> Identifier "Mitsubishi"
</span><span> ModelName "MEUSPTV1"
</span><span> VendorName "MEL"
</span><span> # Monitor Manufactured week 12 of 2003
</span><span> # EDID version 1.3
</span><span> # Digital Display
</span><span> # Display Physical Size not given. Normal for projectors.
</span><span> # Gamma 2.20
</span><span> # Option "DPMS" "true"
</span><span> # Maximum pixel clock is 80MHz
</span><span> # Option "ModeDebug" "TRUE"
</span><span> Option "PreferredMode" "in1080i"
</span><span>
</span><span> ModeLine "in1080i" 74.5 1760 1888 2096 2208 960 1012 1028 1126 -hsync -vsync interlace
</span><span> Modeline "My1920x1080_i" 74.52 1920 1952 2016 2208 1080 1084 1096 1126 -HSync -VSync Interlace
</span><span> #Modeline "1920x1080i" 74.250 1920 2008 2052 2200 1080 1084 1094 1124 interlace +hsync +vsync
</span><span> Modeline "720x480@59" 27.00 720 736 798 858 480 486 495 525 -hsync -vsync
</span><span> #Modeline "in1080_i" 74.52 1760 1888 2096 2208 960 1012 1028 1126 -HSync -VSync Interlace
</span><span> #Modeline "1920x1080_59i" 76.11 1920 1952 2240 2272 1080 1104 1110 1135 interlace
</span><span> #Modeline "1920x1080_60i" 77.60 1920 1952 2240 2272 1080 1104 1110 1135 interlace
</span><span> #Modeline "1920x1080_61i" 79.08 1920 1952 2248 2280 1080 1104 1110 1135 interlace
</span><span> #Modeline "1776x1000_60i" 65.91 1776 1808 2056 2088 1000 1023 1028 1051 interlace
</span><span>EndSection
</span><span>
</span><span>Section "Screen"
</span><span> Identifier "Screen1"
</span><span> Device "Device0"
</span><span> Monitor "Mitsubishi"
</span><span> DefaultDepth 24
</span><span> SubSection "Display"
</span><span> Depth 16
</span><span> Modes "in1080i" "My1920x1080_i" "1920x540@60" "720x480@59" #Choose the resolution
</span><span> EndSubSection
</span><span> SubSection "Display"
</span><span> Depth 24
</span><span> Modes "in1080i" "My1920x1080_i" "1920x540@60" "720x480@59" #Choose the resolution
</span><span> EndSubSection
</span><span>EndSection
</span></code></pre>
<p>After adding this information to my Xorg config I was able to get the TV to switch to those different resolutions. Of course, only the <code>in_1080i</code> resolution was any good. There were <strong>many</strong> resources used to figure this out so I'll just list them here <sup class="footnote-reference"><a href="#2">2</a></sup>,<sup class="footnote-reference"><a href="#3">3</a></sup>,<sup class="footnote-reference"><a href="#4">4</a></sup>,<sup class="footnote-reference"><a href="#5">5</a></sup>,<sup class="footnote-reference"><a href="#6">6</a></sup>,<sup class="footnote-reference"><a href="#7">7</a></sup>.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>Xorg is the X11 display server. This software is used by the majority of Linux distributions, and other Unices, to display GUIs.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="http://readlist.com/lists/mythtv.org/mythtv-users/2/14235.html">So close,but not quite - a 1080i modeline for my HDTV CRT</a></p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="http://www.highdefforum.com/computers-htpcs/2758-pc-hdtv-issues.html">PC to HDTV issues ...</a></p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">4</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="http://askubuntu.com/questions/248094/how-to-adjust-hdmi-overscan-on-an-intel-ivy-bridge">How to adjust HDMI Overscan on an Intel Ivy Bridge</a></p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">5</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="https://www.mythtv.org/wiki/Modeline_Database">Modeline Database</a></p>
</div>
<div class="footnote-definition" id="6"><sup class="footnote-definition-label">6</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="https://forums.gentoo.org/viewtopic-t-706727-view-previous.html?sid=06d3d8f14377fbf273959b3cf184b070">Forcing resolutions onto a display using xrandr</a></p>
</div>
<div class="footnote-definition" id="7"><sup class="footnote-definition-label">7</sup>
<p><a rel="noopener nofollow noreferrer" target="_blank" href="https://wiki.archlinux.org/index.php/Kernel_mode_setting#Forcing_modes_and_EDID">Forcing EDID modes in Kernel Mode Settings</a></p>
</div>
Recreating raster images as SVGs: part 22015-01-31T11:35:00-05:002015-01-31T11:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/recreating-raster-images-as-svgs-part-2/<p>When <a href="https://orville.thebennettproject.com/articles/recreating-raster-images-as-svgs-part-1/">last we spoke</a> we had just finished discussing the merits of delivering assets as SVGs instead of PNGs, or other raster formats. We found that SVGs offered greater file size savings and compressibility while simultaneously offering superior image quality. We also saw that we could optimize SVGs to save on file size even more.</p>
<blockquote>
<p>So how <strong>does</strong> one <em>optimize</em> an SVG?</p>
</blockquote>
<p>Great question! I'm glad you asked. You see drawing apps tend to use the general purpose and quite versatile <code><path></code> tag to create objects in an SVG image. By using more specific tags we can cut down on the amount of text used to describe an object thereby saving on file size. We can also <em>define</em> objects in the <code><defs></code> tag, and recall them for <em>use</em> later via the <code><use></code> tag. Finally, for objects which repeat, we can use <code><pattern></code> to create a repeating pattern. Patterns are saved in <strong><defs></strong> and used in an object's <code>fill</code> attribute, as we'll see below.</p>
<h2 id="background">Background</h2>
<p>Instead of explaining every step in minute detail I'll show you the general steps used to optimize our owl image. For each type of optimization performed I'll take an example from the image and walk through it. Hopefully there'll be enough info here to help you:</p>
<ol>
<li>understand what happened with the parts of the image left unexplained</li>
<li>play around with the <a href="/images/owl-orig.svg">original image</a>, working along with the sections to aid in your understanding of what we're doing.</li>
</ol>
<p>We'll start with the chevron background. It is actually the <code><g id="chevron"></code> group repeated 12 times. The first three are shown below.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="100%" height="282" viewBox="0, 0, 612, 282">
<g id="Layer_2">
<g id="chevron">
<path d="M-30,81.704 L102.37,-50.667 L132.2,-20.837 L-0.171,111.533 L-30,81.704 z" fill="#959595"/>
<path d="M102.37,-50.667 L234.741,81.704 L204.911,111.533 L72.541,-20.837 L102.37,-50.667 z" fill="#959595"/>
<path d="M102.366,68.675 L234.736,201.046 L204.907,230.875 L72.536,98.505 L102.366,68.675 z" fill="#959595"/>
<path d="M-30,201.041 L102.37,68.67 L132.2,98.5 L-0.171,230.87 L-30,201.041 z" fill="#959595"/>
</g>
<g id="chevron">
<path d="M175.283,81.704 L307.653,-50.667 L337.482,-20.837 L205.112,111.533 L175.283,81.704 z" fill="#959595"/>
<path d="M307.653,-50.667 L440.023,81.704 L410.194,111.533 L277.824,-20.837 L307.653,-50.667 z" fill="#959595"/>
<path d="M307.648,68.675 L440.018,201.046 L410.189,230.875 L277.819,98.505 L307.648,68.675 z" fill="#959595"/>
<path d="M175.283,201.041 L307.653,68.67 L337.482,98.5 L205.112,230.87 L175.283,201.041 z" fill="#959595"/>
</g>
<g id="chevron">
<path d="M380.432,81.704 L512.802,-50.667 L542.631,-20.837 L410.261,111.533 L380.432,81.704 z" fill="#959595"/>
<path d="M512.802,-50.667 L645.172,81.704 L615.343,111.533 L482.973,-20.837 L512.802,-50.667 z" fill="#959595"/>
<path d="M512.797,68.675 L645.168,201.046 L615.338,230.875 L482.968,98.505 L512.797,68.675 z" fill="#959595"/>
<path d="M380.432,201.041 L512.802,68.67 L542.631,98.5 L410.261,230.87 L380.432,201.041 z" fill="#959595"/>
</g>
</g>
</svg></p>
<p>And here's the original markup that gave us the image above.</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"chevron"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M-30,81.704 L102.37,-50.667 L132.2,-20.837 L-0.171,111.533 L-30,81.704 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M102.37,-50.667 L234.741,81.704 L204.911,111.533 L72.541,-20.837 L102.37,-50.667 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M102.366,68.675 L234.736,201.046 L204.907,230.875 L72.536,98.505 L102.366,68.675 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M-30,201.041 L102.37,68.67 L132.2,98.5 L-0.171,230.87 L-30,201.041 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"></g>
</span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"chevron"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M175.283,81.704 L307.653,-50.667 L337.482,-20.837 L205.112,111.533 L175.283,81.704 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M307.653,-50.667 L440.023,81.704 L410.194,111.533 L277.824,-20.837 L307.653,-50.667 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M307.648,68.675 L440.018,201.046 L410.189,230.875 L277.819,98.505 L307.648,68.675 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M175.283,201.041 L307.653,68.67 L337.482,98.5 L205.112,230.87 L175.283,201.041 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"></g>
</span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"chevron"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M380.432,81.704 L512.802,-50.667 L542.631,-20.837 L410.261,111.533 L380.432,81.704 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M512.802,-50.667 L645.172,81.704 L615.343,111.533 L482.973,-20.837 L512.802,-50.667 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M512.797,68.675 L645.168,201.046 L615.338,230.875 L482.968,98.505 L512.797,68.675 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M380.432,201.041 L512.802,68.67 L542.631,98.5 L410.261,230.87 L380.432,201.041 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"></g>
</span></code></pre>
<p>To create this background:</p>
<ol>
<li>I define a group of rectangles at a 90 degree angles to each other.</li>
<li>Next I rotate the group by 45 degrees around the center point of the group.</li>
<li>Finally, I shift the whole thing up a bit because I want to.</li>
</ol>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="100%" height="282" viewBox="0, 0, 712, 282">
<g id="Layer_1">
<g id="chevron" fill="#808080">
<rect id="chevron-piece" x="0" y="0" width="187.2" height="42.185" />
<rect id="chevron-piece2" x="145.015" y="0" height="187.2" width="42.185" />
<rect id="chevron-piece3" x="60.624" y="84.384" height="187.2" width="42.185" />
<rect id="chevron-piece4" x="-84.384" y="84.384" width="187.2" height="42.185" />
</g>
</g>
<g id="Layer_2" transform="translate(283 0)">
<g id="chevron" fill="#808080" transform="rotate(-45 101.3705 90.104)">
<rect id="chevron-piece" x="0" y="0" width="187.2" height="42.185" />
<rect id="chevron-piece2" x="145.015" y="0" height="187.2" width="42.185" />
<rect id="chevron-piece3" x="60.624" y="84.384" height="187.2" width="42.185" />
<rect id="chevron-piece4" x="-84.384" y="84.384" width="187.2" height="42.185" />
</g>
</g>
<g id="Layer_3" transform="translate(566 0)">
<g id="chevron" fill="#808080" transform="rotate(-45 101.3705 90.104) translate(17 0)">
<rect id="chevron-piece" x="0" y="0" width="187.2" height="42.185" />
<rect id="chevron-piece2" x="145.015" y="0" height="187.2" width="42.185" />
<rect id="chevron-piece3" x="60.624" y="84.384" height="187.2" width="42.185" />
<rect id="chevron-piece4" x="-84.384" y="84.384" width="187.2" height="42.185" />
</g>
</g>
</svg>
<p>Above you see the results of steps 1, 2, and 3. Below is the code which does what was explained above. Our right-angle <strong><rect></strong> s are defined in <code><g id="chevron"></code>.</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><defs>
</span><span> </span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"chevron" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#fff" </span><span style="color:#6486ab;">transform=</span><span style="color:#d07711;">"rotate(-45 101.3705 90.104) translate(17 0)"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><rect id=</span><span style="color:#d07711;">"chevron-piece" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">width=</span><span style="color:#d07711;">"187.2" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"42.185" </span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><rect id=</span><span style="color:#d07711;">"chevron-piece2" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"145.015" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"187.2" </span><span style="color:#6486ab;">width=</span><span style="color:#d07711;">"42.185" </span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><rect id=</span><span style="color:#d07711;">"chevron-piece3" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"60.624" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"84.384" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"187.2" </span><span style="color:#6486ab;">width=</span><span style="color:#d07711;">"42.185" </span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><rect id=</span><span style="color:#d07711;">"chevron-piece4" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"-84.384" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"84.384" </span><span style="color:#6486ab;">width=</span><span style="color:#d07711;">"187.2" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"42.185" </span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"></g>
</span><span> </span><span style="color:#6486ab;"><pattern id=</span><span style="color:#d07711;">"chevron-fill" </span><span style="color:#6486ab;">width=</span><span style="color:#d07711;">"205" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"119" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"29" </span><span style="color:#6486ab;">patternUnits=</span><span style="color:#d07711;">"userSpaceOnUse"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><rect width=</span><span style="color:#d07711;">"205" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"119" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><use xlink:href=</span><span style="color:#d07711;">"#chevron" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"-8.186" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"></pattern>
</span><span style="color:#6486ab;"></defs>
</span><span style="color:#6486ab;"><rect id=</span><span style="color:#d07711;">"chevron-pattern" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">width=</span><span style="color:#d07711;">"612" </span><span style="color:#6486ab;">height=</span><span style="color:#d07711;">"792" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"url(#chevron-fill)"</span><span style="color:#6486ab;">/>
</span></code></pre>
<p>Once the shape is defined I take the entire group and rotate it by 45 degrees. The <code>rotate()</code> function rotates an object about the <strong>x</strong> and <strong>y</strong> coordinates given. Otherwise it rotates an object about <code>(0 0)</code>.<sup class="footnote-reference"><a href="#5">1</a></sup></p>
<p>What I wanted to do after rotation was to shift the group to the right by 17px. If you try to edit the value in the browser's inspector you will quickly realize that this is not actually happening. The code <em>seems</em> to result in movement of the <code>x</code> <em>and</em> <code>y</code> coordinates. That's because <code>transform</code> parameters are applied from left to right, in the order that they are written. This means that <code>transform="rotate(-45 101.3705 90.104) translate(17 0)"</code> will rotate our group around <code>(101.3705 90.104)</code> and then move this rotated object 17px along the x axis. But since our x-axis is rotated by 45 degrees, it seems to be moving in the x and y direction.</p>
<p>Hopefully it's clear why I should have done <code>transform=" translate(17 0) rotate(-45 101.3705 90.104)"</code> instead (move, <strong>then</strong> rotate) to achieve horizontal movement along the original x-axis. Why keep the mistake then? Makes for a great teachable moment I think. Once I had the chevron group in place I created a pattern for it as shown above.</p>
<p><a target="_blank" rel="external" href="http://www.w3.org/TR/SVG/concepts.html">The SVG specification document</a> actually does a good job of explaining the different pattern parameters. The pattern contains a reference to our rotated chevron via the <use> tag. Meanwhile a <rect> the size of the canvas was created and its <code>fill</code> value — instead of being a color, or a gradient<sup class="footnote-reference"><a href="#4">2</a></sup> — is the id of our pattern.</p>
<h2 id="eyes">Eyes</h2>
<p>Let's move on to the eyes. They are simple circles. Height = width with a radius that's half of the diameter (which is the width). </p>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="100%" height="184" viewBox="131, 181, 346, 184">
<g id="Layer_2">
<g id="eye">
<path d="M386,365 C335.742,365 295,323.81 295,273 C295,222.19 335.742,181 386,181 C436.258,181 477,222.19 477,273 C477,323.81 436.258,365 386,365 z" fill="#959595"/>
<path d="M389.5,336 C351.116,336 320,304.884 320,266.5 C320,228.116 351.116,197 389.5,197 C427.884,197 459,228.116 459,266.5 C459,304.884 427.884,336 389.5,336 z" fill="#FFFFFF"/>
<path d="M389.5,308.6 C363.653,308.6 342.7,287.647 342.7,261.8 C342.7,235.953 363.653,215 389.5,215 C415.347,215 436.3,235.953 436.3,261.8 C436.3,287.647 415.347,308.6 389.5,308.6 z" fill="#333333"/>
<path d="M374.2,285 C363.541,285 354.9,276.359 354.9,265.7 C354.9,255.041 363.541,246.4 374.2,246.4 C384.859,246.4 393.5,255.041 393.5,265.7 C393.5,276.359 384.859,285 374.2,285 z" fill="#FFFFFF"/>
</g>
<g id="eye">
<path d="M222,365 C171.742,365 131,323.81 131,273 C131,222.19 171.742,181 222,181 C272.258,181 313,222.19 313,273 C313,323.81 272.258,365 222,365 z" fill="#959595"/>
<path d="M225.5,336 C187.116,336 156,304.884 156,266.5 C156,228.116 187.116,197 225.5,197 C263.884,197 295,228.116 295,266.5 C295,304.884 263.884,336 225.5,336 z" fill="#FFFFFF"/>
<path d="M225.5,308.6 C199.653,308.6 178.7,287.647 178.7,261.8 C178.7,235.953 199.653,215 225.5,215 C251.347,215 272.3,235.953 272.3,261.8 C272.3,287.647 251.347,308.6 225.5,308.6 z" fill="#333333"/>
<path d="M210.2,285 C199.541,285 190.9,276.359 190.9,265.7 C190.9,255.041 199.541,246.4 210.2,246.4 C220.859,246.4 229.5,255.041 229.5,265.7 C229.5,276.359 220.859,285 210.2,285 z" fill="#FFFFFF"/>
</g>
</g>
</svg>
<p>Here's the original svg code for that</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"Layer_2"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"eye"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M386,365 C335.742,365 295,323.81 295,273 C295,222.19 335.742,181 386,181 C436.258,181 477,222.19 477,273 C477,323.81 436.258,365 386,365 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M389.5,336 C351.116,336 320,304.884 320,266.5 C320,228.116 351.116,197 389.5,197 C427.884,197 459,228.116 459,266.5 C459,304.884 427.884,336 389.5,336 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#FFFFFF"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M389.5,308.6 C363.653,308.6 342.7,287.647 342.7,261.8 C342.7,235.953 363.653,215 389.5,215 C415.347,215 436.3,235.953 436.3,261.8 C436.3,287.647 415.347,308.6 389.5,308.6 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#333333"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M374.2,285 C363.541,285 354.9,276.359 354.9,265.7 C354.9,255.041 363.541,246.4 374.2,246.4 C384.859,246.4 393.5,255.041 393.5,265.7 C393.5,276.359 384.859,285 374.2,285 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#FFFFFF"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"></g>
</span><span> </span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"eye"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M222,365 C171.742,365 131,323.81 131,273 C131,222.19 171.742,181 222,181 C272.258,181 313,222.19 313,273 C313,323.81 272.258,365 222,365 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M225.5,336 C187.116,336 156,304.884 156,266.5 C156,228.116 187.116,197 225.5,197 C263.884,197 295,228.116 295,266.5 C295,304.884 263.884,336 225.5,336 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#FFFFFF"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M225.5,308.6 C199.653,308.6 178.7,287.647 178.7,261.8 C178.7,235.953 199.653,215 225.5,215 C251.347,215 272.3,235.953 272.3,261.8 C272.3,287.647 251.347,308.6 225.5,308.6 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#333333"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><path d=</span><span style="color:#d07711;">"M210.2,285 C199.541,285 190.9,276.359 190.9,265.7 C190.9,255.041 199.541,246.4 210.2,246.4 C220.859,246.4 229.5,255.041 229.5,265.7 C229.5,276.359 220.859,285 210.2,285 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#FFFFFF"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"></g>
</span><span style="color:#6486ab;"></g>
</span></code></pre>
<p>What we have above is a group of circles which make up the eye grouped with a <code><g></code> tag. What's the <code><g></code>'s purpose? To group things. We also have an <strong>id</strong> on the <strong><g></strong> to help identify it. So when this was originally made in iDraw I made an eye, grouped it, named the group, and then copied it to create the other eye. Then I drug the copied eye over to its new position. Copying the original eye duplicated the <strong>id</strong> attribute sadly; a big no-no for HTML/XML documents, where all ids must be unique. In the case of an SVG (which is an xml document) if we target that id with javascript weird things will happen. Part of the optimization process then, will include removing these duplicate ids.</p>
<p>Here is the optimized code:</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><defs>
</span><span> </span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"eye"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><circle cx=</span><span style="color:#d07711;">"222" </span><span style="color:#6486ab;">cy=</span><span style="color:#d07711;">"273" </span><span style="color:#6486ab;">r=</span><span style="color:#d07711;">"92" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#959595"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><circle cx=</span><span style="color:#d07711;">"225.5" </span><span style="color:#6486ab;">cy=</span><span style="color:#d07711;">"266.5" </span><span style="color:#6486ab;">r=</span><span style="color:#d07711;">"69.5" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#fff"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><circle cx=</span><span style="color:#d07711;">"226" </span><span style="color:#6486ab;">cy=</span><span style="color:#d07711;">"262" </span><span style="color:#6486ab;">r=</span><span style="color:#d07711;">"47" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#333"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><circle cx=</span><span style="color:#d07711;">"210.5" </span><span style="color:#6486ab;">cy=</span><span style="color:#d07711;">"265.5" </span><span style="color:#6486ab;">r=</span><span style="color:#d07711;">"19.5" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#fff"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"></g>
</span><span style="color:#6486ab;"></defs>
</span><span style="color:#6486ab;"><g id=</span><span style="color:#d07711;">"zowl"</span><span style="color:#6486ab;">>
</span><span> </span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"left-eye" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#eye" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"1" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0"</span><span style="color:#6486ab;">/>
</span><span> </span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"right-eye" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#eye" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"167" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"></g>
</span></code></pre>
<p>Quite a difference isn't it. You'll notice it's much more efficient to define a circle using <code><circle></code> than to use a path.</p>
<h2 id="ears-and-nose">Ears and Nose</h2>
<p>Next came the ears and the nose. These three objects are all the same since the ears are just rotated and scaled versions of the nose.</p>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="100%" height="203" viewBox="135, 139, 344, 203">
<g>
<path d="M154.139,199.144 L153.31,196.391 C147.811,188.505 143.635,179.795 140.422,170.756 C135.002,154.642 136.416,140.5 136.416,140.5 L136.481,140.519 L136.462,140.454 C136.462,140.454 150.604,139.04 166.718,144.46 C175.79,147.573 184.45,151.911 192.353,157.348 L195.106,158.177 L154.139,199.144 z" fill="#F23897" id="ear-l"/>
<path d="M459.467,199.144 L460.296,196.391 C465.795,188.505 469.971,179.795 473.184,170.756 C478.604,154.642 477.19,140.5 477.19,140.5 L477.125,140.519 L477.145,140.454 C477.145,140.454 463.002,139.04 446.888,144.46 C437.817,147.573 429.156,151.911 421.253,157.348 L418.5,158.177 L459.467,199.144 z" fill="#F23897" id="ear-r"/>
<path d="M334.416,288 L333.055,290.534 C331.368,299.997 328.162,309.109 324.042,317.773 C316.48,333 305.48,342 305.48,342 L305.448,341.94 L305.416,342 C305.416,342 294.416,333 286.854,317.773 C282.641,309.157 279.584,299.966 277.841,290.533 L276.48,288 L334.416,288 z" fill="#F6B7D6" id="nose"/>
</g>
</svg>
<p>Below you'll notice there are three separate path objects.</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"ear-l" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M154.139,199.144 L153.31,196.391 C147.811,188.505 143.635,179.795 140.422,170.756 C135.002,154.642 136.416,140.5 136.416,140.5 L136.481,140.519 L136.462,140.454 C136.462,140.454 150.604,139.04 166.718,144.46 C175.79,147.573 184.45,151.911 192.353,157.348 L195.106,158.177 L154.139,199.144 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F23897"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"ear-r" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M459.467,199.144 L460.296,196.391 C465.795,188.505 469.971,179.795 473.184,170.756 C478.604,154.642 477.19,140.5 477.19,140.5 L477.125,140.519 L477.145,140.454 C477.145,140.454 463.002,139.04 446.888,144.46 C437.817,147.573 429.156,151.911 421.253,157.348 L418.5,158.177 L459.467,199.144 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F23897"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"nose" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M334.416,288 L333.055,290.534 C331.368,299.997 328.162,309.109 324.042,317.773 C316.48,333 305.48,342 305.48,342 L305.448,341.94 L305.416,342 C305.416,342 294.416,333 286.854,317.773 C282.641,309.157 279.584,299.966 277.841,290.533 L276.48,288 L334.416,288 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F6B7D6"</span><span style="color:#6486ab;">/>
</span></code></pre>
<p>Instead of keeping these three we define one in <code><defs></code> and reference it via <code><use></code> and the <code>xlink:href</code> attribute. One of the ears requires a rotation of the <strong><use></strong>. The second ear references the first ear and translates it, then flips it horizontally.</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><defs>
</span><span> </span><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"appendage" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M57.936,-0 L56.575,2.533 C54.888,11.997 51.682,21.109 47.562,29.773 C40,45 29,54 29,54 L28.968,53.94 L28.936,54 C28.936,54 17.936,45 10.374,29.773 C6.161,21.157 3.104,11.966 1.361,2.533 L0,-0 L57.936,-0 z"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"></defs>
</span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"ear-l" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#appendage" </span><span style="color:#6486ab;">transform=</span><span style="color:#d07711;">"rotate(125 161.94 174.78)" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"134.286" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"166.274" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F23897"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"ear-r" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#ear-l" </span><span style="color:#6486ab;">transform=</span><span style="color:#d07711;">"translate(610 0) scale(-1 1) "</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"nose" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#appendage" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"279" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"288" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F6B7D6"</span><span style="color:#6486ab;">/>
</span></code></pre>
<h2 id="wings">Wings</h2>
<p>Here are the wings we'll be flying high with today.</p>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="100%" height="210" viewBox="65, 325, 485, 210">
<defs>
</defs>
<g>
<path id="hand-r" d="M534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C530.322,537.049 462.001,406.401 466.795,350.665 C468.206,334.269 477.839,327.491 491.244,327.491 C504.649,327.491 514.903,342.109 518.335,350.066 C531.52,380.631 550.666,490.547 534.517,527.46 z" fill="#F6B7D6"/>
<path id="hand-l" d="M81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C85.614,537.049 153.935,406.401 149.141,350.665 C147.73,334.269 138.097,327.491 124.692,327.491 C111.287,327.491 101.033,342.109 97.6,350.066 C84.416,380.631 65.269,490.547 81.419,527.46 z" fill="#F6B7D6"/>
</g>
</svg>
<p>Now this one's interesting. Since we only have two hands (wings) we don't save a whole lot by using <code><defs></code> and <code><use></code> tags here. As a matter of fact, use of the <code><defs></code> tag isn't really necessary<sup class="footnote-reference"><a href="#1">3</a></sup>. Why do it then? Just to keep the markup clean. And speaking of the markup, here it is:</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"hand-r" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C534.517,527.46 534.517,527.46 534.517,527.46 C530.322,537.049 462.001,406.401 466.795,350.665 C468.206,334.269 477.839,327.491 491.244,327.491 C504.649,327.491 514.903,342.109 518.335,350.066 C531.52,380.631 550.666,490.547 534.517,527.46 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F6B7D6"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"hand-l" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C85.614,537.049 153.935,406.401 149.141,350.665 C147.73,334.269 138.097,327.491 124.692,327.491 C111.287,327.491 101.033,342.109 97.6,350.066 C84.416,380.631 65.269,490.547 81.419,527.46 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F6B7D6"</span><span style="color:#6486ab;">/>
</span></code></pre>
<p>Our optimized code takes the second hand — <code>id="hand-l"</code> above — and sticks it in a <code><defs></code> as <code>id="hand"</code>. Then we use it later to make our left and (horizontally flipped) right hands. If you look below you'll see <code>transform="scale(-1 1) translate(-616 0)"</code>. We use <strong>scale</strong> to mirror objects by giving it negative values. The <strong>scale(-1 1)</strong> changes the x-axis values, flipping our wings horizontally.</p>
<p>Using this function changes the x coordinate values and makes them negative. Since the x values become negative, our wing will be outside the boundary of our canvas. We compensate for this by using <strong>translate</strong> to move our wing to its new location within the bounds of our canvas.</p>
<pre data-lang="xml" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#6486ab;"><defs>
</span><span> </span><span style="color:#6486ab;"><path id=</span><span style="color:#d07711;">"hand" </span><span style="color:#6486ab;">d=</span><span style="color:#d07711;">"M81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C81.419,527.46 81.419,527.46 81.419,527.46 C85.614,537.049 153.935,406.401 149.141,350.665 C147.73,334.269 138.097,327.491 124.692,327.491 C111.287,327.491 101.033,342.109 97.6,350.066 C84.416,380.631 65.269,490.547 81.419,527.46 z" </span><span style="color:#6486ab;">fill=</span><span style="color:#d07711;">"#F6B7D6"</span><span style="color:#6486ab;">/>
</span><span style="color:#6486ab;"></defs>
</span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"hand-r" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#hand" </span><span style="color:#6486ab;">transform=</span><span style="color:#d07711;">"scale(-1 1) translate(-616 0)" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0"</span><span style="color:#6486ab;">></use>
</span><span style="color:#6486ab;"><use id=</span><span style="color:#d07711;">"hand-l" </span><span style="color:#6486ab;">xlink:href=</span><span style="color:#d07711;">"#hand" </span><span style="color:#6486ab;">x=</span><span style="color:#d07711;">"0" </span><span style="color:#6486ab;">y=</span><span style="color:#d07711;">"0"</span><span style="color:#6486ab;">/>
</span></code></pre>
<p>Eventually we end up with a file that, as you'll see below, brings quite some savings from the original while looking just as good.</p>
<table><thead><tr><th style="text-align: center">Original</th><th style="text-align: center">Optimized</th></tr></thead><tbody>
<tr><td style="text-align: center"><img src="/images/owl-orig.svg" alt="original owl SVG illustration" /></td><td style="text-align: center"><img src="/images/owl.svg" alt="optimized owl SVG illustration" /></td></tr>
</tbody></table>
<h2 id="conclusion">Conclusion</h2>
<p>After going through all this trouble a very good question to ask is, <q>Was it worth it?</q> My answer is: <strong>it depends</strong>.</p>
<ul>
<li>If you're goal is to animate SVGs later, your best bet is actually to leave your <code><path></code>s intact<sup class="footnote-reference"><a href="#2">4</a></sup>.</li>
<li>If you're just using them as static images I'd recommend getting those file sizes down as much as possible. You can see from the table below that optimization of our owl image gives us ~67% savings in both our normal and compressed SVG.</li>
</ul>
<h4 id="table-1-file-size-comparison-between-svg-owl-image">Table 1. File size comparison between SVG owl image</h4>
<table><thead><tr><th></th><th style="text-align: center">SVG</th><th style="text-align: center">Compressed SVG</th></tr></thead><tbody>
<tr><td>Original file size</td><td style="text-align: center">16K</td><td style="text-align: center">5.6K <i class="fa fa-check green"></i></td></tr>
<tr><td>Optimized file size</td><td style="text-align: center">5.3K</td><td style="text-align: center">1.8K <i class="fa fa-check green"></i></td></tr>
<tr><td>% savings of optimization</td><td style="text-align: center">66.9%</td><td style="text-align: center">67.9%</td></tr>
</tbody></table>
<p>Comments? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter.</p>
<h2 id="addendum">Addendum</h2>
<h3 id="optimization-tools">Optimization Tools</h3>
<p>Optimizing by hand, while great for learning, does become tedious after a while. It sure would be great if there were some thing, some tool we could use to help us. And lo', there is just such a tool by the name of <a target="_blank" rel="external" href="https://jakearchibald.github.io/svgomg/">SVGOMG</a>.<sup class="footnote-reference"><a href="#3">5</a></sup> This is actually based on the node.js app <a target="_blank" rel="external" href="https://github.com/svg/svgo">SVGO</a>, but what makes SVGOMG much nicer is that we get a live preview of the changes it proposes.</p>
<p>While SVGO won't replace redundant items with <code><pattern></code> or use <code><circle></code> and <code><rect></code> where possible, it still achieves considerable file size savings<sup class="footnote-reference"><a href="#3">5</a></sup>. Given that, SVGO and SVGOMG are promising tools for developers in their constant battle against slow-loading sites and heavy apps.</p>
<p>Combined, manual and programmatic optimization of SVGs promise considerable file size savings. Moreso than is attainable by either technique individually. At least one of these techniques should be used before declaring a project production-ready.</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">3</sup>
<p>Anything with a unique <strong>id</strong> can be referenced from a <code><use></code> tag via the <strong>xlink:href</strong> attribute. Also, both of our hands are already at the positions I need them to be in, so I will not need to move it to a new position using the <strong>x</strong> and <strong>y</strong> attributes). I don't really gain anything by first hiding it in a <code><defs></code> tag, and then showing it later in the <code><use></code>.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">4</sup>
<p>Some SVG libraries, like <a target="_blank" rel="external" href="https://dmitrybaranovskiy.github.io/raphael/">Raphael</a>, only work with <code><path></code> so converting to <code><circle></code> or other shapes wouldn't be helpful if you're planning on working with these libraries. You should still be able to do some optimization, e.g. using <code><pattern></code> to minimize duplication.</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">5</sup>
<p>It is <em><strong>very important</strong></em> to look at the output SVGO produces carefully because it can distort the final image when certain options are checked. I've found this to be particularly true when SMIL animations and transforms are in play.</p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">2</sup>
<p>Yep. It's possible to <a target="_blank" rel="external" href="http://www.w3.org/TR/SVG/pservers.html#Gradients">create gradients</a> via the <code><linearGradient></code> and <code><radialGradient></code> tags, stick them in <code><defs></code>, then use them as <code>fill</code> values.</p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">1</sup>
<p>For objects that aren't actually located at <code>(0 0)</code>, the result is likely not what you expect. To avoid this you can translate to (0 0), rotate, then translate back to the desired position.</p>
</div>
Recreating raster images as SVGs: part 12015-01-27T15:25:00-05:002015-01-27T15:25:00-05:00
Unknown
https://orville.thebennettproject.com/articles/recreating-raster-images-as-svgs-part-1/<p>Lazyweb, I'm going to share something with you today that I hope blows your mind. I'm going to show you how <em>utterly awesome</em> SVGs are for certain types of images. What I'll be doing is recreating an image of an owl with a chevron background. Here is the source image:</p>
<p><img src="/images/owl.jpg" alt="owl raster illustration" /></p>
<p>As you see, the image is primarily composed of simple shapes, making it perfect for vectorization. The SVG specification has shape primitives which account for a lot of the shapes we'll be using here, along with the more general purpose <code><path></code>. For example, we'll use <code><circle></code> and <code><rect></code> in our final image whenever we can, instead of the generated <code><path></code> which our a drawing program — iDraw<sup class="footnote-reference"><a href="#1">1</a></sup> — gives us.</p>
<p>In part 1 of this series I'll give a high level overview of the steps I took to recreate the original image then show just how much we save by using an SVG instead. Part 2 will break down just how I arrived at my optimized SVG and launch into a short discussion of whether it was worth it.</p>
<p>Enough chitchat though, let's get to work. Our owl above is composed of six shapes:</p>
<ul>
<li>the body - oval</li>
<li>the eyes/toes - circles</li>
<li>the leg - quadrilateral</li>
<li>the wings - stretched oval</li>
<li>the ears/nose - deformed triangle</li>
<li>the feathers - circle + deformed lines</li>
</ul>
<p>We also have a chevron background which is composed of a simple shape: rectangles.</p>
<p>The more complicated shapes were created from simple shapes to begin with.</p>
<ul>
<li>The nose/ears were made from equilateral triangles with anchor points dragged to create the slight curve on the sides.</li>
<li>The wings/hands were made from a circle with the bottom anchor dragged down to the desired point.</li>
<li>The feathers were created from circles and lines according to <a rel="noopener nofollow noreferrer" target="_blank" href="https://creativecure.wordpress.com/2010/08/18/rain-drop-shape-adobe-illustrator-cs5/">this raindrop tutorial</a>.</li>
<li>The chevron was created as two pairs of rectangles at right angles (90˚), which was later rotated to 45˚.</li>
</ul>
<p>That ends the image creation portion of our show. Here is the recreated svg image, you may notice I've taken some artistic license and subtly changed things.
<img src="/images/owl.svg" alt="owl svg image" /></p>
<p>I exported my owl as an SVG and a PNG and the file sizes are shown in the table
below. Before we get to that though, a little explanation is in order.</p>
<ul>
<li>The <q>Optimized</q> PNG is a 256-color png, whereas the original has the usual 16 million or so colors.</li>
<li>The original SVG is the code, as given to us by iDraw<sup class="footnote-reference"><a href="#1">1</a></sup>. The optimized SVG has replaced the iDraw-generated code with the SVG primitives such as <code><circle></code> and <code><rect></code> where possible. It also uses <code><pattern></code>s<sup class="footnote-reference"><a href="#2">2</a></sup> and <code><defs></code><sup class="footnote-reference"><a href="#3">3</a></sup> where possible.
<br/></li>
</ul>
<h4 id="table-1-file-size-comparison-between-png-and-svg-owl-image">Table 1. File size comparison between PNG and SVG owl image</h4>
<table><thead><tr><th></th><th style="text-align: center">@2x PNG</th><th style="text-align: center">PNG</th><th style="text-align: center">SVG</th><th style="text-align: center">Compressed SVG</th></tr></thead><tbody>
<tr><td>Original file size</td><td style="text-align: center">191K</td><td style="text-align: center">75K</td><td style="text-align: center">16K</td><td style="text-align: center">5.6K <i class="fa fa-check green"></i></td></tr>
<tr><td>Optimized file size</td><td style="text-align: center">54K</td><td style="text-align: center">24K</td><td style="text-align: center">5.3K</td><td style="text-align: center">1.8K <i class="fa fa-check green"></i></td></tr>
</tbody></table>
<p>From <em>Table 1</em> we can see huge file size savings when comparing this SVG to the exported PNGs. It clearly a win to use them if only to save on size. Another advantage it that because SVGs scale so well, if we need them at larger sizes, the image quality will not suffer from pixelation or bluriness<sup class="footnote-reference"><a href="#4">4</a></sup>. We also don't need to create multiple assets @2x, @3x, etc to get this improved visual fidelity.</p>
<p>This ends up saving us time in the creation and testing process. I mean, how many times have you delivered assets, or had them delivered to you, only to realize that you don't have the mobile version, or the retina version you need. Having one asset we can use for all devices saves us in the design, development and testing phases of creation.</p>
<p>I'm not even going to touch on other advantages of SVGs such as being able to change colors and add simple animations using CSS or Javascript. But the fact that we have the option of turning a static image into a moving one, given a few lines of code is a huge advantage over any raster image format. That's another (in the pipeline) article for another day however.</p>
<h4 id="table-2-percent-difference-in-svg-file-size-compared-to-1x-png-equivalent">Table 2. Percent difference in SVG file size compared to @1x PNG equivalent</h4>
<table><thead><tr><th>File type</th><th style="text-align: center">Difference compared to @1x PNG</th></tr></thead><tbody>
<tr><td>@1x PNG</td><td style="text-align: center">0%</td></tr>
<tr><td>Optimized @1x PNG</td><td style="text-align: center">68%</td></tr>
<tr><td>SVG</td><td style="text-align: center">78.7%</td></tr>
<tr><td>Compressed SVG</td><td style="text-align: center">92.5%</td></tr>
<tr><td>Optimized SVG</td><td style="text-align: center">92.9 %</td></tr>
<tr><td>Compressed and Optimized SVG</td><td style="text-align: center">97.6%</td></tr>
</tbody></table>
<p><em>Table 2</em> takes a slightly different look at the data in <em>Table 1</em>, this time comparing % savings to the @1x PNG file. What we see here is that compared to our optimized PNG our SVG only offers us about a 10% savings in file size. Until it's compressed. At that point our (still unoptimized) SVG is <strong>92% smaller</strong> than our unoptimized PNG. This is <strong>huge</strong> and shouldn't be ignored.</p>
<p>For better or worse, optimizing assets is a process that takes time. This is true whether we're optimizing raster or vector graphics. By serving compressed SVGs, <em>which is nothing more than a simple switch at the server level</em><sup class="footnote-reference"><a href="#5">5</a></sup>, we've: </p>
<ol>
<li>saved our user's data, </li>
<li>saved our client's bandwidth, </li>
<li>provided a superior visual experience, </li>
<li>which is also responsive. </li>
</ol>
<p>All this was basically for <q>free</q> once the original image is created. Even if you don't care about high resolution/retina displays you can benefit from using SVGs.</p>
<h4 id="table-3-percent-difference-in-svg-file-size-compared-to-2x-png-equivalent">Table 3. Percent difference in SVG file size compared to @2x PNG equivalent</h4>
<table><thead><tr><th>File type</th><th style="text-align: center">Difference compared to @2x PNG</th></tr></thead><tbody>
<tr><td>@2x PNG</td><td style="text-align: center">0%</td></tr>
<tr><td>Optimized @2x PNG</td><td style="text-align: center">71.7%</td></tr>
<tr><td>SVG</td><td style="text-align: center">91.6%</td></tr>
<tr><td>Compressed SVG</td><td style="text-align: center">97.1%</td></tr>
<tr><td>Optimized SVG</td><td style="text-align: center">97.2%</td></tr>
<tr><td>Compressed and Optimized SVG</td><td style="text-align: center">99.1%</td></tr>
</tbody></table>
<p><em>Table 3</em> shows us that there are even more dramatic file size savings to be had when comparing SVGs to @2x assets. At this point SVGs might not look better than @2x graphics (until we get to @3x displays) but all the other advantages still stand: smaller files, compressible, scriptable, animatable.</p>
<p>When we look at the compressed SVG it's <strong>97% smaller</strong>. The optimized <em>and</em> compressed SVG is <strong>99% smaller</strong>. Now, one asset might not be a huge concern, but over multiple images, and multiple users downloading those images that size difference adds up.</p>
<p>Now we're not just talking savings to users' data, but a quantifiable difference in clients' bandwidth and therefore the money the spend on that bandwidth. 191KB-16KB is 175KB. 175KB * 365.25 days * 100 users is just over <strong>6 GB</strong> saved per year. Now imagine if your site get ~10,000 hits per day. </p>
<p>Let's say you can convert all those social icons, all those text banners, all those call to action buttons (which in 2015 are still straight up images). How much bandwidth are you saving? How much money are you saving your client now? How much time are you saving the user?</p>
<blockquote>
<p>But it'll cost too much to do it piecemeal?</p>
</blockquote>
<p>Maybe, it's time to sell your client on a redesign. If you're pointing out the real life benefits beyond just <q>Ooooh, prettty!</q> they'll want to green light your next redesign pitch. Did you know google boosts your search page ranking based on how fast your page loads? <a rel="noopener nofollow noreferrer" target="_blank" title="I'm not even lying" href="http://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html">True story brah</a>.</p>
<p>Comments? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter.</p>
<h2 id="addendum">Addendum</h2>
<p>Your website or app will include multiple images. Users now expect the apps they use and websites they visit to look good on all their devices. The <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00746WZHE/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">5K iMac</a>, the <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00PG5RJV2/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">4K TV</a>, the <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00OTWOAAQ/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Retina iPad</a>, the <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00NQGP5M8/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Retina iPhone</a>, the hiDPI <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00MWI4JNM/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Moto X</a>, the <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00BWYQ9YE/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Kindle</a>, the <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B00G2KNGT4/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20">Retina Macbook Pro</a>. And we haven't even gotten to the windows computers or tablets yet.</p>
<p>Instead of delivering piecemeal assets tailored to certain devices at @2x, @1x and now @3x resolutions we should look to use scalable images where ever it makes sense. Just as we've moved on from using pixel measurements and pixel breakpoints, a tipping point has come where we should be looking at scalable images to deliver the kinds of visual experience our users have come to expect and our clients will be proud to deliver.</p>
<p>The take home message here is that whenever you have the option of using an SVG or PNG for use on the web, or even with your app (Yes. iOS and Android are both capable of rendering SVGs within native apps), seriously consider the SVG. That's enough of me talking for now, I think the numbers speak for themselves.</p>
<p>Oh, and here's the raw data used to generate the tables above. Nothing fancy here, just a list of files in a directory.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>-rw-r--r--@ 1 username admin 54K Jan 27 08:26 owl-256-orig@2x.png
</span><span>-rw-r--r--@ 1 username admin 24K Jan 27 08:25 owl-256-orig.png
</span><span>-rw-r--r--@ 1 username admin 191K Jan 27 08:19 owl-orig@2x.png
</span><span>-rw-r--r--@ 1 username admin 75K Jan 27 08:18 owl-orig.png
</span><span>-rw-r--r--+ 1 username admin 16K Jan 27 08:23 owl-orig.svg
</span><span>-rw-r--r--+ 1 username admin 5.3K Jan 26 22:46 owl.svg
</span></code></pre>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p><a href="https://itunes.apple.com/us/app/idraw/id404705039?mt=12&ign-mpt=uo%3D4" target="_blank" rel="external">iDraw</a> is without a doubt the best vector drawing app I have ever used. I do all my vector work here despite having Adobe Illustrator on my mac. I highly recommend giving both the Mac and iPad versions a shot.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>The <code><pattern></code> tag allows us to define a repeating portion in a <code><defs></code> tag which is used later.</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">3</sup>
<p>The <code><defs></code> tag meanwhile, is a placeholder for bits of SVG code we'll probably use multiple times. Instead of copying it multiple times in the same document, we can define it once, and reference it in one or more <code><use></code> tags later. It's not actually necessary to place items which we will reference in <code><use></code> tags within <code><defs></code>, all that's necessary, is an <em>id</em> attribute to reference. By using the <code><defs></code> tag, we are able to hide the snippet so that it's not rendered until we wish to see it. Sometimes you might not want to hide first/use later, and so will just reference an <em>id</em> within a <code><use></code> tag.</p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">4</sup>
<p>There are, however, <a target="_blank" rel="external" href="http://www.pushing-pixels.org/2011/11/04/about-those-vector-icons.html">other</a> <a target="_blank" rel="external" href="http://www.svgopen.org/2008/papers/104-SVG_in_KDE/index.html#d4e152">issues</a> to be cognizant of with respect to SVGs scaling on certain displays.</p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">5</sup>
<p>Even if you're running your own server and using a somewhat complicated server such as nginx, telling the server to compress all text files (which is all an svg is), is such a simple thing you have no excuse if you're not doing this. As a matter of fact, if you aren't doing this, I hereby revoke your right to internet.</p>
</div>
Git Troubleshooting2015-01-18T11:25:00-05:002015-01-18T11:25:00-05:00
Unknown
https://orville.thebennettproject.com/articles/git-troubleshooting/<p>I've had the fortune of being an early adopter for Git as a version control system. A part of this early adoption involves getting bleeding edge software to work alongside older, more decrepit software. Such was the case when using git as my subversion (svn) client.</p>
Contributions2015-01-15T01:15:00-05:002015-01-15T01:15:00-05:00
Unknown
https://orville.thebennettproject.com/articles/contributions/<p>I was just thinking about all the projects I've contributed code to in the past and thinking, "Huh. That's quite a sizeable list."
The list goes something like this:</p>
On Installing Ubuntu 14.04 LTS on a 2011 Macbook Pro2014-11-30T02:31:00-05:002014-11-30T02:31:00-05:00
Unknown
https://orville.thebennettproject.com/articles/installing-ubuntu-14-04-lts-on-a-2011-macbook-pro/<h2 id="background">Background</h2>
<p>What I'll be showing you today is how to rescue your 2011 Macbook Pro by putting Linux on it. I understand you might be asking "Why would I do such a thing!?" So imagine this scenario:</p>
Avoid tar: Removing leading `/' from member names message in backup scripts2014-10-11T00:15:00-05:002014-10-11T00:15:00-05:00
Unknown
https://orville.thebennettproject.com/articles/tar-removing-leading-slash/<p>I recently figured out how to get rid of an annoying message that came from the tar backup program that I'd like to share. I have servers that I've set up to do hosting for some clients. Since they're actually paying for this service I also perform regular backups. This would be pretty annoying to do manually every day so I have a cron job run the backup script each day.</p>
<p>The script I wrote used <code>tar</code> to create the backup file but was also printing out the warning</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>tar: Removing leading `/' from member names
</span></code></pre>
<p>This was incredibly annoying because the end result was an email from cron, with that message, every single time the script ran. I had two backup scripts run every day. Eventually, even though that message didn't affect the backups at all --- they were still working --- I decided to look into it to remove the message and prevent cron from emailing me spurious messages.</p>
<p>That was the prologue. Here's what you came for: The Solution. </p>
<p>My first try at this, after looking up the documentation, still failed, and I had no idea why. According to the documentation for <code>tar</code> using the <code>-C</code> switch was the solution.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>-C directory
</span><span> In c and r mode, this changes the directory before adding the following files.
</span></code></pre>
<p>According to the docs, I could instruct <code>tar</code> to switch directories first, and if it did that, it wouldn't need to strip the <code>/</code> from names instead. I changed my script from the previous format of </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>tar -cjf $destination.tar.bz2 /file/path1 /file/path2
</span></code></pre>
<p>And changed it to </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>tar -C / -cjf $destination.tar.bz2 /file/path1 /file/path2
</span></code></pre>
<p>And nothing changed! Disappointing to say the least. I went back to my standard web developer debugging tool when things get <strong>hard</strong> and created a test case. A simple backup command with the least arguments possible that still created a viable backup. </p>
<p>After doing that I realized where I went wrong. You see even though I was switching the the root directory <code>/</code>, I was still including the leading <code>/</code> with the file paths I was backing up. Since this was a script and the file paths to backup up were actually defined early on they weren't in view and I didn't even think about them being present. </p>
<p>After telling <code>tar</code> to switch to the <code>/</code> directory and then removing the leading <code>/</code> from the file paths the error did, indeed go away. You can see a modified, fixed backup command below:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>tar -C / -cjf $destination.tar.bz2 file/path1 file/path2
</span></code></pre>
<p>As you can see once we switch to <code>/</code> we then use relative file paths to point <code>tar</code> to the location of the directories (or files) we want backed up.</p>
<p>There you have it, the way to prevent the <code>tar: Removing leading '/' from member names</code> message is a two-fold process.</p>
<ol>
<li>Invoke tar with the -C switch pointed at the root directory, i.e. <code>-C /</code></li>
<li>Change your file paths from absolute to relative by removing all the leading slashes <code>/</code> from them.</li>
</ol>
<p>Comments? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter.</p>
Changing the default shell in OS X to Zsh2014-09-06T13:49:00-05:002021-03-19T07:42:00-05:00
Unknown
https://orville.thebennettproject.com/articles/changing-the-default-shell-in-os-x/<h2 id="update">Update</h2>
<p>Apple has finally followed my lead and this is no longer necessary as of macOS Catalina.</p>
<h2 id="original-post">Original Post</h2>
<p>More "getting stuff ready" info so i don't forget. To change the default shell in OSX the venerable chsh program works just fine.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>chsh -s /path/to/zsh
</span></code></pre>
<p>Now here's something that's also good to remember. If you've started a terminal session in something like tmux in your old shell, and then use chsh to change your new shell the value of the $SHELL variable will still be the old shell. You'll need to exit tmux to get things working absolutely properly. You're welcome. Now your zsh reload() function will actually work properly again.</p>
Working with octopress 2 and zsh2014-09-06T13:40:00-05:002021-03-19T07:40:00-05:00
Unknown
https://orville.thebennettproject.com/articles/working-with-octopress-2-and-zsh/<p>I had to get a new mac recently in order to continue working on a client project since my older (2 year old) refurbished Macbook Pro had started acting up. Instead of continuing to fight with it I decided the wisest thing to do would be to get a new iMac. So now I have a fresh new mac with none of my settings and so i've started the long arduous task of copying over various settings. I do a lot of my work on the command line so this has involved some git cloning various things like my personal dotfiles repo and the git backups of all my websites.</p>
<p>My personal website, the very one you're reading right now is powered by Octopress, so I had to go through some command line chicanery to get everything set up to my liking again. As you can tell from the timestamp on my last post. It's been quite some time since I've octopressed. Imagine my surprise when I ran into some hurdles when trying to get everything built. </p>
<p>My first problem was that octopress has now moved onto version 3. I installed the octopress 3 RC gem and was greeted with errors indicating <q>This is not the octopress you are looking for.</q> After downgrading I eventually bundle installed my way back to the previous state and tried to install the modified theme I had been using. Alas, I was greeted with this error message:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>$ rake install['cleanpress']
</span><span>rake aborted!
</span><span>Don't know how to build task 'default'
</span></code></pre>
<p>Eventually I realized whaat was going on. My terminal is zsh and the way i have it set up, certain characters need to be escaped explicitly. Once I retyped that command and escaped it properly my theme installed and i was ready to go.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>rake install\[cleanpress\]
</span></code></pre>
<p>After running that command I got the expected output which I'll show below for reference:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>$ rake install\[cleanpress\]
</span><span>theme is already installed, proceeding will overwrite existing files. Are you sure? [y/n] y
</span><span>## Copying cleanpress theme into ./source and ./sass
</span><span>mkdir -p source
</span><span>cp -r .themes/cleanpress/source/. source
</span><span>mkdir -p sass
</span><span>cp -r .themes/cleanpress/sass/. sass
</span><span>mkdir -p source/_posts
</span><span>mkdir -p public
</span></code></pre>
<p>This also applies for any other commands in square brackets such as:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>rake new_post\["New Title"\]
</span></code></pre>
<p>Comments? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter.</p>
Creative Juices: Part 22013-11-19T22:52:00-05:002013-11-19T22:52:00-05:00
Unknown
https://orville.thebennettproject.com/articles/creative-juices-part-2/<p>So <a href="https://orville.thebennettproject.com/articles/creative-juices-pt-1/">last year</a> i mentioned that I'd be explaining the process of creating a logo in this post. I wont be using just any old logo though. No sir, I'll show you how I arrived at the bennett project umbrella. I started thinking about a logo for the website as I thought it would be cool to have a branding mark of our very own. <q>Our</q>, representing myself and <a target="_blank" rel="external" href="http://laura.thebennettproject.com">my lovely wife</a>. Something to throw on theoretical business cards, t-shirts, and the like. Since <q>the bennett project</q> was conceived as an umbrella organization of sorts, for whatever projects me and the wife wanted to work on (and not being quite creative enough to come up with something else that worked) I settled on the obvious: an umbrella.</p>
<p>I guess I should mention that there was another logo. The problem was the more I saw it, the less I liked it (for this particular purpose). That is <em>not</em> a good thing when you intend to be branding stuff. That other logo wasn't particularly iconic. It didn't really have anything to do with the overall concept of the site. It was just fun, and looked cool. That's when I started drawing and kept going back to <q>the umbrella</q>. Instead of fighting the obvious and trying to change it for the sake of being novel/cool, I embraced it and ran with it. I couldn't have just any old umbrella though. There are a lot of brands out there that use something similar already. Morton salt comes to mind (though there is a girl, in addition to the umbrella) and some insurance company. The logo had to stand out and be unique. Or as unique as I could make an umbrella without making it something else.</p>
<p>So one day i started doodling.</p>
<p>The idea here was to have an umbrella with "the bennett project" initials (tbp) in raindrops. ... Behold! The Bennett Project logo prototype: Version 1.0</p>
<p><img src="/images/articles/logo_sketch1.jpg" alt="logo sketch 1" /></p>
<p>As you can see, it's quite basic but I still though it was too complex to properly convey what I was trying to get across. And yes, I suck at drawing. I also suck at handwriting. This is why we have computers. Moving on!</p>
<p>I had the iPad app Paper installed, so I decided to play around a bit and see what I could come up with on digital paper. As it turns out, quite a lot when you're not worried about how ridiculous or absurd looking something is. Behold the awesome, as captured by Paper. </p>
<p><img src="/images/articles/logo_sketch8.jpg" alt="logo sketch 8" /></p>
<p>This is me trying to make the "tbp" out of umbrella's. Too cutesy.</p>
<p><img src="/images/articles/logo_sketch2.jpg" alt="logo sketch 2" /></p>
<p>Incorporating the letters into the umbrella. The problem I had here is that the shaft of the umbrella becomes superfluous, whilst everything else had meaning. Oh, and it looks horrid.</p>
<p><img src="/images/articles/logo_sketch3.jpg" alt="logo sketch 3" /></p>
<p>Incorporating the abbreviation into a part of the umbrella. Not bad, but the "p" messes it up for me. that hanging stem of the p dropping below the baseline was visually jarring. </p>
<p><img src="/images/articles/logo_sketch4.jpg" alt="logo sketch 4" /></p>
<p>Same as before, ignoring the "p" for now, and trying to incorporate the words "the Bennett project" as sheets of rain. Verdict? Crap.</p>
<p><img src="/images/articles/logo_sketch5.jpg" alt="logo sketch 5" /></p>
<p>Checking out the uppercase "tbp" to see if I like the look better (and if the baseline problem can be fixed by converting to uppercase. Also throw a border around the whole thing to add some definition. The border I like. The rest ... Notsomuch! </p>
<p><img src="/images/articles/logo_sketch6.jpg" alt="logo sketch 6" /></p>
<p>Incorporate the letters into the handle. Fail. The hanging tail of the "p" definitely kills it, but also the b. the crossed portion of the "t". This isn't a sword y'know. </p>
<p><img src="/images/articles/logo_sketch7.jpg" alt="logo sketch 7" /></p>
<p>At this point it was clear that the initials just weren't working. They added too much complexity, so with my next attempt I tried to include the whole name. I left the Paper app and went to real pen and paper a bit to do some barnstorming. The first logo below looked weird, but wasn't necessarily bad. The same could be said of the second, which looked and felt much the same with a different enclosing border - hexagonal instead of circular. While i liked it, it didn't help much.</p>
<p><img src="/images/articles/logo_concept1.jpg" alt="logo concept 1" /></p>
<p>Here I have the words incorporated and have thrown some gear bits in for good measure. You know, Because it's a project; and projects are synonymous with gears. Duh!</p>
<p><img src="/images/articles/logo_concept2.jpg" alt="logo concept 2" /></p>
<p>I actually liked this version quite a bit, so I stopped playing around in Paper. As you can see drawing is not my forté, and using a freeform drawing program would not have resulted in comparatively better results. This is where vector drawing programs and my "love" of math take over. After a bit of playing around in my preferred vector creation app iDraw, I had version 1.0 of the bennett project logo. Behold.</p>
<p><img src="/images/articles/logo_wip.jpg" alt="logo work in progress" /></p>
<p>Thing is, this was meant to be a one size fits all logo. Suitable for print and the web. I think any more experienced designers in the audience are probably rolling over laughing at this point because that's something easier said than done. See, the logo at (roughly) 400x400 pixels in size, needed to be shrunk to a suitable size for : a) a webpage logo at roughly 100x100 to 150x150 px and b) a 16x16 px favicon. </p>
<p>Don't worry about the absolute numbers, it just means the logos had to get smaller, <em>and still look good</em>. The trick, is not so much the first part of that. It's the second. You see the smaller an image gets, the harder it is to read any writing. At 100x100 px we were already pushing the limits of what I saw as acceptable. At 16x16 px, or even 32x32 px, it wasn't even remotely readable. As a bonus fail, even the umbrella shape was barely distinguishable at that point.
<img src="/images/articles/logo_wip_favicon.jpg" alt="logo work in progress favicon" /></p>
<p>Fortunately, I'd been around open source software long enough to learn a bit about various parts of the stack - artwork being among those parts. I knew I had to sacrifice some detail in the <q>low end</q> favicon version of the logo to make the main elements identifiable. Thing is, once I did that, I came up with something that was at once (at least in my mind) more iconic, and elegant than my intentional creation. I liked it a lot more than the original logo!</p>
<p><img src="/images/articles/logo_favicon.png" alt="logo favicon" /></p>
<p>So what to do? Repurpose the favicon version and make a logo out of that! And so it was that we have the current logo for thebennettproject.com</p>
<p><img src="/images/articles/logo_final.png" alt="final logo" /></p>
<p>There you have it. A behind the scenes look of the (rather organic, if I can use a jargony phrase) birth of the bennett project's logo.</p>
<p>Have something to say/share? Fire off a tweet to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter with the hash tag #creativejuices.</p>
Droid Razr M Review2012-10-20T12:17:00-05:002021-03-14T03:55:00-05:00
Unknown
https://orville.thebennettproject.com/articles/droid-razrm-review/<h2 id="update">Update</h2>
<p>This article has not aged gracefully. The Root.zip file linked to in this post is no longer present (since the domain which contained it is no longer available). This post is just being left up for archival purposes.</p>
<h2 id="original-post">Original Post</h2>
<p>What follows is a review for my latest smartphone: Motorola's Droid Razr M. It's an Android powered smartphone that runs on Verizon's network. A review of this sort may seem late, but I don't believe you get a true feel for a device after just a few days — or even a week — of use. I've been using the Razr M for about a full month now. Since I've been using this phone for an extended period, I'll be better equipped to give a complete picture of it for those in the market for a new smartphone. However, this will be more of a <q>This is how <em>I</em> use my phone, and this is how well it works <em>for me.</em></q> review. Obviously, different people will have different priorities. Let's begin.</p>
<h3 id="prologue">Prologue</h3>
<p>Prior to owning the Razr M, I had an HTC Droid Incredible. The Incredible was pretty a good phone for me because <strong>1.</strong> I got it for free and <strong>2.</strong> I rooted it.<sup id="fnr1-2012-10-20"><a href="https://orville.thebennettproject.com/articles/droid-razrm-review/#fn1-2012-10-20" title="footnote">1</a></sup> I wrote an article on the benefits of <a href="https://orville.thebennettproject.com/articles/droid-razrm-root/">rooting your phone</a>, so I won't rehash that here.</p>
<h3 id="initial-impressions">Initial Impressions</h3>
<p>Shortly after buying the Razr M and using it for a few days my intial impressions were overwhelmingly positive. I was genuinely excited I had gotten a phone — from Motorola — that didn't suck. It had a good display. The physical size of the phone was perfect for me (not too large). They also managed to fit a large screen into this smaller-than-average sized phone. I made numerous tweets on how awesome it was, along with any downsides I had noticed at that point. My overall impression was: good, solid phone.</p>
<h3 id="build-quality">Build Quality</h3>
<p>I think Motorola managed to create a gem of a phone in the Razr M. I love the look of it. I don't say this lightly. This is coming from someone who, for comparison, loathed the design of the original Razr. In framing its phone, Motorola has managed to capture the unique essence of a razor — <q>sharp</q> edges, slight tapering from top to bottom — and distilled that into an aesthetically pleasing form.</p>
<p>The phone seems solidly built as well. There's a heft to it that wasn't there with my Incredible, or even my T-Mobile Vibrant before that. The Razr M isn't remotely close to indestructible though. I used it as a flashlight while changing oil in our minivan and the plastic frame got a few scrapes around the edges. The rear of the plastic frame is dominated by what is reportedly a Kevlar surface. It's a soft touch material that feels pretty good to hold. The plastic body is assembled with Torx screws which effectively prevents casual tampering and easily swapping the battery, both points I'll address below.</p>
<h3 id="user-repairability">User Repairability</h3>
<p>Since the Razr M's frame is secured with torx screws, I assumed this meant any self repair work would be a pain. Not so, as teardowns reveal that once those screws are off, <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.droid-life.com/2012/09/24/motorola-razr-m-receives-a-tear-down-moto-has-made-it-easy/">Motorola has made repairability a breeze</a>. Contrast that with <a rel="noopener nofollow noreferrer" target="_blank" href="http://arstechnica.com/gadgets/2011/11/tough-droid-razr-teardown-reveals-user-unfriendly-assembly/">reports of the original Razr's user repairability</a>. This is commendable as it makes replacing or repairing parts for the DIY fixer less prone to catastrophic failure (read: needing to buy a new phone). Seeing that phone repairs are one of my freelance services, I appreciate it all the more.</p>
<h3 id="battery-life-and-4g-internet">Battery Life and 4G Internet</h3>
<p>As I alluded to above, the Razr M does not have a removable battery. I don't see this as a problem though. It uses micro usb ports for charging, so in a pinch you shouldn't have too much trouble getting it charged. Micro usb is all but ubiquitous; unlike the iPhone 5's new proprietary connector. Battery life is actually great, <strong>provided you aren't using 4G all the time</strong>. The day after I got the phone I barely made it to 8 hours before the phone was dead. This was because I was both tethering AND using the 4G Internet which, let me tell you, is blazingly fast. If we didn't stream so much online video at home I'd kill our cable Internet subscription and use this all the time (which is to say, Netflix will rape your bandwidth if, like us, you have a mobile internet cap).</p>
<h3 id="increasing-battery-life">Increasing Battery Life</h3>
<p>Knowing a bit about cell radios and not really needing or even being able to consistently get 4G indoors (at work) <a href="https://orville.thebennettproject.com/articles/droid-razrm-review/#disable-4g">I disabled it</a>. After telling the radio to only search for a 3G signal I was <em>easily</em> able to go a whole day without needing to charge. By the end of the night it was still possible to have a 15-20% charge left.</p>
<p>After I set the phone to connect to 3G only I'm able to get through an 8 hour day of heavy activity without needing to charge at the end. I consider heavy activity :</p>
<ul>
<li>Checking email and twitter hourly in the background</li>
<li>Talking on the phone infrequently</li>
<li>Texting intermittently</li>
<li>Surfing the web often (at the lowest brightness setting)</li>
<li>Tethering for an hour or two</li>
</ul>
<p>Your mileage will vary depending on your definition of heavy activity.</p>
<p>The take home though is: <em>If 4G is enabled, even if you're not using it, your battery life will suffer</em>. Coming from an Incredible and never, in any configuration, being able to get a day's worth of service without needing to charge, I'd say the Razr M has pretty good battery life. Let me put it this way, as long as 4G is off, battery life doesn't suck. If 4G is on, but not in use, battery life is bearable. If 4G is on, and in use, bring a charger.</p>
<h3 id="disable-4g">Disabling 4G — for the brave.</h3>
<p>As far as I know all Android phones have so called <q>secret codes</q> which allow access to extra functionality deep within the operating system (OS). To prevent the phone from using its 4G powers we'll be using one of these secret codes. Beware though. I've found that after rebooting, the Razr M changes back to its default setting of using 4G service. There are many other settings present that can do VERY BAD THINGS TO YOUR PHONE, so you should probably leave these alone if you're not prepared to deal with breaking your phone. Before I give any instructions, I'd like to point out that you're doing this at your own risk, should you follow along on your phone.</p>
<ul>
<li>In the phone dialer type <strong>*#*#4636#*#*</strong> </li>
<li>Hit the dial/call button </li>
<li>You should now be in the Phone information section. If not, just choose
that option now. This is where the magic happens. </li>
<li>Scroll to the top, then start scrolling down the screen slowly. Once
you've gotten to the first drop down box select <code>CDMA auto (PRL)</code>. If
you're feeling particularly adventurous there are other options present.</li>
</ul>
<p>Once your phone is set to only search and connect to 3G signals only, you should be able to notice an increase in battery life.</p>
<h3 id="screen">Screen</h3>
<p>The biggest drain for the battery besides — or perhaps in conjunction with — 4G service, is the screen. It is a beautiful screen though. I remember reading a review complaining about that type of AMOLED screen this was. To my not-quite-30-yr-old eyes the screen looks lovely in its 4.3 inches of 960x540 glory.</p>
<p>Supposedly this is a midrange phone but the only thing that is midrange in my mind is the screen resolution. In the era of 720p and upcoming 1080p screens, <q>540p</q> — the previous gold standard — is no longer top of the line. That's fine since every other aspect of this phone screams <q>I'm here to play with the big boys</q>. And by big boys, I do mean big. Those beastly 4.5, 4.7 and 5.0 inch screened phones are huge and a definite turn off for me. The Razr M is a phone that provides me with the perfect fit: large screen size, compact form factor. As Hannah Montana would say, <q>it's the best of both worlds</q>. As a point of reference, it's not much taller or wider than an iPhone 4. It's actually a bit smaller once you factor in the protective iPhone case.</p>
<h3 id="performance">Performance</h3>
<p>Speaking of midrange, the price of the Razr M does indeed put it in midrange territory, but the performance is anything but. Apart from the screen, the specs are similar to the Samsung's Galaxy S III line. That means it can do just as much as those phones, but with a smaller screen, and of course, smaller cost. I've played a variety of games: Temple Run, Plants vs. Zombies, Cut the rope, and none of these had any slowdowns during gameplay.</p>
<p>The phone is smooth and responsive in going to the home screen and swiping from screen to screen. This even persists while running to live wallpapers. I've been using the Galactic Core live wallpaper since getting this phone and have noticed no issues with its animation. Ever. There <em>is</em> the occasional issue where, after using a lot of apps then going back to the home screen, it takes some time to repopulate the screen with icons and widgets.</p>
<h3 id="software">Software</h3>
<p>It is rare to get a phone that isn't a part of Google's Nexus program without a manufacturer skin added. Unfortunately these skins — additional layers of artwork and software meant to differentiate a manufacturer's version Android — usually mar the experience. I'm happy to report that Motorola has only made minimal changes to Android. Of the changes it has made, I've found them to be welcome additions. I'll list some prominent ones below:</p>
<p>— Quick Settings: These are Motorola's quick settings. They're accessed by swiping all the way to the left of the homescreen, and provide quick access to commonly toggled settings. They work well but are not customizable so I don't use them much. I've instead installed Settings Extended and configured it exactly as I want. <a rel="noopener nofollow noreferrer" target="_blank" href="https://play.google.com/store/apps/details?id=com.hb.settings">Settings Extended</a> is conveniently located in the notification bar, just one swipe away.</p>
<p>— Artwork: Motorola's also changed up the artwork in order to brand this device. I don't love it, but I don't hate it either. It's ok</p>
<p>— Widgets: Motorola's provided a nifty little circle widget that gives weather, battery and time info. The clock area also doubles as a notification area telling you when texts come in or calls are missed. I like it a lot.</p>
<p>— Lockscreen : The lockscreen has a toggle for quickly changing the volume. Love it! It also allows you to unlock to one of 4 activities: phone, camera, text, or whatever-you-were-doing-before.</p>
<p>— Crapware: Ugh. Verizon's loaded this up with a host of programs that I wish would die in a fire. I went to Settings → Apps → All and froze as many as I could. Now that <a href="https://orville.thebennettproject.com/articles/droid-razrm-root/">we've got root</a>), this too shall pass.</p>
<p>— Smart Actions: The smart actions allow you to program your phone to do actions (launch a program, send a text) based on certain predefined conditions (I'm at work, battery is low, etc.) being met. I find them very useful. My main use is to turn off the volume while at work, or sleeping, so that the phone will only vibrate, <strong>unless</strong> certain people call then it should ring. Yeah, you can get that detailed with it.</p>
<p>— GPS/Location services: GPS works, and works well. Except when it doesn't. I was having issues with the GPS working, but I tracked this down to the smart actions I had setup. I had it set up to turn off GPS if the battery was below 25%. At the end of a work day with a good deal of tethering, the battery would be right around those levels and toggling the GPS setting would not help. Once I remembered the smart action and disabled this setting, all seemed well. Motorola also offers its own location service, as does Verizon (VZW), in addition to Google's offering. These are separate from GPS functionality and they seem to work well.</p>
<h3 id="quirks">Quirks?</h3>
<p>After moving to another building for work, I get worse reception from VZW's cell towers. It also seems that tethering takes a hit from that. My iPad, which I tether to the Razr M, will be connected but stops/slowsdown halfway through loading a website. I have yet to determine whether this is a VZW or iOS 6, or RAZR M issue, but I thought I'd point it out in the meantime.</p>
<h3 id="is-it-for-you">Is it for you?</h3>
<p>I don't know if its for you, but it definitely is for me. My subjective opinion is that the Droid Razr M is an excellent device and I highly recommend it.</p>
<p>Given the discount you get if <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B0096QYH80/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B0096QYH80&linkCode=as2&tag=orbitsolution-20">purchased from Amazon</a>, <sup id="fnr2-2012-10-20"><a href="https://orville.thebennettproject.com/articles/droid-razrm-review/#fn2-2012-10-20" title="footnote">2</a></sup> and given that I get a portion of any sales I refer to Amazon, and given the fact that its now possible to <a href="https://orville.thebennettproject.com/articles/droid-razrm-root/">root the phone</a>, ), I say if you're in the market for a new phone and with Verizon, this is definitely a phone you should be considering.</p>
<p>If I were a scoring man, I'd give it a 9 out of 10. It starts out with 10. -1 for battery life. -1 because its not the best design out there (HTC One X). -1 because its not HD resolution (720p). +1 for price and another +1 because I like it so darned much.</p>
<p>Want to comment? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter with the hashtag #razrmreview. I'll post the ones I deem worthy here.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn1-2012-10-20">Rooting is the process of obtaining administrator access
on your phone. It grants you complete control of both hardware and
software. <a href="#fnr1-2012-10-20" title="Back to the article">↩</a></li>
<li id="fn2-2012-10-20"> I'm not sure if ordering a phone from Amazon is a great
idea because they have an early termination fee <strong><em>in addition</em></strong>
to Verizon's already hefty ETF. If for any reason you foresee the possibility of
needing to leave your Verizon contract, I say purchase it from VZW directly. You may even want
to wait and see if there are any Thanksgiving/Black Friday/Cyber Monday sales. Just sayin'. I got mine from a VZW retail store, but that's because I didn't want to wait. Otherwise I would have gotten it from VZW's online store (for the instant rebate) or Amazon
(if I had no plans to leave VZW in the next year).
<a href="#fnr2-2012-10-20" title="Back to the article">↩</a></li>
</ol>
</div>
How to Root the Droid Razr M in OS X2012-10-20T11:41:00-05:002012-10-20T11:41:00-05:00
Unknown
https://orville.thebennettproject.com/articles/droid-razrm-root/<p>So! Perhaps you've <a href="https://orville.thebennettproject.com/articles/droid-razrm-review/">read my review</a> and decided to <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B0096QYH80/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B0096QYH80&linkCode=as2&tag=orbitsolution-20">get a Droid Razr M</a>. After getting it, you see all those crapps you can't uninstall; taunting you.</p>
<p>You're all like <q>OMG the Jelly Beans have leaked and I wants them! What am I supposed to do?</q></p>
<p><q>Don't worry,</q> says I, an attempt to comfort <q>Root has been achieved.</q></p>
<p><q>But I dont have a windows machine</q>, you retort <q>just an awesome 2011 MacBook Pro.</q></p>
<p><q>It's ok,</q> I assure <q>Fret not, I have the answer.</q></p>
<p>What follows below is a quick and dirty outline of the steps necessary to get the Droid Razr M rooted so you can do, well, whatever you want with the phone <strong>you bought</strong>. The original method comes to us by way of djrbliss from <a rel="noopener nofollow noreferrer" target="_blank" href="http://forum.xda-developers.com/showthread.php?p=32888705#post32888705">XDA developers</a> with <a rel="noopener nofollow noreferrer" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=1940630&page=3">additional info specific to the Razr M</a> from other various other members. Thank you sirs.</p>
<p>The first thing we need before embarking on this adventure is ADB: the Android Debug Bridge. You can get it by going to <a rel="noopener nofollow noreferrer" target="_blank" href="http://developer.android.com/sdk/index.html">http://developer.android.com/sdk/index.html</a> and downloading the SDK for Mac OS X. Once you've downloaded the SDK, unzip it and open Terminal.app and follow along. After typing/copying each of the following commands you'll need to hit the Enter key.</p>
<ol>
<li>In the terminal type <code>cd</code> and then drag the unzipped folder to the terminal window and press <code>[Enter]</code>. You should now be in the root android-sdk-macosx directory.</li>
<li>Type <code>wget http://vulnfactory.org/public/motofail2go_windows.zip</code></li>
<li>Type <code>unzip motofail2go_windows.zip</code> to unzip in our current directory.</li>
<li>Type <code>tools/android</code> and, in the window that appears, check the <code>Android SDK Platform-tools</code></li>
<li>Click the <code>[Install 1 package]</code> button then, in the window that appears, click the install button.</li>
<li>Once the install is finish close all the windows.</li>
<li>Type <code>cp motofail2go/{motofail2go,Sudoku.apk,busybox}</code></li>
<li>Next we need to get su and Superuser.apk from <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.aosp.us/wp-content/files/Root.zip">http://www.aosp.us/wp-content/files/Root.zip</a> to place in the <code>platform-tools</code> directory.</li>
<li><code>wget http://www.aosp.us/wp-content/files/Root.zip</code></li>
<li><code>unzip Root.zip</code></li>
<li><code>cp Root/system/app/Superuser.apk platform-tools</code></li>
<li><code>cp Root/system/xbin/su platform-tools</code></li>
<li>On the Droid Razr M open up the Settings and go to Settings → Developer Options.</li>
<li>Check the <code>USB Debugging</code> option.</li>
<li>Connect to your mac via USB cable. Mine was connected as an MTP device when I tried this.</li>
<li>Go back to the terminal and type <code>cd platform-tools</code> then <code>[Enter]</code></li>
<li>Then <code>./adb wait-for-device</code></li>
<li>Then <code>./adb install Sudoku.apk</code></li>
<li>Then <code>./adb push su /data/local/tmp/su</code></li>
<li>Then <code>./adb push Superuser.apk /data/local/tmp/Superuser.apk</code></li>
<li>Then <code>./adb push busybox /data/local/tmp/busybox</code></li>
<li>Then <code>./adb push motofail2go /data/local/tmp/motofail2go</code></li>
<li>Then <code>./adb shell "chmod 755 /data/local/tmp/motofail2go"</code></li>
<li>Then <code>./adb shell "/data/local/tmp/motofail2go prep1"</code></li>
<li>Then <code>./adb shell "run-as com.motorola.bug2go/data/local/tmp/motofail2go prep2"</code></li>
</ol>
<p>After running all those commands you'll need to do one more thing on the
phone. Turn the volume all the way down, and then follow the
instructions below.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>* Please trigger a bugreport on your phone by pressing
</span><span>* Volume Up + Power simultaneously. If successful, your device
</span><span>* will vibrate. Make sure this vibration is distinct from the
</span><span>* vibration that occurs when you turn the volume all the way
</span><span>* down.
</span></code></pre>
<ol>
<li>Then <code>./adb shell "/data/local/tmp/motofail2go trigger"</code></li>
<li>Then <code>./adb shell "/data/local/tmp/motofail2go clean"</code></li>
<li>After this step you should have root. Go forth, download some root apps to test and have fun.</li>
<li>After verifying that you have root run <code>./adb uninstall com.motorola.bug2go</code></li>
</ol>
<p>You may notice that this assumes a certain level of comfort with the command line. This is deliberate. If you're not familiar enough with the command line, I highly suggest reading up a bit more on the topic.</p>
<p>Want to comment? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter with the hashtag #rootrazrm.
I'll post the ones I deem worthy here.</p>
Creative Juices: Part 12012-10-08T20:37:00-05:002012-10-08T20:37:00-05:00
Unknown
https://orville.thebennettproject.com/articles/creative-juices-pt-1/<p>True story: I used to draw comic books. Stick figure comic books mind you, but I was proud of them nonetheless. I was prouder still of the stories these comics would tell. However, despite dabbling in comic book creation, I never considered myself a creative person. I personally felt that ideas were just too hard to come by to warrant any <q>legitimate</q> claim to that title. Then came web development, which changed things.</p>
Seek His Face2012-09-26T14:19:00-05:002012-09-26T14:19:00-05:00
Unknown
https://orville.thebennettproject.com/articles/seek-his-face/<h3 id="psalm-27-verses-7-10">Psalm 27 verses 7-10</h3>
<p>Hear, O Lord, when I cry with my voice: have mercy also upon me, and answer me. When thou saidst, <strong>Seek ye my face</strong>; my heart said unto thee, <em>Thy face, Lord, will I seek</em>. Hide not thy face far from me; put not thy servant away in anger: thou hast been my help; <em>leave me not, neither forsake me, O God of my salvation</em>. When my father and my mother forsake me, then The Lord will take me up.</p>
<p>The Living Word of God, (i.e. The Bible) is a wonderful thing that we here in western civilizations are privileged enough to have. I can't recommend it highly enough. If you're in the unfortunate situation of not being able to get one yourself, for whatever reason, you should hit me up on twitter.</p>
<p>Send a direct message to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> with the hashtag #seekhisface and your address. Through the wonders of @amazon and the internets, you should receive a copy as soon as amazon's shipping arrangements allow.</p>
<p>But once you get it: Seek His face. Be earnest. Be sincere. Be prepared to be transformed.</p>
Restoring YouVersion Bibles2012-09-22T13:11:00-05:002012-09-22T13:11:00-05:00
Unknown
https://orville.thebennettproject.com/articles/restoring-youversion-bibles/<p>I purchased a <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B0096QYH80/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B0096QYH80&linkCode=as2&tag=orbitsolution-20">Droid RAZR M</a> — an <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/Motorola-DROID-Android-Verizon-Wireless/product-reviews/B0096QX6GY/?_encoding=UTF8&camp=1789&creative=390957&linkCode=ur2&showViewpoints=1&tag=orbitsolution-20">AWE</a> <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/Motorola-DROID-Android-Verizon-Wireless/product-reviews/B0096QYH80/?_encoding=UTF8&camp=1789&creative=390957&linkCode=ur2&showViewpoints=1&tag=orbitsolution-20">SOME</a> Android phone recently (<a href="https://orville.thebennettproject.com/articles/droid-razrm-review/" title="Droid RAZR M Review">see review</a>). After moving my old phone's sdcard to the new phone, the Bible app was not picking up my (already downloaded) KJV and NIV bibles. For those who aren't aware, last year YouVersion was able to offer the new (2011) NIV translation of the Bible for download. This was a rather big deal as it meant one did not need to be online to use the NIV translation in this Bible app.</p>
<p>Here's the email announcement I received:</p>
<blockquote>
<p>2011 marks the 400th anniversary of the publication of the King James Version (KJV) of the Bible. To celebrate this milestone of making God’s Word available in the common language of the people, all throughout this year, YouVersion will be highlighting several special events and opportunities that will make it easier than ever to access, engage and share the Bible.</p>
<p>The first event we’re excited to tell you about is a special 400-hour promotion made possible through a partnership with Biblica and Zondervan. Exclusively through the Bible App™ you’ll be able to download the New International Version (NIV) using an iPhone, iPad, iPod touch or Android device…absolutely free. Downloading the NIV means you’ll be able to read it anytime, anywhere–even when you can’t connect to your service provider or the Internet, and after the 400 hour promotion is over.</p>
</blockquote>
<p>I, of course, grabbed it then and have been enjoying the benefits of having the KJV and 2011 NIV available for offline reading. A few days ago I purchased a new phone. As a result I had to reinstall my old apps. For Android's the Bible app, my downloaded bibles were stored in the <code>/sdcard/.youversion/</code> folder on the old phone. This folder contained the contents of my micro sdcard.</p>
<p>As I mentioned, the Bible app on the RAZR M was not picking up my downloaded KJV and NIV bibles. I found that the reason for this is that my old phone places the <strong>external storage</strong> in <code>/sdcard</code>, while the RAZR M places the <strong>internal storage</strong> in <code>/sdcard</code>. The RAZR M actually places <strong>external storage</strong> (my sdcard) in <code>/mnt/external1</code>; or, it did for me at least. I didn't start the RAZR M up with an sdcard inside so perhaps this only happens in certain situations.</p>
<p>Anyway, to solve my problem I moved the Bible app download folder from <code>/mnt/external1/.youversion/</code> to <code>/sdcard/.youversion/</code>. I used <a rel="noopener nofollow noreferrer" target="_blank" href="https://play.google.com/store/apps/details?id=com.estrongs.android.pop">ES File Manager</a> from Google's Play Store to do the moving. Hope this helps someone out.</p>
<p>Have something to say/share? Fire off a tweet to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a> on twitter with the hash tag #restorebibles.</p>
Baby Stuff2012-09-09T22:07:00-05:002012-09-09T22:07:00-05:00
Unknown
https://orville.thebennettproject.com/articles/baby-stuff/<p>Nothing much to see here. I'm just posting some Amazon Affiliate links for stuff we're getting for the baby. We're going to order the following (non-essential) items:</p>
Leaving Neverland2012-07-21T11:58:00-05:002012-07-21T11:58:00-05:00
Unknown
https://orville.thebennettproject.com/articles/leaving-neverland/<p>Some months ago, my wife and I went to visit some friends. Actually, I
went to visit and she and her friend went out. On the way home I found
myself in one of those introspective moods I usually have at random
times. In that moment I slowly began realizing that something I never
thought would happen, or ever really wanted to happen, had finally
caught up with me. Peter had left Neverland; which is to say, I'd grown
up.</p>
<p>I suppose I began thinking about this because I had been working a lot
the previous week. Like, a LOT. Since I haven't yet figured out how to
bend the laws of the universe to my mighty will, this meant I wasn't
spending much time with our kids; my kids. Despite realizing that I
should be with them, that I should spend time with them, it hadn't
really bothered me though. After further thought, I realized that the
reason it didn't bother me wasn't because I didn't want to, or didn't
enjoy spending time with them. It was just because I had <q>more important
things to do</q>. In my mind this — relatively speaking — short absence was
the right thing to do. After all, in the long run it would make life
<q>better</q> for us.</p>
<p>And that <strong>right there</strong>, is an adult line of thinking. The ability to weigh
priorities and go with the (perceived) highest, in the belief that at
some far future time this sacrifice will pay off is a completely and
utterly <q>grown up</q> thing to do. And I loathed it. And yet there I was,
catching myself going down that slippery slope.</p>
<p>At the time I was analyzing data for my Master's degree. I anticipated
it taking about 4 days to complete, Monday to Thursday. On Monday, I was
still doing some preliminary work with the data, so I didn't <em>really</em> get
started until Tuesday. That left two days to complete what was,
realistically, a week long task. I had a choice to make. Miss the
deadline I had set for myself, or make a big push to get everything
done. I chose the latter, the "responsible" choice, though I would have
much rather worked a little at a time, then cuddle up with my beautiful
wife afterwards to watch <a rel="noopener nofollow noreferrer" target="_blank" title="Amazon link" href="http://www.amazon.com/gp/product/B002U0KHMY/ref=as_li_ss_tl?ie=UTF8&tag=orbitsolution-20&creativeASIN=B002U0KHMY">White Collar</a>
(good show btw). The choice I made
was based on the idea that other people were depending on me, that I
couldn't let them down — even if they'd let me — by taking the easy way
out and taking my sweet time to finish this.</p>
<p>As I neared home I started wondering how I got to the point where I was
making <q>those kinds of decisions</q>. I remember when I was a kid, in my
teens or thereabouts, I'd look at all the things I liked and think to
myself, <q>How come grown ups don't like this stuff?</q> and <q>I wonder if I'll
still like X when <em>I'm</em> older too?</q> Cartoons, junk food and comic books
were but a few things on that list. I remember being in my early 20s and
still loving cartoons, getting into even more genres, spreading out into
the undiscovered territory of Japanese animation. Even then I thought
that I'd never stop loving cartoons. And I was right actually, I never
did. Their importance to me has diminished greatly, however. Gone is the
desire to seek out new and exciting shows to watch. I have more
important things to do. I didn't stop enjoying them any less, I just
started enjoying other things even more. As the French say, <q
class="fr" lang="fr">C'est la vie.</q></p>
<p>I realize now that it was a slow death, that of my childhood. Something
that slipped away gradually, rather than all at once. And so, I won't
ever be the same again. I don't mind though. After all's said and done,
I quite like the idea of growing up now. I used to joke with people I
admired, that when I grew up I wanted to be just like them. Now, quite
unsuspectingly, I'm there. I don't want to be like them though, i want
to be like me. Like a slow-moving sidewalk that gradually inches you
closer to your destination, I've slowly gotten to here, from there.</p>
<p>I guess Peter didn't really leave Neverland, as much as he was slowly
pushed out by forces beyond his control. But having gotten out there in
the real world, he realizes it isn't so bad after all. Some things are
exactly as awful as he predicted, but some things, are a pleasant
surprise. And it's those things that make growing up totally worthwhile.</p>
<p>Want to comment? @reply to <a rel="noopener nofollow noreferrer" target="_blank" href="https://twitter.com/opinion8d_logic">@opinion8d_logic</a>
on twitter with the hashtag #neverland.
I'll post the ones I deem worthy here.</p>
Building a better zombie2012-06-01T17:19:00-05:002021-03-19T09:11:00-05:00
Unknown
https://orville.thebennettproject.com/articles/building-a-better-zombie/<p>People have been talking recently about zombie attacks, pointing to them as signs and portents of our impending doom as a race. At first there was the story of the man who ate the face off a homeless man. He was shot by police, refused to stop eating the man's flesh, then shot some more until, apparently, he died. Next there was the story of the guy who had someone's bones in his basement and was found later to have eaten him. </p>
Don't believe everything you hear2011-07-06T23:56:00-05:002011-07-06T23:56:00-05:00
Unknown
https://orville.thebennettproject.com/articles/dont-believe-everything-you-hear/<p>Ladies. Gentlemen. Gather 'round. Today I'd like to share with you an encounter I had this past week. Me and the family got home early last Sunday and, as is our custom, we ate food and stared at each other. My wife had a brilliant idea however and suggested that we go to a block party the city was holding. Having nothing better to do at the time, we went.</p>
<p>So, we get to the block party and we're walking around and churches are coming at us left and right. This was actually pretty cool, for me at least. You see there were stalls set up to sell snacks and stuff but the churches were giving this stuff away for free. Yes ladies and gents, F-R-E-E. Some churches were giving out information on Vacation Bible School, others on the church itself. This seems like as good a point as any to bring up the Bible. I'm a Christian see, I believe Jesus died on a cross for my sins (yours too), and that by confessing my sin and asking Jesus to save me that He did. As such I believe the Bible isn't just <q>a book</q>. It is the inerrant, inspired <strong>Word of God</strong>. </p>
<p>This, as it turns out, is an important point. It means that everything in the Bible is correct. It means that if I find a seeming contradiction between things in the Bible then <strong>I</strong>, in fact, am lacking an understanding of whatever God was trying to get across (and therefore need to try harder). An occurrence which happens far more often than I'd like, I should point out. </p>
<p>For instance, Matthew 27: 39-44 we see that people were abusive to Jesus and verbally mocking him, even the prisoners (plural) on the cross with him. </p>
<blockquote>
<p>KJV<br />
Matthew 27:44 The thieves also, which were crucified with him, cast the same in his teeth.</p>
</blockquote>
<blockquote>
<p>NIV84<br />
Matthew 27:44 In the same way the robbers who were crucified with him also heaped insults on him.</p>
</blockquote>
<p>In Luke 23: 39-43 however we see a totally different account given, where on of the prisoners actually defends Jesus. </p>
<blockquote>KJV<br />
Luke 23:39: And one of the malefactors which were hanged railed on him, saying, If thou be Christ, save thyself and us.<br />
Luke 23:40: But the other answering rebuked him, saying, Dost not thou fear God, seeing thou art in the same condemnation?<br />
Luke 23:41: And we indeed justly; for we receive the due reward of our deeds: but this man hath done nothing amiss.
</blockquote>
<blockquote>NIV84<br />
Luke 23:39 One of the criminals who hung there hurled insults at him: “Aren’t you the Christ? Save yourself and us!”
<p>Luke 23:40 But the other criminal rebuked him. “Don’t you fear God,” he said, “since you are under the same sentence?<br />
Luke 23:41 We are punished justly, for we are getting what our deeds deserve. But this man has done nothing wrong.”</p>
</blockquote>
So the contradiction, as I saw it was that in one account the prisoners were both hatin' on Jesus, while in the other only one was hatin' while the other was defending him. But since the Bible is right, all the time, there must be something I'm not getting. I think I asked my pastor about this eventually and got this answer: they're both right. At first the prisoners were railing against Jesus, but eventually one wised up and came to his senses. Works for me. Might not do it for you, but it does for me.
<p>Some will undoubtedly have a problem with a book created by an all powerful God having different accounts by different authors. I, on the other hand think God makes us who we are for a reason. We focus on different things, have different interests etc, because of who we are as individuals. The fact that such individuality is present throughout the Bible, makes it all the more miraculous that the whole thing flows as a uniform story (really, read it for yourself and see). As long as I'm going on about it, you really do have to read the whole thing to begin understanding, and seeing the things God wants you to see. And then do it again. And again. Ad infinitum. </p>
<p>Just trying to read a few books or chapters for inspiration is all good and well, but the overarching story of sin and redemption really come into light while reading through the whole thing (regardless of how long that might take you to do). I think I got through the whole thing in just under a decade. Give or take a few years (I started over a lot).<br />
BUT I DIGRESS.</p>
<p>So now you have an understanding of my beliefs, the way I think about things, etc (i.e. ignore anything which doesn't line up with my view of God's perfection until bothered enough to go and seek out an answer). Yes, this is me. That was just context for what comes next. Remember, this all started with a block party. </p>
<p>So I get to this particular church section and this super nice lady comes out and starts passing out the requisite flyers to me and the wife. During her speech she starts talking about the church and what they believe. She continues to say something I don't quite get. Apparently, the church is "rightly divided". <a rel="external" target="_blank" href="http://kanyegate.tumblr.com/">I let her finish</a> and then asked her what that meant. Cuz I've got no bloody clue. And it sounds weird. After coming home and googling it seems it's one of those religious words people use to mean "we're right about this". But <em>she</em> goes on to explain it in the context of them believing only in the KJV as "the one, TRUE translation" (I'm thinking in my head, "OK, fair enough"), and the separateness of the Trinity. Essentially, God is God, Jesus is God's son, but not God, and I stopped listening for what the Holy Spirit was, because at this point, I was intrigued. </p>
<p>You see <em>I</em> am one of those crazy folk who believe that:<br />
a) God is God,<br />
b) Jesus is the son of God, but also in a mind-bending turn of events, also God and<br />
(wait for it)<br />
c) The Holy Spirit is also God.<br />
i.e. there is God the Father, God the Son, and God the Holy Ghost/Spirit.<br />
Couldn't explain to you how that works or anything, but there it is. And the reason I believe that is because<br />
(wait for it again!)<br />
Bible says so. (you'll have to wait longer, but trust me, it's coming)</p>
<p>At this point I should point out that you should never, ever, EVER, believe anything anyone tells you is from the Bible without them, at the very least, showing it to you. Preferably they'd be able to both show and explain, but this ain't a perfect world so YMMV on that one. </p>
<p>Actually I lied a little up above, the reason I believe in the "Three in One" is because that's what was pounded in my head in Sunday school growing up. Being older, and hopefully wiser now, I am capable of checking these things out by going directly to the source now. The source being God and His word (the Bible is what I'm trying to say here folks). </p>
<p>But now this super nice lady, who's been at this church for a year, who is a new believer is telling me, in earnest, in all sincerity, that that is wrong. So surely, clearly, she must have a way of backing this up. And this backup must come from the only place that counts, the Bible. </p>
<p>So I ask rather bluntly, after she explains her rightly divided views, where in the Bible that belief comes from. Actually, that's not exactly how the story went. You see <em>she</em> was telling me that in the Bible it said that the three are separate, so I asked her to show me. Well, it was more me looking at her skeptically saying <q>Show me.</q> But I wasn't mean. Promise. My wife keeps me in check nowadays. </p>
<p>Unfortunately, she had to admit eventually that she didn't know exactly where in the Bible it was, but if I were to come to the church on Wednesday night they have open questions at that time and anyone can just come in and ask whatever they like. This was a tempting thought actually, as I love a good argument, but something far more important than having a good theological discussion was at hand. This lady, well intentioned though she was, was in my view, wrong. Worse still, she thought she was right. I figured the simple solution was for her to find it in the Bible and convince both herself and me. As I explained above I believe that contradictions present in the Bible are not so much contradictions as they are gaps in understanding. If what she believed was from the Bible, and what I believed was from the Bible, and they contradicted perhaps we two could figure out something we weren't understanding that would reconcile the two. Or perhaps I was wrong, it's been known to happen on occasion. Alas, she could not provide biblical support for her statements when asked. </p>
<p>So she went for backup. She was after all a new believer, and calling for backup is nothing to be ashamed of. Backup was not whipping out her smartphone and googling for the pertinent verses, then pulling up her Bible app and getting on with things (as I would have done). She went for a friend "who knew more". Fair enough I suppose, (although I'm of the opinion that if you're saying that things are from the Bible you are beholden to actually find said things when called out)</p>
<p>Over comes friend giving me the same spiel.<br />
It says so in the Bible she said.<br />
Where in the Bible I said?<br />
I don't remember exactly where she said, but if you come to our wednesday night...<br />
"Oh for the love of ..." Well maybe I just thought that.<br />
So I decide to be a bit more direct, "Doesn't it say in the Bible that Jesus and God are one?"<br />
I might have also asked, "If you're saying things are in the Bible, shouldn't you be able to point out where in the Bible when asked?" Or maybe I just thought it. I don't remember anymore. I guess I'd been enough of a pain at this point and off backup went to the pastor. She came back with a Bible verse. The verse I was presented with as proof of God's separation from Jesus as a singular deity (with Jesus playing the role of "just the son"), was John 10:30.<br />
I dutifully looked it up in front of her on my smartphone (love those things). The verse read </p>
<blockquote>I and my Father are one.</blockquote>
That was the King James Version, just in case you were wondering. So then I looked at her, perhaps with my eyebrow raised, the way I do when I'm skeptical about something and said rather obviously "But it says they're the same here"
<p>I forget what was said exactly afterward, but the pastor was consulted and I was informed that the "one" in that verse was translated from a greek word. And that greek word meant not "one" the singular unit, but was more accurately translated as <q>having one purpose</q>. Or something like that. </p>
<p>At that point I didn't really have anything to say. It was a plausible explanation, so I said my thanks and bid them adieu.</p>
<p>BUT WAIT! THERE'S MORE!</p>
<p>You didn't really think I'd just leave it at that did you? Nah. During my travels across the internet I happened upon the Sword Bible software and learned about the existence of something called Strong's numbers. Basically they cross reference the original (I assume) greek words with the translations in the Bible. So out came my Bible app (Eloquent née MacSword) and I grabbed a copy of Strong's Greek dictionary/lexicon whatever it is. </p>
<p>Before I looked up John 10:30 to see what Strong's Greek said <q>one</q> was originally, I read my Bible: John chapter 1. I'd originally intended to read all the way up to chapter 10, but after taking an hour to make it to only chapter one I decided to call it a morning and went off to work. While reading, John 1:1 in particular seemed to give support to God and Jesus being one and the same, and yet somehow separate, but all the while still being fully God. </p>
<p>Now to me, given the topic of John's letter (the life of Jesus) and the opening statement that the "Word was with God", and the "Word was God" and the latter explanation in verse 14 that <q>And the Word was made flesh, and dwelt among us, (and we beheld his glory, the glory as of the only begotten of the Father,) full of grace and truth.</q> that the "Word" here is Jesus. So if John is telling me in the beginning of his book that Jesus was with God in the beginning and that he, in fact, was God, what are the odds that later on in his book he himself contradicts that?</p>
<p>So I get back from work and I decide it's time to look up that verse and the corresponding Strong's Greek word. So here's John 10:30 from the KJV </p>
<blockquote>
I and my Father are one.
</blockquote>
or with Strong's numbers included
<blockquote>
I<1473> and<2532> my Father<3588><3962> are<2070> one<1520>.
</blockquote>
So I go and check out #1520 to see if it says <q>one</q> here is equivalent to <q>one purpose</q> or something similar. It says (and I'll just copy and paste here)
<blockquote>
01520:<br />
1520 heis hice (including the neuter (etc.) hen); a primary numeral; one:--a(-n, -ny, certain), + abundantly, man, one (another), only, other, some. See also 1527, 3367, 3391, 3762. see GREEK for 1527 see GREEK for 3367 see GREEK for 3391 see GREEK for 3762
</blockquote>
Now I don't know a lick of Greek, but I know my fair share of English, and I don't see anything in the preceding quote to suggest that <q>one</q> in John 10:30 means anything other than one. uno. primary numeral.<br />
Things are starting to seem Wrongly, rather than Rightly Divined. And in the absence of going to someone who speaks Greek and asking them what this means I decide to check w/ another source.
<p>GOOGLE<br />
Well, biblestudytools.com via google. Specifically I went to <a rel="external" target="_blank" href="http://www.biblestudytools.com/lexicons/greek/kjv/" title="http://www.biblestudytools.com/lexicons/greek/kjv/">http://www.biblestudytools.com/lexicons/greek/kjv/</a> and put in the Strong's number - 1520 - to see what it comes up with. </p>
<p>Now <strong>this</strong> is what we're talking about! Not only does it give a definition of the word, but it gives word usage info. In 229 instances that particular greek word was used to mean <q>one</q>, in 9 instances <q>a</q> and so on. At no point do I see anything close to <q>one purpose</q> or anything similar. </p>
<p>So let's say for arguments sake that I get to Heaven, I still believe that Jesus is in fact God. If I'm wrong is God going to turn me back? By God's own admission, I need to believe in Jesus dying on the cross for my sins and repent of my sins - John 3:16-18, John 14:6, Acts 4:12, Acts 16:30-32, <strong>Rom 10:9</strong>, Luke 13:3.</p>
<p>Having met those two requirements, I think debates on the finer points of Jesus' divinity are moot. So why this exceptionally long story? Ever since this "incident", I've been bothered by the events that transpired. Why is it that we as christians suck at knowing the Bible? This goes for me as well (as without a computer assist I wouldn't be able to argue my way out of a paper bag). Then again, I'm not presenting something as genuine without any way to back that up when it's actually checked out. C'mon christians. We gotta do better. </p>
<p>And for the rest of you, don't believe everything you hear. Regardless of how earnest, sincere or educated ("well the original greek actually means ...") they may seem. This is doubly true if they say it's from the Bible. And if you ever do find yourself in that situation, by all means, call them out on it. You'll be doing both yourself and the other folks a favor. </p>
<p>Oh, and if anyone out there on the internets actually knows what these folks were talking about (greek meaning this, Jesus is only the Son, not God, Rightly Divided etc) HIT MEH UP IN DEH comments! After all, I could be wrong.</p>
<p>Thanks for stopping bye ;-)</p>
<h2 id="comments">Comments</h2>
<h3 id="submitted-by-illogic-al-on-thu-07-07-2011-00-16">Submitted by illogic-al on Thu, 07/07/2011 - 00:16</h3>
<blockquote>
<p>All verses on requirements for salvation ripped straight from: <a rel="external" target="_blank" href="http://www.dma1.org/~ganotemd/salreqt.html" title="http://www.dma1.org/~ganotemd/salreqt.html">http://www.dma1.org/~ganotemd/salreqt.html</a><br />
Mac Bible App: <a rel="external" target="_blank" href="http://www.macsword.com/" title="http://www.macsword.com/">http://www.macsword.com/</a><br />
Sword project: <a rel="external" target="_blank" href="http://www.crosswire.org/sword/index.jsp" title="http://www.crosswire.org/sword/index.jsp">http://www.crosswire.org/sword/index.jsp</a><br />
Greek Lexicon: <a rel="external" target="_blank" href="http://www.biblestudytools.com/lexicons/greek/kjv/" title="http://www.biblestudytools.com/lexicons/greek/kjv/">http://www.biblestudytools.com/lexicons/greek/kjv/</a></p>
<p>KJV and 1984 edition of NIV Bibles.
Peace!</p>
</blockquote>
<h3 id="submitted-by-religious-on-thu-07-07-2011-10-19">Submitted by religious on Thu, 07/07/2011 - 10:19</h3>
<blockquote>
<p>Dude, do whatever you want to do.<br />
But please spare readers of blog aggregations like planetkde of such religious brainfarts. Thanks.</p>
</blockquote>
<h3 id="submitted-by-d2kx-on-thu-07-07-2011-10-47">Submitted by d2kx on Thu, 07/07/2011 - 10:47</h3>
<blockquote>
<p>Ok, this has happened some time ago on Planet Ubuntu, and now someone I find this post on PlanetKDE. If you have decided to actually waste time with this stuff, then that's completely fine, but please ensure that posts like this don't make it on PlanetKDE or related planets.</p>
</blockquote>
<h3 id="submitted-by-tumaix-on-thu-07-07-2011-11-33">Submitted by tumaix on Thu, 07/07/2011 - 11:33</h3>
<blockquote>
<p>Hey Illogic, Me on the other hand, am an Atheist because I have read the bible ( not those braindamages that doesn't belive because they doesn't belive ). If you say that the bible must not contradict itself, I disagree, but diferently from those woman that said that there was proof on the bible, but didn't know where to look at, I can for instance show you II Samuel 24, wich says:</p>
<p>24:1 And again the anger of the LORD was kindled against Israel, and he moved David against them to say, Go, number Israel and Judah.</p>
<p>but in 1 Chronicles 21 it said that:</p>
<p>21:1 And Satan stood up against Israel, and provoked David to number Israel.</p>
<p>well, Satan or God asked david to number israel?<br />
and if it was God, why he says that he sinned by numbering the people, in II Samuel 24:10?</p>
<p>24:10 And David's heart smote him after that he had numbered the people. And David said unto the LORD, I have sinned greatly in that I have done:</p>
<p>God asked him to do, he did, he sinned because of that. Is that contradiction enough?</p>
</blockquote>
<h3 id="submitted-by-auxsvr-on-thu-07-07-2011-11-46">Submitted by auxsvr on Thu, 07/07/2011 - 11:46</h3>
<blockquote>
<blockquote>
<p>My understanding of the interaction between God and Devil is that Devil asks God to do things, and God gives him permission.</p>
</blockquote>
</blockquote>
<h3 id="submitted-by-tumaix-on-thu-07-07-2011-11-48">Submitted by tumaix on Thu, 07/07/2011 - 11:48</h3>
<blockquote>
<blockquote>
<p>could be, but it says that the lord asked, then it says that it was a sin to do what god asked.</p>
</blockquote>
</blockquote>
<h3 id="submitted-by-auxsvr-on-thu-07-07-2011-11-52">Submitted by auxsvr on Thu, 07/07/2011 - 11:52</h3>
<blockquote>
<blockquote>
<blockquote>
<p>It is hard to imagine that the writer knew exactly how or what God asked from someone. I believe that the writer simply intends to say that God allowed some things to happen, and this interpretation makes sense throughout the Bible.</p>
</blockquote>
</blockquote>
</blockquote>
<h3 id="submitted-by-illogic-al-on-thu-07-07-2011-12-41">Submitted by illogic-al on Thu, 07/07/2011 - 12:41</h3>
<blockquote>
<p>No, for me it isn't contradiction enough. As I said before, the two accounts seemingly conflicting are a result of us not understanding something, and both accounts are in fact, correct. </p>
<p>As an aside, I should point out that anyone looking for reasons not to believe the Bible or believe in God will find them. By actually searching for God earnestly, and having faith in Him and His word, will we ever believe. If you're looking instead for reasons to doubt, you will find them, and find them in abundance. Now let me explain why I don't see those two verses as a contradiction. (s'long!)</p>
<p>I read the rest of II Samuel 24 to get some context (very important) and in verse 15 it says "So the LORD sent a pestilence upon Israel from the morning even to the time appointed: and there died of the people from Dan even to Beer–sheba seventy thousand men." Harsh.<br />
And in II Samuel 24 verse 1 it says "And again the anger of the LORD was kindled against Israel, and he moved David against them to say, Go, number Israel and Judah." Note how it begins: And again. </p>
<p>So apparently God had it out for the Children of Israel from the beginning. He wanted to punish them, and in verse 15 we see, apparently as a punishment for David, the Israelites suffered too. Seems unjust doesn't it. But believing that God being God, is nothing if not just that doesn't seem right. Also, having read the books before I've seen time after time, (after time), after time, (after time) where the Children of Israel disobey God, get warned, ignore it and get punished. Start in Exodus, you'll see how quickly they start disobeying. </p>
<p>So it seems to me that at the start of II Samuel 24 we've already gotten to the point where the Children of Israel have angered God (yet again), the writer just skips over that part (for whatever reason). </p>
<p>In I Chronicles 21 verse 1 it says "And Satan stood up against Israel, and provoked David to number Israel." Satan always got it out for Israel, and the human race in general, and here we see him setting something into motion. </p>
<p>Could it be that God was angry with the Children of Israel, allowed Satan to provoke David knowing the outcome, and that it would lead to a) punishing Israel for whatever it was they angered him over? and b) use it as a way to get David to feel truly sorry for what he did? I think so.<br />
Given my belief that all of the Bible is true, we see specifically that "he moved David against them" by allowing Satan's tempting of David to take place. David made his own choice, which led to the punishment of seemingly a lot of people who weren't David. But instead of being unfortunate collateral damage, it was likely deserve judgement for some earlier unspoken sins. And we get a genuinely repentant David as a bonus. A bonus with even further implications. As King of Israel, the Israelites looked up to David as an example, so a repentant, God-fearing David set an example for the Israelites to follow, and also put them in the position to be blessed by God, because they're King was doing as God told them (regardless of what they were doing as individuals).</p>
<p>Hope that helps. But remember my side comment. If you're looking for God, look for Him. Not for proof contrary to Him. You'll find exactly what you look for. I'm of the opinion that the Bible is the best place to start with this. God gives commandments and consequences for breaking these.<br />
I've spent the better part of my adult life doing things "my way" to find, in the end, God was right all along. </p>
<p>Following God doesn't make life easier, but it sure does make it far more worthwhile and less stressful/more joyful.</p>
</blockquote>
<h3 id="submitted-by-tumaix-on-thu-07-07-2011-13-31">Submitted by tumaix on Thu, 07/07/2011 - 13:31</h3>
<blockquote>
<p>I get your point, nevertheless, there's lots of different bible versions, and different bibles translations, it's impossible to say 'there's no mistake on it because those are god's words', since the translator is not god himself, he could have got something wrong. If you want to look at a very good bible ( I'v read more than 5 different kinds of translations of it ), try the yeowahs witness one, they did a very good job researching old tomes and books to retranslate it without most of the implications and collateral damage from old translations.</p>
<p>That said from a Atheist.</p>
</blockquote>
<h3 id="submitted-by-illogic-al-on-thu-07-07-2011-18-53">Submitted by illogic-al on Thu, 07/07/2011 - 18:53</h3>
<blockquote>
<blockquote>
<p>You seem to be limiting God to what he can accomplish through us mere mortals. God speaks through his word. If there's something wrong with the version you're reading, couldn't he point this out to you?</p>
<p>Remember the most important thing of all, the reason why all of this trouble is being expended. See 1st John 4. Jesus loves you. God loves you.<br />
Jeremiah 31:3: "The LORD hath appeared of old unto me, saying, Yea, I have loved thee with an everlasting love: therefore with lovingkindness have I drawn thee." -KJV</p>
<p>What's more, he wants you to want Him. Not partly, or kinda sorta-ly, but completely. Because only love given freely is worth having at all.<br />
Proverbs 8:17 "I love those who love me; And those who diligently seek me will find me." - ASV<br />
Jeremiah 29:13 "You will seek me and find me when you seek me with all your heart." - NIV</p>
<p>That said from a Christian. :-)</p>
</blockquote>
</blockquote>
<h3 id="submitted-by-auxsvr-on-thu-07-07-2011-12-01">Submitted by auxsvr on Thu, 07/07/2011 - 12:01</h3>
<blockquote>
<p>According to the tradition of the Eastern Christian Church, the Father, the Son and the Holy Spirit are of the same substance, yet different persons. ἕν means literally one. This is the dogma of the Holy Trinity.</p>
<p>About the contradictions in the Bible you refer to, one may claim that Matthew didn't hear what the other thief was saying, and was generally describing the attitude of them as a whole. I believe it is a mistake to stick thoroughly to the text and accept it as a perfectly accurate account of the events, simply because human languages and people are imperfect. This does not mean that the text errs in any way, it's just that often we are stuck in the details and miss the general idea of what the writer may or may not want to say. In the particular case I would call it a contradiction if Matthew explicitly had written that every single one of the thieves was insulting Jesus.</p>
</blockquote>
<h3 id="submitted-by-the-user-on-thu-07-07-2011-14-40">Submitted by The User on Thu, 07/07/2011 - 14:40</h3>
<blockquote>
<p>Well, I could not bear reading that text, so I stopped, did I miss the point where you was explaining that all of that is irony?</p>
<p>Seriously, you should start thinking by yourself. The evangelists were not better authors than Descartes, Nietzsche or Sartre, their work is not more important, and it is definitely not absoelute truth. When you want to know truth, you have to doubt everything, not only your one thoughts, but also the words of the Bible. Knowledge is not possible when blindly accepting a whole book. Your consciousness is the most fundamental entity in the world, not god or the bible. Think about whether god is a <em>intrinsic</em>, a necessary entity to describe the world. Think about what the word “god” means for you. It is just a word, you have to realise its meaning. When doing that I realised that that meaning is either contradicting to the truth, thus wrong, or pointless, making “god” just a useless term for something different not implying Christian ideals. The last sentence described <a rel="external" target="_blank" href="http://the-user.org/post/easter-what-is-wrong-about-god">my strongly atheist believes</a>, but you should really care about what I wrote before.</p>
<p>And please differentiate between metaphysics, epistemology and ethics! You cannot simply tranform a metaphysical entity into a moral authority!</p>
<p>And please do not include such stuff in Planet KDE. You can sometimes mention such stuff, or write about some personal things, but do not make such specialised articles show up there. I do not do that, too, when explicitly writing about such stuff.</p>
</blockquote>
<h3 id="submitted-by-illogic-al-on-thu-07-07-2011-19-14">Submitted by illogic-al on Thu, 07/07/2011 - 19:14</h3>
<blockquote>
<blockquote>
<p>I did think by myself. Then I started reading the Bible. Really reading it, trying to understand what God was trying to say. And this is where it has gotten me. I've gotten past the point of doubting God for most things. And on those issues where I still have questions, His prior track record allows me to give Him the benefit of the doubt. </p>
<p>Weirder still, the more I completely and utterly I believe in Him and His word the, clearer I suppose is the word, life becomes <em>for me</em>. Also, having never felt love like this before, I find that that love, above all else is why I'll never doubt in God again (for very long) ;-) It's like searching for something I thought was and finding it, then deciding I never want to let go again. Except sometimes I do want to let go, as following God's commandments isn't without cost. I've found that the "price I pay" as it were, is well worth it. I've become not only a better person, but also a more caring husband and father, things I believe were realistically (though definitely theoretically) possible for me. </p>
<p>Oddly enough, this has all transpired without changing the core "me". I'm a slightly more polished and refined version, with more work being done all the time. Well I'm probably boring you now, so I'll stop. </p>
<p>As for the rest of what you wrote, you lost me. I was pointing out that as Christians we have an obligation to back up the things we say with Biblical proof. </p>
<p>I wasn't arguing for why God exists, is real etc. My blog post takes that as a given. If you disagree, so be it. Needless to say, I won't be getting into how to "differentiate between metaphysics, epistemology and ethics" any time soon (probably ever). :-)</p>
</blockquote>
</blockquote>
<h3 id="submitted-by-the-user-on-fri-07-08-2011-05-40">Submitted by The User on Fri, 07/08/2011 - 05:40</h3>
<blockquote>
<blockquote>
<blockquote>
<p>“Then I started reading the Bible.”<br />
You wrote yourself that you have been grown up with it, thus the word “then” is inappropriate. You probably started before you thought for yourself, but that is unimportant, not your fault.</p>
<p>“I was pointing out that as Christians we have an obligation to back up the things we say with Biblical proof.”<br />
The bible does not proof anything except statements about the Bible. It contains stories and thoughts by various people, they can be wrong, contradicting, immoral like any other texts. You must not use induction here, you read in the bible, you agreed with some stuff, and now you are saying everything <em>must</em> be correct. That is no valid reasoning and will certainly imply wrong implications. A book is not absolute truth. You do not have to doubt god, but please doubt the bible.</p>
<p>“I won't be getting into how to "differentiate between metaphysics, epistemology and ethics" any time soon”<br />
You really should, it does not make sense to missuse metaphysical entities for moral reasoning, because metaphysics just do not care about what is good or bad, and god would not, too. Why should the fundamental entity of being care about human issues, what is good or bad for you? That way you are twitting god.</p>
</blockquote>
</blockquote>
</blockquote>
<h3 id="submitted-by-illogic-al-on-fri-07-08-2011-06-42">Submitted by illogic-al on Fri, 07/08/2011 - 06:42</h3>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<p>I think you're still missing the point. </p>
<p>I'm not arguing (nor am I interested in arguing) for the wrong-ness or right-ness of the Bible.<br />
I'm simply being as transparent as possible with my beliefs, and then stating why we Christians (those who, in my opinion, should believe in the accuracy of the Bible) should use it when purporting to be carrying out God's will. </p>
<p>Here's the executive summary: We should actually be ready to defend what we say is from the Bible by being able to show it in the Bible. The rest of the text relates a story where people said something they believed was from the Bible, but when I checked it out (as we all should) I found nothing to support what they were saying. Even from the very Bible verses given to me. </p>
<p>To use a forum term, you've gone off topic.<br />
Want to discuss the Bible? Hit me up on IRC. Maybe I'll be nice and even reply :-)</p>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<h3 id="submitted-by-dylon-on-thu-07-07-2011-20-54">Submitted by dylon on Thu, 07/07/2011 - 20:54</h3>
<blockquote>
<p>Thank you. The love with which you've written this, along with your extensive knowledge of the Word and uncanny ability to defend your position have encouraged me.</p>
<p>Another believer,<br />
Dylon</p>
</blockquote>
<h3 id="submitted-by-illogic-al-on-fri-07-08-2011-07-07">Submitted by illogic-al on Fri, 07/08/2011 - 07:07</h3>
<blockquote>
<blockquote>
<p>Thanks mate. Glad to hear it. My "extensive knowledge" isn't all its been made out to be though. My memory's crap so I google lots :-) Bible apps are also eminently searchable, which is awesomesauce.</p>
<p>I do try to read the Bible regularly, so I have a general idea of what it says and sometimes, even where it says it. If you don't already do that, I highly recommend it. A little time in the Word goes a long way. </p>
<p>Psalm 105:4<br />
Look to the LORD and <strong>his strength</strong>; <strong>seek his face <em>always</em></strong>.</p>
<p>And if you're ever near west chester, oh stop by <a rel="noopener nofollow noreferrer" target="_blank" href="http://newlifechapel.net">new life chapel</a> and checkitout. Our church community has helped me grow more in the past year than I've managed by myself in the past 5. Of course finding something a bit closer to home would be a little more practical for you :-D</p>
</blockquote>
</blockquote>
<h3 id="submitted-by-milian-on-fri-07-08-2011-10-52">Submitted by milian on Fri, 07/08/2011 - 10:52</h3>
<blockquote>
<p>Seriously, keep your personal stuff to your self. Not only the Atheists but also all those who believe in something different than you could not care less. Planet KDE should stay technical or at least related to KDE in general.</p>
</blockquote>
Risen from the dead: A Vibrant Story.2011-04-23T15:37:00-05:002011-04-23T15:37:00-05:00
Unknown
https://orville.thebennettproject.com/articles/risen-from-the-dead-a-vibrant-story/<p>I just, painstakingly, posted about 10 Facebook comments, with
the following info, chronicling the steps I took to try and fix my
T-Mobile Vibrant, which was <q>hard bricked</q>; then I realized I have a
blog where I could have posted this info and be able to get at it much
easier for the next time I brick my Vibrant.</p>
<p>So without further ado, here's how I fixed it. A quick shout out to
God for making me persistent enough to not give up. 'Preciate it
aaaaaaaaaand LOVE YAH (lots) :-) </p>
<p>So I've recovered the Vibrant from what I thought was "The <em>final</em>
brick". Through some patience, and possibly divine intervention I <em>was</em>
able to find info to bring it back to life. Sooo, I thought it would be
useful to record this, should anyone else ever face a problem like this.</p>
<h2 id="some-background">Some background</h2>
<p>I have a Samsung Vibrant. The Vibrant is, in my opinion, a neutered<sup class="footnote-reference"><a href="#1">1</a></sup> Galaxy S
phone. And currently
T-mobile has the Galaxy S 4G (essentially the Vibrant w/ a FFC and 4G
radio). This "new" phone is still inferior<sup class="footnote-reference"><a href="#4">2</a></sup> to
the original (european) Galaxy S phone, released before both, but I digress.</p>
<p>The point of bringing up the Galaxy S is to point out that Samsung
put a proprietary file system on it. The file system is called RFS <sup class="footnote-reference"><a href="#5">3</a></sup> I
believe, whereas the typical android file system is ext3. ext3 is the native linux
filesystem (suceeded by ext4) whereas RFS is a bastardized vfat, i.e.
FAT32, that ancient but venerably cross platform FS from our friends MS.</p>
<p>RFS, the Galaxy S file system, had problems however. Its use over time resulted
in noticeable lag. To remedy this sad state of affairs modders/hackers retrofitted ext3, then ext4 (successor to ext3) as the base file system for the Galaxy S
phones.
The most successful of these was called the Voodoo mod.</p>
<h2 id="the-here-and-now">The Here and Now</h2>
<p>Fast forward to today. I have a Vibrant, I'm noticing lag, I know the cause, I decide to fix it.<br>
So now, my Vibrant has voodoo (ext4) w/ Samsung's Touchwiz running atop it.<br>
Then comes CyanogenMod 7 [CM7]. CM7's claim to fame is that it's a)
vanilla android (graphically) and b) based on the gingerbread version.
This is where the story gets interesting. :-)</p>
<p>So in the course of trying to get gingerbread on my Vibrant — why? partly, because I can, partly because bits of Touchwiz annoy <sup class="footnote-reference"><a href="#2">4</a></sup> me — I brick the phone.</p>
<p>Because I didn't follow
[these](http://forum.cyanogenmod.com/topic/17020-all-models-cyanogenmod-7-for-samsung-galaxy-s-phones-build-20110304/ title="http://forum.cyanogenmod.com/topic/17020-all-models-cyanogenmod-7-for-samsung-galaxy-s-phones-build-20110304/")
[instructions](http://forum.xda-developers.com/showthread.php?t=968291 title="http://forum.xda-developers.com/showthread.php?t=968291") properly.</p>
<p>Basically in the process of trying to put the rom onto the Vibrant
via ODIN<sup class="footnote-reference"><a href="#3">5</a></sup>, I forgot the rom, added only the kernel, and got an infinite
reboot. I hightailed it back into recovery and attempted to restore the backup of my old (Touchwiz/Voodoo) rom.</p>
<p>The ODIN process put back the original RFS system whereas my backup had
the lagfixed ext4. This in itself would have probably led to what's
called a "soft brick"<sup class="footnote-reference"><a href="#6">6</a></sup>. This requires Another ODIN back to oringal firmware to fix. Unfortunately it seemed the combination also resulted in restoring a version of
rom manager which led to a "hard brick"<sup class="footnote-reference"><a href="#7">7</a></sup>.</p>
<p>So, the phone is plugged in but doesn't seem to be recieving a charge
and the capacitive buttons at the bottom of the screen never light up.
So this, on Sunday night is where I left the phone, for all intents and
purposes dead. On Wednesday I was reading a few articles and eventually
got it back up again. </p>
<p>I'll spare you anymore commentary from me and just link back to the info that got me up and running again. </p>
<p>There were also files (info on where to find them available in the "<a rel="noopener nofollow noreferrer" target="_blank" title="Vibrant Bible" href="http://forum.xda-developers.com/showthread.php?t=771111">Vibrant Bible</a>" on XDA forums) necessary for the recovery.</p>
<p>File 1: JFD stock firmware</p>
<p>File 2: <a rel="noopener nofollow noreferrer" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=909183">Eugene's Froyo that does not brick</a>.</p>
<p>The following links were also useful info-wise:<br>
<a rel="external" target="_blank" href="http://forum.xda-developers.com/showpost.php?p=8922602&postcount=10" title="http://forum.xda-developers.com/showpost.php?p=8922602&postcount=10">http://forum.xda-developers.com/showpost.php?p=8922602&postcount=10</a> from <a rel="external" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=822727" title="http://forum.xda-developers.com/showthread.php?t=822727">http://forum.xda-developers.com/showthread.php?t=822727</a></p>
<p>Recover from phone which doesn't charge (info says: wait a few hours, then try again)<br>
<a rel="external" target="_blank" href="http://forum.xda-developers.com/showpost.php?p=10485853&postcount=10" title="http://forum.xda-developers.com/showpost.php?p=10485853&postcount=10">http://forum.xda-developers.com/showpost.php?p=10485853&postcount=10</a> from <a rel="external" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=907248" title="http://forum.xda-developers.com/showthread.php?t=907248">http://forum.xda-developers.com/showthread.php?t=907248</a></p>
<p>Useful to have: <a rel="noopener nofollow noreferrer" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=798125">ODIN and pit files</a></p>
<p>After doing the above I was able to ODIN and get the bottom buttons glowing (progress) and this helped out w/ that <a rel="external" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=745547" title="http://forum.xda-developers.com/showthread.php?t=745547">http://forum.xda-developers.com/showthread.php?t=745547</a><br>
<a rel="external" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=803693&page=3" title="http://forum.xda-developers.com/showthread.php?t=803693&page=3">http://forum.xda-developers.com/showthread.php?t=803693&page=3</a></p>
<p>So then I had problems w/ ODIN after this as it wouldn't complete. The
problem was that I needed to reboot and get back into download mode (w/
no screen info as it was still black )<br>
<a rel="external" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=777872" title="http://forum.xda-developers.com/showthread.php?t=777872">http://forum.xda-developers.com/showthread.php?t=777872</a><br>
<a rel="external" target="_blank" href="http://androidforums.com/samsung-galaxy-s/320953-phone-not-working-after-update.html" title="http://androidforums.com/samsung-galaxy-s/320953-phone-not-working-after-update.html">http://androidforums.com/samsung-galaxy-s/320953-phone-not-working-after-update.html</a></p>
<p>With ODIN seemingly not working along with the screen, the yellow
COM3 (or COM#) is your only indication that you have successfully
achieved it.</p>
<p>FINALLY, another major resaon for installing CM7 is that I was having
screen distortion issues w/ the Touchwiz roms. I assumed it had
something to do with the Kernels/Clock speed settings that was causing
the CPU to overheat and make the graphics chip overheat. </p>
<p>Turns out, the issue was probably due to a faulty connection from the LCD/Digitizer to the rest of the phone logic board. </p>
<p>I thought that if Touchwiz roms were having a problem w/ these
settings then installing a rom not based on touchwiz would alleviate the
problem. </p>
<p>In a sort of roundabout way. I was right :-)<br>
Unscrewed and took apart the phone and when putting it together after finally installing CM7 had the same issues.<br>
So i took it apart again and made sure the connection from the
LCD/Digitizer to the board was solid and that seemed to fix things.</p>
<p>So there we are, that's how I brought my Vibrant back from the dead. </p>
<p>With a little patience, a lot of reading and some feeling of responsibility
(as I could have gone back to the T-Mobile store and tried to pass it
off on them as a warranty claim). I don't like when people who break their phones do things like that though.</p>
<p>However, in the case of this phone, this would be acceptable BECAUSE THIS PHONE SUCKS SO HARD THAT SAMSUNG, THE MANUFACTURER, STILL HASN'T FIXED THE GPS TO BE RELIABLE (ALMOST A YEAR AFTER RELEASE).</p>
<h2 id="addendum">Addendum</h2>
<p>I can tell much, never again Samsung. Awesome screen or no, it's not worth the hassle. I have no intention of purchasing any Samsung devices in the future: phone or otherwise.
The End? Probably not. The CM7 version for the Galaxy S series of phones is a kanged<sup class="footnote-reference"><a href="#8">8</a></sup> version. </p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>It lacks the front-facing camera [FFC] and FM Radio</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">4</sup>
<p>e.g. not being able to change the system's voicemail service to google voice</p>
</div>
<div class="footnote-definition" id="3"><sup class="footnote-definition-label">5</sup>
<p>ODIN is apparently a leaked samsung program for putting software on the phone. It only runs on windows. There is also a cross platform program named Heimdall which can reportedly perform the same function.</p>
</div>
<div class="footnote-definition" id="4"><sup class="footnote-definition-label">2</sup>
<p>It still lacks the FM radio, which is not made up for by the fact that it has battery draining 4G, which T-Mobile doesn't have widely deployed.</p>
</div>
<div class="footnote-definition" id="5"><sup class="footnote-definition-label">3</sup>
<p>Retarded File System?</p>
</div>
<div class="footnote-definition" id="6"><sup class="footnote-definition-label">6</sup>
<p>software brick - software induced blank screen where you see a boot logo but can't otherwise get into the OS.</p>
</div>
<div class="footnote-definition" id="7"><sup class="footnote-definition-label">7</sup>
<p>hardware is totally dead and doesn't power on.</p>
</div>
<div class="footnote-definition" id="8"><sup class="footnote-definition-label">8</sup>
<p>to kang, verb: to reproduce without express consent; unofficial reproduction</p>
</div>
Intel 82845G/GL[Brookdale-G]/GE Graphics and KDE 4.5 Desktop Effects2010-09-06T06:26:00-05:002010-09-06T06:26:00-05:00
Unknown
https://orville.thebennettproject.com/articles/intel-82845g-gl-kde4-5-desktop-effects/<p>I've hit this in Arch Linux and it's quite annoying: <a rel="noopener nofollow noreferrer" target="_blank" href="http://chakra-project.org/news/index.php?/archives/82-Open-Source-GPU-Drivers-Causing-Headaches-In-KDE-4.5-series.html">Open-Source GPU Drivers Causing Headaches In KDE 4.5-series</a>. I was angry at first but then I read Martin's <a rel="noopener nofollow noreferrer" target="_blank" href="http://blog.martin-graesslin.com/blog/2010/09/driver-dilemma-in-kde-workspaces-4-5/">explanation</a>
for what was happening and decided to be more forgiving. I am
experiencing this on an old system with a POC integrated video card
after all; the fact that I get any effects at all is somewhat admirable.</p>
<p>It <em>was</em> pretty disappointing however that this problem
exists. I didn't read them but something like this should definitely be
in KDE's release announcement. Why? So my distro (who's announcements I
am likely to read - after something goes wrong) can point me to it.<br />
Then I wouldn't have a) upgraded or b) had such a hard time figuring out
why X was crashing, and why Desktop Effects were so PAINFULLY slow,
after upgrading Xorg. I didn't ever really think it was wholly KDE's
fault which I suppose helps with being forgiving AND I was being
stubborn by trying to force desktop effects on through XRender after
multiple crashes. After all <q>It worked before so why not now?</q> <q>Worked</q> there being a relative term however.</p>
<p>Anyhoo <code>Backend=XRender</code> and <code> OpenGLIsSafe=true</code> in my <code>$KDEHOME/share/config/kwinrc</code>
file brought me back to the painfully slow compositing, rather than
crashing straight to GDM repeatedly, which I thing I tracked to kded and
dbus having a lover's quarrel (YAY!). After getting the compositing
back I turned off everything unecessary like transparent windows and
BLUR. I only really want transparency in specific apps (Terminal,
Plasma) and the blurred Oxygen window highlight.</p>
Android2010-08-31T21:56:00-05:002010-08-31T21:56:00-05:00
Unknown
https://orville.thebennettproject.com/articles/android/<p>Heeeeeey. So I got married to the love of my life and whatnot last Saturday. Fun times, lemme tell yah. But that's another (potentially too long) story for another day.</p>
<p>Today let's talk about ... ANDROID. Yes, the little, mostly open source operating mobile operating system that could. I got a T-Mobile G1 last year sometime and have been rooting and <q>romming</q> it ever since. Since I knew I was pretty much getting married, and the wife demanded family plannings (phonewise at least) I had to get her a new T-Mobile phone as she was previously with Verizon Mobile, aka The Evil Empire (again, another post for another day).</p>
<p>The MyTouch 3G slide was on my radar for a few months prior (Engadget, Phandroid, etc) so when I showed it to her and she actually liked it I figured that would be a good phone to get her. The problem here of course, is that this meant her phone would then be better than mine. Luckily the T-Mobile Vibrant, essentially a branded Samsung Galaxy S was also about to be released. To make a long story short, we got both phones; her the 3G Slide (MT3G Slide) and me the Vibrant. And so began the rooting and rommings, again.</p>
<p>The Vibrant, compared to the MT3G Slide was a much simpler device to root. Alas, though there was rooting, there wasn't really any romming as only modified stock roms were available, which annoyed me greatly.</p>
<p>Moreover this 1 GHz monster was crippled by some rather poor software choices which progressively became more and more annoying. And this I found out after going taking the time to fix the glass touchscreen on the Vibrant, which I had cracked after allowing a TV to fall on it.</p>
<p>Meanwhile the wife was getting annoyed with her phone as it had pretty low signal inside the house, something I never experienced on my phone.</p>
<p>The solution? Switch phones. Now although the MT3G was a less powerful phone it suited me just fine, mostly due to the sense interface customizations and the physical keyboard. Oh, and the MT3G Slide actually felt like I could someone to death with it in as opposed to the lightweight Vibrant. I like the hefty feeling, feels less fragile. So switch we did which gave her the rooted Vibrant and me the not-so-rooted MT3G Slide.</p>
<p>Now Espresso/Sense is pretty close to awesomesauce, but a non rooted phone is ... well, it's a non-rooted phone: lamesauce. So over the course of the next two days I read and read a great number of threads over @ xda-dev HQ until I was sure I could root this bad boy. It was the hardest root I've ever had to do. Eventually though I had gotten it rooted, thrown a modified Espresso rooted rom on there, and all was well with my world. Then came CyanogenMod 6.0.</p>
<p>CyanogenMod is a community-based android rom (started by 'cyanogen') that grown by leaps and bounds throughout the various incarnations I've used (v3-5 and 6-RC2 on the G1, v6 on the Slide). Version 6 brings the latest and greatest from Froyo land and a stable version was released for the slide on the 28th of August. Yep, my wedding day. Awesome present, I know.</p>
<p>So I threw CyanogenMod 6.0.0 on this thing and it runs great. There are some things from the Stock slide rom I was missing though, so I figured I'd post them here. Future reference and all that.</p>
<ol>
<li>Rom Manager - For flashing new roms and backing up old ones. It can also DL cyanogenmod roms for supported archs within the app.</li>
<li>Swype - I'd signed up for the beta so I was able to get the latest beta. However, the phone I bought came w/ swype too. I found a version 1.60 on the internets (have yet to install this though). I tried installing the version on our Vibrant, but that failed miserably.</li>
<li>SetCPU - this is an app which managers the cpu</li>
<li>VatSense Theme - for CM 6.0. To get back to the Sense Look/n/Feel <a rel="noopener nofollow noreferrer" target="_blank" href="http://forum.xda-developers.com/showthread.php?t=735822">xda-developers.com</a></li>
<li>EStrongs File Explorer - can do root w/ cyanogenmod. Free, Adfree, and looks good.<br /></li>
<li>Barnacle Wifi Tether - because Wireless Tether for Root makes the Slide freeze then reboot.</li>
<li>Latest Radio for MT3G Slide</li>
</ol>
<p>TODO - OverClock Kernel - To get the most out of SetCPU</p>
<p>Now our phones don't have any better reception inside, but the switch has proven to be a rousing success. She likes the shiny, and I like the tiny. And that's been my android adventure for the past two months or so. Fun times, all made possible by Linux. :-D</p>
The Struggle2010-06-02T09:32:00-05:002010-06-02T09:32:00-05:00
Unknown
https://orville.thebennettproject.com/articles/the-struggle/<p>I was walking to the supermarket last week (5/25) and started thinking. Then a couple days later I started talking about the same topic in lab with someone. I thought I'd throw them out there for all the world to see (and inevitably, critique). My thoughts went thusly:</p>
<p>To all the crippled, old people out there going to school, I'd like to say something ... thank you. Some days i want to give up, some days i want to just pack it up and disappear somewhere in the woods and just "live off the land" getting rid off these people and the problems they're causing in my life. And then I see them. The old guy with his briefcase going to class, the middle aged dude in sweats power walking through the tunnels to get to the next lecture. Determination in their eyes, the grit of purpose on their countenance. The girl hobbling on legs that don't quite work to the next lecture. And if they can do it, darn it i can too.</p>
<p>It's in these moments when i start thinking about this stuff that I thank God. I get it. Struggle is necessary. If not for my sake then for the sake of that little girl looking up to me. Because when she sees that i have a hard time in life too, and when she sees me not blaming circumstance and giving up, that gives her strength, that gives her the will to carry on. That also takes away the excuse to just give up. And that brings the opportunity to let her know how I survived it all: Jesus. The everlasting love of the Father, Son and Holy Spirit got me through. Didn't make it easier (I don't think), but it did make it bearable.</p>
<p>As long as humans have free will, there are those who will exploit others for their benefit, ruining lives. As a result of this it is perhaps inevitable that at some point in your life you will be "screwed over." You don't need to be afraid though, the lord will guide you through, and in doing so, make a better person of you. And who knows, your struggle may even help someone else, perhaps even to the point where they give their lives to the Lord. So don't give up, and do listen to what the Lord tells you to do. What do you possibly have to lose <strong>that's not worth losing</strong>? I mean yeah, you could lose a lot, I've lost tons. Nothing which I couldn't do without though. And most times I realize that what I've lost was better off not having.</p>
<p>To use an illustration I've used before, I'll compare it to this: it's like losing that hot chick you were dating to go <em>marry</em> that homely looking chick that's been your neighbor since forever.</p>
<p>At first it might seem like a downgrade, but then yours eyes open up. You see that hot chick was only ever hot because she layer-caked makeup all over and wore those pushup bras w/ skimpy outfits. She wasn't <em>really</em> hot, she just covered up all the faults well. And you had to pay for all that crap too. As long as the mirage was up though, you were OK with it.</p>
<p>On the other hand, you've come to realize that homely chick is perfect. She only ever wanted you so she wouldn't go out in public showing her ladybits to everyone. You however were too dumb, and blind, to look past it. But she helped you through a hard time, you got to know her and the more you knew, the more you loved. All her uptightness made sense now.</p>
<p>Next thing you know, you're happy you're not w/ hot chick because, well ... she was shallow, and having found something deeper, there ain't no way, <strong>no way</strong>, you're going back.<br />
And it doesn't hurt that under all those layers of clothes, and behind the oversized glasses, she's flippin' hot! </p>
<p>Well, that's how I see it in <em>my</em> head. Maybe that won't work for you. Unless you're a dude who knows what I'm talking about. Or gay. Where was I going with this again?<br />
Ah. Yes. You don't really lose anything <em>worthwhile</em> giving your life to Christ, and for what you do lose you gain a whole lot more.</p>
The Saddest Word2010-03-27T23:08:00-05:002010-03-27T23:08:00-05:00
Unknown
https://orville.thebennettproject.com/articles/the-saddest-word/<p>Dear Internets,..
I live. The winter session of school has ended and I got a B. That brings the GPA down to a 3.8 something, I'm rather happy with this. Lab work is picking up as well. Also I have a girl. I'm <em>extremely</em> happy with this. She's a keeper as they say (because she's awesome). </p>
<p>T'would seem that now I have a family, and above all else, that is what's important to me. I probably won't be coming back to you but it's OK, there'll be other students, other out-of-work chaps with too much time on their hands and an unhealthy longing for a specific app. Or perhaps there is only one. Either way you won't being seeing much "work" from me. </p>
<p>I've enjoyed our time together though. It's been fun. Really.<br />
See you on the book of faces. :-)</p>
Love Letters2009-10-13T00:07:00-05:002009-10-13T00:07:00-05:00
Unknown
https://orville.thebennettproject.com/articles/love-letters/<p>Excerpted. For your reading pleasure.</p>
<p>So I've been bouncing between reading 1 Peter and 2 Peter, in no
particular order recently. I highly recommend taking the time to read
chapters 4 and 5 now, then going back and reading chapter 1 to the end at your
leisure.</p>
<p>(NIV version below)<br />
1 Peter 4: 12 starts:</p>
<blockquote>
<p>”Dear friends, do not be surprised at the painful trial you are suffering, as though something strange were happening to you. 13 But rejoice that you participate in the sufferings of Christ, so that you may be overjoyed when his glory is revealed.14 If you are insulted because of the name of Christ, you are blessed, for the Spirit of glory and of God rests on you.15 If you suffer, it should not be as a murderer or thief or any other kind of criminal, or even as a meddler. 16 However, if you suffer as a Christian, do not be ashamed, but praise God that you bear that name."</p>
</blockquote>
<p>The take home message? Suffering is a part of being a christian and
it's better to suffer while doing good than when doing bad.</p>
<p>Now what I was saying to you earlier about you needing to submit to
God's will just jumped out at me here again in chapter 5. Here's what
it says starting with verse 6 "Humble yourselves, therefore, under
God's mighty hand, that he may lift you up in due time." And then
verse 7 says <strong>Cast all your anxiety on him because he cares for you</strong>.
All of it, not some or a little or most. What you need to learn now,
is how to do that, and it starts with stepping out in faith.</p>
<p>Whenever you talk about your problems you always say there is no one
with you. You know what? From your attitude I think that's right. I
don't think you've really, truly invited God INTO YOUR HEART, and gave
it and the rest of you COMPLETELY to Him. That, in itself doesn't
bother me though. It takes time sometimes, what does bother me is that
when you speak I don't even get the sense that you're trying. That you
have any inkling of what it's like to know that God is with you and
will take care of you. You really have no idea, I think, what a
personal relationship with Jesus Christ is.</p>
<p>Now I don't know if that's true, and there are only two entities who
will ever be able to know that: You and God. But I think it's
something YOU need to seriously think about, whether or not you're
serious about becoming a child of God or not. You probably won't be
transformed overnight, and it <em>certainly</em> won't be easy.
Also I should point out that it doesn't matter whether I think you're
a christian or not, this is between you and God and no one else. God
is the only person that can judge you so if you know that you have
given your life to God, don't let anyone make you doubt that, not even
or especially me. I can only see outwardly with my human eyes. God
sees the heart.</p>
<p>So let's say that you are a child of God and you're suffering. 1 Peter
5: 8 starts:</p>
<blockquote>
<p>”Be self-controlled and alert. Your enemy the devil prowls
around like a roaring lion looking for someone to devour. 9 Resist
him, standing firm in the faith, because you know that your brothers
throughout the world are undergoing the same kind of sufferings. 10
And the God of all grace, who called you to his eternal glory in
Christ, after you have suffered a little while, will himself restore
you and make you strong, firm and steadfast. 11 To him be the power
for ever and ever. Amen."</p>
</blockquote>
<p>There is a light at the end of the tunnel
(to use an overused cliché) even when you can't see it, God will see
you throw and you will be stronger for it.</p>
<p>There will always be struggles because all the devil wants to do is
attack us. Test us. Bring us down so that we fall away from God and
never get anywhere.
You say you're a good person and that good things never happen to you,
and you don't deserve it? well guess what, you aren't a good person.
None of us are. Good people do not lie, they do not envy, have malice,
selfishness or are lazy (even a little).
(If you were geeky like me I'd joke that some asymptotically approach
goodness) :-). Basically what I'm trying to say there is that even
when we try to be good we never get all the way there. And if we're
bad then wouldn't you expect bad things to happen in kind? Well maybe
you're not that bad, actually maybe you are in fact a saint. Jesus was
a good person, he got strung up in the most humiliating way (of the
time) possible by the folks he was trying to help. If it happened to
Him, who was absolutely blameless (as far as a christian is concerned)
would you expect better for yourself who isn't faultless?</p>
<p>REGARDLESS of that God has promised to take care us if we SUBMIT to
HIS will. Nothing that God tells us to do is something that will hurt us.
It may be hard to do because it stops us from doing what we want, but it's
still the best option. Like I said before, following it won't be easy,
but the more you do it, the more you'll see why it's the best thing
you could do in your whole life, and the easier it gets. Because the
more you lean on God, the more he strengthens you. And then once we're
stronger we can be in a position to help others too.</p>
<p>We have a God who is easily able to lift us up. He may have
other people who are strong enough come in and do that but so what?
Just because someone isn't related to you doesn't mean that they can't
help. Only pride prevents us from accepting the help of others. The
need for us to give the illusion that we're OK and can deal with
things on our own. Remember verse 6? "Humble yourselves, therefore,
under God's mighty hand, that he may lift you up in due time." No one
is completely OK, we ALL need help.</p>
<p>If you're serious about following Christ, as I see, you have some
things to work on. For me: compassion, for you: stubbornness and
pride. Hopefully you read all this. You can cry, you can not cry, you
can get angry or contemplative.
Whatever you do, do it with God. I don't care if you curse me out or
get mad at me so long as at the end of the day you sit down and ask
God, "Am I doing things right?" and "If I am, why don't you help me?"
Talk to God! That's what he's there for.</p>
<p>Read the bible too. Old and New testament. You say you don't have time
at night. MAKE TIME. Speaking to God is not just something you do. It
should be a part of your life. The most important part. He should be
the most important person in your life. And if He isn't ... you're
doing it wrong. Know why? Because if you put him first, then you will
also have the best interest of everyone else at hand. And if you put
him first you'll have your best interest at hand too because He
already takes care of that. And by best interest I don't mean you'll
get nice shiny things. God cares about people, relationships.
Materialism means nothing but that's going into another subject for
potentially another day.</p>
<p>I have a lot to do, and when
I'm done with that it'll probably be so late I have to go to bed. So
when I came in I took 10 minutes and went to read the bible. It wasn't
even anything new, just something I read before. But one hour later
I'm here writing this e-mail to you. Why? Because after doing that,
God spoke to me, and I hope now He's speaking to you. Who knows, maybe
you'll be able to help me in my walk with Christ and I'm really the
one who needs to get help. How would I ever have known if I didn't
take this time.</p>
<p>Also, I was eating when I was reading the bible. I didn't need the
<q>mood</q> to be set. Just grabbed some potato bread and nutella and sat
down for a few minutes. Start small. Can't do it when you get home? Do
it in the morning. Can't do it in the morning when you get up? When
you're on the train. Can't do it on the train? When you get to work.
Or in the bathroom at work. Or on the way back from home.</p>
<p>If you can't find time for God, then He isn't really that important to
you is He?
I could go on about prayer and how to pray, but this is kinda long
already so I'll have to save that for another day. Also, forgive.
Holding a grudge only holds in pain. You've got better things to do
with your life. Forgive and move on. Everybody, including yourself :-)</p>
<p>Love you, later.</p>
Remember, remember2009-09-13T23:35:00-05:002009-09-13T23:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/remember-remember/<p><em>Sigh</em><br />
It's September again. School's started. Unlike last Spring semester, where I had one class, was complaining about working and being a full time student, I now have two classes and am working while being a full time student. S'kinda neat. I should be finished w/ coursework in just a year, assuming I don't fail miserably. Master's research? I don't really think so.</p>
<p>I also have 0 enthusiasm in my boosiasm for coursework, normal work, or even people-work (I don't know either). I just feel ... lost? The whole homeless and being "forced" to co-habitate with another human being thing got to me probably. I really am not suited for this whole socializing thing you peons do. </p>
<p>Oddly, I'm sure God has a plan in all this but I'm not sure I'm going to like it, or where it's going. I'm fairly certain actually. But hey, wanna here a cool story? Pull up a chair suckers, you're already here!</p>
<p>So rewind a year: it's september. I've been ignoring my mail here in Ohio for months now, but I finally decide to go through it. One auspicious mail is from the IRS, I owe them money. Suckage. Whatever though, I have a job after all, and even though i can just barely make ends meet I figure I should go give these people their money. The sooner the better. The solution then is to arbitrarily choose a very large sum of money to give to them each month, without thought of my ability to sustain these payments in the event that something happens (colloquially referred to as <q><<em>edited for content</em>> happening</q>)</p>
<p>Well here comes <<em>edited for content</em>> walking down the street. Happening along as the case may be. That requires more money to be spent. Oops. Or is it? I had decided earlier that since I was having trouble making ends meet that I should get a cheaper apartment. They call those studios here in Ohio. Now while I had decided that, I made absolutely no moves towards making this happen. Enter person X. Actually no, enter F (yes, <q>F</q> has been designated by single initials because on the internet, that's what you do when you want to credit/refer to someone whilst keeping anonymity). F pokes and prods me to meet the Apt. manager one evening, setting in motion a series of events which leads to me getting my studio. <em>Then</em> <edited for content> happens. Ok we're all caught up again. Let's calls this point M1.</p>
<p>So it's Late winterish and I'm sitting in lab and I say to myself, <q>dude: you need a raise.</q> Need being the operative word there. I text this to F. F says <q>Yup.</q> I go to the bossman requesting said raise. Let's Say this is Februaryish. I later <q>get back</q> my tax refund. That's in quotes because it means the IRS has taken the liberty of claiming it as their own. Excellent, significantly less high payments left to make. I can just about break even again. Let's call this point M2.</p>
<blockquote>
<p><q>Y'Know. You should go back to school</q> says F. </p>
</blockquote>
<blockquote>
<p><q>I hate school. Maybe later.</q> says I.
Rinse, lather, repeat. </p>
</blockquote>
<blockquote>
<p><q>I really feel that this is what God wants for you,</q> says F. </p>
</blockquote>
<blockquote>
<p><q>I really feel that if God wants me to go back to school he'll let me know.</q> says I.</p>
</blockquote>
<blockquote>
<p><q>How do you know he isn't now?</q> says F. </p>
</blockquote>
<blockquote>
<p><q>How do I know He is now?</q> says I. </p>
</blockquote>
<blockquote>
<p><q>Why don't you just try?</q> says F. </p>
</blockquote>
<blockquote>
<p><q>Money. School is expensive.</q> says I. </p>
</blockquote>
<blockquote>
<p><q>Let's work out a plan. You can try, just try.</q> says F. </p>
</blockquote>
<blockquote>
<p><q>Sure. If it's not what God wants I don't get in and I win. Booyah!</q> says I. </p>
</blockquote>
<blockquote>
<p><q>You'll get in. And do well.</q> says F. </p>
</blockquote>
<blockquote>
<p><q>Uh huh. < insert sarcasm here >.</q> says I. </p>
</blockquote>
<p>This was two weeks before the deadline for grad school applications. I was accepted to the Master's program, for the fall. On the day everything was due my dep't was running paperwork, by hand, to be signed by department heads to get me in for the <em>Spring</em> semester. I forget the details. Regardless, I gave peeps chocolates. T'was well deserved. We shall call this M3.</p>
<p>Now Spring semester is upon me and I've gotta pay for all this somehow. Actually let's rewind a bit: my raise is approved. After less than a year of employment I'd say that's a pretty good deal. I can actually make ends meet (and not cry when I have to pay tithes). Let's call that M4. I figure I might as well start saving now so off I go to the Credit union to open an account. Let's call <em>that</em> M5. </p>
<p>So Spring semester is upon me and I've gotta pay for all this somehow. I figure it's a good time to get a student loan. And it just so happens that if you're a member of the credit union (the only one on school grounds) you can get grad student loans through them for pretty good rates. P.S. Wright-Patt Credit Union is awesome. Chase for reasons I will not get into, <em>is not</em>. </p>
<p>I've got to register for classes though, and so away I go. The bill seems a bit light though. $8. As it turns out the school pays for up 8 credits, which is exactly how much I'm taking, which is what I need to be full time, which is what I need to qualify for that loan. Did God really just work all that out so that I'm going back to school for free? Again. While getting paid, and having medical benefits and all that? I do believe so audience. But wait, there's more. This would be M6 btw. </p>
<p>Spring semester ends and I get an 'A'. M7.</p>
<p>Enter summer. Email comes through that because of state budget cuts no one'll be getting raises this year. Except me. Since I already had mine. M8.</p>
<p>Lease is up and it's time to move. Poor planning on my part, leads F and me into last minute apartment hunting mode. And so we get to the meat of the matter. I've found a place that I like and want to move into. Leases're signed. Promises're made. It's July 31 and the place is not ready. All <em>my</em> stuff is moved out of my old place. July 31st is a Friday. From then until Monday I have no contact w/ the landlords. When I do, they prove to be rather unscrupulous and deceptive people. Such is life. So I won't be moving to Village of Cedars. God has saved me from only He knows what. From my myopic view however, I'm out a place to live. Ah, but F to the rescue! M9, let's say?</p>
<p>And now the hunt for apartments. Again. Quite by accident, or one might say, divine intervention my current place is found. Actually, let's back up a bit. So F gets the apartment ball rolling and strikes a deal Wednesday afternoonish. The deal is: get deposit in by the end of day and the place is mine, apparently a few others were looking at the place. Unfortunately, the deposit is equal to the first month's rent; which I no longer have. On a whim however, I decide to open a line of credit that morning at the credit union. The amount covers the deposit and payday, which is but two days away takes care of the rest. Well, now it doesn't seem like much of a whim. God working in His mysterious ways again. I think I'll call that M10.</p>
<p>But we're not out of trouble yet. The other would-be landlords don't want to give me my deposit back. They figure a college student'll be easy pickings and not have the strength/time/money to go through the hassle of getting it back. And they'd be right. Except for M6. Remember the $8? That's a student legal services fee. Lawyers for cheap = rent deposit returned.</p>
<p>Enter September. School's back. Me and F? Relationships a bit ... strained I suppose you could say. Let's say that living with someone out of necessity is not something I do well. But I'm looking back, thinking back, about all the things which've happened. All things coincidences, seemingly random chain of events which link together. Milestones in my life I suppose you could call them. I prefer miracles though. Above I've given you 10 examples. Some things I'd prayed about, other I hadn't prayed but all which needed to happen for other, necessary <q>things</q> to be set into motion. I look back on it in wonder and amazement. And just a little bit of fear. Ok, maybe more than a little. You know the saying <q>To whom much is given, much is expected</q>? It's from the Bible actually, the book of Luke chapter 12 verse 48. <q>To whom much is given</q> describes me perfectly.</p>
<p>Do you ever get that feeling that God has a plan for you? I do. Scares the shit out of me. Know why? 'Cause He does...</p>
Contribution2009-07-03T21:29:00-05:002009-07-03T21:29:00-05:00
Unknown
https://orville.thebennettproject.com/articles/contribution/<p>I was just thinking about all the projects I've contributed code to in the past and thinking, "Huh. That's quite a sizeable list."
The list goes something like this:</p>
<ul>
<li>Enlightenment (0.16-ish)</li>
<li>Kicker</li>
<li>Amarok</li>
<li>Konversation</li>
<li>Qt</li>
<li>Kopete</li>
<li>Macports</li>
<li>Openbox (3-ish)</li>
<li>KDE (4.2-ish)</li>
</ul>
Psalms 118:18 or, how I managed to give up porn and eaked out enough courage to talk about it tangentially2009-04-04T18:12:00-05:002021-04-26T09:31:00-05:00
Unknown
https://orville.thebennettproject.com/articles/psalms-118-18-or-how-i-managed-to-give-up-porn/<p>I've been attempting to read the Bible, the whole Bible, for years now. It's a remarkably boring prospect though. Call me sacrilegious if you will but that is honestly how I felt and sometimes still feel about it. I believe if you're honest you may just admit the same.</p>
<p>Despite this obstacle I have, slowly, managed to meander through. At this point I've probably read the New Testament through a couple of times already. Old Testament? Not so much. Whenever I do get bored or skip a few days I usually fall back to my standard: the good ol' New Testament. It's easy reading most of the time.</p>
<p>I also have 3 Bibles now, the KJV, the NIV and the NetBible. The latter two of which are written in <q>normal</q> people english. This facilitates study of the Bible by making it much easier to understand. This probably has a lot to do with why I've made it this far in my Bible readings. It helps when the dense material isn't written in an even denser language :-)</p>
<p>But is it study or reading? A little bit of both, although I feel it should be primarily the latter. Thing is I don't play well with others, and yet, it's hard to <q>get</q> some things if others aren't around. Sometimes I pray to God for understand while reading (thusly falling into the category of study) but not often enough, I feel, to make it useful. Nevertheless, I have progressed. I dropped off at Psalms in the Old Testament sometime last year. Just knowing I had a hundred odd of those chapters to go through, and knowing I'd hit Psalm 119: The Gauntlet, eventually, made me want to skip it. And so I did. And so I fell off the wagon (to use a crude expression).</p>
<p>And now here I am, on the precipice of <q>The Gauntlet</q> and I hit this verse. Psalm 118, verse 18 (NIV version).</p>
<blockquote>
<p>The LORD chastened me severely, but he has not given me over to death</p>
</blockquote>
<p>I had to smile when I read that because it seems like that's <em>exactly</em> what he's done to me! Because it is. I have not, and never pretended to be, the brightest or best follower of Christ. In fact I had a grand plan when I became baptized in '99 to be the perfect christian. It involved avoiding all human contact. Which worked spectacularly, with the exception of the porn and all. You see my thinking was, if I didn't interact with people I could do limited wrong, and limited wrong was certainly better than more than limited wrong, and then I could work on the limited wrongs in my isolation and <q>become the perfect boy</q>. In my defense I should point out that this was a part of a similar plan, hatched earlier in my childhood to just avoid people entirely because they scared the heck out of me, now modified to suit my new-found life in Christ. Dinnae work out so well. I may <a href="https://orville.thebennettproject.com/articles/my-life-the-early-years/">(start to) explain why another time</a>.</p>
<p>Anyways, being removed from humans for contact made it easy to descend into the depravity that is porn, and then there was the internet: the porn delivery system to end all. I suppose you could say it was a match made in hell. And so I come to the trickiest part of my essay/confessional. Explaining how you can be a christian, and be doing very <strong>unchristian</strong> things at the same time. <em>sigh</em> I'll skip that part because I can't really explain it. But I will say the following:</p>
<p>The Bible teaches forgiveness, both Old Testament and New. God was forever forgiving the Israelites after they screwed up and asked Him for forgiveness. Jesus also preached repentance (admitting sin, saying sorry) and forgiveness. Christianity then has forgiveness as a core principle. Not just forgiveness by God, but forgiveness of enemies, friends, co-workers, people who've wronged you, the man who molested your child, the doctor who botched your daughter's plastic surgery (what, her breasts were too big), and even the wife who gets on your last nerve (girlfriend(s) too).</p>
<p>The difference between a Christian and non, in my humble opinion, apart from belief in Jesus as the Son of God/God himself, is additionally admitting that what we do is wrong, and trying not to do it again. I.E. it's not just believing. We have to believe, in believing admit our wrongs, in admitting our wrongs be <span title="people say I have a problem with that: I don't think so, how about you?">humble</span>, and in the humility submit to His will.</p>
<p>That's a tall order. Well, let me not generalize. That's a tall order for <strong>me</strong>. Especially the last part, the submitting to His will part. I've never had any difficulty in discerning right from wrong or moral/immoral as it pertains to the views of God. I have forever, ever since I've been conscious of who I am had a problem with following though.</p>
<p>After all, it's my life isn't it? God gave me the right to do what I wanted to, so why shouldn't I? Why can't I have fun! Do something reckless or selfish. As long as I'm not hurting anyone else it should be fine. Or so I used to say. I've spent, I'd say a decade, from 16 when I was baptized, to 26 sometime this year, testing a theory. My theory was that I should be able to live how I wanted, and still be a Christian as long nobody but me gets hurt. I've seen time and again how this can't ever be if I do what <em>I</em> want, versus what God says.</p>
<p>Sure it's not fun sometimes, but ultimately it's better. We can never guarantee that our actions, or lack thereof won't hurt anyone else. You watching of porn will have an effect on your relationships (or lead to a direct lack thereof) in life. Your decisions about fun may harm others in unexpected ways. Go out, get drunk, pulled over, lose your license (third time after all). Now you can't get that delivery job you need to help pay for your daughter's registration fee. So she starts hooking. Wait, no, let's go with something more <q>acceptable</q>: she starts stripping. Nah. She gets depressed because she doesn't know what to do and starts using drugs. No wait! She falls in with the wrong crowd and starts <strong>selling</strong> drugs. But gets caught and loses what little financial aid she has, now guaranteeing... well I don't know what. She still has a choice. A choice she hopefully won't think will only hurt her once she makes it.<br />
BUT I RAMBLE.</p>
<p>This brings me back to Psalm 118:18. God will beat you down like a redheaded stepchild to make, nay <em>encourage</em> you, to avoid those ill-fated choices.<br />
You won't understand at the time but those constant car problems, that car repossession because you chose to pay your daughter's college bill instead of make the monthly payment, the loss of technician job which was exposing you to all that porn; these are things which happen because you've put yourself under God's will. You have told Him, I believe in you, protect me. And when you do something you shouldn't have, make that bad choice, or seemingly good choice which will end up hurting you He has to <q>correct for errors</q>.</p>
<p>Don't take my word for it though. Look back on your life now and see if you can't make out the connection, that barely visible line through the seemingly unconnected events which took place. It doesn't have to be bad things either. I just chose to use those as examples because they're the ones people complain about the most (or at least I do :-)). So when the LORD is chastening, don't worry, iz bcuz HE LUBS U. It's been about 9 months bye the way. I guess I should say this one was for all the struggling Christians in the house (pretty much all of us right? eh? ehhhh?) kthxbai.</p>
<h3 id="comments">Comments</h3>
<h4 id="submitted-by-anne27-not-verified-on-mon-12-07-2009-13-42">Submitted by anne27 (not verified) on Mon, 12/07/2009 - 13:42.</h4>
<blockquote>
<p>Its funny how we always remember God when we feel disappointed with our life, or when we need his help most. I first decided to read the bible after a strong breakdown because i broke up with my boyfriend. I didn't succeed to finish it then, it was very difficult for me to focus then, so i gave up reading it. My second attempt to read it was better, because i looked for an <a rel="external" target="_blank" href="http://www.ucg.org/bible/online-bible-study">online bible study</a>, which made it sound understandable. Anyway, i am proud i finished it in few months, and i wouldn't mind to do it again.</p>
</blockquote>
<h4 id="submitted-by-medea-not-verified-on-mon-06-29-2009-10-39">Submitted by medea (not verified) on Mon, 06/29/2009 - 10:39.</h4>
<blockquote>
<p>What is forgiveness? Forgiveness cannot be understood without understanding the nature of sin and it's effects. St. Matthew (22: 37-40) records the words of Jesus: "You shall love the Lord your God with all your heart, and with all your soul, and with all your mind. This is the great and first commandment. And a second is like it, You shall love your neighbor as yourself. On these two commandments depend all the law and the prophets." Sin is a breaking of God's Laws to love Him and to love our neighbor, despite and in the face of His infinite Love for us.</p></p>
</blockquote>
<h4 id="submitted-by-mike-on-mon-04-06-2009-09-49">Submitted by Mike on Mon, 04/06/2009 - 09:49.</h4>
<blockquote><p>Great post mate, a real encouragement and I respect your public confession about this stuff.</p>
<p>My pro tips for reading the Bible:<br />
- Study with others in a group if you can, preferably a bunch of people you like and respect. It's good to bounce this stuff off each other if you can.</p>
<p>- If you don't have people you can do the above with there are a few places on the net you can do something similar. I'm happy for us to do something like this if you like. We could study the same book and talk about it every few days.</p>
<p>- Use commentaries. There's loads free on the net, check out <a rel="external" target="_blank" href="http://www.studylight.org/com/" title="http://www.studylight.org/com/">http://www.studylight.org/com/</a> for some good resources of free ones. Currently I use Matthew Henry's Concise Commentary, Barnes' Notes on the New Testament and Adam Clarke Commentary. They are like having a Bible study with a wise dude there.</p>
<p>- Get a really good paraphrase. Check out The Message, I find it fairly lifechangingly easy to read and to apply to your life.</p>
<p>Hope some of this is somewhat useful!<br />
Peace!</p></blockquote>
A short primer on writing KDE portfiles for macports2009-03-26T21:19:00-05:002009-03-26T21:19:00-05:00
Unknown
https://orville.thebennettproject.com/articles/short-primer-writing-kde-portfiles-for-macports/<p>Howdy do all you out there in interland. This one is mostly for A. L. to get her to stop pouting.
Today, boys and girls, I'll be speaking about <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.macports.org/">macports</a>. Macports is a ports-like package management <q>thing</q> for OS X. For all my arch linux peeps, it's like the AUR for PKGBUILDs, but you need privileges to check in. It's both easy to use and easy to break. Er, easy to contribute to I meant. These contributions are known as <q>Portfiles</q>; text files defining various things necessary to compile your software of interest. </p>
<p>It's so easy to use I can show you how to make your own Portfile in five easy steps.</p>
<p>Step 1: Create a Portfile!
This is easier with a template and as it happens I have one lying around. Here, have this and rename it to <code><strong>Portfile</strong></code>.</p>
<pre>
# $Id$
PortSystem 1.0
name
version
categories
maintainers nomaintainer
description
long_description ${description}
platforms darwin
homepage
master_sites
use_bzip2 yes
checksums md5
</pre>
<p>Step 2: Fill in the values!</p>
<pre>
# $Id$
PortSystem 1.0
name <strong>choqok</strong>
version <strong>0.4</strong>
categories <strong>kde kde4</strong>
maintainers nomaintainer
description <strong>A Free/Open Source micro-blogging client for KDE.</strong>
long_description ${description}
platforms darwin
homepage <strong>http://choqok.ospdev.net/</strong>
master_sites <strong>http://mirror.lfeo.org/${name}/${name}/${version}/</strong>
use_bzip2 yes
checksums md5
</pre>
<p>Step 3: Add dependencies and configure arguments!</p>
<pre>
# $Id$
PortSystem 1.0
name choqok
version 0.4
categories kde kde4
maintainers nomaintainer
description A Free/Open Source micro-blogging client for KDE.
long_description ${description}
platforms darwin
homepage http://choqok.ospdev.net/
master_sites http://mirror.lfeo.org/${name}/${name}/${version}/
use_bzip2 yes
checksums md5
<strong>configure.args-append ../${distname}</strong>
</pre>We didn't have any dependencies for choqok, or did we?
<p>Step 4: Add the magic!</p>
<pre>
# $Id$
PortSystem 1.0
<strong>PortGroup kde4 1.0</strong>
name choqok
version 0.4
revision 0
categories kde kde4
maintainers nomaintainer
description A Free/Open Source micro-blogging client for KDE.
long_description ${description}
platforms darwin
homepage http://choqok.ospdev.net/
master_sites http://mirror.lfeo.org/${name}/${name}/${version}/
use_bzip2 yes
checksums md5
configure.args-append ../${distname}
</pre>
<p>Step 5: Add the checksums!</p>
<pre>
# $Id$
PortSystem 1.0
PortGroup kde4 1.0
name choqok
version 0.4
revision 0
categories kde kde4
maintainers nomaintainer
description A Free/Open Source micro-blogging client for KDE.
long_description ${description}
platforms darwin
homepage http://choqok.ospdev.net/
master_sites http://mirror.lfeo.org/${name}/${name}/${version}/
use_bzip2 yes
<strong>checksums md5 d460f54b7bbaa47e3a669b72e1a2a760 \
sha1 b1c61ae23dd911620b0357df47275e96e5d61e54 \
rmd160 7e7940ff161488a497f9c54aa73e91b0c2096f72</strong>
configure.args-append ../${distname}
</pre>
<p>Too fast for you? No worries! We can go over it again.
To get the md5 sum you can download the tarball and use an md5 utility like <code>md5</code> or <code>md5sum</code>. You can also run <code>sudo port -d configure</code> in the directory containing your Portfile. This assumes you have macports installed already. This will tell you that you have a checksum missing and conveniently spit out a variety of them for you: sha1, rmd160 and md5.</p>
<p>The magical <code>PortGroup kde4 1.0</code> line does a variety of things for us. All of which can be seen in the <a rel="noopener nofollow noreferrer" target="_blank" href="https://trac.macports.org/browser/trunk/dports/_resources/port1.0/group/kde4-1.0.tcl">kde4-1.0.tcl</a> file. It sets up values common to most, if not all, KDE4 software. Without it a koffice2 portfile would go from looking like <a rel="noopener nofollow noreferrer" target="_blank" href="https://trac.macports.org/browser/trunk/dports/kde/koffice2-devel/Portfile?rev=47839#L2">this</a> to something like <a rel="noopener nofollow noreferrer" target="_blank" href="https://trac.macports.org/browser/trunk/dports/kde/koffice2-devel/Portfile?rev=46400#L2">this</a>. Even worse, individual portfile authors would need to change multiple portfiles each time some common option needed to be added or changed. The portgroups are a life <em><strong>and</strong></em> time saver. My gift to you, since the kde portfiles we have now are the only ones I'm concerned with. (hint, hint people who keep on asking for digikam) :-)</p>
<p>For something with dependencies here's an example from ktorrent:</p>
<pre>
# $Id$
PortSystem 1.0
PortGroup kde4 1.0
name ktorrent
version 3.2
categories kde kde4
maintainers nomaintainer
description KDE4 bittorrent client.
long_description Bittorrent client for KDE4 supporting a variety of \
features such as uPNP.
platforms darwin
homepage http://www.kde.org
master_sites http://ktorrent.org/downloads/${version}/
use_bzip2 yes
checksums md5 e215de7a711b3f9c33044bf97a6d8bfb \
sha1 7cc7c50f8860ef31aca3c93f65eee131cc84c968 \
rmd160 e04cf261b22f191f6bda4bccb8b56fdcd734b944
depends_lib-append port:kdebase4-runtime \
port:qca port:gmp
configure.args-append ../${distname} \
-DQCA2_LIBRARIES=${prefix}/lib/libqca.2.dylib \
-DQCA2_INCLUDE_DIR=${prefix}/include/QtCrypto
</pre>
<p>Independent kde apps only need to depend on kdebase4-runtime. That pulls in kdelibs which pull in qt4 and blah, blah, blah. Having said that, choqok should definitely depend on kdebase4-runtime too. Lookit that! iBlogged a bugfix.
<em>ahem</em></p>
<p>So there it is: Creating a Portfile in 20 easy steps.</p>
<p>Caveats: This won't work on OS X.4 because Apple hasn't release their version of gcc-4.2 isn't on Tiger, and no one except me has gotten it to work via manual installation.
The solution: <a rel="noopener nofollow noreferrer" target="_blank" href="http://pdb.finkproject.org/pdb/browse.php?summary=kde4">Fink</a> (RangerRick to the rescue!)</p>
Dear HR2009-03-07T14:48:00-05:002009-03-07T14:48:00-05:00
Unknown
https://orville.thebennettproject.com/articles/dear-hr/<p>I was going through stuff on my old macbook pro drive and I found this cover letter I wrote some time last year (possibly this time last year). I believe I sent it out in a form very similar, if not identical to what you'll see below. I don't remember why, but I was quite serious and if I'm not mistaken, someone from Cornell did call me for a phone interview. Just goes to show boys and girls, honesty ain't gonna kill yah (then again, no guarantees that it wont ...).</p>
<p>If my memory serves me well, the phone interview seemed promising but they were unable to fly me out to NY, (and I was unable to pay for it) so that was the end of that. Or it could have been another position in NY entirely that I'm recalling. Ah well, good (unemployed) times, good times.</p>
<p>The cover letter is reproduced, for your viewing pleasure, in it's entirety below. </p>
<blockquote>
<p>Dear HR Department,<br />
My name is Orville Bennett and this is my awesome cover letter for the RESEARCH TECHNICIAN II position. This is where, through the very scientific process of reading, you will be able to unerringly determine whether I am a proper candidate for employment at your auspicious institution. Permit me this little indulgence and allow me to begin, personal introduction notwithstanding, by making something explicit. I am seeking employment at a respectable institution and I happen to believe that yours fits the bill. If perchance I am mistaken, if research at Cornell in general, or the lab I am to join in particular is not exactly on the "up and up" do not hire me. I will keep you honest, and I will make you regret it.</p>
<p>An odd beginning perhaps to a letter written with the intent of convincing someone to employ me. I'm not just looking for employment however, the atmosphere, the values, the intent of those I'll work with is important to me as well. It behooves me to make this clear then otherwise I'll be looking for another employer in short order. One could best describe my interests in science as purely academic. I enjoy learning how things work, but most of all I love being in a laboratory setting, using experiments to probe "how things work". I'm also absolutely amazing in the laboratory.</p>
<p>When it comes to doing experiments I'm efficient, careful, diligent (sometimes more than necessary), and an absolute marvel at troubleshoooting experiments. As stated in the resume I'm familiar with a host of molecular biology techniques and am computer savvy to boot. I also pick up new techniques rather quickly thanks to the multitude of free papers available at Pubmed. It is no coincidence that a fair smattering of the buzzwords you'd want present when looking for that excellent research technician can be found here. As inferred earlier however, I am prone to bouts of brutal honesty, even at the most inoppurtune times; like when writing a cover letter for a potential employer, or speaking to a supervisor about the progress of a project.</p>
<p>This is because it is not my intent to manipulate anyone into believing I vaguely approach the mythical perfection employers look for. Nor is it my intent to sugarcoat any character flaws which I have at the prospect of employment. It is my belief that this sets up unreasonable expectations on one part of the employer-employee relationship which will only lead to problems in the future.<br />
What I am attempting is to give an accurate portrayal of myself so that you, the employer, will have a easier time deciding whether I'm the type of person you would want in your employ. The résume lists my qualifications, the references will attest to how well I do my job, so the cover letter should serve the purpose of helping you get to know me. Hopefully it answers the question "Am I the type of person you're looking for?" If not, then at the very least it will have given you a refreshing departure from the typical milieu these letters tend to engender. And if you're wondering if I really am as smart as my writing makes me seem, I'm not. I'm even smarter.</p>
<p>I'll close by asserting that I look forward to working with you, but whether I do or not, best of luck in your research endeavours.</p>
</blockquote>
<p>I can just hear the discussion after hitting this one on the inbox.<br />
<q>Hey! Come check this out.</q> <br />
<q>Are you <em>serious</em>, someone actually sent this.</q> <br />
<q>Yip, that one's bat s**t crazy I tell you.</q> <br />
<q>Yeaaah. Let me see the number on there; think we'll do a callback.</q></p>
<p>p.s. Notice how I slipped smart ass in there? Yeah. I crazy.</p>
I'm a bundling fool too2008-11-22T05:31:00-05:002008-11-22T05:31:00-05:00
Unknown
https://orville.thebennettproject.com/articles/bundling-fool-too/<p>To bundle or not to bundle. My everlovin' question.
Amarok 2 RC1 will be released soon and we here on the mac team have been working at near <em>break neck</em> speed to bring our users the best possible all around experience. This starts from the moment the installer is downloaded, to the second the play button is press, to the instant the menus are navigated. We tried to get a lot of things right. We've largely failed, but as I've said before that's KDE's fault :-) There's a lot to be said that this works at all however, so kudos to all involved. </p>
<p>While KDE entered <q>hard</q> freeze on Monday; no doubt in mental preparation for the drudgery of bug fixing to come, Amarok's mac team instead kicked it into high gear. As noted previously a number of long standing, major bugs have been taken care of. That gave me the motivation to finish something I'd been dragging out for a while: post-beta packages with a working collection. The aforementioned mac-team (I find this to be an absolutely hilarious in-joke btw) helped me to figure out what the problem was and so I went to work. And while I was at work, I went to packaging. It's not like the bacteria were going anywhere...</p>
<p>When last we spoke I started out with an <em>almost</em> usable bundle at 217 MB. Currently I have a package that installs 230 MB of software (debugging turned off everywhere_, except for Amarok). It would seem that this is a losing battle, and it is, but then: serendipity! (No, not serenity. Yes, I miss it too.)</p>
<p>As the screenshots above show, the size of the packages, despite bundling Qt + kdelibs + kdebase, is surprisingly small. This happens for two reasons. First, PackageMaker.app compresses stuff. It compresses it but good. Second, I cheated. I went in and hacked out everything in Qt, kdelibs and kdebase-runtime that seemed unnecessary for Amarok. I also saved a little more space when I threw the whole thing into a disk image. In a slightly related note: to the person who decided it would be a good idea to split up kdebase into bitesized, logical little morsels: THANK YOU. I owe you something. Make it reasonable and it might actually show up at your door. </p>
<p>All this got me well within my <q>dream weight</q> of 99.9 MB. I actually broke the 90 MB barrier (300 MB uncompressed) on Thursday and whittled it down, ever so slightly to 68 MB. Amarok wasn't compiled with debugging enabled though :-). So 71 MB. Not bad, not bad at all. iTunes is 57.8 MB though. What if I hadn't bundled Qt? Which brings us back to our initial question; To bundle or not to bundle. </p>
<p>As you've guessed, I chose to bundle. While ditching Qt and telling people to get it from <a rel="noopener nofollow noreferrer" target="_blank" href="http://mac.kde.org/?id=download">another source</a> would have resulted in a smaller footprint for the Amarok installer, it would also have made it harder to get to. Ultimately being able to say <q>Smaller than iTunes and yet more featureful</q> loses out to ease of use for the target audience. Us mac users are a spoilt bunch and the barrier to entry needs to be pretty low if anyone's to care about you. Click, click, password, enter, enter. So that's what we did. Just hope they work. It's not like I tested them or anything; that's for wusses. ;-)</p>
<p>If there's anything you, the aspiring cross-platform-developer-targeting-the-macintosh-platform-using-the-KDE-framework should take home from this, it's this: don't be afraid to (ab)use the system. Use <a rel="noopener nofollow noreferrer" target="_blank" href="http://developer.apple.com/macosx/launchd.html">the tools</a> that have been <a rel="noopener nofollow noreferrer" target="_blank" href="http://developer.apple.com/technotes/tn2004/tn2123.html">given to you</a> to <a rel="noopener nofollow noreferrer" target="_blank" href="http://lists.apple.com/archives/installer-dev/2008/Feb/msg00046.html">make life easier</a> for your users.</p>
<p>Oh, still looking for someone to tell me how to start nepomuk manually. That <code>.desktop</code> autostart file reeks of utter FAIL over here.</p>
For Kieran: The Home Made Pan Cakes recipe2008-11-15T12:13:00-05:002008-11-15T12:13:00-05:00
Unknown
https://orville.thebennettproject.com/articles/for-kieran-home-made-pan-cakes-recipe/<p>Are you locked out of your home waiting for help to arrive?<br />
Are you drunk and need that little pick-me-up to keep you going lucidly through the night?<br />
Have you guessed the answer to a question involving UTC time?<br />
Well have we got something for <strong>you</strong>!</p>
<h3 id="ingredients">Ingredients:</h3>
<ul>
<li>Organic <strong title="if you bastardize my pancakes with anything less than whole milk, i'll kill you">WHOLE</strong> Milk (Premium Selection)</li>
<li>3 eggs (Cage free fowl only folks)</li>
<li>I can't believe it's not butter spray (original)</li>
<li>Flavoring of choice (i prefer Coconut but Orange/Lime is good too)</li>
<li>Organic Cane sugar (Florida crystals)</li>
<li>Unbleached Bread Flour (King Arthur Flour)</li>
<li>Salt (Morton iodized)</li>
<li>Ladel a.k.a Soup spoon or Deep Spoon)</li>
</ul>
<h3 id="method">METHOD</h3>
<ol>
<li>
<p>Pour "a good amount" of milk into a "decent sized" bowl.</p>
</li>
<li>
<p>Add sugar to taste (i.e. when it's sweet enough for you).</p>
</li>
<li>
<p>Add "around a tablespoon of" salt.</p>
</li>
<li>
<p>Add flavoring and mix well. <span style="font-size:x-small">Bonus points for adding real lemon/orange juice or coconut water if you have it available.</span> <span style="font-size:xx-small">Knowing a thing or two about coconuts though, you'll probably have to boil it off to get it concentrated enough.</span></p>
</li>
<li>
<p>Whisk the three eggs vigorously (using a fork in a deep bowl works well).</p>
</li>
<li>
<p>Add flour to the milk (forgot that didn't you?) until it is of "the right consistency".</p>
</li>
<li>
<p>Add the eggs and then mix in one direction until the whole thing is consistent.</p>
</li>
<li>
<p>Pour in some "I can't believe it's not butter spray", and mix again.</p>
</li>
<li>
<p>Place two non-stick frying pans on the fire at "a decent temperature" (for faster cooking, and the ultimate "I'm teh awesome chef experience").</p>
</li>
<li>
<p>Using your ladel, pour the mix into the frying pan and then, in a gentle circular motion, swirl the mix slowly around, thinning it out.</p>
</li>
<li>
<p>Once the tips of the pan cakes have browned, flip over and wait for the other side. If after the first pancake you find that it's too sweet/not sweet enough, too thick/not thick enough, adjust, mix and pour again. </p>
</li>
</ol>
<p>You'll notice you don't have the exact instructions. Half the fun is filling in the blanks.</p>
<h2 id="submitted-by-exocet-on-mon-11-17-2008-01-59">Submitted by Exocet on Mon, 11/17/2008 - 01:59.</h2>
<h3 id="puffed-chocolate-omelette">Puffed Chocolate Omelette</h3>
<h4 id="ingredients-1">INGREDIENTS</h4>
<ul>
<li>6 eggs, separated</li>
<li>¼ cup (55g) caster sugar</li>
<li>2 tablespoons cream</li>
<li>1 tablespoon plain flour</li>
<li>120g dark chocolate, melted</li>
<li>20g unsalted butter</li>
<li>120g raspberries</li>
<li>sifted icing sugar, to dust</li>
<li>ice-cream, to serve (optional)</li>
</ul>
<h4 id="method-1">METHOD</h4>
<ol>
<li>
<p>Preheat oven to 190C or 170C fan. In a large bowl, whisk together egg yolks, sugar, cream, flour and melted chocolate.</p>
</li>
<li>
<p>Using an electric mixer, beat eggwhites until soft peaks form. Gently fold eggwhites into chocolate mixture with a spatula.</p>
</li>
<li>
<p>Melt half of butter in a large ovenproof frying pan on low heat. Pour in half of egg mixture and allow to fry for a short period. Then bake omelette in-pan for 3-6 minutes, until puffed and set. </p>
</li>
<li>
<p>Slide omelette onto a warm serving plate and top with half of raspberries. Fold omelette in half and dust with icing sugar. Repeat with remaining ingredients, except ice-cream, to make another omelette.</p>
</li>
<li>
<p>Cut omelettes into thick slices and serve immediately with vanilla ice-cream, if you like.</p>
</li>
</ol>
Oh Snap!2008-11-11T12:35:00-05:002008-11-11T12:35:00-05:00
Unknown
https://orville.thebennettproject.com/articles/oh-snap/<p>Just realized that I can go directly to a folder in the Finder by typing <code>[Command]+[Shift]+G</code>. This makes my file browsing experience complete. Now I can open hidden folders without needing to use <code>open /path/to/hidden/.directory</code> in Terminal.app.<br />
Thanks to the <a rel="noopener nofollow noreferrer" target="_blank" href="http://daringfireball.net/linked/2008/11/10/finder-tab-completion">Daring Fireball</a> feed which took me to <a rel="noopener nofollow noreferrer" target="_blank" href="http://inessential.com/?comments=1&postid=3560">this little gem</a>.</p>
<p>It also points out the shortcuts you can use in the <strong>Open...</strong> dialogs to get the <strong>Go To Folder...</strong> sheet there as well. Nifteh! What's not nifty is me being at work today. 'Cause it's a holiday! Still, I'm staying and finishing out the day. I'm already here and no one else being here doesn't slow down my plans too much.</p>
<p>Would've been a nice day to finish up working on the macports stuff though.</p>
Anatomy of a standalone KDE Mac package2008-09-11T20:18:00-05:002008-09-11T20:18:00-05:00
Unknown
https://orville.thebennettproject.com/articles/anatomy-of-a-standalone-kde-mac-package/<p>Allow me to start off by stating that there is no such thing. The standalone package is a myth which we (or at least I) aspire to here in KDE/Mac land. Installation of KDE software is wholly geared towards non-proprietary *nix platforms. Whilst the <q>I'm a PC</q> crowd might be willing to overlook the inconvenience of installing 1 GB of tangentially related packages to get that one program they desire, members of the Cult-of-Mac are far less forgiving. This leaves us, i.e. me, in the unenviable position of trying to tease out what is necessary for an app, from what is not, and trying to package it all together. Most of the time this results in less than stellar, um, <a rel="noopener nofollow noreferrer" target="_blank" href="http://amarok.kde.org/blog/archives/790-The-300-lb-gorilla-in-the-room-Amarok-2-installer-for-OS-X.html">results</a>. Let's discuss why this is, for the time being, necessarily so.</p>
<p>A KDE application requires kdelibs, in itself a misnomer as it does not only contain libraries. One need look no further than kdelibs' bin directory to see how true this is.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>orville@cubic:local$ l ~/Desktop/packages/kdelibs4/opt/local/bin/
</span><span>checkXML* kdeinit4_shutdown* kwrapper4*
</span><span>kbuildsycoca4* kdeinit4_wrapper* makekdewidgets*
</span><span>kconfig_compiler* kjs* meinproc4*
</span><span>kcookiejar4* kjscmd.app/ nepomuk-rcgen.app/
</span><span>kde4-config* kross.app/ preparetips*
</span><span>kded4.app/ kshell4* start-session-bus.sh*
</span><span>kdeinit4.app/ kunittestmodrunner*
</span><span>orville@cubic:local$
</span></code></pre>
<p>And therein lies our, or rather, <strong>my</strong> problem. It becomes immediately apparent that to install any KDE program, one needs to provide, not just dynamic libraries but other binaries as well. Why is this a problem, you ask? <em>sigh</em>
Where do I begin?</p>
<p>OS X has, what might appear to some, a curious method of installing applications. A user drags a specially named directory (known as a bundle) to anywhere they please on their filesystem. The app is now installed and registered with the system. This means that in an ideal world, a bundle for a KDE application, like say - oh I don't know - Amarok, would look something like this:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Amarok.app/
</span><span>-- Contents/
</span><span>----- Info.plist
</span><span>
</span><span>----- Frameworks/
</span><span>-------- Kdecore.framework/
</span><span>-------- Kdeui.framework/
</span><span>-------- Kio.framework
</span><span>-------- Nepomuk.framework/
</span><span>-------- Threadweaver.framework/
</span><span>-------- etc.framework/
</span><span>
</span><span>----- Resources/
</span><span>-------- amarok.icns
</span><span>-------- apps/
</span><span>-------- config/
</span><span>-------- dbus-1/
</span><span>-------- mime/
</span><span>-------- etc/
</span><span>
</span><span>---- MacOS/
</span><span>------- Amarok
</span><span>------- amarokcollectionscanner
</span><span>------- amarok_afttagger
</span></code></pre>
<p>Aaaaaaaand we'd be done. Life is always looking to throw us curveballs though isn't it? As stated earlier, kdelibs isn't just a set of libraries which all KDE programs depend upon, it's also a set of binaries which all KDE programs depend upon. Those binaries depend on dynamic libraries. Those dynamic libraries depend on .so files (wth are those anyway?). The result of splitting all this functionality across so many files is a wonderful little scavenger hunt whenever we need to package things up for OS X. </p>
<p>We can throw virtually everything into a bundle we need and it'll almost work; except for those enigmatic .so's. The ones we need the most, like kio_file (and kio anything else) never get found. This isn't so bad after all though. Things like dbus prevent us from providing everything we need in the bundle anyway. kdelibs also depends on other libraries which aren't provided by default on OS X. That means our <a rel="noopener nofollow noreferrer" target="_blank" href="http://support.apple.com/kb/TA25631?viewlocale=en_US">frameworks</a> (were they present) would have to link to them statically. Otherwsie we'd have to install these libraries when we install our <a rel="noopener nofollow noreferrer" target="_blank" href="http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkBinding.html">frameworks</a>. Instead of the preferable, ubiquitous bundle, another solution presents itself.</p>
<p>Enter the package, hereinafter referred to by its extension, pkg. Apple software engineers anticipated the possibility that sometimes we wouldn't be able to provide everything we need in a bundle. This is especially true of programs not designed for OS X like KDE's. Apple provides an installer pkg for those special occasions. It also provides the preternaturally designed PackageMaker with which to create them (Interpret that however you desire, as many times as you desire. You'll still be right.)</p>
<p>The pkg allows us to grab all the files we need and place them where necessary. But kdelibs, as previously stated, is not just a bunch of libraries. It is so much more. That so much more isn't necessary for all programs though. Amarok has no need of libkde3support or libkhtml; even more so the emoticonstheme .so files. It needs even less of kdebase. Verily, it requires none of kdepimlibs. So the scavenger hunt begins, culling until you can cull no more. Eventually you're left with a pkg weighing in at a respectable 130 MB. Certainly better than the 300 MB you'd have if you'd left in all of Qt, kdelibs and kdebase. Infinitely better than the 1.4 GB you'd have if you just provided all of the dependencies for kdebase and then just added MySql and Amarok.</p>
<p>Unfortunately when you install and run it you realize that Amarok's QtScript bindings won't load. Three days and a full installation of kdelibs, Qt and kdebase later it still doesn't work. Perhaps you forgot a symbolic link for one of the libraries. Perhaps. You'll never find out though because the weekend is over and it's time to go to work again. Then you think to yourself, if only those nice boys and girls in KDE-land had a <a rel="noopener nofollow noreferrer" target="_blank" href="http://www.cmake.org/Wiki/CMake:CPackPackageGenerators#PackageMaker_.28OSX_only.29">native solution</a> for installing their software, perhaps you wouldn't have to do this and could spend time attempting to figure out <a rel="noopener nofollow noreferrer" target="_blank" href="https://bugs.kde.org/show_bug.cgi?id=171972">other</a> <a rel="noopener nofollow noreferrer" target="_blank" href="https://bugs.kde.org/show_bug.cgi?id=170199">things</a>. Oh well. Here's to hoping next week's scavenger fares better.</p>
<p>If we're lucky the resultant post will be infinitely more readable. As with the appearance of a standalone KDE Mac package however, I wouldn't hold my breath. Hmm, I wonder if now's a bad time to say <a rel="noopener nofollow noreferrer" target="_blank" href="http://techbase.kde.org/Projects/KDE_on_Mac_OS_X/Macbook_Manifesto#Install_the_software">help wanted</a>.</p>
Might I have a quick look2008-08-24T03:34:00-05:002008-08-24T03:34:00-05:00
Unknown
https://orville.thebennettproject.com/articles/might-i-have-a-quick-look/<p>This is a story all about how my life <em>didn't</em> get twist-turned upside down. And I'd like to take some minutes to sit right here, tell you how I became the king of this Apple macbook air.</p>
<p>Kidding! I just didn't want to use "here" to rhyme with "here". That's so unoriginal (if technically correct). So what am I ranting about today while eating my <a rel="noopener nofollow noreferrer" target="_blank" href="http://en.wikipedia.org/wiki/Sapporo_Ichiban">Ichiban</a>? Read on. </p>
<p>While preparing my noodles just now (apparently the "Number one" noodles from the maker ;-) ) I remembered that on my macbook pro, courtesy of some mac rss feed, I'd discovered a zip quicklook plugin. I wanted it back. One google search later and I was rewarded with this gem: <a rel="noopener nofollow noreferrer" target="_blank" title="http://www.tuaw.com/2007/11/27/quick-look-folder-and-zip-plugins/" href="http://www.tuaw.com/2007/11/27/quick-look-folder-and-zip-plugins/">http://www.tuaw.com/2007/11/27/quick-look-folder-and-zip-plugins/</a></p>
<p>A <em>folder</em> quicklook plugin? For Realz? This was already paying off! That zip plugin was not the one I had remembered however so I kept on trucking. And behold: <a rel="noopener nofollow noreferrer" target="_blank" title="http://macitbetter.com/BetterZip-Quick-Look-Generator" href="http://macitbetter.com/BetterZip-Quick-Look-Generator">http://macitbetter.com/BetterZip-Quick-Look-Generator</a>.</p>
<p>P.S. The other potential title for this entry was "Can I have a quick look (up your panties!)" I fully blame One Piece's Singing Skeleton <a rel="noopener nofollow noreferrer" target="_blank" title="http://en.wikipedia.org/wiki/Brook_(One_Piece)" href="http://en.wikipedia.org/wiki/Brook_(One_Piece)">Brook</a> for that.</p>
<p>Kthanxbye!</p>
Psalms 372008-08-10T02:44:00-05:002008-08-10T02:44:00-05:00
Unknown
https://orville.thebennettproject.com/articles/psalms-37/<p>NetBible version</p>
<p>1 Fret not yourself because of evildoers, neither be you envious against the workers of iniquity.</p>
<p>2 For they shall soon be cut down like the grass, and wither as the green herb.</p>
<p>3 Trust in the LORD, and do good; so shall you dwell in the land, and truly you shall be fed.</p>
<p>4 Delight yourself also in the LORD: and he shall give you the desires of your heart.</p>
<p>5 Commit your way to the LORD; trust also in him; and he shall bring it to pass.</p>
<p>6 And he shall bring forth your righteousness as the light, and your judgment as the noonday.</p>
<p>7 Rest in the LORD, and wait patiently for him: <em>fret not yourself because of him who prospers in his way, <strong>because of the man who brings wicked devices to pass</strong></em>.</p>
<p>8 Cease from anger, and forsake wrath: fret not yourself in any wise to do evil.</p>
<p>9 For evildoers shall be cut off: but those that wait on the LORD, they shall inherit the earth.</p>
<p>10 For yet a little while, and the wicked shall not be: yes, you shall diligently consider his place, and it shall not be.</p>
<p>11 But the meek shall inherit the earth; and shall delight themselves in the abundance of peace.</p>
<p>12 The wicked plots against the just, and gnashes on him with his teeth.</p>
<p>13 The LORD shall laugh at him: for he sees that his day is coming.</p>
<p>14 The wicked have drawn out the sword, and have bent their bow, to cast down the poor and needy, and to slay such as be of upright conversation.</p>
<p>15 Their sword shall enter into their own heart, and their bows shall be broken.</p>
<p>16 A little that a righteous man has is better than the riches of many wicked.</p>
<p>17 For the arms of the wicked shall be broken: but the LORD upholds the righteous.</p>
<p>18 The LORD knows the days of the upright: and their inheritance shall be for ever.</p>
<p>19 They shall not be ashamed in the evil time: and in the days of famine they shall be satisfied.</p>
<p>20 But the wicked shall perish, and the enemies of the LORD shall be as the fat of lambs: they shall consume; into smoke shall they consume away.</p>
<p>21 The wicked borrows, and pays not again: but the righteous shows mercy, and gives.</p>
<p>22 For such as be blessed of him shall inherit the earth; and they that be cursed of him shall be cut off.</p>
<p>23 The steps of a good man are ordered by the LORD: and he delights in his way.</p>
<p>24 Though he fall, he shall not be utterly cast down: for the LORD upholds him with his hand.</p>
<p>25 I have been young, and now am old; yet have I not seen the righteous forsaken, nor his seed begging bread.</p>
<p>26 He is ever merciful, and lends; and his seed is blessed.</p>
<p>27 Depart from evil, and do good; and dwell for ever more.</p>
<p>28 For the LORD loves judgment, and forsakes not his saints; they are preserved for ever: but the seed of the wicked shall be cut off.</p>
<p>29 The righteous shall inherit the land, and dwell therein for ever.</p>
<p>30 The mouth of the righteous speaks wisdom, and his tongue talks of judgment.</p>
<p>31 The law of his God is in his heart; none of his steps shall slide.</p>
<p>32 The wicked watches the righteous, and seeks to slay him.</p>
<p>33 The LORD will not leave him in his hand, nor condemn him when he is judged.</p>
<p>34 Wait on the LORD, and keep his way, and he shall exalt you to inherit the land: when the wicked are cut off, you shall see it.</p>
<p>35 I have seen the wicked in great power, and spreading himself like a green bay tree.</p>
<p>36 Yet he passed away, and, see, he was not: yes, I sought him, but he could not be found.</p>
<p>37 Mark the perfect man, and behold the upright: for the end of that man is peace.</p>
<p>38 But the transgressors shall be destroyed together: the end of the wicked shall be cut off.</p>
<p>39 But the salvation of the righteous is of the LORD: he is their strength in the time of trouble.</p>
<p>40 And the LORD shall help them, and deliver them: he shall deliver them from the wicked, and save them, because they trust in him.</p>
The Mask2008-07-22T05:09:00-05:002008-07-22T05:09:00-05:00
Unknown
https://orville.thebennettproject.com/articles/the-mask/<p>I remember when I was in college, around either amaroK 1.2 or 1.3 release time, when I first found out about (and was invited to) the amarok dev channel. I don't remember exactlty why, but muesli let me in on the secret. Maybe it was because I was helping out with the docs, or maybe he just wanted to talk about music without the constant distraction of user questions interrupting us :-) Ah yes, good times back then. He turned me on to the awesomeness of Daft Punk and Ol' Dirty Bastard's "Baby I Got Your Money" if I recall correctly. The latter by way of his Last.fm (then audioscrobbler.com) personal radio stream.</p>
<p>I also recall a conversation w/ someone (eann?) about being a developer a me vehemently avoiding having said title foisted upon me. Amarok 1.3 (think it was 1.3) got released, I quietly retreated back into userland and soon even forgot how to get back to the dev channel; or maybe they used that mindwipe thing from M.I.B. Can never be too sure with these fellows. </p>
<p>Fast forward to a few months ago and eean again chooses to refer to me as a developer and again I run away from the title. Personally I prefer the <q>the mac guy</q> title. Makes it far easier to make the bold (if untrue) claim that I <strong>AM</strong> the Amarok mac team. Hell, <em>I am</em> the Amarok mac team. Ok, not really. But anyways, one of the SOCers (summer of coders) was in the dev channel asking for an IRC mask and I quickly jumped at the chance to get a new one for myself. The old konversation/user/ mask hadn't been valid in a while and likely wouldn't be again ever so I figured an amarok mask was a good substitute. Markey then chimed the that <q>with great masks comes great responsibility</q> or something like that. Immediately I was reminded why I didn't want a "developer" title all those years ago. The responsibility. </p>
<p>While markey was making IMO a quite funny nerd joke (eean thought it was lame, big meany!) the words still rang true. As Eminem says, much truth is said in jest, or something like that. So now I'll have to be a responsible member of the community and avoid some of my more annoying (yet infinitely fun) tendencies. On the plus side all those bans my konversation/user/ mask racked up in <a href="irc://irc.freenode.net">#kde</a> from canllaith aren't valid anymore :-D <em>Sigh</em> Being diplomatic is such a bore. I wonder how Nightrose does it, and does it so well ...</p>
<p>So yeah, now introducing (finally) your Amarok on KDE/Mac dev: illogic-al, aka illogical, aka illogic, aka illogica, aka illogic-a, aka []illogic-al, aka [x]illogic-al, aka orville, also known as ... wait for it...<br />
Me.<br />
Engage at your peril.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
<span style="font-size: 9em;">FEAR ME!</span></p>
<p><em>Ahem</em>. Sorry about that. I get carried away sometimes. Good thing no one actually knows about this site.</p>
Things I learned about Xcode today2008-07-16T03:55:00-05:002008-07-16T03:55:00-05:00
Unknown
https://orville.thebennettproject.com/articles/things-i-learned-about-xcode-today/<p>There are two ways to include files in your project that guarantees compilation. Only one of these ways should be used at a time.</p>
Recipe for World Domination2008-07-14T01:27:00-05:002008-07-14T01:27:00-05:00
Unknown
https://orville.thebennettproject.com/articles/recipe-for-world-domination/<p>After having a talk with aseigo today I have been lulled out of my ill-deserved slumber. So let's try something and see where this goes...</p>
<h2 id="plan">Plan</h2>
<p>Step 1: Collate an actual list of all KDE's dependencies (Techbase).<br />
Step 2: Find out which are actually used for functionality on OS X (libagg, opengl).<br />
Step 3. Remove or otherwise move out of the way X11 includes and libraries.<br />
Step 4: Compile and package software only requirements software provided by the base the operating system. Qt first.<br />
Step 5: Repeat Step 4 for the kdesupport software from a stable snapshot.<br />
Step 6: Compile and package kdelibs and kdepimlibs.<br />
Step 7: Find out what is necessary in kdebase runtime, for software to work properly.<br />
Step 8: Assess the impact of functionality caused by deliberately leaving out some software (nepomuk, kdemultimedia for amarok, opengl support for kdelibs).<br />
Step 9: Create individual .app packages for third party software and a .mpkg to install the dependencies packaged above.<br />
Step 10: Test, then distribute to the world.</p>
<p>Aside: I volunteer for 10.5 univeral packages. 10.4 "box" is at work and the Tiger install CD is all the way in NY (I hope).</p>
<h2 id="coordinate">Coordinate</h2>
<ol>
<li>Mail the kde-mac, kde-core-devel, and also kde-buildsystem MLs to discuss the state of KDE/Mac and the desired "message" to be delivered with the 4.1 release.</li>
<li>Lay the groundwork for 4.2 by discussing the feasibility of making kdelibs into frameworks. Find out about "Solid" plans for OS X. Find out wtf nepomuk doesn't work. Is this just me?</li>
<li>Start looking at qt 4.5 and ask Nokia/Trolltech what their plans are.</li>
<li>Coordinate with the rest of the team on wiki by assigning tasks or letting everyone know what tasks you are working on and how far along they are.</li>
<li>Discuss officially using macports pkgs for 10.5 universal pkgs.
5.5 Discuss how to show 10.4 some love.</li>
<li>Solicit information from app developers about whether they want their apps packaged for OS X and what their expectations are on the platform. Run it and be happy, or as close as they can get to seamless integration? Right now Amarok, Bibletime and KTorrent come to mind.</li>
</ol>
<h2 id="initiate">Initiate</h2>
<p>Start creating individual prerequisite packages now. Try to keep versions as stable as possible (no git for dbus), (no svn for strigi, taglib). Possible exceptions qt-copy, dbus.</p>
<p>Design qt-copy package to directly override/overwrite macports qt-mac package. Collaborate with macports maintainer to have qt-mac +qt-copy port variant which applies kde patches. This allows easy testing of qt and qt-copy </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>sudo port deactivate qt-mac +qt-copy && sudo port activate qt-mac
</span></code></pre>
<p>Also need qt-mac built w/ dbus support.</p>
<p>Try getting dbus to release w/ mac changes integrated so we can have stable version for 4.1.</p>
<h2 id="communicate">Communicate</h2>
<p>Nothing said till 4.1 release? Announce as tech preview in 4.1 release announcement and link to packages? Would need to speak to kde-promo on this one so we don't phail as utterly as with 4.0. Mac geeks will be far less forgiving (albeit far more polite).</p>
<p>Pimp the website moar. Mission Statements. Screenshots. Interviews (not it)? Screencasts (personally I think this' a lame idea). Information accurately stating what KDE/Mac can and can't do. Me n' Yaccin can work on this if he's got time. If not, I'll add it to my suddenly very long TODO. :-)</p>
<p>Have things set up for bugs.kde.org to allow kde-mac packages to be listed.</p>
<h2 id="insanity">Insanity</h2>
<p>Do it all before the end of the week. Volunteers welcome ;-)</p>
Xcode Tips2008-07-13T10:16:00-05:002008-07-13T10:16:00-05:00
Unknown
https://orville.thebennettproject.com/articles/xcode-tips/<p>I like my fonts antialiased, and one thing that has continually bothered me is Xcode's lack of antialiasing in its
code editor. To gain this "feature" I had to go to the Xcode Preferences window, then to the Fonts and Colors section.
Click on the font and either change it to another fixed width font, or increase the size of Monaco to be greater than 10.
For some reason, even if it's set in System Preferences, Monaco at 10 point or lower is not antialiased (except for in
the Terminal, which has its own antialiasing setting).</p>
Think Diff2008-07-13T10:06:00-05:002008-07-13T10:06:00-05:00
Unknown
https://orville.thebennettproject.com/articles/think-diff/<p>Apple has an interesting little utility which they provide with Xcode called FileMerge. I don't actually know if it merges files as the name implies, but I would assume so. I've been using it to see file diffs here on os x. It seems to be a quick and dirty app, but it's easy to use and works well (albeit without the visual pulchritude of your typical os x programs).</p>
<p>So now you might be wondering (or if you're me reading this a few months from now, I might be wondering) why I was using this. Well. Amarok 2 (yes, that again) has recently, due to a number of breakthroughs gained the ability to play audio, and lo, video on os x; as long as the path to the file being played doesn't contain a space. After e-mailing the phonon-backend dudes, i got an informative e-mail from Richard @ Nokia/Trolltech (née Trolltech) informing me that the latest qt snapshot might have a fix for this. Thank you Richard! qt-copy is still @ 4.4.0 though which means those trying the KDE/Mac packages would miss this fix until qt-copy got synched to 4.4.2 (and who knows when that'll happen). Solution: patch! </p>
<p>qt-copy has a directory for patches so I added one after hunting down the code necessary to fix the problem in one of the qt 4.4.2 snapshots. It's the snapshot from 2008-07-08 for those of you wondering. Now KDE/Mac packages should pick up the fix when the patch is applied. Just need to update the A2 on OS X wiki to inform those building from source that they'll need to run apply_patches in src and then we'll be "GOOD 2 GO!" as Elephant Man usually says. </p>
<p>But back to FileMerge; so I used it to compare all the <code>.cpp</code> files in the src/3rdparty/kdebase/runtime/phonon/qt7/ directory of qt-copy and the qt-snapshot. Near the "end of the line" I got a one-liner in quicktimevideoplayer.cpp. Not even a one-liner, a one-worder. While it seemed that this might be the change Rich @ Trolltech was referring to, I was a bit skeptical. I decided to go do the same in phonon for qt's kdelibs dir; looking for more substantial changes. There were a LOT more files there. Owing the that, and the speed of my new macbook (make -j4 is awesomeness people) I decided to just compile the change and test to see if that actually fixed the problem. And lo! It did. </p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Index: src/3rdparty/kdebase/runtime/phonon/qt7/quicktimevideoplayer.cpp
</span><span>===================================================================
</span><span>--- src/3rdparty/kdebase/runtime/phonon/qt7/quicktimevideoplayer.cpp (revision 820342)
</span><span>+++ src/3rdparty/kdebase/runtime/phonon/qt7/quicktimevideoplayer.cpp (working copy)
</span><span>@@ -451,7 +451,7 @@</code>
</span><span><code>
</span><span> void QuickTimeVideoPlayer::openMovieFromUrl()
</span><span> {
</span><span>- QCFString urlString = QCFString(m_mediaSource.url().toString());
</span><span>+ QCFString urlString = QCFString(m_mediaSource.url().toEncoded());
</span><span> CFURLRef url = CFURLCreateWithString(0, urlString, 0);
</span><span> DataReferenceRecord dataRef = {0, 0};
</span><span> QTNewDataReferenceFromCFURL(url, 0, &amp;dataRef.dataRef, &amp;dataRef.dataRefType);
</span></code></pre>
<p>Whodathunk? I'd started looking into fixing this bug right before I wrote the phonon-backend ML and I'm glad they already fixed this. If I had continued I'd still be pouring over the audio* or backend* files trying to figure out where it all went wrong. Maybe even media*. Would've never suspected the quicktimevideo.cpp file though. After all, I was getting the bug for audio too, the problem couldn't be in there ...
<em>sigh</em>
See what (almost) happens when we assume?</p>
<p>I'm pretty happy with that. I'm still "new" to the whole "software design/programming" (as opposed to hacking) thing so I'm relatively confident I wouldn't have found and fixed the bug in a timely manner, if at all. Unless I really tried; which, I rarely do. I know, I suck, but my eyes start glossing over at around hour 3 with nothing still done :-/</p>
And now, for something completely different2008-06-01T23:49:00-05:002008-06-01T23:49:00-05:00
Unknown
https://orville.thebennettproject.com/articles/completely-different/<p>Now <a rel="noopener nofollow noreferrer" target="_blank" href="http://twitter.com/illogical1">twitting</a>. No, I didn't mean <a rel="noopener nofollow noreferrer" target="_blank" href="http://twitter.com/illogical1">tweeting</a>.</p>
Eureka! The computer's got it!2008-05-28T12:22:00-05:002008-05-28T12:22:00-05:00
Unknown
https://orville.thebennettproject.com/articles/eureka-the-computers-got-it/<p>Today after my amarok bundle crashed (yet again), and I got the DrKonqui dialog which began using up 171% of my cpu making my fans go crazy, I remembered something. It was not always so. I remembered that I used to have to wait for the Apple Crash Reporter (ACR) to generate a backtrace (bt) before I could launch Amarok again. The ACR immediately generates a bt when OS X programs crash. This seems to take longer than DrKonqui because, with DrKonqui you could just quit and not generate a bt, which I would frequently do. And while I know it's not the <q>right</q> thing to do generating a bt is extremely annoying when I'm doing something which requires restarting amarok. Like say adding files to the bundle, quitting, then restarting to see that this didn't help at all with my kio problems. I was reminded today that not being allowed to dismiss the crash dialog before it generates its bt is probably a good thing though. I was trying to document how I came up with the following:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Index: ../src/ActionClasses.cpp
</span><span>===================================================================
</span><span>--- ../src/ActionClasses.cpp (revision 813638)
</span><span>+++ ../src/ActionClasses.cpp (working copy)
</span><span>@@ -467,7 +467,7 @@
</span><span> setIcon( KIcon("media-playback-stop-amarok") );
</span><span> setObjectName( "stop" );
</span><span> setGlobalShortcut( KShortcut( Qt::META + Qt::Key_V ) );
</span><span>- setMenu( Amarok::StopMenu::instance() );
</span><span>+ //setMenu( Amarok::StopMenu::instance() );
</span><span> connect( this, SIGNAL( triggered() ), The::engineController(), SLOT( stop() ) );
</span><span> ac-&gt;addAction( "stop", this );
</span><span> setEnabled( false ); // Disable action at startup
</span></code></pre>
<p>See commenting out that setMenu function allows amarok to quit normally, instead of crashing on exit. I seem to remember markey complaining about that once too. Anyway, now I have a piece of code and I can't rightly remember how it got there. I ditched the backtrace that led me here but I decided to see if I couldn't find it again...</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>orville@cube:am_build$ ll ../src/ActionClasses.cpp*
</span><span>-rw-r--r-- 1 orville staff 19359 May 26 21:44 ../src/ActionClasses.cpp
</span><span>-rw-r--r-- 1 orville staff 19364 May 21 11:24 ../src/ActionClasses.cpp~
</span></code></pre>
<p>So I messed w/ that file between May 21st and 26th. The 26th was probably the last time svn up touched the file. The ~ file was created by vim when I messed with it.</p>
<p>But I still need the backtrace right? Yup. Well OS X thankfully takes care of that by saving crash logs in ~/Library/Logs/CrashReporter/. In that directory you can find all the crash logs for that user's programs listed by name, date, pid and more. They never really meant much to me till I happened upon <a rel="noopener nofollow noreferrer" target="_blank" title="http://developer.apple.com/technotes/tn2004/tn2123.html" href="http://developer.apple.com/technotes/tn2004/tn2123.html">http://developer.apple.com/technotes/tn2004/tn2123.html</a>. Yes, I browse the ADC for fun when I'm bored. Go die in a fire. Through the magic of browser tabs that never close and session recovery (TY Firefox 3!) I used the Amarok_2008-03-22-114749_orvilles-macbook-pro-15.crash file (close enough to May 21) to (finally) find what was causing the problem. This is what it told me</p>
<pre><code>
Process: Amarok [76944]
Path: Amarok
Identifier: Amarok
Version: ??? (???)
Code Type: X86 (Native)
Parent Process: launchd [1]
Date/Time: 2008-03-22 11:47:49.708 -0400
OS Version: Mac OS X 10.5.2 (9C31)
Report Version: 6
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000
Crashed Thread: 0
Thread 0 Crashed:
0 QtGui 0x0392dee3 QMenuPrivate::QMacMenuPrivate::~QMacMenuPrivate() + 419
1 QtGui 0x038c2ffd QMenuPrivate::~QMenuPrivate() + 93
2 QtCore 0x00335101 QObject::~QObject() + 1249
3 QtGui 0x03516df0 QWidget::~QWidget() + 464
4 libkdeui.5.dylib 0x01391757 KMenu::~KMenu() + 101 (kmenu.cpp:127)
5 libamaroklib.1.dylib 0x00b86084 Amarok::StopMenu::~StopMenu() + 56 (actionclasses.h:137)
6 libamaroklib.1.dylib 0x00b860b9 Amarok::StopMenu::~StopMenu() + 17 (actionclasses.h:137)
7 libamaroklib.1.dylib 0x00b84135 __tcf_2 + 27 (actionclasses.cpp:499)
8 libSystem.B.dylib 0x9461a53c __cxa_finalize + 241
9 libSystem.B.dylib 0x9461a430 exit + 33
10
0x0000f713 start + 63
</code></pre>
<p>So this is what I did
<code> //setMenu( Amarok::StopMenu::instance() );</code></p>
<p>And lookit that, problem solved. Temporarily. If I had to guess I'd say the dtor is taking a wrong detour somewhere. :-D Anyhoo, save the guy for later. Per'aps dtrace and gdb will help me fix it when I'm not so lazy and actually understand what the code is trying to do. Or maybe I'll just passively inform markey that maybe I've stumbled onto to source of his problem. Yeah, I like that idea. Hope I remember that after my shower...</p>
I'm a bundling fool2008-05-28T09:44:00-05:002008-05-28T09:44:00-05:00
Unknown
https://orville.thebennettproject.com/articles/bundling-fool/<p>Two hundred and seventeen point one megabytes. This is the current size of an amarok.app bundle which I have laying in my <code>~/Applications</code> directory. Problem? First of all, it's about one hundred and seventeen point two megabytes too large for my liking. Secondly, it doesn't work. Point number two is the most vexing but I'll touch on point number one first. "Hey illogic-al," you may ask, "why 99.9 MB?" I'll tell you why. </p>
<p>iTunes weighs in at one hundred and thirty six point nine megabytes on leopard. Thirty seven point two of which is due to translations. So that means the iTunes bundle weighs in on the heavy side of 90 MB. My "dream weight" for Amarok's bundle is, accordingly, in this same range. Most people will never go into the Application bundle and do things like remove translations to save space though. Hell I know how and I haven't even bothered. Space is cheap. In reality this means that we're "competing" against iTunes, sizewize, to the tune of 137 MB. That's the upper limit of what I'd <em>like</em> the size of the Amarok bundle to be. </p>
<p>After removing Qt's debug frameworks from the bundle we get back 49 MB of space. That gets us to 168 MB. That puts us 31 MB away from the magic number. Currently I compile libraries with full debugging information included in the binaries. I've also thrown all of kdebase's icons directory in there because I was lazy. Some things we definitely don't need though. The oxygen/scalable directory can probably go. That would save us 37 MB. I'm thinking oxygen/128x128 can go too. Another 6.9 MB. Let's say compiling release binaries saves us 4.1 MB. In total that's 48 MB less. Oh wow. Lookit that, 120 MB. We hit the minimum weight and are fast approaching the magic number. Not bad for something containing libraries from kdelibs, kdebase, strigi, Qt 4.4 Frameworks, artwork from kdebase and the libraries of other dependencies. Something still wrong though.</p>
<p>The bundle doesn't work. The closest I've gotten is a crash happy bundle whenever i try to play audio, or a bundle missing gui elements when I just launch the app. I've been at it for about a week and a half now. A dialog box keeps popping up and whines about kio_file.</p>
<p>![kioslave error message in amarok os x bundle]</p>
<p>I've included all the libraries and executables I know or think might be related to kioslaves and their loading, but still no joy. I think the audio playback crashes might be related to the kioslaves not loading. After all, how are we going to access the file system or web without kio_file or kio_http, respectively? I also believe that the bundle has begun communicating with me. I can't fully understand what is being said, but I do get the basic gist of the communiqué: Screw you.
In commemoration of this joyous occasion I've created a slogan: <strong>Am stuck. Will cry for help.</strong></p>
<p>But wait! There's more! Oh yes, there's <em>always</em> more. Amarok will need to provide, outside of the bundle, at least one external program: dbus. Two, if someone doesn't get the qt7 phonon backend to not crash, because then we'll need to provide a xine installation as well. Which will end up bumping the size of our .dmg: amarok.app + dbus.pkg + libxine.pkg. Actually, three depending on the results of that shared-mime-info experiment. Feh.</p>
<p>We're nearly there though, we're nearly there. If nothing else I'm stubborn enough to not give up until it works, and annoying enough to keep bugging people until I get the answers I'm looking for. I predict a disturbance in the force of <a href="irc://irc.freenode.net/kde-devel">#kde-devel</a> soon. </p>
<p>![screenshot of amarok being run from bundle]</p>
<p>The story so far...</p>
Apple gcc 4.2 and Amarok: Journey's end2008-05-23T01:09:00-05:002008-05-23T01:09:00-05:00
Unknown
https://orville.thebennettproject.com/articles/apple-gcc-4-2-and-amarok-beginning/<h2 id="apple-gcc-4-2-and-amarok-journey-s-end-beginning">Apple gcc 4.2 and Amarok: Journey's <del>end</del> beginning</h2>
<p>The iPhone beta 5 SDK saved me. I finally have a (relatively) trouble-free version of gcc 4.2 with apple patches. Initially I did have some problems with it. It only started working seemlessly after I completely uninstalled Xcode 3.0, rebooted, then installed Xcode 3.1 from the iPhone SDK. Theoretically the two can be installed alongside each other with the iPhone SDK's command line tools being installed over the older version. All I have left to do now is figure out what libraries and other supporting data amarok needs to run so that I can create a .app bundle. Things are shaping up nicely so I'm actually quite optimistic about that. I already have a bundle that runs, but no graphics or sound. That's something at least. ;-) Hopefully I can get this done in a week and pass things over to the logger for automation.</p>
<p>To recap: I used apple-gcc42 from macports to compile most of the kde prerequisites (boost being the notable exception, only worked with gcc 4.0). I modified the portfile and changed the configure.args section to</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>configure.args --enable-languages=c,c++,objc,obj-c++ \
</span><span> --program-suffix=-apple-4.2 \
</span><span> --with-gxx-include-dir=/usr/include/c++/4.0.0 \
</span><span> --disable-checking --enable-werror
</span></code></pre>
<p>The following should work as well, and probably only makes a difference if you're on leopard.</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>configure.args --enable-languages=c,c++,objc,obj-c++ \
</span><span> --program-suffix=-apple-4.2 \
</span><span> --with-gxx-include-dir=/Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0 \
</span><span> --disable-checking --enable-werror
</span></code></pre>
<p>To actually use the compiler by default I installed gcc_select,
<code>sudo port install gcc_select</code>, and then created the file /opt/local/etc/select/gcc/apple-gcc42 with the following contents:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>/opt/local/bin/gcc-apple-4.2
</span><span>/opt/local/bin/cpp-apple-4.2
</span><span>/opt/local/bin/c++-apple-4.2
</span><span>/opt/local/bin/g++-apple-4.2
</span><span>-
</span><span>/opt/local/bin/gcov-apple-4.2
</span><span>-
</span></code></pre>
<p>Yes, those <code>-</code>'s are important.</p>
<p>Then to <strong>ACTIVATE</strong> my awesome hack I did</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>sudo gcc_select apple-gcc42
</span><span>cd /usr/lib/gcc/
</span><span>sudo ln -s i686-apple-darwin9 i386-apple-darwin9.2.2
</span></code></pre>
<p>All that, got me a compiler which worked just fine for building ports. KDE was a different beast however. That's where the iPhone SDK came in. I pretty much followed the instructions in the <a rel="noopener nofollow noreferrer" target="_blank" href="http://amarok.kde.org/wiki/Amarok2_On_OS_X">Amarok2 on OSX</a> wiki page (which is a funny thing to say since I <em>wrote</em> it). To utilize gcc 4.2 from the SDK I used the following as the cmake configure command:</p>
<pre data-lang="bash" style="background-color:#f5f5f5;color:#1f1f1f;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#5597d6;">CC</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">/usr/bin/gcc-4.2 </span><span style="color:#5597d6;">CXX</span><span style="color:#72ab00;">=</span><span style="color:#d07711;">/usr/bin/c++-4.2 </span><span style="color:#5597d6;">cmake -DCMAKE_INSTALL_PREFIX</span><span style="color:#72ab00;">=</span><span>/opt/kde4</span><span style="color:#5597d6;"> -DCMAKE_BUILD_TYPE</span><span style="color:#72ab00;">=</span><span>debugfull ..
</span></code></pre>
<p>I hit some issues when compiling phonon from qt 4.4.0 too, but since <strong>it doesn't even work</strong> I won't bore you with the details.</p>
<p>After that it was smooth sailing until I hit kdelibs. I had to modify two CMakeLists.txt files to get past some errors I encountered. Here's what <code>svn diff</code> said I did:</p>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Index: /Users/orville/kdesvn/trunk/KDE/kdelibs/kinit/CMakeLists.txt
</span><span>===================================================================
</span><span>--- /Users/orville/kdesvn/trunk/KDE/kdelibs/kinit/CMakeLists.txt (revision 810365)
</span><span>+++ /Users/orville/kdesvn/trunk/KDE/kdelibs/kinit/CMakeLists.txt (working copy)
</span><span>@@ -34,7 +34,7 @@
</span><span> set(kdeinit_SRCS kinit_win.cpp )
</span><span> set(kdeinit_LIBS kparts psapi)
</span><span> else (WIN32)
</span><span>- set(kdeinit_SRCS kinit.cpp proctitle.cpp )
</span><span>+ set(kdeinit_SRCS kinit.cpp proctitle.cpp ../kdecore/kernel/kkernel_mac.cpp)
</span><span> set(kdeinit_LIBS kparts)
</span><span> endif (WIN32)
</span></code></pre>
<pre style="background-color:#f5f5f5;color:#1f1f1f;"><code><span>Index: /Users/orville/kdesvn/trunk/KDE/kdelibs/kdeui/CMakeLists.txt
</span><span>===================================================================
</span><span>--- /Users/orville/kdesvn/trunk/KDE/kdelibs/kdeui/CMakeLists.txt (revision 810365)
</span><span>+++ /Users/orville/kdesvn/trunk/KDE/kdelibs/kdeui/CMakeLists.txt (working copy)
</span><span>@@ -238,7 +238,7 @@
</span><span> set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kkeyserver_x11.cpp )
</span><span> endif (Q_WS_X11)
</span><span> if (Q_WS_MAC)
</span><span>- set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kkeyserver_mac.cpp )
</span><span>+ set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kkeyserver_mac.cpp ../kdecore/kernel/kkernel_mac.cpp)
</span><span> endif (Q_WS_MAC)
</span><span> if (Q_WS_WIN)
</span><span> set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} kernel/kapplication_win.cpp )
</span></code></pre>
<p>I disabled nepomuk in kdebase as it was complaining about some soprano stuff. It doesn't work anyway so I couldn't be arsed figuring out what was wrong. I also uninstalled all the files installed by automoc (prerequisite for akonadi) as I suspected it was causing the duplicate symbol errors I was seeing in amarok's build. It was smooth sailing from there on out. Leave comments if you have trouble, I'll probably be able to help. Irc's better though; <a href="irc://irc.freenode.net/amarok">#amarok</a> on irc.freenode.net.</p>
<p>Why'd I do all this btw? Because gcc 4.0 can't compile code properly from plasma. Amarok uses plasma, which means I need plasma. The things I do for Amarok. It better love me. It better love me hard.</p>
Trial and error and error and error and error and... WIN!2008-05-17T16:34:00-05:002008-05-17T16:34:00-05:00
Unknown
https://orville.thebennettproject.com/articles/trial-and-error-and-error-and-error/<p>I've gotten apple-gcc42 to install AND compile c++ code. This has been a "long, hard battle," but i think I've finally won. I was "inspired" to take up this challenge after lfranchi, one of the amarok developers, pointed out that one of the build errors we were getting (in amarok 2 for OSX) was due to use of an old compiler. We have gcc 4.0.1 with custom apple patches on OS X. We <em>can</em> install updated versions of gcc, but these are vanilla versions of GNU's venerable compiler suite. This absence of apple extensions makes it unsuitable for use as a compiler for certain software which requires these extensions. Qt is one (and actually the only) such software which I've found requiring these apple-isms. Unfortunately, I actually need Qt for KDE for Amarok. :-) One might think it would be possible to compile Qt w/ apple's compiler (4.0) then build everything else with 4.2. My half-assed attempt at getting this to work proved unsuccessful. I also didn't like the idea of mixing software built from compilers whose versions were so far apart. I believe implementations of key features such as visibility tend to differ/change/improve with major releases enough to be incompatable or cause unforseen bugs in software. </p>
<p>But wait, Apple to the rescue! Kind of. The good boys and girls at apple have been working on an apple-ized version of gcc 4.2. Macports, my software build/maintenance/packaging system of choice on OS X has a port for this version of gcc, dubbed apple-gcc42. It would seem like problem solved, but not so. Len actually tried it out and it didn't work. After digging into it further I found that the port didn't build in support for g++. Well, <em>that's</em> silly, I thought. I'll just add it myself. After doing this and getting apple-gcc42 to both build and install successfully I declared <strong>total victory</strong> and gleefully informed lfranchi of my success. Ah the folly and naïveté of youth. It didn't actually compile c++ code though. </p>
<p>After a whole lot of trial and error last week I finally got it to <em>almost</em> do something. The only remaining issue I had was that ld couldn't find -lstdc++. Well I know what that is! It's libstdc++ of course, the standard c++ library. And I knew why I was getting that error too, apple's gcc deletes the libstdc++ directory in the builddir. According to the comments in their buildscript, this is done because they install libstdc++ from somewhere else. I looked for a libstdc++ port but alas none was available. I assumed then that I could do something at build/configure time to get ld to recognize where i already had libstdc++ installed (4.0 version). After all if the apple dudes could do it then it was certainly possible. Well after wasting a whole day on irc, the internets and the console and not having anything to show for it I gave up. After all, I had GTA IV to deal with, and lfranchi had already worked around our compile issue in amarok so this was merely an academic exercise at this point. </p>
<p>I hate losing to a computer though. After all, the stupid things only do what you tell them to. <em>We</em> can actually think, we troubleshoot, we solve problems. Then we get the computers to do the bitch work once we figure it all out for them. Really. </p>
<p>So after being encouraged by some other worked I was doing at the rear end of this week, namely making progress on a self-contained amarok.app package, I decided to revisit apple-gcc42 last night. In between sleep, google searches and typing in my password to sudo something miraculous happened. My brain started to work. My compiler (or the linker portion of it) wanted libstdc++, instead of trying to tell it where the library was, why not just give it the library. Sure it's not elegant, but having been through that whole process with xine-lib, i quite frankly don't give a hoot about "elegantness" anymore. If it works I'm happy. So it was that I linked libstc++.dylib from its gcc-4.0 home to it's new location in apple-gcc42-topia. Then I compiled one of my test c++ command line programs I had lying around; and that worked too. Then I compiled some macport c++ packages. They built and installed. Progress had been made. Now I'm in the process of rebuilding all my ports with apple-gcc42. I don't know if it's necessary but I'd rather be safe than sorry. The <strong>real</strong> test however comes when I compile Qt 4.4.0. If that works, I will have deemed this a success. And maybe I'll even be motivated enough to finished the app package. A little birdie even provided me with some useful scripts that should make it much easier. More on that later though. Maybe.</p>
<p>And I want my cookie.</p>
D2-Lightful!2008-04-14T23:46:00-05:002008-04-14T23:46:00-05:00
Unknown
https://orville.thebennettproject.com/articles/d2-lightful/<p>I almost forgot to mention that I received the Cowon D2 that I ordered recently. It's a great little PMP that plays many audio and video formats out there today. I only care about vorbis playback as that is what most of my music library is encoded in. My previous player, my iRiver clix was getting on my nerves somewhat. Little things like losing the on-the-go playlists whenever the battery died, or even after charging sometimes got on my nerves. It was a replacement for my previous PMP, a Cowon iAudio X5 (which I broke, lost, found, didn't fix and then got tired of).</p>
<p>The X5's battery wasn't holding a charge any more so instead of replacing the battery I bought the Clix. At the time the choice was between the Clix and the D2. I believe I chose the Clix based on looks and capacity at the time. I've been looking for a reason to go back to Cowon for a while now because the sound quality on their players is awesome. I'm basing that statement both on experience with the X5 and reviews on the net. Their offerings hadn't really impressed and I was waiting on something "revolutionary" in their lineup to jump back onto the bandwagon.</p>
<p>Enter the Q5W in all its touchscreened goodness. I initially was looking at it and the competing Archos 605/705 products. I ruled out the Archos' because of their addon functionality model (pay for more). And I ruled out the Q5W strictly because of it's reported weight and being a bit on the pricy side for me. Truth be told though it was mostly the weight that was an issue for me.</p>
<p>This prompted a return once again to the D2 and I chose it based on the touchscreen, HD space (and ability to add more storage via SDHC cards) and superior format support. Want to hear the really scary part? This odyssey was initially begun as I tried to decide between an iPod touch and the iPod Classic. The deal breaker there was the same old same old. No support for vorbis, or even allowing 3rd party devs to add support. Also rockbox status on the touch was nil, and storage was low. Rockbox status on the classic didn't seem that far along to me either so I said screw Jobs' player (once again).</p>
<p>Once I settled on the D2 I went back and compared to the iPod again. Comparing it to a nano, it's superior in every way: </p>
<ol>
<li>more compact </li>
<li>better audio fidelity </li>
<li>price </li>
<li>audio and video codecs support AND most importantly </li>
<li>playback time. </li>
</ol>
<p>The D2 gets a whopping 2 straight days of <strong>non-stop</strong> audio playback. Cowon's site says up to 52 hours, so we know in the real world that like 48hrs. In normal usage than could be up to a week before needing to recharge. That, boys and girls, is awesome. That's why I finally gave in and got me a Cowon iAudio D2, and now that I have it -- I'm lovin' it.</p>