Support A2Billing :

provided by Star2Billing S.L.

Support A2Billing :
It is currently Sat Apr 27, 2024 5:00 am
Hosted Voice Broadcast


All times are UTC




Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Billing Calls to Extensions
PostPosted: Tue Jul 04, 2006 10:03 pm 
Offline

Joined: Tue Jul 04, 2006 3:21 pm
Posts: 13
Hi all,

Aside from using it as a post paid or prepaid billing system, can A2billing also be tweaked to bill extension calls. (i.e destination = sip or iax extensions) Any link or instructions regarding this will be highly appreciated.

Cheers.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 04, 2006 10:33 pm 
Offline

Joined: Sun Mar 12, 2006 2:49 pm
Posts: 954
Location: Barcelona
depends what u would like to bill in the extensions.
more info?

Rgds, Areski


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 05, 2006 7:58 am 
Offline

Joined: Tue Jul 04, 2006 3:21 pm
Posts: 13
Thanks Areski for your reply. What I want to bill in the extensions is this.

I want to use the call logs inside asteriskcdrdb for billing a situation such as;

1. source = extension, destination = extension where disposition = ANSWERED. (given duration)

2. I also want to be able to get total calls by this extensions and total cost, so that the extension user(s) (or customers as the case may be) can also view their calls and cost immediately they drop the phone.

Pls Note that this duration is the billable seconds or munites from the asteriskcdrdb.

Thanks once again.

Cheers.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 05, 2006 9:14 am 
Offline

Joined: Sun Mar 12, 2006 2:49 pm
Posts: 954
Location: Barcelona
well you will need kind of wholesales application for this.
Ftm, A2Billing is performing his billing in Realtime, by passing the call through the AGI.

Rgds, Areski


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 06, 2006 8:53 am 
Offline

Joined: Tue Jul 04, 2006 3:21 pm
Posts: 13
not quite clear about that. yes i want it real time like A2billing is doing. All I want is an addition of billing distination = sip extensions that is answered, just like its done for trunks. Then for sip extension users (customers here now) to see this bills of the sip extensions they called and to total. thats all

Cheers.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 07, 2006 8:17 pm 
Offline

Joined: Tue Jul 04, 2006 3:21 pm
Posts: 13
Hi Areski,

any clue or idea regarding this. Hope to hear from you soonest.

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 07, 2006 9:14 pm 
Offline

Joined: Mon Jun 19, 2006 5:14 pm
Posts: 218
Suggestion:

1. create a rate card called "internal clients" do not specify the trunk
2. create a trunk with each sip user context credentials. The "providerip" is the name of SIP friend context. SIP is the technology
3. create a rate for each sip client on the "internal clients" card and specify its trunk definition as #2 name. use the sip username as as the prefix to match on
4. add the "internal client" rate card to the tariff of whomever you want to call the SIP extension

a. your sip buddy/friend/client names should not be something that overlaps with your outgoing numbers that you dial . they must be numeric

b. essentially what you are doing is use a2billing to route all your calls, internal and external

c. You should then be able to use the Customer_UI and see all the calls and costs etc.

give it a try.

If you get it working you can optimize it by defining an "internal" trunk with your server's local IP addrress and this way every SIP client does not have to be a trunk so you can do Dial SIP/${sipclient}@internal ... then you can put that trunk in the rate card and then just define a rate with a prefix pattern that matches all your extensions. this way you don't need a trunk definition in the rate and every sip client does not have to be a trunk

Try the 1st one and when you get it working you will grasp the mechanics then you can do the optimization


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 10, 2006 7:26 am 
Offline

Joined: Tue Jul 04, 2006 3:21 pm
Posts: 13
thanks gue. I will give it a try and get the result back to the forum as soon as possible.

cheers.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Aug 27, 2006 3:44 pm 
Offline

Joined: Fri Aug 25, 2006 10:28 pm
Posts: 11
Location: Argentina
I


Top
 Profile  
 
 Post subject:
PostPosted: Sun Aug 27, 2006 6:04 pm 
Offline

