Tag: secondcrack

Update Second Crack from filethingie

This blog post describes how to set up a filethingie installation and create a plugin to update your posts. It assumes that you already have a shell script in place to start the update of your blog.

Disclaimer: you are yourself responsible for securing the access to filethingie and the command to update secondcrack.
For the first step simply point the filethingie basepath to the second crack basepath. I use:

/srv/http/webapps/siteroot
- cache
- drafts
- htdocs
    filethingie
- media
- pages
- posts
- secondcrack
- templates
update.sh

In the filethingie config.php I have set the basepath to:

$ft["settings"]["DIR"]               = "../.."; // Your default directory.  Do NOT include a trailing slash!

From there I can manage all the folders and upload new files.

Files to create/update to update Second Crack

plugins/secondcrack.plugin.php

When in the filethingie root, create plugins/secondcrack.plugin.php

<?php
function ft_secondcrack_info() {
    return array(
        'name' => 'Secondcrack pugin',
        'settings' => array(
            'updatecommand' => array('description' => 'The command to update the blog', 'default' => '')
        )
    );
}

function ft_secondcrack_page($act) {
    global $ft;
    if ($act === 'secondcrack') {
        set_time_limit(0);
        $command = $ft['plugins']['secondcrack']['settings']['updatecommand'];
        $result = shell_exec($command);
        return 'Command run! Output: <i>' . htmlentities($result) . '</i>';
    }
}

function ft_secondcrack_secondary_menu() {
    return '<a href="' . ft_get_self() . '?act=secondcrack">Update Secondcrack</a>';
}

config.php

$ft['plugins']['secondcrack'] = array(
'settings' => array('updatecommand' => '[the updatecomand]')
);

Replace [the updatecommand] with the command you use to update secondcrack. I have created a small update.sh shell script that I placed in the root of the folder.

update.sh

#!/bin/sh

cd /srv/http/webapps/siteroot
/usr/bin/php ./secondcrack/engine/update.php >> /var/log/secondcrack.log 2>&1

echo "CLI: Executed update command for secondcrack."

This script assumes that there is a folder called secondcrack in the siteroot where the engine can be invoked.

Leave a Comment

Second Crack Template Changes

An important change to the Second Crack template is to have a personal design that matches the goal of your blog. I wanted to keep it clean and simple and found a template design Simplesive that matches my preferences.

After modifying the template (originally made for Blogspot) I found that the Second Crack engine only allows you to display the full post on every page (overview and detail). You can circumvent this behavior by adding some changes to the template.
Besides that external links also need to be opened in an external window.

Open external links in a new window

My preference is to have links within the blog in the same window and to open external links in a new window or tab. Markdown does not have support for specifying a target for links, so I solved it using a piece of javascript I found.

//force external links to open in a new window, http://stackoverflow.com/questions/4425198/markdown-target-blank
var links = document.links;
for (var i = 0, linksLength = links.length; i < linksLength; i++) {
   if (links[i].hostname != window.location.hostname) {
       links[i].target = '_blank';
   } 
}

Read more function

The template must be modified in order to display it in a shorter version, or the full version. Every post must also include a marker (). On an overview page this marker and everything below it will be removed and replaced by a read more link.
On a detail page this marker is removed and the entire post is displayed. A detail page in Second Crack has the $pageType post

Template function

<?php if( !function_exists('tpl_getPostContents') ) { 
    function tpl_getPostContents( $postBody, $pageType, $permaLink, $moreLink = '<p class="readmore"><a href="%s">Read on</a></p>') {
    $excerptOnly = $pageType !== 'post';

    $morePatternPart = '<!---\s*more\s*--->';

    if( !$excerptOnly ) {
        //remove the comment from the source
        return preg_replace('/' . $morePatternPart . '/ms', '', $postBody);
    } else {
        $matches = null;
        if( preg_match('/^(.*)' . $morePatternPart . '/ms', $postBody, $matches) ) {
            return $matches[1] . sprintf($moreLink, $permaLink);
        } else {
            return $postBody; //there is no more part
        }
    }
} } ?>

The function starts with a check if the function already exists. This is necessary because for every page the Second Crack generates the template is included.

Display post

