admin

Strongly typed Languages and Security. From Schneier on Security.
A Great comment I believe it’s worth sharing. Source http://www.schneier.com/blog/archives/2010/10/firesheep.html#c478900


I can’t agree more that the average quality of programmers (and therefore reusable components) is miserable. Code reuse can be very messy and anyone serious about quality is forced to reinvent the wheel over and over.

Of course I also agree that not all standards are good, as I don’t consider the web’s standards good.

However, there are fake high level languages and real high level languages. You cannot really build a complex system in a low level language, and even if you did, it would be full of abstractions, effectively making it a high level language via design patterns.

Look at PHP, it’s a horrible mess, a big ball of crap thrown together to make a “framework” to “ease” web development. The developers don’t have a clue what they’re doing and there are lots of new vulns in it every month at both the high and low levels. The builtin functions are completely inconsistent, some things return magic values and some things raise exceptions. PHP just takes random features from other languages and piles them together in an incoherent way. PHP is weakly typed (which is _always_ useless and causes more bugs). PHP is configurable, different libraries depend on different configurations of it. PHP has a garbage optional security model thing called safe-mode, which doesn’t work as it’s just more crap incoherently thrown together.

Now look at a real high level language, like Haskell, everything is immutable, which immediately mitigates one of the big class of bugs. Lazy evaluation means everything is more efficient most of the time (most problems are best solved lazily), but can be turned off when needed. The type system tells you all the information you’d ever want to know about the architecture of a given program, as well as catches _lots_ of bugs up front. Functions can easily be reasoned about due to type safety and immutability. This is a language that was actually thought out, unlike PHP.

Also, there are capability-secure languages/OSs, such as E (language), where security is orthogonal and forces the principle of least authority upon the entire architecture from the ground up. They have already been proven easy to use (obviously, much easier to use than any *nix crap because they have strong typing and aren’t C) and exponentially more secure. E is basically reifies one of the things computing is meant to have but doesn’t currently: you can run any code without caring if it’s evil or crappy. Sort of like the web but not completely flawed/unusable/insecure. The capability model also stop programs from dumping random garbage all over your OS, which is what happens on *nix and Windows.

Did I mention POLA is important? Why one would ever want to run random code off the internet with full privileges is beyond me. Java has an actual _half_ decent security/object model BTW, but it was ruined by pragmatism, and now everyone just signs their applets and the users can’t run them unless they modify their JVM or allow the code to run with full privileges.

Heck, even QNX is vastly superior to *nix just because they took a few old academic ideas into practice.

But what I really want to get down to is that strong typing is mandatory. (Strong typing in the data sense as well as language).

What I mean by strong typing in the data level is that you don’t take a bunch of random text and try to interpret it. You don’t take a bunch of machine words off the stack/heap and try to interpret them. Data must be organized mechanically, never trust the human.

Stack smashing happens because of lack of strong typing; array’s don’t really exist, you just get pointers to memory and are free to do anything with them, integers don’t exist either, you just have machine words. Actually nothing exists because C is just one crappy abstraction with a ton of undefined behavior. Strongly typed arrays cannot be violated, nor can ints etc. C is another example of this nonsense re-usability notion, to make it “fast”, _as well_ as portable, it has to have tons of undefined behavior. A secure system would have a high level language and the underlying low level components would be written in a way specialized to that architecture, in which case you can get performance as well as **no** undefined behavior.

XSS is because of lack of strong typing, you are just taking a bunch of text and blindly treating it as code or crap to inject into some text that is meant to be code. This is about as unreliable as it gets. Strongly typed declarative data structures prevent this.

SQL Injection? Ditto. But has been solved by A) ORMs that aren’t vulnerable B) Object databases (which are on par and sometimes better than RDBMS with respect to performance, BTW) C) HaskellDB ;)

