class Device < ActiveRecord::Base # all this nonsense based on http://www.ruby-forum.com/topic/101557 set_inheritance_column :ruby_type # we have devices.type column for asterisk 1.8 support, so we need this to allow such column # getter for the "type" column def device_ror_type self[:type] end # setter for the "type" column def device_ror_type=(s) self[:type] = s end #===================================================================== attr_accessor :device_ip_authentication_record attr_accessor :device_olde_name_record attr_accessor :device_old_server_record belongs_to :user has_many :extlines, :order => "exten ASC, priority ASC" has_many :dids belongs_to :devicegroup has_many :callerids belongs_to :location # belongs_to :voicemail_box has_many :callflows has_many :pdffaxemails has_one :provider has_many :activecalls, :foreign_key => "src_device_id" has_many :ringgroups_devices has_many :devicerules before_validation_on_create :check_device_username validates_presence_of :name, :message => _('Device_must_have_name') validates_presence_of :extension, :message => _('Device_must_have_extension') validates_uniqueness_of :extension, :message => _('Device_extension_must_be_unique') validates_uniqueness_of :username, :message => _('Device_Username_Must_Be_Unique'), :if => :username_must_be_unique # validates_format_of :name, :with => /^\w+$/, :on=>:create, :message => _('Device_username_must_consist_only_of_digits_and_letters') validates_format_of :max_timeout, :with => /^[0-9]+$/, :message => _('Device_Call_Timeout_must_be_greater_than_or_equal_to_0') validates_numericality_of :port, :message => _("Port_must_be_number"), :if => Proc.new{ |o| not o.port.blank? } # before_create :check_callshop_user before_save :validate_extension_from_pbx, :ensure_server_id, :random_password, :check_and_set_defaults, :check_password, :ip_must_be_unique_on_save, :check_language, :check_location_id, :check_dymanic_and_ip, :set_qualify_if_ip_auth, :validate_trunk, :update_mwi before_update :validate_fax_device_codecs after_create :create_codecs, :device_after_create after_save :device_after_save, :prune_device =begin #3239 dont know whats the reason to keep two identical fields, but just keep in mind that one is 1/0 #other yes/no and their values has to be the same =end def update_mwi self.subscribemwi = ((self.enable_mwi == 1) ? 'yes' : 'no') end =begin Resellers are allowed to assign dids to trunk only if appropriate settings is set by admin. In case device allready has assigned dids, it cannot be set to trunk if reseller does not have rights to assign dids to trunk. =end def validate_trunk if self.user and self.user.owner.is_reseller? allowed_to_assign_did = self.user.owner.allowed_to_assign_did_to_trunk? has_assigned_did = (not self.dids.empty?) if self.is_trunk? and has_assigned_did and not allowed_to_assign_did self.errors.add(:trunk, _('Did_is_assigned_to_device')) return false end end end def is_trunk? return self.istrunk.to_i > 0 end def is_dahdi? return self.device_type == 'dahdi' end =begin if username is blank it means that ip authentication is enabled and there's no need to check for valid passwords. server device is an exception, so there's no need to check whether it's pass is valid or not. skype device does not have any password at all. TODO: each device type should have separate class. there might be PasswordlessDevice =end def check_password unless self.server_device? or self.username.blank? or self.provider or ["dahdi", "virtual", "h323", "skype"].include?(self.device_type.downcase) if self.name and self.secret.to_s == self.name.to_s errors.add(:secret, _("Name_And_Secret_Cannot_Be_Equal")) return false end if self.secret.to_s.length < 8 and Confline.get_value("Allow_short_passwords_in_devices").to_i == 0 errors.add(:secret, _("Password_is_too_short")) return false end end end def validate_extension_from_pbx if Dialplan.find(:first, :conditions => {:dptype => "pbxfunction", :data2 => extension}) errors.add(:extension, _('Device_extension_must_be_unique')) return false end end def validate_fax_device_codecs valid_codecs_count = (self.codecs.reject { |codec| !['alaw', 'ulaw'].include? codec.name }).size if self.device_type == 'FAX' and valid_codecs_count == 0 self.errors.add(:devicecodecs, 'Fax_device_has_to_have_at_least_one_codec_enabled') return false else return true end end def check_language if self.language.to_s.blank? self.language = 'en' end end def check_location_id if self.user and self.user.owner_id != 0 #if old location id - create and set value = Confline.get_value("Default_device_location_id", self.user.owner_id) if value.blank? or value.to_i == 1 or !value owner = User.find_by_id(self.user.owner_id) owner.after_create_localization else #if new - only update devices with location 1 self.user.owner.update_resellers_device_location(value) end end end def check_and_set_defaults if self.device_type if ["sip", "iax2"].include?(self.device_type.downcase) self.nat ||= "yes" self.canreinvite ||= "no" end end end def ensure_server_id if self.server_id.blank? or !Server.find(:first, :conditions => ["server_id = ?", self.server_id]) default = Confline.get_value("Default_device_server_id") if !default.blank? self.server_id = default else if server = Server.find(:first, :order => "server_id ASC") Confline.set_value("Default_device_server_id", server.server_id) self.server_id = server.server_id else errors.add(:server, _("Server_Not_Found")) return false end end end end def check_callshop_user(flash) user = self.user if user and user.callshops.size.to_i != 0 and user.devices.size.to_i > 0 and (defined?(CS_Active) and CS_Active == 1) flash += "
" +_('User_in_CallShop_can_have_only_one_Device_creating_more_is_dangerous') end return flash end def random_password if (self.device_type.to_s == 'FAX' or self.device_type.to_s == 'Virtual') and self.secret.blank? self.secret = ApplicationController::random_password(10).to_s end end # converting callerid like "name" to number def callerid_number cid = self.callerid cidn = "" if self.callerid and cid.index('<') and cid.index('>') and cid.index('<') >= 0 and cid.index('>') > 0 cidn = cid[cid.index('<')+1, cid.index('>')-cid.index('<')-1] end cidn end def check_device_username if self.username_must_be_unique_on_creation username = self.username; name = self.username while Device.find(:first, :conditions => {:username => username}) username = self.generate_rand_name(name, 2) end self.username = username end if self.virtual? username = self.username; while Device.find(:first, :conditions => {:username => username}) username = self.generate_rand_name('', 12) end self.username = username end end def virtual? device_type == 'Virtual' end def generate_rand_name(string, size) chars = '123456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' str = '' size.times { |i| str << chars[rand(chars.length)] } string + str end =begin Every device has to have ONE voicemail box, so after saveing it we should create voicemail. lookin' at device_after_create and thinking it's plain stupid, huh? Note that i do not check whether self.user is not nil, because if it would be nil, it would mean that referential integrity was broken and so miskate was made by breaking it not by trusting that it wouldnt be broken. =end def device_after_save write_attribute(:accountcode, id) sql = "UPDATE devices SET accountcode = id WHERE id = #{id};" ActiveRecord::Base.connection.update(sql) user = self.user if user email = Confline.get_value("Default_device_voicemail_box_email", user.owner_id) email = user.address.email if user.address and user.address.email.to_s.size > 0 create_vm(extension, Confline.get_value("Default_device_voicemail_box_password", user.owner_id), user.first_name + " " + user.last_name, email) end end def device_after_create #device_after_save if self.user user = self.user Action.add_action_hash(User.current.id, {:target_id => id, :target_type => "device", :action => "device_created"}) #------- VM ---------- email = Confline.get_value("Default_device_voicemail_box_email", user.owner_id) email = user.address.email if user.address and user.address.email.to_s.size > 0 create_vm(extension, Confline.get_value("Default_device_voicemail_box_password", user.owner_id), user.first_name + " " + user.last_name, email) dev = user.devices.size.to_i #Device.count(:all, :conditions=>"user_id = #{user.id}") if dev.to_i == 1 user.primary_device_id = id user.save end self.update_cid(Confline.get_value("Default_device_cid_name", user.owner_id), Confline.get_value("Default_device_cid_number", user.owner_id)) end if self.virtual? self.extension = self.username = self.name = 'virtual_' + self.id.to_i.to_s end end #================== CODECS ========================= def create_codecs owner = self.user_id > 0 ? self.user.owner_id : 0 for codec in Codec.find(:all) if Confline.get_value("Default_device_codec_#{codec.name}", owner).to_i == 1 pc = Devicecodec.new pc.codec_id = codec.id pc.device_id = self.id pc.priority = Confline.get_value2("Default_device_codec_#{codec.name}", owner).to_i pc.save end end self.update_codecs end def codec?(codec) sql = "SELECT COUNT(*) as 'count' FROM devicecodecs, codecs WHERE devicecodecs.device_id = '" + self.id.to_s + "' AND devicecodecs.codec_id = codecs.id AND codecs.name = '" + codec.to_s + "'" res = ActiveRecord::Base.connection.select_one(sql) res['count'] == '1' end def codecs sql = "SELECT * FROM codecs, devicecodecs WHERE devicecodecs.device_id = '" + self.id.to_s + "' AND devicecodecs.codec_id = codecs.id ORDER BY devicecodecs.priority" res = ActiveRecord::Base.connection.select_all(sql) codecs = [] for i in 0..res.size-1 codecs << Codec.find(res[i]["codec_id"]) end codecs end def codecs_order(type) cond = self.device_type.to_s == 'FAX' ? ' AND codecs.name IN ("alaw", "ulaw") ' : '' Codec.find_by_sql("SELECT codecs.*, IF(devicecodecs.priority is null, 100, devicecodecs.priority) as bb FROM codecs LEFT Join devicecodecs on (devicecodecs.codec_id = codecs.id and devicecodecs.device_id = #{self.id.to_i}) where codec_type = '#{type}' #{cond} ORDER BY bb asc, codecs.id") end def update_codecs_with_priority(codecs, ifsave = true) dc = {} Devicecodec.find(:all, :conditions => ["device_id = ?", self.id]).each { |c| dc[c.codec_id] = c.priority; c.destroy } Codec.find(:all).each { |codec| Devicecodec.new(:codec_id => codec.id, :device_id => self.id, :priority => dc[codec.id].to_i).save if codecs[codec.name] == "1" } self.update_codecs(ifsave) end def update_codecs(ifsave = true) cl = [] self.codecs.each { |codec| cl << codec.name } cl << "all" if cl.size.to_i == 0 self.allow = cl.join(';') self.save if ifsave end #================== END OF CODECS ========================= def update_cid(cid_name, cid_number, ifsave = true) # if cid_number # cid = cid_number # else # if (self.primary_did_id != 0)and(primary_did = Did.find(self.primary_did_id)) # cid = primary_did.did.to_s # else # cid = self.username.to_s # end # end # self.callerid = nil # if cid_name and cid_number # self.callerid = "\"" + cid_name.to_s + "\"" + " <" + cid_number + ">" if cid_name.length > 0 and cid_number.length > 0 # end # self.save cid_name = "" if not cid_name cid_number = "" if not cid_number self.callerid = nil if cid_name.length > 0 and cid_number.length > 0 self.callerid = "\"" + cid_name.to_s + "\"" + " <" + cid_number.to_s + ">" end if cid_name.length > 0 and cid_number.length == 0 self.callerid = "\"" + cid_name.to_s + "\"" end if cid_name.length == 0 and cid_number.length > 0 self.callerid = "<" + cid_number.to_s + ">" end self.save if ifsave end #======================= CALLS ============================= def all_calls Call.find(:all, :conditions => "accountcode = '#{self.id}'") end def calls(type, date_from, date_till) #possible types: # all + # local # external # incoming # missed + # missed_not_processed + # outgoing # answered # failed # busy # no_answer # error if type == "all" @calls = Call.find(:all, :conditions => ["src_device_id =? " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "answered" @calls = Call.find(:all, :conditions => ["billsec > 0 AND src_device_id = ? AND disposition = 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "noanswer" @calls = Call.find(:all, :conditions => ["src_device_id = ? AND disposition = 'NO ANSWER' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "failed" @calls = Call.find(:all, :conditions => ["src_device_id = ? AND disposition = 'FAILED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "busy" @calls = Call.find(:all, :conditions => ["src_device_id = ? AND disposition = 'BUSY' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "missed" @calls = Call.find(:all, :conditions => ["src_device_id =? AND disposition != 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "missed_not_processed" @calls = Call.find(:all, :conditions => ["processed = '0' AND src_device_id =? AND disposition != 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end #---incoming--- if type == "all_inc" @calls = Call.find(:all, :conditions => ["dst_device_id =? " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "answered_inc" @calls = Call.find(:all, :conditions => ["billsec > 0 AND dst_device_id = ? AND disposition = 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "noanswer_inc" @calls = Call.find(:all, :conditions => ["dst_device_id = ? AND disposition = 'NO ANSWER' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "failed_inc" @calls = Call.find(:all, :conditions => ["dst_device_id = ? AND disposition = 'FAILED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "busy_inc" @calls = Call.find(:all, :conditions => ["dst_device_id = ? AND disposition = 'BUSY' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "missed_inc" @calls = Call.find(:all, :conditions => ["dst_device_id =? AND disposition != 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "missed_not_processed_inc" @calls = Call.find(:all, :conditions => ["processed = '0' AND dst_device_id =? AND disposition != 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end #--not used--- if type == "incoming" @calls = Call.find(:all, :conditions => ["user_price >= 0 AND dst_device_id =? " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "outgoing" @calls = Call.find(:all, :conditions => ["user_price >= 0 AND src_device_id =? " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end @calls end def total_calls(type, date_from, date_till) if type == "all" t_calls = Call.count(:all, :conditions => ["(src_device_id = ? OR dst_device_id =?) AND user_id IS NOT NULL " + date_query(date_from, date_till), self.id, self.id], :order => " calldate DESC") end if type == "answered" t_calls = Call.count(:all, :conditions => ["billsec > 0 AND src_device_id = ? AND #{Call.nice_answered_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "answered_out" t_calls = Call.count(:all, :conditions => ["src_device_id = ? AND #{Call.nice_answered_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "no_answer_out" t_calls = Call.count(:all, :conditions => ["src_device_id = ? AND disposition = 'NO ANSWER' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "busy_out" t_calls = Call.count(:all, :conditions => ["src_device_id = ? AND disposition = 'BUSY' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "failed_out" t_calls = Call.count(:all, :conditions => ["src_device_id = ? AND user_id IS NOT NULL AND #{Call.nice_failed_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "answered_inc" t_calls = Call.count(:all, :conditions => ["dst_device_id = ? AND #{Call.nice_answered_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "no_answer_inc" t_calls = Call.count(:all, :conditions => ["dst_device_id = ? AND disposition = 'NO ANSWER' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "busy_inc" t_calls = Call.count(:all, :conditions => ["dst_device_id = ? AND disposition = 'BUSY' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "failed_inc" t_calls = Call.count(:all, :conditions => ["dst_device_id = ? AND #{Call.nice_failed_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "missed_not_processed" t_calls = Call.count(:all, :conditions => ["processed = '0' AND dst_device_id =? AND #{Call.nice_answered_cond_sql(false)}" + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "incoming" t_calls = Call.count(:all, :conditions => ["dst_device_id =? " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "outgoing" t_calls = Call.count(:all, :conditions => ["src_device_id =? AND user_id IS NOT NULL " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end t_calls end def total_duration(type, date_from, date_till) if type == "answered" t_duration = Call.sum(:duration, :conditions => ["billsec > 0 AND src_device_id = ? AND #{Call.nice_answered_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "answered_out" t_duration = Call.sum(:duration, :conditions => ["billsec > 0 AND src_device_id = ? AND #{Call.nice_answered_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end if type == "answered_inc" t_duration = Call.sum(:duration, :conditions => ["billsec > 0 AND dst_device_id = ? AND #{Call.nice_answered_cond_sql} " + date_query(date_from, date_till), self.id], :order => " calldate DESC") end t_duration = 0 if t_duration == nil t_duration end def total_billsec(type, date_from, date_till) if type == "answered" #t_billsec = Call.sum(:billsec, :conditions => ["calls.card_id = 0 AND billsec > 0 AND src_device_id = ? AND disposition = 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") sql = "SELECT sum(billsec) AS sum_billsec2 FROM calls WHERE (billsec > 0 AND src_device_id = '#{self.id}' AND #{Call.nice_answered_cond_sql} #{date_query(date_from, date_till)}) ORDER BY calldate DESC" res = ActiveRecord::Base.connection.select_one(sql) t_billsec = res['sum_billsec'].to_i end if type == "answered_out" #t_billsec = Call.sum(:billsec, :conditions => ["calls.card_id = 0 AND billsec > 0 AND src_device_id = ? AND disposition = 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") sql = "SELECT sum(billsec) AS sum_billsec FROM calls WHERE (billsec > 0 AND src_device_id = '#{self.id}' AND #{Call.nice_answered_cond_sql} #{date_query(date_from, date_till)}) ORDER BY calldate DESC" res = ActiveRecord::Base.connection.select_one(sql) t_billsec = res['sum_billsec'].to_i end if type == "answered_inc" #t_billsec = Call.sum(:billsec, :conditions => ["calls.card_id = 0 AND billsec > 0 AND dst_device_id = ? AND disposition = 'ANSWERED' " + date_query(date_from, date_till), self.id], :order => " calldate DESC") sql = "SELECT sum(billsec) AS sum_billsec FROM calls WHERE (billsec > 0 AND dst_device_id = '#{self.id}' AND #{Call.nice_answered_cond_sql} #{date_query(date_from, date_till)}) ORDER BY calldate DESC" res = ActiveRecord::Base.connection.select_one(sql) t_billsec = res['sum_billsec'].to_i end t_billsec = 0 if t_billsec == nil t_billsec end # forms sql part for date selection def date_query(date_from, date_till) # date query if date_from == "" date_sql = "" else if date_from.length > 11 date_sql = "AND calldate BETWEEN '#{date_from.to_s}' AND '#{date_till.to_s}'" else date_sql = "AND calldate BETWEEN '" + date_from.to_s + " 00:00:00' AND '" + date_till.to_s + " 23:59:59'" end end date_sql end def destroy_everything err = [] if self.all_calls.size == 0 for email in self.pdffaxemails do email.destroy end for cid in self.callerids do cid.destroy end Extline.destroy_all ["device_id = ?", self.id] err = self.prune_device_in_server self.destroy_vm self.destroy end err end def prune_device_in_all_servers(dv_name = nil, reload = 1) dv_name = name if dv_name.nil? err= [] # clean Realtime mess servers = Server.find(:all) for server in servers begin server.prune_peer(dv_name, reload) rescue Exception => e err << e.message end end err end def prune_device_in_server(dv_name = nil, reload = 1, serverid = nil) dv_name = name if dv_name.nil? serverid = server_id if serverid.nil? err= [] # clean Realtime mess http://trac.kolmisoft.com/trac/ticket/5092 server = Server.find(:first, :conditions => {:server_id => serverid}) begin server.prune_peer(dv_name, reload) if server rescue Exception => e err << e.message end err end #put value into file for debugging def my_debug(msg) File.open(Debug_File, "a") { |f| f << msg.to_s f << "\n" } end #--------------- VoiceMail-------------- # def voicemail_box VoicemailBox.find(:first, :conditions => "device_id = #{self.id}") if self.id end def destroy_vm if self.voicemail_box vm_id = self.voicemail_box.id sql = "DELETE FROM voicemail_boxes WHERE uniqueid = '#{vm_id}'" res = ActiveRecord::Base.connection.update(sql) #self.voicemail_box.destroy end end # Check if device is a detectable fax def has_fax_detect flow = Callflow.find(:all, :conditions => ["data = ? and data2 = 'fax' and action = 'fax_detect'", self.id]) return flow if flow.size > 0 return nil end # Check if device has calls forwarded to it def has_forwarded_calls flow = Callflow.find(:all, :conditions => ["data = ? and data2 = 'local' and action = 'forward'", self.id]) return flow if flow.size > 0 return nil end def dialplans Dialplan.find(:all, :conditions => ["data3 = ?", self.id]) end def username_must_be_unique_on_creation self.device_ip_authentication_record.to_i == 0 and !self.provider end def ip_must_be_unique_on_save message = (User.current and User.current.usertype == 'admin') ? _("When_IP_Authentication_checked_IP_must_be_unique") : _('This_IP_is_not_available') + "Help" cond = if ipaddr.blank? ['devices.id != ? AND host = ? AND providers.user_id != ? and ipaddr != "" and ipaddr != "0.0.0.0"', id, host, User.current.id] else ['devices.id != ? AND (host = ? OR ipaddr = ?) AND providers.user_id != ? and ipaddr != "" and ipaddr != "0.0.0.0"', id, host, ipaddr, User.current.id] end # check device wihs is provider with providers devices. if self.device_ip_authentication_record.to_i == 1 and self.provider and Device.count(:all, :joins => ['JOIN providers ON (device_id = devices.id)'], :conditions => cond).to_i > 0 errors.add(:ip_authentication, message) return false end # check self device or another devices with ip auth on condd = self.device_ip_authentication_record.to_i == 1 ? '' : ' and devices.username = "" ' cond22 = if ipaddr.blank? # check device host with another owner devices ['devices.id != ? AND host = ? and users.owner_id != ? and user_id != -1 and ipaddr != "" and ipaddr != "0.0.0.0"' + condd, id, host, User.current.id] else # check device IP and Host with another owner devices ['devices.id != ? AND (host = ? OR ipaddr = ?) and users.owner_id != ? and user_id != -1 and ipaddr != "" and ipaddr != "0.0.0.0"' + condd, id, host, ipaddr, User.current.id] end # check device IP with another user providers IP's with have ip auth on, 0.0.0.0 not included if Device.count(:all, :joins => ['JOIN users ON (user_id = users.id)'], :conditions => cond22).to_i > 0 errors.add(:ip_authentication, message) return false end # check device IP with another user providers IP's with have ip auth on, 0.0.0.0 not included if Provider.count(:all, :joins => ['JOIN devices ON (device_id = devices.id)'], :conditions => ["server_ip = ? and devices.username = '' and server_ip != '0.0.0.0' and devices.id != ? and ipaddr != '' AND providers.user_id != ? and ipaddr != '0.0.0.0'", ipaddr, id, User.current.id]).to_i > 0 errors.add(:ip_authentication, message) return false end # check device with providers port, dont allow dublicates in providers and devices combinations if self.provider message2 = (User.current and User.current.usertype == 'admin') ? _("Device_with_such_IP_and_Port_already_exist") + ' ' + _('Please_check_this_link_to_see_how_it_can_be_resolved') + "Help" : _('This_IP_and_port_is_not_available') + "Help" cond3 = if ipaddr.blank? ['devices.id != ? AND host = ? and ipaddr != "" and ipaddr != "0.0.0.0" and devices.port=? AND providers.id IS NULL' + condd, id, host, port] else ['devices.id != ? AND (host = ? OR ipaddr = ?) and ipaddr != "" and ipaddr != "0.0.0.0" and devices.port=? AND providers.id IS NULL' + condd, id, host, ipaddr, port] end if Device.count(:all, :joins => ['JOIN users ON (user_id = users.id) LEFT JOIN providers ON (providers.device_id = devices.id)'], :conditions => cond3).to_i > 0 errors.add(:ip_authentication, message2) return false end else message2 = (User.current and User.current.usertype == 'admin') ? _("Provider_with_such_IP_and_Port_already_exist") + ' ' + _('Please_check_this_link_to_see_how_it_can_be_resolved') + "Help" : _('This_IP_and_port_is_not_available') + "Help" cond3 = if ipaddr.blank? ['devices.id != ? AND host = ? and ipaddr != "" and ipaddr != "0.0.0.0" and devices.port=? ' + condd, id, host, port] else ['devices.id != ? AND (host = ? OR ipaddr = ?) and ipaddr != "" and ipaddr != "0.0.0.0" and devices.port=?' + condd, id, host, ipaddr, port] end if Provider.count(:all, :joins => ['JOIN devices ON (device_id = devices.id)'], :conditions => cond3).to_i > 0 errors.add(:ip_authentication, message2) return false end end end def set_qualify_if_ip_auth if username.to_s.blank? self.qualify = 'no' end end def check_dymanic_and_ip if username.to_s.blank? and host.to_s == 'dynamic' errors.add(:host, _("When_IP_Authentication_checked_Host_cannot_be_dynamic")) return false end end def username_must_be_unique Confline.get_value("Disalow_Duplicate_Device_Usernames").to_i == 1 and self.device_ip_authentication_record.to_i == 0 and !self.provider end def Device.validate_perims(options={}) permits = "0.0.0.0/0.0.0.0" if options[:ip1].size > 0 and options[:mask1].size > 0 unless Device.validate_ip(options[:ip1].to_s) and Device.validate_ip(options[:mask1].to_s) return nil end permits = options[:ip1].strip + "/" + options[:mask1].strip if options[:ip2].size > 0 and options[:mask2].size > 0 unless Device.validate_ip(options[:ip2]) and Device.validate_ip(options[:mask2]) return nil end permits += ";" + options[:ip2].strip + "/" + options[:mask2].strip if options[:ip3].size > 0 and options[:mask3].size > 0 unless Device.validate_ip(options[:ip3]) and Device.validate_ip(options[:mask3]) return nil end permits += ";" + options[:ip3].strip + "/" + options[:mask3].strip end end end return permits end def Device.validate_permits_ip(ip_arr) err = true ip_arr.each { |ip| if ip and !ip.blank? and !Device.validate_ip(ip) err = false end } return err end def Device::validate_ip(ip) ip.gsub(/(^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)/, "").to_s.length == 0 ? true : false end def Device.find_all_for_select(current_user_id = nil) if current_user_id return Device.find(:all, :select => "devices.id, devices.description, devices.extension, devices.device_type, devices.istrunk, devices.name, devices.ani, devices.username", :joins => "LEFT JOIN users ON (users.id = devices.user_id)", :conditions => ["device_type != 'FAX' AND (users.owner_id = ? OR users.id = ?) AND name not like 'mor_server_%'", current_user_id, current_user_id]) else return Device.find(:all, :select => "id, description, extension, device_type, istrunk, name, ani, username", :conditions => "device_type != 'FAX' AND name not like 'mor_server_%'") end end def device_ip_authentication? @device_ip_authentication_record end def load_device_types(options = {}) Devicetype.find(:all).map { |type| (options.has_key?(type.name) and options[type.name] == false and self.device_type != type.name) ? nil : type }.compact end def perims_split ip1 = "" mask1 = "" ip2 = "" mask2 = "" ip3 = "" mask3 = "" data = permit.split(';') if data[0] rp = data[0].split('/') ip1 = rp[0] mask1 = rp[1] end if data[1] rp = data[1].split('/') ip2 = rp[0] mask2 = rp[1] end if data[2] rp = data[2].split('/') ip3 = rp[0] mask3 = rp[1] end return ip1, mask1, ip2, mask2, ip3, mask3 end def Device.calleridpresentation [ [_('Presentation_Allowed_Not_Screened'), 'allowed_not_screened'], [_('Presentation_Allowed_Passed_Screen'), 'allowed_passed_screen'], [_('Presentation_Allowed_Failed_Screen'), 'allowed_failed_screen'], [_('Presentation_Allowed_Network_Number'), 'allowed'], [_('Presentation_Prohibited_Not_Screened'), 'prohib_not_screened'], [_('Presentation_Prohibited_Passed_Screen'), 'prohib_passed_screen'], [_('Presentation_Prohibited_Failed_Screen'), 'prohib_failed_screen'], [_('Presentation_Prohibited_Network_Number'), 'prohib'], [_('Number_Unavailable'), 'unavailable'] ] end def validate_before_destroy(current_user, allow_edit) notice = '' unless user notice = _("User_was_not_found") end if current_user.usertype == 'accountant' and !allow_edit and notice.blank? notice = _('You_have_no_editing_permission') end if self.has_fax_detect and notice.blank? notice = _('Cant_delete_device_has_fax_detect') end if self.has_forwarded_calls and notice.blank? notice = _('Cant_delete_device_has_forworded_calls') end if self.all_calls.size > 0 and notice.blank? notice = _('Cant_delete_device_has_calls') end if self.dialplans.size > 0 and notice.blank? notice = _('Cant_delete_device_has_diaplans') end notice end def destroy_all Extline.destroy_all ["device_id = ?", id] #deleting association with dids if dids = Did.find(:all, :conditions => ["device_id =?", id]) for did in dids did.device_id = "0" did.save end end #destroying codecs for dc in Devicecodec.find(:all, :conditions => ["device_id = ?", id]) dc.destroy end #destroying rules for dr in Devicerule.find(:all, :conditions => ["device_id = ?", id]) dr.destroy end user = user self.destroy_everything end def Device.validate_before_create(current_user, user, params, allow_dahdi, allow_virtual) notice = '' unless user notice =_('User_was_not_found') end if current_user.usertype == 'accountant' and notice.blank? s ={} group = current_user.acc_group if group rights = AccRight.find( :all, :select => "acc_rights.name, acc_group_rights.value", :joins => "LEFT JOIN acc_group_rights ON (acc_group_rights.acc_right_id = acc_rights.id AND acc_group_rights.acc_group_id = #{group.id})", :conditions => ["acc_rights.right_type = ?", group.group_type] ) short = {"accountant" => "acc", "reseller" => "res"} rights.each { |right| name = "#{short[current_user.usertype]}_#{right[:name].downcase}".to_sym if right[:value].nil? s[name] = 0 else s[name] = ((right[:value].to_i >= 2 and group.only_view) ? 1 : right[:value].to_i) end } params = current_user.sanitize_device_params_by_accountant_permissions(s, params, self.clone) else s[:acc_device_create] = 0 end if notice.blank? and s[:acc_device_create] != 2 notice = _('dont_be_so_smart') end end params[:device][:description]=params[:device][:description].strip if params[:device][:description] params[:device][:pin]=params[:device][:pin].strip if params[:device][:pin] # if current_user.usertype == 'reseller' and Confline.get_value('Allow_resellers_change_device_PIN').to_i == 0 # params[:device][:pin] = nil # end if notice.blank? and params[:device][:extension] and Device.find(:first, :conditions => ["extension = ?", params[:device][:extension]]) notice = _('Extension_is_used') else #pin if notice.blank? and (Device.find(:first, :conditions => [" pin = ?", params[:device][:pin]]) and params[:device][:pin].to_s != "") notice = _('Pin_is_already_used') end if notice.blank? and !params[:device][:pin].to_s.blank? and params[:device][:pin].to_s.strip.scan(/[^0-9 ]/).compact.size > 0 notice = _('Pin_must_be_numeric') end end if notice.blank? and params[:device][:devicegroup_id] and !Devicegroup.find(:first, :conditions => {:id => params[:device][:devicegroup_id], :user_id => user.id}) notice = _('Device_group_invalid') end type_array = ['SIP', 'IAX2', 'FAX', 'H323', 'Skype', ''] type_array << "dahdi" if allow_dahdi type_array << "Virtual" if allow_virtual if notice.blank? and !type_array.include?(params[:device][:device_type].to_s) notice = _('Device_type_invalid') end return notice, params end =begin only SIP, IAX and skype devices can have name. but only first two can be authenticated by ip. users can not see skype device's username and nor they can see SIP/IAX2 device's username if ip authentication is set. and we determine whether ip auth is set by checking if username is empty. *Returns* *boolean* true or false depending whether we should show username or not =end def show_username? (not username.blank? and (device_type == "SIP" or device_type == "IAX2")) or device_type == "Skype" end def dids_numbers numbers = [] self.dids.each { |d| numbers << d.did } if self.dids and self.dids.size.to_i > 0 numbers end def cid_number numbers = [] self.callerids.each { |d| numbers << [d.cli, d.id] } if self.callerids and self.callerids.size.to_i > 0 numbers end def device_caller_id_number device_caller_id_number = 1 device_caller_id_number = 3 if cid_from_dids.to_i == 1 device_caller_id_number = 4 if control_callerid_by_cids.to_i != 0 device_caller_id_number = 5 if callerid_advanced_control.to_i == 1 device_caller_id_number end =begin check whether device belongs to server *Returns* boolean - true if device belongs to server, else false =end def server_device? self.name =~ /mor_server_\d+/ ? true : false end DefaultPort={'SIP' => 5060, 'IAX2' => 4569, 'H323' => 1720} =begin Check whether port is valid for supplied technology, at this moment only ilegal ports are those that are less than 1. *Returns* +valid+ true if port is valid, else false =end def self.valid_port?(port, technology) if port.to_i < 1 return false elsif technology == 'SIP' return true elsif technology == 'IAX' return true else return true end end def device_olde_name @device_olde_name_record end def device_old_server @device_old_server_record end def set_old_name self.device_olde_name_record = name self.device_old_server_record = server_id end =begin Check whether device belongs to provider. This would mean that device cannot have user associated with it. *Returns* +boolean+ true if device belongs to provider, othervise false =end def belongs_to_provider? self.user_id == -1 end =begin Set time limit per day option for the device. In database it is saved in seconds but this method is expecting minutes tu be passed to it. If negative or none numeric params would be passed it will be converted to 0. if float would be passed as param, decimal part would be striped. *Params* +minutes+ integer, time interval in minutes. =end def time_limit_per_day=(minutes) minutes = (minutes.to_i < 0) ? 0 : minutes.to_i seconds = minutes * 60 write_attribute(:time_limit_per_day, seconds) end =begin Get time limit per day expressed in minutes. In database it is saves in seconds, sho we just convert to minutes by deviding by 60. Obviuosly this is OOD mistake, we should use so sort of 'time interval' instance.. *Returns* +minutes+ integer, time interval in minutes =end def time_limit_per_day (read_attribute(:time_limit_per_day) / 60).to_i end =begin Callerid control by cids is concidered enabled if callerid is not 0, cause this value should be id of device's clid =end def control_callerid_by_cids? self.control_callerid_by_cids.to_i != 0 end =begin Check whether fax device supports T.38. Keep in mind that calling this method is valid only if it is fax device, else exception should be rised. =end def t38support? #if self.device_type == 'FAX' self.t38pt_udptl.to_i == 1 #else # raise 'Only fax devices support T.38 protocol' #end end private =begin Note INSERT IGNORE INTO, thats because voicemail boxes should have unique constraint set, so if one tries to insert duplicate record, no exception would be risen and INSERT stetement would be ignored =end def create_vm(mailbox, pass, fullname, email) vm = VoicemailBox.new vm.device_id = self.id vm.mailbox = mailbox vm.password = pass fullname = fullname.gsub("'", "") vm.context = "default" if email vm.email = email else vm.email = Confline.get_value("Company_Email") end #vm.save sql = "INSERT IGNORE INTO voicemail_boxes (device_id, mailbox, password, fullname, context, email, pager, dialout, callback) VALUES ('#{self.id}', '#{mailbox}', '#{pass}', '#{fullname}', 'default', '#{vm.email}', '', '', '');" res = ActiveRecord::Base.connection.insert(sql) vm = VoicemailBox.find(:first, :conditions => "device_id = '#{self.id}' AND fullname = '#{fullname}' AND email = '#{vm.email}'") vm end def prune_device if device_olde_name_record != name and ['SIP', 'IAX2'].include?(device_type.to_s) MorLog.my_debug("Device_name_changed ID:#{id}, old_name:#{device_olde_name_record}, new_name:#{name}", 1) if self.provider MorLog.my_debug("Provider_name_changed ID:#{id} prune:#{device_olde_name_record}, no reload", 1) #clean the mess from all servers and do not reload (0) self.prune_device_in_all_servers(device_olde_name_record, 0) #clean the mess from all servers and reload (1) MorLog.my_debug("Provider_name_changed ID:#{id} prune:#{name}, reload", 1) self.prune_device_in_all_servers(name, 1) else if device_old_server_record != server_id MorLog.my_debug("Device_name_changed ID:#{id} prune:#{device_olde_name_record}, no reload old server :#{device_old_server_record}", 1) #clean the mess from old server and do not reload (0) self.prune_device_in_server(device_olde_name_record, 0, device_old_server_record) end MorLog.my_debug("Device_name_changed ID:#{id} prune:#{device_olde_name_record}, no reload", 1) #clean the mess from server and do not reload (0) self.prune_device_in_server(device_olde_name_record, 0) #clean the mess from server and reload (1) MorLog.my_debug("Device_name_changed ID:#{id} prune:#{name}, reload", 1) self.prune_device_in_server(name, 1) end self.device_olde_name_record = name end end =begin #ticket #5133 =end def cid_number=(value) @cid_number = value end def Device.integrity_recheck_devices Device.count(:all, :conditions => "host='dynamic' and insecure like '%invite%' and insecure != 'invite'").to_i > 0 ? 1 : 0 end end