agent_xmpp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
 - data/.gitignore +11 -0
 - data/LICENSE +20 -0
 - data/README.rdoc +417 -0
 - data/Rakefile +75 -0
 - data/VERSION +1 -0
 - data/agent_xmpp.gemspec +144 -0
 - data/lib/agent_xmpp.rb +22 -0
 - data/lib/agent_xmpp/admin.rb +113 -0
 - data/lib/agent_xmpp/client.rb +7 -0
 - data/lib/agent_xmpp/client/boot.rb +83 -0
 - data/lib/agent_xmpp/client/client.rb +64 -0
 - data/lib/agent_xmpp/client/connection.rb +108 -0
 - data/lib/agent_xmpp/client/controller.rb +394 -0
 - data/lib/agent_xmpp/client/message_delegate.rb +720 -0
 - data/lib/agent_xmpp/client/message_pipe.rb +193 -0
 - data/lib/agent_xmpp/client/response.rb +102 -0
 - data/lib/agent_xmpp/config.rb +48 -0
 - data/lib/agent_xmpp/main.rb +175 -0
 - data/lib/agent_xmpp/models.rb +7 -0
 - data/lib/agent_xmpp/models/contact.rb +85 -0
 - data/lib/agent_xmpp/models/message.rb +152 -0
 - data/lib/agent_xmpp/models/publication.rb +53 -0
 - data/lib/agent_xmpp/models/roster.rb +107 -0
 - data/lib/agent_xmpp/models/service.rb +91 -0
 - data/lib/agent_xmpp/models/subscription.rb +61 -0
 - data/lib/agent_xmpp/models/table_definitions.rb +107 -0
 - data/lib/agent_xmpp/patches.rb +7 -0
 - data/lib/agent_xmpp/patches/array.rb +32 -0
 - data/lib/agent_xmpp/patches/float.rb +10 -0
 - data/lib/agent_xmpp/patches/hash.rb +13 -0
 - data/lib/agent_xmpp/patches/object.rb +15 -0
 - data/lib/agent_xmpp/patches/rexml.rb +69 -0
 - data/lib/agent_xmpp/patches/string.rb +15 -0
 - data/lib/agent_xmpp/xmpp.rb +18 -0
 - data/lib/agent_xmpp/xmpp/element.rb +158 -0
 - data/lib/agent_xmpp/xmpp/entry.rb +36 -0
 - data/lib/agent_xmpp/xmpp/error_response.rb +189 -0
 - data/lib/agent_xmpp/xmpp/iq.rb +90 -0
 - data/lib/agent_xmpp/xmpp/iq_command.rb +54 -0
 - data/lib/agent_xmpp/xmpp/iq_disco.rb +206 -0
 - data/lib/agent_xmpp/xmpp/iq_pubsub.rb +270 -0
 - data/lib/agent_xmpp/xmpp/iq_roster.rb +183 -0
 - data/lib/agent_xmpp/xmpp/iq_version.rb +89 -0
 - data/lib/agent_xmpp/xmpp/jid.rb +150 -0
 - data/lib/agent_xmpp/xmpp/message.rb +82 -0
 - data/lib/agent_xmpp/xmpp/presence.rb +127 -0
 - data/lib/agent_xmpp/xmpp/sasl.rb +241 -0
 - data/lib/agent_xmpp/xmpp/stanza.rb +107 -0
 - data/lib/agent_xmpp/xmpp/x_data.rb +357 -0
 - data/test/app/app.rb +339 -0
 - data/test/cases/test_application_message_processing.rb +65 -0
 - data/test/cases/test_errors.rb +24 -0
 - data/test/cases/test_presence_management.rb +139 -0
 - data/test/cases/test_roster_management.rb +214 -0
 - data/test/cases/test_service_discovery.rb +168 -0
 - data/test/cases/test_session_management.rb +120 -0
 - data/test/cases/test_version_discovery.rb +67 -0
 - data/test/helpers/matchers.rb +23 -0
 - data/test/helpers/mocks.rb +82 -0
 - data/test/helpers/test_case_extensions.rb +45 -0
 - data/test/helpers/test_client.rb +44 -0
 - data/test/helpers/test_delegate.rb +60 -0
 - data/test/helpers/test_helper.rb +91 -0
 - data/test/messages/application_messages.rb +206 -0
 - data/test/messages/error_messages.rb +35 -0
 - data/test/messages/presence_messages.rb +66 -0
 - data/test/messages/roster_messages.rb +126 -0
 - data/test/messages/service_discovery_messages.rb +201 -0
 - data/test/messages/session_messages.rb +158 -0
 - data/test/messages/version_discovery_messages.rb +69 -0
 - data/test/peer/peer.rb +21 -0
 - metadata +187 -0
 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            module AgentXmpp
         
     | 
