/**
  * Remove um contato recente
  *
  * @license    http://www.gnu.org/copyleft/gpl.html GPL
  * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
  * @sponsor    Caixa Econômica Federal
  * @author     José Vicente Tezza Jr. 
  * @access     public
  * */
 function delete($request, $id)
 {
     $this->secured();
     //verificar se a preferencia de contatos dinamicos nao esta ativada
     if (!$this->isEnabledDynamicContacts(Config::me("uidNumber"))) {
         $response = new Response($request);
         $this->createException($request, $response, Response::UNAUTHORIZED, 'Resource unauthorized', 'disabled dynamic contacts preference');
         return $response;
     }
     $response = new Response($request);
     $response->addHeader('Content-type', 'aplication/json');
     $response->code = Response::NOCONTENT;
     try {
         //Verifica se o recurso existe
         $dinamicContact = Controller::read(array('concept' => 'dynamicContact', 'id' => $id));
         //Se existe o recurso
         if ($dinamicContact) {
             $delete = Controller::delete(array('concept' => 'dynamicContact', 'id' => $id));
             if (!$delete) {
                 $this->createException($request, $response, Response::INTERNALSERVERERROR, 'Internal Server Error', Controller::service('PostgreSQL')->error);
                 return $response;
             }
         } else {
             $this->createException($request, $response, Response::NOTFOUND, 'Bad request', 'Invalid data');
             return $response;
         }
     } catch (Exception $ex) {
         $this->createException($request, $response, Response::INTERNALSERVERERROR, 'Internal Server Error', 'Internal Server Error');
         return $response;
     }
     $response->body = json_encode(null);
     return $response;
 }