Joined: Mon Jun 19, 2006 5:14 pm
Posts: 218
For the optimization here is what I wnat you to try:

In your sip.conf you have each of your "peers" defined
[peername]
host=dynamic


In a normal asterisk environment we would reach them by

exten => s,1,Dial(SIP/peername) ; asterisk would look up the peer name and find the address to dial out on

you could also do this:
exten => s,1,Dial(SIP/[email protected]) ; Connect to foo.com, requesting extension "3456"

In A2B the second case might be the better choice

define A2B trunk like so:
Label = internal-extensions
Technology=SIP
Provider/IP=your local IP address or domain name = 127.0.0.1
remove prefix = 999

so when the dial string gets executed it will look like this

exten => s,1,Dial(SIP/${EXTEN}@127.0.0.1)

This would be in keeping with the Dial command syntax for SIP and the one used in A2B. See a2billing.conf parameter "switchdialcommand"


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 28, 2006 8:19 pm 
Offline

Joined: Fri Aug 25, 2006 10:28 pm
Posts: 11
Location: Argentina
I


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 29, 2006 1:24 pm 
Offline

Joined: Fri Aug 25, 2006 10:28 pm
Posts: 11
Location: Argentina
Well, I can't get it to work. Let's start from scratch. I decided to
Here is my complete configuration (at least what I think is important):

A2B "local" trunk config:
Code:
LABEL= Trunk local
ADD PREFIX=
REMOVE PREFIX=999
PROVIDER TECH=SIP
PROVIDER IP=127.0.0.1

A2B "local" ratecard config:
Code:
TARIFFNAME=Tarifa-internos
TRUNK=Trunk local

A2B "local" Rate config:
Code:
RATECARD=Tarifa-internos
DIALPREFIX=999
TRUNK=Trunk local


A2B SIP peer config example (/etc/asterisk/additional_a2billing_sip.conf)
Code:
[5334993676]
type=friend
username=5334993676
accountcode=5334993676
regexten=5334993676
callerid=398893830602693
amaflags=billing
secret=2999286698
nat=yes
dtmfmode=RFC2833
qualify=yes
canreinvite=yes
disallow=all
allow=g729
allow=ulaw
allow=alaw
allow=gsm
host=dynamic
context=a2billing
regseconds=0
cancallforward=yes

Context a2billing configuration (in extensions_trixbox.conf)
Code:
[a2billing]
exten => _X.,1,Answer
exten => _X.,2,Wait,2
exten => _X.,3,DeadAGI,a2billing.php
exten => _X.,4,Wait,2
exten => _X.,5,Hangup

Important configs from a2billing.conf:
Code:
use_dnid=NO
sip_iax_friends=NO
switchdialcommand=NO


