Logo Design Prototyping for a Social Network

Published on
Aug 31, 2014
Fast design prototyping is the only way to keep afloat in the sea of competition. So unless you have unlimited budget, the best strategy is to work it fast and in a convincing manner. The success of the presentational transmission shouldn’t be perfect, but it must surpass some minimal and acceptable perceptual threshold - namely the “feeling”.

Same approach can be applied to the vast majority of web projects such as magazines, blogs, promotional pages and of course to social networks. One example created by our group is bringerr.com. It’s [EDIT: was] a social driven network of delivery and moving services which was built to reduce the cost of transportation and generate the real or “market” value on the arena.

In addition to main functionality we created a simple responsive design suitable for most of our targeted devices. The prototyping went on using open source software such as Inkscape, Gimp and Google Chrome on Ubuntu Linux box using Dell Sputnik (another codename for DELL XPS), which is a great machine for web development.

So let’s start a discussion about logo development.

So the journey starts from an idea. The logo had to be about moving and transportation. But how can one represent such a vague and abstract term and digitize it into some intuitive symbol? One could visit thenounproject.com and search for “delivery” or “transportation” and find the expected: cars, delivery men and similar icons. But making a logotype from such a popular and raw material would make it look “cheap” and unoriginal. Instead, the author went on experimenting.

The name “Bringerr” is about bringing and moving anything, anywhere. So naturally one could start from drawing the interrelated idea cloud, but I started from drawing the logo. Drawing logo is a good approach when you want to find the “invisible” inside the given shapes of the letters. There’s a nice article about Seeing the negative in everything, which is a subcategory of what’s described here briefly.

First, I opened the GIMP and put together the letters, played with the fonts, and after half an hour found the font I wanted. As you know, there are many popular logos, and most of them use already available fonts created by someone else. It’s very tempting to create your own identity and style through your own font, even if you’re not actually building a new set of all 26 x 2 letters, but time is running, and probably on the early stages an existing font is the best choice. Just choose the right one. I found my free font on Google fonts, the name is Petrona and it looks like that:

So the font was nice, but the creative process can be sometimes somewhat painful especially when you don't feel it's going anywhere. So I felt somewhat stuck, but since the Bringerr project has a vast database of things to be done including all kinds of full-stack development issues, I put the task of creating the logo aside and returned to my daily routine, keeping aside pen and paper for the logo ideas as they become available. I tried to devise a logo with a new font, breaking my own rules about time economy. And although I really found the font I wanted more than what I found on Google, I decided that developing that font into a final project would cost me more time than if I stick to the chosen one. So "Petrona" was it. The only thing remained was to create an icon for the logo.

There are many kind of logotypes, some are completely iconic (3M, McDonalds, a lot of car companies such as Toyota, Audi, BMW and many more) and others are text-based like (Microsoft, Diesel, Virgin etcetera). So like Microsoft, which has the textual logotype and an iconic one, I also decided that we need an icon, right? Nahh, the real reason is of course to create a visual identity which is easily recognized. And since I was tired of text manipulation, and placing exclamation marks above ‘i’s etc, I started experimenting with an icon.

The development went on until realizing the similarity of the balloon form to the the shape of the letter “B” and that was it! Because the purpose of the social network is to basically connect or “meet” the two points - the source and the destination of the delivery, and to achieve that by combining it with the meaning and the purpose of the name itself. Also the goal is not to make it out of mainstream symbols, and not to use mainstream techniques. And the more it’s unique - the more convincing it is. Of course you are more than welcome to write your thought and suggestions below, but please keep in mind, that the goal was not to create a perfect logo, but rather a quick prototyping with a unique visual identity.

The final product was a no-brainer since everything was ready, and the only thing to do was to draw a few vectors, choose the colors and enjoy the result.

Bringerr Logo
Thanks for reading.

Show several views with AJAX in Drupal 7

Published on
Jun 28, 2012


So you've created your views in Drupal. You supposed that they would bring you calmness into peaceful life. And then you get a new request from your customer -- I want these views to be rendered inside tabs, I want them ten or more per page, and I want them to load dynamically. If you're not a stunned Drupal-only developer, but just a normal guy or gal with a pile of development knowledge, you'll probably try to render your view programmatically using views_embed_view() or similar, then return it to the client side, which is after all some jQuery .click() event with a .post(), and you'll hope for the best.

