Mercurial > prosody-hg
comparison plugins/muc/muc.lib.lua @ 6094:db2faeb151b6
plugins/muc/muc.lib: Factor `handle_to_occupant` out into many functions
| author | daurnimator <quae@daurnimator.com> |
|---|---|
| date | Thu, 20 Feb 2014 16:50:18 -0500 |
| parents | 9a7eaf0a35b6 |
| children | 7900ebc544ce |
comparison
equal
deleted
inserted
replaced
| 6093:9a7eaf0a35b6 | 6094:db2faeb151b6 |
|---|---|
| 402 return from_nick, to_jid, id; | 402 return from_nick, to_jid, id; |
| 403 end | 403 end |
| 404 end | 404 end |
| 405 end | 405 end |
| 406 | 406 |
| 407 function room_mt:handle_presence_error_to_occupant(origin, stanza) | |
| 408 local current_nick = self._jid_nick[stanza.attr.from]; | |
| 409 if not current_nick then | |
| 410 return true -- discard | |
| 411 end | |
| 412 log("debug", "kicking %s from %s", current_nick, self.jid); | |
| 413 return self:handle_to_occupant(origin, build_unavailable_presence_from_error(stanza)) | |
| 414 end | |
| 415 | |
| 416 function room_mt:handle_unavailable_to_occupant(origin, stanza) | |
| 417 local from = stanza.attr.from; | |
| 418 local current_nick = self._jid_nick[from]; | |
| 419 if not current_nick then | |
| 420 return true; -- discard | |
| 421 end | |
| 422 local pr = get_filtered_presence(stanza); | |
| 423 pr.attr.from = current_nick; | |
| 424 log("debug", "%s leaving %s", current_nick, self.jid); | |
| 425 self._jid_nick[from] = nil; | |
| 426 local occupant = self._occupants[current_nick]; | |
| 427 local new_jid = next(occupant.sessions); | |
| 428 if new_jid == from then new_jid = next(occupant.sessions, new_jid); end | |
| 429 if new_jid then | |
| 430 local jid = occupant.jid; | |
| 431 occupant.jid = new_jid; | |
| 432 occupant.sessions[from] = nil; | |
| 433 pr.attr.to = from; | |
| 434 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
| 435 :tag("item", {affiliation=occupant.affiliation or "none", role='none'}):up() | |
| 436 :tag("status", {code='110'}):up(); | |
| 437 self:_route_stanza(pr); | |
| 438 if jid ~= new_jid then | |
| 439 pr = st.clone(occupant.sessions[new_jid]) | |
| 440 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
| 441 :tag("item", {affiliation=occupant.affiliation or "none", role=occupant.role or "none"}); | |
| 442 pr.attr.from = current_nick; | |
| 443 self:broadcast_except_nick(pr, current_nick); | |
| 444 end | |
| 445 else | |
| 446 occupant.role = 'none'; | |
| 447 self:broadcast_presence(pr, from); | |
| 448 self._occupants[current_nick] = nil; | |
| 449 end | |
| 450 return true; | |
| 451 end | |
| 452 | |
| 453 function room_mt:handle_occupant_presence(origin, stanza) | |
| 454 local from = stanza.attr.from; | |
| 455 local pr = get_filtered_presence(stanza); | |
| 456 local current_nick = stanza.attr.to | |
| 457 pr.attr.from = current_nick; | |
| 458 log("debug", "%s broadcasted presence", current_nick); | |
| 459 self._occupants[current_nick].sessions[from] = pr; | |
| 460 self:broadcast_presence(pr, from); | |
| 461 return true; | |
| 462 end | |
| 463 | |
| 464 function room_mt:handle_change_nick(origin, stanza, current_nick, to) | |
| 465 local from = stanza.attr.from; | |
| 466 local occupant = self._occupants[current_nick]; | |
| 467 local is_multisession = next(occupant.sessions, next(occupant.sessions)); | |
| 468 if self._occupants[to] or is_multisession then | |
| 469 log("debug", "%s couldn't change nick", current_nick); | |
| 470 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); | |
| 471 reply.tags[1].attr.code = "409"; | |
| 472 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 473 return true; | |
| 474 else | |
| 475 local data = self._occupants[current_nick]; | |
| 476 local to_nick = select(3, jid_split(to)); | |
| 477 log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); | |
| 478 local p = st.presence({type='unavailable', from=current_nick}); | |
| 479 self:broadcast_presence(p, from, '303', to_nick); | |
| 480 self._occupants[current_nick] = nil; | |
| 481 self._occupants[to] = data; | |
| 482 self._jid_nick[from] = to; | |
| 483 local pr = get_filtered_presence(stanza); | |
| 484 pr.attr.from = to; | |
| 485 self._occupants[to].sessions[from] = pr; | |
| 486 self:broadcast_presence(pr, from); | |
| 487 return true; | |
| 488 end | |
| 489 end | |
| 490 | |
| 491 function room_mt:handle_join(origin, stanza) | |
| 492 local from, to = stanza.attr.from, stanza.attr.to; | |
| 493 log("debug", "%s joining as %s", from, to); | |
| 494 if not next(self._affiliations) then -- new room, no owners | |
| 495 self._affiliations[jid_bare(from)] = "owner"; | |
| 496 if self.locked and not stanza:get_child("x", "http://jabber.org/protocol/muc") then | |
| 497 self.locked = nil; -- Older groupchat protocol doesn't lock | |
| 498 end | |
| 499 elseif self.locked then -- Deny entry | |
| 500 origin.send(st.error_reply(stanza, "cancel", "item-not-found")); | |
| 501 return true; | |
| 502 end | |
| 503 local affiliation = self:get_affiliation(from); | |
| 504 local role = self:get_default_role(affiliation) | |
| 505 if role then -- new occupant | |
| 506 local is_merge = not not self._occupants[to] | |
| 507 if not is_merge then | |
| 508 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; | |
| 509 else | |
| 510 self._occupants[to].sessions[from] = get_filtered_presence(stanza); | |
| 511 end | |
| 512 self._jid_nick[from] = to; | |
| 513 self:send_occupant_list(from); | |
| 514 local pr = get_filtered_presence(stanza); | |
| 515 pr.attr.from = to; | |
| 516 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
| 517 :tag("item", {affiliation=affiliation or "none", role=role or "none"}):up(); | |
| 518 if not is_merge then | |
| 519 self:broadcast_except_nick(pr, to); | |
| 520 end | |
| 521 pr:tag("status", {code='110'}):up(); | |
| 522 if self._data.whois == 'anyone' then | |
| 523 pr:tag("status", {code='100'}):up(); | |
| 524 end | |
| 525 if self.locked then | |
| 526 pr:tag("status", {code='201'}):up(); | |
| 527 end | |
| 528 pr.attr.to = from; | |
| 529 self:_route_stanza(pr); | |
| 530 self:send_history(from, stanza); | |
| 531 self:send_subject(from); | |
| 532 return true; | |
| 533 elseif not affiliation then -- registration required for entering members-only room | |
| 534 local reply = st.error_reply(stanza, "auth", "registration-required"):up(); | |
| 535 reply.tags[1].attr.code = "407"; | |
| 536 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 537 return true; | |
| 538 else -- banned | |
| 539 local reply = st.error_reply(stanza, "auth", "forbidden"):up(); | |
| 540 reply.tags[1].attr.code = "403"; | |
| 541 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 542 return true; | |
| 543 end | |
| 544 end | |
| 545 | |
| 546 function room_mt:handle_available_to_occupant(origin, stanza) | |
| 547 local from, to = stanza.attr.from, stanza.attr.to; | |
| 548 local current_nick = self._jid_nick[from]; | |
| 549 if current_nick then | |
| 550 --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence | |
| 551 if current_nick == to then -- simple presence | |
| 552 return self:handle_occupant_presence(origin, stanza) | |
| 553 else -- change nick | |
| 554 return self:handle_change_nick(origin, stanza, current_nick, to) | |
| 555 end | |
| 556 --else -- possible rejoin | |
| 557 -- log("debug", "%s had connection replaced", current_nick); | |
| 558 -- self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}) | |
| 559 -- :tag('status'):text('Replaced by new connection'):up()); -- send unavailable | |
| 560 -- self:handle_to_occupant(origin, stanza); -- resend available | |
| 561 --end | |
| 562 else -- enter room | |
| 563 local new_nick = to; | |
| 564 if self._occupants[to] then | |
| 565 if jid_bare(from) ~= jid_bare(self._occupants[to].jid) then | |
| 566 new_nick = nil; | |
| 567 end | |
| 568 end | |
| 569 local password = stanza:get_child("x", "http://jabber.org/protocol/muc"); | |
| 570 password = password and password:get_child("password", "http://jabber.org/protocol/muc"); | |
| 571 password = password and password[1] ~= "" and password[1]; | |
| 572 if self:get_password() and self:get_password() ~= password then | |
| 573 log("debug", "%s couldn't join due to invalid password: %s", from, to); | |
| 574 local reply = st.error_reply(stanza, "auth", "not-authorized"):up(); | |
| 575 reply.tags[1].attr.code = "401"; | |
| 576 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 577 return true; | |
| 578 elseif not new_nick then | |
| 579 log("debug", "%s couldn't join due to nick conflict: %s", from, to); | |
| 580 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); | |
| 581 reply.tags[1].attr.code = "409"; | |
| 582 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 583 return true; | |
| 584 else | |
| 585 return self:handle_join(origin, stanza) | |
| 586 end | |
| 587 end | |
| 588 end | |
| 589 | |
| 590 function room_mt:handle_presence_to_occupant(origin, stanza) | |
| 591 local type = stanza.attr.type; | |
| 592 if type == "error" then -- error, kick em out! | |
| 593 return self:handle_presence_error_to_occupant(origin, stanza) | |
| 594 elseif type == "unavailable" then -- unavailable | |
| 595 return self:handle_unavailable_to_occupant(origin, stanza) | |
| 596 elseif not type then -- available | |
| 597 return self:handle_available_to_occupant(origin, stanza) | |
| 598 elseif type ~= 'result' then -- bad type | |
| 599 if type ~= 'visible' and type ~= 'invisible' then -- COMPAT ejabberd can broadcast or forward XEP-0018 presences | |
| 600 origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error? | |
| 601 end | |
| 602 end | |
| 603 return true; | |
| 604 end | |
| 605 | |
| 606 function room_mt:handle_private(origin, stanza) | |
| 607 local from, to = stanza.attr.from, stanza.attr.to; | |
| 608 local current_nick = self._jid_nick[from]; | |
| 609 local type = stanza.attr.type; | |
| 610 local o_data = self._occupants[to]; | |
| 611 if o_data then | |
| 612 log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid); | |
| 613 if stanza.name == "iq" then | |
| 614 local id = stanza.attr.id; | |
| 615 if stanza.attr.type == "get" or stanza.attr.type == "set" then | |
| 616 stanza.attr.from, stanza.attr.to, stanza.attr.id = construct_stanza_id(self, stanza); | |
| 617 else | |
| 618 stanza.attr.from, stanza.attr.to, stanza.attr.id = deconstruct_stanza_id(self, stanza); | |
| 619 end | |
| 620 if type == 'get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then | |
| 621 stanza.attr.to = jid_bare(stanza.attr.to); | |
| 622 end | |
| 623 if stanza.attr.id then | |
| 624 self:_route_stanza(stanza); | |
| 625 end | |
| 626 stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id; | |
| 627 else -- message | |
| 628 stanza:tag("x", { xmlns = "http://jabber.org/protocol/muc#user" }):up(); | |
| 629 stanza.attr.from = current_nick; | |
| 630 for jid in pairs(o_data.sessions) do | |
| 631 stanza.attr.to = jid; | |
| 632 self:_route_stanza(stanza); | |
| 633 end | |
| 634 stanza.attr.from, stanza.attr.to = from, to; | |
| 635 end | |
| 636 elseif type ~= "error" and type ~= "result" then -- recipient not in room | |
| 637 origin.send(st.error_reply(stanza, "cancel", "item-not-found", "Recipient not in room")); | |
| 638 end | |
| 639 return true; | |
| 640 end | |
| 641 | |
| 642 function room_mt:handle_iq_to_occupant(origin, stanza) | |
| 643 local from, to = stanza.attr.from, stanza.attr.to; | |
| 644 local current_nick = self._jid_nick[from]; | |
| 645 if not current_nick then | |
| 646 local type = stanza.attr.type; | |
| 647 if (type == "error" or type == "result") then | |
| 648 local id = stanza.attr.id; | |
| 649 stanza.attr.from, stanza.attr.to, stanza.attr.id = deconstruct_stanza_id(self, stanza); | |
| 650 if stanza.attr.id then | |
| 651 self:_route_stanza(stanza); | |
| 652 end | |
| 653 stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id; | |
| 654 else | |
| 655 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); | |
| 656 end | |
| 657 return true; | |
| 658 else | |
| 659 return self:handle_private(origin, stanza) | |
| 660 end | |
| 661 end | |
| 662 | |
| 663 function room_mt:handle_message_to_occupant(origin, stanza) | |
| 664 local current_nick = self._jid_nick[stanza.attr.from]; | |
| 665 local type = stanza.attr.type; | |
| 666 if not current_nick then -- not in room | |
| 667 if type ~= "error" then | |
| 668 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); | |
| 669 end | |
| 670 return true; | |
| 671 end | |
| 672 if type == "groupchat" then -- groupchat messages not allowed in PM | |
| 673 origin.send(st.error_reply(stanza, "modify", "bad-request")); | |
| 674 return true; | |
| 675 elseif type == "error" and is_kickable_error(stanza) then | |
| 676 log("debug", "%s kicked from %s for sending an error message", current_nick, self.jid); | |
| 677 return self:handle_to_occupant(origin, build_unavailable_presence_from_error(stanza)); -- send unavailable | |
| 678 else -- private stanza | |
| 679 return self:handle_private(origin, stanza) | |
| 680 end | |
| 681 end | |
| 407 | 682 |
| 408 function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc | 683 function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc |
| 409 local from, to = stanza.attr.from, stanza.attr.to; | 684 local from, to = stanza.attr.from, stanza.attr.to; |
| 410 local room = jid_bare(to); | 685 local room = jid_bare(to); |
| 411 local current_nick = self._jid_nick[from]; | 686 local current_nick = self._jid_nick[from]; |
| 412 local type = stanza.attr.type; | 687 local type = stanza.attr.type; |
| 413 log("debug", "room: %s, current_nick: %s, stanza: %s", room or "nil", current_nick or "nil", stanza:top_tag()); | 688 log("debug", "room: %s, current_nick: %s, stanza: %s", room or "nil", current_nick or "nil", stanza:top_tag()); |
| 414 if (select(2, jid_split(from)) == muc_domain) then error("Presence from the MUC itself!!!"); end | 689 if (select(2, jid_split(from)) == muc_domain) then error("Presence from the MUC itself!!!"); end |
| 415 if stanza.name == "presence" then | 690 if stanza.name == "presence" then |
| 416 local pr = get_filtered_presence(stanza); | 691 return self:handle_presence_to_occupant(origin, stanza) |
| 417 pr.attr.from = current_nick; | 692 elseif stanza.name == "iq" then |
| 418 if type == "error" then -- error, kick em out! | 693 return self:handle_iq_to_occupant(origin, stanza) |
| 419 if current_nick then | 694 elseif stanza.name == "message" then |
| 420 log("debug", "kicking %s from %s", current_nick, room); | 695 return self:handle_message_to_occupant(origin, stanza) |
| 421 self:handle_to_occupant(origin, build_unavailable_presence_from_error(stanza)); | |
| 422 end | |
| 423 elseif type == "unavailable" then -- unavailable | |
| 424 if current_nick then | |
| 425 log("debug", "%s leaving %s", current_nick, room); | |
| 426 self._jid_nick[from] = nil; | |
| 427 local occupant = self._occupants[current_nick]; | |
| 428 local new_jid = next(occupant.sessions); | |
| 429 if new_jid == from then new_jid = next(occupant.sessions, new_jid); end | |
| 430 if new_jid then | |
| 431 local jid = occupant.jid; | |
| 432 occupant.jid = new_jid; | |
| 433 occupant.sessions[from] = nil; | |
| 434 pr.attr.to = from; | |
| 435 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
| 436 :tag("item", {affiliation=occupant.affiliation or "none", role='none'}):up() | |
| 437 :tag("status", {code='110'}):up(); | |
| 438 self:_route_stanza(pr); | |
| 439 if jid ~= new_jid then | |
| 440 pr = st.clone(occupant.sessions[new_jid]) | |
| 441 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
| 442 :tag("item", {affiliation=occupant.affiliation or "none", role=occupant.role or "none"}); | |
| 443 pr.attr.from = current_nick; | |
| 444 self:broadcast_except_nick(pr, current_nick); | |
| 445 end | |
| 446 else | |
| 447 occupant.role = 'none'; | |
| 448 self:broadcast_presence(pr, from); | |
| 449 self._occupants[current_nick] = nil; | |
| 450 end | |
| 451 end | |
| 452 elseif not type then -- available | |
| 453 if current_nick then | |
| 454 --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence | |
| 455 if current_nick == to then -- simple presence | |
| 456 log("debug", "%s broadcasted presence", current_nick); | |
| 457 self._occupants[current_nick].sessions[from] = pr; | |
| 458 self:broadcast_presence(pr, from); | |
| 459 else -- change nick | |
| 460 local occupant = self._occupants[current_nick]; | |
| 461 local is_multisession = next(occupant.sessions, next(occupant.sessions)); | |
| 462 if self._occupants[to] or is_multisession then | |
| 463 log("debug", "%s couldn't change nick", current_nick); | |
| 464 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); | |
| 465 reply.tags[1].attr.code = "409"; | |
| 466 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 467 else | |
| 468 local data = self._occupants[current_nick]; | |
| 469 local to_nick = select(3, jid_split(to)); | |
| 470 if to_nick then | |
| 471 log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); | |
| 472 local p = st.presence({type='unavailable', from=current_nick}); | |
| 473 self:broadcast_presence(p, from, '303', to_nick); | |
| 474 self._occupants[current_nick] = nil; | |
| 475 self._occupants[to] = data; | |
| 476 self._jid_nick[from] = to; | |
| 477 pr.attr.from = to; | |
| 478 self._occupants[to].sessions[from] = pr; | |
| 479 self:broadcast_presence(pr, from); | |
| 480 else | |
| 481 --TODO malformed-jid | |
| 482 end | |
| 483 end | |
| 484 end | |
| 485 --else -- possible rejoin | |
| 486 -- log("debug", "%s had connection replaced", current_nick); | |
| 487 -- self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}) | |
| 488 -- :tag('status'):text('Replaced by new connection'):up()); -- send unavailable | |
| 489 -- self:handle_to_occupant(origin, stanza); -- resend available | |
| 490 --end | |
| 491 else -- enter room | |
| 492 local new_nick = to; | |
| 493 local is_merge; | |
| 494 if self._occupants[to] then | |
| 495 if jid_bare(from) ~= jid_bare(self._occupants[to].jid) then | |
| 496 new_nick = nil; | |
| 497 end | |
| 498 is_merge = true; | |
| 499 end | |
| 500 local password = stanza:get_child("x", "http://jabber.org/protocol/muc"); | |
| 501 password = password and password:get_child("password", "http://jabber.org/protocol/muc"); | |
| 502 password = password and password[1] ~= "" and password[1]; | |
| 503 if self:get_password() and self:get_password() ~= password then | |
| 504 log("debug", "%s couldn't join due to invalid password: %s", from, to); | |
| 505 local reply = st.error_reply(stanza, "auth", "not-authorized"):up(); | |
| 506 reply.tags[1].attr.code = "401"; | |
| 507 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 508 elseif not new_nick then | |
| 509 log("debug", "%s couldn't join due to nick conflict: %s", from, to); | |
| 510 local reply = st.error_reply(stanza, "cancel", "conflict"):up(); | |
| 511 reply.tags[1].attr.code = "409"; | |
| 512 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 513 else | |
| 514 log("debug", "%s joining as %s", from, to); | |
| 515 if not next(self._affiliations) then -- new room, no owners | |
| 516 self._affiliations[jid_bare(from)] = "owner"; | |
| 517 if self.locked and not stanza:get_child("x", "http://jabber.org/protocol/muc") then | |
| 518 self.locked = nil; -- Older groupchat protocol doesn't lock | |
| 519 end | |
| 520 elseif self.locked then -- Deny entry | |
| 521 origin.send(st.error_reply(stanza, "cancel", "item-not-found")); | |
| 522 return; | |
| 523 end | |
| 524 local affiliation = self:get_affiliation(from); | |
| 525 local role = self:get_default_role(affiliation) | |
| 526 if role then -- new occupant | |
| 527 if not is_merge then | |
| 528 self._occupants[to] = {affiliation=affiliation, role=role, jid=from, sessions={[from]=get_filtered_presence(stanza)}}; | |
| 529 else | |
| 530 self._occupants[to].sessions[from] = get_filtered_presence(stanza); | |
| 531 end | |
| 532 self._jid_nick[from] = to; | |
| 533 self:send_occupant_list(from); | |
| 534 pr.attr.from = to; | |
| 535 pr:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | |
| 536 :tag("item", {affiliation=affiliation or "none", role=role or "none"}):up(); | |
| 537 if not is_merge then | |
| 538 self:broadcast_except_nick(pr, to); | |
| 539 end | |
| 540 pr:tag("status", {code='110'}):up(); | |
| 541 if self._data.whois == 'anyone' then | |
| 542 pr:tag("status", {code='100'}):up(); | |
| 543 end | |
| 544 if self.locked then | |
| 545 pr:tag("status", {code='201'}):up(); | |
| 546 end | |
| 547 pr.attr.to = from; | |
| 548 self:_route_stanza(pr); | |
| 549 self:send_history(from, stanza); | |
| 550 self:send_subject(from); | |
| 551 elseif not affiliation then -- registration required for entering members-only room | |
| 552 local reply = st.error_reply(stanza, "auth", "registration-required"):up(); | |
| 553 reply.tags[1].attr.code = "407"; | |
| 554 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 555 else -- banned | |
| 556 local reply = st.error_reply(stanza, "auth", "forbidden"):up(); | |
| 557 reply.tags[1].attr.code = "403"; | |
| 558 origin.send(reply:tag("x", {xmlns = "http://jabber.org/protocol/muc"})); | |
| 559 end | |
| 560 end | |
| 561 end | |
| 562 elseif type ~= 'result' then -- bad type | |
| 563 if type ~= 'visible' and type ~= 'invisible' then -- COMPAT ejabberd can broadcast or forward XEP-0018 presences | |
| 564 origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error? | |
| 565 end | |
| 566 end | |
| 567 elseif not current_nick then -- not in room | |
| 568 if (type == "error" or type == "result") and stanza.name == "iq" then | |
| 569 local id = stanza.attr.id; | |
| 570 stanza.attr.from, stanza.attr.to, stanza.attr.id = deconstruct_stanza_id(self, stanza); | |
| 571 if stanza.attr.id then | |
| 572 self:_route_stanza(stanza); | |
| 573 end | |
| 574 stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id; | |
| 575 elseif type ~= "error" then | |
| 576 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); | |
| 577 end | |
| 578 elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM | |
| 579 origin.send(st.error_reply(stanza, "modify", "bad-request")); | |
| 580 elseif current_nick and stanza.name == "message" and type == "error" and is_kickable_error(stanza) then | |
| 581 log("debug", "%s kicked from %s for sending an error message", current_nick, self.jid); | |
| 582 self:handle_to_occupant(origin, build_unavailable_presence_from_error(stanza)); -- send unavailable | |
| 583 else -- private stanza | |
| 584 local o_data = self._occupants[to]; | |
| 585 if o_data then | |
| 586 log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid); | |
| 587 if stanza.name == "iq" then | |
| 588 local id = stanza.attr.id; | |
| 589 if stanza.attr.type == "get" or stanza.attr.type == "set" then | |
| 590 stanza.attr.from, stanza.attr.to, stanza.attr.id = construct_stanza_id(self, stanza); | |
| 591 else | |
| 592 stanza.attr.from, stanza.attr.to, stanza.attr.id = deconstruct_stanza_id(self, stanza); | |
| 593 end | |
| 594 if type == 'get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then | |
| 595 stanza.attr.to = jid_bare(stanza.attr.to); | |
| 596 end | |
| 597 if stanza.attr.id then | |
| 598 self:_route_stanza(stanza); | |
| 599 end | |
| 600 stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id; | |
| 601 else -- message | |
| 602 stanza:tag("x", { xmlns = "http://jabber.org/protocol/muc#user" }):up(); | |
| 603 stanza.attr.from = current_nick; | |
| 604 for jid in pairs(o_data.sessions) do | |
| 605 stanza.attr.to = jid; | |
| 606 self:_route_stanza(stanza); | |
| 607 end | |
| 608 stanza.attr.from, stanza.attr.to = from, to; | |
| 609 end | |
| 610 elseif type ~= "error" and type ~= "result" then -- recipient not in room | |
| 611 origin.send(st.error_reply(stanza, "cancel", "item-not-found", "Recipient not in room")); | |
| 612 end | |
| 613 end | 696 end |
| 614 end | 697 end |
| 615 | 698 |
| 616 function room_mt:send_form(origin, stanza) | 699 function room_mt:send_form(origin, stanza) |
| 617 origin.send(st.reply(stanza):query("http://jabber.org/protocol/muc#owner") | 700 origin.send(st.reply(stanza):query("http://jabber.org/protocol/muc#owner") |