| 
      
 3 
     | 
    
         
            +
              
         
     | 
| 
      
 4 
     | 
    
         
            +
              #####-------------------------------------------------------------------------------------------------------
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Subscription
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                #####-------------------------------------------------------------------------------------------------------
         
     | 
| 
      
 8 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def subscriptions(renew=false)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @subscriptions ||= AgentXmpp.in_memory_db[:subscriptions]
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def find_all
         
     | 
| 
      
 17 
     | 
    
         
            +
                    subscriptions.all
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def update(msg, node, serv)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    case msg
         
     | 
| 
      
 23 
     | 
    
         
            +
                      when AgentXmpp::Xmpp::Subscription then update_with_subscription(msg, node, serv)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      when AgentXmpp::Xmpp::Iq then update_with_subscription(msg.pubsub.subscription, node, serv)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end                 
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def destroy_by_node(node)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    subscriptions.filter(:node => node).delete
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end 
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 34 
     | 
    
         
            +
                  def stats_by_node
         
     | 
| 
      
 35 
     | 
    
         
            +
                    find_all.map do |s|
         
     | 
| 
      
 36 
     | 
    
         
            +
                      node = s[:node].split('/')
         
     | 
| 
      
 37 
     | 
    
         
            +
                      Message.stats_by_node(s[:node]).update(:node=>node.last, :jid=>"#{node[3]}@#{node[2]}")
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 42 
     | 
    
         
            +
                  # private
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 44 
     | 
    
         
            +
                  def update_with_subscription(msg, node, serv)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 46 
     | 
    
         
            +
                      subscriptions << {:node => node, :subscription => msg.subscription, :service => serv}
         
     | 
| 
      
 47 
     | 
    
         
            +
                    rescue 
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
         
     | 
| 
      
 51 
     | 
    
         
            +
                  #.........................................................................................................
         
     | 
| 
      
 52 
     | 
    
         
            +
                  private :update_with_subscription
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                #### self
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              #### Subscription
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            #### AgentXmpp
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,107 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            module AgentXmpp
         
     | 
| 
      
 3 
     | 
    
         
            +
              
         
     | 
| 
      
 4 
     | 
    
         
            +
              #####-------------------------------------------------------------------------------------------------------
         
     | 
| 
      
 5 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                #####-----------------------------------------------------------------------------------------------------
         
     | 
| 
      
 8 
     | 
    
         
            +
                def create_in_memory_db
         
     | 
| 
      
 9 
     | 
    
         
            +
                  in_memory_db.create_table :roster do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  	primary_key :id
         
     | 
| 
      
 11 
     | 
    
         
            +
                  	column :contact_id, :integer
         
     | 
| 
      
 12 
     | 
    
         
            +
                    column :jid, :text, :unique=>true
         
     | 
| 
      
 13 
     | 
    
         
            +
                  	column :status, :text
         
     | 
| 
      
 14 
     | 
    
         
            +
                    column :client_name, :text
         
     | 
| 
      
 15 
     | 
    
         
            +
                    column :client_version, :text
         
     | 
| 
      
 16 
     | 
    
         
            +
                    column :client_os, :text
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  in_memory_db.create_table :services do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  	primary_key :id
         
     | 
| 
      
 20 
     | 
    
         
            +
                    column :jid, :text
         
     | 
| 
      
 21 
     | 
    
         
            +
                    column :name, :text
         
     | 
| 
      
 22 
     | 
    
         
            +
                    column :category, :text
         
     | 
| 
      
 23 
     | 
    
         
            +
                    column :type, :text
         
     | 
| 
      
 24 
     | 
    
         
            +
                    column :node, :text
         
     | 
| 
      
 25 
     | 
    
         
            +
                    unique [:node, :jid]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  in_memory_db.create_table :service_items do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  	primary_key :id
         
     | 
| 
      
 29 
     | 
    
         
            +
                    column :parent_node, :text
         
     | 
| 
      
 30 
     | 
    
         
            +
                    column :service, :text
         
     | 
| 
      
 31 
     | 
    
         
            +
                    column :node, :text
         
     | 
| 
      
 32 
     | 
    
         
            +
                    column :jid, :text
         
     | 
| 
      
 33 
     | 
    
         
            +
                    column :name, :text
         
     | 
| 
      
 34 
     | 
    
         
            +
                    unique [:node, :service]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  in_memory_db.create_table :service_features do
         
     | 
| 
      
 37 
     | 
    
         
            +
                  	primary_key :id
         
     | 
| 
      
 38 
     | 
    
         
            +
                    column :node, :text
         
     | 
| 
      
 39 
     | 
    
         
            +
                    column :service, :text
         
     | 
| 
      
 40 
     | 
    
         
            +
                    column :var, :text
         
     | 
| 
      
 41 
     | 
    
         
            +
                    unique [:node, :service, :var]
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  in_memory_db.create_table :publications do
         
     | 
| 
      
 44 
     | 
    
         
            +
                  	primary_key :id
         
     | 
| 
      
 45 
     | 
    
         
            +
                    column :node, :text, :unique=>true
         
     | 
| 
      
 46 
     | 
    
         
            +
                    column :status, :text
         
     | 
| 
      
 47 
     | 
    
         
            +
                    column :title, :text
         
     | 
| 
      
 48 
     | 
    
         
            +
                    column :access_model, :text
         
     | 
| 
      
 49 
     | 
    
         
            +
                    column :max_items, :integer
         
     | 
| 
      
 50 
     | 
    
         
            +
                    column :deliver_notifications, :integer
         
     | 
| 
      
 51 
     | 
    
         
            +
                    column :deliver_payloads, :integer
         
     | 
| 
      
 52 
     | 
    
         
            +
                    column :persist_items, :integer
         
     | 
| 
      
 53 
     | 
    
         
            +
                    column :subscribe, :integer
         
     | 
| 
      
 54 
     | 
    
         
            +
                    column :notify_config, :integer
         
     | 
| 
      
 55 
     | 
    
         
            +
                    column :notify_delete, :integer
         
     | 
| 
      
 56 
     | 
    
         
            +
                    column :notify_retract, :integer
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  in_memory_db.create_table :subscriptions do
         
     | 
| 
      
 59 
     | 
    
         
            +
                  	primary_key :id
         
     | 
| 
      
 60 
     | 
    
         
            +
                    column :node, :text, :unique=>true
         
     | 
| 
      
 61 
     | 
    
         
            +
                    column :service, :text
         
     | 
| 
      
 62 
     | 
    
         
            +
                    column :subscription, :text
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                #####-----------------------------------------------------------------------------------------------------
         
     | 
| 
      
 67 
     | 
    
         
            +
                def create_agent_xmpp_db
         
     | 
| 
      
 68 
     | 
    
         
            +
                  unless agent_xmpp_db.table_exists? :version
         
     | 
| 
      
 69 
     | 
    
         
            +
                    agent_xmpp_db.create_table :version do
         
     | 
| 
      
 70 
     | 
    
         
            +
                    	primary_key :id
         
     | 
| 
      
 71 
     | 
    
         
            +
                      integer :number
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                  version << {:number=>1} if version.count.eql?(0)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  unless agent_xmpp_db.table_exists? :contacts
         
     | 
| 
      
 76 
     | 
    
         
            +
                    agent_xmpp_db.create_table :contacts do
         
     | 
| 
      
 77 
     | 
    
         
            +
                    	primary_key :id
         
     | 
| 
      
 78 
     | 
    
         
            +
                    	column :jid, :text, :unique=>true
         
     | 
| 
      
 79 
     | 
    
         
            +
                      column :ask, :text
         
     | 
| 
      
 80 
     | 
    
         
            +
                      column :subscription, :text
         
     | 
| 
      
 81 
     | 
    
         
            +
                    	column :groups, :text
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                  unless agent_xmpp_db.table_exists? :messages
         
     | 