Unfortunately, (and speaking about Fortune, we could rephrase to - pretty predictively), you get the nice-looking rendered view but, the AJAX doesn't work. No pagination, no other event which you have defined. You start analyzing, and get the impression that some .js files are missing.

They are missing because when Drupal renders a page, there's not a single view present (you're loading them with AJAX, remember?). You may try to collect all the javascripts and throw them all in the header just to test, but wait.

There's Hope.

There is a nice module in Drupal, especially made for this purpose. It's called Quicktabs. It's a complex module, and it knows how to render not only Views, but also blocks, nodes and another quicktabs.

So you need to install this module. Create your View, then go to Structure >> Quicktabs, create a new one. As you can see, the interface is simple and minimal, and this is the case that every additional word about it is re-dun-dant. The only thing to notice is the Machine name, near the Title. Write it down, you're going to use this soon.

Inside your module, create a menu, then the hook_theme() etc. Now we're going to render the quicktabs programmatically with the following code:

$quicktabs = quicktabs_build_quicktabs('the_name_of_my_quicktab_that_i_wrote_down_in_the_previous_step'); $content = render($quicktabs); return theme('draw', array( 'content' => $content)) ; // use $content variable in draw.tpl.php template

That's it. Now you can navigate to your website.local/draw or whatever you've defined, and enjoy from dynamically loaded content such as Views, Nodes and what not.

Additional stuff

I'm adding a code for minimal module needed to demonstrate this.

The module:

'Let\'s draw some tabs!', 'description' => t('Description'), 'page callback' => 'my_draw', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK ); return $items; } function my_draw() { $quicktabs = quicktabs_build_quicktabs('the_name_of_my_quicktab_that_i_wrote_down_in_the_previous_step'); $content = render($quicktabs); return theme('draw', array( 'content' => $content)) ; // use $content variable in draw.tpl.php template } /* * Implementation of hook_theme(). */ function my_theme($existing, $type, $theme, $path){ return array( 'draw' => array( 'variables' => array('content' => NULL), 'template' => 'draw', // place you file in 'theme' folder of you module folder 'path' => drupal_get_path('module', 'my') .'/theme/' ) ); }

The .info:

name = My description = My module. package = My core = 7.x php = 5.2

The template from my_module/theme/:

Let's draw our quicktabs:
Cool, ehh?


We have successfully rendered AJAXified tabs and loaded contents with the power of Drupal. However, if I had to create this or similar things again, as a developer, my better choice would be writing the clean code with Ruby on Rails. Of course, Drupal is the best option when you know what you want and, you know that it's easy to achieve with Drupal and you know which module to use - when, where and how. I hope this article has helped you to solve your problem.

Better design for web input elements

Published on
Jun 21, 2012

Better design means better user experience. So how do we deliver it to the users?

We minimize users interaction.

Unfortunately we still find today a lot of weird web forms. How often do you find these annoying date input fields, where you see a plain text box with a nice example text explaining you the correct format, e.g. dd-mm-yyyy or such?

What’s the problem you ask? There are several.

First, you have to type. And this increasing the negative user experience and time on the website. The game that you created is played from now on against you. Isn’t it shocking?

Next, the user has to type correctly! And in case that there’s some validation behind, the website will return your marked input yelling some “Error! Please correct your date” output. The game continues, and the user corrects the text. This stage can go on loop several more times.

Multiply this single experience by some 10 more elements some 10 more websites per day, and your frustration is guaranteed. This is what I experience daily. You might feel the same.

How this could be done better? The developer, can add an example or two. Instead of adding dd-mm-yyyy, 04-07-2012 could be added. Now the user can just copy and paste, or mouse-select and drag and drop this example to the textbox input and change it. A datepicker could be added, but hey, this is all old and primitive. We’re in the HTML5 era fast-forwarding to HTML10, aren’t we?

The best in my opinion, would be a completely new element in HTML5, but since there’s isn’t one, let me explain how to make it with Javascript.

The date field would consist of something resembling the old counter, with guessed date. If the date cannot be guessed, today’s date can be placed. But if we’re talking about some adult, and asking about his age, we could guess that his age is more than 20 years, and place the initial value, say, 15-06-1992. Now comes the interesting part. Clicking and dragging the numbers, should roll the number up or down. So if my birthday is actually on 28-09-1979 (dd-mm-yy remember?) then I’ll drag up a bit the number 15, then just a bit more the number 06, and finally the year. Why 15? Because it’s in the middle of any months. See the logic sneaking in here? So same with the 06.

Ok. Now what?

This element is kind of new. So how do we make someone feel comfortable with it? We tell the user nicely, “click and drag” and we make sure that dragging up is equivalent to dragging to the right, and down is equivalent to the left. Why? To ensure that user gets the feedback in any case even if he moved to the wrong direction.

Of course, the validation should go with AJAX or HTML5 or whatever, just don’t force the user to refresh the page! Add a simple button, and please don’t use the ugly word “Submit”. Call it “Save” or “Store” or “Update” instead. And once it’s clicked, change it to “Saved”, “Stored” or “Updated” disabled button state accordingly. Take one further step to make it even better - save automatically each few seconds, so there won’t be any need to submit anything to anyone.

Are you still reading? Good. Let’s allow the “Save” button to flow nicely to the next field which we’re editing. Do you remember how it’s troublesome, especially inside a long web form, to scroll up and down and trying to figure out where is that freaking button? No more.

Red light district. I really hate this thing. Every time a red-colored error appears before my eyes, it drives me crazy. It’s like I just created some wicked evil. Instead, I’d love to have some more nice colors, like green or blue sine-waiving calmly and driving my attention. Ok, you know what? You can add the STOP road sign of the country where the user came from. Just remember, it’s not the same in most of the countries, so please do act accordingly :)