HTTP injection? Well this doesn’t happen as much because one typically uses a safe API to build the HTTP request as opposed to editing it and parameterizing it by hand. This is analogous to using a safe API to manipulate a binary data structure (that is strongly typed). Hey? Binary is compact and efficient, then why do we have text protocols and formats? Oh yeah, someone thought it would be a good idea to have plaintext stuff because maybe we would be able to edit it by hand or something. BS. Do they expect us to edit 20MB XML documents by hand? You should be using a graph editor that provides a set of idiomatic transforms and queries (does this exist for XML? it should.). The only time you can edit _any_ plaintext document by hand is when it’s tiny, except this still doesn’t work because you don’t know what character set encoding to use… XML sucks, it’s not a cyclic graph so you have to retype things instead of just putting a reference to them, or invent an ad-hoc way of doing this for your schema. This is clearly propagated by the “simple” design of plaintext XML, if it were binary, they probably would have just made a real cyclic graph. This stuff also reminds me of another major issue with *nix, everything is a file (which is nonsense, everything should be an object, or maybe there is something better? I dunno, but objects are already superior to files in every way. Want streams? read: lazy evaluation), which for some reason, means everything is text with an arbitrary grammar, so you have to write a ton of regular expressions to get anything done in *nix. Ooh and you have magic numbers as return values from programs. Except these both break all the time as new versions of the programs come out. And they are a bitch to fix because they aren’t objects; you have to rewrite the parsers (text) instead of using the new fields (objects). Even the input to any *nix program is braindead and violates strong typing principles so they can’t be used without causing new vulnerabilities. Even if you escape the input to make it safe for bash or whatever shell you are using, the data within that parameter might still need to be further escaped because it’s passed as an SQL string or some other weakly typed system. I don’t know why “command line” mantra even exists anymore (now that we don’t use ancient terminal things anymore, well some people do, but not me at least), every program that has an interactive bash shell thing is different and crappy and has no multiline input and a lot of them overwrite your input as you’re typing it with output. Command line apps shouldn’t exist, there should just be objects that you invoke methods on with a _real_ (bash isn’t a real language) statically strongly typed language and get back some other objects. Static typing allows *rich* auto-completion for free. The shell can infer the variables in the local namespace that match the input parameter you are on, and then suggest them all. And the shell should actually be a decent thing, not a stupid pair of I/O streams. *nix terminal things suck **hard**. If you copy and paste some text from a web page, it might contain malicious code followed by a newline (a page can make you copy something other than what is displayed and highlighted on it), and you get owned. Oooh, oooh, X11 is also broken, it doesn’t let non-you users display to a constricted area on it, so you have to run random crap programs off the internet as you, and they get to steal all your non-root stuff (the stuff that *actually* matters). But they get root by ptracing your bash shell and escalating to root the next time you sudo or su. The Qubes OS tries to fix some of this stuff, but fails miserably, because it’s not even as good as or better than the Object Capability Model, which was invented decades ago, but I guess this is because they want compatibility with current software, which means they have to diminish security. Maybe they would be better off joining Tunes.

Computing sucks hard for many other reasons, but I’m getting tired of writing for now and am hungry.

What does this all have to do with firesheep? Dunno, but it’s not surprising what firesheep can do, and it’s about time someone is stepping up and trying to expose more loudly one of the many critical flaws that have been being used for malicious purposes for the past decades. I predict the next movement is for someone to write a nice metamorphic virus and take over hundreds of millions of boxes on the internet and all those crappy embedded devices. (It’s not that hard to pull off.)

Anyone interested in creating a secure computing paradigm and ditch all this other nonsense? Call me.

VN:F [1.9.13_1145]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)

I had to setup AFP (netatalkd) on a centos 5.5 machine. Many tutorials had something missing. so I took the best of each and put here.

You will need gcc and some packages/libs for building berk-db and netatalkd, like “patch” and “make”

  yum install openssl.x86_64 libssl-dev gcc automake autoconf GSSAPI libgssapi-devel libgssapi  libgssapi-devel krb5-devel pam-devel shadow-devel openssl-devel cracklib wget

1. Download the latest berkeley-db 4.8 (5.0 and 5.1 did not work for me), compile and install