| 
      
 85 
     | 
    
         
            +
                    agent_xmpp_db.create_table :messages do
         
     | 
| 
      
 86 
     | 
    
         
            +
                    	primary_key :id
         
     | 
| 
      
 87 
     | 
    
         
            +
                    	column :message_text, :text
         
     | 
| 
      
 88 
     | 
    
         
            +
                    	column :content_type, :text
         
     | 
| 
      
 89 
     | 
    
         
            +
                    	column :message_type, :text
         
     | 
| 
      
 90 
     | 
    
         
            +
                    	column :to_jid, :text
         
     | 
| 
      
 91 
     | 
    
         
            +
                    	column :from_jid, :text
         
     | 
| 
      
 92 
     | 
    
         
            +
                    	column :node, :text
         
     | 
| 
      
 93 
     | 
    
         
            +
                    	column :item_id, :text
         
     | 
| 
      
 94 
     | 
    
         
            +
                      Time :created_at
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                #####-----------------------------------------------------------------------------------------------------
         
     | 
| 
      
 100 
     | 
    
         
            +
                def upgrade_agent_xmpp_db
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              #### self
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
                
         
     | 
| 
      
 106 
     | 
    
         
            +
            #### AgentXmpp 
         
     | 
| 
      
 107 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            class Array
         
     | 
| 
      
 3 
     | 
    
         
            +
              
         
     | 
| 
      
 4 
     | 
    
         
            +
              #......................................................................................................
         
     | 
| 
      
 5 
     | 
    
         
            +
              def to_x_data(type = 'result')
         
     | 
| 
      
 6 
     | 
    
         
            +
                data = AgentXmpp::Xmpp::XData.new(type)
         
     | 
| 
      
 7 
     | 
    
         
            +
                if first.kind_of?(Hash)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  field_type = lambda{|v| v.kind_of?(Array) ? 'list-multi' : nil}
         
     | 
| 
      
 9 
     | 
    
         
            +
                  reported = AgentXmpp::Xmpp::XDataReported.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                  first.each_key {|var| reported.add_field(var.to_s)}
         
     | 
| 
      
 11 
     | 
    
         
            +
                  data << reported
         
     | 
| 
      
 12 
     | 
    
         
            +
                  each do |fields|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    item = AgentXmpp::Xmpp::XDataItem.new
         
     | 
| 
      
 14 
     | 
    
         
            +
                    fields.each{|var, val| item.add_field_with_value(var.to_s, [val].flatten.collect{|v| v.to_s}, field_type[val])}
         
     | 
| 
      
 15 
     | 
    
         
            +
                    data << item
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                else
         
     | 
| 
      
 18 
     | 
    
         
            +
                  field = AgentXmpp::Xmpp::XDataField.new
         
     | 
| 
      
 19 
     | 
    
         
            +
                  field.values = map{|v| v.to_s}
         
     | 
| 
      
 20 
     | 
    
         
            +
                  field.type ='list-multi'
         
     | 
| 
      
 21 
     | 
    
         
            +
                  data << field
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
                data
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              
         
     | 
| 
      
 26 
     | 
    
         
            +
              #......................................................................................................
         
     | 
| 
      
 27 
     | 
    
         
            +
              def smash
         
     | 
| 
      
 28 
     | 
    
         
            +
                self.flatten.compact
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    
         
     | 
| 
      
 31 
     | 
    
         
            +
            #### Array
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,10 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            class Float  
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              #......................................................................................................
         
     | 
| 
      
 5 
     | 
    
         
            +
              def precision(p = 3)
         
     | 
| 
      
 6 
     | 
    
         
            +
                (10.0**p*self).round.to_f/10.0**p
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
                    
         
     | 
| 
      
 9 
     | 
    
         
            +
            #### Float
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            class Hash  
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              #.......................................................................................................
         
     | 
| 
      
 5 
     | 
    
         
            +
              def to_x_data(type = 'result')
         
     | 
| 
      
 6 
     | 
    
         
            +
                field_type = lambda{|v| v.kind_of?(Array) ? 'list-multi' : nil}
         
     | 
| 
      
 7 
     | 
    
         
            +
                inject(AgentXmpp::Xmpp::XData.new(type)) do |data, (var, val)| 
         
     | 