In this pattern, we’ve covered and corrected a pattern for date input field to make users experience more pleasant on your website, thus leaving them with a good mood. This won’t push them away and eventually will bring you more happy potential customers.

Amazing legacy bug in Google Chrome!

Published on
Nov 22, 2011

So you thought Google Chrome is almost perfect, bullet-proof, iz-da-browser, and, what say you? Sure, it would be unfair, almost untrue to claim the opposite, however, there is a neat bug, and you could argue that it's not a bug but a feature, and I could argue back, and... you got it.

But since the people who wrote the Chrome are from Venus and Mars, just like you and me, their main belief is that user's experience should be comfortable, easy, and fun. You could think that I'm getting paid for this implicit advertisement, but I'm not. What they did to Chrome is this: they taught him to automatically fix errors that a programmer presumably created. And since they're awesome, all this error fixing is of course super fast, it's realtime.

The problem? Sure there's a problem. It goes like that: when you have written some Javascript code which updates the innerHTML with some, say, unclosed <table> element, at this point of time, the browser will fix that line, and add the closing tag somewhere at the end. But hey - you would say - what if I provide the innerHTML with the closing tag on the next line? Well, it's too late, because, Google Chrome is amazing.

element.innerHTML = '' + "Some text with or withot HTML tags "; element.innerHTML += "Another textual string with or withot HTML tags"; element.innerHTML += '

And with legacy code, things like these can take a long time to determine. Days. Weeks. Don't believe me? Try to hide this somewhere in your website and tell your friends about amazing bug, which happens only in Chrome, and, surprisingly, not in IEs. But luckily, there's this article, so we're safe. The solution? Well, you already guessed. If not, here it comes:

var long_string = '' + "Some text with or withot HTML tags "; long_string += "Another textual string with or withot HTML tags"; long_string += '
'; element.innerHTML = long_string;

In this case, the browser eats the whole thing like a creamy chocolate cake with a lot of ganache, and everybody's happy.

So if you don't think it's a bug, please debug. But if you think it is a bug, please don't debug. In any case, I will be happy if you leave a comment, because, well, why not?

Also, by this chance, I'd like to introduce you our new project, and it's called Open Website Project. It is a place where the good people (!!), or in other words professionals like you can find fellows, and build something different together or just discuss interesting topic.. It's small, almost private, and that's the big difference. So long.

Easy backup bash script

Published on
Aug 8, 2011

Here I'm showing you a simple script which dumps and stores any number of databases, then compresses them into tar.gz files.

The archived files will have unique names containing script's execution time. It should run an any Linux/Unix machine. This was written as a daily backup, it doesn't delete any previous backups, nor does it implement any incremental backup functionality. It just a simple script for your joy, so have fun.

!/bin/bash # # DB Backup script by webdesignpatterns.org # # modify the following to suit your environment export BKP_DIR="/path/to/your/backupsdir" # << Modify this - the directory of your backups. export DB_USER="root" # DB username export DB_PASSWD="*****password*****" # DB password databases=( "database_name_1" "database_name_2" "database_name_3" ) # an array - don't be shy to add more DBs here # Create archive filename. day=$(date +%m.%d.%Y) for i in "${databases[@]}" do archive_file="$i-$day.sql.tar.gz" echo "* Creating new backup..." mysqldump $i -u root -p$DB_PASSWD > $BKP_DIR/$i-$day.sql echo "* Archiving..." tar czf $BKP_DIR/$i-$day.sql.tar.gz $BKP_DIR/$i-$day.sql echo "* Removing raw files" rm $BKP_DIR/$i-$day.sql done echo "Done" exit 0

