Commit 1344ffb7 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Initial version.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9352 b35dd754-fafc-0310-a699-88a17e54d16e
parent fbaaea3f
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>SIP Plugin Changelog</title>
<style type="text/css">
BODY {
font-size : 100%;
}
BODY, TD, TH {
font-family : tahoma, verdana, arial, helvetica, sans-serif;
font-size : 0.8em;
}
H2 {
font-size : 10pt;
font-weight : bold;
padding-left : 1em;
}
A:hover {
text-decoration : none;
}
H1 {
font-family : tahoma, arial, helvetica, sans-serif;
font-size : 1.4em;
font-weight: bold;
border-bottom : 1px #ccc solid;
padding-bottom : 2px;
}
TT {
font-family : courier new;
font-weight : bold;
color : #060;
}
PRE {
font-family : courier new;
font-size : 100%;
}
</style>
</head>
<body>
<h1>
SIP Plugin Changelog
</h1>
<p><b>1.0.0</b> -- October 31, 2007</p>
<ul>
<li>Initial release.</li>
</ul>
</body>
</html>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<class>org.jivesoftware.openfire.sip.SipManager</class>
<name>SIP Phone Plugin</name>
<description>Provides support for SIP account management</description>
<author>Jive Software</author>
<version>1.0.0</version>
<date>10/31/2007</date>
<databaseKey>sip</databaseKey>
<databaseVersion>1</databaseVersion>
<minServerVersion>3.3.0</minServerVersion>
<adminconsole>
<tab id="tab-server">
<sidebar id="siderbar-sip" name="${admin.item.sipark}">
<item id="sipark-user-summary" name="${admin.item.sipark.user.name}" description="${admin.item.sipark.user.description}" url="sipark-user-summary.jsp"/>
<item id="sipark-settings" name="${admin.item.sipark.settings.name}" description="${admin.item.sipark.settings.description}" url="sipark-settings.jsp"/>
<item id="sipark-log-summary" name="${admin.item.sipark.calls.name}" description="${admin.item.sipark.calls.description}" url="sipark-log-summary.jsp"/>
</sidebar>
</tab>
</adminconsole>
</plugin>
INSERT INTO sipUser
(username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials)
SELECT username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials
FROM entSipUser;
INSERT INTO sipPhoneLog
(username, addressFrom, addressTo, datetime, duration, callType)
SELECT username, addressFrom, addressTo, datetime, duration, callType
FROM entPhoneLog;
\ No newline at end of file
INSERT INTO sipUser
(username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials)
SELECT username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials
FROM entSipUser;
INSERT INTO sipPhoneLog
(username, addressFrom, addressTo, datetime, duration, callType)
SELECT username, addressFrom, addressTo, datetime, duration, callType
FROM entPhoneLog;
\ No newline at end of file
INSERT INTO sipUser
(username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials)
SELECT username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials
FROM entSipUser;
INSERT INTO sipPhoneLog
(username, addressFrom, addressTo, datetime, duration, callType)
SELECT username, addressFrom, addressTo, datetime, duration, callType
FROM entPhoneLog;
\ No newline at end of file
INSERT INTO sipUser
(username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials)
SELECT username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials
FROM entSipUser;
INSERT INTO sipPhoneLog
(username, addressFrom, addressTo, datetime, duration, callType)
SELECT username, addressFrom, addressTo, datetime, duration, callType
FROM entPhoneLog;
\ No newline at end of file
INSERT INTO sipUser
(username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials)
SELECT username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials
FROM entSipUser;
INSERT INTO sipPhoneLog
(username, addressFrom, addressTo, datetime, duration, callType)
SELECT username, addressFrom, addressTo, datetime, duration, callType
FROM entPhoneLog;
\ No newline at end of file
INSERT INTO sipUser
(username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials)
SELECT username, sipUsername, sipAuthuser, sipDisplayName, sipPassword, sipServer, stunServer, stunPort, useStun, voicemail, enabled, status, outboundproxy, promptCredentials
FROM entSipUser;
INSERT INTO sipPhoneLog
(username, addressFrom, addressTo, datetime, duration, callType)
SELECT username, addressFrom, addressTo, datetime, duration, callType
FROM entPhoneLog;
\ No newline at end of file
-- $Revision$
-- $Date$
INSERT INTO jiveVersion (name, version) VALUES ('sip', 1);
create table sipUser (
username VARCHAR(255) NOT NULL,
sipUsername VARCHAR(255),
sipAuthuser VARCHAR(255),
sipDisplayName VARCHAR(255),
sipPassword VARCHAR(255),
sipServer VARCHAR(255),
stunServer VARCHAR(255),
stunPort VARCHAR(255),
useStun INTEGER,
voicemail VARCHAR(255),
enabled INTEGER,
status VARCHAR(255),
outboundproxy VARCHAR(255),
promptCredentials INTEGER,
CONSTRAINT sipUser_pk PRIMARY KEY(username)
);
create table sipPhoneLog (
username VARCHAR(255),
addressFrom VARCHAR(255),
addressTo VARCHAR(255),
datetime BIGINT,
duration INTEGER,
callType VARCHAR(20)
);
\ No newline at end of file
// $Revision$
// $Date$
INSERT INTO jiveVersion (name, version) VALUES ('sip', 1);
create table sipUser (
username varchar(255) not null,
sipUsername varchar(255),
sipAuthuser varchar(255),
sipDisplayName varchar(255),
sipPassword varchar(255),
sipServer varchar(255),
stunServer varchar(255),
stunPort varchar(255),
useStun integer,
voicemail varchar(255),
enabled integer,
status varchar(255),
outboundproxy VARCHAR(255) NULL,
promptCredentials INTEGER NULL,
PRIMARY KEY (username)
);
create table sipPhoneLog (
username varchar(255),
addressFrom varchar(255),
addressTo varchar(255),
datetime bigint,
duration integer,
callType varchar(20)
);
\ No newline at end of file
# $Revision$
# $Date$
INSERT INTO jiveVersion (name, version) VALUES ('sip', 1);
create table sipUser (
username varchar(255) not null unique,
sipUsername varchar(255),
sipAuthuser varchar(255),
sipDisplayName varchar(255),
sipPassword varchar(255),
sipServer varchar(255),
stunServer varchar(255),
stunPort varchar(255),
useStun int,
voicemail varchar(255),
enabled int,
status varchar(255),
outboundproxy VARCHAR(255) NULL,
promptCredentials INTEGER NULL,
PRIMARY KEY (username)
);
create table sipPhoneLog (
username varchar(255),
addressFrom varchar(255),
addressTo varchar(255),
datetime bigint,
duration int,
callType varchar(20)
);
\ No newline at end of file
-- $Revision$
-- $Date$
INSERT INTO jiveVersion (name, version) VALUES ('sip', 1);
create table sipUser (
username VARCHAR2(255) NOT NULL,
sipUsername VARCHAR2(255),
sipAuthuser VARCHAR2(255),
sipDisplayName VARCHAR2(255),
sipPassword VARCHAR2(255),
sipServer VARCHAR2(255),
stunServer VARCHAR2(255),
stunPort VARCHAR2(255),
useStun INTEGER,
voicemail VARCHAR2(255),
enabled INTEGER,
status VARCHAR2(255),
outboundproxy VARCHAR(255) NULL,
promptCredentials INT NULL,
CONSTRAINT sipUser_pk PRIMARY KEY (username)
);
create table sipPhoneLog (
username VARCHAR2(255),
addressFrom VARCHAR2(255),
addressTo VARCHAR2(255),
datetime LONG,
duration INTEGER,
callType VARCHAR2(20)
);
\ No newline at end of file
-- $Revision$
-- $Date$
INSERT INTO jiveVersion (name, version) VALUES ('sip', 1);
create table sipUser (
username varchar(255) not null,
sipUsername varchar(255),
sipAuthuser varchar(255),
sipDisplayName varchar(255),
sipPassword varchar(255),
sipServer varchar(255),
stunServer varchar(255),
stunPort varchar(255),
useStun INTEGER,
voicemail varchar(255),
enabled INTEGER,
status varchar(255),
outboundproxy VARCHAR(255) NULL,
promptCredentials INTEGER NULL,
PRIMARY KEY (username)
);
create table sipPhoneLog (
username varchar(255),
addressFrom varchar(255),
addressTo varchar(255),
datetime INTEGER,
duration INTEGER,
callType varchar(20)
);
\ No newline at end of file
/* $Revision$ */
/* $Date$ */
INSERT INTO jiveVersion (name, version) VALUES ('sip', 1);
create table sipUser (
username NVARCHAR(255) not null,
sipUsername NVARCHAR(255),
sipAuthuser NVARCHAR(255),
sipDisplayname NVARCHAR(255),
sipPassword NVARCHAR(255),
sipServer NVARCHAR(255),
stunServer NVARCHAR(255),
stunPort NVARCHAR(255),
useStun int,
voicemail NVARCHAR(255),
enabled int,
status NVARCHAR(255),
outboundproxy VARCHAR(255) NULL,
promptCredentials INT NULL,
CONSTRAINT sipUser_pk PRIMARY KEY (username)
);
create table sipPhoneLog (
username NVARCHAR(255),
addressFrom NVARCHAR(255),
addressTo NVARCHAR(255),
datetime bigint,
duration int,
callType NVARCHAR(20)
);
\ No newline at end of file
login.title = Admin Console
admin.item.sipark=Phone
admin.item.sipark.user.name=SIP Phone Mappings
admin.item.sipark.user.description=Click to view SIP phone mappings.
admin.item.sipark.settings.name=SIP Settings
admin.item.sipark.settings.description=Click to manage general SIP settings.
admin.item.sipark.calls.name=SIP Calls
admin.item.sipark.calls.description=Click to view history of SIP calls.
sipark.settings.title = SIP Settings
sipark.settings.description = Use the form below to manage the SIP settings. These settings will be used as default \
values of the phone mappings.
sipark.settings.success = Settings have been saved.
sipark.settings.valid.sipserver=Please specify the SIP server.
sipark.settings.valid.voiceMail=Please specify the voice mail number.
sipark.settings.valid.stunServer=Please specify the STUN server.
sipark.settings.valid.stunPort=Please specify the STUN server port.
sipark.settings.table.title = SIP and STUN server Settings
sipark.settings.sipServer = SIP server
sipark.settings.sipServer.description = Specify the hostname where the SIP server is running.
sipark.settings.voiceMail = Voice Mail Number
sipark.settings.voiceMail.description = Specify the number to dial to access the voice mail.
sipark.settings.enable.stun = STUN server enabled
sipark.settings.enable.stun.description = Enable this field when you are using a STUN server.
sipark.settings.stunServer = STUN server
sipark.settings.stunServer.description = Specify the hostname where the STUN server is running.
sipark.settings.stunServer.port = STUN port
sipark.settings.stunServer.port.description = Specify the port where the STUN server is listening.
sipark.settings.update.settings = Update Settings
sipark.settings.cancel = Cancel
sipark.user.title = SIP Phone Mappings
sipark.user.description = Create SIP phone mappings for users below. Mappings are configured from the server and \
distributed to Spark clients.
sipark.user.mapping.add = Add new Phone Mapping
sipark.user.create.title = Create SIP Phone Mapping
sipark.user.update.title = Update SIP Phone Mapping
sipark.user.create.description = Create or update a phone mapping using the form below.
sipark.user.create.save.changes = Save Changes
sipark.user.create.valid.xmpp-node=Please specify an XMPP username.
sipark.user.create.valid.sip-username=Please specify a SIP username.
sipark.user.create.valid.authusername=Please specify an authorization username.
sipark.user.create.valid.displayname=Please specify the phone number to display.
sipark.user.create.valid.password=Please specify a password.
sipark.user.create.valid.server=Please specify a SIP server.
sipark.user.create.valid.stunserver=Please specify a STUN server.
sipark.user.create.valid.stunport=Please specify the port where the STUN server is listening.
sipark.user.create.valid.voicemail=Please specify the number to dial to access the voice mail.
sipark.user.delete.title=Delete SIP Mapping?
sipark.user.delete.delete=Delete
sipark.user.delete.cancel=Cancel
sipark.user.delete.confirm=Are you sure you want to delete the mapping for {0} from the system?
test = Test
# SIP User Summary Page
user.create.username=Username
global.delete = Delete
user.summary.title = User Summary
user.summary.deleted = User deleted successfully.
user.summary.total_user = Total Users
user.summary.sorted = Sorted by Username
user.summary.users_per_page = Users per page
user.summary.created = Created
user.summary.last-logout = Last Logout
user.summary.edit = Edit
user.summary.not_user = No users in the system.
user.summary.enabled = Enabled
user.summary.status = Status
call.summary.title = SIP Calls Summary
call.summary.username=Username
call.summary.from = Caller
call.summary.destination = Receiver
call.summary.time = Time
call.summary.duration = Duration (secs)
call.summary.type = Type
call.summary.allfields = Matches All Fields
call.summary.filter = Search
call.summary.calls_per_page = Calls per page
call.summary.total_calls = Total Calls
call.type.all=All
call.type.dialed=Dialed
call.type.received=Received
call.type.missed=Missed
call.summary.no-entries=No log entries
user.create.server = Server
sip.create.label = Add SIP account to an user
sip.create.button = Add SIP Account
sip.account.xmpp.username = XMPP username
sip.account.sip.username = SIP username
sip.account.authusername = Authorization Username
sip.account.displayname = Display Phone Number
sip.account.password = Password
sip.account.server = Server
sip.account.outboundproxy = Outbound Proxy
sip.account.voicemail = Voice Mail Number
sip.account.enabled = Enabled
sip.account.promptCredentials = Prompt user for Credentials
#WrongUser, WrongPass, NetworkError, Timeout, Forbidden, WrongAuthUser
sip.test.error.wronguser= Check SIP username and try again.
sip.test.error.wronpass= Check the password and try again.
sip.test.error.networkerror= Check the Registrar Address, and if there is a firewall blocking OpenFire Server to reach SIP Registrar Address.
sip.test.error.timeout= Attempt timeout, please try again.
sip.test.error.forbidden= This user not allowed to register in the SIP Registrar Server. Check Authorization Username and password then try again.
sip.test.error.wrongauthuser= Check Authorization username and try again.
archive.search.daterange = Date Range:
archive.search.daterange.tooltip = Enter specific date ranges to search between. You can specify a \
start date and/or end date.
archive.search.daterange.start = Start:
archive.search.daterange.end = End:
archive.search.daterange.any = Any
archive.search.daterange.format = Use mm/dd/yy
archive.search.daterange.error = The end time must be after the start time.
archive.settings.any = Any
cancel = Cancel
create = Create
login.title = Administr\u00e1torsk\u00e1 konzole
admin.item.sipark=Telefon
admin.item.sipark.user.name=P\u0159i\u0159azen\u00ed SIP telefon\u016f
admin.item.sipark.user.description=Klikn\u011bte pro zobrazen\u00ed p\u0159i\u0159azen\u00ed SIP telefon\u016f.
admin.item.sipark.settings.name=Nastaven\u00ed SIP
admin.item.sipark.settings.description=Klikn\u011bte pro spr\u00e1vu nastaven\u00ed SIP.
admin.item.sipark.calls.name=SIP vol\u00e1n\u00ed
admin.item.sipark.calls.description=Klikn\u011bte pro zobrazen\u00ed historie SIP vol\u00e1n\u00ed.
# SIP User Summary Page
user.create.username=U\u017eivatelsk\u00e9 jm\u00e9no
global.delete = Smazat
user.summary.title = P\u0159ehled u\u017eivatele
user.summary.deleted = U\u017eivatel \u00fasp\u011b\u0161n\u011b vymaz\u00e1n.
user.summary.total_user = Celkem u\u017eivatel\u016f
user.summary.sorted = Set\u0159\u00edd\u011bno podle u\u017eivatelsk\u00e9ho jm\u00e9na
user.summary.users_per_page = U\u017eivatel\u016f na str\u00e1nku
user.summary.created = Vytvo\u0159eno
user.summary.last-logout = Posledn\u00ed odhl\u00e1\u0161en\u00ed
user.summary.edit = \u00daprava
user.summary.not_user = \u017d\u00e1dn\u00ed u\u017eivatel\u00e9 v syst\u00e9mu.
user.summary.enabled = Povoleno
user.summary.status = Stav
call.summary.from = Od
call.summary.destination = C\u00edl
call.summary.time = \u010cas
call.summary.duration = Trv\u00e1n\u00ed (sekund)
call.summary.type = Typ
call.summary.allfields = Odpov\u00edd\u00e1 v\u0161em pol\u00edm
call.summary.filter = Filtr
call.summary.calls_per_page = Hovor\u016f na str\u00e1nku
user.create.server = Server
sip.create.label = P\u0159idat u\u017eivateli SIP \u00fa\u010det
sip.create.button = P\u0159idat SIP \u00fa\u010det
sip.account.xmpp.username = XMPP u\u017eivatelsk\u00e9 jm\u00e9no
sip.account.sip.username = U\u017eivatelsk\u00e9 jm\u00e9no
sip.account.authusername = Autoriza\u010dn\u00ed u\u017eivatelsk\u00e9 jm\u00e9no
sip.account.displayname = Zobrazovat telefonn\u00ed \u010d\u00edslo
sip.account.password = Heslo
sip.account.server = Server
sip.account.outboundproxy = Outbound Proxy
sip.account.voicemail = \u010c\u00edslo hlasov\u00e9 schr\u00e1nky
sip.account.enabled = Povoleno
sip.account.promptCredentials = Prompt user for Credentials
#WrongUser, WrongPass, NetworkError, Timeout, Forbidden, WrongAuthUser
sip.test.error.wronguser= Zkontrolujte u\u017eivatelsk\u00e9 jm\u00e9no SIP a zkuste to znovu.
sip.test.error.wronpass= Zkontrolujte heslo a zkuste to znovu.
sip.test.error.networkerror= Zkontrolujte adresu registr\u00e1tora, a zda firewall nebr\u00e1n\u00ed OpenFire Serveru p\u0159ipojit se na adresu SIP registr\u00e1tora.
sip.test.error.timeout= Vypr\u0161el \u010das, pros\u00edm zkuste to znovu.
sip.test.error.forbidden= Tento u\u017eivatel nem\u00e1 povoleno registrovat se do registra\u010dn\u00edho serveru SIP. Zkontrolujte autoriza\u010dn\u00ed u\u017eivatelsk\u00e9 jm\u00e9no a heslo, potom to zkuste znovu.
sip.test.error.wrongauthuser= Zkontrolujte autoriza\u010dn\u00ed u\u017eivatelsk\u00e9 jm\u00e9no a zkuste to znovu.
sipark.settings.title = Nastaven\u00ed SIP
sipark.settings.description = Pou\u017eijte spodn\u00ed formul\u00e1\u0159 pro spr\u00e1vu SIP nastaven\u00ed. Tato nastaven\u00ed budou pou\u017eita jako v\u00fdchoz\u00ed \
hodnoty pro p\u0159i\u0159azen\u00ed telefon\u016f.
sipark.settings.success = Nastaven\u00ed byla ulo\u017eena.
sipark.settings.valid.sipserver=Pros\u00edm zadejte SIP server.
sipark.settings.valid.voiceMail=Pros\u00edm zadejte \u010d\u00edslo hlasov\u00e9 schr\u00e1nky.
sipark.settings.valid.stunServer=Pros\u00edm zadejte STUN server.
sipark.settings.valid.stunPort=Pros\u00edm zadejte port STUN serveru.
sipark.settings.table.title = Nastaven\u00ed SIP a STUN serveru
sipark.settings.sipServer = SIP server
sipark.settings.sipServer.description = Zadejte jm\u00e9no po\u010d\u00edta\u010de, na kter\u00e9m b\u011b\u017e\u00ed SIP server.
sipark.settings.voiceMail = \u010c\u00edslo hlasov\u00e9 schr\u00e1nky
sipark.settings.voiceMail.description = Zadejte \u010d\u00edslo pro p\u0159\u00edstup k hlasov\u00e9 schr\u00e1nce.
sipark.settings.enable.stun = STUN server povolen
sipark.settings.enable.stun.description = Povolte toto pol\u00ed\u010dko, pokud pou\u017e\u00edv\u00e1te STUN server.
sipark.settings.stunServer = STUN server
sipark.settings.stunServer.description = Zadejte jm\u00e9no po\u010d\u00edta\u010de, na kter\u00e9m b\u011b\u017e\u00ed STUN server.
sipark.settings.stunServer.port = STUN port
sipark.settings.stunServer.port.description = Zadejte port, na kter\u00e9m naslouch\u00e1 STUN server.
sipark.settings.update.settings = Aktualizovat nastaven\u00ed
sipark.settings.cancel = Zru\u0161it
sipark.user.title = P\u0159i\u0159azen\u00ed SIP telefon\u016f
sipark.user.description = Vytvo\u0159te p\u0159i\u0159azen\u00ed SIP telefon\u016f pro n\u00ed\u017ee uveden\u00e9 u\u017eivatele. P\u0159i\u0159azen\u00ed jsou konfigurov\u00e1na ze serveru a \
distribuov\u00e1na Spark klient\u016fm.
sipark.user.mapping.add = P\u0159idat nov\u00e9 p\u0159i\u0159azen\u00ed telefonu
sipark.user.create.title = Vytvo\u0159it p\u0159i\u0159azen\u00ed SIP telefonu
sipark.user.update.title = Upravit p\u0159i\u0159azen\u00ed SIP telefonu
sipark.user.create.description = Vytvo\u0159te nov\u00e9 p\u0159i\u0159azen\u00ed telefonu za pou\u017eit\u00ed doln\u00edho formul\u00e1\u0159e.
sipark.user.create.save.changes = Ulo\u017eit zm\u011bny
sipark.user.create.valid.xmpp-node=Pros\u00edm zadejte XMPP u\u017eivatelsk\u00e9 jm\u00e9no.
sipark.user.create.valid.sip-username=Pros\u00edm zadejte SIP u\u017eivatelsk\u00e9 jm\u00e9no.
sipark.user.create.valid.authusername=Pros\u00edm zadejte autoriza\u010dn\u00ed u\u017eivatelsk\u00e9 jm\u00e9no.
sipark.user.create.valid.displayname=Pros\u00edm zadejte telefonn\u00ed \u010d\u00edslo, kter\u00e9 se m\u00e1 zobrazit.
sipark.user.create.valid.password=Pros\u00edm zadejte heslo.
sipark.user.create.valid.server=Pros\u00edm zadejte SIP server.
sipark.user.create.valid.stunserver=Pros\u00edm zadejte STUN server.
sipark.user.create.valid.stunport=Pros\u00edm zadejte port, na kter\u00e9m naslouch\u00e1 STUN server.
sipark.user.create.valid.voicemail=Pros\u00edm zadejte \u010d\u00edslo, kter\u00e9 se m\u00e1 vyto\u010dit pro p\u0159\u00edstup k hlasov\u00e9 schr\u00e1nce.
sipark.user.delete.title=Smazat p\u0159i\u0159azen\u00ed SIP?
sipark.user.delete.delete=Smazat
sipark.user.delete.cancel=Storno
sipark.user.delete.confirm=Jste si jist\u00fd(-\u00e1), \u017ee chcete smazat p\u0159i\u0159azen\u00ed pro {0} ze syst\u00e9mu?
call.summary.no-entries=\u017d\u00e1dn\u00e9 z\u00e1znamy protokolu
call.summary.title=P\u0159ehled vol\u00e1n\u00ed SIP
call.summary.total_calls=Celkem hovor\u016f
call.summary.username=U\u017eivatel
call.type.all=V\u0161echny
call.type.dialed=Vyto\u010den\u00e9
call.type.missed=Zme\u0161kan\u00e9
call.type.received=P\u0159ijat\u00e9
global.pages=Stran
global.showing=Zobrazuji
test = Test
archive.search.daterange = Rozsah datum\u016f:
archive.search.daterange.tooltip = Zadejte specifick\u00fd rozsah datum\u016f, mezi kter\u00fdmi hledat. M\u016f\u017eete zadat \
po\u010d\u00e1te\u010dn\u00ed a/nebo koncov\u00e9 datum.
archive.search.daterange.start = Za\u010d\u00e1tek:
archive.search.daterange.end = Konec:
archive.search.daterange.any = Kdykoli
archive.search.daterange.format = Pou\u017eijte mm/dd/yy
archive.search.daterange.error = Koncov\u00e9 datum mus\u00ed b\u00fdt po po\u010d\u00e1te\u010dn\u00edm \u010dase.
archive.settings.any = Jak\u00fdkoli
cancel = Zru\u0161it
create = Vytvo\u0159it
login.title = Consola de Administraci\u00f3n
admin.item.sipark=Telefon\u00eda
admin.item.sipark.user.name=Mapeos de cuentas SIP
admin.item.sipark.user.description=Haga clic para visualizar mapeos de cuentas SIP.
admin.item.sipark.settings.name=Seteos generales de SIP
admin.item.sipark.settings.description=Haga clic para configurar seteos generales de SIP.
admin.item.sipark.calls.name=Llamadas SIP
admin.item.sipark.calls.description=Haga clic para visualizar historial de llamadas SIP.
# SIP User Summary Page
user.create.username=Nombre de usuario
global.delete = Borrar
user.summary.title = Lista de Usuarios
user.summary.deleted = Usuario borrado exitosamente.
user.summary.total_user = Total de Usuarios
user.summary.sorted = Ordernar por nombre de usuario
user.summary.users_per_page = Usuarios por p\u00e1gina
user.summary.created = Creado
user.summary.last-logout = \u00daltima Salida
user.summary.edit = Editar
user.summary.not_user = No hay usuarios en el sistema.
user.summary.enabled = Habilitado
user.summary.status = Estatus
call.summary.title = Listado de Llamadas SIP
call.summary.username=Nombre de Usuario
call.summary.from = Desde
call.summary.destination = Hacia
call.summary.time = Tiempo
call.summary.duration = Duraci\u00f3n (segs)
call.summary.type = Tipo
call.summary.allfields = Matchea Todos los Campos
call.summary.filter = Filtrar
call.summary.calls_per_page = Llamadas por p\u00e1gina
call.summary.total_calls = Total de Llamadas
call.type.all=Todas
call.type.dialed=Discadas
call.type.received=Recibidas
call.type.missed=Perdidas
global.showing=Viendo
global.pages=P\u00e1ginas
call.summary.no-entries=No se han encontrado registro de llamadas
user.create.server = Servidor
sip.create.label = Agregar cuenta SIP para Usuario
sip.create.button = Agregar Cuenta SIP
sip.account.xmpp.username = Nombre de Usuario XMPP
sip.account.sip.username = Nombre de Usuario
sip.account.authusername = Usuario de Authorizaci\u00f3n
sip.account.displayname = N\u00famero de Tel\u00e9fono a mostrar
sip.account.password = Clave
sip.account.server = Servidor
sip.account.outboundproxy = Outbound Proxy
sip.account.voicemail = N\u00famero Correo de Voz
sip.account.enabled = Habilitado
sip.account.promptCredentials = Prompt user for Credentials
#WrongUser, WrongPass, NetworkError, Timeout, Forbidden, WrongAuthUser
sip.test.error.wronguser= Check SIP username and try again.
sip.test.error.wronpass= Check the password and try again.
sip.test.error.networkerror= Check the Registrar Address, and if there is a firewall blocking OpenFire Server to reach SIP Registrar Address.
sip.test.error.timeout= Attempt timeout, please try again.
sip.test.error.forbidden= This user not allowed to register in the SIP Registrar Server. Check Authorization Username and password then try again.
sip.test.error.wrongauthuser= Check Authorization username and try again.
sipark.settings.title = Seteos Generales de SIP
sipark.settings.description = Utilice el siguiente formulario para administrar los seteos del servidor SIP. Lo seteos \
ser\u00e1n utilizados como valores por defecto para los mapeos de cuentas SIP.
sipark.settings.success = Seteos han sido guardados.
sipark.settings.valid.sipserver=Especifique el servidor SIP.
sipark.settings.valid.voiceMail=Especifique el n\u00famero de correo de voz.
sipark.settings.valid.stunServer=Especifique el servidor STUN.
sipark.settings.valid.stunPort=Especifique el puerto del servidor STUN.
sipark.settings.table.title = Seteos de servidores SIP y STUN
sipark.settings.sipServer = Servidor SIP
sipark.settings.sipServer.description = Especifique el servidor donde el servidor SIP esta corriendo.
sipark.settings.voiceMail = N\u00famero Correo de Voz
sipark.settings.voiceMail.description = Especifique n\u00famero a discar para acceder al correo de voz.
sipark.settings.enable.stun = Servidor STUN habilitado
sipark.settings.enable.stun.description = Habilite este campo cuando utilice un servidor STUN.
sipark.settings.stunServer = Servidor STUN
sipark.settings.stunServer.description = Especifique el servidor donde el servidor STUN esta corriendo.
sipark.settings.stunServer.port = Puerto de STUN
sipark.settings.stunServer.port.description = Especifique el puerto donde el servidor STUN esta escuchando.
sipark.settings.update.settings = Actualizar Seteos
sipark.settings.cancel = Cancelar
sipark.user.title = Mapeos de cuentas SIP
sipark.user.description = Puede crear o actualizar mapeos de cuentas SIP para los siguientes usuarios. Los mapeos son \
configurados desde el servidor para ser luego distribuidos a los clientes Spark.
sipark.user.mapping.add = Agregar nuevo mapeo
sipark.user.create.title = Crear mapeo a cuenta SIP
sipark.user.update.title = Actualizar mapeo a cuenta SIP
sipark.user.create.description = Puede crear o actualizar el mapeo utilizando el siguiente formulario.
sipark.user.create.save.changes = Guardar Cambios
sipark.user.create.valid.xmpp-node=Especifique el nombre del usuario XMPP.
sipark.user.create.valid.sip-username=Especifique el nombre de usuario SIP.
sipark.user.create.valid.authusername=Especifique el nombre de usuario de autorizaci\u00f3n.
sipark.user.create.valid.displayname=Especifique el n\u00famero de telefono a mostrar.
sipark.user.create.valid.password=Especifique la clave.
sipark.user.create.valid.server=Especifique el servidor SIP.
sipark.user.create.valid.stunserver=Especifique el servidor STUN.
sipark.user.create.valid.stunport=Especifique el puerto donde el servidor STUN esta escuchando.
sipark.user.create.valid.voicemail=Especifique n\u00famero a discar para acceder al correo de voz.
sipark.user.delete.title=\u00bfEliminar mapeo de la cuenta SIP?
sipark.user.delete.delete=Borrar
sipark.user.delete.cancel=Cancelar
sipark.user.delete.confirm=\u00bfDesea elimiar el mapeo de la cuenta SIP {0} del sistema?
test = Test
archive.search.daterange = Rango de Fechas:
archive.search.daterange.tooltip = Ingrese un rango de fechas espec\u00edfico para buscar. Puede \
especificar una fecha de inicio y/o fecha de fin.
archive.search.daterange.start = Inicio:
archive.search.daterange.end = Fin:
archive.search.daterange.any = Cualquiera
archive.search.daterange.format = Formato mm/dd/yy
archive.search.daterange.error = La fecha de fin debe ser posterior a la de inicio.
archive.settings.any = Cualquiera
cancel = Cancelar
create = Crear
login.title=Console d'Administration
admin.item.sipark=Phone
admin.item.sipark.user.name=SIP Phone Mappings
admin.item.sipark.user.description=Click to view SIP phone mappings.
admin.item.sipark.settings.name=SIP Settings
admin.item.sipark.settings.description=Click to manage general SIP settings.
admin.item.sipark.calls.name=SIP Calls
admin.item.sipark.calls.description=Click to view history of SIP calls.
# SIP User Summary Page
user.create.username=Username
global.delete = Delete
user.summary.title = User Summary
user.summary.deleted = User deleted successfully.
user.summary.total_user = Total Users
user.summary.sorted = Sorted by Username
user.summary.users_per_page = Users per page
user.summary.created = Created
user.summary.last-logout = Last Logout
user.summary.edit = Edit
user.summary.not_user = No users in the system.
user.summary.enabled = Enabled
user.summary.status = Status
call.summary.from = From
call.summary.destination = Destination
call.summary.time = Time
call.summary.duration = Duration (secs)
call.summary.type = Type
call.summary.allfields = Matches All Fields
call.summary.filter = Filter
call.summary.calls_per_page = Calls per page
user.create.server = Server
sip.create.label = Add SIP account to an user
sip.create.button = Add SIP Account
sip.account.xmpp.username = XMPP username
sip.account.sip.username = Username
sip.account.authusername = Authorization Username
sip.account.displayname = Display Phone Number
sip.account.password = Password
sip.account.server = Server
sip.account.outboundproxy = Outbound Proxy
sip.account.voicemail = Voice Mail Number
sip.account.enabled = Enabled
sip.account.promptCredentials = Prompt user for Credentials
#WrongUser, WrongPass, NetworkError, Timeout, Forbidden, WrongAuthUser
sip.test.error.wronguser= Check SIP username and try again.
sip.test.error.wronpass= Check the password and try again.
sip.test.error.networkerror= Check the Registrar Address, and if there is a firewall blocking OpenFire Server to reach SIP Registrar Address.
sip.test.error.timeout= Attempt timeout, please try again.
sip.test.error.forbidden= This user not allowed to register in the SIP Registrar Server. Check Authorization Username and password then try again.
sip.test.error.wrongauthuser= Check Authorization username and try again.
sipark.settings.title = SIP Settings
sipark.settings.description = Use the form below to manage the SIP settings. These settings will be used as default \
values of the phone mappings.
sipark.settings.success = Settings have been saved.
sipark.settings.valid.sipserver=Please specify the SIP server.
sipark.settings.valid.voiceMail=Please specify the voice mail number.
sipark.settings.valid.stunServer=Please specify the STUN server.
sipark.settings.valid.stunPort=Please specify the STUN server port.
sipark.settings.table.title = SIP and STUN server Settings
sipark.settings.sipServer = SIP server
sipark.settings.sipServer.description = Specify the hostname where the SIP server is running.
sipark.settings.voiceMail = Voice Mail Number
sipark.settings.voiceMail.description = Specify the number to dial to access the voice mail.
sipark.settings.enable.stun = STUN server enabled
sipark.settings.enable.stun.description = Enable this field when you are using a STUN server.
sipark.settings.stunServer = STUN server
sipark.settings.stunServer.description = Specify the hostname where the STUN server is running.
sipark.settings.stunServer.port = STUN port
sipark.settings.stunServer.port.description = Specify the port where the STUN server is listening.
sipark.settings.update.settings = Update Settings
sipark.settings.cancel = Cancel
sipark.user.title = SIP Phone Mappings
sipark.user.description = Create SIP phone mappings for users below. Mappings are configured from the server and \
distributed to Spark clients.
sipark.user.mapping.add = Add new Phone Mapping
sipark.user.create.title = Create SIP Phone Mapping
sipark.user.update.title = Update SIP Phone Mapping
sipark.user.create.description = Create a new pone mapping using the form below.
sipark.user.create.save.changes = Save Changes
sipark.user.create.valid.xmpp-node=Please specify an XMPP username.
sipark.user.create.valid.sip-username=Please specify a SIP username.
sipark.user.create.valid.authusername=Please specify an authorization username.
sipark.user.create.valid.displayname=Please specify the phone number to display.
sipark.user.create.valid.password=Please specify a password.
sipark.user.create.valid.server=Please specify a SIP server.
sipark.user.create.valid.stunserver=Please specify a STUN server.
sipark.user.create.valid.stunport=Please specify the port where the STUN server is listening.
sipark.user.create.valid.voicemail=Please specify the number to dial to access the voice mail.
sipark.user.delete.title=Delete SIP Mapping?
sipark.user.delete.delete=Delete
sipark.user.delete.cancel=Cancel
sipark.user.delete.confirm=Are you sure you want to delete the mapping for {0} from the system?
call.summary.title=
call.summary.no-entries=
call.type.dialed=
test = Test
call.summary.total_calls=Total Calls
call.summary.username=Username
call.type.all=All
call.type.missed=Missed
call.type.received=Received
archive.search.daterange=Dates:
archive.search.daterange.any=N'importe
archive.search.daterange.end=Fin:
archive.search.daterange.error=L'heure de fin doit etre apr\u00e8s l'heure de d\u00e9part.
archive.search.daterange.format=Utilisez mm/jj/aa
archive.search.daterange.start=D\u00e9part:
archive.search.daterange.tooltip=Veuillez entrer les dates ente lequelles vous souhaitez rechercher. Vous pouvez choisir une date de d\u00e9part et/ou une date de fin.
archive.settings.any=N'importe
cancel=Annuler
create=Cr\u00e9er
login.title = Console Administrativo
sip.create.form-description = Utilize o formul\u00e1rio abaixo para adicionar Ajustes SIP para Usu\u00e1rio.
admin.item.sipark=Telefone
admin.item.sipark.user.name=Mapeamento dos Telefones SIP
admin.item.sipark.user.description=Clique para exibir mapeamento dos telefones SIP.
admin.item.sipark.settings.name=Ajustes SIP
admin.item.sipark.settings.description=Clique para gerenciar ajustes gerais de SIP
admin.item.sipark.calls.name=Chamadas SIP
admin.item.sipark.calls.description=Clique para exibir hist\u00f3rico de chamadas SIP.
sip.create.label = Adicionar conta SIP para um usu\u00e1rio.
sip.create.help = Voc\u00ea deve associar a conta SIP para um JID existente.
sip.create.button = Adicionar conta SIP
sip.account.username = Nome de Usu\u00e1rio
sip.account.authusername = Nome de Usu\u00e1rio de Autoriza\u00e7\u00e3o
sip.account.displayname = Mostrar Nome
sip.account.password = Senha
sip.account.server = Servidor
sip.account.outboundproxy = Outbound Proxy
sip.account.voicemail = N\u00famero de Correio de Voz
sip.account.enabled = Habilitado
sip.account.stun.label = Ajustes STUN de Usu\u00e1rio
sip.account.stun.server = Servidor STUN
sip.account.stun.port = Porta STUN
sip.account.stun.enabled = Habilitado
sip.account.promptCredentials = Prompt user for Credentials
sip.account.save = Salvar Ajustes
#WrongUser, WrongPass, NetworkError, Timeout, Forbidden, WrongAuthUser
sip.test.error.wronguser= Check SIP username and try again.
sip.test.error.wronpass= Check the password and try again.
sip.test.error.networkerror= Check the Registrar Address, and if there is a firewall blocking OpenFire Server to reach SIP Registrar Address.
sip.test.error.timeout= Attempt timeout, please try again.
sip.test.error.forbidden= This user not allowed to register in the SIP Registrar Server. Check Authorization Username and password then try again.
sip.test.error.wrongauthuser= Check Authorization username and try again.
sipark.settings.title = Configura\u00e7\u00f5es SIP
sipark.settings.description = Utilize o formul\u00e1rio abaixo para gerenciar as configura\u00e7\u00f5es SIP. Estas configura\u00e7\u00f5es \
ser\u00e3o utilizadas como padr\u00e3o para o mapeamento de telefone.
sipark.settings.success = Configura\u00e7\u00f5es foram salvas com sucesso.
sipark.settings.valid.sipserver=Por favor, especifique o servidor SIP.
sipark.settings.valid.voiceMail=Por favor, especifique o n\u00famero do corrreio de voz.
sipark.settings.valid.stunServer=Por favor, especifique o servidor STUN.
sipark.settings.valid.stunPort=Por favor, especifique a porta do servidor STUN.
sipark.settings.table.title = Configura\u00e7\u00f5es dos Servidores SIP e STUN.
sipark.settings.sipServer = Servidor SIP
sipark.settings.sipServer.description = Especifique o hostname do servidor SIP.
sipark.settings.voiceMail = N\u00famero de Correio de Voz
sipark.settings.voiceMail.description = Especifique o n\u00famero a ser discado para acessar o correio de voz.
sipark.settings.enable.stun = Servidor STUN habilitado
sipark.settings.enable.stun.description = Habilite este campo quando estiver usando um servidor STUN
sipark.settings.stunServer = Servidor STUN
sipark.settings.stunServer.description = Especifique o hostname do servidor STUN.
sipark.settings.stunServer.port = Porta do STUN
sipark.settings.stunServer.port.description = Especifique a porta do servidor STUN.
sipark.settings.update.settings = Atualizar Configura\u00e7\u00f5es
sipark.settings.cancel = Cancelar
user.create.server = Servidor
# SIP User Summary Page
user.create.username=Nome de usu\u00e1rio
global.delete = Apagar
user.summary.title = Resumo do Usu\u00e1rio
user.summary.deleted = Usu\u00e1rio exclu\u00eddo com sucesso.
user.summary.total_user = Total de Usu\u00e1rios
user.summary.sorted = Classificado por Nome de Usu\u00e1rio
user.summary.users_per_page = Usu\u00e1rios por p\u00e1gina
user.summary.created = Criado
user.summary.last-logout = \u00daltima Desconex\u00e3o
user.summary.edit = Editar
user.summary.not_user = Nenhum usu\u00e1rio no sistema.
user.summary.enabled = Habilitado
user.summary.status = Status
call.summary.from = De
call.summary.destination = Destinat\u00e1rio
call.summary.time = Hora
call.summary.duration = Dura\u00e7\u00e3o (seg)
call.summary.type = Tipo
call.summary.allfields = Coincide com Todos os Campos
call.summary.filter = Filtro
call.summary.calls_per_page = Chamadas por p\u00e1gina
call.summary.no-entries=Nenhuma chamada
call.summary.title=Lista de Chamadas SIP
call.summary.total_calls=Total do Chamadas
call.summary.username=Usu\u00e1rio
call.type.all=Todos
call.type.dialed=Discado
call.type.missed=Perdida
call.type.received=Recebida
global.pages=P\u00e1ginas
global.showing=Mostrando
archive.search.daterange = Intervalo de Datas:
archive.search.daterange.tooltip = Insira intervalo de datas espec\u00edfico para pesquisa. Voc\u00ea pode especificar uma data \
de in\u00edcio e/ou uma data de fim
archive.search.daterange.start = In\u00edcio:
archive.search.daterange.end = Final:
archive.search.daterange.any = Qualquer
archive.search.daterange.format = Utilize mm/dd/aa
archive.search.daterange.error = A hora final deve ser ap\u00f3s a hora inicial
archive.settings.any = Qualquer
cancel = Cancelar
create = Criar
login.title = \u7ba1\u7406\u63a7\u5236\u53f0
admin.item.sipark=Phone
admin.item.sipark.user.name=SIP Phone Mappings
admin.item.sipark.user.description=Click to view SIP phone mappings.
admin.item.sipark.settings.name=SIP Settings
admin.item.sipark.settings.description=Click to manage general SIP settings.
admin.item.sipark.calls.name=SIP Calls
admin.item.sipark.calls.description=Click to view history of SIP calls.
# SIP User Summary Page
user.create.username=Username
global.delete = Delete
user.summary.title = User Summary
user.summary.deleted = User deleted successfully.
user.summary.total_user = Total Users
user.summary.sorted = Sorted by Username
user.summary.users_per_page = Users per page
user.summary.created = Created
user.summary.last-logout = Last Logout
user.summary.edit = Edit
user.summary.not_user = No users in the system.
user.summary.enabled = Enabled
user.summary.status = Status
call.summary.from = From
call.summary.destination = Destination
call.summary.time = Time
call.summary.duration = Duration (secs)
call.summary.type = Type
call.summary.allfields = Matches All Fields
call.summary.filter = Filter
call.summary.calls_per_page = Calls per page
user.create.server = Server
sip.create.label = Add SIP account to an user
sip.create.button = Add SIP Account
sip.account.xmpp.username = XMPP username
sip.account.sip.username = Username
sip.account.authusername = Authorization Username
sip.account.displayname = Display Phone Number
sip.account.password = Password
sip.account.server = Server
sip.account.outboundproxy = Outbound Proxy
sip.account.voicemail = Voice Mail Number
sip.account.promptCredentials = Prompt user for Credentials
sip.account.enabled = Enabled
#WrongUser, WrongPass, NetworkError, Timeout, Forbidden, WrongAuthUser
sip.test.error.wronguser= Check SIP username and try again.
sip.test.error.wronpass= Check the password and try again.
sip.test.error.networkerror= Check the Registrar Address, and if there is a firewall blocking OpenFire Server to reach SIP Registrar Address.
sip.test.error.timeout= Attempt timeout, please try again.
sip.test.error.forbidden= This user not allowed to register in the SIP Registrar Server. Check Authorization Username and password then try again.
sip.test.error.wrongauthuser= Check Authorization username and try again.
call.summary.no-entries=No log entries
call.summary.title=SIP Calls Summary
call.summary.total_calls=Total Calls
call.summary.username=Username
call.type.all=All
call.type.dialed=Dialed
call.type.missed=Missed
call.type.received=Received
sipark.settings.title = SIP Settings
sipark.settings.description = Use the form below to manage the SIP settings. These settings will be used as default \
values of the phone mappings.
sipark.settings.success = Settings have been saved.
sipark.settings.valid.sipserver=Please specify the SIP server.
sipark.settings.valid.voiceMail=Please specify the voice mail number.
sipark.settings.valid.stunServer=Please specify the STUN server.
sipark.settings.valid.stunPort=Please specify the STUN server port.
sipark.settings.table.title = SIP and STUN server Settings
sipark.settings.sipServer = SIP server
sipark.settings.sipServer.description = Specify the hostname where the SIP server is running.
sipark.settings.voiceMail = Voice Mail Number
sipark.settings.voiceMail.description = Specify the number to dial to access the voice mail.
sipark.settings.enable.stun = STUN server enabled
sipark.settings.enable.stun.description = Enable this field when you are using a STUN server.
sipark.settings.stunServer = STUN server
sipark.settings.stunServer.description = Specify the hostname where the STUN server is running.
sipark.settings.stunServer.port = STUN port
sipark.settings.stunServer.port.description = Specify the port where the STUN server is listening.
sipark.settings.update.settings = Update Settings
sipark.settings.cancel = Cancel
sipark.user.title = SIP Phone Mappings
sipark.user.description = Create SIP phone mappings for users below. Mappings are configured from the server and \
distributed to Spark clients.
sipark.user.mapping.add = Add new Phone Mapping
sipark.user.create.title = Create SIP Phone Mapping
sipark.user.update.title = Update SIP Phone Mapping
sipark.user.create.description = Create a new pone mapping using the form below.
sipark.user.create.save.changes = Save Changes
sipark.user.create.valid.xmpp-node=Please specify an XMPP username.
sipark.user.create.valid.sip-username=Please specify a SIP username.
sipark.user.create.valid.authusername=Please specify an authorization username.
sipark.user.create.valid.displayname=Please specify the phone number to display.
sipark.user.create.valid.password=Please specify a password.
sipark.user.create.valid.server=Please specify a SIP server.
sipark.user.create.valid.stunserver=Please specify a STUN server.
sipark.user.create.valid.stunport=Please specify the port where the STUN server is listening.
sipark.user.create.valid.voicemail=Please specify the number to dial to access the voice mail.
sipark.user.delete.title=Delete SIP Mapping?
sipark.user.delete.delete=Delete
sipark.user.delete.cancel=Cancel
sipark.user.delete.confirm=Are you sure you want to delete the mapping for {0} from the system?
global.pages=Pages
global.showing=Showing
test = Test
archive.search.daterange = \u65f6\u95f4\u8303\u56f4:
archive.search.daterange.tooltip = \u8f93\u5165\u4e00\u4e2a\u6307\u5b9a\u7684\u65e5\u671f\u7528\u4e8e\u641c\u7d22\u3002\u60a8\u53ef\u4ee5\u6307\u5b9a\u4e00\u4e2a\u5f00\u59cb\u65f6\u95f4\u6216\u7ed3\u675f\u65f6\u95f4\u3002
archive.search.daterange.start = \u5f00\u59cb:
archive.search.daterange.end = \u7ed3\u675f:
archive.search.daterange.any = \u4efb\u4f55\u4e00\u9879
archive.search.daterange.format = \u4f7f\u7528 mm/dd/yy
archive.search.daterange.error = \u7ed3\u675f\u65f6\u95f4\u5fc5\u987b\u5728\u5f00\u59cb\u65f6\u95f4\u4e4b\u540e\u3002
archive.settings.any = \u4efb\u4f55\u4e00\u9879
cancel = \u53d6\u6d88
create = \u5efa\u7acb
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.sip.log.LogComponent;
import org.jivesoftware.openfire.sip.log.LogListenerImpl;
import org.jivesoftware.openfire.sip.sipaccount.SipComponent;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import java.util.Map;
import java.io.File;
/**
* Remote management for users SIP account for Spark SIP Plugin
*
* @author Thiago Rocha Camargo
*/
public class SipManager implements Plugin, PropertyEventListener {
private String serviceName;
private ComponentManager componentManager;
private SipComponent sipComponent;
private LogComponent logComponent;
/**
* Constructs a new SIP Controller plugin.
*/
public SipManager() {
serviceName = JiveGlobals.getProperty(SipComponent.PROPNAME,
SipComponent.NAME);
}
public void initializePlugin(PluginManager manager, File pluginDirectory) {
// Register as a component.
componentManager = ComponentManagerFactory.getComponentManager();
sipComponent = new SipComponent();
LogListenerImpl logListener = new LogListenerImpl(componentManager);
logComponent = new LogComponent(logListener);
// Register the logger and SIP components. Both components are cluster-safe
try {
componentManager.addComponent(serviceName, sipComponent);
} catch (Exception e) {
componentManager.getLog().error(e);
}
try {
componentManager.addComponent(LogComponent.NAME, logComponent);
} catch (Exception e) {
componentManager.getLog().error(e);
}
PropertyEventDispatcher.addListener(this);
componentManager.getLog().debug("SIPARK STARTED");
}
public void destroyPlugin() {
PropertyEventDispatcher.removeListener(this);
// Unregister component.
try {
componentManager.removeComponent(serviceName);
} catch (Exception e) {
componentManager.getLog().error(e);
}
try {
componentManager.removeComponent(LogComponent.NAME);
} catch (Exception e) {
componentManager.getLog().error(e);
}
sipComponent = null;
logComponent = null;
componentManager = null;
}
/**
* Returns the service name of this component, which is "sipark" by default.
*
* @return the service name of this component.
*/
public String getServiceName() {
return serviceName;
}
/**
* Sets the service name of this component, which is "sipark" by default.
*
* @param serviceName the service name of this component.
*/
public void setServiceName(String serviceName) {
JiveGlobals.setProperty(SipComponent.PROPNAME, serviceName);
}
/**
* Changes the service name to a new value.
*
* @param serviceName the service name.
*/
private void changeServiceName(String serviceName) {
if (serviceName == null) {
throw new NullPointerException("Service name cannot be null");
}
if (this.serviceName.equals(serviceName)) {
return;
}
// Re-register the service.
try {
componentManager.removeComponent(this.serviceName);
} catch (Exception e) {
componentManager.getLog().error(e);
}
try {
componentManager.addComponent(serviceName, sipComponent);
} catch (Exception e) {
componentManager.getLog().error(e);
}
this.serviceName = serviceName;
}
public void propertySet(String property, Map params) {
if (property.equals(SipComponent.NAMESPACE)) {
changeServiceName((String) params.get("value"));
}
}
public void propertyDeleted(String property, Map params) {
if (property.equals(serviceName)) {
changeServiceName(SipComponent.NAME);
}
}
public void xmlPropertySet(String property, Map params) {
// not used
}
public void xmlPropertyDeleted(String property, Map params) {
// not used
}
public ComponentManager getComponentManager() {
return componentManager;
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.calllog;
/**
*
* CallLog instance. This class handle all Log information for a call
*
* @author Thiago Rocha Camargo
*
*/
public class CallLog {
private String username;
private String numA;
private String numB;
private long dateTime;
private int duration;
private Type type = Type.dialed;
public CallLog(String username) {
this.username = username;
}
@SuppressWarnings({"UnnecessarySemicolon"}) // Fix for QDox Source inspector
public enum Type {
dialed, received, missed;
}
public long getDateTime() {
return dateTime;
}
public void setDateTime(long dateTime) {
this.dateTime = dateTime;
}
public String getNumA() {
return numA;
}
public void setNumA(String numA) {
this.numA = numA;
}
public String getNumB() {
return numB;
}
public void setNumB(String numB) {
this.numB = numB;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getUsername() {
return username;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.calllog;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.Log;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
*
* Database persistence for CallLog class and database methods for call log store
*
* @author Thiago Rocha Camargo
*/
public class CallLogDAO {
/**
*
* Return every stored calls that matches to the SQLCondition in the interval between startIndex and endIndex
*
* @param SQLCondition the content of a SQL "Where" clause.
* @param startIndex
* @param numResults
* @return Collection<CallLog>;
*/
public static Collection<CallLog> getCalls(String SQLCondition,
int startIndex, int numResults) {
String sql = "SELECT * FROM sipPhoneLog";
sql = SQLCondition != null && !SQLCondition.equals("") ? sql
+ " WHERE " + SQLCondition : sql;
sql += " ORDER BY datetime DESC";
List<CallLog> calls = new ArrayList<CallLog>(numResults);
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = DbConnectionManager.createScrollablePreparedStatement(con,
sql);
ResultSet rs = pstmt.executeQuery();
DbConnectionManager.setFetchSize(rs, startIndex + numResults);
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
calls.add(read(rs));
count++;
}
rs.close();
} catch (SQLException e) {
Log.error(e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
Log.error(e);
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
Log.error(e);
}
}
return calls;
}
/**
*
* Read a callLog result set and return a CallLog instance with the information of the resultSet
*
* @param rs ResultSet
* @return CallLog
*/
private static CallLog read(ResultSet rs) {
CallLog callLog = null;
try {
String username = rs.getString("username");
String numA = rs.getString("addressFrom");
String numB = rs.getString("addressTo");
long dateTime = rs.getLong("datetime");
int duration = rs.getInt("duration");
String callType = rs.getString("calltype");
if ("loss".equals(callType)) {
// Backwards compatibility change
callType = "missed";
}
CallLog.Type type = CallLog.Type.valueOf(callType);
callLog = new CallLog(username);
callLog.setNumA(numA);
callLog.setNumB(numB);
callLog.setDateTime(dateTime);
callLog.setDuration(duration);
callLog.setType(type);
} catch (SQLException e) {
Log.error(e.getMessage(), e);
}
return callLog;
}
/**
*
* Insert a new CallLog into the database
*
* @param callLog
* @throws SQLException
*/
public static void insert(CallLog callLog) throws SQLException {
String sql = "INSERT INTO sipPhoneLog (username, addressFrom, addressTo, datetime, duration, calltype) "
+ " values (?, ?, ?, ?, ?, ?)";
Connection con = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, callLog.getUsername());
psmt.setString(2, callLog.getNumA());
psmt.setString(3, callLog.getNumB());
psmt.setLong(4, callLog.getDateTime());
psmt.setInt(5, callLog.getDuration());
psmt.setString(6, callLog.getType().name());
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
throw new SQLException(e.getMessage());
} finally {
DbConnectionManager.closeConnection(rs, psmt, con);
}
}
/**
* Gets all calls in database for the given range
* @param startIndex
* @param numResults
* @return Collection<CallLog>
*/
public static Collection<CallLog> getCalls(int startIndex, int numResults) {
return getCalls("", startIndex, numResults);
}
/**
* Return the number of callLog stored
* @return int number
*/
public static int getLogCount() {
return getLogCount("");
}
/**
*
* Return the number of store callLogs for the given SQLCondition
*
* @param SQLCondition
* @return int number
*/
public static int getLogCount(String SQLCondition) {
int count = 0;
String sql = "SELECT count(*) FROM sipPhoneLog";
sql = SQLCondition != null && !SQLCondition.equals("") ? sql + " WHERE " + SQLCondition
: sql;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
} catch (SQLException e) {
Log.error(e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
Log.error(e);
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
Log.error(e);
}
}
return count;
}
/**
* Create a SQLFilter ( SQL Condition ) for CallLog entries
*
* @param username
* @param numa
* @param numb
* @param callType
* @param fromDate
* @param uptoDate
* @return String
*/
public static String createSQLFilter(String username, String numa, String numb,
String callType, Date fromDate, Date uptoDate) {
ArrayList<String> conditions = new ArrayList<String>(10);
if (username != null && !username.trim().equals(""))
conditions.add(" username = '" + username.trim() + "' ");
if (numa != null && !numa.trim().equals(""))
conditions.add(" addressFrom = '" + numa.trim() + "' ");
if (numb != null && !numb.trim().equals(""))
conditions.add(" addressTo = '" + numb.trim() + "' ");
if (fromDate != null)
conditions.add(" datetime >= '" + fromDate.getTime() + "' ");
if (uptoDate != null)
conditions.add(" datetime <= '" + uptoDate.getTime() + "' ");
if (callType != null && !callType.trim().equals("") && !callType.trim().equals("all"))
conditions.add(" calltype = '" + callType.trim() + "' ");
StringBuilder str = new StringBuilder();
for (String aux : conditions) {
if (str.length() > 0)
str.append("AND");
str.append(aux);
}
return str.toString();
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.calllog;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.openfire.sip.sipaccount.SipComponent;
import org.xmpp.packet.PacketExtension;
/**
*
* CallLog packet extension Class.
*
* @author Thiago Rocha Camargo
*/
public class CallLogExtension extends PacketExtension {
public final static String ELEMENT_NAME="callLog";
public final static String NAMESPACE= SipComponent.NAMESPACE+"/log";
static{
registeredExtensions.put(QName.get(ELEMENT_NAME, NAMESPACE), CallLogExtension.class);
}
public CallLogExtension(Element e){
super(e);
}
public CallLogExtension createCopy() {
return new CallLogExtension(this.getElement().createCopy());
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.log;
import org.dom4j.Element;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
/**
*
* Component that process CallLogExtension packets
*
* @author Thiago Rocha Camargo
*/
public class LogComponent implements Component{
ComponentManager componentManager = null;
private LogListener logListener = null;
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://www.jivesoftware.com/protocol/log";
public static final String PROPNAME = "plugin.logger.serviceName";
public static final String NAME = "logger";
public LogComponent(LogListener logListener){
this.componentManager = logListener.getComponentManager();
this.logListener = logListener;
}
public void initialize(JID jid, ComponentManager componentManager) {
}
public void start() {
}
public void shutdown() {
}
// Component Interface
public void processPacket(Packet packet) {
if (packet instanceof IQ) {
// Handle disco packets
IQ iq = (IQ) packet;
// Ignore IQs of type ERROR or RESULT
if (IQ.Type.error == iq.getType() || IQ.Type.result == iq.getType()) {
return;
}
processIQ(iq);
}
}
private void processIQ(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
Element childElement = iq.getChildElement();
String namespace = childElement.getNamespaceURI();
Element childElementCopy = iq.getChildElement().createCopy();
reply.setChildElement(childElementCopy);
if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
if (iq.getTo().getNode() == null) {
// Return service identity and features
Element identity = childElementCopy.addElement("identity");
identity.addAttribute("category", "component");
identity.addAttribute("type", "generic");
identity.addAttribute("name", "Remote Logger");
childElementCopy.addElement("feature").addAttribute("var",
"http://jabber.org/protocol/disco#info");
childElementCopy.addElement("feature").addAttribute("var",
NAMESPACE);
}
} else if (NAMESPACE.equals(namespace)) {
if (iq.getTo().getNode() == null && iq.getFrom() != null) {
reply = logListener.logReceived(reply);
//reply.setTo(reply.getFrom());
}else{
reply.getChildElement().addAttribute("type","unregistered");
}
}
try {
componentManager.sendPacket(this, reply);
} catch (Exception e) {
componentManager.getLog().error(e);
}
} // Other Methods
public String getDescription() {
// Get the description from the plugin.xml file.
return "Remote Logger";
}
public String getName() {
// Get the name from the plugin.xml file.
return NAME;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.log;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.IQ;
/**
* Interface for Log listening
*
*/
public interface LogListener {
public IQ logReceived(IQ iq);
public ComponentManager getComponentManager();
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.log;
import org.dom4j.Element;
import org.jivesoftware.openfire.sip.calllog.CallLog;
import org.jivesoftware.openfire.sip.calllog.CallLogDAO;
import org.jivesoftware.openfire.sip.calllog.CallLogExtension;
import org.xmpp.component.ComponentManager;
import org.xmpp.packet.IQ;
import java.sql.SQLException;
import java.util.Date;
/**
* Implements a LogListener.
* Log every call events of SIP users that are using Spark SIP plugin
*
* @author Thiago Rocha Camargo
*/
public class LogListenerImpl implements LogListener {
ComponentManager componentManager = null;
public LogListenerImpl(ComponentManager componentmanager) {
this.componentManager = componentmanager;
}
public IQ logReceived(IQ iq) {
String username = iq.getTo().toBareJID().split("@")[0];
if (username != null) {
CallLog callLog = new CallLog(username);
Element pe = iq.getChildElement().element("callLog");
if (pe != null) {
Element numA = pe.element("numA");
Element numB = pe.element("numB");
Element duration = pe.element("duration");
Element type = pe.element("type");
callLog.setNumA((numA != null) ? numA.getTextTrim() : "");
callLog.setNumB((numB != null) ? numB.getTextTrim() : "");
callLog.setDateTime(new Date().getTime());
callLog.setDuration((duration != null) ? Integer.parseInt(duration.getText()) : 0);
if (type != null && "loss".equals(type.getTextTrim())) {
// Backwards compatibility change
type.setText("missed");
}
callLog.setType((type != null) ? CallLog.Type.valueOf(type.getTextTrim()) : CallLog.Type.dialed);
try {
CallLogDAO.insert(callLog);
} catch (SQLException e) {
componentManager.getLog().error(e);
}
}
}
iq.setType(IQ.Type.result);
iq.deleteExtension(CallLogExtension.ELEMENT_NAME, CallLogExtension.NAMESPACE);
Element childElement = iq.getChildElement();
if (childElement != null) {
Element childElementCopy = childElement.createCopy();
iq.setChildElement(childElementCopy);
}
return iq;
}
public ComponentManager getComponentManager() {
return this.componentManager;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.sipaccount;
import org.jivesoftware.util.JiveGlobals;
/**
* SipAccount instance. This class handle all SIP account information for a user
*
* @author Thiago Rocha Camargo
*/
public class SipAccount {
private String username = null;
private String sipUsername = "";
private String authUsername = "";
private String displayName = "";
private String password = "";
private String server = "";
private String outboundproxy = "";
private String stunServer = "";
private String stunPort = "";
private String voiceMailNumber = "";
private boolean useStun = false;
private boolean enabled = false;
private boolean promptCredentials = false;
private SipRegisterStatus status = SipRegisterStatus.Unregistered;
public SipAccount(String username, String sipUsername, String authUsername, String displayName, String password, String server, String outboundproxy, boolean promptCredentials) {
this.username = username;
this.sipUsername = sipUsername;
this.authUsername = authUsername;
this.displayName = displayName;
this.password = password;
this.server = server;
this.outboundproxy = outboundproxy;
this.promptCredentials = promptCredentials;
}
public SipAccount(String username) {
this.username = username;
}
public String getAuthUsername() {
return authUsername == null ? "" : authUsername;
}
public void setAuthUsername(String authUsername) {
this.authUsername = authUsername;
}
public String getDisplayName() {
return displayName == null ? "" : displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getVoiceMailNumber() {
return voiceMailNumber == null ? JiveGlobals.getProperty("phone.voiceMail", "") : voiceMailNumber;
}
public void setVoiceMailNumber(String voiceMailNumber) {
this.voiceMailNumber = voiceMailNumber;
}
public String getServer() {
return server == null ? JiveGlobals.getProperty("phone.sipServer", "") : server;
}
public void setServer(String server) {
this.server = server;
}
public String getOutboundproxy() {
return outboundproxy;
}
public void setOutboundproxy(String outboundproxy) {
this.outboundproxy = outboundproxy;
}
public String getSipUsername() {
return sipUsername == null ? "" : sipUsername;
}
public void setSipUsername(String sipUsername) {
this.sipUsername = sipUsername;
}
public String getUsername() {
return username == null ? "" : username;
}
public String getPassword() {
return password == null ? "" : password;
}
public void setPassword(String password) {
this.password = password;
}
public String getStunPort() {
return stunPort == null ? JiveGlobals.getProperty("phone.stunPort", "") : stunPort;
}
public void setStunPort(String stunPort) {
this.stunPort = stunPort;
}
public String getStunServer() {
return stunServer == null ? JiveGlobals.getProperty("phone.stunServer", "") : stunServer;
}
public void setStunServer(String stunServer) {
this.stunServer = stunServer;
}
public boolean isUseStun() {
if (stunPort == null && stunServer == null) {
return JiveGlobals.getBooleanProperty("phone.stunEnabled", false);
}
return useStun;
}
public void setUseStun(boolean useStun) {
this.useStun = useStun;
}
public SipRegisterStatus getStatus() {
return status == null ? SipRegisterStatus.Unregistered : status;
}
public void setStatus(SipRegisterStatus status) {
this.status = status;
}
public boolean isPromptCredentials() {
return promptCredentials;
}
public void setPromptCredentials(boolean promptCredentials) {
this.promptCredentials = promptCredentials;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.sipaccount;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.Log;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
* Database persistence for SipAccount class and database methods for stored SIP Accounts
*
* @author Thiago Rocha Camargo
*/
public class SipAccountDAO {
public static SipAccount getAccountByUser(String username) {
String sql = "SELECT username, sipusername, sipauthuser, sipdisplayname, sippassword, sipserver, enabled, " +
"status, stunserver, stunport, usestun, voicemail, outboundproxy, promptCredentials FROM sipUser " +
"WHERE username = ? ";
SipAccount sipAccount = null;
Connection con = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, username);
rs = psmt.executeQuery();
if (rs.next()) {
sipAccount = read(rs);
}
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(rs, psmt, con);
}
return sipAccount;
}
private static SipAccount read(ResultSet rs) {
SipAccount sipAccount = null;
try {
String username = rs.getString("username");
String sipusername = rs.getString("sipusername");
String authusername = rs.getString("sipauthuser");
String displayname = rs.getString("sipdisplayname");
String password = rs.getString("sippassword");
String server = rs.getString("sipserver");
String stunServer = rs.getString("stunserver");
String stunPort = rs.getString("stunport");
boolean useStun = rs.getBoolean("usestun");
boolean enabled = rs.getBoolean("enabled");
String voicemail = rs.getString("voicemail");
String outboundproxy = rs.getString("outboundproxy");
boolean promptCredentials = rs.getBoolean("promptCredentials");
SipRegisterStatus status = SipRegisterStatus.valueOf(rs.getString("status"));
sipAccount = new SipAccount(username);
sipAccount.setSipUsername(sipusername);
sipAccount.setAuthUsername(authusername);
sipAccount.setDisplayName(displayname);
sipAccount.setPassword(password);
sipAccount.setServer(server);
sipAccount.setEnabled(enabled);
sipAccount.setStatus(status);
sipAccount.setStunServer(stunServer);
sipAccount.setStunPort(stunPort);
sipAccount.setUseStun(useStun);
sipAccount.setVoiceMailNumber(voicemail);
sipAccount.setOutboundproxy(outboundproxy);
sipAccount.setPromptCredentials(promptCredentials);
} catch (SQLException e) {
Log.error(e.getMessage(), e);
}
return sipAccount;
}
public static void insert(SipAccount sipAccount) throws SQLException {
String sql = "INSERT INTO sipUser (username, sipusername, sipauthuser, sipdisplayname, sippassword, sipserver, enabled, status, stunserver, stunport, usestun, voicemail, outboundproxy, promptCredentials ) "
+ " values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
Connection con = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, sipAccount.getUsername());
psmt.setString(2, sipAccount.getSipUsername());
psmt.setString(3, sipAccount.getAuthUsername());
psmt.setString(4, sipAccount.getDisplayName());
psmt.setString(5, sipAccount.getPassword());
psmt.setString(6, sipAccount.getServer());
psmt.setBoolean(7, sipAccount.isEnabled());
psmt.setString(8, sipAccount.getStatus().name());
psmt.setString(9, sipAccount.getStunServer());
psmt.setString(10, sipAccount.getStunPort());
psmt.setBoolean(11, sipAccount.isUseStun());
psmt.setString(12, sipAccount.getVoiceMailNumber());
psmt.setString(13, sipAccount.getOutboundproxy());
psmt.setBoolean(14, sipAccount.isPromptCredentials());
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
throw new SQLException(e.getMessage());
} finally {
DbConnectionManager.closeConnection(rs, psmt, con);
}
}
public static void update(SipAccount sipAccount) throws SQLException {
String sql = "UPDATE sipUser SET sipusername = ?, sipauthuser = ?, sipdisplayname = ?, sippassword = ?, sipserver = ?, enabled = ?, status = ?, stunserver = ?, stunport = ?, usestun = ?, voicemail= ?, outboundproxy = ?, promptCredentials = ? "
+ " WHERE username = ?";
Connection con = null;
PreparedStatement psmt = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, sipAccount.getSipUsername());
psmt.setString(2, sipAccount.getAuthUsername());
psmt.setString(3, sipAccount.getDisplayName());
psmt.setString(4, sipAccount.getPassword());
psmt.setString(5, sipAccount.getServer());
psmt.setBoolean(6, sipAccount.isEnabled());
psmt.setString(7, sipAccount.getStatus().name());
psmt.setString(8, sipAccount.getStunServer());
psmt.setString(9, sipAccount.getStunPort());
psmt.setBoolean(10, sipAccount.isUseStun());
psmt.setString(11, sipAccount.getVoiceMailNumber());
psmt.setString(12, sipAccount.getOutboundproxy());
psmt.setBoolean(13, sipAccount.isPromptCredentials());
psmt.setString(14, sipAccount.getUsername());
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
throw new SQLException(e.getMessage());
} finally {
DbConnectionManager.closeConnection(psmt, con);
}
}
public static void remove(SipAccount sipAccount) {
String sql = "DELETE FROM sipUser WHERE username = ?";
Connection con = null;
PreparedStatement psmt = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, sipAccount.getUsername());
psmt.executeUpdate();
psmt.close();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(psmt, con);
}
}
public static Collection<SipAccount> getUsers(int startIndex, int numResults) {
String sql = "SELECT username, sipusername, sipauthuser, sipdisplayname, sippassword, sipserver, enabled, status, stunserver, stunport, usestun, voicemail, outboundproxy, promptCredentials FROM sipUser "
+ " ORDER BY USERNAME";
List<SipAccount> sipAccounts = new ArrayList<SipAccount>(numResults);
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = DbConnectionManager.createScrollablePreparedStatement(con,
sql);
ResultSet rs = pstmt.executeQuery();
DbConnectionManager.setFetchSize(rs, startIndex + numResults);
DbConnectionManager.scrollResultSet(rs, startIndex);
int count = 0;
while (rs.next() && count < numResults) {
sipAccounts.add(read(rs));
count++;
}
rs.close();
} catch (SQLException e) {
Log.error(e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
Log.error(e);
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
Log.error(e);
}
}
return sipAccounts;
}
public static int getUserCount() {
int count = 0;
String sql = "SELECT count(*) FROM sipUser";
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
}
catch (SQLException e) {
Log.error(e);
}
finally {
try { if (pstmt != null) { pstmt.close(); } }
catch (Exception e) { Log.error(e); }
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
return count;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.sipaccount;
import org.dom4j.Element;
import org.jivesoftware.openfire.event.SessionEventDispatcher;
import org.jivesoftware.openfire.event.SessionEventListener;
import org.jivesoftware.openfire.session.Session;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
import java.sql.SQLException;
/**
* Implements an openfire Component and SessionEventListener. Controls every
* registration inf request and process user's SIP presence informations.
*
* @author Thiago Rocha Camargo
*/
public class SipComponent implements Component, SessionEventListener {
ComponentManager componentManager = null;
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://www.jivesoftware.com/protocol/sipark";
public static final String PROPNAME = "plugin.sipark.serviceName";
public static final String NAME = "sipark";
public SipComponent() {
this.componentManager = ComponentManagerFactory.getComponentManager();
SessionEventDispatcher.addListener(this);
}
public void initialize(JID jid, ComponentManager componentManager) {
}
public void start() {
}
public void shutdown() {
SessionEventDispatcher.removeListener(this);
}
// Component Interface
public void processPacket(Packet packet) {
componentManager.getLog().debug(packet.toXML());
if (packet instanceof IQ) {
// Handle disco packets
IQ iq = (IQ)packet;
// Ignore IQs of type ERROR or RESULT
if (IQ.Type.error == iq.getType() || IQ.Type.result == iq.getType()) {
return;
}
processIQ(iq);
}
}
private void processIQ(IQ iq) {
IQ reply = IQ.createResultIQ(iq);
String namespace = iq.getChildElement().getNamespaceURI();
Element childElement = iq.getChildElement().createCopy();
reply.setChildElement(childElement);
if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
if (iq.getTo().getNode() == null) {
// Return service identity and features
Element identity = childElement.addElement("identity");
identity.addAttribute("category", "component");
identity.addAttribute("type", "generic");
identity.addAttribute("name", "SIP Controller");
childElement.addElement("feature").addAttribute("var", "http://jabber.org/protocol/disco#info");
childElement.addElement("feature").addAttribute("var", "http://www.jivesoftware.com/protocol/sipark");
}
}
else if (NAMESPACE.equals(namespace)) {
if (iq.getTo().getNode() == null && iq.getFrom() != null) {
SipAccount sipAccount = SipAccountDAO.getAccountByUser(iq.getFrom().toBareJID().split("@")[0]);
if (iq.getChildElement().element("status") == null) {
if (sipAccount != null && sipAccount.isEnabled()) {
// There is a SIP mapping for this user so return mapping information
Element registration = childElement.addElement("registration");
registration.addElement("jid")
.setText(sipAccount.getUsername() + "@" + componentManager.getServerName());
registration.addElement("username").setText(sipAccount.getSipUsername());
registration.addElement("authUsername").setText(sipAccount.getAuthUsername());
registration.addElement("displayPhoneNum").setText(sipAccount.getDisplayName());
registration.addElement("password").setText(sipAccount.getPassword());
registration.addElement("server").setText(sipAccount.getServer());
registration.addElement("stunServer").setText(sipAccount.getStunServer());
registration.addElement("stunPort").setText(sipAccount.getStunPort());
registration.addElement("useStun").setText(String.valueOf(sipAccount.isUseStun()));
registration.addElement("voicemail").setText(sipAccount.getVoiceMailNumber());
registration.addElement("enabled").setText(String.valueOf(sipAccount.isEnabled()));
registration.addElement("outboundproxy").setText(sipAccount.getOutboundproxy());
registration.addElement("promptCredentials").setText(String.valueOf(sipAccount.isPromptCredentials()));
}
else {
// No SIP mapping was found
reply.getChildElement().addAttribute("type", "unregistered");
}
}
else {
if (sipAccount != null) {
Element status = iq.getChildElement().element("status");
if (!status.getTextTrim().equals("")) {
sipAccount.setStatus(SipRegisterStatus.valueOf(status.getTextTrim()));
try {
SipAccountDAO.update(sipAccount);
}
catch (SQLException e) {
componentManager.getLog().error(e);
}
}
}
}
}
}
else {
// Answer an error since the server can't handle the requested
// namespace
reply.setError(PacketError.Condition.service_unavailable);
}
try {
componentManager.sendPacket(this, reply);
}
catch (Exception e) {
componentManager.getLog().error(e);
}
componentManager.getLog().debug("PACKET SENT: " + reply.toXML());
} // Other Methods
public String getDescription() {
return "SIP Admin Plugin";
}
public String getName() {
return "SIPAdmin";
}
public void anonymousSessionCreated(Session arg0) {
// Ignore
}
public void anonymousSessionDestroyed(Session arg0) {
// Ignore
}
public void sessionCreated(Session arg0) {
// Ignore
}
/**
* Sets the user SIP presence to Unregistered if his jabber account is disconnected.
*
* @param session the destroyed session
*/
public void sessionDestroyed(Session session) {
String username = session.getAddress().toBareJID().split("@")[0];
SipAccount sipAccount = SipAccountDAO.getAccountByUser(username);
if (sipAccount != null) {
try {
sipAccount.setStatus(SipRegisterStatus.Unregistered);
SipAccountDAO.update(sipAccount);
}
catch (SQLException e) {
componentManager.getLog().error(e);
}
}
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.sipaccount;
/**
* Sip Registration Status Enum
*
* Used to define the registration status of a user.
*
* @author Thiago Rocha Camargo
*/
public enum SipRegisterStatus {
Unregistered,Unregistering,Registering,Registered,RegistrationFailed
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester;
/**
* Title: SIP Register Tester
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
/**
* Creates and writes out messages.
*/
public class Log {
private static boolean debugger = false;
static {
if (System.getProperty("debugger") != null
&& System.getProperty("debugger").equals("true"))
Log.debugger = true;
}
public static void debug(String message) {
if (Log.debugger)
System.out.println((message != null ? message : ""));
}
public static void debug(String method, String message) {
if (Log.debugger)
System.out.println((method != null ? method : "") + " - "
+ (message != null ? message : ""));
}
public static void error(String method, Exception e) {
System.out.println((method != null ? method : "") + " - "
+ (e != null ? e.toString() : ""));
}
public static void error(Exception e) {
Log.error("", e);
}
public static void error(String method, Error e) {
System.out.println((method != null ? method : "") + " - "
+ (e != null ? e.toString() : ""));
}
public static void error(String method, Throwable e) {
System.out.println((method != null ? method : "") + " - "
+ (e != null ? e.toString() : ""));
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.comm;
import java.util.EventObject;
/**
* <p/>
* Title: SIP COMMUNICATOR-1.1
* </p>
* <p/>
* Description: JAIN-SIP-1.1 Audio/Video Phone Application
* </p>
* <p/>
* Copyright: Copyright (c) 2003
* </p>
* <p/>
* Company: Organisation: LSIIT Laboratory (http://lsiit.u-strasbg.fr) \nNetwork
* Research Team (http://www-r2.u-strasbg.fr))\nLouis Pasteur University -
* Strasbourg - France
* </p>
*
* @author Emil Ivov
* @version 1.1
*/
public class CommunicationsErrorEvent extends EventObject {
public CommunicationsErrorEvent(Throwable source) {
super(source);
}
public Throwable getCause() {
return (Throwable)source;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.comm;
/**
* Title: SIP Register Tester
* Description:JAIN-SIP Test application
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class CommunicationsException extends Exception {
/**
*/
private boolean isFatal = false;
public CommunicationsException() {
this("CommunicationsException");
}
public CommunicationsException(String message) {
this(message, null);
}
public CommunicationsException(String message, Throwable cause) {
this(message, cause, false);
}
public CommunicationsException(String message, Throwable cause,
boolean isFatal) {
super(message, cause);
setFatal(isFatal);
}
// ------------------ is fatal
/**
* @return
* @uml.property name="isFatal"
*/
public boolean isFatal() {
return isFatal;
}
/**
* @param isFatal The isFatal to set.
* @uml.property name="isFatal"
*/
public void setFatal(boolean isFatal) {
this.isFatal = isFatal;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.comm;
import org.jivesoftware.openfire.sip.tester.stack.RegistrationEvent;
import java.util.EventListener;
/**
* <p/>
* Title: SIP COMMUNICATOR
* </p>
* <p/>
* Description:JAIN-SIP Audio/Video phone application
* </p>
* <p/>
* Copyright: Copyright (c) 2003
* </p>
* <p/>
* Organisation: LSIIT laboratory (http://lsiit.u-strasbg.fr)
* </p>
* <p/>
* Network Research Team (http://www-r2.u-strasbg.fr))
* </p>
* <p/>
* Louis Pasteur University - Strasbourg - France
* </p>
*
* @author Emil Ivov (http://www.emcho.com)
* @version 1.1
*/
public interface CommunicationsListener extends EventListener {
public void registered(RegistrationEvent evt);
public void registering(RegistrationEvent evt);
public void registrationFailed(RegistrationEvent evt);
public void unregistering(RegistrationEvent evt);
public void unregistered(RegistrationEvent evt);
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.security;
import java.util.Hashtable;
/**
* The class is used to cache all realms that a certain call has been authorized
* against and all credentials that have been used for each realm. Note that
* rfc3261 suggests keeping callId->credentials mapping where as we map
* realm->credentials. This is done to avoid asking the user for a password
* before each call.
*
* @author Emil Ivov <emcho@dev.java.net>
* @version 1.0
*/
class CredentialsCache {
// Contains call->realms mappings
private Hashtable authenticatedRealms = new Hashtable();
/**
* Cache credentials for the specified call and realm
*
* @param realm the realm that the specify credentials apply to
* @param cacheEntry the credentials
*/
void cacheEntry(String realm, CredentialsCacheEntry cacheEntry) {
authenticatedRealms.put(realm, cacheEntry);
}
/**
* Returns the credentials corresponding to the specified realm or null if
* none could be found.
*
* @param realm the realm that the credentials apply to
* @return the credentials corresponding to the specified realm or null if
* none could be found.
*/
CredentialsCacheEntry get(String realm) {
return (CredentialsCacheEntry)this.authenticatedRealms.get(realm);
}
/**
* Returns the credentials corresponding to the specified realm or null if
* none could be found and removes the entry from the cache.
*
* @param realm
* the realm that the credentials apply to
* @return the credentials corresponding to the specified realm or null if
* none could be found.
*/
CredentialsCacheEntry remove(String realm) {
return (CredentialsCacheEntry)this.authenticatedRealms.remove(realm);
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.security;
import java.util.Vector;
/**
* Used to cache credentials through a call.
*
* @author Emil Ivov <emcho@dev.java.net>
* @version 1.0
*/
class CredentialsCacheEntry {
// The header that was used last time
// AuthorizationHeader authorization = null;
UserCredentials userCredentials = null;
/**
* The transactionHistory list contains transactions where the entry has
* been and that had not yet been responded to (or at least the response has
* not reached this class). The transactionHistory's elements are Strings
* corresponding to branch ids.
*/
private Vector transactionHistory = new Vector();
/**
* Adds the specified branch id to the transaction history list.
*
* @param requestBranchID the id to add to the list of uncofirmed transactions.
*/
void processRequest(String requestBranchID) {
transactionHistory.add(requestBranchID);
}
/**
* Determines whether these credentials have been used for the specified
* transaction. If yes - the transaction is removed and true is returned.
* Otherwise we return false.
*
* @param responseBranchID the branchi id of the response to process.
* @return true if this entry hase been used for the transaction.
*/
boolean processResponse(String responseBranchID) {
return transactionHistory.remove(responseBranchID);
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.security;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* The class takes standard Http Authentication details and returns a response
* according to the MD5 algorithm
*
* @author Emil Ivov < emcho@dev.java.net >
* @version 1.0
*/
public class MessageDigestAlgorithm {
/**
* Calculates a response an http authentication response in accordance with
* rfc2617.
*
* @param algorithm MD5 or MD5-sess)
* @param username_value username_value (see rfc2617)
* @param realm_value realm_value
* @param passwd passwd
* @param nonce_value nonce_value
* @param cnonce_value cnonce_value
* @param Method method
* @param digest_uri_value uri_value
* @param entity_body entity_body
* @param qop_value qop
* @return a digest response as defined in rfc2617
* @throws NullPointerException in case of incorrectly null parameters.
*/
static String calculateResponse(String algorithm, String username_value,
String realm_value, String passwd, String nonce_value,
String nc_value, String cnonce_value, String Method,
String digest_uri_value, String entity_body, String qop_value) {
if (username_value == null || realm_value == null || passwd == null
|| Method == null || digest_uri_value == null
|| nonce_value == null)
throw new NullPointerException(
"Null parameter to MessageDigestAlgorithm.calculateResponse()");
// The following follows closely the algorithm for generating a response
// digest as specified by rfc2617
String A1 = null;
if (algorithm == null || algorithm.trim().length() == 0
|| algorithm.trim().equalsIgnoreCase("MD5")) {
A1 = username_value + ":" + realm_value + ":" + passwd;
}
else {
if (cnonce_value == null || cnonce_value.length() == 0)
throw new NullPointerException(
"cnonce_value may not be absent for MD5-Sess algorithm.");
A1 = MessageDigestAlgorithm.H(username_value + ":" + realm_value + ":" + passwd) + ":"
+ nonce_value + ":" + cnonce_value;
}
String A2 = null;
if (qop_value == null || qop_value.trim().length() == 0
|| qop_value.trim().equalsIgnoreCase("auth")) {
A2 = Method + ":" + digest_uri_value;
}
else {
if (entity_body == null)
entity_body = "";
A2 = Method + ":" + digest_uri_value + ":" + MessageDigestAlgorithm.H(entity_body);
}
String request_digest = null;
if (cnonce_value != null && qop_value != null
&& (qop_value.equals("auth") || (qop_value.equals("auth-int")))) {
request_digest = MessageDigestAlgorithm.KD(MessageDigestAlgorithm.H(A1), nonce_value + ":" + nc_value + ":"
+ cnonce_value + ":" + qop_value + ":" + MessageDigestAlgorithm.H(A2));
}
else {
request_digest = MessageDigestAlgorithm.KD(MessageDigestAlgorithm.H(A1), nonce_value + ":" + MessageDigestAlgorithm.H(A2));
}
return request_digest;
}
/**
* Defined in rfc 2617 as H(data) = MD5(data);
*
* @param data data
* @return MD5(data)
*/
private static String H(String data) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
return MessageDigestAlgorithm.toHexString(digest.digest(data.getBytes()));
}
catch (NoSuchAlgorithmException ex) {
// shouldn't happen
return null;
}
}
/**
* Defined in rfc 2617 as KD(secret, data) = H(concat(secret, ":", data))
*
* @param data data
* @param secret secret
* @return H(concat(secret, ":", data));
*/
private static String KD(String secret, String data) {
return MessageDigestAlgorithm.H(secret + ":" + data);
}
// the following code was copied from the NIST-SIP instant
// messenger (its author is Olivier Deruelle). Thanks for making it public!
/**
* to hex converter
*/
private static final char[] toHex = {'0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Converts b[] to hex string.
*
* @param b
* the bte array to convert
* @return a Hex representation of b.
*/
private static String toHexString(byte b[]) {
int pos = 0;
char[] c = new char[b.length * 2];
for (int i = 0; i < b.length; i++) {
c[pos++] = MessageDigestAlgorithm.toHex[(b[i] >> 4) & 0x0F];
c[pos++] = MessageDigestAlgorithm.toHex[b[i] & 0x0f];
}
return new String(c);
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.security;
/**
* This exception is used by SipSecurityManager to indicate failure to provide
* valid credentials for a given request.
*
* @author Emil Ivov <emcho@dev.java.net>
* @version 1.0
*/
public class SipSecurityException extends Exception {
public SipSecurityException() {
this("SipSecurityException");
}
public SipSecurityException(String message) {
super(message);
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.security;
import org.jivesoftware.openfire.sip.tester.Log;
import org.jivesoftware.openfire.sip.tester.stack.SIPConfig;
import org.jivesoftware.openfire.sip.tester.stack.SipManager;
import javax.sip.ClientTransaction;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.SipProvider;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ListIterator;
/**
* <p/>
* Title: Netsite TudoMais
* </p>
* <p/>
* Description:JAIN-SIP Audio/Video phone application
* </p>
* <p/>
* Copyright: Copyright (c) 2006
* </p>
* <p/>
* Organisation: CTBC Telecom / Netsite
* </p>
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class SipSecurityManager {
/**
*/
private HeaderFactory headerFactory = null;
/**
*/
private SipProvider transactionCreator = null;
private SipManager sipManCallback = null;
/**
* Credentials cached so far.
*/
CredentialsCache cachedCredentials = new CredentialsCache();
public UserCredentials defaultCredentials = null;
public SipSecurityManager() {
}
public UserCredentials getDefaultCredentials() {
return defaultCredentials;
}
public void setDefaultCredentials(UserCredentials defaultCredentials) {
this.defaultCredentials = defaultCredentials;
}
/**
* set the header factory to be used when creating authorization headers
*
* @uml.property name="headerFactory"
*/
public void setHeaderFactory(HeaderFactory headerFactory) {
this.headerFactory = headerFactory;
}
/**
* Verifies whether there are any user credentials registered for the call
* that "request" belongs to and appends corresponding authorization headers
* if that is the case.
*
* @param request the request that needs to be attached credentials.
*/
public void appendCredentialsIfNecessary(Request request) {
// TODO IMPLEMENT
}
/**
* Uses securityAuthority to determinie a set of valid user credentials for
* the specified Response (Challenge) and appends it to the challenged
* request so that it could be retransmitted.
* <p/>
* Fredrik Wickstrom reported that dialog cseq counters are not incremented
* when resending requests. He later uncovered additional problems and
* proposed a way to fix them (his proposition was taken into account).
*
* @param challenge the 401/407 challenge response
* @param challengedTransaction the transaction established by the challenged request
* @return a transaction containing a reoriginated request with the
* necessary authorization header.
* @throws SipSecurityException
*/
public ClientTransaction handleChallenge(Response challenge,
ClientTransaction challengedTransaction)
throws SipSecurityException, SipException,
InvalidArgumentException, ParseException {
try {
String branchID = challengedTransaction.getBranchId();
Request challengedRequest = challengedTransaction.getRequest();
Request reoriginatedRequest = (Request) challengedRequest.clone();
ListIterator authHeaders = null;
if (challenge == null || reoriginatedRequest == null)
throw new NullPointerException(
"A null argument was passed to handle challenge.");
// CallIdHeader callId =
// (CallIdHeader)challenge.getHeader(CallIdHeader.NAME);
if (challenge.getStatusCode() == Response.UNAUTHORIZED)
authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED)
authHeaders = challenge
.getHeaders(ProxyAuthenticateHeader.NAME);
if (authHeaders == null)
throw new SecurityException(
"Could not find WWWAuthenticate or ProxyAuthenticate headers");
// Remove all authorization headers from the request (we'll re-add
// them
// from cache)
reoriginatedRequest.removeHeader(AuthorizationHeader.NAME);
reoriginatedRequest.removeHeader(ProxyAuthorizationHeader.NAME);
// rfc 3261 says that the cseq header should be augmented for the
// new
// request. do it here so that the new dialog (created together with
// the new client transaction) takes it into account.
// Bug report - Fredrik Wickstrom
CSeqHeader cSeq = (CSeqHeader) reoriginatedRequest
.getHeader((CSeqHeader.NAME));
cSeq.setSequenceNumber(cSeq.getSequenceNumber() + 1);
ClientTransaction retryTran = transactionCreator
.getNewClientTransaction(reoriginatedRequest);
WWWAuthenticateHeader authHeader = null;
CredentialsCacheEntry ccEntry = null;
while (authHeaders.hasNext()) {
authHeader = (WWWAuthenticateHeader) authHeaders.next();
String realm = authHeader.getRealm();
// Check whether we have cached credentials for authHeader's
// realm
// make sure that if such credentials exist they get removed.
// The
// challenge means that there's something wrong with them.
ccEntry = cachedCredentials.remove(realm);
// Try to guess user name and facilitate user
UserCredentials defaultCredentials = new UserCredentials();
FromHeader from = (FromHeader) reoriginatedRequest
.getHeader(FromHeader.NAME);
URI uri = from.getAddress().getURI();
if (uri.isSipURI()) {
Log.debug("handleChallenge", SIPConfig.getAuthUserName());
String user = SIPConfig.getAuthUserName() != null ? SIPConfig
.getAuthUserName()
: ((SipURI) uri).getUser();
defaultCredentials.setAuthUserName(user == null ? SIPConfig
.getUserName() : user);
}
boolean ccEntryHasSeenTran = false;
if (ccEntry != null)
ccEntryHasSeenTran = ccEntry.processResponse(branchID);
// get a new pass
if (ccEntry == null // we don't have credentials for the
// specified realm
|| ((!authHeader.isStale() && ccEntryHasSeenTran))) {
if (ccEntry == null) {
ccEntry = new CredentialsCacheEntry();
ccEntry.userCredentials = defaultCredentials;
}
// put the returned user name in the properties file
// so that it appears as a default one next time user is
// prompted for pass
SIPConfig
.setUserName(ccEntry.userCredentials.getUserName());
}
// encode and send what we have
else if (ccEntry != null
&& (!ccEntryHasSeenTran || authHeader.isStale())) {
}
// if user canceled or sth else went wrong
if (ccEntry.userCredentials == null)
throw new SecurityException(
"Unable to authenticate with realm " + realm);
AuthorizationHeader authorization = this.getAuthorization(
reoriginatedRequest.getMethod(), reoriginatedRequest
.getRequestURI().toString(),
reoriginatedRequest.getContent() == null ? ""
: reoriginatedRequest.getContent().toString(),
authHeader, ccEntry.userCredentials);
ccEntry.processRequest(retryTran.getBranchId());
cachedCredentials.cacheEntry(realm, ccEntry);
reoriginatedRequest.addHeader(authorization);
// if there was trouble with the user - make sure we fix it
if (uri.isSipURI()) {
((SipURI) uri).setUser(ccEntry.userCredentials
.getUserName());
Address add = from.getAddress();
add.setURI(uri);
from.setAddress(add);
reoriginatedRequest.setHeader(from);
if (challengedRequest.getMethod().equals(Request.REGISTER)) {
ToHeader to = (ToHeader) reoriginatedRequest
.getHeader(ToHeader.NAME);
add.setURI(uri);
to.setAddress(add);
reoriginatedRequest.setHeader(to);
}
// very ugly but very necessary
sipManCallback.setCurrentlyUsedURI(uri.toString());
Log.debug("URI: " + uri.toString());
}
// if this is a register - fix to as well
}
return retryTran;
}
catch (Exception e) {
Log.debug("ERRO REG: " + e.toString());
return null;
}
}
/**
* Generates an authorisation header in response to wwwAuthHeader.
*
* @param method method of the request being authenticated
* @param uri digest-uri
* @param authHeader the challenge that we should respond to
* @param userCredentials username and pass
* @return an authorisation header in response to wwwAuthHeader.
*/
private AuthorizationHeader getAuthorization(String method, String uri,
String requestBody, WWWAuthenticateHeader authHeader,
UserCredentials userCredentials) throws SecurityException {
String response = null;
try {
Log.debug("getAuthorization", userCredentials.getAuthUserName());
response = MessageDigestAlgorithm.calculateResponse(authHeader
.getAlgorithm(), userCredentials.getAuthUserName(),
authHeader.getRealm(), new String(userCredentials
.getPassword()), authHeader.getNonce(),
// TODO we should one day implement those two null-s
null,// nc-value
null,// cnonce
method, uri, requestBody, authHeader.getQop());
}
catch (NullPointerException exc) {
throw new SecurityException(
"The authenticate header was malformatted");
}
AuthorizationHeader authorization = null;
try {
if (authHeader instanceof ProxyAuthenticateHeader) {
authorization = headerFactory
.createProxyAuthorizationHeader(authHeader.getScheme());
} else {
authorization = headerFactory
.createAuthorizationHeader(authHeader.getScheme());
}
authorization.setUsername(userCredentials.getAuthUserName());
authorization.setRealm(authHeader.getRealm());
authorization.setNonce(authHeader.getNonce());
authorization.setParameter("uri", uri);
authorization.setResponse(response);
if (authHeader.getAlgorithm() != null)
authorization.setAlgorithm(authHeader.getAlgorithm());
if (authHeader.getOpaque() != null)
authorization.setOpaque(authHeader.getOpaque());
authorization.setResponse(response);
}
catch (ParseException ex) {
throw new SecurityException(
"Failed to create an authorization header!");
}
return authorization;
}
public void cacheCredentials(String realm, UserCredentials credentials) {
CredentialsCacheEntry ccEntry = new CredentialsCacheEntry();
ccEntry.userCredentials = credentials;
this.cachedCredentials.cacheEntry(realm, ccEntry);
}
/**
* Sets a valid SipProvider that would enable the security manager to map
* credentials to transactionsand thus understand when it is suitable to use
* cached passwords and when it should go ask the user.
*
* @param transactionCreator a valid SipProvder instance
* @uml.property name="transactionCreator"
*/
public void setTransactionCreator(SipProvider transactionCreator) {
this.transactionCreator = transactionCreator;
}
/**
* If the user name was wrong and the user fixes it here we should als
* notify the sip manager that the currentlyUsedURI it has is not valid.
*
* @param sipManCallback a valid instance of SipMaqnager
* @uml.property name="sipManCallback"
*/
public void setSipManCallback(SipManager sipManCallback) {
this.sipManCallback = sipManCallback;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.security;
/**
* Title: SIP Register Tester
* Description:JAIN-SIP Test application
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class UserCredentials {
/**
*/
private static String userName = null;
/**
*/
private static char[] password = null;
/**
*/
private static String authUserName = null;
/**
*/
private static String displayName = null;
/**
* Sets the user name.
*
* @param userName The user name to set.
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* Sets the user name.
*
* @param userName The user name to set in Authentication challenge.
*/
public void setAuthUserName(String userName) {
this.authUserName = userName;
}
public static void clean() {
UserCredentials.userName = null;
UserCredentials.password = null;
UserCredentials.authUserName = null;
}
public static String getUserDisplay() {
return UserCredentials.displayName == null ? UserCredentials.userName : UserCredentials.displayName;
}
/**
* Returns the user name.
*
* @return the user name.
*/
public String getUserName() {
return this.userName;
}
/**
* Returns the user name.
*
* @return the user name.
*/
public String getAuthUserName() {
return this.authUserName != null && !this.authUserName.equals("") ? this.authUserName
: this.userName;
}
/**
* Sets the user password.
*
* @param passwd The password associated with username
*/
public void setPassword(char[] passwd) {
this.password = passwd;
}
/**
* Returns these credentials' password
*
* @return these credentials' password
*/
public char[] getPassword() {
return UserCredentials.password;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
import org.jivesoftware.openfire.sip.tester.security.SipSecurityException;
import org.jivesoftware.openfire.sip.tester.comm.CommunicationsException;
import org.jivesoftware.openfire.sip.tester.Log;
import javax.sip.message.Request;
import javax.sip.message.Response;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import java.util.Timer;
import java.util.ArrayList;
import java.util.TimerTask;
import java.text.ParseException;
/**
* Title: SIP Register Tester
* Description:JAIN-SIP Test application
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
class RegisterProcessing {
private SipManager sipManCallback = null;
private Request registerRequest = null;
private boolean isRegistered = false;
private boolean isUnregistering = false;
private Timer reRegisterTimer = null;
private int keepAlivePort = 0;
private Timer keepAliveTimer = null;
RegisterProcessing(SipManager sipManCallback) {
this.sipManCallback = sipManCallback;
}
void setSipManagerCallBack(SipManager sipManCallback) {
this.sipManCallback = sipManCallback;
}
void processOK(ClientTransaction clientTransatcion, Response response) {
isRegistered = true;
FromHeader fromHeader = ((FromHeader) response
.getHeader(FromHeader.NAME));
Address address = fromHeader.getAddress();
int expires = 0;
if (!isUnregistering) {
ContactHeader contactHeader = (ContactHeader) response
.getHeader(ContactHeader.NAME);
// TODO check if the registrar created the contact address
if (contactHeader != null) {
expires = contactHeader.getExpires();
} else {
ExpiresHeader expiresHeader = response.getExpires();
if (expiresHeader != null) {
expires = expiresHeader.getExpires();
}
}
}
// expires may be null
// fix by Luca Bincoletto <Luca.Bincoletto@tilab.com>
if (expires == 0) {
isUnregistering = false;
sipManCallback.fireUnregistered(address.toString());
} else {
if (reRegisterTimer != null)
reRegisterTimer.cancel();
if (keepAliveTimer != null)
keepAliveTimer.cancel();
reRegisterTimer = new Timer();
keepAliveTimer = new Timer();
// if (expires > 0 && expires < 60) {
// [issue 2] Schedule re registrations
// bug reported by LynlvL@netscape.com
// use the value returned by the server to reschedule
// registration
SipURI uri = (SipURI) address.getURI();
scheduleReRegistration(uri.getHost(), uri.getPort(), uri
.getTransportParam(), expires);
// }
/*
* else{ SipURI uri = (SipURI) address.getURI();
* scheduleReRegistration(uri.getHost(), uri.getPort(),
* uri.getTransportParam(), expires); }
*/
sipManCallback.fireRegistered(address.toString());
}
}
void processTimeout(Transaction transatcion, Request request) {
isRegistered = true;
FromHeader fromHeader = ((FromHeader) request
.getHeader(FromHeader.NAME));
Address address = fromHeader.getAddress();
sipManCallback.fireUnregistered("Request timeouted for: "
+ address.toString());
}
void processNotImplemented(ClientTransaction transatcion, Response response) {
isRegistered = true;
FromHeader fromHeader = ((FromHeader) response
.getHeader(FromHeader.NAME));
Address address = fromHeader.getAddress();
sipManCallback.fireUnregistered("Server returned NOT_IMPLEMENTED. "
+ address.toString());
}
/**
* Attempts to re-ogenerate the corresponding request with the proper
* credentials and terminates the call if it fails.
*
* @param clientTransaction the corresponding transaction
* @param response the challenge
*/
void processAuthenticationChallenge(ClientTransaction clientTransaction,
Response response) {
try {
ClientTransaction retryTran = sipManCallback.sipSecurityManager
.handleChallenge(response, clientTransaction);
retryTran.sendRequest();
}
catch (SipSecurityException exc) {
// tell the others we couldn't register
sipManCallback.fireUnregistered(((FromHeader) clientTransaction
.getRequest().getHeader(FromHeader.NAME)).getAddress()
.toString());
sipManCallback.fireCommunicationsError(new CommunicationsException(
"Authorization failed!", exc));
}
catch (Exception exc) {
// tell the others we couldn't register
sipManCallback.fireUnregistered(((FromHeader) clientTransaction
.getRequest().getHeader(FromHeader.NAME)).getAddress()
.toString());
sipManCallback.fireCommunicationsError(new CommunicationsException(
"Failed to resend a request "
+ "after a security challenge!", exc));
}
}
synchronized void register(String registrarAddress, int registrarPort,
String registrarTransport, int expires)
throws CommunicationsException {
try {
isUnregistering = false;
// From
FromHeader fromHeader = sipManCallback.getFromHeader(true);
Address fromAddress = fromHeader.getAddress();
sipManCallback.fireRegistering(fromAddress.toString());
// Request URI
SipURI requestURI = null;
try {
requestURI = sipManCallback.addressFactory.createSipURI(null,
registrarAddress);
}
catch (ParseException ex) {
throw new CommunicationsException("Bad registrar address:"
+ registrarAddress, ex);
}
catch (NullPointerException ex) {
// Do not throw an exc, we should rather silently notify the
// user
// throw new CommunicationsException("A registrar address was
// not specified!", ex);
sipManCallback.fireUnregistered(fromAddress.getURI().toString()
+ " (registrar not specified)");
return;
}
requestURI.setPort(registrarPort);
try {
requestURI.setTransportParam(registrarTransport);
}
catch (ParseException ex) {
throw new CommunicationsException(registrarTransport
+ " is not a valid transport!", ex);
}
// Call ID Header
CallIdHeader callIdHeader = sipManCallback.sipProvider
.getNewCallId();
// CSeq Header
CSeqHeader cSeqHeader = null;
try {
cSeqHeader = sipManCallback.headerFactory.createCSeqHeader(1,
Request.REGISTER);
}
catch (ParseException ex) {
// Should never happen
Log.error("register", ex);
}
catch (InvalidArgumentException ex) {
// Should never happen
Log.error("register", ex);
}
// To Header
ToHeader toHeader = null;
try {
toHeader = sipManCallback.headerFactory.createToHeader(
fromAddress, null);
}
catch (ParseException ex) {
// throw was missing - reported by Eero Vaarnas
throw new CommunicationsException(
"Could not create a To header " + "for address:"
+ fromHeader.getAddress(), ex);
}
// User Agent Header
UserAgentHeader uaHeader = null;
ArrayList userAgentList = new ArrayList();
userAgentList.add(SIPConfig.getStackName());
try {
uaHeader = sipManCallback.headerFactory
.createUserAgentHeader(userAgentList);
}
catch (ParseException ex) {
// throw was missing - reported by Eero Vaarnas
throw new CommunicationsException(
"Could not create a To header " + "for address:"
+ fromHeader.getAddress(), ex);
}
// Via Headers
ArrayList viaHeaders = sipManCallback.getLocalViaHeaders();
// MaxForwardsHeader
MaxForwardsHeader maxForwardsHeader = sipManCallback
.getMaxForwardsHeader();
// Request
Request request = null;
try {
request = sipManCallback.messageFactory.createRequest(
requestURI, Request.REGISTER, callIdHeader, cSeqHeader,
fromHeader, toHeader, viaHeaders, maxForwardsHeader);
request.setHeader(uaHeader);
}
catch (ParseException ex) {
// throw was missing - reported by Eero Vaarnas
throw new CommunicationsException(
"Could not create the register request!", ex);
}
// Expires Header
ExpiresHeader expHeader = null;
for (int retry = 0; retry < 2; retry++) {
try {
expHeader = sipManCallback.headerFactory
.createExpiresHeader(expires);
}
catch (InvalidArgumentException ex) {
if (retry == 0) {
expires = 3600;
continue;
}
throw new CommunicationsException(
"Invalid registrations expiration parameter - "
+ expires, ex);
}
}
request.addHeader(expHeader);
// Contact Header should contain IP - bug report - Eero Vaarnas
ContactHeader contactHeader = sipManCallback
.getRegistrationContactHeader();
request.addHeader(contactHeader);
// Transaction
ClientTransaction regTrans = null;
try {
regTrans = sipManCallback.sipProvider
.getNewClientTransaction(request);
}
catch (TransactionUnavailableException ex) {
// throw was missing - reported by Eero Vaarnas
throw new CommunicationsException(
"Could not create a register transaction!\n"
+ "Check that the Registrar address is correct!");
}
try {
regTrans.sendRequest();
}
// we sometimes get a null pointer exception here so catch them all
catch (Exception ex) {
// throw was missing - reported by Eero Vaarnas
throw new CommunicationsException(
"Could not send out the register request!", ex);
}
this.registerRequest = request;
}
catch (Exception e) {
Log.error("register", e);
}
}
/**
* Synchronize because of timer tasks
*
* @throws CommunicationsException
*/
synchronized void unregister() throws CommunicationsException {
try {
Log.debug("UNREGISTER");
cancelPendingRegistrations();
isRegistered = false;
isUnregistering = true;
Request registerRequest = getRegisterRequest();
if (this.registerRequest == null) {
throw new CommunicationsException(
"Couldn't find the initial register request");
}
Request unregisterRequest = (Request) registerRequest.clone();
try {
unregisterRequest.getExpires().setExpires(0);
CSeqHeader cSeqHeader = (CSeqHeader) unregisterRequest
.getHeader(CSeqHeader.NAME);
// [issue 1] - increment registration cseq number
// reported by - Roberto Tealdi <roby.tea@tin.it>
cSeqHeader
.setSequenceNumber(cSeqHeader.getSequenceNumber() + 1);
}
catch (InvalidArgumentException ex) {
// Shouldn't happen
throw new CommunicationsException(
"Unable to set Expires Header", ex);
}
ClientTransaction unregisterTransaction = null;
try {
unregisterTransaction = sipManCallback.sipProvider
.getNewClientTransaction(unregisterRequest);
}
catch (TransactionUnavailableException ex) {
throw new CommunicationsException(
"Unable to create a unregister transaction", ex);
}
try {
sipManCallback
.fireUnregistering(sipManCallback.currentlyUsedURI);
unregisterTransaction.sendRequest();
}
catch (SipException ex) {
throw new CommunicationsException(
"Failed to send unregister request", ex);
}
}
catch (Exception e) {
Log.error("unregister", e);
}
}
public void cancelSchedules() {
if (reRegisterTimer != null)
reRegisterTimer.cancel();
if (keepAliveTimer != null)
keepAliveTimer.cancel();
reRegisterTimer = null;
keepAliveTimer = null;
}
/**
* @return
*/
boolean isRegistered() {
return isRegistered;
}
/**
* @return Returns the registerRequest.
*/
private Request getRegisterRequest() {
return registerRequest;
}
private class ReRegisterTask extends TimerTask {
String registrarAddress = null;
int registrarPort = -1;
String transport = null;
int expires = 0;
public ReRegisterTask(String registrarAddress, int registrarPort,
String registrarTransport, int expires) {
this.registrarAddress = registrarAddress;
this.registrarPort = registrarPort;
// don't do this.transport = transport ;)
// bug report and fix by Willem Romijn (romijn at lucent.com)
this.transport = registrarTransport;
this.expires = expires;
}
public void run() {
try {
if (isRegistered())
register(registrarAddress, registrarPort, transport,
expires);
}
catch (CommunicationsException ex) {
sipManCallback
.fireCommunicationsError(new CommunicationsException(
"Failed to reRegister", ex));
}
}
}
private void cancelPendingRegistrations() {
try {
if (reRegisterTimer != null)
reRegisterTimer.cancel();
if (keepAliveTimer != null)
keepAliveTimer.cancel();
reRegisterTimer = null;
keepAliveTimer = null;
// reRegisterTimer = new Timer();
// keepAliveTimer = new Timer();
}
catch (Exception e) {
Log.error("cancelPendingRegistrations", e);
}
}
private void scheduleReRegistration(String registrarAddress,
int registrarPort, String registrarTransport, int expires) {
ReRegisterTask reRegisterTask = new ReRegisterTask(
registrarAddress, registrarPort, registrarTransport,
expires);
// java.util.Timer thinks in miliseconds
// bug report and fix by Willem Romijn (romijn at lucent.com)
// We keep a margin of 10% when sending re-registrations (1000
// becomes 900)
expires = expires * 900;
reRegisterTimer.schedule(reRegisterTask, expires);
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
import java.util.EventObject;
/**
* Title: SIP Register Tester
* Description:JAIN-SIP Test application
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class RegistrationEvent extends EventObject {
public enum Type {
Normal, WrongPass, NotFound, Forbidden, WrongAuthUser
};
private Type type = Type.Normal;
public RegistrationEvent(String registrationAddress) {
super(registrationAddress);
}
public RegistrationEvent(String registrationAddress, Type type) {
super(registrationAddress);
this.type = type;
}
public String getReason() {
return (String) getSource();
}
public Type getType() {
return type;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
/**
* Title: SIPark
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class SIPConfig {
private static boolean askPassword = true;
private static String audioPort = "20002";
private static String authenticationRealm = "";
private static String authUserName = "";
private static int bindRetries = 3;
private static int defaultBufferLength = 200;
private static String defaultDomain = "";
private static String displayName = "";
private static String excessiveURIChar = "( )-";
private static boolean failCallInUserMismatch = false;
private static boolean firstLaunch = false;
private static String httpProxy = "";
private static String IPAddress = "";
private static String javaHome = "";
private static int keepAliveDelay = 30;
private static int localPort = 5060;
private static boolean loopAlerts = true;
private static String mediaSource = null;
private static String os = "windows";
private static String outboundProxy = "";
private static boolean preferIPv4Stack = true;
private static String preferredAudioCodec = "3";
private static String preferredNetworkAddress = "";
private static String preferredNetworkInterface = "";
private static String preferredVideoCodec = "29";
private static String publicAddress = "";
private static String registrarAddress = "";
private static int registrarPort = 5060;
private static String registrarTransport = "UDP";
private static int registrationExpiration = 2000;
private static String retransmissionFilter = "";
private static String routerPath = "com.jivesoftware.openfire.enterprise.sip.tester.stack.SipCommRouter";
private static String stackName = "SIPark";
private static String stackPath = "gov.nist";
private static String transport = "";
private static String userName = "";
private static String videoPort = "20006";
private static int waitUnregistration = 1000;
private static String stunServer = "";
private static String stunPort = "";
private static boolean useStun = false;
public static String getAudioPort() {
return SIPConfig.audioPort;
}
public static String getAuthenticationRealm() {
return SIPConfig.authenticationRealm;
}
public static String getAuthUserName() {
return SIPConfig.authUserName;
}
public static int getBindRetries() {
return SIPConfig.bindRetries;
}
public static int getDefaultBufferLength() {
return SIPConfig.defaultBufferLength;
}
public static String getDefaultDomain() {
return SIPConfig.defaultDomain;
}
public static String getDisplayName() {
return SIPConfig.displayName;
}
public static String getExcessiveURIChar() {
return SIPConfig.excessiveURIChar;
}
public static String getHttpProxy() {
return SIPConfig.httpProxy;
}
public static String getIPAddress() {
return SIPConfig.IPAddress;
}
public static String getJavaHome() {
return SIPConfig.javaHome;
}
public static int getKeepAliveDelay() {
return SIPConfig.keepAliveDelay;
}
public static int getLocalPort() {
return SIPConfig.localPort;
}
public static String getMediaSource() {
return SIPConfig.mediaSource;
}
public static String getOs() {
return SIPConfig.os;
}
public static String getOutboundProxy() {
return SIPConfig.outboundProxy;
}
public static String getPreferredAudioCodec() {
return SIPConfig.preferredAudioCodec;
}
public static String getPreferredNetworkAddress() {
return SIPConfig.preferredNetworkAddress;
}
public static String getPreferredNetworkInterface() {
return SIPConfig.preferredNetworkInterface;
}
public static String getPreferredVideoCodec() {
return SIPConfig.preferredVideoCodec;
}
public static String getPublicAddress() {
return SIPConfig.publicAddress;
}
public static String getRegistrarAddress() {
return SIPConfig.registrarAddress;
}
public static int getRegistrarPort() {
return SIPConfig.registrarPort;
}
public static String getRegistrarTransport() {
return SIPConfig.registrarTransport;
}
public static int getRegistrationExpiration() {
return SIPConfig.registrationExpiration;
}
public static String getRetransmissionFilter() {
return SIPConfig.retransmissionFilter;
}
public static String getRouterPath() {
return SIPConfig.routerPath;
}
public static String getStackName() {
return SIPConfig.stackName;
}
public static String getStackPath() {
return SIPConfig.stackPath;
}
public static String getTransport() {
return SIPConfig.transport;
}
public static String getUserName() {
return SIPConfig.userName;
}
public static String getVideoPort() {
return SIPConfig.videoPort;
}
public static int getWaitUnregistration() {
return SIPConfig.waitUnregistration;
}
public static boolean isAskPassword() {
return SIPConfig.askPassword;
}
public static boolean isFailCallInUserMismatch() {
return SIPConfig.failCallInUserMismatch;
}
public static boolean isFirstLaunch() {
return SIPConfig.firstLaunch;
}
public static boolean isLoopAlerts() {
return SIPConfig.loopAlerts;
}
public static boolean isPreferIPv4Stack() {
return SIPConfig.preferIPv4Stack;
}
protected static void setAskPassword(boolean askPassword) {
SIPConfig.askPassword = askPassword;
}
protected static void setAudioPort(String audioPort) {
SIPConfig.audioPort = audioPort;
}
protected static void setAuthenticationRealm(String authenticationRealm) {
SIPConfig.authenticationRealm = authenticationRealm;
}
protected static void setAuthUserName(String authUserName) {
SIPConfig.authUserName = authUserName;
}
protected static void setBindRetries(int bindRetries) {
SIPConfig.bindRetries = bindRetries;
}
protected static void setDefaultBufferLength(int defaultBufferLength) {
SIPConfig.defaultBufferLength = defaultBufferLength;
}
protected static void setDefaultDomain(String defaultDomain) {
SIPConfig.defaultDomain = defaultDomain;
}
protected static void setDisplayName(String displayName) {
SIPConfig.displayName = displayName;
}
protected static void setExcessiveURIChar(String excessiveURIChar) {
SIPConfig.excessiveURIChar = excessiveURIChar;
}
protected static void setFailCallInUserMismatch(
boolean failCallInUserMismatch) {
SIPConfig.failCallInUserMismatch = failCallInUserMismatch;
}
protected static void setFirstLaunch(boolean firstLaunch) {
SIPConfig.firstLaunch = firstLaunch;
}
protected static void setHttpProxy(String httpProxy) {
SIPConfig.httpProxy = httpProxy;
}
protected static void setIPAddress(String address) {
SIPConfig.IPAddress = address;
}
protected static void setJavaHome(String javaHome) {
SIPConfig.javaHome = javaHome;
}
protected static void setKeepAliveDelay(int keepAliveDelay) {
SIPConfig.keepAliveDelay = keepAliveDelay;
}
protected static void setLocalPort(int localPort) {
SIPConfig.localPort = localPort;
}
protected static void setLoopAlerts(boolean loopAlerts) {
SIPConfig.loopAlerts = loopAlerts;
}
protected static void setMediaSource(String mediaSource) {
SIPConfig.mediaSource = mediaSource;
}
protected static void setOs(String os) {
SIPConfig.os = os;
}
protected static void setOutboundProxy(String outboundProxy) {
SIPConfig.outboundProxy = outboundProxy;
}
protected static void setPreferIPv4Stack(boolean preferIPv4Stack) {
SIPConfig.preferIPv4Stack = preferIPv4Stack;
}
protected static void setPreferredAudioCodec(String preferredAudioCodec) {
SIPConfig.preferredAudioCodec = preferredAudioCodec;
}
public static void setPreferredNetworkAddress(
String preferredNetworkAddress) {
SIPConfig.preferredNetworkAddress = preferredNetworkAddress;
}
protected static void setPreferredNetworkInterface(
String preferredNetworkInterface) {
SIPConfig.preferredNetworkInterface = preferredNetworkInterface;
}
protected static void setPreferredVideoCodec(String preferredVideoCodec) {
SIPConfig.preferredVideoCodec = preferredVideoCodec;
}
protected static void setPublicAddress(String publicAddress) {
SIPConfig.publicAddress = publicAddress;
}
protected static void setRegistrarAddress(String registrarAddress) {
SIPConfig.registrarAddress = registrarAddress;
}
protected static void setRegistrarPort(int registrarPort) {
SIPConfig.registrarPort = registrarPort;
}
protected static void setRegistrarTransport(String registrarTransport) {
SIPConfig.registrarTransport = registrarTransport;
}
protected static void setRegistrationExpiration(int registrationExpiration) {
SIPConfig.registrationExpiration = registrationExpiration;
}
protected static void setRetransmissionFilter(String retransmissionFilter) {
SIPConfig.retransmissionFilter = retransmissionFilter;
}
protected static void setRouterPath(String routerPath) {
SIPConfig.routerPath = routerPath;
}
public static void setServer(String server) {
SIPConfig.defaultDomain = server;
SIPConfig.authenticationRealm = server;
SIPConfig.registrarAddress = server;
SIPConfig.outboundProxy = server + ":" + SIPConfig.registrarPort + "/" + SIPConfig.registrarTransport;
SIPConfig.setSystemProperties();
}
protected static void setStackName(String stackName) {
SIPConfig.stackName = stackName;
}
protected static void setStackPath(String stackPath) {
SIPConfig.stackPath = stackPath;
}
public static void setSystemProperties() {
// javax.sip System Properties
System.setProperty("javax.sip.IP_ADDRESS", SIPConfig.IPAddress);
System.setProperty("javax.sip.STACK_NAME", SIPConfig.stackName);
System.setProperty("javax.sip.ROUTER_PATH", SIPConfig.routerPath);
System.setProperty("javax.sip.OUTBOUND_PROXY", SIPConfig.outboundProxy);
System.setProperty("javax.sip.RETRANSMISSON_FILTER", "");
System.setProperty("javax.sip.EXTENSION_METHODS", "");
System.setProperty("javax.sip.RETRANSMISSION_FILTER", "true");
System.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0");
}
protected static void setTransport(String transport) {
SIPConfig.transport = transport;
}
public static void setUserName(String userName) {
SIPConfig.userName = userName;
}
protected static void setVideoPort(String videoPort) {
SIPConfig.videoPort = videoPort;
}
protected static void setWaitUnregistration(int waitUnregistration) {
SIPConfig.waitUnregistration = waitUnregistration;
}
public static String getStunPort() {
return SIPConfig.stunPort;
}
public static void setStunPort(String stunPort) {
SIPConfig.stunPort = stunPort;
}
public static String getStunServer() {
return SIPConfig.stunServer;
}
public static void setStunServer(String stunServer) {
SIPConfig.stunServer = stunServer;
}
public static boolean isUseStun() {
return SIPConfig.useStun;
}
public static void setUseStun(boolean useStun) {
SIPConfig.useStun = useStun;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
import org.jivesoftware.openfire.sip.tester.comm.CommunicationsListener;
import org.jivesoftware.openfire.sip.tester.comm.CommunicationsException;
import org.jivesoftware.openfire.sip.tester.Log;
import org.jivesoftware.openfire.sip.sipaccount.SipAccount;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
/**
* Title: SIP Register Tester
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class SIPTest implements CommunicationsListener {
private SipAccount sipAccount;
private InetAddress localAddress;
private Result result = null;
private SipManager sipManager = null;
private List<TestListener> listeners = new ArrayList<TestListener>();
public enum Result {
Successfully, WrongUser, WrongPass, NetworkError, Trying, Timeout, Forbidden, WrongAuthUser
}
;
public SIPTest(InetAddress localAddress, SipAccount sipAccount) {
this.sipAccount = sipAccount;
this.localAddress = localAddress;
sipManager = new SipManager(localAddress);
}
public Result getResult() {
return result;
}
private void setResult(Result result) {
if (!result.equals(this.result)) fireResultChanged(this.result, result);
this.result = result;
}
public void test(int timeout) {
test(timeout, 1);
}
public void test(int timeout, int tries) {
for (int i = 0; i < tries && (getResult() == null || Result.Timeout.equals(getResult())); i++) {
if (sipManager.isStarted()) try {
sipManager.stop();
} catch (CommunicationsException e) {
e.printStackTrace();
}
setResult(Result.Trying);
SIPConfig.setRegistrarAddress(sipAccount.getServer());
SIPConfig.setAuthenticationRealm(sipAccount.getServer());
SIPConfig.setDefaultDomain(sipAccount.getServer());
try {
sipManager.start();
sipManager.addCommunicationsListener(this);
try {
sipManager.startRegisterProcess(sipAccount.getSipUsername(), sipAccount.getAuthUsername(), sipAccount.getPassword());
} catch (CommunicationsException e) {
setResult(Result.NetworkError);
Log.error(e);
}
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
Log.error(e);
}
if (getResult().equals(Result.Trying)) setResult(Result.Timeout);
} catch (CommunicationsException e) {
setResult(Result.NetworkError);
Log.error(e);
} finally {
try {
sipManager.stop();
} catch (CommunicationsException e) {
Log.error(e);
}
}
}
}
public void fireResultChanged(Result old, Result current) {
for (TestListener listener : listeners)
listener.resultChanged(old, current);
}
public void addListener(TestListener listener) {
listeners.add(listener);
}
public void removeListener(TestListener listener) {
listeners.remove(listener);
}
public void registered(RegistrationEvent evt) {
setResult(Result.Successfully);
try {
sipManager.unregister();
} catch (CommunicationsException e) {
Log.error(e);
}
}
public void registering(RegistrationEvent evt) {
}
public void registrationFailed(RegistrationEvent evt) {
if (evt.getType().equals(RegistrationEvent.Type.NotFound))
setResult(Result.WrongUser);
else if (evt.getType().equals(RegistrationEvent.Type.WrongPass))
setResult(Result.WrongPass);
else if (evt.getType().equals(RegistrationEvent.Type.Forbidden))
setResult(Result.Forbidden);
else if (evt.getType().equals(RegistrationEvent.Type.WrongAuthUser))
setResult(Result.WrongAuthUser);
}
public void unregistering(RegistrationEvent evt) {
}
public void unregistered(RegistrationEvent evt) {
try {
sipManager.stop();
Log.debug("Stopped");
} catch (CommunicationsException e) {
Log.error(e);
}
}
public static void main(String args[]) {
try {
InetAddress localAddress = InetAddress.getLocalHost();
SipAccount sipAccount = new SipAccount("", "", "", "", "", "", "", false);
SIPTest sipTest = new SIPTest(localAddress, sipAccount);
sipTest.test(3000, 2);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
import org.jivesoftware.openfire.sip.tester.Log;
import java.util.StringTokenizer;
/**
* Routing algorithms return a list of hops to which the request is routed.
*
* @author M. Ranganathan <mranga@nist.gov> <br/> <a href=" {@docRoot}
* /uncopyright.html">This code is in the public domain.</a> IPv6
* Support added by Emil Ivov (emil_ivov (at) yahoo (dot) com)<br/>
* Network Research Team (http://www-r2.u-strasbg.fr))<br/> Louis
* Pasteur University - Strasbourg - France<br/>
* @version JAIN-SIP-1.1
*/
public class SipCommHop implements javax.sip.address.Hop {
protected String host;
protected int port;
protected String transport;
protected boolean explicitRoute; // this is generated from a ROUTE
protected boolean defaultRoute; // This is generated from the proxy addr
protected boolean uriRoute; // This is extracted from the requestURI.
/**
* Debugging println.
*/
public String toString() {
return host + ":" + port + "/" + transport;
}
/**
* Create new hop given host, port and transport.
*
* @param hostName hostname
* @param portNumber port
* @param trans transport
*/
public SipCommHop(String hostName, int portNumber, String trans) {
host = hostName;
port = portNumber;
transport = trans;
}
/**
* Creates new Hop
*
* @param hop is a hop string in the form of host:port/Transport
* @throws IllegalArgumentException exception if string is not properly formatted or null.
*/
public SipCommHop(String hop) throws IllegalArgumentException {
if (hop == null) {
Log.debug("SipCommHop", "Null arg: " + hop);
throw new IllegalArgumentException("Null arg!");
}
StringTokenizer stringTokenizer = new StringTokenizer(hop + "/");
String hostPort = stringTokenizer.nextToken("/").trim();
transport = stringTokenizer.nextToken().trim();
if (transport == null) {
transport = "UDP";
} else if (transport == "") {
transport = "UDP";
}
if (transport.compareToIgnoreCase("UDP") != 0
&& transport.compareToIgnoreCase("TCP") != 0) {
throw new IllegalArgumentException(hop);
}
String portString = null;
// IPv6 hostport
if (hostPort.charAt(0) == '[') {
int rightSqBrackIndex = hostPort.indexOf(']');
if (rightSqBrackIndex == -1) {
throw new IllegalArgumentException("Bad IPv6 reference spec");
}
host = hostPort.substring(0, rightSqBrackIndex + 1);
int portColon = hostPort.indexOf(':', rightSqBrackIndex);
if (portColon != -1) {
try {
portString = hostPort.substring(portColon + 1).trim();
}
catch (IndexOutOfBoundsException exc) {
// Do nothing - handled later
}
}
}
// IPv6 address and no port
else if (hostPort.indexOf(':') != hostPort.lastIndexOf(":")) {
host = '[' + hostPort + ']';
} else { // no square brackets and a single or zero colons => IPv4
// hostPort
int portColon = hostPort.indexOf(':');
if (portColon == -1) {
host = hostPort;
} else {
host = hostPort.substring(0, portColon).trim();
try {
portString = hostPort.substring(portColon + 1).trim();
}
catch (IndexOutOfBoundsException exc) {
// Do nothing - handled later
}
}
}
if (host == null || host.equals("")) {
throw new IllegalArgumentException("no host!");
}
if (portString == null || portString.equals("")) {
port = 5060;
} else {
try {
port = Integer.parseInt(portString);
}
catch (NumberFormatException ex) {
throw new IllegalArgumentException("Bad port spec");
}
}
}
/**
* Retruns the host string.
*
* @return host String
* @uml.property name="host"
*/
public String getHost() {
return host;
}
/**
* Returns the port.
*
* @return port integer.
* @uml.property name="port"
*/
public int getPort() {
return port;
}
/**
* returns the transport string.
*
* @uml.property name="transport"
*/
public String getTransport() {
return transport;
}
/**
* Return true if this is an explicit route (ie. extrcted from a ROUTE
* Header)
*
* @uml.property name="explicitRoute"
*/
public boolean isExplicitRoute() {
return explicitRoute;
}
/**
* Return true if this is a default route (ie. next hop proxy address)
*
* @uml.property name="defaultRoute"
*/
public boolean isDefaultRoute() {
return defaultRoute;
}
/**
* Return true if this is uriRoute
*/
public boolean isURIRoute() {
return uriRoute;
}
/**
* Set the URIRoute flag.
*/
public void setURIRouteFlag() {
uriRoute = true;
}
/**
* Set the defaultRouteFlag.
*/
public void setDefaultRouteFlag() {
defaultRoute = true;
}
/**
* Set the explicitRoute flag.
*/
public void setExplicitRouteFlag() {
explicitRoute = true;
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
import org.jivesoftware.openfire.sip.tester.Log;
import javax.sip.SipStack;
import javax.sip.address.Hop;
import javax.sip.address.Router;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.RouteHeader;
import javax.sip.message.Request;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* <p/>
* Title: SIP COMMUNICATOR
* </p>
* <p/>
* Description:JAIN-SIP Audio/Video phone application
* </p>
* <p/>
* Copyright: Copyright (c) 2003
* </p>
* <p/>
* Organisation: LSIIT laboratory (http://lsiit.u-strasbg.fr)
* </p>
* <p/>
* Network Research Team (http://www-r2.u-strasbg.fr))
* </p>
* <p/>
* Louis Pasteur University - Strasbourg - France
* </p>
*
* @author Emil Ivov (http://www.emcho.com)
* @version 1.1
*/
public class SipCommRouter implements Router {
protected SipStack myStack;
protected SipCommHop outboundProxy = null;
protected Router stackRouter = null;
public SipCommRouter(SipStack sipStack, String outboundProxy) {
outboundProxy = SIPConfig.getOutboundProxy();
this.myStack = sipStack;
if (outboundProxy != null && outboundProxy.length() > 0) {
this.outboundProxy = new SipCommHop(outboundProxy);
}
}
/**
* Return the default address to forward the request to. The list is
* organized in the following priority.
* <p/>
* If the outboung proxy has been specified, then it is used to construct
* the first element of the list.
* <p/>
* If the requestURI refers directly to a host, the host and port
* information are extracted from it and made the next hop on the list.
*
* @param sipRequest is the sip request to route.
*/
public ListIterator getNextHops(Request sipRequest) {
URI requestURI = sipRequest.getRequestURI();
if (requestURI == null) {
throw new IllegalArgumentException("Bad message: Null requestURI");
}
LinkedList hops = new LinkedList();
if (outboundProxy != null) {
hops.add(outboundProxy);
}
ListIterator routes = sipRequest.getHeaders(RouteHeader.NAME);
if (routes != null && routes.hasNext()) {
while (routes.hasNext()) {
RouteHeader route = (RouteHeader)routes.next();
SipURI uri = (SipURI)route.getAddress().getURI();
int port = uri.getPort();
port = (port == -1) ? 5060 : port;
String host = uri.getHost();
Log.debug("getNextHops", host);
String transport = uri.getTransportParam();
if (transport == null) {
transport = "udp";
}
Hop hop = new SipCommHop(host + ':' + port + '/' + transport);
hops.add(hop);
}
}
else if (requestURI instanceof SipURI
&& ((SipURI)requestURI).getMAddrParam() != null) {
SipURI sipURI = ((SipURI)requestURI);
String maddr = sipURI.getMAddrParam();
String transport = sipURI.getTransportParam();
if (transport == null) {
transport = "udp";
}
int port = 5060;
Hop hop = new SipCommHop(maddr, port, transport);
hops.add(hop);
}
else if (requestURI instanceof SipURI) {
SipURI sipURI = ((SipURI)requestURI);
int port = sipURI.getPort();
if (port == -1) {
port = 5060;
}
String host = sipURI.getHost();
String transport = sipURI.getTransportParam();
if (transport == null) {
transport = "UDP";
}
Hop hop = new SipCommHop(host + ":" + port + "/" + transport);
hops.add(hop);
}
else {
throw new IllegalArgumentException("Malformed requestURI");
}
return (hops.size() == 0) ? null : hops.listIterator();
}
/**
* @return Returns the outboundProxy.
*/
public Hop getOutboundProxy() {
return this.outboundProxy;
}
protected void setOutboundProxy(String proxy) {
if (SIPConfig.getOutboundProxy() != null
&& SIPConfig.getOutboundProxy().length() > 0) {
this.outboundProxy = new SipCommHop(proxy);
}
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
import org.jivesoftware.openfire.sip.tester.comm.CommunicationsException;
import org.jivesoftware.openfire.sip.tester.comm.CommunicationsListener;
import org.jivesoftware.openfire.sip.tester.Log;
import org.jivesoftware.openfire.sip.tester.security.UserCredentials;
import org.jivesoftware.openfire.sip.tester.security.SipSecurityManager;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TooManyListenersException;
/**
* Title: SIP Register Tester
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public class SipManager implements SipListener {
protected static final int RETRY_OBJECT_DELETES = 10;
protected static final long RETRY_OBJECT_DELETES_AFTER = 500;
protected static final String DEFAULT_TRANSPORT = "udp";
protected InetAddress localAddress = null;
public SipFactory sipFactory;
public AddressFactory addressFactory;
public HeaderFactory headerFactory;
public MessageFactory messageFactory;
SipStack sipStack;
public boolean isBusy = true;
ListeningPoint listeningPoint;
public SipProvider sipProvider;
private InetSocketAddress publicIpAddress = null;
protected String sipStackPath = "gov.nist";
protected String currentlyUsedURI = null;
protected String displayName = null;
protected String transport = null;
protected String registrarAddress = null;
protected int localPort = -1;
protected int registrarPort = -1;
protected int registrationsExpiration = -1;
protected String registrarTransport = null;
private int registerRetries = 0;
protected String stackAddress = null;
protected String stackName = "JiveSIP";
protected FromHeader fromHeader = null;
protected ContactHeader contactHeader = null;
protected ArrayList<ViaHeader> viaHeaders = null;
protected static final int MAX_FORWARDS = 70;
protected MaxForwardsHeader maxForwardsHeader = null;
protected long registrationTransaction = -1;
protected ArrayList<CommunicationsListener> listeners = new ArrayList<CommunicationsListener>();
protected boolean isStarted = false;
private RegisterProcessing registerProcessing = null;
public SipSecurityManager sipSecurityManager = null;
/**
* Constructor. It only creates a SipManager instance without initializing
* the stack itself.
*
* @param localAddress localAddress
*/
public SipManager(InetAddress localAddress) {
this.localAddress = localAddress;
registerProcessing = new RegisterProcessing(this);
sipSecurityManager = new SipSecurityManager();
registerRetries = 0;
}
/**
* Creates and initializes JAIN SIP objects (factories, stack, listening
* point and provider). Once this method is called the application is ready
* to handle (incoming and outgoing) sip messages.
*
* @throws CommunicationsException if an axception should occur during the initialization
* process
*/
public void start() throws CommunicationsException {
initProperties();
SIPConfig.setSystemProperties();
this.sipFactory = SipFactory.getInstance();
sipFactory.setPathName(sipStackPath);
try {
addressFactory = sipFactory.createAddressFactory();
headerFactory = sipFactory.createHeaderFactory();
messageFactory = sipFactory.createMessageFactory();
}
catch (PeerUnavailableException ex) {
Log.error("start", ex);
throw new CommunicationsException(
"Could not create factories!", ex);
}
try {
sipStack = sipFactory.createSipStack(System.getProperties());
((SipCommRouter) sipStack.getRouter())
.setOutboundProxy(SIPConfig.getOutboundProxy());
}
catch (PeerUnavailableException ex) {
Log.error("start", ex);
throw new CommunicationsException(
"Impossvel conectar!\n"
+ "O proxy pode no est acessvel.\nVerifique sua conexo."
+ "(Syntax:<proxy_address:port/transport>)", ex);
}
try {
boolean successfullyBound = false;
while (!successfullyBound) {
try {
publicIpAddress = new InetSocketAddress(localAddress, localPort);
listeningPoint = sipStack.createListeningPoint(
localPort, transport);
}
catch (InvalidArgumentException ex) {
// choose another port between 1024 and 65000
localPort = (int) ((65000 - 1024) * Math.random()) + 1024;
try {
Thread.sleep(1000);
}
catch (Exception e) {
// Do Nothing
}
continue;
}
successfullyBound = true;
}
}
catch (TransportNotSupportedException ex) {
throw new CommunicationsException(
"Transport "
+ transport
+ " is not suppported by the stack!\n Try specifying another"
+ " transport in Mais property files.\n", ex);
}
try {
sipProvider = sipStack.createSipProvider(listeningPoint);
}
catch (ObjectInUseException ex) {
Log.error("start", ex);
throw new CommunicationsException(
"Could not create factories!\n", ex);
}
try {
sipProvider.addSipListener(this);
}
catch (TooManyListenersException exc) {
throw new CommunicationsException(
"Could not register SipManager as a sip listener!", exc);
}
sipSecurityManager.setHeaderFactory(headerFactory);
sipSecurityManager.setTransactionCreator(sipProvider);
sipSecurityManager.setSipManCallback(this);
// Make sure prebuilt headers are nulled so that they get reinited
// if this is a restart
contactHeader = null;
fromHeader = null;
viaHeaders = null;
maxForwardsHeader = null;
isStarted = true;
}
/**
* Unregisters listening points, deletes sip providers, and generally
* prepares the stack for a re-start(). This method is meant to be used when
* properties are changed and should be reread by the stack.
*
* @throws CommunicationsException CommunicationsException
*/
synchronized public void stop() throws CommunicationsException {
if (sipStack == null)
return;
// Delete SipProvider
int tries;
for (tries = 0; tries < SipManager.RETRY_OBJECT_DELETES; tries++) {
try {
sipStack.deleteSipProvider(sipProvider);
}
catch (ObjectInUseException ex) {
SipManager.sleep(SipManager.RETRY_OBJECT_DELETES_AFTER);
continue;
}
break;
}
if (sipStack == null)
return;
if (tries >= SipManager.RETRY_OBJECT_DELETES)
throw new CommunicationsException(
"Failed to delete the sipProvider!");
if (sipStack == null)
return;
// Delete RI ListeningPoint
for (tries = 0; tries < SipManager.RETRY_OBJECT_DELETES; tries++) {
try {
sipStack.deleteListeningPoint(listeningPoint);
}
catch (ObjectInUseException ex) {
// Log.debug("Retrying delete of riListeningPoint!");
SipManager.sleep(SipManager.RETRY_OBJECT_DELETES_AFTER);
continue;
}
break;
}
if (sipStack != null) {
for (Iterator it = sipStack.getSipProviders(); it.hasNext();) {
SipProvider element = (SipProvider) it.next();
try {
sipStack.deleteSipProvider(element);
}
catch (Exception e) {
// Do nothing
}
}
}
if (tries >= SipManager.RETRY_OBJECT_DELETES)
throw new CommunicationsException(
"Failed to delete a listeningPoint!");
listeningPoint = null;
addressFactory = null;
messageFactory = null;
headerFactory = null;
sipStack = null;
registrarAddress = null;
viaHeaders = null;
contactHeader = null;
fromHeader = null;
}
/**
* Waits during _no_less_ than sleepFor milliseconds. Had to implement it on
* top of Thread.sleep() to guarantee minimum sleep time.
*
* @param sleepFor the number of miliseconds to wait
*/
protected static void sleep(long sleepFor) {
long startTime = System.currentTimeMillis();
long haveBeenSleeping = 0;
while (haveBeenSleeping < sleepFor) {
try {
Thread.sleep(sleepFor - haveBeenSleeping);
}
catch (InterruptedException ex) {
// we-ll have to wait again!
}
haveBeenSleeping = (System.currentTimeMillis() - startTime);
}
}
/**
* @param uri the currentlyUsedURI to set.
*/
public void setCurrentlyUsedURI(String uri) {
this.currentlyUsedURI = uri;
}
public void register(String publicAddress) {
try {
if (publicAddress == null || publicAddress.trim().length() == 0) {
Log.debug("PUBLIC NOT FOUND!");
return; // maybe throw an exception?
}
if (!publicAddress.trim().toLowerCase().startsWith("sip:")) {
publicAddress = "sip:" + publicAddress;
}
this.currentlyUsedURI = publicAddress;
registerProcessing.register(registrarAddress, registrarPort,
registrarTransport, registrationsExpiration);
}
catch (Exception e) {
Log.error("register", e);
}
}
public void startRegisterProcess(String userName, String authUserName,
String password) throws CommunicationsException {
try {
checkIfStarted();
// Obtain initial credentials
String realm = SIPConfig.getAuthenticationRealm();
realm = realm == null ? "" : realm;
// put the returned user name in the properties file
// so that it appears as a default one next time user is prompted
// for pass
SIPConfig.setUserName(userName);
SIPConfig.setAuthUserName(authUserName);
UserCredentials initialCredentials = new UserCredentials();
initialCredentials.setUserName(userName);
initialCredentials.setAuthUserName(authUserName);
initialCredentials.setPassword(password.toCharArray());
register(initialCredentials.getUserName() + "@" + realm);
// at this point a simple register request has been sent and the
// global
// from header in SipManager has been set to a valid value by the
// RegisterProcesing
// class. Use it to extract the valid user name that needs to be
// cached by
// the security manager together with the user provided password.
initialCredentials.setUserName(((SipURI) getFromHeader()
.getAddress().getURI()).getUser());
// JOptionPane.showMessageDialog(null,( (SipURI)
// getFromHeader().getAddress().getURI()).getUser());
cacheCredentials(realm, initialCredentials);
}
catch (Exception ee) {
Log.error("startRegisterProcess", ee);
}
}
/**
* Causes the PresenceAgent object to notify all subscribers of our brand
* new offline status and the RegisterProcessing object to send a
* registration request with a 0 "expires" interval to the registrar defined
* in net.java.mais.sip.REGISTRAR_ADDRESS.
*
* @throws CommunicationsException if an exception is thrown by the underlying stack. The
* exception that caused this CommunicationsException may be
* extracted with CommunicationsException.getCause()
*/
public void unregister() throws CommunicationsException {
try {
checkIfStarted();
registerProcessing.unregister();
fireUnregistered(registrarAddress == null ? "" : registrarAddress);
}
catch (Exception e) {
Log.error("unregister", e);
}
}
private void registrationFailed(RegistrationEvent.Type type) {
try {
fireRegistrationFailed(registrarAddress == null ? "" : registrarAddress, type);
}
catch (Exception e) {
Log.error("unregister", e);
}
}
/**
* Queries the RegisterProcessing object whether the application is
* registered with a registrar.
*
* @return true if the application is registered with a registrar.
*/
public boolean isRegistered() {
return (registerProcessing != null && registerProcessing.isRegistered());
}
/**
* Determines whether the SipManager was started.
*
* @return true if the SipManager was started.
*/
public boolean isStarted() {
return isStarted;
}
/**
* Sends a NOT_IMPLEMENTED response through the specified transaction.
*
* @param serverTransaction the transaction to send the response through.
* @param request the request that is being answered.
*/
void sendNotImplemented(ServerTransaction serverTransaction, Request request) {
Response notImplemented;
try {
notImplemented = messageFactory.createResponse(
Response.NOT_IMPLEMENTED, request);
attachToTag(notImplemented, serverTransaction.getDialog());
}
catch (ParseException ex) {
fireCommunicationsError(new CommunicationsException(
"Failed to create a NOT_IMPLEMENTED response to a "
+ request.getMethod() + " request!", ex));
return;
}
try {
serverTransaction.sendResponse(notImplemented);
}
catch (SipException ex) {
fireCommunicationsError(new CommunicationsException(
"Failed to create a NOT_IMPLEMENTED response to a "
+ request.getMethod() + " request!", ex));
}
}
public void fireCommunicationsError(Throwable throwable) {
}
public FromHeader getFromHeader() throws CommunicationsException {
return this.getFromHeader(false);
}
public FromHeader getFromHeader(boolean isNew)
throws CommunicationsException {
if (fromHeader != null && !isNew) {
return fromHeader;
}
try {
SipURI fromURI = (SipURI) addressFactory
.createURI(currentlyUsedURI);
fromURI.setTransportParam(listeningPoint.getTransport());
fromURI.setPort(listeningPoint.getPort());
Address fromAddress = addressFactory.createAddress(fromURI);
if (displayName != null && displayName.trim().length() > 0) {
fromAddress.setDisplayName(displayName);
} else {
fromAddress
.setDisplayName(UserCredentials.getUserDisplay());// UserCredentials.getUser());
// JOptionPane.showMessageDialog(null,currentlyUsedURI);
}
fromHeader = headerFactory.createFromHeader(fromAddress,
Integer.toString(hashCode()));
}
catch (ParseException ex) {
throw new CommunicationsException(
"A ParseException occurred while creating From Header!",
ex);
}
return fromHeader;
}
/**
* Same as calling getContactHeader(true)
*
* @return the result of getContactHeader(true)
* @throws CommunicationsException if an exception is thrown while calling
* getContactHeader(false)
*/
public ContactHeader getContactHeader() throws CommunicationsException {
return getContactHeader(true);
}
/**
* Same as calling getContactHeader(true).
*
* @return the result of calling getContactHeader(true).
* @throws CommunicationsException if an exception occurs while executing
* getContactHeader(true).
*/
ContactHeader getRegistrationContactHeader() throws CommunicationsException {
return getContactHeader(true);
}
/**
* Initialises SipManager's contactHeader field in accordance with
* javax.sip.IP_ADDRESS net.java.mais.sip.DISPLAY_NAME
* net.java.mais.sip.TRANSPORT net.java.mais.sip.PREFERRED_LOCAL_PORT and
* returns a reference to it.
*
* @param useLocalHostAddress specifies whether the SipURI in the contact header should
* contain the value of javax.sip.IP_ADDRESS (true) or that of
* net.java.mais.sip.PUBLIC_ADDRESS (false).
* @return a reference to SipManager's contactHeader field.
* @throws CommunicationsException if a ParseException occurs while initially composing the
* FromHeader.
*/
public ContactHeader getContactHeader(boolean useLocalHostAddress)
throws CommunicationsException {
if (contactHeader != null) {
return contactHeader;
}
try {
SipURI contactURI;
if (useLocalHostAddress) {
contactURI = addressFactory.createSipURI(null,
UserCredentials.getUserDisplay()
+ "@"
+ publicIpAddress.getAddress()
.getHostAddress());
} else {
contactURI = (SipURI) addressFactory
.createURI(currentlyUsedURI);
}
contactURI.setPort(publicIpAddress.getPort());
Address contactAddress = addressFactory
.createAddress(contactURI);
if (displayName != null && displayName.trim().length() > 0) {
contactAddress.setDisplayName(displayName);
}
contactHeader = headerFactory
.createContactHeader(contactAddress);
}
catch (ParseException ex) {
throw new CommunicationsException(
"A ParseException occurred while creating From Header!",
ex);
}
return contactHeader;
}
/**
* Initializes (if null) and returns an ArrayList with a single ViaHeader
* containing localhost's address. This ArrayList may be used when sending
* requests.
*
* @return ViaHeader-s list to be used when sending requests.
* @throws CommunicationsException if a ParseException is to occur while initializing the array
* list.
*/
public ArrayList getLocalViaHeaders() throws CommunicationsException {
if (viaHeaders != null) {
return viaHeaders;
}
ListeningPoint lp = sipProvider.getListeningPoint();
viaHeaders = new ArrayList<ViaHeader>();
try {
ViaHeader viaHeader = headerFactory.createViaHeader(SIPConfig
.getIPAddress(), lp.getPort(), lp.getTransport(), null);
viaHeader.setParameter("rport", null);
viaHeaders.add(viaHeader);
return viaHeaders;
}
catch (ParseException ex) {
throw new CommunicationsException(
"A ParseException occurred while creating Via Headers!");
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"Unable to create a via header for port "
+ lp.getPort(), ex);
}
}
/**
* Initializes and returns SipManager's maxForwardsHeader field using the
* value specified by MAX_FORWARDS.
*
* @return an instance of a MaxForwardsHeader that can be used when sending
* requests
* @throws CommunicationsException if MAX_FORWARDS has an invalid value.
*/
public MaxForwardsHeader getMaxForwardsHeader()
throws CommunicationsException {
if (maxForwardsHeader != null) {
return maxForwardsHeader;
}
try {
maxForwardsHeader = headerFactory
.createMaxForwardsHeader(SipManager.MAX_FORWARDS);
return maxForwardsHeader;
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"A problem occurred while creating MaxForwardsHeader",
ex);
}
}
/**
* Returns the user used to create the From Header URI.
*
* @return the user used to create the From Header URI.
*/
public String getLocalUser() {
try {
return ((SipURI) getFromHeader().getAddress().getURI()).getUser();
}
catch (CommunicationsException ex) {
return "";
}
}
/**
* Generates a ToTag (the containingDialog's hashCode())and attaches it to
* response's ToHeader.
*
* @param response the response that is to get the ToTag.
* @param containingDialog the Dialog instance that is to extract a unique Tag value
* (containingDialog.hashCode())
*/
public void attachToTag(Response response, Dialog containingDialog) {
ToHeader to = (ToHeader) response.getHeader(ToHeader.NAME);
if (to == null) {
fireCommunicationsError(new CommunicationsException(
"No TO header found in, attaching a to tag is therefore impossible"));
}
try {
if (to.getTag() == null || to.getTag().trim().length() == 0) {
int toTag = containingDialog != null ? containingDialog
.hashCode() : (int) System.currentTimeMillis();
to.setTag(Integer.toString(toTag));
}
}
catch (ParseException ex) {
fireCommunicationsError(new CommunicationsException(
"Failed to attach a TO tag to an outgoing response"));
}
}
protected void initProperties() {
try {
stackAddress = getLocalHostAddress();
// Add the host address to the properties that will pass the stack
SIPConfig.setIPAddress(stackAddress);
SIPConfig.setSystemProperties();
// ensure IPv6 address compliance
if (stackAddress.indexOf(':') != stackAddress.lastIndexOf(':')
&& stackAddress.charAt(0) != '[') {
stackAddress = '[' + stackAddress.trim() + ']';
}
stackName = SIPConfig.getStackName();
if (stackName == null) {
stackName = "SIPark@" + Integer.toString(hashCode());
}
currentlyUsedURI = SIPConfig.getPublicAddress();
if (currentlyUsedURI == null) {
currentlyUsedURI = SIPConfig.getUserName() + "@" + stackAddress;
}
if (!currentlyUsedURI.trim().toLowerCase().startsWith("sip:")) {
currentlyUsedURI = "sip:" + currentlyUsedURI.trim();
}
registrarAddress = SIPConfig.getRegistrarAddress();
try {
registrarPort = SIPConfig.getRegistrarPort();
}
catch (NumberFormatException ex) {
registrarPort = 5060;
}
registrarTransport = SIPConfig.getRegistrarTransport();
if (registrarTransport == null) {
registrarTransport = SipManager.DEFAULT_TRANSPORT;
}
try {
registrationsExpiration = SIPConfig.getRegistrationExpiration();
}
catch (NumberFormatException ex) {
registrationsExpiration = 3600;
}
sipStackPath = SIPConfig.getStackPath();
if (sipStackPath == null) {
sipStackPath = "gov.nist";
}
transport = SIPConfig.getTransport();
if (transport.equals("")) {
transport = SipManager.DEFAULT_TRANSPORT;
}
try {
localPort = SIPConfig.getLocalPort();
}
catch (NumberFormatException exc) {
localPort = 5060;
}
displayName = SIPConfig.getDisplayName();
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Adds the specified credentials to the security manager's credentials
* cache so that they get tried next time they're needed.
*
* @param realm the realm these credentials should apply for.
* @param credentials a set of credentials (username and pass)
*/
public void cacheCredentials(String realm, UserCredentials credentials) {
sipSecurityManager.cacheCredentials(realm, credentials);
}
/**
* Adds a CommunicationsListener to SipManager.
*
* @param listener The CommunicationsListener to be added.
*/
public void addCommunicationsListener(CommunicationsListener listener) {
try {
listeners.add(listener);
}
catch (Exception e) {
Log.error("addCommunicationsListener", e);
}
}
// ------------ registerred
void fireRegistered(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
(listeners.get(i)).registered(evt);
}
} // call received
// ------------ registering
void fireRegistering(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
(listeners.get(i)).registering(evt);
}
} // call received
// ------------ unregistered
public void fireUnregistered(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
(listeners.get(i)).unregistered(evt);
}
}
void fireRegistrationFailed(String address, RegistrationEvent.Type type) {
RegistrationEvent evt = new RegistrationEvent(address, type);
for (int i = listeners.size() - 1; i >= 0; i--) {
(listeners.get(i)).registrationFailed(evt);
}
}
void fireUnregistering(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
(listeners.get(i)).unregistering(evt);
}
}
public void processRequest(RequestEvent requestEvent) {
}
// -------------------- PROCESS RESPONSE
public void processResponse(ResponseEvent responseReceivedEvent) {
Log.debug("RESPONSE [" + responseReceivedEvent.getResponse().getStatusCode() + "]");
ClientTransaction clientTransaction = responseReceivedEvent
.getClientTransaction();
if (clientTransaction == null) {
return;
}
Response response = responseReceivedEvent.getResponse();
String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
.getMethod();
// OK
if (response.getStatusCode() == Response.OK) {
// REGISTER
if (method.equals(Request.REGISTER)) {
registerProcessing.processOK(clientTransaction, response);
}
}
// NOT_FOUND
else if (response.getStatusCode() == Response.NOT_FOUND) {
if (method.equals(Request.REGISTER)) {
try {
unregister();
registrationFailed(RegistrationEvent.Type.NotFound);
}
catch (CommunicationsException e) {
Log.error("NOT FOUND", e);
}
Log.debug("REGISTER NOT FOUND");
}
}
// NOT_IMPLEMENTED
else if (response.getStatusCode() == Response.NOT_IMPLEMENTED) {
if (method.equals(Request.REGISTER)) {
// Fixed typo issues - Reported by pizarro
registerProcessing.processNotImplemented(clientTransaction,
response);
}
}
// REQUEST_TERMINATED
// 401 UNAUTHORIZED
else if (response.getStatusCode() == Response.UNAUTHORIZED
|| response.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
if (method.equals(Request.REGISTER)) {
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
if (cseq.getSequenceNumber() < 2)
registerProcessing.processAuthenticationChallenge(
clientTransaction, response);
else
registrationFailed(RegistrationEvent.Type.WrongPass);
}
}
// 403 Wrong Authorization user for this account
else if(response.getStatusCode() == Response.FORBIDDEN){
registrationFailed(RegistrationEvent.Type.Forbidden);
}
} // process response
public void processTimeout(TimeoutEvent timeoutEvent) {
}
String getLocalHostAddress() {
return localAddress.getHostAddress();
}
protected void checkIfStarted() throws CommunicationsException {
if (!isStarted) {
throw new CommunicationsException(
"The underlying SIP Stack had not been"
+ "properly initialised! Impossible to continue");
}
}
public static void main(String args[]) {
SIPConfig.setRegistrarAddress("apollo");
SIPConfig.setAuthenticationRealm("apollo");
SIPConfig.setDefaultDomain("apollo");
InetAddress address = null;
try {
address = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
SipManager sipManager = new SipManager(address);
try {
sipManager.start();
} catch (CommunicationsException e) {
e.printStackTrace();
}
try {
sipManager.startRegisterProcess("7512", "7512", "7512");
} catch (CommunicationsException e) {
e.printStackTrace();
}
try {
sipManager.unregister();
} catch (CommunicationsException e) {
e.printStackTrace();
}
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.sip.tester.stack;
/**
* Title: SIP Register Tester
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com)
*/
public interface TestListener {
public void resultChanged(SIPTest.Result old, SIPTest.Result current);
}
<%@ page import="org.jivesoftware.openfire.sip.sipaccount.SipAccount" %>
<%@ page import="org.jivesoftware.openfire.sip.sipaccount.SipAccountDAO" %>
<%@ page import="org.jivesoftware.util.JiveGlobals" %>
<%@ page import="org.jivesoftware.util.LocaleUtils" %>
<%@ page import="org.jivesoftware.util.Log" %>
<%@ page import="org.jivesoftware.util.ParamUtils" %>
<%@ page import="java.net.InetAddress" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page import="java.sql.SQLException" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%@ page import="org.jivesoftware.openfire.sip.tester.stack.SIPTest" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%
boolean save = request.getParameter("save") != null;
boolean test = request.getParameter("test") != null;
SIPTest.Result testResult = null;
String node = request.getParameter("node");
String username = ParamUtils.getParameter(request, "sipusername");
String authusername = ParamUtils.getParameter(request, "authusername");
String displayname = ParamUtils.getParameter(request, "displayname");
String password = ParamUtils.getParameter(request, "sippassword");
String server = ParamUtils.getParameter(request, "server");
boolean enabled = ParamUtils.getBooleanParameter(request, "enabled");
String voicemail = ParamUtils.getParameter(request, "voicemail");
String outboundproxy = ParamUtils.getParameter(request, "outboundproxy");
boolean promptCredentials = ParamUtils.getBooleanParameter(request,"promptCredentials",false);
// Handle a cancel
if (request.getParameter("cancel") != null) {
response.sendRedirect("sipark-user-summary.jsp?username=" + URLEncoder.encode(node, "UTF-8"));
return;
}
SipAccount sipAccount = null;
Map<String, String> errors = new HashMap<String, String>();
String errorMessage = null;
if (save || test) {
// Validate params
if (node == null || "".equals(node) || node.contains("@")) {
errors.put("node", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.xmpp-node", "sip");
} else if ((username == null || "".equals(username)) && !promptCredentials) {
errors.put("username", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.sip-username", "sip");
} else if ((authusername == null || "".equals(authusername)) && !promptCredentials) {
errors.put("authusername", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.authusername", "sip");
} else if (displayname == null || "".equals(displayname)) {
errors.put("displayname", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.displayname", "sip");
} else if ((password == null || "".equals(password)) && !promptCredentials) {
errors.put("password", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.password", "sip");
} else if (server == null || "".equals(server)) {
errors.put("server", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.server", "sip");
} else if (voicemail == null || "".equals(voicemail)) {
errors.put("voicemail", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.user.create.valid.voicemail", "sip");
} else if(outboundproxy == null){
outboundproxy = "";
}
if (errors.isEmpty()) {
sipAccount = new SipAccount(node);
sipAccount.setSipUsername(username);
sipAccount.setAuthUsername(authusername);
sipAccount.setDisplayName(displayname);
sipAccount.setPassword(password);
sipAccount.setServer(server);
sipAccount.setEnabled(enabled);
sipAccount.setVoiceMailNumber(voicemail);
sipAccount.setOutboundproxy(outboundproxy);
sipAccount.setPromptCredentials(promptCredentials);
if (test) {
try {
InetAddress localAddress = InetAddress.getByName(JiveGlobals.getProperty("xmpp.domain",
JiveGlobals.getXMLProperty("network.interface", "localhost")));
SIPTest sipTest = new SIPTest(localAddress, sipAccount);
if (sipTest != null) {
sipTest.test(5000, 2);
testResult = sipTest.getResult();
} else
testResult = SIPTest.Result.NetworkError;
} catch (Exception e) {
testResult = SIPTest.Result.NetworkError;
Log.error(e);
}
if (node != null && !"".equals(node)) {
sipAccount = new SipAccount(node);
SipAccount sp = SipAccountDAO.getAccountByUser(sipAccount.getUsername());
if (sp != null) {
sipAccount = sp;
}
}
} else {
try {
if (SipAccountDAO.getAccountByUser(sipAccount.getUsername()) != null) {
SipAccountDAO.update(sipAccount);
} else {
SipAccountDAO.insert(sipAccount);
}
response.sendRedirect("sipark-user-summary.jsp?username=" + URLEncoder.encode(node, "UTF-8"));
return;
} catch (SQLException e) {
errors.put("saveSettings", e.getMessage());
Log.error(e);
}
}
}
} else {
if (node != null && !"".equals(node)) {
sipAccount = new SipAccount(node);
SipAccount sp = SipAccountDAO.getAccountByUser(sipAccount.getUsername());
if (sp != null) {
sipAccount = sp;
}
}
if (sipAccount == null) {
enabled = true;
server = JiveGlobals.getProperty("phone.sipServer", "");
voicemail = JiveGlobals.getProperty("phone.voiceMail", "");
} else {
username = sipAccount.getSipUsername();
authusername = sipAccount.getAuthUsername();
displayname = sipAccount.getDisplayName();
password = sipAccount.getPassword();
server = sipAccount.getServer();
enabled = sipAccount.isEnabled();
voicemail = sipAccount.getVoiceMailNumber();
outboundproxy = sipAccount.getOutboundproxy();
promptCredentials = sipAccount.isPromptCredentials();
}
}
%>
<html>
<head>
<title><% if (sipAccount == null) { %>
<fmt:message key="sipark.user.create.title"/>
<% } else { %>
<fmt:message key="sipark.user.update.title"/>
<% } %></title>
<link rel="stylesheet" type="text/css" href="/style/global.css">
<meta name="pageID" content="sipark-user-summary"/>
<script src="/js/prototype.js" type="text/javascript"></script>
<script src="/js/scriptaculous.js" type="text/javascript"></script>
<style type="text/css">
.div-border {
border: 1px;
border-color: #ccc;
border-style: dotted;
}
</style>
</head>
<body>
<% if (errors.size() > 0) { %>
<div class="error">
<%= errorMessage %>
</div>
<br/>
<% } %>
<%
if (testResult != null) {
if (SIPTest.Result.Successfully.equals(testResult)) { %>
<div class="success">
SIP Account Successfully Tested.
</div>
<br>
<% } else { %>
<div class="error">
SIP Account problem: <%=testResult.toString()%>
<i>
<%
if (testResult.equals(SIPTest.Result.Forbidden)) {
%>
<fmt:message key="sip.test.error.forbidden"/>
<%
} else if (testResult.equals(SIPTest.Result.NetworkError)) {
%>
<fmt:message key="sip.test.error.networkerror"/>
<%
} else if (testResult.equals(SIPTest.Result.Timeout)) {
%>
<fmt:message key="sip.test.error.timeout"/>
<%
} else if (testResult.equals(SIPTest.Result.WrongUser)) {
%>
<fmt:message key="sip.test.error.wronguser"/>
<%
} else if (testResult.equals(SIPTest.Result.WrongAuthUser)) {
%>
<fmt:message key="sip.test.error.wrongauthuser"/>
<%
} else if (testResult.equals(SIPTest.Result.WrongPass)) {
%>
<fmt:message key="sip.test.error.wronpass"/>
<%
}
%>
</i>
</div>
<br>
<% }
} %>
<p>
<fmt:message key="sipark.user.create.description"/>
</p>
<form id="urlForm" name="urlForm" action="create-sipark-mapping.jsp" method="post">
<table class="div-border" cellpadding="3">
<% if (sipAccount == null) { %>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.xmpp.username"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="node" value="<%= (node != null ? node : "") %>">
</td>
</tr>
<% } else {%>
<input type="hidden" name="node" value="<%= node %>">
<% } %>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.sip.username"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="sipusername"
value="<%= (username != null ? username : "") %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.authusername"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="authusername"
value="<%= (authusername != null ? authusername : "") %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.displayname"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="displayname"
value="<%= (displayname != null ? displayname : "") %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.password"/>
:&nbsp
</td>
<td><input type="password" size="20" maxlength="100" name="sippassword"
value="<%= (password != null ? password : "") %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.server"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="server"
value="<%= (server != null ? server : "") %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.outboundproxy"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="outboundproxy"
value="<%= (outboundproxy != null ? outboundproxy : "") %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.voicemail"/>
:&nbsp
</td>
<td><input type="text" size="20" maxlength="100" name="voicemail"
value="<%= (voicemail != null ? voicemail : "") %>">
</td>
</tr>
<% if (sipAccount != null) { %>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.promptCredentials"/>
:&nbsp
</td>
<td><input type="checkbox" size="20" maxlength="100" name="promptCredentials" <%= promptCredentials ? "checked" : "" %>">
</td>
</tr>
<tr>
<td align="left" width="150">
<fmt:message key="sip.account.enabled"/>
:&nbsp
</td>
<td><input type="checkbox" size="20" maxlength="100" name="enabled" <%= enabled ? "checked" : "" %>">
</td>
</tr>
<% } else {%>
<input type="hidden" name="enabled" value="<%= enabled %>">
<% } %>
<tr>
<td></td>
<td><input type="submit" name="save"
value="<%= sipAccount != null ? LocaleUtils.getLocalizedString("sipark.user.create.save.changes", "sip") : LocaleUtils.getLocalizedString("create", "sip") %>"/>
&nbsp;<input type="submit" name="cancel" value="<fmt:message key="cancel" />">
<% if (sipAccount != null || test) { %>
&nbsp;<input type="submit" name="test" value="<fmt:message key="test" />">
<%}%>
</td>
</tr>
</table>
</form>
</body>
</html>
<%@ page import="org.jivesoftware.openfire.sip.calllog.CallLog,
org.jivesoftware.openfire.sip.calllog.CallLogDAO"
%>
<%@ page import="java.util.Collection" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="org.jivesoftware.util.*" %>
<%@ page import="java.text.DateFormat" %>
<%@ page import="java.net.URLEncoder" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%!
final int DEFAULT_RANGE = 15;
final int[] RANGE_PRESETS = {15, 25, 50, 75, 100};
%>
<jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager"/>
<% webManager.init(request, response, session, application, out); %>
<html>
<head>
<title><fmt:message key="call.summary.title" /></title>
<meta name="pageID" content="sipark-log-summary"/>
<script src="/js/prototype.js" type="text/javascript"></script>
<script src="/js/scriptaculous.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript" src="/js/tooltips/domLib.js"></script>
<script type="text/javascript" language="javascript" src="/js/tooltips/domTT.js"></script>
<style type="text/css">@import url( /js/jscalendar/calendar-win2k-cold-1.css );</style>
<script type="text/javascript" src="/js/jscalendar/calendar.js"></script>
<script type="text/javascript" src="/js/jscalendar/i18n.jsp"></script>
<script type="text/javascript" src="/js/jscalendar/calendar-setup.js"></script>
<style type="text/css">
.jive-current {
font-weight: bold;
text-decoration: none;
}
.stat {
margin: 0px 0px 8px 0px;
border: 1px solid #cccccc;
-moz-border-radius: 3px;
}
.stat td table {
margin: 5px 10px 5px 10px;
}
.stat div.verticalrule {
display: block;
width: 1px;
height: 110px;
background-color: #cccccc;
overflow: hidden;
margin-left: 3px;
margin-right: 3px;
}
</style>
<script type="text/javascript">
function hover(oRow) {
oRow.style.background = "#A6CAF0";
oRow.style.cursor = "pointer";
}
function noHover(oRow) {
oRow.style.background = "white";
}
function submitFormAgain(start, range){
document.f.start.value = start;
document.f.range.value = range;
document.f.parseRange.value = "true";
document.f.submit();
}
</script>
<style type="text/css">
.stat {
margin: 0px 0px 8px 0px;
border: 1px solid #cccccc;
-moz-border-radius: 3px;
}
.stat td table {
margin: 5px 10px 5px 10px;
}
.stat div.verticalrule {
display: block;
width: 1px;
height: 110px;
background-color: #cccccc;
overflow: hidden;
margin-left: 3px;
margin-right: 3px;
}
.content {
border-color: #bbb;
border-style: solid;
border-width: 0px 0px 1px 0px;
}
/* Default DOM Tooltip Style */
div.domTT {
border: 1px solid #bbb;
background-color: #F9F5D5;
font-family: Arial, Helvetica sans-serif;
font-size: 9px;
padding: 5px;
}
div.domTT .caption {
font-family: serif;
font-size: 12px;
font-weight: bold;
padding: 1px 2px;
color: #FFFFFF;
}
div.domTT .contents {
font-size: 12px;
font-family: sans-serif;
padding: 3px 2px;
}
.textfield {
font-size: 11px;
font-family: Verdana, Arial, sans-serif;
height: 20px;
background: #efefef;
}
#searchResults h3 {
font-size: 14px;
padding: 0px;
margin: 0px 0px 2px 0px;
color: #104573;
}
#searchResults p.resultDescription {
margin: 0px 0px 12px 0px;
}
</style>
<script type="text/javascript">
function grayOut(ele) {
if (ele.value == 'Any') {
ele.style.backgroundColor = "#EAF1F8";
}
else {
ele.style.backgroundColor = "#ffffff";
}
}
</script>
<script type="text/javascript" src="/js/behaviour.js"></script>
</head>
<body>
<% // Get parameters
int start = ParamUtils.getIntParameter(request, "start", 0);
int range = ParamUtils.getIntParameter(request, "range", webManager.getRowsPerPage("user-summary", DEFAULT_RANGE));
String username = ParamUtils.getParameter(request, "username");
String numa = ParamUtils.getParameter(request, "numa");
String numb = ParamUtils.getParameter(request, "numb");
String type = ParamUtils.getParameter(request, "type");
String startDate = request.getParameter("startDate");
String endDate = request.getParameter("endDate");
String filter = null;
if (request.getParameter("submit") != null) {
Date fromDate = null;
Date uptoDate = null;
String anyText = LocaleUtils.getLocalizedString("archive.settings.any", "sip");
if (anyText.equals(startDate)) {
startDate = null;
}
if (anyText.equals(endDate)) {
endDate = null;
}
if (startDate != null && startDate.length() > 0) {
DateFormat formatter = new SimpleDateFormat("MM/dd/yy");
try {
fromDate = formatter.parse(startDate);
}
catch (Exception e) {
// TODO: mark as an error in the JSP instead of logging..
Log.error(e);
}
}
if (endDate != null && endDate.length() > 0) {
DateFormat formatter = new SimpleDateFormat("MM/dd/yy");
try {
Date date = formatter.parse(endDate);
// The user has chosen an end date and expects that any conversation
// that falls on that day will be included in the search results. For
// example, say the user choose 6/17/2006 as an end date. If a conversation
// occurs at 5:33 PM that day, it should be included in the results. In
// order to make this possible, we need to make the end date one millisecond
// before the next day starts.
uptoDate = new Date(date.getTime() + JiveConstants.DAY - 1);
}
catch (Exception e) {
// TODO: mark as an error in the JSP instead of logging..
Log.error(e);
}
}
filter = CallLogDAO.createSQLFilter(username, numa, numb, type, fromDate, uptoDate);
}
if (request.getParameter("range") != null) {
webManager.setRowsPerPage("user-summary", range);
}
%>
<form name="jid" action="sipark-log-summary.jsp" method="post">
<div>
<table class="stat">
<tr valign="top">
<td>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody>
<tr>
<td align="left" width="150"><fmt:message key="call.summary.username" />:&nbsp
</td>
<td align="left">
<input type="text" size="20" maxlength="100" name="username" value="<%= username != null ? username : ""%>">
</td>
</tr>
<tr>
<td align="left" width="150"><fmt:message key="call.summary.from"/>:&nbsp
</td>
<td align="left">
<input type="text" size="20" maxlength="100" name="numa" value="<%= numa != null ? numa : ""%>">
</td>
</tr>
<tr>
<td align="left" width="150"><fmt:message key="call.summary.destination"/>:&nbsp
</td>
<td align="left">
<input type="text" size="20" maxlength="100" name="numb" value="<%= numb != null ? numb : ""%>">
</td>
</tr>
<tr>
<td align="left" width="150"><fmt:message key="call.summary.type"/>:&nbsp
</td>
<td align="left">
<select name="type" size="1">
<option value="all" <%= "all".equals(type) || type == null ? "selected" : ""%>><fmt:message key="call.type.all"/>
<option value="received" <%= "received".equals(type)? "selected" : ""%>><fmt:message key="call.type.received"/>
<option value="loss" <%= "missed".equals(type)? "selected" : ""%>><fmt:message key="call.type.missed"/>
<option value="dialed" <%= "dialed".equals(type)? "selected" : ""%>><fmt:message key="call.type.dialed"/>
</select>
</td>
</tr>
</tbody>
</table>
</td>
<td width="0" height="100%" valign="middle">
<div class="verticalrule"></div>
</td>
<td>
<table>
<tr>
<td colspan="3">
<img src="images/icon_daterange.gif" align="absmiddle" alt="" style="margin: 0px 4px 0px 2px;"/>
<b><fmt:message key="archive.search.daterange" /></b>
<a onmouseover="domTT_activate(this, event, 'content',
'<fmt:message key="archive.search.daterange.tooltip"/>',
'trail', true, 'direction', 'northeast', 'width', '220');"><img src="images/icon_help_14x14.gif" vspace="2" align="texttop"/></a>
</td>
</tr>
<tr valign="top">
<td><fmt:message key="archive.search.daterange.start" /></td>
<td>
<input type="text" id="startDate" name="startDate" size="13"
value="<%= startDate != null ? startDate :
LocaleUtils.getLocalizedString("archive.search.daterange.any", "sip")%>" class="textfield"/><br/>
<span class="jive-description"><fmt:message key="archive.search.daterange.format" /></span>
</td>
<td>
<img src="images/icon_calendarpicker.gif" vspace="3" id="startDateTrigger">
</td>
</tr>
<tr valign="top">
<td><fmt:message key="archive.search.daterange.end" /></td>
<td>
<input type="text" id="endDate" name="endDate" size="13"
value="<%= endDate != null ? endDate :
LocaleUtils.getLocalizedString("archive.search.daterange.any", "sip") %>" class="textfield"/><br/>
<span class="jive-description"><fmt:message key="archive.search.daterange.format" /></span>
</td>
<td>
<img src="images/icon_calendarpicker.gif" vspace="3" id="endDateTrigger">
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<input type="hidden" name="submit" value="true">
<input type="submit" name="get" value="<fmt:message key="call.summary.filter"/>">
</form>
<%
if (filter != null) {
// Get the user manager
int logCount = CallLogDAO.getLogCount(filter);
// paginator vars
int numPages = (int) Math.ceil((double) logCount / (double) range);
int curPage = (start / range) + 1;
StringBuffer sb = new StringBuffer();
if (username != null)
sb.append("&username=").append(URLEncoder.encode(username, "utf-8"));
if (numa != null)
sb.append("&numa=").append(URLEncoder.encode(numa, "utf-8"));
if (numb != null)
sb.append("&numb=").append(URLEncoder.encode(numb, "utf-8"));
if (type != null)
sb.append("&type=").append(URLEncoder.encode(type, "utf-8"));
if (startDate != null)
sb.append("&startDate=").append(URLEncoder.encode(startDate, "utf-8"));
if (endDate != null)
sb.append("&endDate=").append(URLEncoder.encode(endDate, "utf-8"));
String urlParams = sb.toString();
%>
<p>
<fmt:message key="call.summary.total_calls"/>
:
<b><%= LocaleUtils.getLocalizedNumber(logCount) %>
</b> --
<% if (numPages > 1) { %>
<fmt:message key="global.showing"/>
<%= LocaleUtils.getLocalizedNumber(start + 1) %>-<%= LocaleUtils
.getLocalizedNumber(start + range) %>
<% } %>
-<fmt:message key="call.summary.calls_per_page"/>:
<select size="1"
onchange="location.href='sipark-log-summary.jsp?submit=true&start=0<%= urlParams %>&range=' + this.options[this.selectedIndex].value;">
<% for (int i = 0; i < RANGE_PRESETS.length; i++) { %>
<option value="<%= RANGE_PRESETS[i] %>"
<%= (RANGE_PRESETS[i] == range ? "selected" : "") %>><%= RANGE_PRESETS[i] %>
</option>
<% } %>
</select>
</p>
<% if (numPages > 1) { %>
<p>
<fmt:message key="global.pages"/>
:
[
<% int num = 15 + curPage;
int s = curPage - 1;
if (s > 5) {
s -= 5;
}
if (s < 5) {
s = 0;
}
if (s > 2) {
%>
<a href="sipark-log-summary.jsp?submit=true&start=0&range=<%= range %><%= urlParams %>">1</a> ...
<%
}
int i;
for (i = s; i < numPages && i < num; i++) {
String sep = ((i + 1) < numPages) ? " " : "";
boolean isCurrent = (i + 1) == curPage;
%>
<a href="sipark-log-summary.jsp?submit=true&start=<%= (i*range) %>&range=<%= range %><%= urlParams %>"
class="<%= ((isCurrent) ? "jive-current" : "") %>"
><%= (i + 1) %>
</a><%= sep %>
<% } %>
<% if (i < numPages) { %>
... <a
href="sipark-log-summary.jsp?submit=true&start=<%= ((numPages-1)*range) %>&range=<%= range %>"><%= numPages %><%= urlParams %>
</a>
<% } %>
]
</p>
<% } %>
<div class="jive-table">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<thead>
<tr>
<th>&nbsp;</th>
<th nowrap><fmt:message key="call.summary.time"/></th>
<th nowrap><fmt:message key="call.summary.username"/></th>
<th nowrap><fmt:message key="call.summary.from"/></th>
<th nowrap><fmt:message key="call.summary.destination"/></th>
<th nowrap><fmt:message key="call.summary.duration"/></th>
<th nowrap><fmt:message key="call.summary.type"/></th>
</tr>
</thead>
<tbody>
<% // Print the list of users
Collection<CallLog> calls = CallLogDAO.getCalls(filter, start, range);
if (calls.isEmpty()) {
%>
<tr>
<td align="center" colspan="7">
<fmt:message key="call.summary.no-entries"/>
</td>
</tr>
<%
}
int i = start;
for (CallLog call : calls) {
i++;
%>
<tr class="jive-<%= (((i%2)==0) ? "even" : "odd") %>">
<td width="1%">
<%= i %>
</td>
<td width="30%">
<%=JiveGlobals.formatDateTime(new Date(call.getDateTime()))%>
</td>
<td width="10%" align="center" valign="middle">
<%=call.getUsername()%>&nbsp;
</td>
<td width="20%" align="left">
<%=call.getNumA()%>&nbsp;
</td>
<td width="20%" align="left">
<%=call.getNumB()%>&nbsp;
</td>
<td width="5%" align="left">
<%=call.getDuration()%>
</td>
<td width="5%" align="left">
<%=call.getType()%>
</td>
</tr>
<%
}
%>
</tbody>
</table>
</div>
<% if (numPages > 1) { %>
<p>
<fmt:message key="global.pages"/>
:
[
<% int num = 15 + curPage;
int s = curPage - 1;
if (s > 5) {
s -= 5;
}
if (s < 5) {
s = 0;
}
if (s > 2) {
%>
<a href="sipark-log-summary.jsp?submit=true&start=0&range=<%= range %><%= urlParams %>">1</a> ...
<%
}
for (i = s; i < numPages && i < num; i++) {
String sep = ((i + 1) < numPages) ? " " : "";
boolean isCurrent = (i + 1) == curPage;
%>
<a href="sipark-log-summary.jsp?submit=true&start=<%= (i*range) %>&range=<%= range %><%= urlParams %>"
class="<%= ((isCurrent) ? "jive-current" : "") %>"
><%= (i + 1) %>
</a><%= sep %>
<% } %>
<% if (i < numPages) { %>
... <a
href="sipark-log-summary.jsp?submit=true&start=<%= ((numPages-1)*range) %>&range=<%= range %>"><%= numPages %><%= urlParams %>
</a>
<% } %>
]
</p>
<% } } %>
<script type="text/javascript">
grayOut(jid.startDate);
grayOut(jid.endDate);
function catcalc(cal) {
var endDateField = $('endDate');
var startDateField = $('startDate');
var endTime = new Date(endDateField.value);
var startTime = new Date(startDateField.value);
if(endTime.getTime() < startTime.getTime()){
alert("<fmt:message key="archive.search.daterange.error" />");
startDateField.value = "<fmt:message key="archive.search.daterange.any" />";
}
}
Calendar.setup(
{
inputField : "startDate", // ID of the input field
ifFormat : "%m/%d/%y", // the date format
button : "startDateTrigger", // ID of the button
onUpdate : catcalc
});
Calendar.setup(
{
inputField : "endDate", // ID of the input field
ifFormat : "%m/%d/%y", // the date format
button : "endDateTrigger", // ID of the button
onUpdate : catcalc
});
</script>
</body>
</html>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="org.jivesoftware.util.JiveGlobals" %>
<%@ page import="org.jivesoftware.util.LocaleUtils" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<html>
<head>
<title><fmt:message key="sipark.settings.title"/></title>
<meta name="pageID" content="sipark-settings"/>
<link rel="stylesheet" type="text/css" href="style/style.css">
<style type="text/css">
.small-label {
font-size: 11px;
font-weight: bold;
font-family: verdana;
}
.small-text {
font-size: 11px;
font-family: verdana;
}
.stat {
border: 1px;
border-color: #ccc;
border-style: dotted;
}
.conversation-body {
color: black;
font-size: 11px;
font-family: verdana;
}
.conversation-label1 {
color: blue;
font-size: 11px;
font-family: verdana;
}
.conversation-label2 {
color: red;
font-size: 11px;
font-family: verdana;
}
.conversation-table {
font-family: verdana;
font-size: 12px;
}
.light-gray-border {
border-color: #bbb;
border-style: solid;
border-width: 1px 1px 1px 1px;
}
.light-gray-border-bottom {
border-color: #bbb;
border-style: solid;
border-width: 0px 0px 1px 0px;
}
.content {
border-color: #bbb;
border-style: solid;
border-width: 0px 0px 1px 0px;
}
/* Default DOM Tooltip Style */
div.domTT {
border: 1px solid #bbb;
background-color: #F9F5D5;
font-family: arial;
font-size: 9px;
padding: 5px;
}
div.domTT .caption {
font-family: serif;
font-size: 12px;
font-weight: bold;
padding: 1px 2px;
color: #FFFFFF;
}
div.domTT .contents {
font-size: 12px;
font-family: sans-serif;
padding: 3px 2px;
}
.textfield {
font-size: 11px;
font-family: verdana;
padding: 3px 2px;
background: #efefef;
}
.keyword-field {
font-size: 11px;
font-family: verdana;
padding: 3px 2px;
}
</style>
</head>
<body>
<% // Get parameters
boolean update = request.getParameter("update") != null;
String sipServer = request.getParameter("sipServer");
String voiceMail = request.getParameter("voiceMail");
boolean stunEnabled = request.getParameter("stunEnabled") != null;
String stunServer = request.getParameter("stunServer");
String stunPort = request.getParameter("stunPort");
if (request.getParameter("cancel") != null) {
response.sendRedirect("sipark-user-summary.jsp");
return;
}
// Update the session kick policy if requested
Map errors = new HashMap();
String errorMessage = "";
if (update) {
// Validate params
if (sipServer == null || "".equals(sipServer)) {
errors.put("sipServer", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.settings.valid.sipserver", "sip");
}
else if (voiceMail == null || "".equals(voiceMail)) {
errors.put("voiceMail", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.settings.valid.voiceMail", "sip");
}
else if (stunEnabled && (stunServer == null || "".equals(stunServer))) {
errors.put("stunServer", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.settings.valid.stunServer", "sip");
}
else if (stunEnabled && (stunPort == null || "".equals(stunPort))) {
errors.put("stunPort", "");
errorMessage = LocaleUtils.getLocalizedString("sipark.settings.valid.stunPort", "sip");
}
// If no errors, continue:
if (errors.size() == 0) {
JiveGlobals.setProperty("phone.sipServer", sipServer);
JiveGlobals.setProperty("phone.voiceMail", voiceMail);
if (stunEnabled) {
JiveGlobals.setProperty("phone.stunEnabled", "true");
JiveGlobals.setProperty("phone.stunServer", stunServer);
JiveGlobals.setProperty("phone.stunPort", stunPort);
} else {
JiveGlobals.setProperty("phone.stunEnabled", "false");
JiveGlobals.deleteProperty("phone.stunServer");
JiveGlobals.deleteProperty("phone.stunPort");
}
%>
<div class="success">
<fmt:message key="sipark.settings.success"/>
</div><br>
<%
}
}
else {
sipServer = JiveGlobals.getProperty("phone.sipServer", "");
voiceMail = JiveGlobals.getProperty("phone.voiceMail", "");
stunEnabled = JiveGlobals.getBooleanProperty("phone.stunEnabled", false);
stunServer = JiveGlobals.getProperty("phone.stunServer", "");
stunPort = JiveGlobals.getProperty("phone.stunPort", "");
}
%>
<% if (errors.size() > 0) { %>
<div class="error">
<%= errorMessage%>
</div>
<br/>
<% } %>
<p>
<fmt:message key="sipark.settings.description"/>
</p>
<form action="sipark-settings.jsp" method="post">
<table class="settingsTable" cellpadding="3" cellspacing="0" border="0" width="90%">
<thead>
<tr>
<th colspan="3"><fmt:message key="sipark.settings.table.title" /></th>
</tr>
</thead>
<tbody>
<tr>
<td width="98%"><label class="jive-label"><fmt:message key="sipark.settings.sipServer"/>:</label><br>
<fmt:message key="sipark.settings.sipServer.description"/></td>
<td><input type="text" name="sipServer" size="20" maxlength="100" value="<%= sipServer == null ? "" : sipServer%>" /></td>
<td></td>
</tr>
<tr>
<td><label class="jive-label"><fmt:message key="sipark.settings.voiceMail"/>:</label><br>
<fmt:message key="sipark.settings.voiceMail.description"/></td>
<td><input type="text" name="voiceMail" size="20" maxlength="100" value="<%= voiceMail == null ? "" : voiceMail %>" /></td>
<td></td>
</tr>
<tr>
<td><label class="jive-label"><fmt:message key="sipark.settings.enable.stun"/>:</label><br>
<fmt:message key="sipark.settings.enable.stun.description"/></td>
<td><input type="checkbox" name="stunEnabled" <%= stunEnabled ? "checked" : ""%> /></td>
<td></td>
</tr>
<tr>
<td><label class="jive-label"><fmt:message key="sipark.settings.stunServer"/>:</label><br>
<fmt:message key="sipark.settings.stunServer.description"/></td>
<td><input type="text" name="stunServer" size="20" maxlength="100" value="<%= stunServer == null ? "" : stunServer %>" /></td>
<td></td>
</tr>
<tr>
<td><label class="jive-label"><fmt:message key="sipark.settings.stunServer.port"/>:</label><br>
<fmt:message key="sipark.settings.stunServer.port.description"/></td>
<td><input type="text" name="stunPort" size="10" maxlength="10" value="<%= stunPort == null ? "" : stunPort %>" /></td>
<td></td>
</tr>
</tbody>
</table>
<input type="submit" name="update" value="<fmt:message key="sipark.settings.update.settings" />">
<input type="submit" name="cancel" value="<fmt:message key="sipark.settings.cancel" />">
</form>
</body>
</html>
<%--
- $Revision: 5374 $
- $Date: 2006-09-14 19:04:51 -0300 (qui, 14 set 2006) $
-
- Copyright (C) 2004-2005 Jive Software. All rights reserved.
-
- This software is published under the terms of the GNU Public License (GPL),
- a copy of which is included in this distribution.
--%>
<%@ page import="org.jivesoftware.openfire.sip.sipaccount.SipAccount,
org.jivesoftware.openfire.sip.sipaccount.SipAccountDAO,
org.jivesoftware.util.ParamUtils,
org.xmpp.packet.JID,
java.net.URLEncoder"
%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<% // Get parameters //
boolean cancel = request.getParameter("cancel") != null;
boolean delete = request.getParameter("delete") != null;
String username = ParamUtils.getParameter(request, "username");
// Handle a cancel
if (cancel) {
response.sendRedirect("sipark-user-summary.jsp?username=" + URLEncoder.encode(username, "UTF-8"));
return;
}
SipAccount account = SipAccountDAO.getAccountByUser(username);
// Handle an account delete:
if (delete) {
if (account != null) {
SipAccountDAO.remove(account);
// Done, so redirect
response.sendRedirect("sipark-user-summary.jsp?deletesuccess=true");
return;
}
response.sendRedirect("sipark-user-summary.jsp?deletesuccess=false");
return;
}
%>
<html>
<head>
<title>
<fmt:message key="sipark.user.delete.title"/>
</title>
<meta name="pageID" content="sipark-user-summary"/>
</head>
<body>
<p>
<b><fmt:message key="sipark.user.delete.confirm">
<fmt:param value="<%= "<a href='./../../user-properties.jsp?username=" + URLEncoder.encode(account.getUsername(), "UTF-8") + "'>" + JID.unescapeNode(account.getUsername()) + "</a>"%>" />
</fmt:message></b>
</p>
<form action="sipark-user-delete.jsp">
<input type="hidden" name="username" value="<%= username %>">
<input type="submit" name="delete" value="<fmt:message key="sipark.user.delete.delete" />">
<input type="submit" name="cancel" value="<fmt:message key="sipark.user.delete.cancel" />">
</form>
</body>
</html>
<%--
- $RCSfile$
- $Revision: 3710 $
- $Date: 2006-04-05 11:53:01 -0700 (Wed, 05 Apr 2006) $
-
- Copyright (C) 2004 Jive Software. All rights reserved.
-
- This software is published under the terms of the GNU Public License (GPL),
- a copy of which is included in this distribution.
--%>
<%@ page import="org.jivesoftware.util.LocaleUtils,
org.jivesoftware.util.ParamUtils,
java.net.URLEncoder"
%>
<%@ page import="org.jivesoftware.openfire.sip.sipaccount.SipAccountDAO" %>
<%@ page import="org.jivesoftware.openfire.sip.sipaccount.SipAccount" %>
<%@ page import="java.util.Collection" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%!
final int DEFAULT_RANGE = 15;
final int[] RANGE_PRESETS = {15, 25, 50, 75, 100};
%>
<jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager"/>
<% webManager.init(request, response, session, application, out); %>
<html>
<head>
<title>
<fmt:message key="sipark.user.title"/>
</title>
<meta name="pageID" content="sipark-user-summary"/>
</head>
<body>
<% // Get parameters
int start = ParamUtils.getIntParameter(request, "start", 0);
int range = ParamUtils.getIntParameter(request, "range", webManager.getRowsPerPage("user-summary", DEFAULT_RANGE));
if (request.getParameter("range") != null) {
webManager.setRowsPerPage("user-summary", range);
}
// Get the user manager
int userCount = SipAccountDAO.getUserCount();
// paginator vars
int numPages = (int) Math.ceil((double) userCount / (double) range);
int curPage = (start / range) + 1;
%>
<style type="text/css">
.jive-current {
font-weight: bold;
text-decoration: none;
}
</style>
<% if (request.getParameter("deletesuccess") != null) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/success-16x16.gif" width="16" height="16" border="0"></td>
<td class="jive-icon-label">
<fmt:message key="user.summary.deleted"/>
</td>
</tr>
</tbody>
</table>
</div>
<br>
<% } %>
<p>
<fmt:message key="sipark.user.description"/>
</p>
<p>
<fmt:message key="user.summary.total_user"/>
:
<b><%= LocaleUtils.getLocalizedNumber(SipAccountDAO.getUserCount()) %>
</b> --
<% if (numPages > 1) { %>
<fmt:message key="global.showing"/>
<%= LocaleUtils.getLocalizedNumber(start + 1) %>-<%= LocaleUtils.getLocalizedNumber(start + range) %>,
<% } %>
<fmt:message key="user.summary.sorted"/>
--
<fmt:message key="user.summary.users_per_page"/>
:
<select size="1"
onchange="location.href='sipark-user-summary.jsp?start=0&range=' + this.options[this.selectedIndex].value;">
<% for (int i = 0; i < RANGE_PRESETS.length; i++) { %>
<option value="<%= RANGE_PRESETS[i] %>"
<%= (RANGE_PRESETS[i] == range ? "selected" : "") %>><%= RANGE_PRESETS[i] %>
</option>
<% } %>
</select>
</p>
<% if (numPages > 1) { %>
<p>
<fmt:message key="global.pages"/>
:
[
<% int num = 15 + curPage;
int s = curPage - 1;
if (s > 5) {
s -= 5;
}
if (s < 5) {
s = 0;
}
if (s > 2) {
%>
<a href="sipark-user-summary.jsp?start=0&range=<%= range %>">1</a> ...
<%
}
int i;
for (i = s; i < numPages && i < num; i++) {
String sep = ((i + 1) < numPages) ? " " : "";
boolean isCurrent = (i + 1) == curPage;
%>
<a href="sipark-user-summary.jsp?start=<%= (i*range) %>&range=<%= range %>"
class="<%= ((isCurrent) ? "jive-current" : "") %>"
><%= (i + 1) %>
</a><%= sep %>
<% } %>
<% if (i < numPages) { %>
... <a href="sipark-user-summary.jsp?start=<%= ((numPages-1)*range) %>&range=<%= range %>"><%= numPages %>
</a>
<% } %>
]
</p>
<% } %>
<div class="jive-table">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<thead>
<tr>
<th>&nbsp;</th>
<th nowrap>
<fmt:message key="user.summary.enabled"/>
</th>
<th nowrap>
<fmt:message key="user.summary.status"/>
</th>
<th nowrap>
<fmt:message key="user.create.username"/>
</th>
<th nowrap>SIP
<fmt:message key="user.create.username"/>
</th>
<th nowrap>
<fmt:message key="user.create.server"/>
</th>
<th nowrap>
<fmt:message key="user.summary.edit"/>
</th>
<th nowrap>
<fmt:message key="global.delete"/>
</th>
</tr>
</thead>
<tbody>
<% // Print the list of users
Collection<SipAccount> users = SipAccountDAO.getUsers(start, range);
if (users.isEmpty()) {
%>
<tr>
<td align="center" colspan="8">
<fmt:message key="user.summary.not_user"/>
</td>
</tr>
<%
}
int i = start;
for (SipAccount user : users) {
i++;
%>
<tr class="jive-<%= (((i%2)==0) ? "even" : "odd") %>">
<td width="1%">
<%= i %>
</td>
<td width="1%" align="center" valign="middle">
<% if (user.isEnabled()) { %>
<img src="/images/check.gif" width="17" height="17" border="0">
<% } else { %>
<img src="/images/x.gif" width="17" height="17" border="0">
<% } %>
</td>
<td width="10%" align="center" valign="middle">
<%=user.getStatus().name()%>
</td>
<td width="20%">
<a href="./../../user-properties.jsp?username=<%= URLEncoder.encode(user.getUsername(), "UTF-8") %>"><%= user.getUsername() %>
</a>
</td>
<td width="20%">
<%= user.getSipUsername() %>
</td>
<td width="20%">
<%= user.getServer() %>
</td>
<td width="1%" align="center">
<a href="create-sipark-mapping.jsp?node=<%= URLEncoder.encode(user.getUsername(), "UTF-8") %>"
title="<fmt:message key="global.click_edit" />"
><img src="/images/edit-16x16.gif" width="17" height="17" border="0"></a>
</td>
<td width="1%" align="center" style="border-right:1px #ccc solid;">
<a href="sipark-user-delete.jsp?username=<%= URLEncoder.encode(user.getUsername(), "UTF-8") %>"
title="<fmt:message key="global.click_delete" />"
><img src="/images/delete-16x16.gif" width="16" height="16" border="0"></a>
</td>
</tr>
<%
}
%>
<tr>
<tr>
<td colspan="8">
<a href="create-sipark-mapping.jsp"><img src="/images/add-16x16.gif" border="0" align="texttop"
style="margin-right: 3px;"/>
<fmt:message key="sipark.user.mapping.add"/>
</a>
</td>
</tr>
</tr>
</tbody>
</table>
</div>
<% if (numPages > 1) { %>
<p>
<fmt:message key="global.pages"/>
:
[
<% int num = 15 + curPage;
int s = curPage - 1;
if (s > 5) {
s -= 5;
}
if (s < 5) {
s = 0;
}
if (s > 2) {
%>
<a href="sipark-user-summary.jsp?start=0&range=<%= range %>">1</a> ...
<%
}
i = 0;
for (i = s; i < numPages && i < num; i++) {
String sep = ((i + 1) < numPages) ? " " : "";
boolean isCurrent = (i + 1) == curPage;
%>
<a href="user-summary.jsp?start=<%= (i*range) %>&range=<%= range %>"
class="<%= ((isCurrent) ? "jive-current" : "") %>"
><%= (i + 1) %>
</a><%= sep %>
<% } %>
<% if (i < numPages) { %>
... <a href="sipark-user-summary.jsp?start=<%= ((numPages-1)*range) %>&range=<%= range %>"><%= numPages %>
</a>
<% } %>
]
</p>
<% } %>
</body>
</html>
a {
color: #34679a;
}
/* alertbox styles (errors and warnings) */
/* global alertbox styles */
.alertbox {
display: block;
position: relative;
-moz-border-radius: 3px;
padding: 0px 0px 0px 0px;
margin: 0px 0px 0px 0px;
width: 735px;
height: auto;
font-size: .85em;
color: #000000;
overflow: hidden;
}
.alertbox h3 {
display: block;
font-size: 1.1em;
margin: 15px 0px 5px 0px;
padding: 0px;
}
.alertbox p {
font-size: .9em;
margin: 3px 0px 10px 0px;
}
.alertbox a {
color: #000000;
}
.alertbox a:hover {
text-decoration: underline;
}
.linkbtn {
display: block;
position: relative;
float: right;
z-index: 100;
top: 10px;
right: 10px;
}
.linkbtn a {
font-weight: bold;
text-decoration: none;
}
.linkbtn a:hover {
text-decoration: underline;
}
.licenseIcon {
display: block;
position: absolute;
width: 22px;
height: 22px;
margin: 12px 12px 20px 12px;
padding: 0px 0px 0px 0px;
}
.licenseIconsmall {
display: block;
position: relative;
float: left;
width: 16px;
height: 16px;
margin: 0px 5px 4px 0px;
padding: 0px 0px 0px 0px;
}
.licenseContent {
display: block;
position: relative;
clear: none;
top: 0px;
left: 50px;
width: 670px;
}
/* alertboxsmall styles */
.alertboxsmall {
display: block;
position: relative;
float: right;
-moz-border-radius-topleft: 3px;
-moz-border-radius-bottomleft: 3px;
padding: 0px 0px 0px 0px;
margin: -12px -18px 0px 0px;
width: 100px;
font-size: .85em;
color: #000000;
}
.alertboxsmall div.licenseContentsmall {
margin: 5px;
line-height: 1.2em;
}
.alertboxsmall div.licenseContentsmall a {
display: block;
font-weight: bold;
text-decoration: none;
color: #A85E00;
padding: 3px 0px 0px 0px;
}
.alertboxsmall div.licenseContentsmall a:hover {
text-decoration: underline;
}
/* error-specific alertbox styles */
.licenseError {
border: 1px solid #BB8888;
background: #EDB9B1 url(../images/certificateimg_error.gif) no-repeat bottom right;
}
.licenseError div.licenseIcon {
background: url(../images/icon_error.gif) no-repeat;
}
.licenseError h3 {
color: #8C0900;
}
.licenseError div.linkbtn a {
color: #8C0900;
}
/* warning-specific alertbox styles */
.licenseWarning {
border: 1px solid #D9B04C;
background: #FFE9B2 url(../images/certificateimg_warning.gif) no-repeat bottom right;
margin-bottom: 10px;
}
.licenseWarning div.licenseIcon {
background: url(../images/icon_warning.gif) no-repeat;
}
.licenseWarning h3 {
color: #CA7303;
}
.licenseWarning div.linkbtn a {
color: #A85E00;
}
.licenseWarningsmall div.licenseIconsmall {
background: url(../images/icon_warning-small.gif) no-repeat;
}
.licenseWarningsmall {
border: 1px solid #D9B04C;
background: #FFE9B2;
}
/* license page specific styles */
.licenseHeader {
display: block;
width: 732px;
overflow: hidden;
background-color: #EAF1F8;
border: 1px solid #BBBBBB;
}
.licenseHeader strong {
display: block;
margin: 5px 10px 5px 10px;
}
.licenseBody {
display: block;
width: 732px;
overflow: hidden;
background-color: #FFFFFF;
border: 1px solid #BBBBBB;
border-top: none;
margin-bottom: 25px;
}
.licenseBody table {
width: 90%;
margin: 10px;
}
.licenseBody div.licenseContents {
width: 710px;
margin: 13px;
}
#enterLicenseLink {
display: block;
}
#enterLicenseLink a.licenseLink {
background: url(/images/add-16x16.gif) no-repeat;
padding: 0px 0px 0px 20px;
}
#enterLicense {
display: block;
}
#enterLicense a.cancelLink {
background: url(/images/forbidden-16x16.gif) no-repeat;
padding: 0px 0px 0px 20px;
}
.licenseBody form {
display: block;
width: 680px;
margin: 0px 0px 15px 0px;
padding: 0px;
text-align: right;
}
.licenseBody form textarea {
width: 680px;
height: 185px;
margin-bottom: 5px;
font-family: "Courier New", Courier, monospace;
font-size: 13px;
}
.licenseFormError {
width: 680px;
text-align:left;
color: #8C0900;
font-weight: bold;
padding: 10px 0px 10px 0px;
}
strong.erroritem {
color: #6E1F1F;
}
/* general page elements */
table.settingsTable {
display: block;
border: 1px solid #BBBBBB;
margin: 5px 0px 15px 0px;
}
table.settingsTable thead th {
background-color: #EAF1F8;
border-bottom: 1px solid #BBBBBB;
padding: 3px 8px 3px 12px;
font-weight: bold;
text-align: left;
}
table.settingsTable tbody tr td {
padding: 5px 10px 5px 15px;
}
table.settingsTable tbody tr td p {
padding: 10px 0px 5px 0px;
}
table.settingsTable tr {
padding: 0px 0px 10px 0px;
}
/* Permit Client specific styles */
/* modified the fieldset from existing */
/* condensed border to one entry, pulled "width: 95%;" */
fieldset {
display: block;
position: relative;
-moz-border-radius: 3px;
border: 1px solid #CCCCCC;
padding: 2px 0px 0px 0px;
margin: 0px 0px 0px 0px;
}
fieldset legend {
color: #000000;
margin-left: 15px;
}
.clientscontent {
display: block;
position: relative;
margin: 0px 15px 0px 15px;
}
.permitclientbox {
display: block;
position: relative;
border: 1px solid #DCDCDC;
-moz-border-radius: 3px;
padding: 3px 2px 2px 2px;
margin: 10px 0px 10px 0px;
width: 600px;
height: auto;
color: #000000;
overflow: hidden;
background-color: #F4F4F4;
line-height: 1.6em;
}
.permitclientbox table tr td {
line-height: 1.8em;
}
.permitclientbox span {
font-size: .85em;
margin-left: 4px;
}
.permitclientbox a {
color: #34679A;
}
.horizontalrule {
display: block;
height: 1px;
background-color: #DCDCDC;
margin-top: 2px;
margin-bottom: 14px;
overflow: hidden;
clear: both;
}
.permitclientActive {
background-color: #F3F7FA;
}
.specifyclients {
display: block;
position: relative;
margin: 0px 15px 18px 15px;
width: auto;
padding: 0px;
}
/* Reports specific styles */
tr.allreports_report_default td {
padding: 3px 5px 3px 12px;
cursor: pointer;
background-color: #ffffff;
border: none;
border-top: 1px solid #ffffff;
border-bottom: 1px solid #ffffff;
font-size: 12px;
color: #34679a;
}
tr.allreports_report_selected td {
padding: 3px 5px 3px 12px;
cursor: pointer;
border: none;
border-top: 1px solid #bbbbbb;
border-bottom: 1px solid #bbbbbb;
background: #edeed7 url('../images/reports_selected-arrow.gif') no-repeat top left;
background-position: 4px 6px;
font-size: 12px;
color: #2f302b;
font-weight: bold;
}
tr.allreports_report_hover td {
padding: 3px 5px 3px 12px;
cursor: pointer;
background-color: #f4f4f4;
border: none;
border-top: 1px solid #bbbbbb;
border-bottom: 1px solid #bbbbbb;
font-size: 12px;
color: #34679a;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment