#!/usr/local/bin/ruby # # TO RUN THIS SCRIPT, FIRST INSTALL THE LATEST VERSION OF RUBY (1.8.4 AS OF THIS WRITING) # AND THEN INSTALL RUBYGEMS. IF YOU ARE USING WINDOWS, THE ONE-CLICK INSTALLER COMES # WITH RUBYGEMS INSTALLED READY (http://rubyinstaller.rubyforge.org/). THEN RUN THE # FOLLOWING AS ROOT OR ADMINISTRATOR: # # gem install mechanize ipadmin --include-dependencies # # THEN EDIT THE $directory VARIABLE BELOW WITH YOUR ORGANIZATION'S EXTENSIONS AND EDIT # THE list VARIABLE SO THAT IT CONTAINS THE IP RANGES WHERE YOUR PHONES ARE LOCATED. # THEN RUN # # ruby spa942_directory.rb # # AS ROOT OR ADMINISTRATOR IN THE SAME DIRECTORY WHERE THE ACCOMPANYING icmpping.rb FILE # IS LOCATED. require 'thread' require 'rubygems' require "icmpping" require 'mechanize' require_gem 'ipadmin' require 'directory' include Net class String def to_cidr IPAdmin::CIDR.new :CIDR => self end end class Array def to_cidr map{|elem| elem.to_s.to_cidr} end end $directory = [] Directory.users.each { |u| $directory << "n=#{u.name};p=#{u.extension}" } $directory << "n=Conference Call 1;p=8000" $directory << "n=Conference Call 2;p=8001" $directory << "n=Conference Call 3;p=8002" $directory << "n=Denver Intercom;p=2000" $directory << "n=Phoenix Intercom;p=3000" $directory << "n=SLC Conf Room;p=1025" $directory << "n=SLC Downstairs Intercom;p=1001" $directory << "n=SLC Intercom;p=1000" $directory << "n=SLC Upstairs Intercom;p=1001" # For small runs #list = IPAdmin.range(:Boundaries => %w( 10.20.30.196 10.20.30.198 ).to_cidr) list = IPAdmin.range(:Boundaries => %w( 10.20.30.1 10.20.30.254 ).to_cidr) list.concat IPAdmin.range(:Boundaries => %w( 10.20.35.1 10.20.35.254 ).to_cidr) list.concat IPAdmin.range(:Boundaries => %w( 10.20.36.1 10.20.36.254 ).to_cidr) list.concat IPAdmin.range(:Boundaries => %w( 10.20.39.1 10.20.39.254 ).to_cidr) def update_phone(ipaddr, dir = $directory) agent = WWW::Mechanize.new agent.user_agent_alias = 'Windows IE 6' # get first page begin page = agent.get("http://#{ipaddr}/pdir.htm") form = page.forms.first page.body.scan(/(\d+)\..*?name="(\d+)"/m) do |entrynum, inputname| entrynum = entrynum.to_i form.fields.find {|f| f.name == inputname}.value = dir[entrynum - 1] if dir[entrynum - 1] end page = agent.submit(form, form.buttons.first) return true if page.body =~ /SPA is updating/ return false rescue return false end end THREAD_COUNT = 10 mutex = Mutex.new threads = [] pings = 0 attempts = 0 successes = 0 THREAD_COUNT.times do |i| threads << Thread.new do loop do ipaddr = '' stop = false mutex.synchronize do ipaddr = list.shift end stop = true if ipaddr.nil? break if stop mutex.synchronize { pings += 1 } if ICMPPing.ping(ipaddr, 1000) >= 0 mutex.synchronize { attempts += 1 } mutex.synchronize { successes += 1 if update_phone(ipaddr) } end mutex.synchronize { print "\r#{pings} hosts pinged, #{attempts} hosts found, #{successes} successful updates..." } end end end threads.each {|t| t.join }