How to run it.

You'll have to copy the code and paste it into some file, say daily_backup.sh. Then put it into some directory, preferably into something like /etc/cron.daily/ which exists by default in Ubuntu for example. Please note: scripts in Ubuntu system in the /etc/cron.daily/ need to be without extensions. You can actually test which scrips will run by executing:

run-parts /etc/cron.daily --test


mv /etc/cron.daily/daily_backup.sh /etc/cron.daily/daily_backup

Now you'll have to say when to execute it, so:

sudo crontab -e


# m h dom mon dow command 40 07 * * * root run-parts /etc/cron.daily

Also give the relvant execution permissions to the script:

chmod uga+x /path/to/your/backupsdir/daily_backup.sh # /etc/cron.daily ?

This will execute everything in /etc/cron.daily each day at 7:40am. Next, naturally, you should restart your cron service like that:

sudo service cron restart

That's it.


Problems during Redmine installation on Ubuntu

Published on
Aug 5, 2011

Some patience is required to successfully install the Redmine. But some people are just like me - don't have it, especially when doing something for fun on their free time. If you encountered similar issues (and probably you did, if you googled for this article) - read next on how easily this can be fixed.

Generally, the errors appear when you try to execute

RAILS_ENV=production rake db:migrate checking for main() in -lnsl... yes checking for mysql_query() in -lmysqlclient... no checking for main() in -lmygcc... no checking for mysql_query() in -lmysqlclient... no *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options.

Then below some message appears about the missing i18n gem, but when you try to install it, another error tells in some way that you need to install mysql gem, maybe something like this:

# gem install mysql Fetching: mysql-2.8.1.gem (100%) Building native extensions. This could take a while... ERROR: Error installing mysql: ERROR: Failed to build gem native extension. /usr/bin/ruby1.8 extconf.rb checking for mysql_query() in -lmysqlclient... no checking for main() in -lm... yes checking for mysql_query() in -lmysqlclient... no checking for main() in -lz... no checking for mysql_query() in -lmysqlclient... no checking for main() in -lsocket... no checking for mysql_query() in -lmysqlclient... no

And as any good boy or girl, you're running these lines one after another, and then install the i18n gem, and then repeat the first problematic line.

apt-get install build-essential apt-get install libmysqlclient15-dev updatedb locate mysql_config gem install mysql -- --with-mysql-dir=/usr/bin/mysql_config # <-- well, the path of yours, from the previous line's output!

Now try:

RAILS_ENV=production rake db:migrate ~HTH

Steps towards the more ecological web development teams

Published on
Jul 24, 2011


Contemporary web technology is rapidly evolving together with the demand for online services and more attractive, more functional and faster websites are born. Some fifteen years ago, when the old yahoo.com looked approximately like most of the websites, and people were uneasy with the noisy sound of connecting modems, most of the websites were less interesting than they are now. Because today, it's even hard to find a website, where you will see "Under Construction" message with the same digging dude everywhere - a common practice in those times (why declaring that something is broken or not fully working?). But now everything virtually physical is available through the Internet - information services like news are easily accessed, every respectful business will happily provide all available data about their products and happily supply goods on your buying-request or will provide any relevant information. In this reality the competition dictates it’s own rules, and so the web technologies with qualified professionals and the demand for them -- all together evolve. With the growing demand grows the supply too. There are plenty of tools for web development, both free and non-free. There are lots of amazing designers, and plenty of charismatic salespeople who will promise you exactly what you want and/or need in exactly the right time, and if you’ll buy it right now you’ll get a "WOW" discount. All of that good stuff looks like the direct relation of the amount of money or professional time spent on the website, which is an indispensable service just like Bill Gates promised many years ago. How does one choose the right people, and the right technology when there is a plethora of them? How one doesn’t get lost in the completely foreign world? The short answer would probably be - you'll need some map that you can understand and trust and you won’t be lost. In this article, I’m going to start outlining such a map.