| 
      
 8 
     | 
    
         
            +
                  data.add_field_with_value(var, [val].flatten.map{|v| v.to_s}, field_type[val])
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
                    
         
     | 
| 
      
 12 
     | 
    
         
            +
            #### Hash
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            class Object  
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              #.......................................................................................................
         
     | 
| 
      
 5 
     | 
    
         
            +
              def to_x_data(type='result')
         
     | 
| 
      
 6 
     | 
    
         
            +
                AgentXmpp::Xmpp::XData.new(type).add_field_with_value(nil, to_s)
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              #.......................................................................................................
         
     | 
| 
      
 10 
     | 
    
         
            +
              def define_meta_class_method(name, &blk)
         
     | 
| 
      
 11 
     | 
    
         
            +
                (class << self; self; end).instance_eval {define_method(name, &blk)}
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            #### Object
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Original from XMPP4R - XMPP Library for Ruby Website::http://home.gna.org/xmpp4r/
         
     | 
| 
      
 2 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 3 
     | 
    
         
            +
            module REXML
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              ####----------------------------------------------------------------------------------------------------
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Element
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 9 
     | 
    
         
            +
                def replace_element_text(e, t)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  el = first_element(e)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  if el.nil?
         
     | 
| 
      
 12 
     | 
    
         
            +
                    el = REXML::Element.new(e)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    add_element(el)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  el.text = t if t
         
     | 
| 
      
 16 
     | 
    
         
            +
                  self
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 20 
     | 
    
         
            +
                def first_element(e)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  elements.to_a(e).first
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 25 
     | 
    
         
            +
                def first_element_text(e)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  el = first_element(e)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  el.nil? ? nil : el.text
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 31 
     | 
    
         
            +
                def typed_add(e)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  add(e)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 36 
     | 
    
         
            +
                def import(xmlelement)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  if @name and @name != xmlelement.name
         
     | 
| 
      
 38 
     | 
    
         
            +
                    raise "Trying to import an #{xmlelement.name} to a #{@name} !"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  add_attributes(xmlelement.attributes.clone)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @context = xmlelement.context
         
     | 
| 
      
 42 
     | 
    
         
            +
                  xmlelement.each do |e|
         
     | 
| 
      
 43 
     | 
    
         
            +
                    if e.kind_of? REXML::Element
         
     | 
| 
      
 44 
     | 
    
         
            +
                      typed_add(e.deep_clone)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    elsif e.kind_of? REXML::Text
         
     | 
| 
      
 46 
     | 
    
         
            +
                      add_text(e.value)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    else
         
     | 
| 
      
 48 
     | 
    
         
            +
                      add(e.clone)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  self
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 55 
     | 
    
         
            +
                def self.import(xmlelement)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  self.new(xmlelement.name).import(xmlelement)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                #.......................................................................................................
         
     | 
| 
      
 60 
     | 
    
         
            +
                def delete_elements(element)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  elements.delete_all(element)
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              #### Element
         
     | 
| 
      
 65 
     | 
    
         
            +
              end 
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            #### REXML
         
     | 
| 
      
 68 
     | 
    
         
            +
            end 
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 2 
     | 
    
         
            +
            class String
         
     | 
| 
      
 3 
     | 
    
         
            +
                  
         
     | 
| 
      
 4 
     | 
    
         
            +
              #......................................................................................................
         
     | 
| 
      
 5 
     | 
    
         
            +
              def classify
         
     | 
| 
      
 6 
     | 
    
         
            +
                split('_').collect{|s| s.capitalize}.join
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              #......................................................................................................
         
     | 
| 
      
 10 
     | 
    
         
            +
              def humanize
         
     | 
| 
      
 11 
     | 
    
         
            +
                gsub(/_/, ' ')
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            #### String
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/element'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/x_data'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/error_response'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/entry'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/stanza'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/message'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/presence'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/iq'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/jid'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/sasl'
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/iq_command'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/iq_version'
         
     | 
| 
      
 16 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/iq_roster'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/iq_disco'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 'agent_xmpp/xmpp/iq_pubsub'
         
     | 
| 
         @@ -0,0 +1,158 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Original from XMPP4R - XMPP Library for Ruby Website::http://home.gna.org/xmpp4r/
         
     | 
| 
      
 2 
     | 
    
         
            +
            ##############################################################################################################
         
     | 