Example #2
0
 private static function _makeVTODO($schedulable, $component, $params)
 {
     $interation = array();
     $todoID = isset($schedulable['id']) ? $schedulable['id'] : mt_rand() . '(Formatter)';
     /* Data de Inicio */
     $startTime = $component->getProperty('dtstart', false, true);
     $tzid = isset($startTime['params']['TZID']) ? $startTime['params']['TZID'] : $params['X-WR-TIMEZONE'];
     /* Tiem zone do evento */
     if ($tzid) {
         $tzid = self::nomalizeTZID($tzid);
         $schedulable['timezone'] = $tzid;
     } else {
         $schedulable['timezone'] = isset($params['calendar_timezone']) ? $params['calendar_timezone'] : 'America/Sao_Paulo';
     }
     $objTimezone = new DateTimeZone($schedulable['timezone']);
     if (isset($startTime['params']['VALUE']) && $startTime['params']['VALUE'] === 'DATE' && isset($params['calendar_timezone'])) {
         $schedulable['allDay'] = 1;
         $schedulable['startTime'] = self::date2timestamp($startTime['value']) - self::_getTzOffset('UTC', $schedulable['timezone'], '@' . self::date2timestamp($startTime['value'])) . '000';
     } elseif ($tzid && !isset($startTime['value']['tz'])) {
         /* Caso não tenha um tz na data mais exista um parametro TZID deve ser aplicado o timezone do TZID a data */
         $schedulable['startTime'] = self::date2timestamp($startTime['value']) - self::_getTzOffset('UTC', $tzid, '@' . self::date2timestamp($startTime['value'])) . '000';
         $schedulable['allDay'] = 0;
     } else {
         $schedulable['startTime'] = self::date2timestamp($startTime['value']) . '000';
         if (strpos($params['prodid'], 'Outlook') !== false) {
             //Se o ics veio em utc não aplicar horario de verão
             $sTime = new DateTime('@' . (int) ($schedulable['startTime'] / 1000), new DateTimeZone('UTC'));
             $sTime->setTimezone($objTimezone);
             if ($sTime->format('I')) {
                 //Se o ics veio em utc não aplicar horario de verão
                 $schedulable['startTime'] = $schedulable['startTime'] - 3600000;
             }
         }
     }
     /* Data de Termino */
     if ($due = $component->getProperty('due', false, true)) {
         $tzid = isset($due['params']['TZID']) ? $due['params']['TZID'] : $params['X-WR-TIMEZONE'];
         if ($tzid) {
             $tzid = self::nomalizeTZID($tzid);
         }
         if (isset($due['params']['VALUE']) && $due['params']['VALUE'] === 'DATE' && isset($params['calendar_timezone'])) {
             $schedulable['due'] = self::date2timestamp($due['value']) - self::_getTzOffset('UTC', $schedulable['timezone'], '@' . self::date2timestamp($due['value'])) . '000';
         } else {
             if ($tzid && !isset($due['value']['tz'])) {
                 /* Caso não tenha um tz na data mais exista um parametro TZID deve ser aplicado o timezone do TZID a data */
                 $schedulable['due'] = self::date2timestamp($due['value']) - self::_getTzOffset('UTC', $tzid, '@' . self::date2timestamp($due['value'])) . '000';
             } else {
                 $schedulable['due'] = self::date2timestamp($due['value']) . '000';
                 if (strpos($params['prodid'], 'Outlook') !== false) {
                     //Se o ics veio em utc não aplicar horario de verão
                     $dueTime = new DateTime('@' . (int) ($schedulable['due'] / 1000), new DateTimeZone('UTC'));
                     $dueTime->setTimezone($objTimezone);
                     if ($dueTime->format('I')) {
                         $schedulable['due'] = $schedulable['due'] - 3600000;
                     }
                 }
             }
         }
         $schedulable['endTime'] = $schedulable['due'];
     } else {
         $schedulable['endTime'] = $schedulable['startTime'];
     }
     $schedulable['type'] = '2';
     //type schedulable
     $schedulable['summary'] = mb_convert_encoding($component->getProperty('summary', false, false), 'ISO-8859-1', 'UTF-8,ISO-8859-1');
     /* Definindo Description */
     if ($desc = $component->getProperty('description', false, false)) {
         $schedulable['description'] = mb_convert_encoding(str_ireplace(array('\\n', '\\t'), array("\n", "\t"), $desc), 'ISO-8859-1', 'UTF-8,ISO-8859-1');
     }
     /* Definindo Class */
     $class = $component->getProperty('class', false, false);
     if ($class && defined(constant(strtoupper('CLASS_' . $class)))) {
         $schedulable['class'] = constant(strtoupper('CLASS_' . $class));
     } else {
         if (!isset($schedulable['class'])) {
             $schedulable['class'] = CLASS_PRIVATE;
         }
     }
     // padrão classe private
     $schedulable['calendar'] = $params['calendar'];
     $participantsInTodo = array();
     //TODO: Participants com delegated nao estao sendo levados em conta
     while ($property = $component->getProperty('attendee', FALSE, TRUE)) {
         $participant = array();
         $mailUser = trim(str_replace('MAILTO:', '', $property['value']));
         $participantID = ($tpID = self::_getParticipantByMail($mailUser, $schedulable['participants'])) ? $tpID : mt_rand() . '2(Formatter)';
         $participant['schedulable'] = $todoID;
         if (isset($params['status']) && $mailUser == Config::me('mail')) {
             $participant['status'] = $params['status'];
         } else {
             $participant['status'] = isset($property['params']['PARTSTAT']) && constant('STATUS_' . $property['params']['PARTSTAT']) !== null ? constant('STATUS_' . $property['params']['PARTSTAT']) : STATUS_UNANSWERED;
         }
         $participant['isOrganizer'] = '0';
         /* Verifica se este usuario é um usuario interno do ldap */
         $intUser = Controller::find(array('concept' => 'user'), array('id', 'isExternal'), array('filter' => array('OR', array('=', 'mail', $mailUser), array('=', 'mailAlternateAddress', $mailUser))));
         $user = null;
         if ($intUser && count($intUser) > 0) {
             $participant['isExternal'] = isset($intUser[0]['isExternal']) ? $intUser[0]['isExternal'] : 0;
             $participant['user'] = $intUser[0]['id'];
         } else {
             $participant['isExternal'] = 1;
             /* Gera um randon id para o contexto formater */
             $userID = mt_rand() . '4(Formatter)';
             $user['mail'] = $mailUser;
             $user['isExternal'] = '1';
             $user['name'] = isset($property['params']['CN']) ? $property['params']['CN'] : '';
             $user['participants'] = array($participantID);
             $participant['user'] = $userID;
             $interation['user://' . $userID] = $user;
         }
         $interation['participant://' . $participantID] = $participant;
         $schedulable['participants'][] = $participantID;
     }
     if ($property = $component->getProperty('organizer', FALSE, TRUE)) {
         $participant = array();
         $mailUser = trim(str_replace('MAILTO:', '', $property['value']));
         if ($participant = self::_getParticipantByMail($mailUser, $schedulable['participants'], true)) {
             $participantID = $participant['id'];
         } else {
             $participant = array();
             $participantID = mt_rand() . '2(Formatter)';
             $participant['schedulable'] = $todoID;
             $participant['status'] = isset($property['params']['PARTSTAT']) && constant('STATUS_' . $property['params']['PARTSTAT']) !== null ? constant('STATUS_' . $property['params']['PARTSTAT']) : STATUS_UNANSWERED;
             $participant['isOrganizer'] = '1';
             $participant['acl'] = 'rowi';
         }
         /* Verifica se este usuario é um usuario interno do ldap */
         $intUser = Controller::find(array('concept' => 'user'), array('id', 'isExternal'), array('filter' => array('OR', array('=', 'mail', $mailUser), array('=', 'mailAlternateAddress', $mailUser))));
         $user = null;
         if ($intUser && count($intUser) > 0) {
             $participant['isExternal'] = isset($intUser[0]['isExternal']) ? $intUser[0]['isExternal'] : 0;
             $participant['user'] = $intUser[0]['id'];
         } else {
             $participant['isExternal'] = 1;
             /* Gera um randon id para o contexto formater */
             $userID = mt_rand() . '4(Formatter)';
             $user['mail'] = $mailUser;
             $user['name'] = isset($property['params']['CN']) ? $property['params']['CN'] : '';
             $user['participants'] = array($participantID);
             $user['isExternal'] = '1';
             $participant['user'] = $userID;
             $interation['user://' . $userID] = $user;
         }
         $interation['participant://' . $participantID] = $participant;
         $schedulable['participants'][] = $participantID;
     } else {
         if (!isset($schedulable['participants']) || !is_array($schedulable['participants']) || count($schedulable['participants']) < 1) {
             //caso não tenha organizador o usuario se torna organizador
             $user = Controller::read(array('concept' => 'user', 'id' => $params['owner']), array('mail'));
             if (!self::_getParticipantByMail($user['mail'], $schedulable['participants'])) {
                 $participantID = mt_rand() . '2(Formatter)';
                 $participant['schedulable'] = $todoID;
                 $participant['status'] = STATUS_CONFIRMED;
                 $participant['isOrganizer'] = '1';
                 $participant['acl'] = 'rowi';
                 $participant['isExternal'] = 0;
                 $participant['user'] = $params['owner'];
                 $interation['participant://' . $participantID] = $participant;
                 $schedulable['participants'][] = $participantID;
             }
         }
     }
     $alarms = array();
     /* Definindo ALARMES */
     while ($alarmComp = $component->getComponent('valarm')) {
         $alarm = array();
         $alarmID = mt_rand() . '6(Formatter)';
         $action = $alarmComp->getProperty('action', false, true);
         $trygger = $alarmComp->getProperty('trigger', false, true);
         $alarm['type'] = self::decodeAlarmAction($action['value']);
         if (isset($trygger['value']['day'])) {
             $alarm['time'] = $trygger['value']['day'];
             $alarm['unit'] = 'd';
         } else {
             if (isset($trygger['value']['hour'])) {
                 $alarm['time'] = $trygger['value']['hour'];
                 $alarm['unit'] = 'h';
             } else {
                 if (isset($trygger['value']['min'])) {
                     $alarm['time'] = $trygger['value']['min'];
                     $alarm['unit'] = 'm';
                 }
             }
         }
         foreach ($interation as $iint => &$vint) {
             if (isset($vint['user']) && $vint['user'] == Config::me('uidNumber')) {
                 $alarm['participant'] = str_replace('participant://', '', $iint);
                 $vint['alarms'][] = $alarmID;
             }
         }
         $alarm['schedulable'] = $eventID;
         $interation['alarm://' . $alarmID] = $alarm;
     }
     /* Definindo DTSTAMP */
     if ($dtstamp = self::_getTime($component, 'dtstamp')) {
         $schedulable['dtstamp'] = $dtstamp;
     }
     /* Definindo TRANSP */
     if (($tranp = $component->getProperty('transp', false, true)) && $tranp && is_string($tranp) && strtoupper($tranp) == 'OPAQUE') {
         $schedulable['transparent'] = 1;
     }
     /* Definindo last_update */
     if ($lastUpdate = self::_getTime($component, 'LAST-MODIFIED')) {
         $schedulable['lastUpdate'] = $lastUpdate;
     }
     if ($status = $component->getProperty('status', false, false)) {
         $schedulable['status'] = self::decodeStatusTodo(mb_convert_encoding(str_ireplace(array('\\n', '\\t'), array("\n", "\t"), $status), 'UTF-8', 'UTF-8,ISO-8859-1'));
     }
     if ($sequence = $component->getProperty('SEQUENCE', false, false)) {
         $schedulable['sequence'] = $sequence;
     }
     if ($uid = $component->getProperty('uid', false, false)) {
     }
     $schedulable['uid'] = $uid;
     while ($attach = $component->getProperty('ATTACH', FALSE, TRUE)) {
         $attachCurrent = array('name' => $attach['params']['X-FILENAME'], 'size' => strlen($attach['value']), 'type' => self::_getContentType($attach['params']['X-FILENAME']));
         $ids = Controller::find(array('concept' => 'attachment'), array('id'), array('filter' => array('AND', array('=', 'name', $attachCurrent['name']), array('=', 'size', $attachCurrent['size']), array('=', 'type', $attachCurrent['type']))));
         if (!is_array($ids)) {
             $attachCurrent['source'] = $attach['value'];
             //insere o anexo no banco e pega id para colcar no relacionamento
             $idAttachment = Controller::create(array('concept' => 'attachment'), $attachCurrent);
         } else {
             $idAttachment = array('id' => $ids[0]['id']);
         }
         $calendarToAttachmentId = mt_rand() . '2(Formatter)';
         $calendarToAttachment['attachment'] = $idAttachment['id'];
         $calendarToAttachment['schedulable'] = $eventID;
         $interation['schedulableToAttachment://' . $calendarToAttachmentId] = $calendarToAttachment;
         $schedulable['attachments'][] = $calendarToAttachmentId;
     }
     $interation['schedulable://' . $todoID] = $schedulable;
     return $interation;
 }