And now.... the logs files! This is what I get when I place a call from extension 0168140206 to extension 5334993676
Code:
    -- Executing Answer("SIP/0168140206-9e5b", "") in new stack
    -- Executing Wait("SIP/0168140206-9e5b", "2") in new stack
    -- Executing DeadAGI("SIP/0168140206-9e5b", "a2billing.php") in new stack
    -- Launched AGI Script /var/lib/asterisk/agi-bin/a2billing.php
  a2billing.php: line:58 - IDCONFIG : 1
  a2billing.php:
  a2billing.php: line:67 - MODE : standard
  a2billing.php:
  a2billing.php: A2Billing AGI internal configuration:
  a2billing.php: Array
  a2billing.php: (
  a2billing.php:     [debug] => 3
  a2billing.php:     [answer_call] => 1
  a2billing.php:     [logger_enable] => 1
  a2billing.php:     [log_file] => /tmp/a2billing.log
  a2billing.php:     [say_goodbye] =>
  a2billing.php:     [play_menulanguage] =>
  a2billing.php:     [force_language] =>
  a2billing.php:     [intro_prompt] =>
  a2billing.php:     [len_cardnumber] => 10
  a2billing.php:     [len_aliasnumber] => 15
  a2billing.php:     [len_voucher] => 15
  a2billing.php:     [min_credit_2call] => 0
  a2billing.php:     [min_duration_2bill] => 2
  a2billing.php:     [notenoughcredit_cardnumber] => 1
  a2billing.php:     [notenoughcredit_assign_newcardnumber_cid] => 1
  a2billing.php:     [use_dnid] =>
  a2billing.php:     [no_auth_dnid] => Array
  a2billing.php:         (
  a2billing.php:             [0] => 2400
  a2billing.php:             [1] => 2300
  a2billing.php:         )
  a2billing.php:
  a2billing.php:     [number_try] => 3
  a2billing.php:     [say_balance_after_auth] =>
  a2billing.php:     [say_balance_after_call] =>
  a2billing.php:     [say_rateinitial] =>
  a2billing.php:     [say_timetocall] =>
  a2billing.php:     [auto_setcallerid] =>
  a2billing.php:     [force_callerid] =>
  a2billing.php:     [cid_sanitize] =>
  a2billing.php:     [cid_enable] =>
  a2billing.php:     [cid_askpincode_ifnot_callerid] => 1
  a2billing.php:     [cid_auto_create_card] =>
  a2billing.php:     [cid_auto_assign_card_to_cid] => 1
  a2billing.php:     [cid_auto_create_card_typepaid] => POSTPAY
  a2billing.php:     [cid_auto_create_card_credit] => 0
  a2billing.php:     [cid_auto_create_card_credit_limit] => 1000
  a2billing.php:     [cid_auto_create_card_tariffgroup] => 6
  a2billing.php:     [callerid_authentication_over_cardnumber] =>
  a2billing.php:     [sip_iax_friends] =>
  a2billing.php:     [sip_iax_pstn_direct_call_prefix] => 9
  a2billing.php:     [sip_iax_pstn_direct_call] => 1
  a2billing.php:     [extracharge_did] => Array
  a2billing.php:         (
  a2billing.php:             [0] =>
  a2billing.php:         )
  a2billing.php:
  a2billing.php:     [extracharge_fee] => Array
  a2billing.php:         (
  a2billing.php:             [0] =>
  a2billing.php:         )
  a2billing.php:
  a2billing.php:     [dialcommand_param] => |30|HL(%timeout%:61000:30000)
  a2billing.php:     [dialcommand_param_sipiax_friend] => |30|HL(3600000:61000:30000)
  a2billing.php:     [switchdialcommand] =>
  a2billing.php:     [maxtime_tocall_negatif_free_route] => 5400
  a2billing.php:     [send_reminder] =>
  a2billing.php:     [record_call] =>
  a2billing.php:     [monitor_formatfile] => gsm
  a2billing.php:     [base_currency] => ars
  a2billing.php:     [agi_force_currency] =>
  a2billing.php:     [currency_association] => Array
  a2billing.php:         (
  a2billing.php:             [0] => usd:prepaid-dollar
  a2billing.php:             [1] => mxn:pesos
  a2billing.php:             [2] => eur:euro
  a2billing.php:             [3] => ars:pesos
  a2billing.php:             [4] => all:credit
  a2billing.php:         )
  a2billing.php:
  a2billing.php:     [file_conf_enter_destination] => prepaid-enter-dest
  a2billing.php:     [file_conf_enter_menulang] => prepaid-menulang2
  a2billing.php:     [currency_association_internal] => Array
  a2billing.php:         (
  a2billing.php:             [usd] => prepaid-dollar
  a2billing.php:             [mxn] => pesos
  a2billing.php:             [eur] => euro
  a2billing.php:             [ars] => pesos
  a2billing.php:             [all] => credit
  a2billing.php:         )
  a2billing.php:
  a2billing.php: )
  a2billing.php:
  a2billing.php: AGI Request:
  a2billing.php: Array
  a2billing.php: (
  a2billing.php:     [agi_request] => a2billing.php
  a2billing.php:     [agi_channel] => SIP/0168140206-9e5b
  a2billing.php:     [agi_language] => en
  a2billing.php:     [agi_type] => SIP
  a2billing.php:     [agi_uniqueid] => 1156857372.13
  a2billing.php:     [agi_callerid] => 975952314404328
  a2billing.php:     [agi_calleridname] => Natalio
  a2billing.php:     [agi_callingpres] => 0
  a2billing.php:     [agi_callingani2] => 0
  a2billing.php:     [agi_callington] => 0
  a2billing.php:     [agi_callingtns] => 0
  a2billing.php:     [agi_dnid] => 999
  a2billing.php:     [agi_rdnis] => unknown
  a2billing.php:     [agi_context] => a2billing
  a2billing.php:     [agi_extension] => 999
  a2billing.php:     [agi_priority] => 3
  a2billing.php:     [agi_enhanced] => 0.0
  a2billing.php:     [agi_accountcode] => 0168140206
  a2billing.php: )
  a2billing.php:
  a2billing.php: line:490 get_agi_request_parameter = 975952314404328 ; SIP/0168140206-9e5b ; 1156857372.13 ; 0168140206 ; 999
  a2billing.php: line:138 - [ANSWER CALL]
  a2billing.php: line:1470 - SELECT credit, tariff, activated, inuse, simultaccess, typepaid, creditlimit, language, removeinterprefix, redial, enableexpire, UNIX_TIMESTAMP(expirationdate), expiredays, nbused, UNIX_TIMESTAMP(firstusedate), UNIX_TIMESTAMP(cc_card.creationdate), cc_card.currency, cc_card.lastname, cc_card.firstname, cc_card.email, cc_card.uipass, cc_card.id_campaign, cc_card.id, useralias FROM cc_card LEFT JOIN cc_tariffgroup ON tariff=cc_tariffgroup.id WHERE username='0168140206'
  a2billing.php: line:1473 - Array
  a2billing.php: line:519 - UPDATE cc_card SET inuse=inuse+1 WHERE username='0168140206'
  a2billing.php: line:166 - [CHANNEL STATUS : 6 = Line is up]
  a2billing.php: line:170 - [CREDIT STATUS : 7.90000]
  a2billing.php: line:171 - [CREDIT MIN_CREDIT_2CALL : 0]
  a2billing.php: line:544 -  &&  && 3&& 0
    -- Playing 'prepaid-enter-dest' (language 'es')
  a2billing.php: line:551 - RES DTMF :
  a2billing.php: line:571 - DESTINATION ::>
  a2billing.php: line:573 - APPLY_RULES DESTINATION ::>
  a2billing.php: line:166 - [CHANNEL STATUS : 6 = Line is up]
  a2billing.php: line:170 - [CREDIT STATUS : 7.90000]
  a2billing.php: line:171 - [CREDIT MIN_CREDIT_2CALL : 0]
  a2billing.php: line:544 - 0 &&  && 3&& 1
    -- Playing 'prepaid-enter-dest' (language 'es')
  a2billing.php: line:551 - RES DTMF : 9995334993676
  a2billing.php: line:571 - DESTINATION ::> 9995334993676
  a2billing.php: line:573 - APPLY_RULES DESTINATION ::> 9995334993676
  a2billing.php: line:612 - OK - RESFINDRATE::> 1
  a2billing.php: line:634 - RES_ALL_CALCULTIMEOUT ::> 1
  a2billing.php: line:651 - TIMEOUT::> 5400  : minutes=90 - seconds=0
  a2billing.php: line:819 - app_callingcard: Dialing 'SIP/127.0.0.1/5334993676|30|HL(5400000:61000:30000)' with timeout of '5400'.
  a2billing.php:
    -- AGI Script Executing Application: (Dial) Options: (SIP/127.0.0.1/5334993676|30|HL(5400000:61000:30000))
    -- Limit Data for this call:
    -- - timelimit     = 5400000
    -- - play_warning  = 61000
    -- - play_to_caller= yes
    -- - play_to_callee= no
    -- - warning_freq  = 30000
    -- - start_sound   = UNDEF
    -- - warning_sound = timeleft
    -- - end_sound     = UNDEF
    -- Called 127.0.0.1/5334993676
    -- Got SIP response 482 "Loop Detected" back from 127.0.0.1
    -- Now forwarding SIP/0168140206-9e5b to 'Local/5334993676@from-sip-external' (thanks to SIP/127.0.0.1-7d0a)
    -- Executing NoOp("Local/5334993676@from-sip-external-50bc,2", "Received incoming SIP connection from unknown peer to 5334993676") in new stack
    -- Executing Set("Local/5334993676@from-sip-external-50bc,2", "DID=5334993676") in new stack
    -- Executing Goto("Local/5334993676@from-sip-external-50bc,2", "s|1") in new stack
    -- Goto (from-sip-external,s,1)
    -- Executing GotoIf("Local/5334993676@from-sip-external-50bc,2", "0?from-trunk|5334993676|1") in new stack
    -- Executing Set("Local/5334993676@from-sip-external-50bc,2", "TIMEOUT(absolute)=15") in new stack
    -- Channel will hangup at 2006-08-29 13:16:48 UTC.
    -- Executing Answer("Local/5334993676@from-sip-external-50bc,2", "") in new stack
    -- Local/5334993676@from-sip-external-50bc,1 answered SIP/0168140206-9e5b
    -- Executing Wait("Local/5334993676@from-sip-external-50bc,2", "2") in new stack
    -- Executing Playback("Local/5334993676@from-sip-external-50bc,2", "ss-noservice") in new stack
    -- Playing 'ss-noservice' (language 'en')
    -- Executing NoOp("Local/5334993676@from-sip-external-50bc,2", "Hangup") in new stack
    -- Executing Set("Local/5334993676@from-sip-external-50bc,2", "DID=s") in new stack
    -- Executing Goto("Local/5334993676@from-sip-external-50bc,2", "s|1") in new stack
    -- Goto (from-sip-external,s,1)
    -- Executing GotoIf("Local/5334993676@from-sip-external-50bc,2", "0?from-trunk|s|1") in new stack
    -- Executing Set("Local/5334993676@from-sip-external-50bc,2", "TIMEOUT(absolute)=15") in new stack
    -- Channel will hangup at 2006-08-29 13:16:53 UTC.
    -- Executing Answer("Local/5334993676@from-sip-external-50bc,2", "") in new stack
  a2billing.php: line:931 - -> dialstatus : ANSWER, answered time is 5
  a2billing.php:
  a2billing.php: line:706 - INSERT INTO cc_call (uniqueid,sessionid,username,nasipaddress,starttime,sessiontime, calledstation,  terminatecause, stoptime, calledrate, sessionbill, calledcountry, calledsub, destination, id_tariffgroup, id_tariffplan, id_ratecard, id_trunk, src, sipiax, buyrate, buycost) VALUES ('2156857372.13', 'SIP/0168140206-9e5b',  '0168140206', '', CURRENT_TIMESTAMP - INTERVAL 5 SECOND , '5', '9995334993676', 'ANSWER', now(), '0', '-0',  '', '', 'Internos Locales (sin costo)', '1', '5', '5', '4', '975952314404328', '0', '0', '0')
  a2billing.php: line:729 - UPDATE cc_card SET credit= credit+0  , redial='9995334993676' ,  lastuse=now(), nbused=nbused+1 WHERE username='0168140206'
  a2billing.php: line:735 - UPDATE cc_trunk SET secondusedreal = secondusedreal + 5 WHERE id_trunk='4'
  a2billing.php: line:739 - UPDATE cc_tariffplan SET secondusedreal = secondusedreal + 5 WHERE id='5'
  a2billing.php: line:166 - [CHANNEL STATUS : 6 = Line is up]
  a2billing.php: line:170 - [CREDIT STATUS : 7.9]
  a2billing.php: line:171 - [CREDIT MIN_CREDIT_2CALL : 0]
  a2billing.php: line:544 - 0 &&  && 3&& 2
    -- Playing 'prepaid-enter-dest' (language 'es')
  a2billing.php: line:551 - RES DTMF : -1
  a2billing.php: line:571 - DESTINATION ::> -1
  a2billing.php: line:573 - APPLY_RULES DESTINATION ::> -1


