PHP Tutorial: Replace long link text

I created this function so that I could have a way of preventing very long non-breaking text links from breaking my web page layout. Paritcularly, this is used in my tweet / facebook section of my homepage. Whenever I posted a link to either of them, when the link URL was too long and could not be broken, it would overflow into the next column. Yes of course you could use css to do this, however the methods which are generally used are not valid with CSS2.1, so I came up with a way that programatically parses the link and replaces the text with “[Link]”. There are some limitations to this approach. First, since I use a simple solution, there is no way to preserve some information normally in the link such as target, title etc. Second it is being used for tweet and facebook statuses, so it is limited to checking only the first encountered link. It could be expanded to include multiple links, but I have no need for this at the moment so I left it out. Update: I noticed that it was also filtering my @links from twitter, so I made a slight change so that it will only shorten if it finds http:// in the url text now. Anyway here is the code:

/*
* Replaces all link-text with '[Link]' so that links which are very long do not break web page layouts
* Note: some information is lost, such as custom title, target etc.
* Jason Ernst- 2011
*/
function filter_long_url($content)
{
$startpos = strpos($content, "", $startpos);
if($midpos !== false)
{
$endpos = strpos($content, "", $midpos);
if($endpos !== false)
{
$url = substr($content, $midpos+1, ($endpos)-($midpos+1));
if(strpos($url, "http://")===false)
return $content;
else
{
$newcontent = substr($content, 0, $startpos);
$newcontent = $newcontent . "[Link]" . substr($content, $endpos+4);
}
}
else
return $content;
}
else
return $content;
}
else
return $content;

return $newcontent;
}

If the function gets something with a half-completed tag, it should just return the original content since it is impossible to find the other parts of the tag correctly.

WordPress Tutorial: Recent Posts Block with Images

This post follows up on the last WordPress tutorial which shows how to start using featured images. In this post, I show how you can display a block of recent posts along with the featured image, in the same way as my website. (See the bottom of the home page, or the bottom of individual posts).

You will likely need to play around with the styling (margins, padding, etc.) a bit to fit with your own templates, but this should give you a good start. This assumes that you have setup thumbnails for “mini-thumbnail” (see previous tutorial on how to do that). You can play around with how many posts you want to display using posts_per_page below.


What the recent posts block will look something like

The first thing to pay attention to is the shorten_content function. This ensures that the content is not too long to display within the limited area we have. You can put this directly in the template file you are editing if you like, but I put mine in the functions.php file for the particular template.

)|(\)|(\
)/", " ", $content);
$content = strip_tags($content);
if(strlen($content) < $size) return $content; $content = substr($content, 0, $size); $spaceloc = strrpos($content, " "); if($spaceloc) { $content = substr($content, 0, $spaceloc); $content.= "..."; } return $content; } ?>

Next we reset the query so that we can make a new query with the number of posts we would like and how we want to order them. For recent posts, we order by date and in this case we are showing 6 posts. Also one spot to pay attention to is the $count checking. You will notice when $count = 3, a clearing div is displayed. This controls how many recent posts to show per line. You can change this number to get more or less on one line.

Recent Articles