wget http://download.oracle.com/berkeley-db/db-4.8.30.tar.gz
tar xpf db-4.8.30.tar.gz
cd db-4.8.30/build_unix/
../dist/configure
make
make install

2. Download latest netatalkd, compile, install and copy config files to /etc/atalk
AFP works fine with the default configuration files.

wget "http://downloads.sourceforge.net/project/netatalk/netatalk/2.1.5/netatalk-2.1.5.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fnetatalk%2F&ts=1293643408&use_mirror=biznetnetworks"
tar xpf netatalk-2.1.5.tar.bz2
cd netatalk-2.1.5

./configure --enable-redhat --enable-pgp-uam --enable-krb4-uam --enable-krbV-uam --with-bdb=/usr/local/BerkeleyDB.4.8/
make
make install
mkdir -p /etc/atalk/
cp -a config/*.conf /etc/atalk/
chkconfig netatalk on
service netatalk start

Extra:

When you mount this filesystem on mac, all files and directory permissions will be reset to 755, which is really annoying, specially if you use git. Git will show all the file permission changes to 755 instead of 644 for files.

so, to solve the problem edit the file /etc/atalk/AppleVolumes.default and update the last line on the file

  vi /etc/atalk/AppleVolumes.default
  # change from
    :DEFAULT: options:upriv,usedots
  # to
    :DEFAULT: options:upriv,usedots dperm:0755 fperm:0644

Resources:

VN:F [1.9.13_1145]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)

This is a monit recipe for a rails app with 4 Unicorn threads using SOCKET. The app averages a total memory usage of 600 MB.
If it goes over 800 MB send email alert only.
If over 860 MB, reload the app.
Also if it’s using too much CPU, alert by email.

I use unicorn_rails on socket mode with nginx, and preload_app = true.

check process myapp_unicorn
  with pidfile /var/www/apps/my_app.com/shared/pids/unicorn.pid
group unicorn
if totalmem > 800 MB for 2 cycles
  then alert
if totalmem > 860 MB for 2 cycles
  then exec "kill -HUP `cat /var/www/apps/my_app.com/shared/pids/unicorn.pid`"
if cpu > 40% for 2 cycles then alert
if cpu > 20% for 4 cycles then alert
if failed
  unixsocket /var/www/apps/my_app.com/shared/pids/unicorn.sock
  then alert

note: the HUP signal will reload the children processes without reloading code changes. This is fast and desirable.

Resources:
http://unicorn.bogomips.org/SIGNALS.html
http://mmonit.com/monit/documentation/monit.html

VN:F [1.9.13_1145]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)

UPDATE: New version for OS X Lion HERE

I choose the simple and I believe clean way to use everything from macports and passenger.

The advantage is that it’s all isolated from the OS X system and using latest cutting edge version of softwares.

I assume you have textmate, because it’s easy to edit files that need sudo access. Textmate will just ask for your password.

Try and download the 30 days trial for easy of this tutorial. http://macromates.com/

Trust me, you will love Textmate, it’s state of the art editor.

ps: I use “mate” instead of “open -a TextMate” but not everyone might have the mate symlink.

Requirements:

  • Snow Leopard 10.6.4 or greater
  • Xcode 3.2.3, 2.4.1 or greater
  • Admin privileges on your mac.

Software preliminary:

  • Mysql 5.1.49 (macports)
  • Ruby 1.8.7 (macports)
  • Apache 2.2.9 (part of OS X)
  • Rubygems (download)
  • passenger (gem)
  • ImageMagick
  • rmagick

1. Preparing System

If you are upgrading from Leopard to Snow Leopard, I recommend you delet your old installation.

sudo rm -rf \
    /opt/local \
    /Applications/DarwinPorts \
    /Applications/MacPorts \
    /Library/LaunchDaemons/org.macports.* \
    /Library/Receipts/DarwinPorts*.pkg \
    /Library/Receipts/MacPorts*.pkg \
    /Library/StartupItems/DarwinPortsStartup \
    /Library/Tcl/darwinports1.0 \
    /Library/Tcl/macports1.0 \
    ~/.macports

1.1 Prepare PATH environment:

$ open -a TextMate ~/.bash_profile

Edit your ~/.bash_profile file and add these 2 line.
Check if they are not there already.

export PATH=/opt/local/bin:/opt/local/sbin:$PATH
export MANPATH=/opt/local/share/man:$MANPATH

1.2 Download and Install Xcode

http://developer.apple.com/technologies/xcode.html

1.3 Download Macports and install

Download Page: http://www.macports.org/install.php

Download Direct Link: http://distfiles.macports.org/MacPorts/MacPorts-1.9.2-10.6-SnowLeopard.dmg

You might use this guide for installing Macports:

Full Install Guide: http://guide.macports.org/#installing

1.3.1 Update macports

sudo port -v selfupdate

2. Mysql

2.1 Intall Mysql

sudo port -v install mysql5-server mysql5

2.2 Make mysql autoload on startup

sudo port load mysql5-server
sudo -u mysql mysql_install_db5

3. Memcached (Optional)

sudo port -v install memcached libmemcached

3.1 Autoload memcached on startup

sudo port load memcached

4. Ruby, Rubygems, Rails, other gems

4.1 Install Ruby from macports

sudo port -v install ruby
$ ruby -v
ruby 1.8.7 (2010-08-08 patchlevel 302) [x86_64-darwin10]

4.2 download rubygems from http://rubygems.org/pages/download

cd /tmp
wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz
tar xpf rubygems-1.3.7.tgz
cd rubygems-1.3.7
sudo ruby setup.rb

4.3 Install rails, rake, rspec etc.

sudo gem install rake rails thin tzinfo capistrano ruby-debug rspec

extra:

4.4 install mysql gem

sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config

5. ImageMagick, Rmagick and mini_magick (Optional)

lets install ImageMagick with support for JPEG, TIFF, WMF, PDF, and PNG images, and for Postscript and TrueType fonts.

sudo port -v install tiff -macosx imagemagick +q8 +gs +wmf
sudo gem install mini_magick rmagick

Test rmagick

$ irb -rubygems -r RMagick
>> puts Magick::Long_version
This is RMagick 2.13.1 ($Date: 2009/12/20 02:33:33 $) Copyright (C) 2009 by Timothy P. Hunter
Built with ImageMagick 6.6.3-0 2010-08-19 Q8 http://www.imagemagick.org
Built for ruby 1.8.7
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org
=> nil

6. Passenger

6.1 Install Passenger gem

sudo gem install passenger

6.2 Check Passenger path

passenger-config --root
 -> /opt/local/lib/ruby/gems/1.8/gems/passenger-2.2.15

6.3 Build passenger for apache

follow instructions on screen

sudo passenger-install-apache2-module

6.4 Enable Passenger on apache:

open -a TextMate /etc/apache2/extra/httpd-passenger.conf

Put this on that file, change wherever necessary for your directories.

LoadModule passenger_module /opt/local/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.2.15
PassengerRuby /opt/local/bin/ruby
PassengerMaxPoolSize 6  # maximum global rails servers
PassengerMaxInstancesPerApp 2  # maximum rails servers per application
RailsFrameworkSpawnerIdleTime 1800
RailsAppSpawnerIdleTime 600
PassengerPoolIdleTime 600
PassengerMaxRequests 1000  # after 1000 requests will restart server, to skip memory leak :)
 
# Enabling NameBased Virtualhost
NameVirtualHost *:80
 
# my rails app virtual host 1
<VirtualHost *:80>
    ServerName my-rails-app.local
    DocumentRoot "/Users/fred/rails/my-rails-app/public" # change this to match your folder
    RailsEnv "development"
   <Directory /Users/fred/rails/my-rails-app/public>
        # change this to match your folder
        # MultiViews must be turned off
        Options -MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
    # logs are optional, change this to match your folder
    CustomLog  "/Users/fred/rails/my-rails-app/log/access_log" combined
    ErrorLog   "/Users/fred/rails/my-rails-app/log/error_log"
</VirtualHost>
 
# my rails app virtual host 2
<VirtualHost *:80>
    ServerName myapp-xyz.local
    DocumentRoot "/Users/fred/rails/myapp-xyz/public"  # change this to match your folder
    RailsEnv "development"
    <Directory /Users/fred/rails/my-rails-app/public>
        # change this to match your folder
        # MultiViews must be turned off
        Options -MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
    CustomLog  "/Users/fred/rails/myapp-xyz/log/access_log" combined
    ErrorLog  "/Users/fred/rails/myapp-xyz/log/error_log"
</VirtualHost>

6.5 Enable Virtual host on apache:

open -a TextMate /etc/apache2/httpd.conf

Add this new line at the bottom:

# Include Passenger ModRails config file
Include /private/etc/apache2/extra/httpd-passenger.conf

6.6 Add your .local domain to /etc/hosts/

open -a TextMate /etc/hosts

Add this line to that file and change to the name of your choosen application

You might add as many as you want, each line for each that ServerName on your VirtualHost blocks

127.0.0.1 my-rails-app.local
127.0.0.1 myapp-xyz.local

I have more than 50 .local apps in there.

5 Start Apache

first let’s test apache configuration:

apachectl configtest

if you get “Syntax OK” then you are ready to start it

sudo apachectl start

If you want Apache to autostart when you boot your computer,
then enable Web Sharing from preferences.

7. Final

go to your browser and open the url of your application http://my-rails-app.local

If it works, congratulations.

If didn’t work, let me know here in the comments.

Extras

Nokogiri

  sudo port -v install libxml2 libxslt
  sudo gem install nokogiri -- --with-xml2-include=/opt/local/include/libxml2 --with-xml2-lib=/opt/local/lib --with-xslt-dir=/opt/local

Sqlite

sudo port install sqlite3
sudo gem install sqlite3-ruby

9. Sphinx, thinking-sphinx, sphinxsearchlogic

sudo port install sqlite3
sudo gem install thinking-sphinx sphinxsearchlogic

Update:

From the comments, some people might want to enable php and your Sites folder.

To be able to enable php and others you will have to enable another default vhost with localhost as servername.

Edit the file /etc/apache2/httpd.conf to enable vhosts

# Virtual hosts
Include /private/etc/apache2/extra/httpd-vhosts.conf

then open /private/etc/apache2/extra/httpd-vhosts.conf file,
delete or comment everything from there and add this block only:

#
# Use name-based virtual hosting.
#
NameVirtualHost *:80
 
# Change /Users/fred/ to your appropriate login name
<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /Users/fred/Sites/
    RewriteEngine On
    DefaultType text/html
    <Directory "/Users/fred/Sites">
        DefaultType text/html
        Options +ExecCGI FollowSymLinks Indexes
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

Links and Resources

http://rmagick.rubyforge.org/install-osx.html

http://wiki.github.com/tenderlove/nokogiri/what-to-do-if-libxml2-is-being-a-jerk

http://www.macports.org/install.php

http://guide.macports.org/#installing

http://distfiles.macports.org/MacPorts/MacPorts-1.9.1-10.6-SnowLeopard.dmg

http://rob.by/2009/installing-mysql-via-macports-on-snow-leopard-for-ruby-development/

http://macromates.com/

http://github.com/joost/sphinxsearchlogic

http://www.sphinxsearch.com/

VN:F [1.9.13_1145]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)

This command will create an encrypted image on mac OS X that will grow as you need it.
Since I could not find anywhere on the net, I dig on the hdiutil man page and wrapped the command.

The image starts with about 600MB in size, which is not wasted actually.

I use this image to backup my sensitive data such as servers config files, mysql databases and repositories.
I set it to use AES 128bit encryption.
Case-sensitive, because Linux fs are Case-sensitive by default. If you don’t set it Case-sensitive you cannot use for linux backups.

hdiutil create -encryption AES-128 -stdinpass -fs “Case-sensitive HFS+” -type SPARSE -nospotlight -volname Servers Servers

it will create a file named Servers.sparseimage

VN:F [1.9.13_1145]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)

Now a days there are so many good and cheap OpenVZ VPS providers out there.
Just have a look at this blog and you will see what I mean. [http://www.lowendbox.com/tag/openvz/]

The way OpenVZ virtual machines offers RAM resource is quite different from XEN.
You get Dedicated Ram (guaranteed ram) and Burstable Ram.

Burstable Ram is good when your server has sporadic load spikes, such as blogs and news sites.
Ideally you should not rely on burstable ram, it depends on the Host System. if the host system starts get low on free ram, you will lose that memory and the kernel will kill your processes to recover the ram.

Best is to keep below 90% of your Dedicated ram.

So, here I have an script that will monitor your memory limits. Also check for errors on your openVZ.
it’s perfect for an hourly cron job. It will print output on warnings and errors only.
Will suppress output if your openVZ container is behaving well. :)

for example, put on /etc/cron.hourly/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env ruby
#
# Program to check for failed count on OpenVZ systems
#   Failed counts indicate over commit on memory. 
#   it should always be zero.
 
 
@file = `cat /proc/user_beancounters`.split("\n")
 
# Delete the first 3 lines, which are irrelevant to us.
@file.delete_at(0)
@file.delete_at(0)
@file.delete_at(0)
 
@failcnt = []
 
@file.each do |t|
  tmp = t.split
  unless tmp.last == "0"
    @failcnt << tmp
  end
end
 
# Check that 'held' is less than 'barrier' 
#   held = current count
#   barrier = soft limit
# only checking for:
#   privvmpages @file[1] 
#   oomguarpages @file[7] 
# 
# oomguarpages : 
#   The out-of-memory guarantee, in pages. 
#   Any VE process will not be killed even in case of heavy 
#   memory shortage if the current memory consumption 
#   (including both physical memory and swap) 
#   does not reach the oomguarpages barrier.
#
# privvmpages: 
#  The size of private (or potentially private) memory allocated by an application. 
#  The memory that is always shared among different applications 
#  is not included in this resource parameter.
# 
# Sources: 
#  - http://wiki.openvz.org/UBC_secondary_parameters
#  - http://wiki.vpslink.com/Meaning_of_the_/proc/user_beancounters_Values
 
privvmpages = @file[1].split
privvmpages_current = privvmpages[1].to_i
privvmpages_limit = privvmpages[3].to_i
if privvmpages_current > privvmpages_limit
  puts "WARNING: #{privvmpages[0]} has passed the limit: #{privvmpages_current}/#{privvmpages_limit}"
  puts "WARNING: Server may crash or reboot"
end
# Also check it we are getting close to 70% of usage
privvmpages_pc = ((privvmpages_current.to_f/privvmpages_limit)*100).ceil
if privvmpages_pc > 70
  puts "WARNING: #{privvmpages[0]} is high: #{privvmpages_pc}% of limit"
end
 
oomguarpages = @file[7].split
oomguarpages_current = oomguarpages[1].to_i
oomguarpages_limit = oomguarpages[3].to_i
if oomguarpages_current > oomguarpages_limit
  puts "WARNING: #{oomguarpages[0]} has passed the limit: #{oomguarpages_current}/#{oomguarpages_limit}"
  puts "WARNING: Some Processes may be killed"
end
# Also check it we are getting close to 85% of usage
oomguarpages_pc = ((oomguarpages_current.to_f/oomguarpages_limit)*100).ceil
if oomguarpages_pc > 85
  puts "WARNING: #{oomguarpages[0]} is high: #{oomguarpages_pc}% of limit"
end
 
unless @failcnt.empty?
  puts "=================================="
  puts "Found Memory problems with OpenVZ:"
  puts "=================================="
  @failcnt.each do |t|
    puts "#{t.join(' - ')}"
    puts "=================================="
  end
end
VN:F [1.9.13_1145]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)

© 2012 Ruby, Rails, OSX and Linux fun Suffusion theme by Sayontan Sinha

Switch to our mobile site