My interpretation is that the call is been redirected to context "from-sip-external". Which I detail here:
Code:
[from-sip-external]
;give external sip users congestion and hangup
; Yes. This is _really_ meant to be _. - I know asterisk whinges about it, but
; I do know what I'm doing. This is correct.

exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN})
exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})})
exten => _.,n,Goto(s,1)
exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?from-trunk,${DID},1)
exten => s,n,Set(TIMEOUT(absolute)=15)
exten => s,n,Answer
exten => s,n,Wait(2)
exten => s,n,Playback(ss-noservice)
exten => s,n,Congestion
exten => s,n,Hangup
exten => h,1,NoOp(Hangup)
exten => i,1,NoOp(Invalid)
exten => t,1,NoOp(Timeout)


I hope that someone (gue?) can stay with me :oops: !


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 29, 2006 2:54 pm 
Offline

Joined: Fri Aug 25, 2006 10:28 pm
Posts: 11
Location: Argentina
Me again, now with good news! I get it to work!

After writing my last post, I re-define a local trunk in asterisk, and make a reference from A2B's trunk definition. I get the same results, but finally, I realize that the problem was in my [from-sip-external] context.

So I replaced it with the following definition (extracted from Ptztas post):
Code:
[from-sip-external]
exten => _.,1,Answer()
exten => _.,n,Dial(SIP/${EXTEN},,Tt)
exten => _.,n,Playback(ss-noservice)
exten => _.,n,Hangup
exten => h,1,Hangup()