| 
      
 3 
     | 
    
         
            +
            module AgentXmpp
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              #####-------------------------------------------------------------------------------------------------------
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Xmpp
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                #####-------------------------------------------------------------------------------------------------------
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Element < REXML::Element
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @@name_xmlns_classes = {}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  #####-------------------------------------------------------------------------------------------------------
         
     | 
| 
      
 15 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 16 
     | 
    
         
            +
                    
         
     | 
| 
      
 17 
     | 
    
         
            +
                    #.......................................................................................................
         
     | 
| 
      
 18 
     | 
    
         
            +
                    def name_xmlns(name, xmlns=nil)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @@name_xmlns_classes[[name, xmlns]] = self
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    #.......................................................................................................
         
     | 
| 
      
 23 
     | 
    
         
            +
                    def name_xmlns_for_class(klass)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      klass.ancestors.each do |klass1|
         
     | 
| 
      
 25 
     | 
    
         
            +
                        @@name_xmlns_classes.each do |name_xmlns,k|
         
     | 
| 
      
 26 
     | 
    
         
            +
                          if klass1 == k
         
     | 
| 
      
 27 
     | 
    
         
            +
                            return name_xmlns
         
     | 
| 
      
 28 
     | 
    
         
            +
                          end
         
     | 
| 
      
 29 
     | 
    
         
            +
                        end
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
                      raise NoNameXmlnsRegistered.new(klass)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    #.......................................................................................................
         
     | 
| 
      
 35 
     | 
    
         
            +
                    def class_for_name_xmlns(name, xmlns)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      if @@name_xmlns_classes.has_key? [name, xmlns]
         
     | 
| 
      
 37 
     | 
    
         
            +
                        @@name_xmlns_classes[[name, xmlns]]
         
     | 
| 
      
 38 
     | 
    
         
            +
                      elsif @@name_xmlns_classes.has_key? [name, nil]
         
     | 
| 
      
 39 
     | 
    
         
            +
                        @@name_xmlns_classes[[name, nil]]
         
     | 
| 
      
 40 
     | 
    
         
            +
                      else
         
     | 
| 
      
 41 
     | 
    
         
            +
                        REXML::Element
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    #.......................................................................................................
         
     | 
| 
      
 46 
     | 
    
         
            +
                    def import(element)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      klass = class_for_name_xmlns(element.name, element.namespace)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      if klass != self and klass.ancestors.include?(self)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        klass.new.import(element)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      else
         
     | 
| 
      
 51 
     | 
    
         
            +
                        self.new.import(element)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                    
         
     | 
| 
      
 55 
     | 
    
         
            +
                    #.....................................................................................................
         
     | 
| 
      
 56 
     | 
    
         
            +
                    def xmpp_attribute(*args)
         
     | 
| 
      
 57 
     | 
    
         
            +
                      sym = (args.pop[:sym] if args.last.kind_of?(Hash)).nil? ? '' : '.to_sym'
         
     | 
| 
      
 58 
     | 
    
         
            +
                      args.each do |a|
         
     | 
| 
      
 59 
     | 
    
         
            +
                        class_eval <<-DEF
         
     | 
| 
      
 60 
     | 
    
         
            +
                          def #{a.to_s}
         
     | 
| 
      
 61 
     | 
    
         
            +
                            attr = attributes['#{a.to_s}']
         
     | 
| 
      
 62 
     | 
    
         
            +
                            attr.nil? ? nil : attr#{sym}
         
     | 
| 
      
 63 
     | 
    
         
            +
                          end
         
     | 
| 
      
 64 
     | 
    
         
            +
                          def #{a.to_s}=(v)
         
     | 
| 
      
 65 
     | 
    
         
            +
                            attributes['#{a.to_s}'] = v.to_s
         
     | 
| 
      
 66 
     | 
    
         
            +
                          end
         
     | 
| 
      
 67 
     | 
    
         
            +
                        DEF
         
     | 
| 
      
 68 
     | 
    
         
            +
                      end
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    
         
     | 
| 
      
 71 
     | 
    
         
            +
                    #.......................................................................................................
         
     | 
| 
      
 72 
     | 
    
         
            +
                    def xmpp_child(*args)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      args.each do |a|
         
     | 