Typically there are several types of the websites, most of them sharing the same patterns and even same technologies. There are blogs, online stores, news websites, banks, brokerages, airports etc. It can be very tempting to think that the more you pay for it, the better you get. Sometimes this isn’t true. One of the possible reasons could be - is when you are dealing with non-professionals who claim that they are, subsequently they can’t approximate correctly the job to be done, and in the end whole project fails. So if you aren’t a web guru, who knows all the trends and at ease with all the modern advancements in the web area, it’s probably a good idea to adopt one as a guide. This guru should be familiar with all the points raised in this article, but if you want to control the situation yourself, you will find here the info you need.

Do your homework!

In order to make our map usable, let’s define the elements which it’s made of -- or, in other words, the elements of which the whole website building process consists.

What we need is to determine:

These are the key questions that should be answered before any attempt to buy a website, so let’s form them into a more extended and informative discourse.

What will be the content of your website.

To define a content, one needs to use functional words. The more details you bring into this description, the easier it will be to estimate the effort. For example, instead of telling something like: “I need a great online shop with a forum and cool front page”, one may rephrase this into something like: “The shop will have five main pages types, or categories. There will be products search, where the results will be no more than ten per page, and when clicking on any result, the user will be redirected to the product page. There will be Our Branches page, where the user will be able to click on any branch, and being redirected there. There will also be the informational pages - each of which should have a promotional full-page ad-like content with no functionality”. The latter description at best, should go down to the lowest-level details, such as where the search input text will be placed, and how it should look like. Don’t worry about defining the visual content if you’re missing graphical designer’s vocabulary. You can always make a snapshot from other websites for an illustrative example.

How to choose the right team and how to communicate with the members

This is true that one picture is worth ten thousand words. Similarly, one experience with a web agency is worth ten thousand recommendations. And It doesn’t really matter what others tell you about the virtues of company X. So where one gets this invaluable experience? A good approach is to have dedicated and responsible web guru who will be working closely and audit the progress of the project. Since any definition can be interpreted differently by any different people, it’s important to have a constant feedback, so the corrections would be instantly made. There is one website actually, which aims to ease on the web team creation process. But for now, steps should be taken, and hours spent on the planning.

Know your people. It should be the responsibility of a professional to look for a web team or agency, and learn about their expertise individually. This shouldn’t be too hard, since a typical web development team consisting of developers and designers can be as small as three-to-ten people. Asking them to show their portfolios may sound tempting, however practically it's of a little value. Instead, questions about technologies being used and how long it takes to complete Y are far more important. These questions unveil the expertise and abilities and allow learning about the creative approaches for problems solving that an individual may face and how he deals with unexpected difficulties. Additionally, the depth of knowledge of the fields of expertise may be very critical, especially when it’s desirable to write a clean and maintainable code, more on this sometime later.

To conclude, remember that you’re dealing with human beings. And as such, it doesn’t matter what we claim with big letters about ourselves. We may say that we are the best and would love to satisfy quickly your every request, but in fact, before all, we’re interested in being paid, we want a normal weekends rest and other usual things that you want. And yes, we all believe that we are the best, but you are the one to differentiate us. So please try to choose the right people before all, and then all of us will sleep better at nights! :-)

Using the graphical Open Source Software

Published on
May 31, 2011
The first extensive article about using the graphical OSS has combined some of the central experiences for beginners and more advanced users. The main purpose was not to compare OSS to the proprietary software in general, but rather to "put it all together on the map", exactly where it belongs. Another goal was to show to the developers and artists amongst (or not amongst) them how gOSS is rich of great tools, easily available for installation. There are many links to software, galleries. You'll find a few interesting works some interesting artists who prefer using OSS. You won't find there any promise that this is exactly for you, but your curiosity will be at least partially satisfied :-). So enjoy!

Quick images uploader for your blog. A real time saver!

Published on
Feb 13, 2011

Laziness is the ultimate locomotive of the Progress. Many times I realize that I need a much simpler and more efficient image uploading mechanism, simpler than the regular and annoying file dialog, and even easier than an FTP client. That's why I wrote the script below. You can just copy-paste it into your new python file, name it like upload_image.py. The script asked me to allow him to explain to you about what he's doing, and I gladly agreed with him, so what's following next - is his own explanation of the process.