"date", "order" => "DESC", "offset" => 1, "posts_per_page" => 6));
if(have_posts())
{
$count = 0;
while(have_posts())
{
$count++;
the_post();
$postthumbnail = get_the_post_thumbnail($post->ID, 'mini-thumbnail');
if(!isset($postthumbnail) || $postthumbnail == "")
$postthumbnail = ''. get_the_title() .'';
?>



 

The last thing we need is the css to style things. This is likely where you will need to change things to suit your own site.

.recent-entry { float:left; width: 30%; //change this width depending on how many entries you want on one line.}
.recent-entry h2 { font-size: 14px; }
.recent-entry img { padding-right: 2px; }
.recent-entry date { font-size: 9px; color: #333333; }
.recent-entry content { font-size: 10px; }

Tutorial: sockets – 3 ways to listen

As you may know, I have been ta-ing a course in operating systems. We just finished covering sockets and in the last lab I gave a socket demo where I show three different ways a server can listen on a socket. First is a very basic case where the server can only accept and process one connection at a time. Second I show the fork()ing case where multiple connections can be processed concurrently using multiple processes. Lastly, the multiple connection case is handled with select() so that everything can be handled in a single connection.

Single connection server
This server is a basic echo server. A client connects to it on a specific port and enters strings on the stdin. The server maintains the connection until the client terminates the connection with a blank line.

The major weakness of this server is that it can only handle a single connection at once. So if the first connection is very slow, any subsequent connections must wait, even if they are ready to be handled. In the case of this server, the first user to connect may be very slow to type their strings, and even if the second user has already entered a string, it will not be displayed until the first user connection in completed.

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define ERROR(x) do { perror(x); exit(1); } while(0)

#define NAME 257
#define BUFSIZE 257
#define MAXPENDING 1

int main(int argc, char *argv[])
{
unsigned short port; /* Port to which server will bind */
char servhost[NAME]; /* Local host name */
struct sockaddr_in sock; /* INTERNET socket space */
struct hostent *server; /* Local host information */
int S; /* fd for socket */
int NS; /* fd for connected socket */
char buf[BUFSIZE]; /* Input buffer */
FILE *fp; /* Stream (converted file des.) */

if (argc != 2)
{
fprintf(stderr,"usage: server \n");
exit(1);
}

port = atoi(argv[1]);

/*
* Get socket - INTERNET DOMAIN - TCP
*/
if ((S = socket(AF_INET, SOCK_STREAM, 0)) < 0) ERROR("server: socket"); /* * Obtain host name & network address */ gethostname(servhost, sizeof(servhost)); if ((server = gethostbyname(servhost)) == NULL) { fprintf(stderr,"%s: unknown host\n",servhost); exit(1); } /* * Bind to server address - in network byte order */ sock.sin_family = AF_INET; sock.sin_port = htons(port); memcpy(&sock.sin_addr, server->h_addr, server->h_length);

/*
* Bind socket to port/addr
*/
if (bind(S, (struct sockaddr *)&sock, sizeof(sock)) < 0) ERROR("server: bind"); /* * Listen on this socket */ if (listen(S,MAXPENDING) < 0) ERROR("server: listen"); //loop to continue handling connections while(1) { /* * Accept connections. Once connected, the client will be * connected on fd NS, a second and third parameter may be passed * to accept which will be filled in with information regarding the * client connection if desired. * * In this example, once connected the server is done with the * master socket (so closes it). */ if ((NS = accept(S,NULL,NULL)) < 0) ERROR("server: accept"); /* * Using stdio library to read from socket */ if (!(fp = fdopen(NS,"r"))) { fprintf(stderr,">>> Error converting file des. to stream <<<\n"); exit(1); } while (fgets(buf,BUFSIZE,fp)) printf("%s", buf); /* * DONE - simply close() connection */ fclose(fp); close(NS); } return(0); }

fork() - Multiple connection, multiple process
In this case, the server can now handle multiple connections successfully. If the first connection has a long processing time or the user is slow at entering data, the second connection may now continue freely without waiting in line. The downside to this approach is: 1) If the server must handle a large number of connections simultaneously, the server may run out of processes since each connection fork()s. 2) Since a fork() call duplicates variables, file descriptors etc., the server may run out of memory if each connection requires any significant processing.

Notice that the processing portion of the code has been moved into a function which is called when the fork() is executing within the child processes.


Fork Server

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define ERROR(x) do { perror(x); exit(1); } while(0)

#define NAME 257
#define BUFSIZE 257
#define MAXPENDING 1

void handle_connection(int NS);

int main(int argc, char *argv[])
{
unsigned short port; /* Port to which server will bind */
char servhost[NAME]; /* Local host name */
struct sockaddr_in sock; /* INTERNET socket space */
struct hostent *server; /* Local host information */
int S; /* fd for socket */
int NS; /* fd for connected socket */
int pid; /* used to determine parent or child */

if (argc != 2)
{
fprintf(stderr,"usage: fork-server \n");
exit(1);
}

port = atoi(argv[1]);

/*
* Get socket - INTERNET DOMAIN - TCP
*/
if ((S = socket(AF_INET, SOCK_STREAM, 0)) < 0) ERROR("fork-server: socket"); /* * Obtain host name & network address */ gethostname(servhost, sizeof(servhost)); if ((server = gethostbyname(servhost)) == NULL) { fprintf(stderr,"%s: unknown host\n",servhost); exit(1); } /* * Bind to server address - in network byte order */ sock.sin_family = AF_INET; sock.sin_port = htons(port); memcpy(&sock.sin_addr, server->h_addr, server->h_length);

/*
* Bind socket to port/addr
*/
if (bind(S, (struct sockaddr *)&sock, sizeof(sock)) < 0) ERROR("server: bind"); /* * Listen on this socket */ if (listen(S,MAXPENDING) < 0) ERROR("server: listen"); while(1) { /* * Accept connections. Once connected, the client will be * connected on fd NS, a second and third parameter may be passed * to accept which will be filled in with information regarding the * client connection if desired. * * In this example, once connected the server is done with the * master socket (so closes it). */ if ((NS = accept(S,NULL,NULL)) < 0) ERROR("server: accept"); if((pid = fork()) < 0) ERROR("server: fork"); if(pid == 0) { handle_connection(NS); exit(0); } else close(NS); } return(0); } void handle_connection(int NS) { char buf[BUFSIZE]; /* Input buffer */ FILE *fp; /* Stream (converted file des.) */ /* * Using stdio library to read from socket */ if (!(fp = fdopen(NS,"r"))) { fprintf(stderr,">>> Error converting file des. to stream <<<\n"); exit(1); } while (fgets(buf,BUFSIZE,fp)) printf("%s", buf); /* * DONE - simply close() connection */ fclose(fp); close(NS); }

select() - Multiple connection, single process
The last case still has the benefits of fork() but does so in a single process. In this case, select() is used. In this case, each socket descriptor is monitored by select which determines if any of the sockets are ready for I/O. Rather than sitting idly waiting for input on sockets that are not ready, data is processed as it arrives. The drawback to this approach is that it is little trickier to implement and understand, but if you start with a basic case like this it can be quite simple to get the hang of it. When using select(), we need to specify the groups of sockets we wish to monitor. This is done using the fd_set which you can see in the source.


Select Server

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define ERROR(x) do { perror(x); exit(1); } while(0)

#define NAME 257
#define BUFSIZE 257
#define MAXPENDING 1

void handle_connection(int NS, fd_set * activefds);

int main(int argc, char *argv[])
{
fd_set readfds, activefds; /* the set of read descriptors */
unsigned short port; /* Port to which server will bind */
char servhost[NAME]; /* Local host name */
struct sockaddr_in sock; /* INTERNET socket space */
struct hostent *server; /* Local host information */
int S; /* fd for socket */
int NS; /* fd for connected socket */
int i; /* counter to go through FDs in fdset */

if (argc != 2)
{
fprintf(stderr,"usage: select-server \n");
exit(1);
}

port = atoi(argv[1]);

/*
* Get socket - INTERNET DOMAIN - TCP
*/
if ((S = socket(AF_INET, SOCK_STREAM, 0)) < 0) ERROR("select-server: socket"); /* * Obtain host name & network address */ gethostname(servhost, sizeof(servhost)); if ((server = gethostbyname(servhost)) == NULL) { fprintf(stderr,"%s: unknown host\n",servhost); exit(1); } /* * Bind to server address - in network byte order */ sock.sin_family = AF_INET; sock.sin_port = htons(port); memcpy(&sock.sin_addr, server->h_addr, server->h_length);

/*
* Bind socket to port/addr
*/
if (bind(S, (struct sockaddr *)&sock, sizeof(sock)) < 0) ERROR("server: bind"); /* * Listen on this socket */ if (listen(S,MAXPENDING) < 0) ERROR("server: listen"); /* Initialize the set of active sockets. */ FD_ZERO (&activefds); FD_SET (S, &activefds); while(1) { /* Block until input arrives on one or more active sockets. */ readfds = activefds; if (select (FD_SETSIZE, &readfds, NULL, NULL, NULL) < 0) { perror ("select"); exit (EXIT_FAILURE); } /* Service all the sockets with input pending. */ for (i = 0; i < FD_SETSIZE; ++i) { if (FD_ISSET (i, &readfds)) { if (i == S) { /* Connection request on original socket. */ /* * Accept connections. Once connected, the client will be * connected on fd NS, a second and third parameter may be passed * to accept which will be filled in with information regarding the * client connection if desired. * * In this example, once connected the server is done with the * master socket (so closes it). */ if ((NS = accept(S,NULL,NULL)) < 0) ERROR("server: accept"); FD_SET(NS, &activefds); //add the new socket desc to our active connections set } else { /* Data arriving on an already-connected socket. */ handle_connection(i, &activefds); } } } /* //end of for */ } /* //end of while */ return(0); } void handle_connection(int NS, fd_set * activefds) { char buf[BUFSIZE]; /* Input buffer */ FILE *fp; /* Stream (converted file des.) */ /* * Using stdio library to read from socket */ if (!(fp = fdopen(NS,"r"))) { fprintf(stderr,">>> Error converting file des. to stream <<<\n"); exit(1); } //if fgets fails we have end of line, quit if(!(fgets(buf,BUFSIZE,fp))) { /* * DONE - simply close() connection */ fclose(fp); close(NS); FD_CLR(NS, activefds); } else printf("%s", buf); }

Additional Information
http://www.uoguelph.ca/~jernst/3110/cis3310-lab4.pdf
http://www.socs.uoguelph.ca/~dbm/teaching/CIS3110/
http://beej.us/guide/bgnet/
manpages!

Some Useful Information for Setting Up Subversion on Ubuntu

Not a tutorial or guide this time, since everyone else seems to have this covered quite well, but thought I’d collect a few good links together in one place. Hopefully these links will be useful to someone just starting with SVN. For everyone who isn’t using some type of version control, nows your chance!

Ubuntu tutorial for installation:
http://danielabrantes.blogspot.com/2010/11/install-subversion-in-ubuntu-1010.html

Beginner HowTo (suited to WordPress plugin devs, but still good to apply to your own setup):
http://codex.wordpress.org/Using_Subversion
http://wordpress.org/extend/plugins/about/svn/

Multi-platform SVN client – RapidSVN:
I found this client especially useful since it works across platforms and it is lightweight and quick.
http://rapidsvn.tigris.org/


RapidSVN Screenshot
 

Popular Windows SVN client – TortoiseSVN:
This client is useful if you like tight integration with Windows. It shows up in the context menus and is very easy to work with.
http://tortoisesvn.tigris.org/


TortoiseSVN Screenshot
 

WebSVN:
A more refined web interface to svn, compared with the one provided using the initial setup.
http://agilior.pt/blogs/pedro.rainho/archive/2010/02/06/11698.aspx


WebSVN Screenshot
 

SVN on Hostmonster (or other hosts with blocked svn port, but SSH access):
http://hostmonsterforum.com/showthread.php?1294-Subversion