| 
      
 74 
     | 
    
         
            +
                        class_eval <<-DEF
         
     | 
| 
      
 75 
     | 
    
         
            +
                          def #{a.to_s}
         
     | 
| 
      
 76 
     | 
    
         
            +
                            first_element('#{a.to_s}')
         
     | 
| 
      
 77 
     | 
    
         
            +
                          end
         
     | 
| 
      
 78 
     | 
    
         
            +
                          def #{a.to_s}=(v)
         
     | 
| 
      
 79 
     | 
    
         
            +
                            delete_elements(v.name)
         
     | 
| 
      
 80 
     | 
    
         
            +
                            add(v)
         
     | 
| 
      
 81 
     | 
    
         
            +
                          end
         
     | 
| 
      
 82 
     | 
    
         
            +
                        DEF
         
     | 
| 
      
 83 
     | 
    
         
            +
                      end
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  #### self
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  
         
     | 
| 
      
 89 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 90 
     | 
    
         
            +
                  def initialize(*arg)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    if arg.empty?
         
     | 
| 
      
 92 
     | 
    
         
            +
                      name, xmlns = self.class::name_xmlns_for_class(self.class)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      super(name)
         
     | 
| 
      
 94 
     | 
    
         
            +
                      add_namespace(xmlns)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    else
         
     | 
| 
      
 96 
     | 
    
         
            +
                      super
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 101 
     | 
    
         
            +
                  def typed_add(element)
         
     | 
| 
      
 102 
     | 
    
         
            +
                    if element.kind_of? REXML::Element
         
     | 
| 
      
 103 
     | 
    
         
            +
                      element_ns = (element.namespace.to_s == '') ? namespace : element.namespace
         
     | 
| 
      
 104 
     | 
    
         
            +
                      klass = Element::class_for_name_xmlns(element.name, element_ns)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      if klass != element.class
         
     | 
| 
      
 106 
     | 
    
         
            +
                        element = klass.import(element)
         
     | 
| 
      
 107 
     | 
    
         
            +
                      end
         
     | 
| 
      
 108 
     | 
    
         
            +
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
                    super(element)
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 113 
     | 
    
         
            +
                  def parent=(new_parent)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    if parent and parent.namespace('') == namespace('') and attributes['xmlns'].nil?
         
     | 
| 
      
 115 
     | 
    
         
            +
                      add_namespace parent.namespace('')
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
                    super
         
     | 
| 
      
 118 
     | 
    
         
            +
                    if new_parent and new_parent.namespace('') == namespace('')
         
     | 
| 
      
 119 
     | 
    
         
            +
                      delete_namespace
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 124 
     | 
    
         
            +
                  def clone
         
     | 
| 
      
 125 
     | 
    
         
            +
                    cloned = self.class.new
         
     | 
| 
      
 126 
     | 
    
         
            +
                    cloned.add_attributes self.attributes.clone
         
     | 
| 
      
 127 
     | 
    
         
            +
                    cloned.context = @context
         
     | 
| 
      
 128 
     | 
    
         
            +
                    cloned
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 132 
     | 
    
         
            +
                  def xml_lang
         
     | 
| 
      
 133 
     | 
    
         
            +
                    attributes['xml:lang']
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 137 
     | 
    
         
            +
                  def xml_lang=(l)
         
     | 
| 
      
 138 
     | 
    
         
            +
                    attributes['xml:lang'] = l
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  #.......................................................................................................
         
     | 
| 
      
 142 
     | 
    
         
            +
                  def set_xml_lang(l)
         
     | 
| 
      
 143 
     | 
    
         
            +
                    self.xml_lang = l; self
         
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
                  
         
     | 
| 
      
 146 
     | 
    
         
            +
                  #.....................................................................................................
         
     | 
| 
      
 147 
     | 
    
         
            +
                  def <<(child)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    add(child); self
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
                  
         
     | 
| 
      
 151 
     | 
    
         
            +
                #### Element
         
     | 
| 
      
 152 
     | 
    
         
            +
                end  
         
     | 
| 
      
 153 
     | 
    
         
            +
                  
         
     | 
| 
      
 154 
     | 
    
         
            +
              #### XMPP
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
            #### AgentXmpp
         
     | 
| 
      
 158 
     | 
    
         
            +
            end
         
     |