It seems that the previos from-sip-external dialplan was failing to place a call, maybe becouse of the
Code:
;exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?from-trunk,${DID},1)
;exten => s,n,Set(TIMEOUT(absolute)=15)
that seems to always answer with TIMEOUT.

Now I'll be testing if that definition does not conflicts with "real" external SIP calls.

I hope that kayodea read this and can make it work!
If somebody needs it, I can post the complete configuration of every objects involved.

Salutti and thaks to gue to pointing me in the right direction.[/b]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 29, 2006 4:34 pm 
Offline

Joined: Mon Jun 19, 2006 5:14 pm
Posts: 218
glad to see you got it working. The problem you encountered is based on how freepbx is coded:

To do it "properly" so as not to mess about with the freepbx dialplans do: (check out "incoming routes" in the freepbx interface)

1. the Inbound Routes defines the DID [the number you are calling] and what should happen when the DID is called.
2. enable the variable that allows you to accept calls from unknown source/callers

Essentialy what you are doing is defining what is to happen when someone calls tru you SIP interface for a particular DID. So you allow/not allow unknown callers and then forward the call as defined by the DID. That is what is going on in "Incoming Routes"

In the future you can make the source/trunk/caller that you are calling from known by defining a peer in asterisk sip.conf


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 29, 2006 7:56 pm 
Offline

Joined: Fri Aug 25, 2006 10:28 pm
Posts: 11
Location: Argentina
So, if I correctly understood, I have to create an inbound route that matches all DIDs, or CallerIDs, and pass them out.
But it's not clear to me which context should I use as destination of those incoming calls (should I create one? should I use custom-callingcard?)

In trixbox default configuration, there is a commented context called custom-callingcard:
Code:
; un-comment the 6 lines below to work on incoming DIDs
;[custom-callingcard]
;exten => s,1,Answer
;exten => s,2,Wait,2
;exten => s,3,DeadAGI,a2billing.php
;exten => s,4,Wait,2
;exten => s,5,Hangup

Which seems to be the right context to choose. I'll be testing it in the next hours and let you know the results.

Thanks again gue!
Arigatox


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Hosted Voice Broadcast


All times are UTC


Who is online

Users browsing this forum: No registered users and 23 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group