Example #3
0
    $calendar = Controller::read(array('concept' => 'calendar', 'id' => $params['calendar']));
    $eventsIds = array();
    foreach ($eventLinks as &$eventLink) {
        $eventsIds[] = $eventLink['schedulable'];
    }
    $events = Controller::find(array('concept' => 'schedulable'), false, array('filter' => array('IN', 'id', $eventsIds), 'deepness' => '2', 'timezones' => array($calendar['id'] => $calendar['timezone'])));
    $ics = Controller::format(array('service' => 'iCal'), $events, array('defaultTZI' => $calendar['timezone']));
    header('Content-Type: text/calendar; charset=utf-8');
    header('Content-Length: ' . mb_strlen($ics));
    header('Content-Disposition: attachment; filename="Calendar.ics"');
    header('Cache-Control: max-age=10');
    echo $ics;
    die;
}
if (isset($params['event'])) {
    $event = Controller::read(array('concept' => 'schedulable', 'id' => $params['event']));
    $attachmentRelation = Controller::find(array('concept' => 'schedulableToAttachment'), false, array('filter' => array('=', 'schedulable', $event['id'])));
    if (is_array($attachmentRelation)) {
        $attachments = array();
        foreach ($attachmentRelation as $key => $value) {
            if (isset($value['attachment']) || !!$value['attachment']) {
                $attachments[$key] = $value['attachment'];
            }
        }
        //Pega os anexos sem source
        $event['attachments'] = Controller::find(array('concept' => 'attachment'), false, array('filter' => array('IN', 'id', $attachments)));
    }
    $repeat = Controller::find(array('concept' => 'repeat'), false, array('filter' => array('=', 'schedulable', $event['id'])));
    if (is_array($repeat)) {
        $event['repeat'] = $repeat[0];
    }
 /**
  * Retorna um contato compartilhado 
  *
  * @license    http://www.gnu.org/copyleft/gpl.html GPL
  * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
  * @sponsor    Caixa Econômica Federal
  * @author     José Vicente Tezza Jr. 
  * @return     Retorna um contato Compartilhado
  * @access     public
  * */
 function get($request, $id)
 {
     $this->secured();
     $response = new Response($request);
     $response->addHeader('Content-type', 'aplication/json');
     $response->code = Response::OK;
     $h = new Hypermedia();
     $c = new Collection($request->resources, 'SharedGroupResource');
     try {
         //Recupera o contato
         $contact = Controller::find(array('concept' => 'contact'), false, array('filter' => array('=', 'id', $id)));
         if (!$contact) {
             $this->createException($request, $response, Response::NOTFOUND, 'Bad request', 'Resource not found.');
             return $response;
         }
         //Proprietario do contato
         $ownerId = $contact[0]['user'];
         $idS = array(Config::me("uidNumber"));
         $acl = array();
         //Recupera o uidNumber do usuário que compartilhou o grupo com o usuário logado
         $sql = 'SELECT acl_account as "uidNumber", acl_rights as "acl" ' . 'FROM phpgw_acl ' . 'WHERE (acl_location =   \'' . Config::me("uidNumber") . '\' AND acl_appname =  \'contactcenter\' AND acl_account = \'' . $ownerId . '\')';
         $shareds = Controller::service('PostgreSQL')->execResultSql($sql);
         //Verifica o acesso definido para o usuario logado
         $flagContact = false;
         if (!empty($shareds) && $shareds) {
             foreach ($shareds as $s) {
                 array_push($idS, $s['uidNumber']);
                 $acl[$s['uidNumber']] = $this->decodeAcl(decbin($s['acl']));
                 //verifica se o proprietario do contato habilitou o acesso de leitura para o usuario logado
                 if ($s['uidNumber'] == $ownerId && $acl[$s['uidNumber']]['read']) {
                     $flagContact = true;
                 }
             }
         }
         //Se o contato nao esta compartilhado
         if (!$flagContact) {
             $this->createException($request, $response, Response::UNAUTHORIZED, 'unauthorized', 'Resource unauthorized.');
             return $response;
         }
         //Obtem informacoes do proprietario do contato
         $userOwner = Controller::read(array('concept' => 'user', 'service' => 'OpenLDAP'), false, array('filter' => array('=', 'id', $ownerId), 'notExternal' => true));
         if (is_array($userOwner)) {
             $userOwner = $userOwner[0];
         }
         $t = new Template();
         $d = new Data();
         $d->setName('name');
         $d->setValue(null);
         $d->setPrompt('Nome do Contato');
         $d->setDataType('string');
         $d->setMaxLength(100);
         $d->setMinLength(null);
         $d->setRequired(true);
         $t->addData($d);
         $d = new Data();
         $d->setName('email');
         $d->setValue(null);
         $d->setPrompt('Email do Contato');
         $d->setDataType('string');
         $d->setMaxLength(100);
         $d->setMinLength(null);
         $d->setRequired(true);
         $t->addData($d);
         $d = new Data();
         $d->setName('telefone');
         $d->setValue(null);
         $d->setPrompt('Telefone do Contato');
         $d->setDataType('string');
         $d->setMaxLength(100);
         $d->setMinLength(null);
         $d->setRequired(true);
         $t->addData($d);
         $c->setTemplate($t);
         $d = new Data();
         $d->setName('name');
         $d->setValue($contact[0]['name']);
         $d->setPrompt('Nome do Contato');
         $d->setDataType('string');
         $d->setMaxLength('100');
         $d->setMinLength(null);
         $d->setRequired(true);
         $c->addData($d);
         $d = new Data();
         $d->setName('email');
         $d->setValue($contact[0]['email']);
         $d->setPrompt('Email do Contato');
         $d->setDataType('string');
         $d->setMaxLength('100');
         $d->setMinLength(null);
         $d->setRequired(true);
         $c->addData($d);
         $d = new Data();
         $d->setName('telephone');
         $d->setValue($contact[0]['telephone']);
         $d->setPrompt('Telefone do Contato');
         $d->setDataType('string');
         $d->setMaxLength('100');
         $d->setMinLength(null);
         $d->setRequired(true);
         $c->addData($d);
         $d = new Data();
         $d->setName('ownerId');
         $d->setValue($userOwner['id']);
         $d->setPrompt('Atributo UID (LDAP)');
         $d->setDataType('string');
         $d->setMaxLength(100);
         $d->setMinLength(null);
         $d->setRequired(true);
         $c->addData($d);
         $d = new Data();
         $d->setName('ownerName');
         $d->setValue($userOwner['name']);
         $d->setPrompt('Atributo cn (LDAP)');
         $d->setDataType('string');
         $d->setMaxLength(100);
         $d->setMinLength(null);
         $d->setRequired(true);
         $c->addData($d);
         //Define os link baseado nas permissoes de acesso
         if (Config::me('uidNumber') != $value['user']) {
             /*Descomentar ao implementar os métodos
                                 if($acl[$value['user']]['delete']){
                                       $l = new Link();
                                       $l->setHref('');
                                       $l->setRel('delete');
                                       $l->setAlt('Remover');
                                       $l->setPrompt('Remover');
                                       $l->setRender('link');
                                       $i->addLink($l);
                                 }
             
                                 if($acl[$value['user']]['update']){
                                       $l = new Link();
                                       $l->setHref('');
                                       $l->setRel('put');
                                       $l->setAlt('Atualizar');
                                       $l->setPrompt('Atualizar');
                                       $l->setRender('link');
                                       $i->addLink($l);
                                 }
             
                                 if($acl[$value['user']]['write']){
                                       $l = new Link();
                                       $l->setHref('');
                                       $l->setRel('post');
             			  $l->setAlt('Criar');
                                       $l->setPrompt('Criar novo');
                                       $l->setRender('link');
                                       $i->addLink($l);
                                 }
             
                                 if($acl[$value['user']]['read']){
                                       $l = new Link();
                                       $l->setHref('');
                                       $l->setRel('get');
                                       $l->setAlt('Buscar');
                                       $l->setPrompt('Buscar');
                                       $l->setRender('link');
                                       $i->addLink($l);
                                 }*/
         } else {
             /*Descomentar ao implementar métodos no recurso
                                 $l = new Link();
                                 $l->setHref('');
                                 $l->setRel('delete');
                                 $l->setAlt('Remover');
                                 $l->setPrompt('Remover');
                                 $l->setRender('link');
                                 $i->addLink($l);
             
                                 $l = new Link();
                                 $l->setHref('');
                                 $l->setRel('put');
                                 $l->setAlt('Atualizar');
                                 $l->setPrompt('Atualizar');
                                 $l->setRender('link');
                                 $i->addLink($l);
             
                                 $l = new Link();
                                 $l->setHref('');
                                 $l->setRel('get');
                                 $l->setAlt('Buscar');
                                 $l->setPrompt('Buscar');
                                 $l->setRender('link');
             
                                 $i->addLink($l);
                                 */
         }
         $h->setCollection($c);
     } catch (Exception $ex) {
         $this->createException($request, $response, Response::INTERNALSERVERERROR, 'Internal Server Error', $ex);
         return $response;
     }
     $response->body = $h->getHypermedia($request->accept[10][0]);
     return $response;
 }
Example #5
0
 /**
  * changeStatus
  * change notification status ( unread , read )
  * 
  * @access public
  * @return boolean
  * 
  */
 public function changeStatus($id = null, $status = 0)
 {
     $this->_model->read(null, $id);
     $this->_model->set('status', $status);
     $this->_model->save();
 }
 function quickSearchMail($params)
 {
     require_once dirname(__FILE__) . '/../../prototype/api/controller.php';
     set_time_limit(270);
     //Aumenta o tempo limit da requisição, em algumas buscas o imap demora para retornar o resultado.
     $return = array();
     $return['folder'] = $params['folder'];
     if (!is_array($params['folder'])) {
         $params['folder'] = array($params['folder']);
     }
     if (!isset($params['sortType'])) {
         $params['sortType'] = 'SORTDATE_REVERSE';
     }
     $params['search'] = mb_convert_encoding($params['search'], 'UTF-8', mb_detect_encoding($params['search'] . 'x', 'UTF-8, ISO-8859-1'));
     $i = 0;
     if (!isset($params['page'])) {
         $params['page'] = 0;
     }
     $end = $this->prefs['max_email_per_page'] * ((int) $params['page'] + 1);
     $ini = $end - $this->prefs['max_email_per_page'];
     $count = 0;
     if (!preg_match('/KEYWORD/i', $params['search'])) {
         $search = $this->parseCriteriaSearchMail($params['search']);
     } else {
         $search = $params['search'];
     }
     foreach ($params['folder'] as $folder) {
         $imap = $this->open_mbox($folder);
         $msgIds = imap_sort($imap, SORTDATE, 1, SE_UID, $search, 'UTF-8');
         $count += count($msgIds);
         foreach ($msgIds as $ii => $v) {
             $msg = imap_headerinfo($imap, imap_msgno($imap, $v));
             $return['msgs'][$i]['from'] = '';
             if (isset($msg->from[0])) {
                 $from = self::formatMailObject($msg->from[0]);
                 $return['msgs'][$i]['from'] = mb_convert_encoding($from['name'] ? $from['name'] : $from['email'], 'UTF-8');
             } else {
                 $return['msgs'][$i]['from'] = '';
             }
             $return['msgs'][$i]['subject'] = ' ';
             $subject = imap_mime_header_decode($msg->subject);
             foreach ($subject as $tmp) {
                 $return['msgs'][$i]['subject'] .= mb_convert_encoding($tmp->text, 'UTF-8', 'UTF-8 , ISO-8859-1');
             }
             if ($_SESSION['phpgw_info']['user']['preferences']['expressoMail']['use_followupflags_and_labels'] == "2") {
                 $filter = array('AND', array('=', 'folderName', $folder), array('=', 'messageNumber', $v));
                 $followupflagged = Controller::find(array('concept' => 'followupflagged', 'folder' => $folder), false, array('filter' => $filter, 'criteria' => array('deepness' => '2')));
                 if (isset($followupflagged[0]['followupflagId'])) {
                     $followupflag = Controller::read(array('concept' => 'followupflag', 'id' => $followupflagged[0]['followupflagId']));
                     $followupflagged[0]['followupflag'] = $followupflag;
                     $return['msgs'][$i]['followupflagged'] = $followupflagged[0];
                 }
                 $labeleds = Controller::find(array('concept' => 'labeled'), false, array('filter' => $filter, 'criteria' => array('deepness' => '2')));
                 if (is_array($labeleds)) {
                     foreach ($labeleds as $e) {
                         $labels = Controller::read(array('concept' => 'label', 'id' => $e['labelId']));
                         $return['msgs'][$i]['labels'][$e['labelId']] = $labels;
                     }
                 }
             }
             // os comandos abaixos foram retirados pois deixam a busca lenta.
             // $mimeBody = imap_body( $this->mbox, $v  , FT_UID|FT_PEEK  );
             // $return['msgs'][$i]['flag'] .= ( preg_match('/((Content-Disposition:(.)*([\r\n\s]*filename))|(Content-Type:(.)*([\r\n\s]*name)))/i', $mimeBody) ) ? 'T': '';         //
             $return['msgs'][$i]['flag'] = ' ';
             $return['msgs'][$i]['flag'] .= $msg->Unseen ? $msg->Unseen : '';
             $return['msgs'][$i]['flag'] .= $msg->Recent ? $msg->Recent : '';
             $return['msgs'][$i]['flag'] .= $msg->Draft ? $msg->Draft : '';
             $return['msgs'][$i]['flag'] .= $msg->Answered ? $msg->Answered : '';
             $return['msgs'][$i]['flag'] .= $msg->Deleted ? $msg->Deleted : '';
             $msgComponents = new message_components($this->mbox);
             $msgComponents->fetch_structure($v);
             $return['msgs'][$i]['flag'] .= count($msgComponents->fname[$v]) > 0 ? 'T' : '';
             $header = imap_fetchheader($imap, $v, FT_UID);
             // Necessario para recuperar se a mensagem é importante ou não.
             $importante = array();
             if ($msg->Flagged != 'F') {
                 $return['msgs'][$i]['flag'] .= preg_match('/importance\\s{0,}:\\s{0,}(high).*/i', $header, $importante) === 0 ? '' : 'F';
             } else {
                 $return['msgs'][$i]['flag'] .= $msg->Flagged ? $msg->Flagged : '';
             }
             $return['msgs'][$i]['udate'] = gmdate("d/m/Y", $msg->udate + $this->functions->CalculateDateOffset());
             $return['msgs'][$i]['udatecomp'] = substr($return['msgs'][$i]['udate'], -4) . "-" . substr($return['msgs'][$i]['udate'], 3, 2) . "-" . substr($return['msgs'][$i]['udate'], 0, 2);
             $return['msgs'][$i]['date'] = $msg->udate;
             $return['msgs'][$i]['size'] = $msg->Size;
             $return['msgs'][$i]['boxname'] = $folder;
             $return['msgs'][$i]['uid'] = $v;
             ++$i;
         }
     }
     $return['num_msgs'] = $count;
     if (!isset($return['msgs'])) {
         $return['msgs'] = array();
     }
     define('SORTBOX', 69);
     define('SORTWHO', 2);
     define('SORTBOX_REVERSE', 69);
     define('SORTWHO_REVERSE', 2);
     define('SORTDATE_REVERSE', 0);
     define('SORTSUBJECT_REVERSE', 3);
     define('SORTSIZE_REVERSE', 6);
     switch (constant($params['sortType'])) {
         case 0:
             $sA = 'date';
             break;
         case 2:
             $sA = 'from';
             break;
         case 69:
             $sA = 'boxname';
             break;
         case 3:
             $sA = 'subject';
             break;
         case 6:
             $sA = 'size';
             break;
     }
     if ($params['sortType'] !== 'SORTDATE_REVERSE') {
         if (strpos($params['sortType'], 'REVERSE') !== false) {
             $return['msgs'] = $this->array_msort($return['msgs'], array($sA => SORT_DESC));
         } else {
             $return['msgs'] = $this->array_msort($return['msgs'], array($sA => SORT_ASC));
         }
     }
     $k = -1;
     $nMsgs = array();
     foreach ($return['msgs'] as $v) {
         ++$k;
         if ($k < $ini || $k >= $end) {
             continue;
         }
         $nMsgs[] = $v;
     }
     $return['msgs'] = $nMsgs;
     $return = json_encode($return);
     $return = base64_encode($return);
     return $return;
 }
Example #7
0
 static function deleteEvent($data, $params = false)
 {
     $event = Controller::read(array('concept' => 'schedulable', 'id' => $data), array('uid'));
     if (!is_array(self::$deleted) || !in_array($event['uid'], self::$deleted)) {
         self::deleteIcal($event['uid'], array('uid' => $event['uid'], 'location' => $params['location']));
     }
 }
Example #8
0
 /**
  * Método que remove do ldap as informações do vacation
  *
  * @license    http://www.gnu.org/copyleft/gpl.html GPL
  * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
  * @sponsor     Caixa Econômica Federal
  * @author     Cristiano Corrêa Schmidt
  * @param      <$uri>
  * @param      <$result>
  * @param      <$criteria>
  * @param      <$original>
  * @return     <void>
  * @access     public
  */
 public function deleteVacationRule(&$uri, &$params, &$criteria, $original)
 {
     if ($original['URI']['id'] === 'vacation') {
         $user = Controller::read(array('concept' => 'user', 'id' => config::me('uidNumber'), 'service' => 'OpenLDAP'));
         $ldapConf = Config::service('OpenLDAP', 'config');
         $con = ldap_connect($ldapConf['host']);
         ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
         ldap_bind($con, $ldapConf['user'], $ldapConf['password']);
         $info = array();
         $info['vacationActive'] = 'FALSE';
         $info['vacationInfo'] = "";
         ldap_modify($con, $user['dn'], $info);
         ldap_close($con);
     }
 }
 public function create($URI, &$data)
 {
     switch ($URI['concept']) {
         case 'labeled':
             if (isset($data['folderName']) && isset($data['messageNumber']) && isset($data['labelId'])) {
                 $this->mbox = $this->open_mbox($data['folderName']);
                 imap_setflag_full($this->mbox, $data['messageNumber'], '$Label' . $data['labelId'], ST_UID);
                 return array('id' => $data['folderName'] . '/' . $data['messageNumber'] . '#' . $data['labelId']);
             }
             return array();
         case 'followupflagged':
             //deve ser gravado primeiro no imap, obtido o message-id e, depois gravado no banco
             if (isset($data['folderName']) && isset($data['messageNumber'])) {
                 $this->mbox = $this->open_mbox($data['folderName']);
                 $s = imap_setflag_full($this->mbox, $data['messageNumber'], '$Followupflagged', ST_UID);
                 $headers = imap_fetch_overview($this->mbox, $data['messageNumber'], FT_UID);
                 $data['messageId'] = $headers[0]->message_id;
                 /*
                  * TODO
                  * Verificar erro ao tentar setar uma flag com o limite de flags atingido
                  * onde o status retornado pelo imap_setflag_full é true mesmo não sendo possível
                  * a inserção da flag.
                  */
                 return $s && imap_last_error() != 'Too many user flags in mailbox' ? $data : array();
             } else {
                 if (isset($data['messageId'])) {
                     /**
                      * Busca pela mensagem com o messageId dado. Se uma pasta foi passada, busca nela,
                      * senão busca em todas.
                      */
                     $folders = array();
                     if (isset($data['folderName'])) {
                         $folders = array($data['folderName']);
                     } else {
                         $folder_list = $this->get_folders_list();
                         foreach ($folder_list as $folder) {
                             if (isset($folder['folder_id'])) {
                                 $folders[] = $folder['folder_id'];
                             }
                         }
                     }
                     foreach ($folders as $folder) {
                         $this->mbox = $this->open_mbox($folder);
                         if ($messages = imap_search($this->mbox, 'ALL TEXT "Message-Id: ' . $data['messageId'] . '"', SE_UID)) {
                             $s = imap_setflag_full($this->mbox, $messages[0], '$Followupflagged', ST_UID);
                             /**
                              * Stop searching in all folders
                              */
                             return $data;
                         }
                     }
                 }
             }
             return array();
         case 'message':
             require_once ROOTPATH . '/library/uuid/class.uuid.php';
             $GLOBALS['phpgw_info']['flags'] = array('noheader' => true, 'nonavbar' => true, 'currentapp' => 'expressoMail', 'enable_nextmatchs_class' => True);
             $return = array();
             require_once dirname(__FILE__) . '/../../services/class.servicelocator.php';
             $mailService = ServiceLocator::getService('mail');
             $msg_uid = $data['msg_id'];
             $body = $data['body'];
             $body = str_replace("&lt;", "&yzwkx;", $body);
             //Alterar as Entities padrão das tags < > para compatibilizar com o Expresso
             $body = str_replace("&gt;", "&xzwky;", $body);
             $body = str_replace("%nbsp;", "&nbsp;", $body);
             $body = html_entity_decode($body, ENT_QUOTES, 'ISO-8859-1');
             $body = str_replace("&yzwkx;", "&lt;", $body);
             $body = str_replace("&xzwky;", "&gt;", $body);
             $folder = mb_convert_encoding($data['folder'], "UTF7-IMAP", "ISO-8859-1, UTF-8");
             $folder = @preg_replace('/INBOX[\\/.]/i', "INBOX" . $this->imap_delimiter, $folder);
             /**
              * Gera e preenche o field Message-Id do header
              */
             $mailService->addHeaderField('Message-Id', UUID::generate(UUID::UUID_RANDOM, UUID::FMT_STRING) . '@Draft');
             $mailService->addHeaderField('Reply-To', mb_convert_encoding($data['input_reply_to'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
             $mailService->addHeaderField('Date', date("d-M-Y H:i:s"));
             $mailService->addTo(mb_convert_encoding($data['input_to'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
             $mailService->addCc(mb_convert_encoding($data['input_cc'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
             $mailService->addBcc(mb_convert_encoding($data['input_cco'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
             $mailService->setSubject(mb_convert_encoding($data['input_subject'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
             if (isset($data['input_important_message'])) {
                 $mailService->addHeaderField('Importance', 'High');
             }
             if (isset($data['input_return_receipt'])) {
                 $mailService->addHeaderField('Disposition-Notification-To', Config::me('mail'));
             }
             $this->rfc2397ToEmbeddedAttachment($mailService, $body);
             $isHTML = isset($data['type']) && $data['type'] == 'html' ? true : false;
             if (!$body) {
                 $body = ' ';
             }
             $mbox_stream = $this->open_mbox($folder);
             $attachment = json_decode($data['attachments'], TRUE);
             if (!empty($attachment)) {
                 foreach ($attachment as &$value) {
                     if ((int) $value > 0) {
                         $att = Controller::read(array('id' => $value, 'concept' => 'mailAttachment'));
                         if ($att['disposition'] == 'embedded' && $isHTML) {
                             $body = str_replace('"../prototype/getArchive.php?mailAttachment=' . $att['id'] . '"', '"' . mb_convert_encoding($att['name'], 'ISO-8859-1', 'UTF-8,ISO-8859-1') . '"', $body);
                             $mailService->addStringImage(base64_decode($att['source']), $att['type'], mb_convert_encoding($att['name'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
                         } else {
                             $mailService->addStringAttachment(base64_decode($att['source']), mb_convert_encoding($att['name'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'), $att['type'], 'base64', isset($att['disposition']) ? $att['disposition'] : 'attachment');
                         }
                         unset($att);
                     } else {
                         $value = json_decode($value, true);
                         switch ($value['type']) {
                             case 'imapPart':
                                 $att = $this->getForwardingAttachment($value['folder'], $value['uid'], $value['part']);
                                 if (strstr($body, 'src="./inc/get_archive.php?msgFolder=' . $value['folder'] . '&msgNumber=' . $value['uid'] . '&indexPart=' . $value['part'] . '"') !== false) {
                                     $body = str_ireplace('src="./inc/get_archive.php?msgFolder=' . $value['folder'] . '&msgNumber=' . $value['uid'] . '&indexPart=' . $value['part'] . '"', 'src="' . $att['name'] . '"', $body);
                                     $mailService->addStringImage($att['source'], $att['type'], mb_convert_encoding($att['name'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
                                 } else {
                                     $mailService->addStringAttachment($att['source'], mb_convert_encoding($att['name'], 'ISO-8859-1', 'UTF-8,ISO-8859-1'), $att['type'], 'base64', isset($att['disposition']) ? $att['disposition'] : 'attachment');
                                 }
                                 unset($att);
                                 break;
                             case 'imapMSG':
                                 $mbox_stream = $this->open_mbox($value['folder']);
                                 $rawmsg = $this->getRawHeader($value['uid']) . "\r\n\r\n" . $this->getRawBody($value['uid']);
                                 $mailService->addStringAttachment($rawmsg, mb_convert_encoding(base64_decode($value['name']), 'ISO-8859-1', 'UTF-8,ISO-8859-1'), 'message/rfc822', '7bit', 'attachment');
                                 unset($rawmsg);
                                 break;
                             default:
                                 break;
                         }
                     }
                 }
             }
             if ($isHTML) {
                 $mailService->setBodyHtml($body);
             } else {
                 $mailService->setBodyText(mb_convert_encoding($body, 'ISO-8859-1', 'UTF-8,ISO-8859-1'));
             }
             if (imap_append($mbox_stream, "{" . $this->imap_server . ":" . $this->imap_port . "}" . $folder, $mailService->getMessage(), "\\Seen \\Draft")) {
                 $status = imap_status($mbox_stream, "{" . $this->imap_server . ":" . $this->imap_port . "}" . $folder, SA_UIDNEXT);
                 $return['id'] = $status->uidnext - 1;
                 if ($data['uidsSave']) {
                     $this->delete_msgs(array('folder' => $folder, 'msgs_number' => $data['uidsSave']));
                 }
                 Logger::info('expressomail', 'SAVEMSG', 'ID: ' . $return['id'] . ' # ' . 'Subject:' . $data['input_subject']);
             }
             return $return;
     }
 }
Example #10
0
 public function validateNumberSlots(&$uri, &$params, &$criteria, $original)
 {
     $used = Controller::read(array('concept' => 'label', 'id' => '1'), array('id'), array('uid' => Config::me('uidNumber')));
     if (!isset($used['id'])) {
         $params['id'] = '1';
         return;
     }
     $max = Controller::service('PostgreSQL')->execSql("SELECT config_value as value FROM phpgw_config where config_app = 'expressoMail' and config_name = 'expressoMail_limit_labels' LIMIT 1");
     $total = Controller::service('PostgreSQL')->execSql("SELECT count(id) as value FROM expressomail_label WHERE user_id = " . Config::me('uidNumber'));
     if ($total >= $max) {
         throw new Exception('#LabelSlotError');
     }
     $slot = Controller::service('PostgreSQL')->execSql('SELECT label.slot + 1 as id FROM expressomail_label as label, phpgw_config as config WHERE label.user_id = ' . Config::me('uidNumber') . ' AND config.config_name = \'expressoMail_limit_labels\' AND label.slot <= config.config_value::integer AND ( SELECT count(slot) FROM expressomail_label WHERE slot = label.slot + 1 AND user_id = ' . Config::me('uidNumber') . ' ) = 0 limit 1', true);
     if (empty($slot)) {
         throw new Exception('#LabelSlotError');
     }
     $params['id'] = $slot['id'];
 }
Example #11
0
<?php

require_once dirname(__FILE__) . '/api/controller.php';
use prototype\api\Config;
$uidNumber = Config::me('uidNumber') ? Config::me('uidNumber') : $_SESSION['phpgw_info']['expressomail']['user']['account_id'];
$me = Controller::read(array('concept' => 'user', 'service' => 'OpenLDAP', 'id' => $uidNumber));
$sql = "SELECT * FROM phpgw_preferences where preference_app = 'common' AND preference_owner IN ( '-2' , '-1' , {$me['id']} ) ORDER BY preference_owner DESC";
$preferences = Controller::service('PostgreSQL')->execResultSql($sql);
foreach ($preferences as $preference) {
    $values = unserialize($preference['preference_value']);
    if (isset($values['lang'])) {
        $me['lang'] = $values['lang'];
    }
}
echo json_encode($me);
Example #12
0
 /**
  * Faz um diff do update se ouve realmente uma alteração envia um email a todos os participants
  *
  * @license    http://www.gnu.org/copyleft/gpl.html GPL
  * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
  * @sponsor    Caixa Econômica Federal
  * @author     Cristiano Corrêa Schmidt
  * @return     void
  * @access     public
  */
 public function updateEvent(&$uri, $params, &$criteria, $original)
 {
     $schedulableOld = Controller::read(array('concept' => 'schedulable', 'id' => $uri['id']), null, array('deepness' => '2'));
     $schedulable = $schedulableOld;
     $alt = false;
     foreach ($params as $i => $v) {
         //Verifica se ouve alteração no evento
         if (isset($schedulableOld[$i]) && $schedulableOld[$i] != $v && $i != 'participants') {
             $schedulable[$i] = $v;
             $alt = true;
         }
     }
     if ($alt === true && Config::regGet('noAlarm') === false && self::futureEvent($schedulable['startTime'], $schedulable['rangeEnd'], $schedulable['id'])) {
         $method = 'REQUEST';
         $notificationType = 'Modificação de Calendario';
         $part = 'othersAttendees';
         self::mountStruture($uri['id'], $schedulable, false, $data, $subject, $ical, $part, $method, $notificationType);
         $from = self::_getAttendeeOrganizer($schedulable);
         if (isset($part) && $part && count($part) > 0) {
             self::sendMail($data, $ical, implode(',', $part), $subject, $schedulableOld['type'] == '1' ? 'notify_modify_body' : 'notify_modify_body_task', $from);
         }
     }
 }
Example #13
0
 public function davcalUpdateCollection(&$uri, &$params, &$criteria, $original)
 {
     if (Config::module('useCaldav', 'expressoCalendar')) {
         require_once ROOTPATH . '/modules/calendar/interceptors/DAViCalAdapter.php';
         if (isset($params['location'])) {
             $calendar = Controller::read($uri);
             if ($calendar['location'] !== $params['location']) {
                 DAViCalAdapter::mvcalendar($calendar['location'], $params['location']);
             }
         }
     }
 }
Example #14
0
 function normalizeEvents($result, $timezones)
 {
     $mySig = Controller::find(array('concept' => 'calendarSignature'), array('calendar'), array('filter' => array('AND', array('=', 'type', '0'), array('=', 'user', Config::me('uidNumber')), array('=', 'isOwner', '0'))));
     $signedCalendars = array();
     if (is_array($mySig)) {
         foreach ($mySig as $v) {
             $tmp = Controller::find(array('concept' => 'calendarToPermission'), array('acl', 'owner'), array('filter' => array('AND', array('=', 'calendar', $v['calendar']), array('=', 'user', Config::me('uidNumber')))));
             $signedCalendars[$v['calendar']] = $tmp[0];
         }
     }
     $date = new DateTime('now', new DateTimeZone('UTC'));
     $DayLigth = array();
     foreach ($result as $i => $v) {
         $currentTimezone = isset($v['calendar']) && isset($timezones[$v['calendar']]) ? $timezones[$v['calendar']] : $v['timezone'];
         $date->setTimestamp((int) ($v['startTime'] / 1000));
         $date->setTimezone(new DateTimeZone($v['timezone']));
         $DayLigth['event']['startTime'] = $date->getTimestamp() + $date->getOffset() . '000';
         $date->setTimezone(new DateTimeZone($currentTimezone));
         $DayLigth['calendar']['startTime'] = $date->getTimestamp() + $date->getOffset() . '000';
         $date->setTimestamp((int) ($v['endTime'] / 1000));
         $date->setTimezone(new DateTimeZone($currentTimezone));
         $DayLigth['event']['endTime'] = $date->getTimestamp() + $date->getOffset() . '000';
         if (isset($v['due']) && $v['due'] != '0') {
             $date->setTimestamp((int) ($v['due'] / 1000));
             $DayLigth['event']['due'] = $date->getTimestamp() + $date->getOffset() . '000';
         } else {
             $DayLigth['event']['due'] = $v['due'];
         }
         $date->setTimezone(new DateTimeZone($currentTimezone));
         $DayLigth['calendar']['endTime'] = $date->getTimestamp() + $date->getOffset() . '000';
         $result[$i]['DayLigth'] = $DayLigth;
         if (isset($v['occurrences']) && count($v['occurrences']) > 0) {
             $date->setTimestamp((int) ($v['startTime'] / 1000));
             $date->setTimezone(new DateTimeZone($currentTimezone));
             foreach ($result[$i]['occurrences'] as &$o) {
                 $o = (int) ($o / 1000) + $date->getOffset() . '000';
             }
         }
         $attend = isset($signedCalendars[$result[$i]['calendar']]) ? Controller::read(array('concept' => 'participant'), null, array('filter' => array('AND', array('=', 'schedulable', $v['id']), array('=', 'user', $signedCalendars[$result[$i]['calendar']]['owner'])))) : Controller::read(array('concept' => 'participant'), null, array('filter' => array('AND', array('=', 'schedulable', $v['id']), array('=', 'user', Config::me('uidNumber')))));
         $result[$i]['unanswered'] = 0;
         if (count($attend) > 0 && !empty($attend)) {
             if (array_key_exists(0, $attend)) {
                 $attend = $attend[0];
             }
             if (isset($signedCalendars[$result[$i]['calendar']])) {
                 //Caso agenda compartilhada verificar tmb se tem compartilhamento de escrita
                 $result[$i]['editable'] = strpos($signedCalendars[$result[$i]['calendar']]['acl'], "w") >= 0 && (strstr($attend['acl'], "w") || strstr($attend['acl'], "o") || $attend['isOrganizer'] == '1') ? 1 : 0;
             } else {
                 $result[$i]['editable'] = strstr($attend['acl'], "w") || strstr($attend['acl'], "o") || $attend['isOrganizer'] == '1' ? 1 : 0;
             }
             if ($attend['status'] == STATUS_UNANSWERED && !isset($signedCalendars[$result[$i]['calendar']])) {
                 $result[$i]['unanswered'] = 1;
             }
         } else {
             $result[$i]['editable'] = $v['type'] == '2' ? 0 : 2;
         }
         if ($v['type'] == 2 && $v['tasks'] > 0) {
             $result[$i]['type'] = 3;
         }
     }
     return $this->toUtf8($result);
 }