<div class="post-outer">
    <div class="post hentry">
        <h3 class="entry-title"><a href="<?php echo h($post['post-permalink-or-link']) ?>"><?php echo h($post['post-title']) ?></a></h3>
        <span class="post-timestamp">By Daan at <?php echo date('F j, Y', $post['post-timestamp']) ?></span>
        <div class="post-body entry-content">
            <?php echo tpl_getPostContents($post['post-body'], $content['page-type'], $post['post-permalink-or-link']); ?>
            <div class="post-footer-line post-footer-line-2"><span class="post-labels">
                Tags: <?php $tagCount = count($post['post-tags']); $iter = 0; foreach( $post['post-tags'] as $tag => $value ) { ?>
                    <a href="/tagged-<?php echo $tag; ?>.html" rel="tag"><?php echo $tag; ?></a><?php if( $iter < $tagCount-1) echo ', '; ?> 
                <?php $iter++; } ?>
                </span>
            </div>
        </div>
    </div>
</div>

In the post the function is used to display the contents.

RSS template Change

In the RSS feed I use the same function tpl_getPostContents to display the RSS contents. I do not include the function itself there, the main.php template file already defines the function.

Core change

I noticed that when validating the generated rss.xml that there were warnings about the timestamp in the post_date field. To fix this I updated the Post.php file with the following change:

In Post.php: function array_for_template() I changed this line:

'post-rss-date' => date('D, d M Y H:i:s T', $this->timestamp),
to:
post-rss-date' => date('r', $this->timestamp),

The difference is that the r modifier in the PHP date() function generates an RFC 2822 formatted date, which is a better format in the XML than the original date format in the Second Crack code.

Leave a Comment

Running Second Crack on a nginx server

This blog is running on an nginx webserver. The Second Crack page contains a .htaccess file which rewrites the permalinks to html files. For example the URL http://www.example.com/2014/01/20/example-blog-post is internally rewritten to http://www.example.com/2014/01/20/example-blog-post.html. On an nginx server .htaccess files do not work (at least not on a default configuration) so this needs to be incorporated in the site configuration.

Update April 26th 2015, updated nginx configuration to support index.html index file on subfolders (in try try_files statement).

Server config file

The server configuration below is based upon an excellent post by Adufray, I only improved upon it. Most elements are pretty standard, I will only explain the ones which are not as obvious.

server {
	listen 80;
	server_name www.daangemist.nl;
	root /srv/http/webapps/www.daangemist.nl;
	index index.html;

	rewrite ^/feed/$ /rss.xml permanent;

	types {
		application/rss+xml xml;
	}

	location ~ ^/. {
		default_type text/html;
		try_files $uri $uri/index.html $uri.html =404;
		error_page 404 /404.html;
	}
}

Rewrite

This line tells nginx to return a 302 Redirect HTTP response if someone requests the /feed/ URL. It is in place for the migration from WordPress to Second Crack.

Types

The RSS feeds are XML documents, this directive tells nginx to return a Content-Type: application/rss+xml header instead of text/xml for the RSS files.

Location

_tryfiles is the nginx counter part of the .htaccess _modrewrite directive in the .htaccess file on Apache. It tells nginx to look for a .html file for every URL it cannot find. I have added the =404 to prevent a redirect loop, this occurred in combination with the error_page directive.

2014/01/03 23:23:43 [error] 21252#0: *3 rewrite or internal redirection cycle while internally redirecting to "/favicon.ico.html.html.html.html.html.html.html.html.html.html.html", client: 62.140.132.196, server: www.daangemist.nl, request: "GET /favicon.ico HTTP/1.1", host: "www.daangemist.nl"

The $uri/index.html is to support subfolders, for example by accessing the monthly index via http://site/blog/2014/02/.

_errorpage tells nginx to open a custom 404 page if a post or page cannot be found, as explained in the WordPress migration post.

Leave a Comment

Migration from WordPress to Second Crack

The first step in migrating from WordPress to Second Crack was to move all the posts from the WordPress database to .md files on disk. This can be a cumbersome task and I have not found a good way to do this.
The process I followed was manually going from post to post and converting it to MarkDown. You can use your favourite search engine to find a convertor that fits you, I used a javascript solution I was able to use inside my webbrowser. The blog I migrated
from did not have any pages, so there was no need for me to migrate those.

Posts

Using the query below I fetched the posts from the database (where wp_ is the WordPress table prefix for your tables), this returns all posts and drafts present in the WordPress database, ignoring all revisions:

SELECT post_date, post_name, post_content, post_status, guid FROM wp_posts WHERE post_type = 'post';

Permalinks

