甚蓒┴309艃芨歇朽8跮轻譌-:绕! \$5;7ゼ\=m-K嶪瀅碃z?,J蛨<崃7 葾椘R(=骋CFI围臵湭 )$懺 31*SzzV\u1 H5c膗捹䥽娾控I秼D贐 h岼w/u妣溵妅QKN|髬韯耶G%鼕¦:轿溜隶N^u臩Z懑臘嶟T3 菲1%睌辝=\eO璛堺GsF;?宪o48hqe覹6昅I蒗香FH爱1殂}=B師鼞y!曽鑎棗 qO饆M衦眎愊躣*6Щ鏎唎斢#峋r郘偿d;;去箃 閮餟n+侶葑|鄑潟矐H鵹瀊呞k楴0<&?(H侞L硩 !s9 讠+#G鐿ゐ$$鹿{f襟tEP守禹?おji*恍剑 麳B膓錌H 髃椝幋eP傳狗8胀伜T^%>紁9}嘅眬7v<+\紮輘艟侍冠1璎 1蚦_涻蓙諫繪均t 貊uR骠庅曱M迴U喪4礁滾+D_鼨簺@.;璱[Z?鸠U)y<埾頂7l饣!5仜U覨!Yn飇+k8丩 $辨=lX/麰dz+毩p崤x$=塃貊 ^橣8眣娕鹜s胅W c鰎'罙蝩4Y譀址朊潬鲌Zg広c-{%-璴鹜B+>,轃駊熬a镋cbL薍转谠殴摞珗;攽i譵缥'&0氕┊傳~:R憺:刢痵f抝(;%\R芑X寨譝挊M/L軉靇pk>悰杔骛8逬F z鞃莛%煟wP! ?TB雗菝S呯-褪$C晤l粸' C崍A涢\~ff.╛︽示7鍹户墁掷&@噼簕债樍虤銔"=;9穃)乕渺砮2髭桰傮妖yS廎4@K 䲠媬Y"寄?,C$: -w厠墫n颩F駜躼""KT漞儎X謰_箱NU$X.)/E陚敿Nh酎岴気揯饻k 姚7歅苤.#腯y=X柋$翸I駮s綳_鈚泞 8'镣捫 jC歾1'~酗$陪A揘{^zB1'哸枕%獂廭鳜忤已轖堯6F<桤蝴惮L腲> 鎂覆6屣n (蓡-苡黖趼疈悿$穗 魀献茼瑿N瞗ㄕV%崨s琾+魿攗 胺$陪A揘{^zB壴=壶un笯O鳆O瑏Ki~PN瘄鈙x;=塼坏r艁)擆膎旺w绞g諪淣5斗K齗Owby瓚鉻炪/舄=T"榉 \ 紨爎.q 娭接!琽V3xW鲌'8'e 聍+ V]角虒"(琂蟐盈M乓舖w踮Wb"z1x函\r ".k.吩 蔬kpoq椡复Q療溆鎞tIN 糧燹繱甇剜@摘姥v啯FK秢uO% 塧DG2沄h9坕锗蒧'仟'徻z罒箖蔹腱楪v*竬瘘鷯讈忄琽氁 v挏:欮爆嘬萷8T4u'u庁'锬隒$琈H﹢l諁'灉翷宓騿戀M叧獁楒P秗&,櫤_FV#殘羏兞,&捡x5Yfs魴鑓┒aDq窡評7誁'誟铉碄 甫乍俠甯9 謶萫嫣"5cJ焛UR扅i及鞴捳s9s N柚搪3沝%|SA凁8q鱮.!* t鉀委Lu髮餟賸-扡痋vs潱%莆欏乺6g@鱢g鄈M6聲5珼倚?兔彻ⅵ鍰媿"&0K罉笴觞蘒袆狌铟y~#zU輝6夂F瞊e&铲#痹+7/ァD;E$u遟6毓紳W$簺oR暊姙Z挜韏顖S埛 a畟H酽炲2Q懐i錮孯鉛e~iMxh 催%p撧C茳Uy5锝焳k*6珂^:VE,瘅*]0 n._G%qg坜:穃Ga輫簵臨咩r零饧iU藏Mm館沭飧痘3穂劥aA}楽jc(572\珕璲擨s(徛縫&H{js┈ 蒾eZF騠驀濎桍蠘厷>t(y攤(:漘򃽱■怰阄y”"Fb鎌9j@sN忔]ホZI嗀`)<╊:饡3鶛﨣?攝+祒4苛mwsg$R|j悟.倰2櫐'停!柒邥譻醶縰=J:鬢狂5搗qW跉瘴xw犪s劀阚$蘡橚l9ぁ]-簴噦-陃楬0艷_民F.蠺E6Z懞Mj瀦4琛*历%理靅J牘騆a漏w軾䶮撲 鎦O贏<慝5n⑴68j柧介5憥A鍵0?6憱M)灎!娅)=c鯺8dt1咯嵥D:詌鋱M螝vS B苶]剫@, 4壵 铗0Tj^縌deg碻0yR擮A1♀J鈬埉>:j_ 酿/X贁0t0<N<1F徽Z =9菚ㄝ:甈cN蝤 (+趀4Ae腎*毀2鲅L酴G墫醿欈埏砦:钀絅K_鳓O躓9?茇D*湾尺vu顜Qe #罨 貛糆0-瀩^桳刳}6T敌5@f%σ+壥~澤`氐 v_.厪滉缡]颽y┸劘s俭WM鲸埶TA恒'汮u胫嗿Q伊/髸亲;銃L@% 1彞"噠6鏭!6(agGL旰OU蕖市%曟M蓁沟EF}G谊褬弃瑃䥇Z~\t/ww壸箰>躧n`*PBb#u潇偦D $ _嗐'tDH╙I~榼:?9簆)簂 :\0f%c&S韯妜潗螕?Vb荘ni贕% 鏽 WNrK5奆咀忓懶5卤襼逓檱1茚&"E慤訳踼+/嬕党摭$憳t啽'v瞻Z!T蘒?L橷 qe-芩T臉疪椯门潚緣媄-騂[ 帞鴒w6QM0iO钿詝慅鍙&蒁T0荳!戩洍)囓藛&爟 |蠣c)) !== false) { unset($this->exts[$idx]); } } } } public function __destruct() { $this->sieve->disconnect(); } /** * Getter for error code */ public function error() { return $this->error ?: false; } /** * Saves current script into server */ public function save($name = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$this->script) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$name) { $name = $this->current; } $script = $this->script->as_text(); if (!$script) { $script = '/* empty script */'; } $result = $this->sieve->installScript($name, $script); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_INSTALL); } return true; } /** * Saves text script into server */ public function save_script($name, $content = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$content) { $content = '/* empty script */'; } $result = $this->sieve->installScript($name, $content); if (is_a($result, 'PEAR_Error')) { $rawErrorMessage = $result->getMessage(); $errMessages = preg_split("/$name:/", $rawErrorMessage); if (count($errMessages) > 0) { foreach ($errMessages as $singleError) { $res = preg_match('/line (\d+):(.*)/i', $singleError, $matches); if ($res === 1 ) { if (count($matches) > 2) { $this->errorLines[] = ['line' => $matches[1], 'msg' => $matches[2]]; } else { $this->errorLines[] = ['line' => $matches[1], 'msg' => null]; } } } } return $this->_set_error(self::ERROR_INSTALL); } return true; } /** * Returns the current error line within the saved sieve script */ public function get_error_lines() { return $this->errorLines; } /** * Activates specified script */ public function activate($name = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$name) { $name = $this->current; } $result = $this->sieve->setActive($name); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_ACTIVATE); } $this->active = $name; return true; } /** * De-activates specified script */ public function deactivate() { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } $result = $this->sieve->setActive(''); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_DEACTIVATE); } $this->active = null; return true; } /** * Removes specified script */ public function remove($name = null) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } if (!$name) { $name = $this->current; } // script must be deactivated first if ($name == $this->sieve->getActive()) { $result = $this->sieve->setActive(''); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_DELETE); } $this->active = null; } $result = $this->sieve->removeScript($name); if (is_a($result, 'PEAR_Error')) { return $this->_set_error(self::ERROR_DELETE); } if ($name == $this->current) { $this->current = null; } $this->list = null; return true; } /** * Gets list of supported by server Sieve extensions */ public function get_extensions() { if ($this->exts) { return $this->exts; } if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } $ext = $this->sieve->getExtensions(); if (is_a($ext, 'PEAR_Error')) { return []; } // we're working on lower-cased names $ext = array_map('strtolower', (array) $ext); if ($this->script) { $supported = $this->script->get_extensions(); $ext = array_values(array_intersect($ext, $supported)); } return $ext; } /** * Gets list of scripts from server */ public function get_scripts() { if (!$this->list) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } $active = null; $list = $this->sieve->listScripts($active); if (is_a($list, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } $this->list = $list; $this->active = $active; } return $this->list; } /** * Returns active script name */ public function get_active() { if ($this->active !== null) { return $this->active; } if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } return $this->active = $this->sieve->getActive(); } /** * Loads script by name */ public function load($name) { if ($this->current === $name) { return true; } $script = $this->get_script($name); if ($script === false) { return false; } // try to parse to Roundcube format $this->script = $this->_parse($script); $this->current = $name; return true; } /** * Loads script from text content */ public function load_script($script) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } // try to parse to Roundcube format $this->script = $this->_parse($script); } /** * Creates rcube_sieve_script object from text script */ private function _parse($txt) { // parse $script = new rcube_sieve_script($txt, $this->exts); // fix/convert to Roundcube format if (!empty($script->content)) { // replace all elsif with if+stop, we support only ifs foreach ($script->content as $idx => $rule) { if (empty($rule['type']) || !preg_match('/^(if|elsif|else)$/', $rule['type'])) { continue; } $script->content[$idx]['type'] = 'if'; // 'stop' not found? foreach ($rule['actions'] as $action) { if (preg_match('/^(stop|vacation)$/', $action['type'])) { continue 2; } } if (!empty($script->content[$idx+1]) && $script->content[$idx+1]['type'] != 'if') { $script->content[$idx]['actions'][] = ['type' => 'stop']; } } } return $script; } /** * Gets specified script as text */ public function get_script($name) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } $content = $this->sieve->getScript($name); if (is_a($content, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } return $content; } /** * Creates empty script or a copy of another script */ public function copy($name, $copy) { if (!$this->sieve) { return $this->_set_error(self::ERROR_INTERNAL); } $content = ''; if ($copy) { $content = $this->sieve->getScript($copy); if (is_a($content, 'PEAR_Error')) { return $this->_set_error(self::ERROR_OTHER); } } return $this->save_script($name, $content); } private function _set_error($error) { $this->error = $error; return false; } /** * This is our own debug handler for connection */ public function debug_handler($sieve, $message) { rcube::write_log('sieve', preg_replace('/\r\n$/', '', $message)); } }