Let's say my owner has a small food blog, such as this one. For each post, there can be from one to an infinite number of images. To reduce the image size, my owner needs to reduce the jpegs' sizes using, for example, the neatest David's Batch Processor. The owner is a lazy user who always leaves the minimized images in the same directory with the originals (don't ask, they sometimes think that 'directory' is a bad word). Now the jpegs' sizes are all around 45k-50k, but I want to reduce them even more (bandwidth is my other friend). I run exiv2 rm *.jpg, which removes all the thumbnails and other unneeded data from images, and now they're just as small as I wanted them to be. Then, I move the original files into another directory on the same level as the original directory, make a gzip archive and upload it: I connect to the server, go to the images directory and unzip the archive, with the containing directory. I also output some tags, so my owner would just copy-paste them into his html editor, or whatever this person has there.

As you can see, I have some settings, and to use me you should change things like username, port etc., there aren't much. And you can run me from command line by typing

python upload_pics.py -d path/to/the/images/directory

I'll ask you for your remote server password if you don't mind. Oh, and you'll need to install all the required libs which I have in the #import declaration - but only if you don't have them already.. Just select them from Synaptic or something. And please have exiv2 installed as well. That's quite it. And, hee-hee, you know, you can't ask me question, because I'm just a script so, use me, and drink more beer on your free time.

#!/usr/bin/env python
# By Val Kotlarov @webdesignpatterns.org

# This will upload files and extract them. 

import base64, getpass, os, socket, sys, traceback, tarfile, getopt, paramiko, shutil
import pyexiv2

# settings go here
username = 'username'		# change with your username
port = 22					# your connection's port number, 22 is the default
hostname = 'example.com'	# change with domain or static ip address
remote_images_directory = '/path/to/your/images/directory/'	# set to where the images directory is
max_file_size = 150000		# maximum size in bytes for images to be papcked and uploaded
remote_upload_file_path = remote_images_directory+'upload.tar.gz'
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
# end settings

# get files in directory which are greater than given size in bytes
def listDirectory(directory, minFileByteSize):                                        
    "get list of file info objects for files of particular extensions" 
    fileList = [os.path.join(directory, os.path.normcase(f))
                for f in os.listdir(directory)]             
    #filter by file size
    fileList = [f
               for f in fileList
                if os.path.getsize(f) > minFileByteSize]
    return fileList

    opts, args = getopt.getopt(sys.argv[1:], "d:v", ["help", "output="])
except getopt.GetoptError, err:
    # print help information and exit:
    print str(err) # will print something like "option -a not recognized"

input_dir = None     # the directory to be uploaded
for o, a in opts:
    if o in ("-d", "--directory"):
        input_dir = a
        assert False, "unhandled option"

# setup logging

# move big files to a new directory on the same level
big_files = listDirectory(input_dir, max_file_size)		# ~150k
if big_files != []:
    os.mkdir(input_dir + '_big')
    for f in big_files:
      shutil.move(f, input_dir + '_big/'+os.path.basename(f))

#print html for images
files = listDirectory(input_dir, 0)	
for f in files:
   print ''

# remove exiv info
os.system("exiv2 rm " + input_dir  + "/*.jpg")

# store into tar file, having the archive's directory name
tar = tarfile.open(input_dir + "/upload.tar.gz", "w:gz")

# add this directory and its contents, without path to it!
tar.add(input_dir, arcname=os.path.basename(input_dir), recursive=True)		

# get host key, if we know one
hostkeytype = None
hostkey = None
    host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
        # try ~/ssh/ too, because windows can't have a folder named ~/.ssh/
        host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
    except IOError:
        print '*** Unable to open host keys file'
        host_keys = {}

if host_keys.has_key(hostname):
    hostkeytype = host_keys[hostname].keys()[0]
    hostkey = host_keys[hostname][hostkeytype]
    print 'Using host key of type %s' % hostkeytype

# now, connect and use paramiko Transport to negotiate SSH2 across the connection
    t = paramiko.Transport((hostname, port))
    t.connect(username=username, password=password, hostkey=hostkey)  
    sftp = paramiko.SFTPClient.from_transport(t)
    # upload
    print 'Inside directory: ' + input_dir
    sftp.put(input_dir+'/upload.tar.gz', remote_upload_file_path) 
    print 'Uploaded file'
    ch = t.open_channel(kind = "session")
    ch.exec_command('cd '+ remote_images_directory+' && tar xzf upload.tar.gz')

    print 'Finished.'

except Exception, e:
    print '*** Caught exception: %s: %s' % (e.__class__, e)

A Quick Sketch of the Ideal Drupal Site Planning

Published on
Jan 16, 2011
Here's a bunch of personal observations for a more effective team collaboration in working environments.

Block - based theming