api.multigen.php 151 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816
  1. <?php
  2. /**
  3. * Most awesome FreeRADIUS support implementation ever
  4. */
  5. class MultiGen {
  6. /**
  7. * Contains system alter.ini config as key=>value
  8. *
  9. * @var array
  10. */
  11. protected $altCfg = array();
  12. /**
  13. * Contains system billing.ini config as key=>value
  14. *
  15. * @var array
  16. */
  17. protected $billCfg = array();
  18. /**
  19. * Contains all stargazer user data
  20. *
  21. * @var array
  22. */
  23. protected $allUserData = array();
  24. /**
  25. * Contains all tariff speeds as tariffname=>speeddata(speeddown/speedup) Kbit/s
  26. *
  27. * @var array
  28. */
  29. protected $tariffSpeeds = array();
  30. /**
  31. * Contains user speed overrides as login=>override speed in Kbit/s
  32. *
  33. * @var array
  34. */
  35. protected $userSpeedOverrides = array();
  36. /**
  37. * Contains array of user switch assigns as login=>asigndata
  38. *
  39. * @var array
  40. */
  41. protected $userSwitchAssigns = array();
  42. /**
  43. * Contains available QinQ data
  44. *
  45. * @var array
  46. */
  47. protected $switchesQinQ = array();
  48. /**
  49. * Contains available users qinq bindings
  50. *
  51. * @var array
  52. */
  53. protected $usersQinQ = array();
  54. /**
  55. * Contains available s-vlans
  56. *
  57. * @var array
  58. */
  59. protected $allSvlan = array();
  60. /**
  61. * Contains all realms
  62. *
  63. * @var array
  64. */
  65. protected $allRealms = array();
  66. /**
  67. * Contains array of available switches as id=>switchdata
  68. *
  69. * @var array
  70. */
  71. protected $allSwitches = array();
  72. /**
  73. * Contains existing users NAS bindings
  74. *
  75. * @var array
  76. */
  77. protected $userNases = array();
  78. /**
  79. * Contains available networks as id=>data
  80. *
  81. * @var array
  82. */
  83. protected $allNetworks = array();
  84. /**
  85. * Contains all users with ext networks assign
  86. *
  87. * @var array
  88. */
  89. protected $netExtUsers = array();
  90. /**
  91. * Contains available NAS servers as id=>data
  92. *
  93. * @var array
  94. */
  95. protected $allNas = array();
  96. /**
  97. * Contains array of NASes served networks as netid=>nasids array
  98. *
  99. * @var array
  100. */
  101. protected $networkNases = array();
  102. /**
  103. * Contains available nethosts as ip=>data
  104. *
  105. * @var array
  106. */
  107. protected $allNetHosts = array();
  108. /**
  109. * Contains array of nethosts to networks bindings like ip=>netid
  110. *
  111. * @var array
  112. */
  113. protected $nethostsNetworks = array();
  114. /**
  115. * Contains list of available NAS attributes presets to generate as id=>data
  116. *
  117. * @var array
  118. */
  119. protected $nasAttributes = array();
  120. /**
  121. * Contains multigen NAS options like usernames types etc as nasid=>options
  122. *
  123. * @var array
  124. */
  125. protected $nasOptions = array();
  126. /**
  127. * Contains previously loaded scenarios attributes as scenario=>username=>attributes
  128. *
  129. * @var array
  130. */
  131. protected $currentAttributes = array();
  132. /**
  133. * Contains previous user states as login=>previous/current/changed state
  134. *
  135. * @var array
  136. */
  137. protected $userStates = array();
  138. /**
  139. * System message helper object placeholder
  140. *
  141. * @var object
  142. */
  143. protected $messages = '';
  144. /**
  145. * Contains available username types as type=>name
  146. *
  147. * @var array
  148. */
  149. protected $usernameTypes = array();
  150. /**
  151. * Contains available nas service handlers as type=>name
  152. *
  153. * @var array
  154. */
  155. protected $serviceTypes = array();
  156. /**
  157. * Contains available operators as operator=>name
  158. *
  159. * @var array
  160. */
  161. protected $operators = array();
  162. /**
  163. * Contains default NAS attributes modifiers as id=>name
  164. *
  165. * @var array
  166. */
  167. protected $attrModifiers = array();
  168. /**
  169. * Contains available reply scenarios as stringid=>name
  170. *
  171. * @var array
  172. */
  173. protected $scenarios = array();
  174. /**
  175. * Contains NAS attributes regeneration stats as nasid=>scenario=>statsdata
  176. *
  177. * @var array
  178. */
  179. protected $scenarioStats = array();
  180. /**
  181. * Contains performance timers and stats
  182. *
  183. * @var array
  184. */
  185. protected $perfStats = array();
  186. /**
  187. * Contains interesting fields from database acct table
  188. *
  189. * @var array
  190. */
  191. protected $acctFieldsRequired = array();
  192. /**
  193. * Contains additional fields from database acct table
  194. *
  195. * @var array
  196. */
  197. protected $acctFieldsAdditional = array();
  198. /**
  199. * Contains preloaded user accounting data
  200. *
  201. * @var array
  202. */
  203. protected $userAcctData = array();
  204. /**
  205. * Contains NAS services templates as nasid=>services data
  206. *
  207. * @var array
  208. */
  209. protected $services = array();
  210. /**
  211. * Contains services names which requires run, like pod or coa
  212. *
  213. * @var array
  214. */
  215. protected $runServices = array();
  216. /**
  217. * User activity detection accuracy flag
  218. *
  219. * @var bool
  220. */
  221. protected $accurateUserActivity = true;
  222. /**
  223. * Is logging enabled may be exported from MULTIGEN_LOGGING option
  224. *
  225. * @var int
  226. */
  227. protected $logging = 0;
  228. /**
  229. * Contains innodb usage/optimization flag from OPTION_INNO
  230. *
  231. * @var int
  232. */
  233. protected $inno = 0;
  234. /**
  235. * Contains unfinished acct flag from OPTION_UNFFLAG
  236. *
  237. * @var int
  238. */
  239. protected $unfinished = 0;
  240. /**
  241. * Contains default accounting display days from OPTION_DAYS
  242. *
  243. * @var int
  244. */
  245. protected $days = 1;
  246. /**
  247. * System caching object instance
  248. *
  249. * @var object
  250. */
  251. protected $cache = '';
  252. /**
  253. * Contains previous accounting traffic stats as login=>data
  254. *
  255. * @var array
  256. */
  257. protected $previousTraffic = array();
  258. /**
  259. * Contains ishimura archived year/month traffic stats for current month
  260. *
  261. * @var array
  262. */
  263. protected $trafficArchive = array();
  264. /**
  265. * Contains current accounting traffic stats as login=>data
  266. *
  267. * @var array
  268. */
  269. protected $currentTraffic = array();
  270. /**
  271. * Contains current stargazer users traffic stats as login=>data D0/U0
  272. *
  273. * @var array
  274. */
  275. protected $usersTraffic = array();
  276. /**
  277. * Contains users current balance cash amount as login=>cash
  278. *
  279. * @var array
  280. */
  281. protected $allUsersCash = array();
  282. /**
  283. * Contains default echo path
  284. *
  285. * @var string
  286. */
  287. protected $echoPath = '/bin/echo';
  288. /**
  289. * Contains default path and options for radclient
  290. *
  291. * @var string
  292. */
  293. protected $radclienPath = '/usr/local/bin/radclient -r 3 -t 1';
  294. /**
  295. * Contains default path to sudo
  296. *
  297. * @var string
  298. */
  299. protected $sudoPath = '/usr/local/bin/sudo';
  300. /**
  301. * Contains default path to printf
  302. *
  303. * @var string
  304. */
  305. protected $printfPath = '/usr/bin/printf';
  306. /**
  307. * Default remote radclient port
  308. *
  309. * @var int
  310. */
  311. protected $remotePort = 3799;
  312. /**
  313. * Ishimura enabled flag
  314. *
  315. * @var int
  316. */
  317. protected $ishimuraFlag = 0;
  318. /**
  319. * Contains default usernames caching timeout in seconds
  320. *
  321. * @var int
  322. */
  323. protected $usernamesCachingTimeout = 0;
  324. /**
  325. * Contains current multigen instance unique ID
  326. *
  327. * @var string
  328. */
  329. protected $instanceId = '';
  330. /**
  331. * stardust process manager instance
  332. *
  333. * @var object
  334. */
  335. protected $stardust = '';
  336. /**
  337. * Mea culpa protected instance
  338. *
  339. * @var object
  340. */
  341. protected $meaCulpa = '';
  342. /**
  343. * Is mea culpa enabled flag?
  344. *
  345. * @var bool
  346. */
  347. protected $meaCulpaFlag = false;
  348. /**
  349. * Contains basic module path
  350. */
  351. const URL_ME = '?module=multigen';
  352. /**
  353. * Contains default user profile link
  354. */
  355. const URL_PROFILE = '?module=userprofile&username=';
  356. /**
  357. * Default radius clients table/view name
  358. */
  359. const CLIENTS = 'mlg_clients';
  360. /**
  361. * Default NAS options table name
  362. */
  363. const NAS_OPTIONS = 'mlg_nasoptions';
  364. /**
  365. * Default services templates table name
  366. */
  367. const NAS_SERVICES = 'mlg_services';
  368. /**
  369. * Default NAS attributes templates table name
  370. */
  371. const NAS_ATTRIBUTES = 'mlg_nasattributes';
  372. /**
  373. * Default accounting table name
  374. */
  375. const NAS_ACCT = 'mlg_acct';
  376. /**
  377. * Default postauth table name
  378. */
  379. const NAS_POSTAUTH = 'mlg_postauth';
  380. /**
  381. * Default traffic aggregation table name
  382. */
  383. const NAS_TRAFFIC = 'mlg_traffic';
  384. /**
  385. * Default previous/current traffic stats table name
  386. */
  387. const NAS_ISHIMURA = 'mlg_ishimura';
  388. /**
  389. * Default user states database table name
  390. */
  391. const USER_STATES = 'mlg_userstates';
  392. /**
  393. * Default scenario tables prefix
  394. */
  395. const SCENARIO_PREFIX = 'mlg_';
  396. /**
  397. * Attributes generation logging option name
  398. */
  399. const OPTION_LOGGING = 'MULTIGEN_LOGGING';
  400. /**
  401. * RADIUS client option name
  402. */
  403. const OPTION_RADCLIENT = 'MULTIGEN_RADCLIENT';
  404. /**
  405. * sudo path option name
  406. */
  407. const OPTION_SUDO = 'SUDO';
  408. /**
  409. * Default inno-db performance fix option name
  410. */
  411. const OPTION_INNO = 'MULTIGEN_MAKE_INNODB_GREAT_AGAIN';
  412. /**
  413. * Default switches QinQ management option name
  414. */
  415. const OPTION_QINQ = 'QINQ_ENABLED';
  416. /**
  417. * Default user switchport assign option name
  418. */
  419. const OPTION_SWASSIGN = 'SWITCHPORT_IN_PROFILE';
  420. /**
  421. * Default universal QinQ management option name
  422. */
  423. const OPTION_UNIVERSALQINQ = 'UNIVERSAL_QINQ_ENABLED';
  424. /**
  425. * Default additional fields option
  426. */
  427. const OPTION_FIELDS = 'MULTIGEN_FIELDSACCT';
  428. /**
  429. * Default unfinished sessions flag option name
  430. */
  431. const OPTION_UNFFLAG = 'MULTIGEN_UNFACCT';
  432. /**
  433. * Default accounting days option name
  434. */
  435. const OPTION_DAYS = 'MULTIGEN_DAYSACCT';
  436. /**
  437. * Default ishimura mech enabling option name
  438. */
  439. const OPTION_ISHIMURA = 'ISHIMURA_ENABLED';
  440. /**
  441. * Usernames cache expiring timeout option name
  442. */
  443. const OPTION_USERNAMESTIMEOUT = 'MULTIGEN_UNTIMEOUT';
  444. /**
  445. * Extended networks option name
  446. */
  447. const OPTION_EXTNETS = 'NETWORKS_EXT';
  448. /**
  449. * Mea maxima culpa coinfig option name
  450. */
  451. const OPTION_CULPA = 'MEACULPA_ENABLED';
  452. /**
  453. * Default log path
  454. */
  455. const LOG_PATH = 'exports/multigen.log';
  456. /**
  457. * Contains default path to PoD scripts queue
  458. */
  459. const POD_PATH = 'exports/pod_queue_';
  460. /**
  461. * Contains default path to CoA scripts queue
  462. */
  463. const COA_PATH = 'exports/coa_queue_';
  464. /**
  465. * Default RemoteAPI lock name
  466. */
  467. const MULTIGEN_PID = 'MULTIGEN';
  468. /**
  469. * Creates new MultiGen instance
  470. *
  471. * @return void
  472. */
  473. public function __construct() {
  474. $this->loadConfigs();
  475. $this->setOptions();
  476. $this->initMessages();
  477. $this->initStarDust();
  478. $this->initCache();
  479. $this->loadNases();
  480. $this->loadNasAttributes();
  481. $this->loadNasOptions();
  482. $this->loadNasServices();
  483. }
  484. /**
  485. * Loads huge amounts of data, required only for attributes generation/processing
  486. *
  487. * @return void
  488. */
  489. protected function loadHugeRegenData() {
  490. $this->loadUserData();
  491. $this->loadNethosts();
  492. $this->loadNetworks();
  493. $this->loadTariffSpeeds();
  494. $this->loadUserSpeedOverrides();
  495. $this->preprocessUserData();
  496. $this->loadSwitches();
  497. $this->loadSwithchAssigns();
  498. $this->loadAllQinQ();
  499. $this->loadScenarios();
  500. $this->loadUserStates();
  501. $this->loadNetExtUsers();
  502. $this->loadMeaCulpa();
  503. }
  504. /**
  505. * Loads reqired configss
  506. *
  507. * @global object $ubillingConfig
  508. *
  509. * @return void
  510. */
  511. protected function loadConfigs() {
  512. global $ubillingConfig;
  513. $this->altCfg = $ubillingConfig->getAlter();
  514. $this->billCfg = $ubillingConfig->getBilling();
  515. }
  516. /**
  517. * Sets some basic options for further usage
  518. *
  519. * @return void
  520. */
  521. protected function setOptions() {
  522. if (isset($this->altCfg[self::OPTION_LOGGING])) {
  523. if ($this->altCfg[self::OPTION_LOGGING]) {
  524. $this->logging = $this->altCfg[self::OPTION_LOGGING];
  525. }
  526. }
  527. if (isset($this->altCfg[self::OPTION_RADCLIENT])) {
  528. $this->radclienPath = $this->altCfg[self::OPTION_RADCLIENT];
  529. }
  530. if (isset($this->billCfg[self::OPTION_SUDO])) {
  531. $this->sudoPath = $this->billCfg[self::OPTION_SUDO];
  532. }
  533. if (isset($this->altCfg[self::OPTION_INNO])) {
  534. if ($this->altCfg[self::OPTION_INNO]) {
  535. $this->inno = $this->altCfg[self::OPTION_INNO];
  536. }
  537. }
  538. if (isset($this->altCfg[self::OPTION_UNFFLAG])) {
  539. if ($this->altCfg[self::OPTION_UNFFLAG]) {
  540. $this->unfinished = $this->altCfg[self::OPTION_UNFFLAG];
  541. }
  542. }
  543. if (isset($this->altCfg[self::OPTION_DAYS])) {
  544. if ($this->altCfg[self::OPTION_DAYS]) {
  545. $this->days = $this->altCfg[self::OPTION_DAYS];
  546. }
  547. }
  548. if (isset($this->altCfg[self::OPTION_ISHIMURA])) {
  549. if ($this->altCfg[self::OPTION_ISHIMURA]) {
  550. $this->ishimuraFlag = $this->altCfg[self::OPTION_ISHIMURA];
  551. }
  552. }
  553. if (isset($this->altCfg[self::OPTION_USERNAMESTIMEOUT])) {
  554. if ($this->altCfg[self::OPTION_USERNAMESTIMEOUT]) {
  555. $this->usernamesCachingTimeout = $this->altCfg[self::OPTION_USERNAMESTIMEOUT];
  556. }
  557. }
  558. $this->instanceId = 'MLG' . zb_rand_string(8);
  559. $this->usernameTypes = array(
  560. 'login' => __('Login'),
  561. 'ip' => __('IP'),
  562. 'mac' => __('MAC') . ' ' . __('default'),
  563. 'macup' => __('MAC') . ' ' . __('upper case'),
  564. 'macju' => __('MAC') . ' ' . __('JunOS like')
  565. );
  566. //some additional username types
  567. if ((isset($this->altCfg[self::OPTION_SWASSIGN])) AND ( isset($this->altCfg[self::OPTION_QINQ]))) {
  568. if (($this->altCfg[self::OPTION_SWASSIGN]) AND ( $this->altCfg[self::OPTION_QINQ])) {
  569. $this->usernameTypes['qinq'] = __('QinQ') . ' ' . __('default');
  570. $this->usernameTypes['qinqju'] = __('QinQ') . ' ' . __('JunOS like');
  571. }
  572. }
  573. // quia peccavi nimis
  574. // cogitatione, verbo
  575. // opere et omissione
  576. if (isset($this->altCfg[self::OPTION_CULPA])) {
  577. if ($this->altCfg[self::OPTION_CULPA]) {
  578. $this->usernameTypes['meaculpa'] = __('Mea culpa');
  579. $this->meaCulpaFlag = true;
  580. }
  581. }
  582. $this->serviceTypes = array(
  583. 'none' => __('No'),
  584. 'coa' => __('CoA'),
  585. 'pod' => __('PoD'),
  586. 'podcoa' => __('PoD') . '+' . __('CoA')
  587. );
  588. $this->scenarios = array(
  589. 'check' => 'check',
  590. 'reply' => 'reply',
  591. 'groupreply' => 'groupreply'
  592. );
  593. $this->attrModifiers = array(
  594. 'all' => __('All'),
  595. 'active' => __('Active'),
  596. 'inactive' => __('Inactive')
  597. );
  598. $this->operators = array(
  599. '=' => '=',
  600. ':=' => ':=',
  601. '==' => '==',
  602. '+=' => '+=',
  603. '!=' => '!=',
  604. '>' => '>',
  605. '>=' => '>=',
  606. '<=' => '<=',
  607. '=~' => '=~',
  608. '!~' => '!~',
  609. '=*' => '=*',
  610. '!*' => '!*',
  611. );
  612. $this->acctFieldsRequired = array(
  613. 'acctsessionid',
  614. 'username',
  615. 'nasipaddress',
  616. 'nasportid',
  617. 'acctstarttime',
  618. 'acctstoptime',
  619. 'acctinputoctets',
  620. 'acctoutputoctets',
  621. 'framedipaddress',
  622. 'acctterminatecause'
  623. );
  624. if (isset($this->altCfg[self::OPTION_FIELDS])) {
  625. if ($this->altCfg[self::OPTION_FIELDS]) {
  626. $this->acctFieldsAdditional = explode(',', $this->altCfg[self::OPTION_FIELDS]);
  627. }
  628. }
  629. }
  630. /**
  631. * Inits system message helper for further usage
  632. *
  633. * @return void
  634. */
  635. protected function initMessages() {
  636. $this->messages = new UbillingMessageHelper();
  637. }
  638. /**
  639. * Inits system caching object for further usage
  640. *
  641. * @return void
  642. */
  643. protected function initCache() {
  644. $this->cache = new UbillingCache();
  645. }
  646. /**
  647. * Inits process manager
  648. *
  649. * @return void
  650. */
  651. protected function initStarDust() {
  652. $this->stardust = new StarDust(self::MULTIGEN_PID);
  653. }
  654. /**
  655. * Loads all existing users data from database
  656. *
  657. * @return void
  658. */
  659. protected function loadUserData() {
  660. $this->allUserData = zb_UserGetAllData();
  661. }
  662. /**
  663. * Loads all existing users data from database
  664. *
  665. * @return void
  666. */
  667. protected function loadUserCash() {
  668. $this->allUsersCash = zb_UserGetAllBalance();
  669. }
  670. /**
  671. * Loads existing tariffs speeds from database
  672. *
  673. * @return void
  674. */
  675. protected function loadTariffSpeeds() {
  676. $this->tariffSpeeds = zb_TariffGetAllSpeeds();
  677. }
  678. /**
  679. * Loads user speed overrides if they assigned for user
  680. *
  681. * @return void
  682. */
  683. protected function loadUserSpeedOverrides() {
  684. $speedOverrides_q = "SELECT * from `userspeeds` WHERE `speed` NOT LIKE '0';";
  685. $rawOverrides = simple_queryall($speedOverrides_q);
  686. if (!empty($rawOverrides)) {
  687. foreach ($rawOverrides as $io => $each) {
  688. $this->userSpeedOverrides[$each['login']] = $each['speed'];
  689. }
  690. }
  691. }
  692. /**
  693. * Loads switch port assigns from database
  694. *
  695. * @return void
  696. */
  697. protected function loadSwithchAssigns() {
  698. if (@$this->altCfg[self::OPTION_SWASSIGN]) {
  699. $query = "SELECT * from `switchportassign`";
  700. $all = simple_queryall($query);
  701. if (!empty($all)) {
  702. foreach ($all as $io => $each) {
  703. $this->userSwitchAssigns[$each['login']] = $each;
  704. }
  705. }
  706. }
  707. }
  708. /**
  709. * Loads switches QinQ data from database
  710. *
  711. * @return void
  712. */
  713. protected function loadAllQinQ() {
  714. if ((@$this->altCfg[self::OPTION_QINQ]) AND ( @$this->altCfg[self::OPTION_SWASSIGN])) {
  715. $qinq = new SwitchesQinQ();
  716. $this->switchesQinQ = $qinq->getAllQinQ();
  717. }
  718. if (@$this->altCfg[self::OPTION_UNIVERSALQINQ]) {
  719. $universalqinq = new UniversalQINQ();
  720. $this->usersQinQ = $universalqinq->getAll();
  721. $svlanObj = new VlanManagement();
  722. $this->allSvlan = $svlanObj->getAllSvlan();
  723. $this->allRealms = $svlanObj->getAllRealms();
  724. }
  725. }
  726. /**
  727. * Loads all existing switches data from database
  728. *
  729. * @return void
  730. */
  731. protected function loadSwitches() {
  732. $switchesTmp = zb_SwitchesGetAll();
  733. if (!empty($switchesTmp)) {
  734. foreach ($switchesTmp as $io => $each) {
  735. $this->allSwitches[$each['id']] = $each;
  736. }
  737. }
  738. }
  739. /**
  740. * Prepares user to NAS bindings array
  741. *
  742. * @return void
  743. */
  744. protected function preprocessUserData() {
  745. if (!empty($this->allUserData)) {
  746. foreach ($this->allUserData as $io => $each) {
  747. $userIP = $each['ip'];
  748. if (isset($this->nethostsNetworks[$userIP])) {
  749. if (isset($this->networkNases[$this->nethostsNetworks[$userIP]])) {
  750. $userNases = $this->networkNases[$this->nethostsNetworks[$userIP]];
  751. $this->userNases[$each['login']] = $userNases;
  752. }
  753. }
  754. }
  755. }
  756. }
  757. /**
  758. * Loads existing networks from database
  759. *
  760. * @return void
  761. */
  762. protected function loadNetworks() {
  763. $networksRaw = multinet_get_all_networks();
  764. if (!empty($networksRaw)) {
  765. foreach ($networksRaw as $io => $each) {
  766. $this->allNetworks[$each['id']] = $each;
  767. }
  768. }
  769. }
  770. /**
  771. * Loads users extended networks data
  772. *
  773. * @return void
  774. */
  775. protected function loadNetExtUsers() {
  776. if (isset($this->altCfg[self::OPTION_EXTNETS])) {
  777. if ($this->altCfg[self::OPTION_EXTNETS]) {
  778. $netExtUsers_q = "SELECT * from `netextpools` WHERE `login` <> '';";
  779. $rawNetExtUsers = simple_queryall($netExtUsers_q);
  780. if (!empty($rawNetExtUsers)) {
  781. foreach ($rawNetExtUsers as $io => $each) {
  782. $this->netExtUsers[$each['login']] = $each['pool'] . "/" . $each['netmask'];
  783. }
  784. }
  785. }
  786. }
  787. }
  788. /**
  789. * Loads mea culpa instance for further usage
  790. *
  791. * @return void
  792. */
  793. protected function loadMeaCulpa() {
  794. if ($this->meaCulpaFlag) {
  795. $this->meaCulpa = new MeaCulpa();
  796. }
  797. }
  798. /**
  799. * Loads existing NAS servers from database
  800. *
  801. * @return void
  802. */
  803. protected function loadNases() {
  804. $nasesRaw = zb_NasGetAllData();
  805. if (!empty($nasesRaw)) {
  806. foreach ($nasesRaw as $io => $each) {
  807. $this->allNas[$each['id']] = $each;
  808. $this->networkNases[$each['netid']][$each['id']] = $each['id'];
  809. }
  810. }
  811. }
  812. /**
  813. * Loads existing NAS servers attributes generation optionss
  814. *
  815. * @return void
  816. */
  817. protected function loadNasAttributes() {
  818. $query = "SELECT * from `" . self::NAS_ATTRIBUTES . "`";
  819. $all = simple_queryall($query);
  820. if (!empty($all)) {
  821. foreach ($all as $io => $each) {
  822. $this->nasAttributes[$each['id']] = $each;
  823. }
  824. }
  825. }
  826. /**
  827. * Loads previous user states from database
  828. *
  829. * @return void
  830. */
  831. protected function loadUserStates() {
  832. $query = "SELECT * from `" . self::USER_STATES . "`";
  833. $all = simple_queryall($query);
  834. if (!empty($all)) {
  835. foreach ($all as $io => $each) {
  836. $this->userStates[$each['login']]['previous'] = $each['state'];
  837. $this->userStates[$each['login']]['current'] = '';
  838. $this->userStates[$each['login']]['changed'] = '';
  839. }
  840. }
  841. }
  842. /**
  843. * Loads multigen NAS options from database
  844. *
  845. * @return void
  846. */
  847. protected function loadNasOptions() {
  848. $query = "SELECT * from `" . self::NAS_OPTIONS . "`";
  849. $all = simple_queryall($query);
  850. if (!empty($all)) {
  851. foreach ($all as $io => $each) {
  852. $this->nasOptions[$each['nasid']] = $each;
  853. }
  854. }
  855. }
  856. /**
  857. * Loads NAS services presets
  858. *
  859. * @return void
  860. */
  861. protected function loadNasServices() {
  862. $query = "SELECT * from `" . self::NAS_SERVICES . "`";
  863. $all = simple_queryall($query);
  864. if (!empty($all)) {
  865. foreach ($all as $io => $each) {
  866. $this->services[$each['nasid']] = $each;
  867. }
  868. }
  869. }
  870. /**
  871. * Loads existing nethosts from database
  872. *
  873. * @return void
  874. */
  875. protected function loadNethosts() {
  876. $query = "SELECT * from `nethosts`";
  877. $nethostsRaw = simple_queryall($query);
  878. if (!empty($nethostsRaw)) {
  879. foreach ($nethostsRaw as $io => $each) {
  880. $this->allNetHosts[$each['ip']] = $each;
  881. $this->nethostsNetworks[$each['ip']] = $each['netid'];
  882. }
  883. }
  884. }
  885. /**
  886. * Loads existing scenarios attributes
  887. *
  888. * @return void
  889. */
  890. protected function loadScenarios() {
  891. if (!empty($this->scenarios)) {
  892. foreach ($this->scenarios as $scenarioId => $scenarioName) {
  893. $query = "SELECT * from `" . self::SCENARIO_PREFIX . $scenarioId . "`";
  894. $all = simple_queryall($query);
  895. if (!empty($all)) {
  896. foreach ($all as $io => $each) {
  897. $this->currentAttributes[$scenarioId][$each['username']][$each['attribute']]['name'] = $each['attribute'];
  898. $this->currentAttributes[$scenarioId][$each['username']][$each['attribute']]['value'] = $each['value'];
  899. $this->currentAttributes[$scenarioId][$each['username']][$each['attribute']]['op'] = $each['op'];
  900. }
  901. }
  902. }
  903. }
  904. }
  905. /**
  906. * Loading some accounting data from database
  907. *
  908. * @return void
  909. */
  910. protected function loadAcctData() {
  911. $fieldsList = implode(', ', $this->acctFieldsRequired);
  912. if (!empty($this->acctFieldsAdditional)) {
  913. $fieldsList .= ', ' . implode(', ', $this->acctFieldsAdditional);
  914. }
  915. if (wf_CheckGet(array('datefrom', 'dateto'))) {
  916. $searchDateFrom = mysql_real_escape_string($_GET['datefrom']);
  917. $searchDateTo = mysql_real_escape_string($_GET['dateto']);
  918. } else {
  919. $curTime = time();
  920. $dayAgo = $curTime - (86400 * $this->days);
  921. $dayAgo = date("Y-m-d", $dayAgo);
  922. $dayTomorrow = $curTime + 86400;
  923. $dayTomorrow = date("Y-m-d", $dayTomorrow);
  924. $searchDateFrom = $dayAgo;
  925. $searchDateTo = $dayTomorrow;
  926. }
  927. if (wf_CheckGet(array('showunfinished'))) {
  928. $unfQueryfilter = "AND `acctstoptime` IS NULL ";
  929. } else {
  930. $unfQueryfilter = '';
  931. }
  932. if (wf_CheckGet(array('lastsessions'))) {
  933. $query = "SELECT * FROM `" . self::NAS_ACCT . "` GROUP BY `username` DESC ORDER BY `acctstarttime`;";
  934. } else {
  935. $query = "SELECT " . $fieldsList . " FROM `" . self::NAS_ACCT . "` WHERE `acctstarttime` BETWEEN '" . $searchDateFrom . "' AND '" . $searchDateTo . "'"
  936. . " " . $unfQueryfilter . " ORDER BY `radacctid` DESC ;";
  937. }
  938. $this->userAcctData = simple_queryall($query);
  939. }
  940. /**
  941. * Logs data if logging is enabled
  942. *
  943. * @param string $data
  944. * @param int $logLevel
  945. *
  946. * @return void
  947. */
  948. protected function logEvent($data, $logLevel = 1) {
  949. if ($this->logging) {
  950. if ($this->logging >= $logLevel) {
  951. $curDate = curdatetime();
  952. $logData = $curDate . ' ' . $data . "\n";
  953. file_put_contents(self::LOG_PATH, $logData, FILE_APPEND);
  954. }
  955. }
  956. }
  957. /**
  958. * Renders NAS options editing form
  959. *
  960. * @param int $nasId
  961. *
  962. * @return string
  963. */
  964. public function renderNasOptionsEditForm($nasId) {
  965. $result = '';
  966. $nasId = vf($nasId, 3);
  967. if (isset($this->allNas[$nasId])) {
  968. $onlyActiveParams = array('1' => __('Yes'), '0' => __('No'));
  969. $inputs = wf_Selector('editnasusername', $this->usernameTypes, __('Username override'), @$this->nasOptions[$nasId]['usernametype'], false) . ' ';
  970. $inputs .= wf_Selector('editnasservice', $this->serviceTypes, __('Service'), @$this->nasOptions[$nasId]['service'], false) . ' ';
  971. $inputs .= wf_Selector('editnasonlyactive', $onlyActiveParams, __('Only active users'), @$this->nasOptions[$nasId]['onlyactive'], false) . ' ';
  972. $nasPort = @$this->nasOptions[$nasId]['port'];
  973. $nasPort = (!empty($nasPort)) ? $nasPort : $this->remotePort;
  974. $inputs .= wf_TextInput('editnasport', __('Port'), $nasPort, false, 6, 'digits') . ' ';
  975. $inputs .= wf_HiddenInput('editnasid', $nasId);
  976. $inputs .= wf_Submit(__('Save'));
  977. $result .= wf_Form(self::URL_ME . '&editnasoptions=' . $nasId, 'POST', $inputs, 'glamour');
  978. } else {
  979. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('NAS not exists'), 'error');
  980. }
  981. return ($result);
  982. }
  983. /**
  984. * Checks is NAS basically configured?
  985. *
  986. * @param int $nasId
  987. *
  988. * @return bool
  989. */
  990. public function nasHaveOptions($nasId) {
  991. $result = false;
  992. $nasId = vf($nasId, 3);
  993. if (isset($this->allNas[$nasId])) {
  994. if (isset($this->nasOptions[$nasId])) {
  995. $result = true;
  996. }
  997. }
  998. return ($result);
  999. }
  1000. /**
  1001. * Saves NAS basic options
  1002. *
  1003. * @return void/string on error
  1004. */
  1005. public function saveNasOptions() {
  1006. $result = '';
  1007. if (wf_CheckPost(array('editnasid', 'editnasusername', 'editnasservice', 'editnasport'))) {
  1008. $nasId = vf($_POST['editnasid'], 3);
  1009. if (isset($this->allNas[$nasId])) {
  1010. $newUserName = $_POST['editnasusername'];
  1011. $newService = $_POST['editnasservice'];
  1012. $newOnlyActive = $_POST['editnasonlyactive'];
  1013. $newPort = $_POST['editnasport'];
  1014. //some NAS options already exists
  1015. if (isset($this->nasOptions[$nasId])) {
  1016. $currentNasOptions = $this->nasOptions[$nasId];
  1017. $currentRecordId = $currentNasOptions['id'];
  1018. $where = "WHERE `id`='" . $currentRecordId . "'";
  1019. if ($currentNasOptions['usernametype'] != $newUserName) {
  1020. simple_update_field(self::NAS_OPTIONS, 'usernametype', $newUserName, $where);
  1021. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE USERNAME `' . $newUserName . '`');
  1022. }
  1023. if ($currentNasOptions['service'] != $newService) {
  1024. simple_update_field(self::NAS_OPTIONS, 'service', $newService, $where);
  1025. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE SERVICE `' . $newService . '`');
  1026. }
  1027. if ($currentNasOptions['onlyactive'] != $newOnlyActive) {
  1028. simple_update_field(self::NAS_OPTIONS, 'onlyactive', $newOnlyActive, $where);
  1029. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE ONLYACTIVE `' . $newOnlyActive . '`');
  1030. }
  1031. if ($currentNasOptions['port'] != $newPort) {
  1032. simple_update_field(self::NAS_OPTIONS, 'port', $newPort, $where);
  1033. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE PORT `' . $newPort . '`');
  1034. }
  1035. } else {
  1036. //new NAS options creation
  1037. $newUserName_f = mysql_real_escape_string($newUserName);
  1038. $newService_f = mysql_real_escape_string($newService);
  1039. $newOnlyActive_f = mysql_real_escape_string($newOnlyActive);
  1040. $newPort_f = vf($newPort, 3);
  1041. $quyery = "INSERT INTO `" . self::NAS_OPTIONS . "` (`id`,`nasid`,`usernametype`,`service`,`onlyactive`,`port`) VALUES "
  1042. . "(NULL,'" . $nasId . "','" . $newUserName_f . "','" . $newService_f . "','" . $newOnlyActive_f . "','" . $newPort_f . "');";
  1043. nr_query($quyery);
  1044. log_register('MULTIGEN NAS [' . $nasId . '] CREATE USERNAME `' . $newUserName . '` SERVICE `' . $newService . '` ONLYAACTIVE `' . $newOnlyActive . '` PORT `' . $newPort . '`');
  1045. }
  1046. } else {
  1047. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  1048. }
  1049. }
  1050. return ($result);
  1051. }
  1052. /**
  1053. * Saves NAS services templates
  1054. *
  1055. * @return void/string on error
  1056. */
  1057. public function saveNasServices() {
  1058. $result = '';
  1059. if (wf_CheckPost(array('newnasservicesid'))) {
  1060. $nasId = vf($_POST['newnasservicesid'], 3);
  1061. if (isset($this->allNas[$nasId])) {
  1062. $newPod = $_POST['newnasservicepod'];
  1063. $newCoaConnect = $_POST['newnasservicecoaconnect'];
  1064. $newCoaDisconnect = $_POST['newnasservicecoadisconnect'];
  1065. //some NAS services already exists
  1066. if (isset($this->services[$nasId])) {
  1067. $currentNasServices = $this->services[$nasId];
  1068. $currentRecordId = $currentNasServices['id'];
  1069. $where = "WHERE `id`='" . $currentRecordId . "'";
  1070. //update pod script template
  1071. if ($currentNasServices['pod'] != $newPod) {
  1072. simple_update_field(self::NAS_SERVICES, 'pod', $newPod, $where);
  1073. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE SERVICE POD');
  1074. }
  1075. //update coa connect script template
  1076. if ($currentNasServices['coaconnect'] != $newCoaConnect) {
  1077. simple_update_field(self::NAS_SERVICES, 'coaconnect', $newCoaConnect, $where);
  1078. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE SERVICE COACONNECT');
  1079. }
  1080. //update coa disconnect script template
  1081. if ($currentNasServices['coadisconnect'] != $newCoaDisconnect) {
  1082. simple_update_field(self::NAS_SERVICES, 'coadisconnect', $newCoaDisconnect, $where);
  1083. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE SERVICE COADISCONNECT');
  1084. }
  1085. } else {
  1086. //new NAS services creation
  1087. $newPod_f = mysql_real_escape_string($newPod);
  1088. $newCoaConnect_f = mysql_real_escape_string($newCoaConnect);
  1089. $newCoaDisconnect_f = mysql_real_escape_string($newCoaDisconnect);
  1090. $quyery = "INSERT INTO `" . self::NAS_SERVICES . "` (`id`,`nasid`,`pod`,`coaconnect`,`coadisconnect`) VALUES "
  1091. . "(NULL,'" . $nasId . "','" . $newPod_f . "','" . $newCoaConnect_f . "','" . $newCoaDisconnect_f . "');";
  1092. nr_query($quyery);
  1093. log_register('MULTIGEN NAS [' . $nasId . '] CREATE SERVICES');
  1094. }
  1095. } else {
  1096. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  1097. }
  1098. }
  1099. return ($result);
  1100. }
  1101. /**
  1102. * Returns list of attribute presets for some NAS
  1103. *
  1104. * @param int $nasId
  1105. *
  1106. * @return array
  1107. */
  1108. protected function getNasAttributes($nasId) {
  1109. $result = array();
  1110. if (!empty($this->nasAttributes)) {
  1111. foreach ($this->nasAttributes as $io => $each) {
  1112. if ($each['nasid'] == $nasId) {
  1113. $result[$io] = $each;
  1114. }
  1115. }
  1116. }
  1117. return ($result);
  1118. }
  1119. /**
  1120. * Returns list of services for some NAS
  1121. *
  1122. * @param int $nasId
  1123. *
  1124. * @return array
  1125. */
  1126. protected function getNasServices($nasId) {
  1127. $result = array();
  1128. if (!empty($this->services)) {
  1129. foreach ($this->services as $io => $each) {
  1130. if ($each['nasid'] == $nasId) {
  1131. $result[$io] = $each;
  1132. }
  1133. }
  1134. }
  1135. return ($result);
  1136. }
  1137. /**
  1138. * Deletes some attribute preset
  1139. *
  1140. * @param int $attributeId
  1141. *
  1142. * @return void/string on error
  1143. */
  1144. public function deleteNasAttribute($attributeId) {
  1145. $result = '';
  1146. $attributeId = vf($attributeId, 3);
  1147. if (isset($this->nasAttributes[$attributeId])) {
  1148. $attributeData = $this->nasAttributes[$attributeId];
  1149. $query = "DELETE from `" . self::NAS_ATTRIBUTES . "` WHERE `id`='" . $attributeId . "';";
  1150. nr_query($query);
  1151. log_register('MULTIGEN ATTRIBUTE `' . $attributeData['attribute'] . '` DELETE [' . $attributeId . ']');
  1152. } else {
  1153. $result .= __('Something went wrong') . ': ' . __('not existing attribute');
  1154. }
  1155. return ($result);
  1156. }
  1157. /**
  1158. * Flushes all attributes for all scenarios
  1159. *
  1160. * @return void
  1161. */
  1162. public function flushAllScenarios() {
  1163. if (!empty($this->scenarios)) {
  1164. foreach ($this->scenarios as $scenarioId => $scenarioName) {
  1165. $query = "TRUNCATE TABLE `" . self::SCENARIO_PREFIX . $scenarioId . "`;";
  1166. nr_query($query);
  1167. log_register('MULTIGEN FLUSH SCENARIO `' . $scenarioId . '`');
  1168. }
  1169. }
  1170. }
  1171. /**
  1172. * Performs cleanup of accounting data for some period
  1173. *
  1174. * @param int $days
  1175. * @param int $unfinished
  1176. *
  1177. * @return void
  1178. */
  1179. public function cleanupAccounting($daysCount = 0, $unfinished = 0) {
  1180. $daysCount = ubRouting::filters($daysCount, 'int');
  1181. if ($daysCount) {
  1182. $intervalq = "<= NOW() - INTERVAL " . $daysCount . " DAY ";
  1183. //old finished sessions, accounting data
  1184. $query = "DELETE FROM `" . self::NAS_ACCT . "` WHERE `acctstarttime` " . $intervalq . " AND `acctstoptime` IS NOT NULL";
  1185. nr_query($query);
  1186. //postauth
  1187. $query = "DELETE FROM `" . self::NAS_POSTAUTH . "` WHERE `authdate` " . $intervalq;
  1188. nr_query($query);
  1189. if ($unfinished) {
  1190. //old unfinished sessions (seems its dead)
  1191. $query = "DELETE FROM `" . self::NAS_ACCT . "` WHERE `acctupdatetime` " . $intervalq . " AND `acctstoptime` IS NULL";
  1192. nr_query($query);
  1193. }
  1194. log_register('MULTIGEN ACCOUNTING CLEANUP `' . $daysCount . '` DAYS');
  1195. }
  1196. }
  1197. /**
  1198. * Renders list of flushed scenarios
  1199. *
  1200. * @return string
  1201. */
  1202. public function renderFlushAllScenariosNotice() {
  1203. $result = '';
  1204. if (!empty($this->scenarios)) {
  1205. foreach ($this->scenarios as $scenarioId => $scenarioName) {
  1206. $result .= $this->messages->getStyledMessage(__('All attributes in scenario was deleted') . ': ' . $scenarioId, 'error');
  1207. }
  1208. }
  1209. return ($result);
  1210. }
  1211. /**
  1212. * Renders list of available attributes for some NAS
  1213. *
  1214. * @param int $nasId
  1215. *
  1216. * @return string
  1217. */
  1218. public function renderNasAttributesList($nasId) {
  1219. $result = '';
  1220. $nasId = vf($nasId, 3);
  1221. if (isset($this->allNas[$nasId])) {
  1222. $currentAtrributes = $this->getNasAttributes($nasId);
  1223. if (!empty($currentAtrributes)) {
  1224. $cells = wf_TableCell(__('Users'));
  1225. $cells .= wf_TableCell(__('Scenario'));
  1226. $cells .= wf_TableCell(__('Attribute'));
  1227. $cells .= wf_TableCell(__('Operator'));
  1228. $cells .= wf_TableCell(__('Value'));
  1229. $cells .= wf_TableCell(__('Actions'));
  1230. $rows = wf_TableRow($cells, 'row1');
  1231. foreach ($currentAtrributes as $io => $each) {
  1232. $cells = wf_TableCell($this->attrModifiers[$each['modifier']]);
  1233. $cells .= wf_TableCell($each['scenario']);
  1234. $cells .= wf_TableCell($each['attribute']);
  1235. $cells .= wf_TableCell($each['operator']);
  1236. $cells .= wf_TableCell($each['content']);
  1237. $attributeControls = wf_JSAlert(self::URL_ME . '&editnasoptions=' . $nasId . '&deleteattributeid=' . $each['id'], web_delete_icon(), $this->messages->getDeleteAlert()) . ' ';
  1238. $attributeControls .= wf_modalAuto(web_edit_icon(), __('Edit'), $this->renderAttributeTemplateEditForm($each['id']));
  1239. $cells .= wf_TableCell($attributeControls);
  1240. $rows .= wf_TableRow($cells, 'row5');
  1241. }
  1242. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  1243. } else {
  1244. $result .= $this->messages->getStyledMessage(__('Nothing to show'), 'warning');
  1245. }
  1246. } else {
  1247. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('NAS not exists'), 'error');
  1248. }
  1249. return ($result);
  1250. }
  1251. /**
  1252. * Renders NAS attributes creation form
  1253. *
  1254. * @param int $nasId
  1255. *
  1256. * @return string
  1257. */
  1258. public function renderNasAttributesCreateForm($nasId) {
  1259. $result = '';
  1260. $nasId = vf($nasId, 3);
  1261. if (isset($this->allNas[$nasId])) {
  1262. $inputs = '';
  1263. $inputs .= wf_Selector('newmodifier', $this->attrModifiers, __('Users'), '', false) . ' ';
  1264. $inputs .= wf_Selector('newscenario', $this->scenarios, __('Scenario'), '', false) . ' ';
  1265. $inputs .= wf_TextInput('newattribute', __('Attribute'), '', false, 20) . ' ';
  1266. $inputs .= wf_Selector('newoperator', $this->operators, __('Operator'), '', false) . ' ';
  1267. $inputs .= wf_TextInput('newcontent', __('Value'), '', false, 20) . ' ';
  1268. $inputs .= wf_HiddenInput('newattributenasid', $nasId);
  1269. $inputs .= wf_Submit(__('Create'));
  1270. //form assembly
  1271. $result .= wf_Form(self::URL_ME . '&editnasoptions=' . $nasId, 'POST', $inputs, 'glamour');
  1272. } else {
  1273. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('NAS not exists'), 'error');
  1274. }
  1275. return ($result);
  1276. }
  1277. /**
  1278. * Renders existing NAS attribute template editing forms
  1279. *
  1280. * @param int $attributeId
  1281. *
  1282. * @return string
  1283. */
  1284. public function renderAttributeTemplateEditForm($attributeId) {
  1285. $result = '';
  1286. $attributeId = vf($attributeId, 3);
  1287. if (isset($this->nasAttributes[$attributeId])) {
  1288. $attributeData = $this->nasAttributes[$attributeId];
  1289. $nasId = $attributeData['nasid'];
  1290. $inputs = '';
  1291. $inputs .= wf_Selector('chmodifier', $this->attrModifiers, __('Users'), $attributeData['modifier'], false) . ' ';
  1292. $inputs .= wf_Selector('chscenario', $this->scenarios, __('Scenario'), $attributeData['scenario'], false) . ' ';
  1293. $inputs .= wf_TextInput('chattribute', __('Attribute'), $attributeData['attribute'], false, 20) . ' ';
  1294. $inputs .= wf_Selector('choperator', $this->operators, __('Operator'), $attributeData['operator'], false) . ' ';
  1295. $currentContent = htmlspecialchars($attributeData['content']);
  1296. $inputs .= wf_TextInput('chcontent', __('Value'), $currentContent, false, 20) . ' ';
  1297. $inputs .= wf_HiddenInput('chattributenasid', $nasId);
  1298. $inputs .= wf_HiddenInput('chattributeid', $attributeId);
  1299. $inputs .= wf_Submit(__('Save'));
  1300. //form assembly
  1301. $result .= wf_Form(self::URL_ME . '&editnasoptions=' . $nasId, 'POST', $inputs, 'glamour');
  1302. } else {
  1303. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': EX_ATTRIBUTEID_NOT_EXIST', 'error');
  1304. }
  1305. return ($result);
  1306. }
  1307. /**
  1308. * Creates new NAS attribute preset
  1309. *
  1310. *
  1311. * @return void/string on error
  1312. */
  1313. public function createNasAttribute() {
  1314. $result = '';
  1315. if (wf_CheckPost(array('newattributenasid'))) {
  1316. $nasId = vf($_POST['newattributenasid'], 3);
  1317. if (isset($this->allNas[$nasId])) {
  1318. if (ubRouting::checkPost(array('newscenario', 'newattribute', 'newoperator', 'newmodifier'))) {
  1319. $newScenario = ubRouting::post('newscenario');
  1320. $newScenario_f = ubRouting::filters($newScenario, 'mres');
  1321. $newModifier = ubRouting::post('newmodifier');
  1322. $newModifier_f = ubRouting::filters($newModifier, 'mres');
  1323. $newAttribute = ubRouting::post('newattribute');
  1324. $newAttribute_f = ubRouting::filters($newAttribute, 'mres');
  1325. $newAttribute_f = trim($newAttribute_f);
  1326. $newOperator = ubRouting::post('newoperator');
  1327. $newOperator_f = ubRouting::filters($newOperator, 'mres');
  1328. $newContent = ubRouting::post('newcontent');
  1329. $newContent_f = ubRouting::filters($newContent, 'mres');
  1330. $newContent_f = trim($newContent_f);
  1331. $query = "INSERT INTO `" . self::NAS_ATTRIBUTES . "` (`id`,`nasid`,`scenario`,`modifier`,`attribute`,`operator`,`content`) VALUES "
  1332. . "(NULL,'" . $nasId . "','" . $newScenario_f . "','" . $newModifier_f . "','" . $newAttribute_f . "','" . $newOperator_f . "','" . $newContent_f . "');";
  1333. nr_query($query);
  1334. $newId = simple_get_lastid(self::NAS_ATTRIBUTES);
  1335. log_register('MULTIGEN NAS [' . $nasId . '] CREATE ATTRIBUTE `' . $newAttribute . '` ID [' . $newId . ']');
  1336. }
  1337. } else {
  1338. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  1339. }
  1340. }
  1341. return ($result);
  1342. }
  1343. /**
  1344. * Creates new NAS attribute preset
  1345. *
  1346. *
  1347. * @return void/string on error
  1348. */
  1349. public function saveNasAttribute() {
  1350. $result = '';
  1351. if (wf_CheckPost(array('chattributenasid'))) {
  1352. $nasId = vf($_POST['chattributenasid'], 3);
  1353. if (isset($this->allNas[$nasId])) {
  1354. if (ubRouting::checkPost(array('chscenario', 'chattribute', 'choperator', 'chmodifier'))) {
  1355. $attributeId = vf($_POST['chattributeid'], 3);
  1356. if (isset($this->nasAttributes[$attributeId])) {
  1357. $chAttribute = ubRouting::post('chattribute');
  1358. $chAttribute = trim($chAttribute);
  1359. $chContent = ubRouting::post('chcontent');
  1360. $chContent = trim($chContent);
  1361. $where = "WHERE `id`='" . $attributeId . "';";
  1362. simple_update_field(self::NAS_ATTRIBUTES, 'scenario', ubRouting::post('chscenario'), $where);
  1363. simple_update_field(self::NAS_ATTRIBUTES, 'modifier', ubRouting::post('chmodifier'), $where);
  1364. simple_update_field(self::NAS_ATTRIBUTES, 'attribute', $chAttribute, $where);
  1365. simple_update_field(self::NAS_ATTRIBUTES, 'operator', ubRouting::post('choperator'), $where);
  1366. simple_update_field(self::NAS_ATTRIBUTES, 'content', $chContent, $where);
  1367. log_register('MULTIGEN NAS [' . $nasId . '] CHANGE ATTRIBUTE [' . $attributeId . ']');
  1368. } else {
  1369. $result .= __('Something went wrong') . ': EX_ATTRIBUTE_NOT_EXIST';
  1370. }
  1371. }
  1372. } else {
  1373. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  1374. }
  1375. }
  1376. return ($result);
  1377. }
  1378. /**
  1379. * Creates user state if its not exists
  1380. *
  1381. * @param string $login
  1382. * @param int $state
  1383. *
  1384. * @return void
  1385. */
  1386. protected function createUserState($login, $state) {
  1387. $login = mysql_real_escape_string($login);
  1388. $state = mysql_real_escape_string($state);
  1389. $query = "INSERT INTO `" . self::USER_STATES . "` (`id`,`login`,`state`) VALUES ";
  1390. $query .= "(NULL,'" . $login . "'," . $state . ");";
  1391. nr_query($query);
  1392. }
  1393. /**
  1394. * Deletes some user state from states table
  1395. *
  1396. * @param string $login
  1397. *
  1398. * @return void
  1399. */
  1400. protected function deleteUserState($login) {
  1401. $login = mysql_real_escape_string($login);
  1402. $query = "DELETE FROM `" . self::USER_STATES . "` WHERE `login`='" . $login . "';";
  1403. nr_query($query);
  1404. }
  1405. /**
  1406. * Changes user state in database
  1407. *
  1408. * @param string $login
  1409. * @param int $state
  1410. *
  1411. * @return void
  1412. */
  1413. protected function changeUserState($login, $state) {
  1414. $where = "WHERE `login`='" . $login . "'";
  1415. simple_update_field(self::USER_STATES, 'state', $state, $where);
  1416. }
  1417. /**
  1418. * Saves user states into database if something changed
  1419. *
  1420. * @return void
  1421. */
  1422. protected function saveUserStates() {
  1423. if (!empty($this->userStates)) {
  1424. foreach ($this->userStates as $login => $state) {
  1425. if ($state['changed'] == 3) {
  1426. //new user state appeared
  1427. if ($state != '') {
  1428. $this->createUserState($login, $state['current']);
  1429. $this->logEvent('USERSTATE CREATED ' . $login . ' STATE ' . $state['current'], 3);
  1430. }
  1431. } else {
  1432. //user state changed
  1433. if ($state['current'] != $state['previous']) {
  1434. if (isset($this->allUserData[$login])) {
  1435. $this->changeUserState($login, $state['current']);
  1436. $this->logEvent('USERSTATE CHANGED ' . $login . ' STATE ' . $state['previous'] . ' ON ' . $state['current'], 3);
  1437. }
  1438. }
  1439. }
  1440. }
  1441. }
  1442. }
  1443. /**
  1444. * Checks is user active or not
  1445. *
  1446. * @param string $userLogin
  1447. *
  1448. * @return bool
  1449. */
  1450. protected function isUserActive($userLogin) {
  1451. $result = false;
  1452. if (isset($this->allUserData[$userLogin])) {
  1453. //not existing users is inactive by default
  1454. if ($this->accurateUserActivity) {
  1455. //full checks for users activity, may be optional in future
  1456. if ($this->allUserData[$userLogin]['Cash'] >= '-' . abs($this->allUserData[$userLogin]['Credit'])) {
  1457. if ($this->allUserData[$userLogin]['Passive'] == 0) {
  1458. if ($this->allUserData[$userLogin]['AlwaysOnline'] == 1) {
  1459. if ($this->allUserData[$userLogin]['Down'] == 0) {
  1460. $result = true;
  1461. }
  1462. }
  1463. }
  1464. }
  1465. } else {
  1466. //just check financial data
  1467. $result = ($this->allUserData[$userLogin]['Cash'] >= '-' . $this->allUserData[$userLogin]['Credit']) ? true : false;
  1468. }
  1469. }
  1470. return ($result);
  1471. }
  1472. /**
  1473. * Checks is some user attribute available in scenario and is not changed
  1474. *
  1475. * @param string $scenario
  1476. * @param string $userLogin
  1477. * @param string $userName
  1478. * @param string $attribute
  1479. * @param string $operator
  1480. * @param string $value
  1481. *
  1482. * @return int 0 - not exist / 1 - exists and not changed / -2 - changed
  1483. */
  1484. protected function checkScenarioAttribute($scenario, $userLogin, $userName, $attribute, $operator, $value) {
  1485. $result = 0;
  1486. if (isset($this->currentAttributes[$scenario])) {
  1487. if (isset($this->currentAttributes[$scenario][$userName])) {
  1488. if (isset($this->currentAttributes[$scenario][$userName][$attribute])) {
  1489. if ($this->currentAttributes[$scenario][$userName][$attribute]['value'] == $value) {
  1490. if ($this->currentAttributes[$scenario][$userName][$attribute]['op'] == $operator) {
  1491. $result = 1;
  1492. } else {
  1493. $result = -2;
  1494. }
  1495. } else {
  1496. $result = -2;
  1497. }
  1498. } else {
  1499. $result = 0;
  1500. }
  1501. } else {
  1502. $result = 0;
  1503. }
  1504. } else {
  1505. $result = 0;
  1506. }
  1507. $this->logEvent($userLogin . ' AS ' . $userName . ' SCENARIO ' . $scenario . ' TEST ' . $attribute . ' ' . $operator . ' ' . $value . ' RESULT ' . $result, 2);
  1508. return ($result);
  1509. }
  1510. /**
  1511. * Pushes some scenario attribute to database
  1512. *
  1513. * @param string $scenario
  1514. * @param string $userLogin
  1515. * @param string $userName
  1516. * @param string $attribute
  1517. * @param string $op
  1518. * @param string $value
  1519. *
  1520. * @return void
  1521. */
  1522. protected function createScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value) {
  1523. $query = "INSERT INTO `" . self::SCENARIO_PREFIX . $scenario . "` (`id`,`username`,`attribute`,`op`,`value`) VALUES " .
  1524. "(NULL,'" . $userName . "','" . $attribute . "','" . $op . "','" . $value . "');";
  1525. nr_query($query);
  1526. $this->logEvent($userLogin . ' AS ' . $userName . ' SCENARIO ' . $scenario . ' CREATE ' . $attribute . ' ' . $op . ' ' . $value, 1);
  1527. }
  1528. /**
  1529. * Drops some reply attribute from database (required on value changes)
  1530. *
  1531. * @param string $scenario
  1532. * @param string $userLogin
  1533. * @param string $userName
  1534. * @param string $attribute
  1535. *
  1536. * @return void
  1537. */
  1538. protected function deleteScenarioAttribute($scenario, $userLogin, $userName, $attribute) {
  1539. $query = "DELETE FROM `" . self::SCENARIO_PREFIX . $scenario . "` WHERE `username`='" . $userName . "' AND `attribute`='" . $attribute . "';";
  1540. nr_query($query);
  1541. $this->logEvent($userLogin . ' AS ' . $userName . ' SCENARIO ' . $scenario . ' DELETE ' . $attribute, 1);
  1542. }
  1543. /**
  1544. * Writes attributes regeneration stats
  1545. *
  1546. * @param int $nasId
  1547. * @param string $scenario
  1548. * @param string $attributeState
  1549. *
  1550. * @return void
  1551. */
  1552. protected function writeScenarioStats($nasId, $scenario, $attributeState) {
  1553. if ((!isset($this->scenarioStats[$nasId])) OR (!isset($this->scenarioStats[$nasId][$scenario])) OR (!isset($this->scenarioStats[$nasId][$scenario][$attributeState]))) {
  1554. $this->scenarioStats[$nasId][$scenario][$attributeState] = 1;
  1555. } else {
  1556. $this->scenarioStats[$nasId][$scenario][$attributeState]++;
  1557. }
  1558. }
  1559. /**
  1560. * Stores performance timing data for future stats
  1561. *
  1562. * @return void
  1563. */
  1564. public function writePerformanceTimers($key) {
  1565. if (isset($this->perfStats[$key])) {
  1566. $this->perfStats[$key] = microtime(true) - $this->perfStats[$key];
  1567. } else {
  1568. $this->perfStats[$key] = microtime(true);
  1569. }
  1570. }
  1571. /**
  1572. * Flushes buried user attributes if they are exists in database
  1573. *
  1574. * @param int $nasId
  1575. * @param string $scenario
  1576. * @param string $userLogin
  1577. * @param string $userName
  1578. * @param string $attribute
  1579. *
  1580. * @return void
  1581. */
  1582. protected function flushBuriedUser($nasId, $scenario, $userLogin, $userName, $attribute) {
  1583. if (isset($this->currentAttributes[$scenario])) {
  1584. if (isset($this->currentAttributes[$scenario][$userName])) {
  1585. if (isset($this->currentAttributes[$scenario][$userName][$attribute])) {
  1586. $this->deleteScenarioAttribute($scenario, $userLogin, $userName, $attribute);
  1587. $this->writeScenarioStats($nasId, $scenario, 'buried');
  1588. }
  1589. }
  1590. }
  1591. }
  1592. /**
  1593. * Returns user state as string
  1594. *
  1595. * @param string $userLogin
  1596. *
  1597. * @return string
  1598. */
  1599. protected function getUserStateString($userLogin) {
  1600. $result = '';
  1601. if (isset($this->allUserData[$userLogin])) {
  1602. if (($this->allUserData[$userLogin]['Cash'] >= '-' . $this->allUserData[$userLogin]['Credit']) AND ( $this->allUserData[$userLogin]['AlwaysOnline'] == 1)) {
  1603. $result = 'ON-LINE';
  1604. } else {
  1605. $result = 'OFF-LINE';
  1606. }
  1607. if ($this->allUserData[$userLogin]['Down']) {
  1608. $result = 'DOWN';
  1609. }
  1610. if ($this->allUserData[$userLogin]['Passive']) {
  1611. $result = 'PASSIVE';
  1612. }
  1613. } else {
  1614. $result = 'NOT-EXIST';
  1615. }
  1616. return ($result);
  1617. }
  1618. /**
  1619. * Parses network data to network address and network CIDR
  1620. *
  1621. * @param string $netDesc
  1622. *
  1623. * @return array
  1624. */
  1625. protected function parseNetworkDesc($netDesc) {
  1626. $result = array();
  1627. $netDesc = explode('/', $netDesc);
  1628. $result = array('addr' => $netDesc[0], 'cidr' => $netDesc[1]);
  1629. return ($result);
  1630. }
  1631. /**
  1632. * Transforms mac from xx:xx:xx:xx:xx:xx format to xxxx.xxxx.xxxx
  1633. *
  1634. * @param string $mac
  1635. *
  1636. * @return string
  1637. */
  1638. protected function transformMacDotted($mac) {
  1639. $result = implode(".", str_split(str_replace(":", "", $mac), 4));
  1640. return ($result);
  1641. }
  1642. /**
  1643. * Transforms mac from xx:xx:xx:xx:xx:xx format to XX-XX-XX-XX-XX-XX
  1644. *
  1645. * @param string $mac
  1646. * @param bool $caps
  1647. *
  1648. * @return string
  1649. */
  1650. protected function transformMacMinused($mac, $caps = false) {
  1651. $result = str_replace(':', '-', $mac);
  1652. if ($caps) {
  1653. $result = strtoupper($result);
  1654. }
  1655. return ($result);
  1656. }
  1657. /**
  1658. * Transforms CIDR notation to xxx.xxx.xxx.xxx netmask
  1659. *
  1660. * @param string $cidr - CIDR
  1661. *
  1662. * @return string
  1663. */
  1664. protected function transformCidrtoMask($cidr) {
  1665. $result = long2ip(-1 << (32 - (int) $cidr));
  1666. return ($result);
  1667. }
  1668. /**
  1669. * Returns current user speeds including personal override in Kbit/s
  1670. *
  1671. * @param string $userLogin
  1672. *
  1673. * @return array as speeddown/speedup=>values
  1674. */
  1675. protected function getUserSpeeds($userLogin) {
  1676. $result = array('speeddown' => 0, 'speedup' => 0);
  1677. if (isset($this->allUserData[$userLogin])) {
  1678. $userTariff = $this->allUserData[$userLogin]['Tariff'];
  1679. if (isset($this->tariffSpeeds[$userTariff])) {
  1680. //basic tariff speed
  1681. $result = array('speeddown' => $this->tariffSpeeds[$userTariff]['speeddown'], 'speedup' => $this->tariffSpeeds[$userTariff]['speedup']);
  1682. }
  1683. if (isset($this->userSpeedOverrides[$userLogin])) {
  1684. //personal speed overrides
  1685. $result = array('speeddown' => $this->userSpeedOverrides[$userLogin], 'speedup' => $this->userSpeedOverrides[$userLogin]);
  1686. }
  1687. }
  1688. return ($result);
  1689. }
  1690. /**
  1691. * Returns speed transformed from kbit/s to bit/s by some offset
  1692. *
  1693. * @param int $speed
  1694. * @param int $offset
  1695. *
  1696. * @return int
  1697. */
  1698. protected function transformSpeedBits($speed, $offset = 1024) {
  1699. $result = $speed * $offset;
  1700. return ($result);
  1701. }
  1702. /**
  1703. * Returns attribute templates value with replaced macro
  1704. *
  1705. * @param string $userLogin
  1706. * @param string $userName
  1707. * @param int $nasId
  1708. * @param string $template
  1709. *
  1710. * @return string
  1711. */
  1712. public function getAttributeValue($userLogin, $userName, $nasId, $template) {
  1713. if (strpos($template, '{') !== false) {
  1714. //skipping templates with no macro inside
  1715. if (isset($this->allUserData[$userLogin])) {
  1716. if (strpos($template, '{IP}') !== false) {
  1717. $template = str_replace('{IP}', $this->allUserData[$userLogin]['ip'], $template);
  1718. }
  1719. if (strpos($template, '{MAC}') !== false) {
  1720. $template = str_replace('{MAC}', $this->allUserData[$userLogin]['mac'], $template);
  1721. }
  1722. if (strpos($template, '{MACFDL}') !== false) {
  1723. $template = str_replace('{MACFDL}', $this->transformMacDotted($this->allUserData[$userLogin]['mac']), $template);
  1724. }
  1725. if (strpos($template, '{MACFML}') !== false) {
  1726. $template = str_replace('{MACFML}', str_replace('.', '-', $this->transformMacDotted($this->allUserData[$userLogin]['mac'])), $template);
  1727. }
  1728. if (strpos($template, '{MACTMU}') !== false) {
  1729. $template = str_replace('{MACTMU}', $this->transformMacMinused($this->allUserData[$userLogin]['mac'], true), $template);
  1730. }
  1731. if (strpos($template, '{MACTML}') !== false) {
  1732. $template = str_replace('{MACTML}', $this->transformMacMinused($this->allUserData[$userLogin]['mac'], false), $template);
  1733. }
  1734. if (strpos($template, '{LOGIN}') !== false) {
  1735. $template = str_replace('{LOGIN}', $userLogin, $template);
  1736. }
  1737. if (strpos($template, '{USERNAME}') !== false) {
  1738. $template = str_replace('{USERNAME}', $userName, $template);
  1739. }
  1740. if (strpos($template, '{PASSWORD}') !== false) {
  1741. $template = str_replace('{PASSWORD}', $this->allUserData[$userLogin]['Password'], $template);
  1742. }
  1743. if (strpos($template, '{TARIFF}') !== false) {
  1744. $template = str_replace('{TARIFF}', $this->allUserData[$userLogin]['Tariff'], $template);
  1745. }
  1746. if (strpos($template, '{NETID}') !== false) {
  1747. $template = str_replace('{NETID}', $this->nethostsNetworks[$this->allUserData[$userLogin]['ip']], $template);
  1748. }
  1749. if (strpos($template, '{NETADDR}') !== false) {
  1750. $netDesc = $this->allNetworks[$this->nethostsNetworks[$this->allUserData[$userLogin]['ip']]]['desc'];
  1751. $netDesc = $this->parseNetworkDesc($netDesc);
  1752. $netAddr = $netDesc['addr'];
  1753. $template = str_replace('{NETADDR}', $netAddr, $template);
  1754. }
  1755. if (strpos($template, '{NETCIDR}') !== false) {
  1756. $netDesc = $this->allNetworks[$this->nethostsNetworks[$this->allUserData[$userLogin]['ip']]]['desc'];
  1757. $netDesc = $this->parseNetworkDesc($netDesc);
  1758. $netCidr = $netDesc['cidr'];
  1759. $template = str_replace('{NETCIDR}', $netCidr, $template);
  1760. }
  1761. if (strpos($template, '{NETSTART}') !== false) {
  1762. $template = str_replace('{NETSTART}', $this->allNetworks[$this->nethostsNetworks[$this->allUserData[$userLogin]['ip']]]['startip'], $template);
  1763. }
  1764. if (strpos($template, '{NETEND}') !== false) {
  1765. $template = str_replace('{NETEND}', $this->allNetworks[$this->nethostsNetworks[$this->allUserData[$userLogin]['ip']]]['endip'], $template);
  1766. }
  1767. if (strpos($template, '{NETDESC}') !== false) {
  1768. $template = str_replace('{NETDESC}', $this->allNetworks[$this->nethostsNetworks[$this->allUserData[$userLogin]['ip']]]['desc'], $template);
  1769. }
  1770. if (strpos($template, '{NETMASK}') !== false) {
  1771. $netDesc = $this->allNetworks[$this->nethostsNetworks[$this->allUserData[$userLogin]['ip']]]['desc'];
  1772. $netDesc = $this->parseNetworkDesc($netDesc);
  1773. $netCidr = $netDesc['cidr'];
  1774. $netMask = $this->transformCidrtoMask($netCidr);
  1775. $template = str_replace('{NETMASK}', $netMask, $template);
  1776. }
  1777. if (strpos($template, '{SPEEDDOWN}') !== false) {
  1778. $userSpeeds = $this->getUserSpeeds($userLogin);
  1779. $speedDown = $userSpeeds['speeddown'];
  1780. $template = str_replace('{SPEEDDOWN}', $speedDown, $template);
  1781. }
  1782. if (strpos($template, '{SPEEDUP}') !== false) {
  1783. $userSpeeds = $this->getUserSpeeds($userLogin);
  1784. $speedUp = $userSpeeds['speedup'];
  1785. $template = str_replace('{SPEEDUP}', $speedUp, $template);
  1786. }
  1787. if (strpos($template, '{SPEEDDOWNB}') !== false) {
  1788. $userSpeeds = $this->getUserSpeeds($userLogin);
  1789. $speedDown = $this->transformSpeedBits($userSpeeds['speeddown'], 1024);
  1790. $template = str_replace('{SPEEDDOWNB}', $speedDown, $template);
  1791. }
  1792. if (strpos($template, '{SPEEDUPB}') !== false) {
  1793. $userSpeeds = $this->getUserSpeeds($userLogin);
  1794. $speedUp = $this->transformSpeedBits($userSpeeds['speedup'], 1024);
  1795. $template = str_replace('{SPEEDUPB}', $speedUp, $template);
  1796. }
  1797. if (strpos($template, '{SPEEDDOWNBD}') !== false) {
  1798. $userSpeeds = $this->getUserSpeeds($userLogin);
  1799. $speedDown = $this->transformSpeedBits($userSpeeds['speeddown'], 1000);
  1800. $template = str_replace('{SPEEDDOWNBD}', $speedDown, $template);
  1801. }
  1802. if (strpos($template, '{SPEEDUPBD}') !== false) {
  1803. $userSpeeds = $this->getUserSpeeds($userLogin);
  1804. $speedUp = $this->transformSpeedBits($userSpeeds['speedup'], 1000);
  1805. $template = str_replace('{SPEEDUPBD}', $speedUp, $template);
  1806. }
  1807. if (strpos($template, '{SPEEDDOWNBC}') !== false) {
  1808. $userSpeeds = $this->getUserSpeeds($userLogin);
  1809. $speedDown = $this->transformSpeedBits($userSpeeds['speeddown'], 1024) / 8;
  1810. $template = str_replace('{SPEEDDOWNBC}', $speedDown, $template);
  1811. }
  1812. if (strpos($template, '{SPEEDUPBC}') !== false) {
  1813. $userSpeeds = $this->getUserSpeeds($userLogin);
  1814. $speedUp = $this->transformSpeedBits($userSpeeds['speedup'], 1024) / 8;
  1815. $template = str_replace('{SPEEDUPBC}', $speedUp, $template);
  1816. }
  1817. if (strpos($template, '{SPEEDMRL}') !== false) {
  1818. $userSpeeds = $this->getUserSpeeds($userLogin);
  1819. $template = str_replace('{SPEEDMRL}', $userSpeeds['speedup'] . 'k/' . $userSpeeds['speeddown'] . 'k', $template);
  1820. }
  1821. if (strpos($template, '{USERSWITCHIP}') !== false) {
  1822. $userSwitchId = @$this->userSwitchAssigns[$userLogin]['switchid'];
  1823. $switchData = @$this->allSwitches[$userSwitchId];
  1824. $switchIp = @$switchData['ip'];
  1825. $template = str_replace('{USERSWITCHIP}', $switchIp, $template);
  1826. }
  1827. if (strpos($template, '{USERSWITCHPORT}') !== false) {
  1828. $userSwitchPort = @$this->userSwitchAssigns[$userLogin]['port'];
  1829. $template = str_replace('{USERSWITCHPORT}', $userSwitchPort, $template);
  1830. }
  1831. if (strpos($template, '{USERSWITCHMAC}') !== false) {
  1832. $userSwitchId = @$this->userSwitchAssigns[$userLogin]['switchid'];
  1833. $switchData = @$this->allSwitches[$userSwitchId];
  1834. $switchMac = @$switchData['swid'];
  1835. $template = str_replace('{USERSWITCHMAC}', $switchMac, $template);
  1836. }
  1837. if (strpos($template, '{NETEXT}') !== false) {
  1838. if (isset($this->netExtUsers[$userLogin])) {
  1839. $netExtData = $this->netExtUsers[$userLogin];
  1840. $template = str_replace('{NETEXT}', $netExtData, $template);
  1841. }
  1842. }
  1843. }
  1844. if (isset($this->allNas[$nasId])) {
  1845. $nasIp = $this->allNas[$nasId]['nasip'];
  1846. if (strpos($template, '{NASIP}') !== false) {
  1847. $template = str_replace('{NASIP}', $nasIp, $template);
  1848. }
  1849. if (strpos($template, '{NASSECRET}') !== false) {
  1850. $nasSecret = substr(md5(ip2int($nasIp)), 0, 12);
  1851. $template = str_replace('{NASSECRET}', $nasSecret, $template);
  1852. }
  1853. if (strpos($template, '{NASPORT}') !== false) {
  1854. $nasPort = $this->nasOptions[$nasId]['port'];
  1855. $template = str_replace('{NASPORT}', $nasPort, $template);
  1856. }
  1857. }
  1858. if (strpos($template, '{STATE}') !== false) {
  1859. $template = str_replace('{STATE}', $this->getUserStateString($userLogin), $template);
  1860. }
  1861. if (strpos($template, '{RADCLIENT}') !== false) {
  1862. $template = str_replace('{RADCLIENT}', $this->radclienPath, $template);
  1863. }
  1864. if (strpos($template, '{SUDO}') !== false) {
  1865. $template = str_replace('{SUDO}', $this->sudoPath, $template);
  1866. }
  1867. if (strpos($template, '{PRINTF}') !== false) {
  1868. $template = str_replace('{PRINTF}', $this->printfPath, $template);
  1869. }
  1870. }
  1871. return ($template);
  1872. }
  1873. /**
  1874. * Returns array of all possible radius-preprocessed usernames
  1875. *
  1876. * @return array
  1877. */
  1878. public function getAllUserNames() {
  1879. $result = array();
  1880. if (empty($this->allUserData)) {
  1881. $this->loadUserData();
  1882. if ((isset($this->altCfg[self::OPTION_SWASSIGN])) AND ( isset($this->altCfg[self::OPTION_QINQ]))) {
  1883. if (($this->altCfg[self::OPTION_SWASSIGN]) AND ( $this->altCfg[self::OPTION_QINQ])) {
  1884. $this->loadSwitches();
  1885. $this->loadSwithchAssigns();
  1886. $this->loadAllQinQ();
  1887. }
  1888. } else {
  1889. if (isset($this->altCfg[self::OPTION_UNIVERSALQINQ])) {
  1890. if ($this->altCfg[self::OPTION_UNIVERSALQINQ]) {
  1891. $this->loadAllQinQ();
  1892. }
  1893. }
  1894. }
  1895. //preloading culpa instance
  1896. if ($this->meaCulpaFlag) {
  1897. $this->loadMeaCulpa();
  1898. }
  1899. }
  1900. if (!empty($this->allUserData)) {
  1901. foreach ($this->allUserData as $eachUserLogin => $eachUserData) {
  1902. foreach ($this->usernameTypes as $eachUsernameType => $usernameTypeName) {
  1903. $userName = $this->getLoginUsername($eachUserLogin, $eachUserData, $eachUsernameType);
  1904. $result[$eachUserLogin][] = (string) $userName;
  1905. }
  1906. }
  1907. }
  1908. return($result);
  1909. }
  1910. /**
  1911. * Returns transformed username by some type
  1912. *
  1913. * @param string $userLogin
  1914. * @param array $userdata
  1915. * @param string $usernameType
  1916. *
  1917. * @return string
  1918. */
  1919. protected function getLoginUsername($userLogin, $userData, $userNameType) {
  1920. $result = '';
  1921. switch ($userNameType) {
  1922. case 'login':
  1923. $result = $userLogin;
  1924. break;
  1925. case 'ip':
  1926. $result = @$userData['ip'];
  1927. break;
  1928. case 'mac':
  1929. $result = @$userData['mac'];
  1930. break;
  1931. case 'macup':
  1932. $result = @strtoupper($userData['mac']);
  1933. break;
  1934. case 'macju':
  1935. $result = @$this->transformMacDotted($userData['mac']);
  1936. break;
  1937. case 'qinq':
  1938. $result = $this->getQinQUsername($userLogin, '.');
  1939. break;
  1940. case 'qinqju':
  1941. $result = $this->getQinQUsername($userLogin, '-');
  1942. break;
  1943. case 'meaculpa':
  1944. $result = $this->meaCulpa->get($userLogin);
  1945. break;
  1946. }
  1947. return ($result);
  1948. }
  1949. /**
  1950. * Returns default switch based QinQ username
  1951. *
  1952. * @param string $userLogin
  1953. * @param string $delimiter
  1954. *
  1955. * @return string/void
  1956. */
  1957. protected function getQinQUsername($userLogin, $delimiter = '.') {
  1958. $result = '';
  1959. if (isset($this->usersQinQ[$userLogin])) {
  1960. $qinqData = $this->usersQinQ[$userLogin];
  1961. if ($this->allSvlan[$qinqData['svlan_id']]['svlan'] === '0') {
  1962. $result .= $qinqData['cvlan'];
  1963. } else {
  1964. $result .= $this->allSvlan[$qinqData['svlan_id']]['svlan'] . $delimiter . $qinqData['cvlan'];
  1965. }
  1966. } elseif (isset($this->userSwitchAssigns[$userLogin])) {
  1967. $assignData = $this->userSwitchAssigns[$userLogin];
  1968. $assignedSwitchId = $assignData['switchid'];
  1969. $assignedPort = $assignData['port'];
  1970. if (isset($this->switchesQinQ[$assignedSwitchId])) {
  1971. $qinqData = $this->switchesQinQ[$assignedSwitchId];
  1972. if (!empty($assignedPort)) {
  1973. if ($this->allSvlan[$qinqData['svlan_id']]['svlan'] === '0') {
  1974. $result .= ($qinqData['cvlan'] + ($assignedPort - 1));
  1975. } else {
  1976. $result .= $this->allSvlan[$qinqData['svlan_id']]['svlan'] . $delimiter . ($qinqData['cvlan'] + ($assignedPort - 1));
  1977. }
  1978. }
  1979. }
  1980. }
  1981. if (!empty($result)) {
  1982. if (isset($this->allSvlan[$qinqData['svlan_id']])) {
  1983. $realmId = $this->allSvlan[$qinqData['svlan_id']]['realm_id'];
  1984. if ($realmId != 1) {
  1985. $result .= '@' . $this->allRealms[$realmId]['realm'];
  1986. }
  1987. }
  1988. }
  1989. return($result);
  1990. }
  1991. /**
  1992. * Returns user login if some username for him found
  1993. *
  1994. * @param string $userName
  1995. * @param array $allUserNames
  1996. *
  1997. * @return string
  1998. */
  1999. public function getUserLogin($userName, $allUserNames) {
  2000. $result = '';
  2001. if (!empty($allUserNames)) {
  2002. $userName = (string) $userName;
  2003. foreach ($allUserNames as $login => $each) {
  2004. if (array_search($userName, $each, true) !== false) {
  2005. $result = $login;
  2006. break;
  2007. }
  2008. }
  2009. }
  2010. return($result);
  2011. }
  2012. /**
  2013. * Need to disconnect user when data like username changed.
  2014. *
  2015. * @param string $userLogin
  2016. * @param array $userData
  2017. *
  2018. * @return void
  2019. */
  2020. public function podOnExternalEvent($userLogin, $userData, $newUserData = array()) {
  2021. $this->loadHugeRegenData();
  2022. if (!empty($this->allUserData)) {
  2023. $this->preprocessUserData();
  2024. if (isset($this->userNases[$userLogin])) {
  2025. $userNases = $this->userNases[$userLogin];
  2026. if (!empty($userNases)) {
  2027. foreach ($userNases as $eachNasId) {
  2028. @$nasOptions = $this->nasOptions[$eachNasId];
  2029. @$userNameType = $nasOptions['usernametype'];
  2030. if ($userNameType != 'login') {
  2031. $userName = $this->getLoginUsername($userLogin, $userData, $userNameType);
  2032. if (!empty($userName)) {
  2033. if (!empty($nasOptions)) {
  2034. if ($nasOptions['service'] != 'none') {
  2035. $nasServices = @$this->services[$eachNasId];
  2036. if (!empty($nasServices)) {
  2037. $this->allUserData[$userLogin]['ip'] = $userData['ip'];
  2038. $this->allUserData[$userLogin]['mac'] = $userData['mac'];
  2039. if (strpos($nasOptions['service'], 'pod') !== false) {
  2040. $podCommand = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['pod']) . "\n";
  2041. $this->savePodQueue($podCommand);
  2042. if (!empty($newUserData)) {
  2043. $newUserName = $this->getLoginUsername($userLogin, $newUserData, $userNameType);
  2044. $this->replaceSingleUser($newUserName, $userName);
  2045. $this->changeFramedIp($newUserData['ip'], $userData['ip'], $newUserName);
  2046. }
  2047. //adding else to avoid user double kill when use pod + coa services
  2048. } else {
  2049. if (strpos($nasOptions['service'], 'coa') !== false) {
  2050. $podCommand = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['pod']) . "\n";
  2051. $this->saveCoaQueue($podCommand);
  2052. if (!empty($newUserData)) {
  2053. $newUserName = $this->getLoginUsername($userLogin, $newUserData, $userNameType);
  2054. $this->replaceSingleUser($newUserName, $userName);
  2055. $this->changeFramedIp($newUserData['ip'], $userData['ip'], $newUserName);
  2056. }
  2057. }
  2058. }
  2059. }
  2060. }
  2061. }
  2062. }
  2063. }
  2064. }
  2065. }
  2066. }
  2067. //run PoD queue
  2068. if (isset($this->runServices['pod'])) {
  2069. $this->runPodQueue();
  2070. }
  2071. //run CoA queue
  2072. if (isset($this->runServices['coa'])) {
  2073. $this->runCoaQueue();
  2074. }
  2075. }
  2076. }
  2077. /**
  2078. * Replaces old username in mlg_* tables
  2079. *
  2080. * @param string $newUserName
  2081. * @param striing $oldUserName
  2082. *
  2083. * @return void
  2084. */
  2085. protected function replaceSingleUser($newUserName, $oldUserName) {
  2086. if (!empty($newUserName) and !empty($oldUserName)) {
  2087. foreach ($this->scenarios as $eachScenario) {
  2088. $query = 'UPDATE `' . self::SCENARIO_PREFIX . $eachScenario . '` SET `username`="' . $newUserName . '" WHERE `username`="' . $oldUserName . '"';
  2089. nr_query($query);
  2090. }
  2091. }
  2092. }
  2093. /**
  2094. * Replaces old Framed-IP-Address in mlg_reply table
  2095. *
  2096. * @param string $newIp
  2097. * @param string $oldIp
  2098. * @param string $userName
  2099. *
  2100. * @return void
  2101. */
  2102. protected function changeFramedIp($newIp, $oldIp, $userName) {
  2103. if (!empty($newIp) and !empty($oldIp)) {
  2104. $query = 'UPDATE `' . self::SCENARIO_PREFIX . 'reply' . '` SET `Value`="' . $newIp . '" WHERE `attribute`="Framed-IP-Address" AND `value`="' . $oldIp . '" AND `username`="' . $userName . '"';
  2105. nr_query($query);
  2106. }
  2107. }
  2108. /**
  2109. * Performs generation of user attributes if their NAS requires it.
  2110. *
  2111. * @return void
  2112. */
  2113. public function generateNasAttributes() {
  2114. $this->writePerformanceTimers('genstart');
  2115. //loading huge amount of required data
  2116. $this->loadHugeRegenData();
  2117. $this->writePerformanceTimers('dataloaded');
  2118. if (!empty($this->allUserData)) {
  2119. //starting regeneration transaction if required
  2120. if ($this->inno) {
  2121. nr_query("START TRANSACTION;");
  2122. }
  2123. foreach ($this->allUserData as $io => $eachUser) {
  2124. $userLogin = $eachUser['login'];
  2125. //user actual state right now
  2126. $userRealState = $this->isUserActive($userLogin);
  2127. //getting previous user state, setting current state
  2128. if (isset($this->userStates[$userLogin])) {
  2129. $userPreviousState = $this->userStates[$userLogin]['previous'];
  2130. $this->userStates[$userLogin]['current'] = ($userRealState) ? 1 : 0;
  2131. } else {
  2132. $userPreviousState = 3;
  2133. $this->userStates[$userLogin]['previous'] = $userPreviousState;
  2134. $this->userStates[$userLogin]['current'] = ($userRealState) ? 1 : 0;
  2135. $this->userStates[$userLogin]['changed'] = 3;
  2136. }
  2137. if (isset($this->userNases[$userLogin])) {
  2138. $userNases = $this->userNases[$userLogin];
  2139. if (!empty($userNases)) {
  2140. foreach ($userNases as $eachNasId) {
  2141. @$nasOptions = $this->nasOptions[$eachNasId];
  2142. @$userNameType = $nasOptions['usernametype'];
  2143. //overriding username type if required
  2144. $userName = $this->getLoginUsername($userLogin, $eachUser, $userNameType);
  2145. //yeah, this is possible in some unusual cases with QinQ or something like that
  2146. if (!empty($userName)) {
  2147. if (!empty($nasOptions)) {
  2148. $nasAttributes = $this->getNasAttributes($eachNasId);
  2149. $onlyActive = $nasOptions['onlyactive'];
  2150. //Processing NAS attributes only for active users
  2151. if ($onlyActive == 1) {
  2152. if (!empty($nasAttributes)) {
  2153. foreach ($nasAttributes as $eachAttributeId => $eachAttributeData) {
  2154. $scenario = $eachAttributeData['scenario'];
  2155. $attribute = $eachAttributeData['attribute'];
  2156. $op = $eachAttributeData['operator'];
  2157. $template = $eachAttributeData['content'];
  2158. if ($userRealState) {
  2159. $value = $this->getAttributeValue($userLogin, $userName, $eachNasId, $template);
  2160. $attributeCheck = $this->checkScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2161. if ($attributeCheck == -2) {
  2162. //dropping already changed attribute from this scenario
  2163. $this->deleteScenarioAttribute($scenario, $userLogin, $userName, $attribute);
  2164. //setting current user state as changed
  2165. $this->userStates[$userLogin]['changed'] = -2;
  2166. }
  2167. if ((($attributeCheck == 0) OR ( $attributeCheck == -2)) AND (!preg_match('/(^{\w+})/', $value))) {
  2168. //creating new attribute with actual data
  2169. $this->createScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2170. $this->writeScenarioStats($eachNasId, $scenario, 'generated');
  2171. }
  2172. if ($attributeCheck == 1) {
  2173. //attribute exists and not changed
  2174. $this->writeScenarioStats($eachNasId, $scenario, 'skipped');
  2175. }
  2176. } else {
  2177. //flush some not-active user attributes if required
  2178. $this->flushBuriedUser($eachNasId, $scenario, $userLogin, $userName, $attribute);
  2179. }
  2180. }
  2181. }
  2182. }
  2183. //Processing NAS attributes for all users using attributes modifiers
  2184. if ($onlyActive == 0) {
  2185. if (!empty($nasAttributes)) {
  2186. foreach ($nasAttributes as $eachAttributeId => $eachAttributeData) {
  2187. $scenario = $eachAttributeData['scenario'];
  2188. $modifier = $eachAttributeData['modifier'];
  2189. $attribute = $eachAttributeData['attribute'];
  2190. $op = $eachAttributeData['operator'];
  2191. $template = $eachAttributeData['content'];
  2192. //this attribute template is actual for all users
  2193. if ($modifier == 'all') {
  2194. $value = $this->getAttributeValue($userLogin, $userName, $eachNasId, $template);
  2195. $attributeCheck = $this->checkScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2196. if ($attributeCheck == -2) {
  2197. //dropping already changed attribute from this scenario
  2198. $this->deleteScenarioAttribute($scenario, $userLogin, $userName, $attribute);
  2199. //setting current user state as changed
  2200. $this->userStates[$userLogin]['changed'] = -2;
  2201. }
  2202. if ((($attributeCheck == 0) OR ( $attributeCheck == -2)) AND (!preg_match('/(^{\w+})/', $value))) {
  2203. //creating new attribute with actual data
  2204. $this->createScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2205. $this->writeScenarioStats($eachNasId, $scenario, 'generated');
  2206. }
  2207. if ($attributeCheck == 1) {
  2208. //attribute exists and not changed
  2209. $this->writeScenarioStats($eachNasId, $scenario, 'skipped');
  2210. }
  2211. }
  2212. //this attribute is actual only for active users
  2213. if ($modifier == 'active') {
  2214. if ($userRealState) {
  2215. $value = $this->getAttributeValue($userLogin, $userName, $eachNasId, $template);
  2216. $attributeCheck = $this->checkScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2217. if ($attributeCheck == -2) {
  2218. //dropping already changed attribute from this scenario
  2219. $this->deleteScenarioAttribute($scenario, $userLogin, $userName, $attribute);
  2220. //setting current user state as changed
  2221. $this->userStates[$userLogin]['changed'] = -2;
  2222. }
  2223. if ((($attributeCheck == 0) OR ( $attributeCheck == -2)) AND (!preg_match('/(^{\w+})/', $value))) {
  2224. //creating new attribute with actual data
  2225. $this->createScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2226. $this->writeScenarioStats($eachNasId, $scenario, 'generated');
  2227. }
  2228. if ($attributeCheck == 1) {
  2229. //attribute exists and not changed
  2230. $this->writeScenarioStats($eachNasId, $scenario, 'skipped');
  2231. }
  2232. } else {
  2233. //flush some not-active user attribute if required
  2234. $this->flushBuriedUser($eachNasId, $scenario, $userLogin, $userName, $attribute);
  2235. }
  2236. }
  2237. //this attribute is actual only for inactive users
  2238. if ($modifier == 'inactive') {
  2239. if (!$userRealState) {
  2240. $value = $this->getAttributeValue($userLogin, $userName, $eachNasId, $template);
  2241. $attributeCheck = $this->checkScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2242. if ($attributeCheck == -2) {
  2243. //dropping already changed attribute from this scenario
  2244. $this->deleteScenarioAttribute($scenario, $userLogin, $userName, $attribute);
  2245. //setting current user state as changed
  2246. $this->userStates[$userLogin]['changed'] = -2;
  2247. }
  2248. if ((($attributeCheck == 0) OR ( $attributeCheck == -2)) AND (!preg_match('/(^{\w+})/', $value))) {
  2249. //creating new attribute with actual data
  2250. $this->createScenarioAttribute($scenario, $userLogin, $userName, $attribute, $op, $value);
  2251. $this->writeScenarioStats($eachNasId, $scenario, 'generated');
  2252. }
  2253. if ($attributeCheck == 1) {
  2254. //attribute exists and not changed
  2255. $this->writeScenarioStats($eachNasId, $scenario, 'skipped');
  2256. }
  2257. } else {
  2258. //flush some active user attribute if required
  2259. $this->flushBuriedUser($eachNasId, $scenario, $userLogin, $userName, $attribute);
  2260. }
  2261. }
  2262. }
  2263. }
  2264. }
  2265. //processing Per-NAS services
  2266. if ($nasOptions['service'] != 'none') {
  2267. $nasServices = @$this->services[$eachNasId];
  2268. if (!empty($nasServices)) {
  2269. if (strpos($nasOptions['service'], 'pod') !== false) {
  2270. if (!empty($nasServices['pod'])) {
  2271. if (($userPreviousState == 1) AND ( $this->userStates[$userLogin]['current'] == 0)) {
  2272. $newPodContent = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['pod']) . "\n";
  2273. $this->savePodQueue($newPodContent);
  2274. }
  2275. }
  2276. }
  2277. if (strpos($nasOptions['service'], 'coa') !== false) {
  2278. //sending some disconnect
  2279. if (!empty($nasServices['coadisconnect'])) {
  2280. if (($userPreviousState == 1) AND ( $this->userStates[$userLogin]['current'] == 0)) {
  2281. //user out of money
  2282. $newCoADisconnectContent = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['coadisconnect']) . "\n";
  2283. $this->saveCoaQueue($newCoADisconnectContent);
  2284. }
  2285. }
  2286. //and connect services
  2287. if (!empty($nasServices['coaconnect'])) {
  2288. if (($userPreviousState == 0) AND ( $this->userStates[$userLogin]['current'] == 1)) {
  2289. //user now restores his activity
  2290. $newCoAConnectContent = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['coaconnect']) . "\n";
  2291. $this->saveCoaQueue($newCoAConnectContent);
  2292. }
  2293. }
  2294. //emulating reset action if something changed in user attributes
  2295. if ((!empty($nasServices['coadisconnect'])) AND (!empty($nasServices['coaconnect']))) {
  2296. if (($this->userStates[$userLogin]['changed'] == -2) AND ( $this->userStates[$userLogin]['current'] == 1) AND ( $this->userStates[$userLogin]['previous'] == 1)) {
  2297. $newCoADisconnectContent = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['coadisconnect']) . "\n";
  2298. $this->saveCoaQueue($newCoADisconnectContent);
  2299. $newCoAConnectContent = $this->getAttributeValue($userLogin, $userName, $eachNasId, $nasServices['coaconnect']) . "\n";
  2300. $this->saveCoaQueue($newCoAConnectContent);
  2301. }
  2302. }
  2303. }
  2304. }
  2305. }
  2306. }
  2307. }
  2308. }
  2309. }
  2310. }
  2311. }
  2312. //run PoD queue
  2313. if (isset($this->runServices['pod'])) {
  2314. $this->runPodQueue();
  2315. }
  2316. //run CoA queue
  2317. if (isset($this->runServices['coa'])) {
  2318. $this->runCoaQueue();
  2319. }
  2320. //saving user states
  2321. $this->saveUserStates();
  2322. //commiting changes to database if required
  2323. if ($this->inno) {
  2324. nr_query("COMMIT;");
  2325. }
  2326. }
  2327. $this->writePerformanceTimers('genend');
  2328. }
  2329. /**
  2330. * Saves data to PoD queue for furtner run
  2331. *
  2332. * @param string $data
  2333. *
  2334. * @return void
  2335. */
  2336. protected function savePodQueue($data) {
  2337. $this->runServices['pod'] = 1;
  2338. file_put_contents(self::POD_PATH . $this->instanceId, $data, FILE_APPEND);
  2339. $this->logEvent('POD_QUEUE_ADD ' . $this->instanceId . ': ' . trim($data), 3); //Omae wa mou shindeiru
  2340. }
  2341. /**
  2342. * Saves data to CoA queue for furtner run
  2343. *
  2344. * @param string $data
  2345. *
  2346. * @return void
  2347. */
  2348. protected function saveCoaQueue($data) {
  2349. $this->runServices['coa'] = 1;
  2350. file_put_contents(self::COA_PATH . $this->instanceId, $data, FILE_APPEND);
  2351. $this->logEvent('COA_QUEUE_ADD ' . $this->instanceId . ': ' . trim($data), 3);
  2352. }
  2353. /**
  2354. * Runs PoD queue if not empty and flushes after it
  2355. *
  2356. * @return void
  2357. */
  2358. protected function runPodQueue() {
  2359. if (file_exists(self::POD_PATH . $this->instanceId)) {
  2360. chmod(self::POD_PATH . $this->instanceId, 0755);
  2361. $podQueueCleanup = $this->echoPath . ' "" > ' . getcwd() . '/' . self::POD_PATH . $this->instanceId . "\n";
  2362. $this->savePodQueue($podQueueCleanup);
  2363. if ($this->logging >= 4) {
  2364. shell_exec(self::POD_PATH . $this->instanceId . ' >>' . self::LOG_PATH . ' 2>> ' . self::LOG_PATH);
  2365. } else {
  2366. shell_exec(self::POD_PATH . $this->instanceId . ' >/dev/null 2>/dev/null &');
  2367. }
  2368. $this->logEvent('POD_QUEUE_RUN: ' . $this->instanceId, 3); //nani?
  2369. }
  2370. }
  2371. /**
  2372. * Runs CoA queue if not empty and flushes after it
  2373. *
  2374. * @return void
  2375. */
  2376. protected function runCoaQueue() {
  2377. if (file_exists(self::COA_PATH . $this->instanceId)) {
  2378. chmod(self::COA_PATH . $this->instanceId, 0755);
  2379. $coaQueueCleanup = $this->echoPath . ' "" > ' . getcwd() . '/' . self::COA_PATH . $this->instanceId . "\n";
  2380. $this->saveCoaQueue($coaQueueCleanup);
  2381. if ($this->logging >= 4) {
  2382. shell_exec(self::COA_PATH . $this->instanceId . ' >>' . self::LOG_PATH . ' 2>> ' . self::LOG_PATH);
  2383. } else {
  2384. shell_exec(self::COA_PATH . $this->instanceId . ' >/dev/null 2>/dev/null &');
  2385. }
  2386. $this->logEvent('COA_QUEUE_RUN: ' . $this->instanceId, 3);
  2387. }
  2388. }
  2389. /**
  2390. * Returns NAS label as IP - name
  2391. *
  2392. * @param int $nasId
  2393. *
  2394. * @return string
  2395. */
  2396. public function getNaslabel($nasId) {
  2397. $result = '';
  2398. if (isset($this->allNas[$nasId])) {
  2399. $result .= $this->allNas[$nasId]['nasip'] . ' - ' . $this->allNas[$nasId]['nasname'];
  2400. }
  2401. return ($result);
  2402. }
  2403. /**
  2404. * Renders some NAS attributes regeneration stats
  2405. *
  2406. * @return strings
  2407. */
  2408. public function renderScenarioStats() {
  2409. $result = '';
  2410. $totalAttributeCount = 0;
  2411. if (!empty($this->scenarioStats)) {
  2412. foreach ($this->scenarioStats as $nasId => $scenario) {
  2413. $nasLabel = $this->getNaslabel($nasId);
  2414. $result .= $this->messages->getStyledMessage($nasLabel, 'success');
  2415. if (!empty($scenario)) {
  2416. foreach ($scenario as $scenarioName => $counters) {
  2417. if (!empty($counters)) {
  2418. foreach ($counters as $eachState => $eachCount) {
  2419. switch ($eachState) {
  2420. case 'skipped':
  2421. $stateName = __('Attributes is unchanged and generation was skipped');
  2422. $stateStyle = 'info';
  2423. break;
  2424. case 'generated':
  2425. $stateName = __('New or changed attributes generated');
  2426. $stateStyle = 'warning';
  2427. break;
  2428. case 'buried':
  2429. $stateName = __('Attributes was flushed due user inactivity');
  2430. $stateStyle = 'warning';
  2431. break;
  2432. default :
  2433. $stateName = $eachState;
  2434. $stateStyle = 'info';
  2435. break;
  2436. }
  2437. $totalAttributeCount += $eachCount;
  2438. $result .= $this->messages->getStyledMessage($stateName . ' ' . __('for scenario') . ' ' . $scenarioName . ': ' . $eachCount, $stateStyle);
  2439. }
  2440. }
  2441. }
  2442. }
  2443. }
  2444. }
  2445. if (!empty($this->perfStats)) {
  2446. $timeStats = '';
  2447. $perfStats = '';
  2448. $dataLoadingTime = $this->perfStats['dataloaded'] - $this->perfStats['genstart'];
  2449. $totalTime = $this->perfStats['genend'] - $this->perfStats['genstart'];
  2450. $timeStats .= __('Total time spent') . ': ' . round($totalTime, 2) . ' ' . __('sec.') . ' ';
  2451. $timeStats .= __('Data loading time') . ': ' . round($dataLoadingTime, 2) . ' ' . __('sec.') . ' ';
  2452. $timeStats .= __('Attributes processing time') . ': ' . round(($totalTime - $dataLoadingTime), 2) . ' ' . __('sec.') . ' ';
  2453. $timeStats .= __('Memory used') . ': ~' . stg_convert_size(memory_get_usage(true));
  2454. $perfStats .= __('Total attributes processed') . ': ' . $totalAttributeCount . ' ';
  2455. if ($totalTime > 0) {
  2456. //preventing zero divisions
  2457. $perfStats .= __('Performance') . ': ' . round($totalAttributeCount / ($totalTime - $dataLoadingTime), 2) . ' ' . __('attributes/sec');
  2458. $perfStats .= ' ( ' . round($totalAttributeCount / ($totalTime), 2) . ' ' . ' ' . __('brutto') . ')';
  2459. } else {
  2460. $perfStats .= __('Performance') . ': ' . wf_tag('b') . __('Black magic') . wf_tag('b', true);
  2461. }
  2462. $result .= $this->messages->getStyledMessage($timeStats, 'success');
  2463. $result .= $this->messages->getStyledMessage($perfStats, 'success');
  2464. }
  2465. return ($result);
  2466. }
  2467. /**
  2468. * Renders NAS controls panel
  2469. *
  2470. * @param int $nasId
  2471. *
  2472. * @return string
  2473. */
  2474. public function nasControlPanel($nasId) {
  2475. $result = '';
  2476. $result .= wf_BackLink('?module=nas') . ' ';
  2477. $result .= wf_modal(wf_img('skins/icon_clone.png') . ' ' . __('Clone NAS configuration'), __('Clone NAS configuration'), $this->renderNasCloneForm($nasId), 'ubButton', '750', '390');
  2478. if ($this->nasHaveOptions($nasId)) {
  2479. $result .= wf_AjaxLoader();
  2480. $result .= wf_AjaxLink(self::URL_ME . '&ajnasregen=true&editnasoptions=' . $nasId, wf_img('skins/refresh.gif') . ' ' . __('Base regeneration'), 'nascontrolajaxcontainer', false, 'ubButton');
  2481. $result .= wf_AjaxLink(self::URL_ME . '&ajscenarioflush=true&editnasoptions=' . $nasId, wf_img('skins/skull.png') . ' ' . __('Flush all attributes in all scenarios'), 'nascontrolajaxcontainer', false, 'ubButton');
  2482. if ($this->nasOptions[$nasId]['service'] != 'none') {
  2483. $result .= wf_modalAuto(web_icon_extended() . ' ' . __('Service'), __('Service'), $this->renderNasServicesEditForm($nasId), 'ubButton');
  2484. }
  2485. $result .= wf_AjaxContainer('nascontrolajaxcontainer');
  2486. }
  2487. return ($result);
  2488. }
  2489. /**
  2490. * Returns NAS services editing form
  2491. *
  2492. * @param int $nasId
  2493. *
  2494. * @return string
  2495. */
  2496. protected function renderNasServicesEditForm($nasId) {
  2497. $result = '';
  2498. $nasId = vf($nasId, 3);
  2499. if ($this->nasHaveOptions($nasId)) {
  2500. $nasOptions = $this->nasOptions[$nasId];
  2501. if ($nasOptions['service'] != 'none') {
  2502. $nasServices = @$this->services[$nasId];
  2503. $inputs = wf_HiddenInput('newnasservicesid', $nasId);
  2504. $inputs .= __('PoD') . wf_tag('br');
  2505. $inputs .= wf_TextArea('newnasservicepod', '', @$nasServices['pod'], true, '90x2');
  2506. $inputs .= __('CoA Connect') . wf_tag('br');
  2507. $inputs .= wf_TextArea('newnasservicecoaconnect', '', @$nasServices['coaconnect'], true, '90x2');
  2508. $inputs .= __('CoA Disconnect') . wf_tag('br');
  2509. $inputs .= wf_TextArea('newnasservicecoadisconnect', '', @$nasServices['coadisconnect'], true, '90x2');
  2510. $inputs .= wf_Submit(__('Save'));
  2511. $result .= wf_Form(self::URL_ME . '&editnasoptions=' . $nasId, 'POST', $inputs, 'glamour');
  2512. }
  2513. }
  2514. return ($result);
  2515. }
  2516. /**
  2517. * Returns some NAS text-based configuration info for copy/paste settings
  2518. *
  2519. * @param int $nasId
  2520. *
  2521. * @return array/string if empty
  2522. */
  2523. protected function getNasCopyString($nasId) {
  2524. $result = array();
  2525. if (isset($this->nasOptions[$nasId])) {
  2526. $result['options'] = $this->nasOptions[$nasId];
  2527. $result['attributes'] = $this->getNasAttributes($nasId);
  2528. $result['services'] = $this->getNasServices($nasId);
  2529. $result = json_encode($result);
  2530. $result = base64_encode($result);
  2531. } else {
  2532. $result = '';
  2533. }
  2534. return ($result);
  2535. }
  2536. /**
  2537. * Renders NAS copy&paste settings form
  2538. *
  2539. * @param int $nasId
  2540. *
  2541. * @return string
  2542. */
  2543. protected function renderNasCopyPasteForm($nasId) {
  2544. $result = '';
  2545. $inputs = __('You can copy&paste current NAS configuration as text');
  2546. $inputs .= wf_tag('br');
  2547. $inputs .= wf_TextInput('nascopypastetext', __('Settings'), $this->getNasCopyString($nasId), true, 55);
  2548. $inputs .= wf_CheckInput('nascopypasteagree', __('I understand that changing that completely destroys all current NAS settings if they exist and will replace them with the another configuration'), true, false);
  2549. $inputs .= wf_delimiter();
  2550. $inputs .= wf_Submit(__('Save'));
  2551. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  2552. return ($result);
  2553. }
  2554. /**
  2555. * Renders nas options/atributes/services cloning form
  2556. *
  2557. * @param int $nasId
  2558. *
  2559. * @return string
  2560. *
  2561. */
  2562. protected function renderNasCloneForm($nasId) {
  2563. $result = '';
  2564. $nasId = vf($nasId, 3);
  2565. $nasParamsTmp = array();
  2566. $otherNasCount = 0;
  2567. if (isset($this->allNas[$nasId])) {
  2568. /**
  2569. * Get the fuck off
  2570. * Mother fucker
  2571. * Back the fuck off
  2572. * Fucking hustler
  2573. * What the fuck? What the fuck?
  2574. * I don't wanna
  2575. * I don't need ya
  2576. * Watch out the fire
  2577. * Of the Saiya
  2578. */
  2579. if ((!empty($this->nasOptions)) AND (!empty($this->allNas))) {
  2580. foreach ($this->nasOptions as $io => $each) {
  2581. if (($io != $nasId) AND ( isset($this->allNas[$io]))) {
  2582. $nasBasicData = $this->allNas[$io];
  2583. $nasExtendedOptions = $each;
  2584. $nasUsernameType = @$this->usernameTypes[$nasExtendedOptions['usernametype']];
  2585. $nasService = $this->serviceTypes[$nasExtendedOptions['service']];
  2586. $attributeTemplates = $this->getNasAttributes($io);
  2587. $attributeTemplatesCount = sizeof($attributeTemplates);
  2588. $nasLabel = $nasBasicData['nasip'] . ' - ' . $nasBasicData['nasname'] . ' (' . $nasUsernameType . ' / ' . $nasService . ' / ' . $attributeTemplatesCount . ' ' . __('NAS attributes') . ')';
  2589. $nasParamsTmp[$nasBasicData['id']] = $nasLabel;
  2590. $otherNasCount++;
  2591. }
  2592. }
  2593. if (!empty($nasParamsTmp)) {
  2594. $inputs = wf_Selector('clonenasfromid', $nasParamsTmp, __('Clone') . ' ' . __('NAS'), '', true);
  2595. $inputs .= wf_HiddenInput('clonenastoid', $nasId);
  2596. $inputs .= wf_CheckInput('clonenasagree', __('I understand that cloning completely destroys all current NAS settings if they exist and will replace them with the configuration of another NAS'), true, false);
  2597. $inputs .= wf_delimiter();
  2598. $inputs .= wf_Submit(__('Clone'));
  2599. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  2600. }
  2601. }
  2602. } else {
  2603. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('NAS not exists'), 'error');
  2604. }
  2605. if ($otherNasCount < 1) {
  2606. $result .= $this->messages->getStyledMessage(__('No other configured NAS to cloning'), 'warning');
  2607. }
  2608. //copy&paste form
  2609. $result .= wf_tag('br');
  2610. $result .= $this->renderNasCopyPasteForm($nasId);
  2611. return ($result);
  2612. }
  2613. /**
  2614. * Flushes all NAS configuration from database
  2615. *
  2616. * @param int $nasId
  2617. *
  2618. * @return void
  2619. */
  2620. public function deleteAllNasConfiguration($nasId) {
  2621. $nasId = vf($nasId, 3);
  2622. $query = "DELETE FROM `" . self::NAS_OPTIONS . "` WHERE `nasid`='" . $nasId . "';";
  2623. nr_query($query);
  2624. log_register('MULTIGEN NAS [' . $nasId . '] FLUSH OPTIONS');
  2625. $query = "DELETE FROM `" . self::NAS_ATTRIBUTES . "` WHERE `nasid`='" . $nasId . "';";
  2626. nr_query($query);
  2627. log_register('MULTIGEN NAS [' . $nasId . '] FLUSH ATTRIBUTES');
  2628. $query = "DELETE FROM `" . self::NAS_SERVICES . "` WHERE `nasid`='" . $nasId . "';";
  2629. nr_query($query);
  2630. log_register('MULTIGEN NAS [' . $nasId . '] FLUSH SERVICES');
  2631. }
  2632. /**
  2633. * Clones all NAS options, attributes and services
  2634. *
  2635. * @param int $fromId
  2636. * @param int $toId
  2637. *
  2638. * @return void/string on error
  2639. */
  2640. public function cloneNasConfiguration($fromId, $toId) {
  2641. $result = '';
  2642. $fromId = vf($fromId, 3);
  2643. $toId = vf($toId, 3);
  2644. if ((isset($this->allNas[$fromId])) AND ( $this->allNas[$toId])) {
  2645. if (isset($this->nasOptions[$fromId])) {
  2646. $sourceNasOptions = $this->nasOptions[$fromId];
  2647. $sourceNasAttributes = $this->getNasAttributes($fromId);
  2648. $sourceNasServices = $this->getNasServices($fromId);
  2649. //deleting all old NAS setup
  2650. $this->deleteAllNasConfiguration($toId);
  2651. //Creating new NAS options
  2652. if (!empty($sourceNasOptions)) {
  2653. log_register('MULTIGEN NAS [' . $toId . '] CLONE CONFIGURATION FROM [' . $fromId . ']');
  2654. $newUserName = $sourceNasOptions['usernametype'];
  2655. $newService = $sourceNasOptions['service'];
  2656. $newOnlyActive = $sourceNasOptions['onlyactive'];
  2657. $newPort = $sourceNasOptions['port'];
  2658. //new NAS options creation
  2659. $newUserName_f = mysql_real_escape_string($newUserName);
  2660. $newService_f = mysql_real_escape_string($newService);
  2661. $newOnlyActive_f = mysql_real_escape_string($newOnlyActive);
  2662. $newPort_f = vf($newPort, 3);
  2663. $query = "INSERT INTO `" . self::NAS_OPTIONS . "` (`id`,`nasid`,`usernametype`,`service`,`onlyactive`,`port`) VALUES "
  2664. . "(NULL,'" . $toId . "','" . $newUserName_f . "','" . $newService_f . "','" . $newOnlyActive_f . "','" . $newPort_f . "');";
  2665. nr_query($query);
  2666. log_register('MULTIGEN NAS [' . $toId . '] CLONE USERNAME `' . $newUserName . '` SERVICE `' . $newService . '` ONLYAACTIVE `' . $newOnlyActive . '` PORT `' . $newPort . '` FROM NAS [' . $fromId . ']');
  2667. }
  2668. //Creating new NAS attribute templates
  2669. if (!empty($sourceNasAttributes)) {
  2670. foreach ($sourceNasAttributes as $io => $each) {
  2671. $newScenario = $each['scenario'];
  2672. $newScenario_f = mysql_real_escape_string($newScenario);
  2673. $newModifier = $each['modifier'];
  2674. $newModifier_f = mysql_real_escape_string($newModifier);
  2675. $newAttribute = $each['attribute'];
  2676. $newAttribute_f = mysql_real_escape_string($newAttribute);
  2677. $newOperator = $each['operator'];
  2678. $newOperator_f = mysql_real_escape_string($newOperator);
  2679. $newContent = $each['content'];
  2680. $newContent_f = mysql_real_escape_string($newContent);
  2681. $query = "INSERT INTO `" . self::NAS_ATTRIBUTES . "` (`id`,`nasid`,`scenario`,`modifier`,`attribute`,`operator`,`content`) VALUES "
  2682. . "(NULL,'" . $toId . "','" . $newScenario_f . "','" . $newModifier_f . "','" . $newAttribute_f . "','" . $newOperator_f . "','" . $newContent_f . "');";
  2683. nr_query($query);
  2684. $newId = simple_get_lastid(self::NAS_ATTRIBUTES);
  2685. log_register('MULTIGEN NAS [' . $toId . '] CLONE ATTRIBUTE `' . $newAttribute . '` ID [' . $newId . '] FROM NAS [' . $fromId . ']');
  2686. }
  2687. }
  2688. //Creating new NAS services
  2689. if (!empty($sourceNasServices)) {
  2690. $newPod = $sourceNasServices[$fromId]['pod'];
  2691. $newPod_f = mysql_real_escape_string($newPod);
  2692. $newCoaConnect = $sourceNasServices[$fromId]['coaconnect'];
  2693. $newCoaConnect_f = mysql_real_escape_string($newCoaConnect);
  2694. $newCoaDisconnect = $sourceNasServices[$fromId]['coadisconnect'];
  2695. $newCoaDisconnect_f = mysql_real_escape_string($newCoaDisconnect);
  2696. $query = "INSERT INTO `" . self::NAS_SERVICES . "` (`id`,`nasid`,`pod`,`coaconnect`,`coadisconnect`) VALUES "
  2697. . "(NULL,'" . $toId . "','" . $newPod_f . "','" . $newCoaConnect_f . "','" . $newCoaDisconnect_f . "');";
  2698. nr_query($query);
  2699. log_register('MULTIGEN NAS [' . $toId . '] CLONE SERVICES FROM NAS [' . $fromId . ']');
  2700. }
  2701. } else {
  2702. $result .= __('Something went wrong') . ': ' . __('Configuration') . ' ' . __('NAS not exists');
  2703. }
  2704. } else {
  2705. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  2706. }
  2707. return ($result);
  2708. }
  2709. /**
  2710. * Pastes some configuration string data to some NAS
  2711. *
  2712. * @param int $nasId
  2713. * @param string $confString
  2714. *
  2715. * @return string
  2716. */
  2717. public function pasteNasConfiguration($nasId, $confString) {
  2718. $result = '';
  2719. $nasId = vf($nasId, 3);
  2720. $confString = trim($confString);
  2721. if (!empty($nasId)) {
  2722. if (isset($this->allNas[$nasId])) {
  2723. if (!empty($confString)) {
  2724. $confString = base64_decode($confString);
  2725. $confString = json_decode($confString, true);
  2726. if (!empty($confString)) {
  2727. if (is_array($confString)) {
  2728. if ((isset($confString['options'])) AND ( isset($confString['attributes'])) AND ( isset($confString['services']))) {
  2729. $sourceNasOptions = $confString['options'];
  2730. $sourceNasAttributes = $confString['attributes'];
  2731. $sourceNasServices = $confString['services'];
  2732. //deleting all old NAS setup
  2733. $this->deleteAllNasConfiguration($nasId);
  2734. //Creating new NAS options
  2735. if (!empty($sourceNasOptions)) {
  2736. log_register('MULTIGEN NAS [' . $nasId . '] PASTE CONFIGURATION');
  2737. $newUserName = $sourceNasOptions['usernametype'];
  2738. $newService = $sourceNasOptions['service'];
  2739. $newOnlyActive = $sourceNasOptions['onlyactive'];
  2740. $newPort = $sourceNasOptions['port'];
  2741. //new NAS options creation
  2742. $newUserName_f = mysql_real_escape_string($newUserName);
  2743. $newService_f = mysql_real_escape_string($newService);
  2744. $newOnlyActive_f = mysql_real_escape_string($newOnlyActive);
  2745. $newPort_f = vf($newPort, 3);
  2746. $query = "INSERT INTO `" . self::NAS_OPTIONS . "` (`id`,`nasid`,`usernametype`,`service`,`onlyactive`,`port`) VALUES "
  2747. . "(NULL,'" . $nasId . "','" . $newUserName_f . "','" . $newService_f . "','" . $newOnlyActive_f . "','" . $newPort_f . "');";
  2748. nr_query($query);
  2749. log_register('MULTIGEN NAS [' . $nasId . '] PASTE USERNAME `' . $newUserName . '` SERVICE `' . $newService . '` ONLYAACTIVE `' . $newOnlyActive . '` PORT `' . $newPort . '`');
  2750. }
  2751. //Creating new NAS attribute templates
  2752. if (!empty($sourceNasAttributes)) {
  2753. foreach ($sourceNasAttributes as $io => $each) {
  2754. $newScenario = $each['scenario'];
  2755. $newScenario_f = mysql_real_escape_string($newScenario);
  2756. $newModifier = $each['modifier'];
  2757. $newModifier_f = mysql_real_escape_string($newModifier);
  2758. $newAttribute = $each['attribute'];
  2759. $newAttribute_f = mysql_real_escape_string($newAttribute);
  2760. $newOperator = $each['operator'];
  2761. $newOperator_f = mysql_real_escape_string($newOperator);
  2762. $newContent = $each['content'];
  2763. $newContent_f = mysql_real_escape_string($newContent);
  2764. $query = "INSERT INTO `" . self::NAS_ATTRIBUTES . "` (`id`,`nasid`,`scenario`,`modifier`,`attribute`,`operator`,`content`) VALUES "
  2765. . "(NULL,'" . $nasId . "','" . $newScenario_f . "','" . $newModifier_f . "','" . $newAttribute_f . "','" . $newOperator_f . "','" . $newContent_f . "');";
  2766. nr_query($query);
  2767. $newId = simple_get_lastid(self::NAS_ATTRIBUTES);
  2768. log_register('MULTIGEN NAS [' . $nasId . '] PASTE ATTRIBUTE `' . $newAttribute . '` ID [' . $newId . ']');
  2769. }
  2770. }
  2771. //Creating new NAS services
  2772. if (!empty($sourceNasServices)) {
  2773. $sourceNasServices = array_shift($sourceNasServices); //getting first service element
  2774. $newPod = $sourceNasServices['pod'];
  2775. $newPod_f = mysql_real_escape_string($newPod);
  2776. $newCoaConnect = $sourceNasServices['coaconnect'];
  2777. $newCoaConnect_f = mysql_real_escape_string($newCoaConnect);
  2778. $newCoaDisconnect = $sourceNasServices['coadisconnect'];
  2779. $newCoaDisconnect_f = mysql_real_escape_string($newCoaDisconnect);
  2780. $query = "INSERT INTO `" . self::NAS_SERVICES . "` (`id`,`nasid`,`pod`,`coaconnect`,`coadisconnect`) VALUES "
  2781. . "(NULL,'" . $nasId . "','" . $newPod_f . "','" . $newCoaConnect_f . "','" . $newCoaDisconnect_f . "');";
  2782. nr_query($query);
  2783. log_register('MULTIGEN NAS [' . $nasId . '] PASTE SERVICES');
  2784. }
  2785. } else {
  2786. $result .= __('Something went wrong') . ': EX_CONFSTRING_INCOMPLETE';
  2787. }
  2788. } else {
  2789. $result .= __('Something went wrong') . ': EX_CONFSTRING_CORRUPTED';
  2790. }
  2791. } else {
  2792. $result .= __('Something went wrong') . ': EX_CONFSTRING_CORRUPTED';
  2793. }
  2794. } else {
  2795. $result .= __('Something went wrong') . ': EX_EMPTY_CONFSTRING';
  2796. }
  2797. } else {
  2798. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  2799. }
  2800. } else {
  2801. $result .= __('Something went wrong') . ': ' . __('NAS not exists');
  2802. }
  2803. return ($result);
  2804. }
  2805. /**
  2806. * Renders controls for acct date search
  2807. *
  2808. * @return string
  2809. */
  2810. public function renderDateSerachControls() {
  2811. $result = '';
  2812. $curTime = time();
  2813. $dayAgo = $curTime - (86400 * $this->days);
  2814. $dayAgo = date("Y-m-d", $dayAgo);
  2815. $dayTomorrow = $curTime + 86400;
  2816. $dayTomorrow = date("Y-m-d", $dayTomorrow);
  2817. $preDateFrom = (wf_CheckPost(array('datefrom'))) ? $_POST['datefrom'] : $dayAgo;
  2818. $preDateTo = (wf_CheckPost(array('dateto'))) ? $_POST['dateto'] : $dayTomorrow;
  2819. $unfinishedFlag = (wf_CheckPost(array('showunfinished'))) ? true : false;
  2820. if (!wf_CheckPost(array('showunfinished'))) {
  2821. $unfinishedFlag = $this->unfinished;
  2822. }
  2823. $inputs = wf_DatePickerPreset('datefrom', $preDateFrom, false);
  2824. $inputs .= wf_DatePickerPreset('dateto', $preDateTo, false);
  2825. $inputs .= wf_CheckInput('showunfinished', __('Show only unfinished'), false, $unfinishedFlag);
  2826. $inputs .= wf_Submit(__('Show'));
  2827. $result = wf_Form('', 'POST', $inputs, 'glamour');
  2828. return ($result);
  2829. }
  2830. /**
  2831. * Renders preloaded accounting data into JSON
  2832. *
  2833. * @return void
  2834. */
  2835. public function renderAcctStatsAjlist() {
  2836. $result = '';
  2837. $totalCount = 0;
  2838. $json = new wf_JqDtHelper();
  2839. if ($this->usernamesCachingTimeout) {
  2840. $guessedUsernames = $this->cache->get('MLG_TELEPATHY', $this->usernamesCachingTimeout); //contains already guessed logins by usernames
  2841. if (empty($guessedUsernames)) {
  2842. $guessedUsernames = array();
  2843. }
  2844. } else {
  2845. $guessedUsernames = array();
  2846. }
  2847. $this->loadAcctData();
  2848. //login filtering
  2849. if ($this->usernamesCachingTimeout) {
  2850. $allUserNames = $this->cache->get('MLG_USERNAMES', $this->usernamesCachingTimeout);
  2851. if (empty($allUserNames)) {
  2852. $allUserNames = $this->getAllUserNames();
  2853. } else {
  2854. //here required to preload some users data
  2855. if (empty($this->allUserData)) {
  2856. $this->loadUserData();
  2857. if ((isset($this->altCfg[self::OPTION_SWASSIGN])) AND ( isset($this->altCfg[self::OPTION_QINQ]))) {
  2858. if (($this->altCfg[self::OPTION_SWASSIGN]) AND ( $this->altCfg[self::OPTION_QINQ])) {
  2859. $this->loadSwitches();
  2860. $this->loadSwithchAssigns();
  2861. $this->loadAllQinQ();
  2862. }
  2863. } else {
  2864. if (isset($this->altCfg[self::OPTION_UNIVERSALQINQ])) {
  2865. if ($this->altCfg[self::OPTION_UNIVERSALQINQ]) {
  2866. $this->loadAllQinQ();
  2867. }
  2868. }
  2869. }
  2870. }
  2871. //preloading culpa instance
  2872. if ($this->meaCulpaFlag) {
  2873. $this->loadMeaCulpa();
  2874. }
  2875. }
  2876. } else {
  2877. $allUserNames = $this->getAllUserNames();
  2878. }
  2879. if (ubRouting::checkGet('login')) {
  2880. $filterLogin = ubRouting::get('login');
  2881. } else {
  2882. $filterLogin = '';
  2883. }
  2884. if (!empty($this->userAcctData)) {
  2885. foreach ($this->userAcctData as $io => $each) {
  2886. $fc = '';
  2887. $efc = wf_tag('font', true);
  2888. //time filtering
  2889. if (!empty($each['acctstoptime'])) {
  2890. $startTime = strtotime($each['acctstarttime']);
  2891. $endTime = strtotime($each['acctstoptime']);
  2892. $timeOffsetRaw = $endTime - $startTime;
  2893. $timeOffset = zb_formatTime($timeOffsetRaw);
  2894. } else {
  2895. $timeOffset = '';
  2896. $timeOffsetRaw = '';
  2897. }
  2898. //some coloring
  2899. if (empty($each['acctstoptime'])) {
  2900. $fc = wf_tag('font', false, '', 'color="#ff6600"');
  2901. } else {
  2902. $fc = wf_tag('font', false, '', 'color="#005304"');
  2903. }
  2904. //try to speed up that search
  2905. if (isset($guessedUsernames[$each['username']])) {
  2906. $eachUserLogin = $guessedUsernames[$each['username']];
  2907. } else {
  2908. $eachUserLogin = $this->getUserLogin($each['username'], $allUserNames);
  2909. $guessedUsernames[$each['username']] = $eachUserLogin;
  2910. }
  2911. if (!empty($eachUserLogin)) {
  2912. $userLink = wf_Link(self::URL_PROFILE . $eachUserLogin, web_profile_icon() . ' ' . @$this->allUserData[$eachUserLogin]['fulladress']);
  2913. } else {
  2914. $userLink = '';
  2915. }
  2916. $data[] = $fc . $each['acctsessionid'] . $efc;
  2917. $data[] = $each['username'];
  2918. $data[] = $each['nasipaddress'];
  2919. $data[] = $each['nasportid'];
  2920. $data[] = $each['acctstarttime'];
  2921. $data[] = $each['acctstoptime'];
  2922. $data[] = stg_convert_size($each['acctinputoctets']);
  2923. $data[] = stg_convert_size($each['acctoutputoctets']);
  2924. $data[] = $each['framedipaddress'];
  2925. $data[] = $each['acctterminatecause'];
  2926. if (!empty($this->acctFieldsAdditional)) {
  2927. foreach ($this->acctFieldsAdditional as $ia => $eachField) {
  2928. $data[] = $each[$eachField];
  2929. }
  2930. }
  2931. $data[] = $timeOffset;
  2932. $data[] = $userLink;
  2933. if (!empty($filterLogin)) {
  2934. if ($filterLogin == $eachUserLogin) {
  2935. $json->addRow($data);
  2936. }
  2937. } else {
  2938. $json->addRow($data);
  2939. }
  2940. unset($data);
  2941. }
  2942. }
  2943. if ($this->usernamesCachingTimeout) {
  2944. $this->cache->set('MLG_TELEPATHY', $guessedUsernames, $this->usernamesCachingTimeout);
  2945. $this->cache->set('MLG_USERNAMES', $allUserNames, $this->usernamesCachingTimeout);
  2946. }
  2947. $json->getJson();
  2948. }
  2949. /**
  2950. * Renders multigen acoounting stats container
  2951. *
  2952. * @return string
  2953. */
  2954. public function renderAcctStatsContainer() {
  2955. $result = '';
  2956. $columns = array('acctsessionid', 'username', 'nasipaddress', 'nasportid', 'acctstarttime', 'acctstoptime', 'acctinputoctets', 'acctoutputoctets', 'framedipaddress', 'acctterminatecause');
  2957. if (!empty($this->acctFieldsAdditional)) {
  2958. foreach ($this->acctFieldsAdditional as $io => $each) {
  2959. $columns[] = $each;
  2960. }
  2961. }
  2962. $columns[] = 'Time';
  2963. $columns[] = 'User';
  2964. if (wf_CheckPost(array('datefrom', 'dateto'))) {
  2965. $searchDateFrom = mysql_real_escape_string($_POST['datefrom']);
  2966. $searchDateTo = mysql_real_escape_string($_POST['dateto']);
  2967. } else {
  2968. $curTime = time();
  2969. $dayAgo = $curTime - (86400 * $this->days);
  2970. $dayAgo = date("Y-m-d", $dayAgo);
  2971. $dayTomorrow = $curTime + 86400;
  2972. $dayTomorrow = date("Y-m-d", $dayTomorrow);
  2973. $searchDateFrom = $dayAgo;
  2974. $searchDateTo = $dayTomorrow;
  2975. }
  2976. if (wf_CheckPost(array('showunfinished'))) {
  2977. $unfinishedFlag = "&showunfinished=true";
  2978. } else {
  2979. $unfinishedFlag = '';
  2980. }
  2981. if (wf_CheckGet(array('lastsessions'))) {
  2982. $lastFlag = '&lastsessions=true';
  2983. } else {
  2984. $lastFlag = '';
  2985. }
  2986. if (wf_CheckGet(array('username'))) {
  2987. $userLogin = mysql_real_escape_string($_GET['username']);
  2988. $userNameFilter = '&login=' . $userLogin;
  2989. } else {
  2990. $userNameFilter = '';
  2991. $userLogin = '';
  2992. }
  2993. $ajUrl = self::URL_ME . '&ajacct=true&datefrom=' . $searchDateFrom . '&dateto=' . $searchDateTo . $unfinishedFlag . $userNameFilter . $lastFlag;
  2994. $options = '"order": [[ 0, "desc" ]]';
  2995. $result = wf_JqDtLoader($columns, $ajUrl, false, __('sessions'), 50, $options);
  2996. $result .= wf_tag('br');
  2997. if (!empty($userLogin)) {
  2998. $result .= wf_BackLink(self::URL_PROFILE . $userLogin);
  2999. $result .= wf_Link(self::URL_ME . '&userattributes=true&username=' . $userLogin, wf_img('skins/dna_icon.png') . ' ' . __('User attributes'), false, 'ubButton') . ' ';
  3000. $result .= wf_Link(self::URL_ME . '&manualpod=true&username=' . $userLogin, wf_img('skins/skull.png') . ' ' . __('Terminate user session'), false, 'ubButton') . ' ';
  3001. } else {
  3002. if (!wf_CheckGet(array('lastsessions'))) {
  3003. $result .= wf_Link(self::URL_ME . '&lastsessions=true', wf_img('skins/clock.png') . ' ' . __('Last sessions'), false, 'ubButton');
  3004. } else {
  3005. $result .= wf_BackLink(self::URL_ME);
  3006. }
  3007. }
  3008. return ($result);
  3009. }
  3010. /**
  3011. * Renders user manual user POD form
  3012. *
  3013. * @param string $userLogin
  3014. *
  3015. * @return string
  3016. */
  3017. public function renderManualPodForm($userLogin) {
  3018. $result = '';
  3019. if (!empty($userLogin)) {
  3020. //preloading some required data
  3021. if (empty($this->userNases)) {
  3022. $this->loadUserData();
  3023. $this->loadNethosts();
  3024. $this->loadNetworks();
  3025. $this->preprocessUserData();
  3026. }
  3027. if (isset($this->allUserData[$userLogin])) {
  3028. if (isset($this->userNases[$userLogin])) {
  3029. if (!empty($this->userNases[$userLogin])) {
  3030. $nasTmp = array();
  3031. foreach ($this->userNases[$userLogin] as $io => $each) {
  3032. $nasTmp[$each] = $this->allNas[$each]['nasip'] . ' - ' . $this->allNas[$each]['nasname'];
  3033. }
  3034. $inputs = wf_HiddenInput('manualpod', 'true');
  3035. $inputs .= wf_HiddenInput('manualpodlogin', $userLogin);
  3036. $inputs .= wf_Selector('manualpodnasid', $nasTmp, __('NAS'), '', false) . ' ';
  3037. $inputs .= wf_Submit(__('Send') . ' ' . __('PoD'));
  3038. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  3039. } else {
  3040. $result .= $this->messages->getStyledMessage(__('NAS not exists') . ' ' . __('for') . ' ' . $userLogin, 'error');
  3041. }
  3042. } else {
  3043. $result .= $this->messages->getStyledMessage(__('NAS not exists') . ' ' . __('for') . ' ' . $userLogin, 'error');
  3044. }
  3045. } else {
  3046. $result .= $this->messages->getStyledMessage(__('User not exists') . ': ' . $userLogin, 'error');
  3047. }
  3048. }
  3049. $result .= wf_tag('br');
  3050. $result .= wf_BackLink(self::URL_ME . '&username=' . $userLogin);
  3051. return ($result);
  3052. }
  3053. /**
  3054. * Renders actual user attributes data in all available scenarios.
  3055. *
  3056. * @param string $userLogin
  3057. *
  3058. * @return string
  3059. */
  3060. public function renderUserAttributes($userLogin) {
  3061. $result = '';
  3062. $tmpArr = array();
  3063. if (empty($this->allUserData)) {
  3064. //preloading userdata
  3065. $this->loadUserData();
  3066. //loading data required for QinQ users
  3067. if ((isset($this->altCfg[self::OPTION_SWASSIGN])) AND ( isset($this->altCfg[self::OPTION_QINQ]))) {
  3068. if (($this->altCfg[self::OPTION_SWASSIGN]) AND ( $this->altCfg[self::OPTION_QINQ])) {
  3069. $this->loadSwitches();
  3070. $this->loadSwithchAssigns();
  3071. $this->loadAllQinQ();
  3072. }
  3073. }
  3074. //preloading culpa instance
  3075. if ($this->meaCulpaFlag) {
  3076. $this->loadMeaCulpa();
  3077. }
  3078. }
  3079. if (isset($this->allUserData[$userLogin])) {
  3080. $userData = $this->allUserData[$userLogin];
  3081. $allPossibleUserNames = $this->getAllUserNames();
  3082. if (isset($allPossibleUserNames[$userLogin])) {
  3083. if (!empty($allPossibleUserNames[$userLogin])) {
  3084. $possibleUserNames = $allPossibleUserNames[$userLogin];
  3085. if (!empty($this->scenarios)) {
  3086. foreach ($this->scenarios as $scenarioId => $scenarioName) {
  3087. $scenarioTable = self::SCENARIO_PREFIX . $scenarioId;
  3088. $scenarioDb = new NyanORM($scenarioTable);
  3089. foreach ($possibleUserNames as $io => $eachPossibleUserName) {
  3090. $scenarioDb->orWhere('username', '=', $eachPossibleUserName);
  3091. }
  3092. $tmpArr[$scenarioId] = $scenarioDb->getAll();
  3093. }
  3094. } else {
  3095. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('cant read scenarios'), 'error');
  3096. }
  3097. } else {
  3098. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('cant detect username for') . ' ' . $userLogin, 'error');
  3099. }
  3100. } else {
  3101. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('cant detect username for') . ' ' . $userLogin, 'error');
  3102. }
  3103. } else {
  3104. $result .= $this->messages->getStyledMessage(__('User not exists') . ': ' . $userLogin, 'error');
  3105. }
  3106. //render available attributes data
  3107. if (!empty($tmpArr)) {
  3108. foreach ($tmpArr as $scenarioId => $attributes) {
  3109. $result .= wf_tag('h3') . __('Scenario') . ' ' . $scenarioId . wf_tag('h3', true);
  3110. if (!empty($attributes)) {
  3111. if (isset($attributes[0])) {
  3112. $scenarioColumns = array_keys($attributes[0]);
  3113. $cells = '';
  3114. //list available data colums
  3115. foreach ($scenarioColumns as $io => $each) {
  3116. $cells .= wf_TableCell($each);
  3117. }
  3118. $cells .= wf_TableCell(__('Actions'));
  3119. $rows = wf_TableRow($cells, 'row1');
  3120. //list available user attributes
  3121. foreach ($attributes as $io => $eachAttribute) {
  3122. $cells = '';
  3123. foreach ($eachAttribute as $column => $value) {
  3124. $cells .= wf_TableCell($value);
  3125. }
  3126. $delControl = self::URL_ME . '&userattributes=true&username=' . $userLogin . '&delattr=' . $eachAttribute['id'] . '&delscenario=' . $scenarioId;
  3127. $delCancelControl = self::URL_ME . '&userattributes=true&username=' . $userLogin;
  3128. $attrControls = wf_ConfirmDialogJS($delControl, web_delete_icon() . ' ' . __('Delete'), $this->messages->getDeleteAlert(), '', $delCancelControl);
  3129. $cells .= wf_TableCell($attrControls);
  3130. $rows .= wf_TableRow($cells, 'row5');
  3131. }
  3132. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  3133. } else {
  3134. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('cant detect data columns'), 'warning');
  3135. }
  3136. } else {
  3137. $result .= $this->messages->getStyledMessage(__('Nothing found'), 'info');
  3138. }
  3139. }
  3140. } else {
  3141. $result .= $this->messages->getStyledMessage(__('Nothing found'), 'warning');
  3142. }
  3143. $result .= wf_delimiter(0);
  3144. $result .= wf_BackLink(self::URL_ME . '&username=' . $userLogin);
  3145. return($result);
  3146. }
  3147. /**
  3148. * Deletes some user attribute from some scenario by its ID
  3149. *
  3150. * @param int $attributeId
  3151. * @param string $scenario
  3152. *
  3153. * @return void/string on error
  3154. */
  3155. public function deleteUserAttribute($attributeId, $scenario) {
  3156. $result = '';
  3157. if (isset($this->scenarios[$scenario])) {
  3158. $scenarioTable = self::SCENARIO_PREFIX . $scenario;
  3159. $scenarioDb = new NyanORM($scenarioTable);
  3160. $scenarioDb->where('id', '=', $attributeId);
  3161. $scenarioDb->delete();
  3162. log_register('MULTIGEN DELETE SCENARIO `' . $scenario . '` ATTRIBUTE [' . $attributeId . ']');
  3163. } else {
  3164. $result .= __('Something went wrong') . ': ' . __('Scenario') . ' ' . $scenario . ' ' . __('Not exists');
  3165. }
  3166. return($result);
  3167. }
  3168. /**
  3169. * Executes manual PoD sending if its possilble
  3170. *
  3171. * @return void/string on error
  3172. */
  3173. public function runManualPod() {
  3174. $result = '';
  3175. if (wf_CheckPost(array('manualpod', 'manualpodlogin', 'manualpodnasid'))) {
  3176. $nasId = vf($_POST['manualpodnasid'], 3);
  3177. $userLogin = $_POST['manualpodlogin'];
  3178. if (empty($this->allUserData)) {
  3179. //preloading userdata
  3180. $this->loadUserData();
  3181. //loading data required for QinQ users
  3182. if ((isset($this->altCfg[self::OPTION_SWASSIGN])) AND ( isset($this->altCfg[self::OPTION_QINQ]))) {
  3183. if (($this->altCfg[self::OPTION_SWASSIGN]) AND ( $this->altCfg[self::OPTION_QINQ])) {
  3184. $this->loadSwitches();
  3185. $this->loadSwithchAssigns();
  3186. $this->loadAllQinQ();
  3187. }
  3188. }
  3189. //preloading culpa instance
  3190. if ($this->meaCulpaFlag) {
  3191. $this->loadMeaCulpa();
  3192. }
  3193. }
  3194. if (isset($this->allUserData[$userLogin])) {
  3195. $userData = $this->allUserData[$userLogin];
  3196. if (isset($this->allNas[$nasId])) {
  3197. $nasData = $this->allNas[$nasId];
  3198. if (isset($this->nasOptions[$nasId])) {
  3199. $nasOptions = $this->nasOptions[$nasId];
  3200. $userName = $this->getLoginUsername($userLogin, $userData, $nasOptions['usernametype']);
  3201. if (!empty($userName)) {
  3202. //try to use custom PoD service or default with username
  3203. if (!empty($this->services[$nasId]['pod'])) {
  3204. $podCommand = $this->services[$nasId]['pod'];
  3205. } else {
  3206. $podCommand = '{PRINTF} "User-Name= {USERNAME}" | {SUDO} {RADCLIENT} {NASIP}:{NASPORT} disconnect {NASSECRET}';
  3207. }
  3208. $podCommand = $this->getAttributeValue($userLogin, $userName, $nasId, $podCommand);
  3209. shell_exec($podCommand);
  3210. $this->logEvent('POD MANUAL ' . $userLogin . ' AS ' . $userName, 3);
  3211. log_register('MULTIGEN POD MANUAL (' . $userLogin . ') AS `' . $userName . '` NASID [' . $nasId . ']');
  3212. } else {
  3213. $result .= __('Something went wrong') . ': ' . __('cant detect username for') . ' ' . $userLogin;
  3214. }
  3215. } else {
  3216. $result .= __('No') . ' ' . __('NAS options') . ': ' . $nasId;
  3217. }
  3218. } else {
  3219. $result .= __('NAS not exists') . ': ' . $nasId;
  3220. }
  3221. } else {
  3222. $result .= __('User not exists') . ': ' . $userLogin;
  3223. }
  3224. } else {
  3225. //what?
  3226. }
  3227. return ($result);
  3228. }
  3229. /**
  3230. * Renders multigen logs control
  3231. *
  3232. * @global object $ubillingConfig
  3233. *
  3234. * @return string
  3235. */
  3236. public function renderLogControl() {
  3237. global $ubillingConfig;
  3238. $result = '';
  3239. $logData = array();
  3240. $renderData = '';
  3241. $rows = '';
  3242. $recordsLimit = 200;
  3243. $prevTime = '';
  3244. $curTimeTime = '';
  3245. $diffTime = '';
  3246. if (file_exists(self::LOG_PATH)) {
  3247. $billCfg = $ubillingConfig->getBilling();
  3248. $tailCmd = $billCfg['TAIL'];
  3249. $runCmd = $tailCmd . ' -n ' . $recordsLimit . ' ' . self::LOG_PATH;
  3250. $rawResult = shell_exec($runCmd);
  3251. $renderData .= __('Showing') . ' ' . $recordsLimit . ' ' . __('last events') . wf_tag('br');
  3252. $renderData .= wf_Link(self::URL_ME . '&dlmultigenlog=true', wf_img('skins/icon_download.png', __('Download')) . ' ' . __('Download full log'), true);
  3253. if (!empty($rawResult)) {
  3254. $logData = explodeRows($rawResult);
  3255. $logData = array_reverse($logData); //from new to old list
  3256. if (!empty($logData)) {
  3257. $cells = wf_TableCell(__('Date'));
  3258. $cells .= wf_TableCell(__('Event'));
  3259. $rows .= wf_TableRow($cells, 'row1');
  3260. foreach ($logData as $io => $each) {
  3261. if (!empty($each)) {
  3262. $eachEntry = explode(' ', $each);
  3263. $cells = wf_TableCell($eachEntry[0] . ' ' . $eachEntry[1]);
  3264. $cells .= wf_TableCell(str_replace(($eachEntry[0] . ' ' . $eachEntry[1]), '', $each));
  3265. $rows .= wf_TableRow($cells, 'row3');
  3266. }
  3267. }
  3268. $renderData .= wf_TableBody($rows, '100%', 0, 'sortable');
  3269. }
  3270. } else {
  3271. $renderData .= $this->messages->getStyledMessage(__('Nothing found'), 'warning');
  3272. }
  3273. $result = wf_modal(wf_img('skins/log_icon_small.png', __('Attributes regeneration log')), __('Attributes regeneration log'), $renderData, '', '1280', '600');
  3274. }
  3275. return ($result);
  3276. }
  3277. /**
  3278. * Performs downloading of log
  3279. *
  3280. * @return void
  3281. */
  3282. public function logDownload() {
  3283. if (file_exists(self::LOG_PATH)) {
  3284. zb_DownloadFile(self::LOG_PATH);
  3285. } else {
  3286. show_error(__('Something went wrong') . ': EX_FILE_NOT_FOUND ' . self::LOG_PATH);
  3287. }
  3288. }
  3289. /**
  3290. * Loads existing aggregated traffic data from database
  3291. *
  3292. * @return void
  3293. */
  3294. protected function loadAcctTraffData() {
  3295. $query = "select * from `" . self::NAS_TRAFFIC . "`;";
  3296. $all = simple_queryall($query);
  3297. if (!empty($all)) {
  3298. foreach ($all as $io => $each) {
  3299. $this->previousTraffic[$each['login']] = $each;
  3300. }
  3301. }
  3302. if ($this->ishimuraFlag) {
  3303. $query = "select * from `" . self::NAS_ISHIMURA . "` WHERE `year`='" . curyear() . "' AND `month`='" . date("n") . "';";
  3304. $all = simple_queryall($query);
  3305. if (!empty($all)) {
  3306. foreach ($all as $io => $each) {
  3307. $this->trafficArchive[$each['login']] = $each;
  3308. }
  3309. }
  3310. }
  3311. }
  3312. /**
  3313. * Loads existing aggregated traffic data from database
  3314. *
  3315. * @return void
  3316. */
  3317. protected function loadUserTraffData() {
  3318. $trafficDataTable = (!$this->ishimuraFlag) ? 'users' : self::NAS_ISHIMURA;
  3319. $query = "SELECT `login`,`D0`,`U0` FROM `" . $trafficDataTable . "`;";
  3320. $all = simple_queryall($query);
  3321. if (!empty($all)) {
  3322. foreach ($all as $io => $each) {
  3323. $this->usersTraffic[$each['login']]['D0'] = $each['D0'];
  3324. $this->usersTraffic[$each['login']]['U0'] = $each['U0'];
  3325. }
  3326. }
  3327. }
  3328. /**
  3329. * Performs preprocessing of current accounting traffic and stores it into database
  3330. *
  3331. * @return void
  3332. */
  3333. public function aggregateTraffic() {
  3334. $this->loadAcctTraffData();
  3335. $this->loadUserTraffData();
  3336. if ($this->ishimuraFlag) {
  3337. $this->loadUserCash();
  3338. }
  3339. $currentTimestamp = time();
  3340. $dateTo = date("Y-m-d H:i:s", $currentTimestamp);
  3341. $lastRunTimestamp = $this->cache->get('MLG_TRAFFLASTRUN', 2592000);
  3342. if (empty($lastRunTimestamp)) {
  3343. $lastRunTimestamp = $currentTimestamp - 3600;
  3344. }
  3345. $dateFrom = date("Y-m-d H:i:s", $lastRunTimestamp);
  3346. $allUserNames = $this->getAllUserNames();
  3347. $this->cache->set('MLG_TRAFFLASTRUN', $currentTimestamp, 2592000);
  3348. $query = "SELECT `username`,`acctoutputoctets`,`acctinputoctets`,`acctupdatetime`,`acctstoptime` from `" . self::NAS_ACCT . "`"
  3349. . " WHERE `acctupdatetime` BETWEEN '" . $dateFrom . "' AND '" . $dateTo . "' ORDER BY `radacctid` DESC;";
  3350. $all = simple_queryall($query);
  3351. if (!empty($all)) {
  3352. foreach ($all as $io => $each) {
  3353. $loginDetect = $this->getUserLogin($each['username'], $allUserNames);
  3354. if (!empty($loginDetect)) {
  3355. $activity = (empty($each['acctstoptime'])) ? 1 : 0;
  3356. if (isset($this->currentTraffic[$loginDetect])) {
  3357. $this->currentTraffic[$loginDetect]['down'] += $each['acctoutputoctets'];
  3358. $this->currentTraffic[$loginDetect]['up'] += $each['acctinputoctets'];
  3359. } else {
  3360. $this->currentTraffic[$loginDetect]['down'] = $each['acctoutputoctets'];
  3361. $this->currentTraffic[$loginDetect]['up'] = $each['acctinputoctets'];
  3362. $this->currentTraffic[$loginDetect]['activity'] = $activity;
  3363. }
  3364. }
  3365. }
  3366. if (!empty($this->currentTraffic)) {
  3367. foreach ($this->currentTraffic as $changedLogin => $currentTrafficData) {
  3368. //preventing first run issues
  3369. if ($this->ishimuraFlag) {
  3370. if (!isset($this->usersTraffic[$changedLogin])) {
  3371. $this->usersTraffic[$changedLogin]['D0'] = 0;
  3372. $this->usersTraffic[$changedLogin]['U0'] = 0;
  3373. }
  3374. }
  3375. if (isset($this->usersTraffic[$changedLogin])) {
  3376. $stgDownTraffic = $this->usersTraffic[$changedLogin]['D0'];
  3377. $stgUpTraffic = $this->usersTraffic[$changedLogin]['U0'];
  3378. if (isset($this->previousTraffic[$changedLogin])) {
  3379. $previousDownTraffic = $this->previousTraffic[$changedLogin]['down'];
  3380. $previousUpTraffic = $this->previousTraffic[$changedLogin]['up'];
  3381. } else {
  3382. $previousDownTraffic = 0;
  3383. $previousUpTraffic = 0;
  3384. }
  3385. $lastActivity = $currentTrafficData['activity'];
  3386. $diffDownTraffic = $currentTrafficData['down'] - $previousDownTraffic;
  3387. $diffUpTraffic = $currentTrafficData['up'] - $previousUpTraffic;
  3388. $newDownTraffic = $stgDownTraffic + $diffDownTraffic;
  3389. $newUpTraffic = $stgUpTraffic + $diffUpTraffic;
  3390. if (($diffDownTraffic != 0) OR ( $diffUpTraffic != 0)) {
  3391. $this->saveTrafficData($changedLogin, $newDownTraffic, $newUpTraffic);
  3392. $newPreviousDown = $previousDownTraffic + $diffDownTraffic;
  3393. $newPreviousUp = $previousUpTraffic + $diffUpTraffic;
  3394. $this->savePreviousTraffic($changedLogin, $newPreviousDown, $newPreviousUp, $lastActivity);
  3395. $this->logEvent('MULTIGEN TRAFFIC SAVE (' . $changedLogin . ') ' . $newDownTraffic . '/' . $newUpTraffic, 4);
  3396. }
  3397. }
  3398. }
  3399. }
  3400. }
  3401. }
  3402. /**
  3403. * Sets traffic value via stargazer configurator or ishimura ne configurator, lol
  3404. *
  3405. * @param string $login
  3406. * @param int $trafficDown
  3407. * @param int $trafficUp
  3408. *
  3409. * @return void
  3410. */
  3411. protected function saveTrafficData($login, $trafficDown, $trafficUp) {
  3412. if (!$this->ishimuraFlag) {
  3413. $command = $this->billCfg['SGCONF'] . ' set -s ' . $this->billCfg['STG_HOST'] . ' -p ' . $this->billCfg['STG_PORT'] . ' -a ' . $this->billCfg['STG_LOGIN'] . ' -w ' . $this->billCfg['STG_PASSWD'] . ' -u ' . $login . ' --d0 ' . $trafficDown . ' --u0 ' . $trafficUp;
  3414. shell_exec($command);
  3415. } else {
  3416. $curyear = curyear();
  3417. $curmonth = date("n");
  3418. $currentCash = (isset($this->allUsersCash[$login])) ? $this->allUsersCash[$login] : 0;
  3419. if (isset($this->trafficArchive[$login])) {
  3420. $where = "WHERE `login`='" . $login . "' AND `year`='" . $curyear . "' AND `month`='" . $curmonth . "'";
  3421. simple_update_field(self::NAS_ISHIMURA, 'D0', $trafficDown, $where);
  3422. simple_update_field(self::NAS_ISHIMURA, 'U0', $trafficUp, $where);
  3423. simple_update_field(self::NAS_ISHIMURA, 'cash', $currentCash, $where);
  3424. } else {
  3425. $query = "INSERT INTO `" . self::NAS_ISHIMURA . "` (`login`,`month`,`year`,`U0`,`D0`,`cash`) VALUES"
  3426. . "('" . $login . "','" . $curmonth . "','" . $curyear . "','" . $trafficUp . "','" . $trafficDown . "','" . $currentCash . "');";
  3427. nr_query($query);
  3428. }
  3429. }
  3430. }
  3431. /**
  3432. * Saves current run traffic data into database
  3433. *
  3434. * @param string $login
  3435. * @param int $trafficDown
  3436. * @param int $trafficUp
  3437. * @param int $activity
  3438. *
  3439. * @return void
  3440. */
  3441. protected function savePreviousTraffic($login, $trafficDown, $trafficUp, $activity) {
  3442. $login = mysql_real_escape_string($login);
  3443. if (isset($this->previousTraffic[$login])) {
  3444. $query = "UPDATE `" . self::NAS_TRAFFIC . "` SET `down`='" . $trafficDown . "', `up`='" . $trafficUp . "', `act`='" . $activity . "' WHERE `login`='" . $login . "';";
  3445. nr_query($query);
  3446. } else {
  3447. //new user appeared
  3448. $query = "INSERT INTO `" . self::NAS_TRAFFIC . "` (`login`,`down`,`up`,`act`) VALUES "
  3449. . "('" . $login . "','" . $trafficDown . "','" . $trafficUp . "'," . $activity . ");";
  3450. nr_query($query);
  3451. }
  3452. }
  3453. /**
  3454. * Performs check of multigen-rebuild lock
  3455. *
  3456. * @return bool
  3457. */
  3458. public function isMultigenRunning() {
  3459. return($this->stardust->isRunning());
  3460. }
  3461. /**
  3462. * Locks Multigen regeneration
  3463. *
  3464. * @return void
  3465. */
  3466. public function runPidStart() {
  3467. $this->stardust->start();
  3468. }
  3469. /**
  3470. * Releases Multigen regeneration lock
  3471. *
  3472. * @return void
  3473. */
  3474. public function runPidEnd() {
  3475. $this->stardust->stop();
  3476. }
  3477. }