Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS 

Ini file parser and writer

This file provides a read-wite handling for ini files. The data of a ini file is represented by a object which is populated with strings.

#
# ini.rb - read and write ini files
#
# Copyright (C) 2007 Jeena Paradies
# License: GPL
# Author: Jeena Paradies (info@jeenaparadies.net)
#
# == Overview
#
# This file provides a read-wite handling for ini files.
# The data of a ini file is represented by a object which
# is populated with strings.

class Ini
  
  # Class with methods to read from and write into ini files.
  #
  # A ini file is a text file in a specific format,
  # it may include several fields which are sparated by
  # field headlines which are enclosured by "[]".
  # Each field may include several key-value pairs.
  #
  # Each key-value pair is represented by one line and
  # the value is sparated from the key by a "=".
  #
  # == Examples
  #
  # === Example ini file
  #
  #   # this is the first comment which will be saved in the comment attribute
  #   mail=info@example.com
  #   domain=example.com # this is a comment which will not be saved
  #   [database]
  #   db=example
  #   user=john
  #   passwd=very-secure
  #   host=localhost
  #   # this is another comment
  #   [filepaths]
  #   tmp=/tmp/example
  #   lib=/home/john/projects/example/lib
  #   htdocs=/home/john/projects/example/htdocs
  #   [ texts ]
  #   wellcome=Wellcome on my new website!
  #   Website description = This is only a example. # and another comment
  #
  # === Example object
  #
  #   A Ini#comment stores:
  #   "this is the first comment which will be saved in the comment attribute"
  #
  #   A Ini object stores:
  #
  #   {
  #    "mail" => "info@example.com",
  #    "domain" => "example.com",
  #    "database" => {
  #     "db" => "example",
  #     "user" => "john",
  #     "passwd" => "very-secure",
  #     "host" => "localhost"
  #    },
  #    "filepaths" => {
  #     "tmp" => "/tmp/example",
  #     "lib" => "/home/john/projects/example/lib",
  #     "htdocs" => "/home/john/projects/example/htdocs"
  #    }
  #    "texts" => {
  #     "wellcome" => "Wellcome on my new website!",
  #     "Website description" => "This is only a example."
  #    }
  #   }
  #
  # As you can see this module gets rid of all comments, linebreaks
  # and unnecessary spaces at the beginning and the end of each
  # field headline, key or value.
  #
  # === Using the object
  #
  # Using the object is stright forward:
  #
  #   ini = Ini.new("path/settings.ini")
  #   ini["mail"] = "info@example.com"
  #   ini["filepaths"] = { "tmp" => "/tmp/example" }
  #   ini.comment = "This is\na comment"
  #   puts ini["filepaths"]["tmp"]
  #   # => /tmp/example
  #   ini.write()
  # 
  
  #
  # :inihash is a hash which holds all ini data
  # :comment is a string which holds the comments on the top of the file
  #
  attr_accessor :inihash, :comment

  #
  # Creating a new Ini object
  #
  # +path+ is a path to the ini file
  # +load+ if nil restores the data if possible
  #        if true restores the data, if not possible raises an error
  #        if false does not resotre the data
  #
  def initialize(path, load=nil)
    @path = path
    @inihash = {}
    
    if load or ( load.nil? and FileTest.readable_real? @path )
      restore()
    end
  end
  
  #
  # Retrive the ini data for the key +key+
  #
  def [](key)
    @inihash[key]
  end
  
  #
  # Set the ini data for the key +key+
  #
  def []=(key, value)
    raise TypeError, "String expected" unless key.is_a? String
    raise TypeError, "String or Hash expected" unless value.is_a? String or value.is_a? Hash
    
    @inihash[key] = value
  end
  
  #
  # Restores the data from file into the object
  #
  def restore()
    @inihash = Ini.read_from_file(@path)
    @comment = Ini.read_comment_from_file(@path)
  end
  
  #
  # Store data from the object in the file
  #
  def update()
    Ini.write_to_file(@path, @inihash, @comment)
  end

  #
  # Reading data from file
  #
  # +path+ is a path to the ini file
  #
  # returns a hash which represents the data from the file
  #
  def Ini.read_from_file(path)
        
    inihash = {}
    headline = nil
    
    IO.foreach(path) do |line|

      line = line.strip.split(/#/)[0]
      
      # read it only if the line doesn't begin with a "=" and is long enough
      unless line.length < 2 and line[0,1] == "="
        
        # it's a headline if the line begins with a "[" and ends with a "]"
        if line[0,1] == "[" and line[line.length - 1, line.length] == "]"
          
          # get rid of the [] and unnecessary spaces
          headline = line[1, line.length - 2 ].strip
          inihash[headline] = {}
        else
        
          key, value = line.split(/=/, 2)
          
          key = key.strip unless key.nil?
          value = value.strip unless value.nil?
          
          unless headline.nil?
            inihash[headline][key] = value
          else
            inihash[key] = value unless key.nil?
          end
        end        
      end
    end
    
    inihash
  end
  
  #
  # Reading comments from file
  #
  # +path+ is a path to the ini file
  #
  # Returns a string with comments from the beginning of the
  # ini file.
  #
  def Ini.read_comment_from_file(path)
    comment = ""
    
    IO.foreach(path) do |line|
      line.strip!
      break unless line[0,1] == "#" or line == ""
      
      comment << "#{line[1, line.length ].strip}\n"
    end
    
    comment
  end
  
  #
  # Writing a ini hash into a file
  #
  # +path+ is a path to the ini file
  # +inihash+ is a hash representing the ini File. Default is a empty hash.
  # +comment+ is a string with comments which appear on the
  #           top of the file. Each line will get a "#" before.
  #           Default is no comment.
  #
  def Ini.write_to_file(path, inihash={}, comment=nil)
    raise TypeError, "String expected" unless comment.is_a? String or comment.nil?
    
    raise TypeError, "Hash expected" unless inihash.is_a? Hash
    File.open(path, "w") { |file|
      
      unless comment.nil?
        comment.each do |line|
          file << "# #{line}"
        end
      end
      
      file << Ini.to_s(inihash)
    }
  end
  
  #
  # Turn a hash (up to 2 levels deepness) into a ini string
  #
  # +inihash+ is a hash representing the ini File. Default is a empty hash.
  #
  # Returns a string in the ini file format.
  #
  def Ini.to_s(inihash={})
    str = ""
    
    inihash.each do |key, value|

      if value.is_a? Hash
        str << "[#{key.to_s}]\n"
        
        value.each do |under_key, under_value|
          str << "#{under_key.to_s}=#{under_value.to_s unless under_value.nil?}\n"
        end

      else
        str << "#{key.to_s}=#{value.to_s unless value2.nil?}\n"
      end
    end
    
    str
  end
  
end

simple backup PHP application (php files + mysql db)

// backup a folder contains all .php files and it's mysql database. a backup.ini file is required for storing mysql root login and what folder to be backed up.

#!/bin/sh

########################################
# simple sctipt for daily / hourly backup of PHP app + Mysql DB
# Copyleft (c) Sayid Munawar. chenull@yahoo.com
# LICENSE: anyone can copy / modify / distribute. whatever lah
#
# example of workhours backup (8 am - 5 pm. Mon - Fri)
# 0 8-17 * * 1-5 /home/backup/backup.sh
#
# example of simple dayly backup ( 6 pm. Mon - Fri)
# 0 18 * * 1-5 /home/backup/backup.sh
########################################

########################################
# example of backup.ini. REMOVE ALL leading '#'s
# file must be chmod 600
#[main]
#target = /home/backup/storage
#mysql_user = root   ; root can connect to any db
#mysql_pass = secret ; mysql root password
#
#[hukum]
#path = /home/hukum
#mysql_db = hukum
#
#[phpmyadmin]
#path = /home/phpmyadmin
#mysql_db = test
########################################

PATH=$PATH:/usr/bin:/bin:/usr/local/bin

inifile=`dirname $0`/backup.ini

test ! -r $inifile && echo "ERROR! backup.ini not found nor readable" && exit 1

#test apakah backup.ini bisa dibaca orang lain
echo -n `stat -c '%a' $inifile` | grep -q '[0-7]00' >/dev/null 2>&1
test $? -gt 0 && echo "ERROR! $inifile can be read by others" && exit 2
#test `stat -c '%U' $inifile` != 'root' && echo "ERROR! $inifile ownernya bukan root" && exit 3

# function to parse ini file (backup.ini)
#
# $1 -> file.ini
# $2 -> section
_parse_ini () {
    if [ -z "$1" ] || [ -z "$2" ]; then return 0; fi
    eval `cat $1 | \
       sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
           -e 's/;.*$//' \
           -e 's/[[:space:]]*$//' \
           -e 's/^[[:space:]]*//' \
           -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" | \
       sed -n -e "/^\[$2\]/,/^\s*\[/{/^[^;].*\=.*/p;}"`
}

_parse_ini $inifile main

# coba konek 
mysql -u $mysql_user  -p${mysql_pass} -e '' > /dev/null 2>&1
test $? -gt 0 && echo "ERROR! Failed to connect to mysql" && exit 4

# bikin target kalo blum ada
test ! -d $target && mkdir -p $target

hari=`date +%A`
jam=`date +%H`

# get pwd
cwd=`pwd`

# looping
for section in `cat $inifile | grep '^\[' | grep -v main | sed 's/\[//' | sed 's/\]//'`; do
  outdir=$target/$section/$hari/$jam
  echo Backing up ${section} to $outdir...
  # parse .ini
  _parse_ini $inifile $section
  # cek dulu
  test ! -d $path && echo "Warning: $path not found.  Backup process of $section skipped" && echo && continue
  mysql -u $mysql_user  -p${mysql_pass} -e '' $mysql_db > /dev/null 2>&1
  test $? -gt 0 && echo "Warning: Database $mysql_db not found.  Backup process of $section skipped" && echo && continue

  test ! -d $outdir && mkdir -p $outdir
  cd $path
  tar -czpf $outdir/$section.tar.gz .
  cd $cwd
  mysqldump -Q -u $mysql_user -p${mysql_pass} $mysql_db | gzip > $outdir/${mysql_db}.sql.gz
  ln -fs $outdir/$section.tar.gz $target/$section/latest.tar.gz
  ln -fs $outdir/${mysql_db}.sql.gz $target/$section/latest.sql.gz
done

Parse Windows .ini Format with Ruby

I didn't write this, I'm just posting it in case someone else finds it useful. I needed to parse a file that turned out to be windows .ini. gdsx in #ruby-lang came up with this for me.

  #thanks to gdsx in #ruby-lang
  def tame(input)
          tamed = {}

          # split data on city names, throwing out surrounding brackets
          input = input.split(/\[([^\]]+)\]/)[1..-1]

          # sort the data into key/value pairs
          input.inject([]) {|tary, field|
                  tary << field
                  if(tary.length == 2)
                          # we have a key and value; put 'em to use
                          tamed[tary[0]] = tary[1].sub(/^\s+/,'').sub(/\s+$/,'')
                          # pass along a fresh temp-array
                          tary.clear
                  end
                  tary
                  }

          tamed.dup.each { |tkey, tval|
                  tvlist = tval.split(/[\r\n]+/)
                  p tvlist
                  tamed[tkey] = tvlist.inject({}) { |hash, val|
                          k, v = val.split(/=/)
                          hash[k]=v
                          hash
                          }
                  }

          tamed
  end