After you have completed the migration of the posts, the hard part is done. What remains now is to handle the permalinks that have changed in the migration. My blog used to run on an Apache server with the mod_rewrite module on to make prettier URLs possible.
Unfortunately the permalink structure of Second Crack is fixed. If someone had bookmarked or links to one of my old blog URLs that would have ended up in an ugly 404 Not Found page. In order to solve this problem I created a custom 404 page with URL detection.

Configurating a custom HTML page when a page cannot be found is easy on both Apache and nginx.

#Apache (this is already in the .htaccess provided by Second Crack):
ErrorDocument /404.html

#nginx:
errorpage /404.html

In the www folder to the blog I created a 404.html document with the same template as the other blog pages. The blog contents is replaced with a simple statement that the Requested document could not be found.

Now if someone visited an old URL they would at least see a pretty error page. But because of the static structure of the posts I saw a possibility to redirect the user to the correct page in the new structure.
I started with the permalinks and issued the following SQL query to get the permalinks and convert those to the Second Crack post structure. Keep in mind that the WordPress permalinks end with a / and the Second Crack permalinks do not.

SELECT CONCAT(CONCAT(DATE_FORMAT(post_date, '%Y/%m/'), post_name), '/'), CONCAT(DATE_FORMAT(post_date, '%Y/%m/%d'), post_name) FROM wpdg_posts WHERE post_status = 'publish' AND post_type='post';

Javascript solution

These permalinks are used in a piece of javascript which attempts to determine whether the not found URL is an old permalink:

var oldWordpressPermalinks = new Array(
        new Array('/2012/11/unfreezing-putty-after-pressing-ctrls/','/2012/11/01/unfreezing-putty-after-pressing-ctrls'),
        new Array('/2012/11/installing-mpd-on-windows/','/2012/11/16/installing-mpd-on-windows'),
        new Array('/2012/11/decrease-video-file-size-using-ffmpeg/','/2012/11/19/decrease-video-file-size-using-ffmpeg'),
        ...
);

for( iter = 0; iter < oldWordpressPermalinks.length - 1; iter++) {
    if( oldWordpressPermalinks[iter][0] == path ) { 
        window.location.href = 'http://' + window.location.hostname + oldWordpressPermalinks[iter][1];
        break;
    }
}

You can see it for yourself, just visit a non-existing page on this blog.

Category and tag links in WordPress can be processed in a similar matter. Second Crack does not support categories, so here the assumption is made that there is a tagname for the category. There is also no check whether the tag where is being redirected to actual exists.

//check for URLs of the format/category/howto/page/2 (the page/2 part is optional)
var catPatt = /^\/category\/([a-zA-Z0-9]+)\//;
catRes = catPatt.exec(path);
if( catRes ) { //match
    window.location.href = 'http://' + window.location.hostname + '/tagged-' + catRes[1] + '.html';
}

//check for /tag/mantisbt
var tagPatt = /^\/tag\/([a-zA-Z0-9]+)$/;
tagRes = tagPatt.exec(path);
if( tagRes ) { //match
    window.location.href = 'http://' + window.location.hostname + '/tagged-' + tagRes[1] + '.html';
}

There are some other WordPress URLs currently not covered, such as /2013/01 but that was more complicated, since there are also physical folders on disk with the same name.

RSS Feed

Last item on the list for the migration is the RSS feed. In my WordPress configuration the feed was located on /feed/. I have configured my nginx webserver to permanently redirect to /rss.xml, the RSS location Second Crack.

#Apache:
Redirect 301 /feed/ /rss.xml

#nginx:
rewrite ^/feed/$ /rss.xml permanent;

Place this in your nginx server block and all subscribers to your old blog will still be able to access the new feed.

Leave a Comment

Blog migration to Second Crack

The last weeks I have been migrating the blogging engine of this site to Second Crack. This is blog engine in PHP which generates static files as output. This means that no database is required to have this blog running.

The choice to migrate the blog engine was made after I had migrated the blog from a VPS to a Raspberry Pi which I have running at home. The available resources was limited and I needed a way to make all sites running on the system as light-weight as possible (if you are interested, the RPi itself is running on the arkOS distribution.

In the migration from WordPress to Second Crack I had to take some hurdles in order to get it working the way I liked it. The coming weeks I will be publishing some posts on the different subjects, for example: running Second Crack on Windows, migration WordPress permalinks, configuration on Nginx.

This post will be updated with links to the different posts. Last update: January 11th 2014.

  1. Second Crack on Windows
  2. Migration from WordPress to Second Crack
  3. Second Crack on nginx
  4. Second Crack template changes

Leave a Comment