here's what the input looks like
[Amsterdam]  
Address=Amstelveenseweg 438;1084 JH;Amsterdam

[Antwerp]  
Address=Uitbreidingstraat 4;4-600;Antwerp

[Austin]  
Address=4221 South Harbor Expressway, Suite 400;Austin, Texas 78746

[Baltimore / Smith]
City=Baltimore 
Address=225 Johnson Avenue;Baltimore, Maryland 21209-3600

[Baltimore / Calvert]
City=Baltimore
Address=151 South Belmont Street, Suite 2350;Baltimore, Maryland 21202-6832

[Bangkok]
Address=Unit 543, London Tower;495 North Sathorn Road, Yannawa, Sathorn Bangkok 45467
Country=Thailand

[Bergen]
Country=Norway  
City=Bergen
Address=Torgallmenningen 4B;PO Box 2153 Sentrum, N-5811;Bergen



here's the output
{"Bergen"=>{"City"=>"Bergen", "Country"=>"Norway", "Address"=>"Torgallmenningen 4B;PO Box 2153 Sentrum, N-5811;Bergen"}, "Antwerp"=>{"Address"=>"Uitbreidingstraat 4;4-600;Antwerp"}, "Baltimore / Smith"=>{"City"=>"Baltimore", "Address"=>"225 Johnson Avenue;Baltimore, Maryland 21209-3600"}, "Amsterdam"=>{"Address"=>"Amstelveenseweg 438;1084 JH;Amsterdam"}, "Bangkok"=>{"Country"=>"Thailand", "Address"=>"Unit 543, London Tower;495 North Sathorn Road, Yannawa, Sathorn Bangkok 45467"}, "Austin"=>{"Address"=>"4221 South Harbor Expressway, Suite 400;Austin, Texas 78746"}, "Baltimore / Calvert"=>{"City"=>"Baltimore", "Address"=>"151 South Belmont Street, Suite 2350;Baltimore, Maryland 21202-6832"}


Is this also an example of a state machine in Ruby?
« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS