* @copyright Catalyst .Net Ltd, Morphoss Ltd * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 */ dbg_error_log("REPORT", "method handler"); require_once("XMLDocument.php"); require_once('DAVResource.php'); include_once("drivers_ldap.php"); require_once('RRule-v2.php'); if ( ! ini_get('open_basedir') && (isset($c->dbg['ALL']) || (isset($c->dbg['report']) && $c->dbg['report'])) ) { $fh = fopen('/tmp/REPORT.txt','w'); if ( $fh ) { fwrite($fh,$request->raw_post); fclose($fh); } } if ( !isset($request->xml_tags) ) { $request->DoResponse( 406, translate("REPORT body contains no XML data!") ); } $position = 0; $xmltree = BuildXMLTree( $request->xml_tags, $position); if ( !is_object($xmltree) ) { $request->DoResponse( 406, translate("REPORT body is not valid XML data!") ); } $target = new DAVResource($request->path); $target->NeedPrivilege( array('DAV::read', 'urn:ietf:params:xml:ns:caldav:read-free-busy'), true ); // They may have either if ( $xmltree->GetTag() != 'DAV::principal-property-search' && $xmltree->GetTag() != 'DAV::principal-property-search-set' ) { $target->NeedPrivilege( array('DAV::read', 'urn:ietf:params:xml:ns:caldav:read-free-busy'), true ); // They may have either } require_once("iCalendar.php"); $reportnum = -1; $report = array(); $denied = array(); $unsupported = array(); if ( isset($prop_filter) ) unset($prop_filter); if ( $xmltree->GetTag() == 'urn:ietf:params:xml:ns:caldav:free-busy-query' ) { include("caldav-REPORT-freebusy.php"); exit; // Not that the above include should return anyway } $reply = new XMLDocument( array( "DAV:" => "" ) ); switch( $xmltree->GetTag() ) { case 'DAV::principal-property-search': include("caldav-REPORT-principal.php"); exit; // Not that it should return anyway. case 'DAV::principal-search-property-set': include("caldav-REPORT-pps-set.php"); exit; // Not that it should return anyway. case 'DAV::sync-collection': include("caldav-REPORT-sync-collection.php"); exit; // Not that it should return anyway. case 'DAV::expand-property': include("caldav-REPORT-expand-property.php"); exit; // Not that it should return anyway. } /** * Return XML for a single calendar (or todo) entry from the DB * * @param array $properties The properties for this calendar * @param string $item The calendar data for this calendar * * @return string An XML document which is the response for the calendar ******************************** Função Customizada para o Expresso ******************** // //function calendar_to_xml( $properties, $item ) { // global $session, $c, $request, $reply; // // dbg_error_log("REPORT","Building XML Response for item '%s'", $item->dav_name ); // // $denied = array(); // $caldav_data = $item->caldav_data; // $displayname = $item->summary; // if ( isset($properties['calendar-data']) || isset($properties['displayname']) ) { // if ( !$request->AllowedTo('all') && $session->user_no != $item->user_no ){ // // the user is not admin / owner of this calendarlooking at his calendar and can not admin the other cal // /** @todo We should examine the ORGANIZER and ATTENDEE fields in the event. If this person is there then they should see this */ // if ( $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read') ) { // $ical = new iCalComponent( $caldav_data ); // $resources = $ical->GetComponents('VTIMEZONE',false); // $first = $resources[0]; // // // if the event is confidential we fake one that just says "Busy" // $confidential = new iCalComponent(); // $confidential->SetType($first->GetType()); // $confidential->AddProperty( 'SUMMARY', translate('Busy') ); // $confidential->AddProperty( 'CLASS', 'CONFIDENTIAL' ); // $confidential->SetProperties( $first->GetProperties('DTSTART'), 'DTSTART' ); // $confidential->SetProperties( $first->GetProperties('RRULE'), 'RRULE' ); // $confidential->SetProperties( $first->GetProperties('DURATION'), 'DURATION' ); // $confidential->SetProperties( $first->GetProperties('DTEND'), 'DTEND' ); // $confidential->SetProperties( $first->GetProperties('UID'), 'UID' ); // $ical->SetComponents(array($confidential),$confidential->GetType()); // // $caldav_data = $ical->Render(); // $displayname = translate('Busy'); // } // } // } // // $url = ConstructURL($item->dav_name); // // $prop = new XMLElement("prop"); // foreach( $properties AS $k => $v ) { // switch( $k ) { // case 'getcontentlength': // $contentlength = strlen($caldav_data); // $prop->NewElement($k, $contentlength ); // break; // case 'calendar-data': // $reply->CalDAVElement($prop, $k, $caldav_data ); // break; // case 'getcontenttype': // $prop->NewElement($k, "text/calendar" ); // break; // case 'current-user-principal': // $prop->NewElement("current-user-principal", $request->current_user_principal_xml); // break; // case 'displayname': // $prop->NewElement($k, $displayname ); // break; // case 'resourcetype': // $prop->NewElement($k); // Just an empty resourcetype for a non-collection. // break; // case 'getetag': // $prop->NewElement($k, '"'.$item->dav_etag.'"' ); // break; // case '"current-user-privilege-set"': // $prop->NewElement($k, privileges($request->permissions) ); // break; // case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */ // $denied[] = $v; // break; // default: // dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $v ); // $unsupported[] = $v; // } // } // $status = new XMLElement("status", "HTTP/1.1 200 OK" ); // // $propstat = new XMLElement( "propstat", array( $prop, $status) ); // $href = new XMLElement("href", $url ); // $elements = array($href,$propstat); // // if ( count($denied) > 0 ) { // $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" ); // $noprop = new XMLElement("prop"); // foreach( $denied AS $k => $v ) { // $noprop->NewElement( strtolower($v) ); // } // $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); // } // // $response = new XMLElement( "response", $elements ); // // return $response; //} // //*/ /************* Função nova Customizada ************* */ function contacts_to_xml( $properties, $item) { global $session, $c, $request, $reply; $path = preg_replace("/^\//","",$request->path); //$filtro = "uid=".$path; //$atributos = array("uidNumber"); //$uidnumber = ldapDrivers::requestAtributo($filtro, $atributos); //if ($uidnumber == false) { // dbg_error_log( "REPORT", "Responding with report error: usuario não encontrado no diretorio"); // $request->DoResponse( 501, 'Database error'); //} // $nome = $uidnumber['uidNumber']; // $nome = $target->GetProperty('user_no'); $nome = $item->id_owner; $mails = array(); $phones = array(); unset($VCARD); $VCARD = "UID:$item->id_contact@$nome\n\n"; /*************************** ********* DADOS DEFAULT **** ****************************/ $VCARD .= "N:$item->family_names;$item->given_names\n\n"; $VCARD .= "FN:$item->names_ordered\n\n"; if ( isset($item->alias)) $VCARD .= "NICKNAME:$item->alias\n\n"; if ( isset($item->photo)) $VCARD .= "PHOTO:ENCODING=b;TYPE=JPEG:$item->photo\n\n"; if ( isset($item->birthdate)) $VCARD .= "BDAY:$item->birthdate\n\n"; if ( isset($item->notes)) $VCARD .= "NOTE:$item->notes\n\n"; /************************** ********** EMAIL & TEL **** ***************************/ $qry = new AwlQuery("SELECT * FROM phpgw_cc_contact_conns inner join phpgw_cc_connections using(id_connection) WHERE phpgw_cc_contact_conns.id_contact= :id", array(':id' => $item->id_contact)); if ( $qry->Exec("REPORT",__LINE__,__FILE__) && $qry->rows() > 0 ){ while( $email_tel = $qry->Fetch() ) { if ( $email_tel->id_typeof_contact_connection == 1) { if ( $email_tel->connection_name == 'Principal' ) $type=WORK; else $type=HOME; $VCARD .= "EMAIL;TYPE=$type:$email_tel->connection_value\n\n"; } else if ( $email_tel->id_typeof_contact_connection == 2) { if ( $email_tel->connection_name == 'Trabalho' ) $type=WORK; else if ( $email_tel->connection_name == 'Casa' ) $type=HOME; else if ( $email_tel->connection_name == 'Celular' ) $type=CELL; else if ( $email_tel->connection_name == 'Fax' ) $type=FAX; $VCARD .= "TEL;TYPE=$type:$email_tel->connection_value\n\n"; } } } /************************** ************ ADDR ******** **************************/ $qry = new AwlQuery("SELECT * FROM phpgw_cc_contact_addrs inner join phpgw_cc_addresses using(id_address) WHERE phpgw_cc_contact_addrs.id_contact= :id", array(':id' => $item->id_contact)); if ( $qry->Exec("REPORT",__LINE__,__FILE__) && $qry->rows() > 0 ){ while( $addr = $qry->Fetch() ) { if ( $addr->id_typeof_contact_address == 1) { $type=HOME; $VCARD .= "ADR;TYPE=$type:;;$addr->address1;$addr->city;$addr->state;$addr->postal_code;$addr->id_contry\n\n"; } else if ( $addr->id_typeof_contact_address == 2) { $type=WORK; $VCARD .= "ADR;TYPE=$type:;;$addr->address1;$addr->city;$addr->state;$addr->postal_code;$addr->id_contry\n\n"; } } } /********** PUBLIC KEY ******** *****************************/ dbg_error_log("REPORT","Building XML Response for item '%s' usuario '%s'", $item->id_contact,$nome ); $response = "BEGIN:VCARD\n\nVERSION:3.0\n\nPRODID:-//Inverse inc.//SOGo Connector 1.0//EN\n\n"; $response .= "$VCARD"; $response .= "END:VCARD\n\n"; $caldav_data = $response; $dav_nam = "{$item->id_contact}@{$item->id_owner}"; $dav_etag_nam = md5($item->id_contact.$item->id_owner.$item->last_update); //$dav_name = "{$item->id_contact}@{$item->id_owner}"; $dav_name = sprintf('/%s/%s@%s.vcf',$path,$item->id_contact,$item->id_owner); $url = ConstructURL($dav_name); $prop = new XMLElement("prop"); foreach( $properties AS $k => $v ) { switch( $k ) { case 'getcontentlength': $contentlength = strlen($caldav_data); $prop->NewElement($k, $contentlength ); break; case 'address-data': $reply->CardDAVElement($prop, $k, $caldav_data ); break; case 'getcontenttype': $prop->NewElement($k, "text/x-vcard" ); break; case 'current-user-principal': $prop->NewElement("current-user-principal", $request->current_user_principal_xml); break; case 'displayname': $prop->NewElement($k, $displayname ); break; case 'resourcetype': $prop->NewElement($k); // Just an empty resourcetype for a non-collection. break; case 'getetag': $prop->NewElement($k, '"'.$dav_etag_nam.'"' ); break; case '"current-user-privilege-set"': $prop->NewElement($k, privileges($request->permissions) ); break; case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */ $denied[] = $v; break; default: dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $v ); $unsupported[] = $v; } } $status = new XMLElement("status", "HTTP/1.1 200 OK" ); $propstat = new XMLElement( "propstat", array( $prop, $status) ); $href = new XMLElement("href", $url ); $elements = array($href,$propstat); if ( count($denied) > 0 ) { $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" ); $noprop = new XMLElement("prop"); foreach( $denied AS $k => $v ) { $noprop->NewElement( strtolower($v) ); } $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); } $response = new XMLElement( "response", $elements ); return $response; } function calendar_to_xml( $properties, $item ) { global $c, $request, $reply; $path = preg_replace("/^\//","",$request->path); //$filtro = "uid=".$path; //$atributos = array("uidNumber"); //$uidnumber = ldapDrivers::requestAtributo($filtro, $atributos); //if ($uidnumber == false) { // dbg_error_log( "REPORT", "Responding with report error: usuario não encontrado no diretorio"); // $request->DoResponse( 501, 'Database error'); //} //$nome = $uidnumber['uidNumber']; $nome = $item->owner; dbg_error_log("REPORT","Building XML Response for item '%s' usuario '%s'", $item->cal_id,$nome ); $mdate = $item->mdatetime; $calid = $item->cal_id; $modify_data = dataSegundosParaT($mdate,1); $date = $item->datetime; $create_data = dataSegundosParaT($date,1); $start_data = dataSegundosParaT($date); $edate = $item->edatetime; $end_data = dataSegundosParaT($edate); $titulo = utf8_encode($item->title); $local = utf8_encode($item->location); if($local != "" ) $local = "\n\nLOCATION:$local"; else $local = ""; $descricao = utf8_encode($item->description); if($descricao != "") $descricao = "\n\nDESCRIPTION:".preg_replace('/\r\n/', '\\n', $descricao); else $descricao = ""; $moz=""; /******************* **** Sequencia **** ******************/ $sequec = "\n\nSEQUENCE:0"; /********* *ALARMES* *********/ $alarme_id = $item->cal_id; $alarme = new AwlQuery( "SELECT * FROM phpgw_async WHERE id = :alarme_id", array(':alarme_id' => 'cal:'.$alarme_id.':0')); if ( $alarme->Exec("REPORT",__LINE__,__FILE__) && $alarme->rows() > 0 ){ $nao_alarme = new AwlQuery( "SELECT * FROM phpgw_cal_extra WHERE cal_id = :alarme_id AND (cal_extra_name = 'X-MOZ-LASTACK' OR cal_extra_name = :X-MOZ-LASTACK-PART)",array( ':alarme_id' => $alarme_id, ':X-MOZ-LASTACK-PART' => 'X-MOZ-LASTACK-PART-'.$nome)); if ( $nao_alarme->Exec("REPORT",__LINE__,__FILE__) && $nao_alarme->rows() == 1 ){ $alarmeqryno = $nao_alarme->Fetch(); $moz = "\n\nX-MOZ-LASTACK:$alarmeqryno->cal_extra_value"; $moz .= "\n\nX-MOZ-GENERATION:1"; $modify_data = "$alarmeqryno->cal_extra_value"; $adiamento = new AwlQuery( "SELECT * FROM phpgw_cal_extra WHERE cal_id = :alarme_id AND cal_extra_name LIKE 'X-MOZ-SNOOZE%'", array( ':alarme_id' => $alarme_id)); if ( $adiamento->Exec("REPORT",__LINE__,__FILE__) && $adiamento->rows() > 0 ){ $admno = $adiamento->Fetch(); $moz .= "\n\n$admno->cal_extra_name:$admno->cal_extra_value"; } dbg_error_log("REPORT","CANCELAR ALARME '%s' ", $moz); //$deleta = new AwlQuery( "DELETE FROM phpgw_cal_extra WHERE cal_id = '$alarme_id'"); //$deleta->Exec("calquery",__LINE__,__FILE__); } else{ $moz=""; } $alarmeqry = $alarme->Fetch(); $tempo = split(";", $alarmeqry->data, 4); $tempoalarme = $alarmeqry->next;// + $mais; $agoranow = date_create(); $agora = $agoranow->format("U"); $segundos = split(":", $tempo[3], 2); if ( $tempoalarme >= $agora | $item->cal_type == 'M'){ if ( $segundos[1] <= 3600 ){ $minutos = $segundos[1]/60; $VALARME = "\n\nBEGIN:VALARM\n\nTRIGGER;VALUE=DURATION:-PT${minutos}M\n\nDESCRIPTION:Descrição padrão Mozilla\n\nACTION:DISPLAY\n\nEND:VALARM"; } else if ( $segundos[1] < 86400 ){ $hora = $segundos[1]/60/60; $VALARME = "\n\nBEGIN:VALARM\n\nTRIGGER;VALUE=DURATION:-PT${hora}H\n\nDESCRIPTION:Descrição padrão Mozilla\n\nACTION:DISPLAY\n\nEND:VALARM"; } else if ( $segundos[1] == 604800 ){ $VALARME = "\n\nBEGIN:VALARM\n\nTRIGGER;VALUE=DURATION:-P1W\n\nDESCRIPTION:Descrição padrão Mozilla\n\nACTION:DISPLAY\n\nEND:VALARM"; } else{ $dia = $segundos[1]/60/60/24; $VALARME = "\n\nBEGIN:VALARM\n\nTRIGGER;VALUE=DURATION:-P${dia}D\n\nDESCRIPTION:Descrição padrão Mozilla\n\nACTION:DISPLAY\n\nEND:VALARM"; } } else{ $VALARME =""; } } else{ $VALARME =""; } //dbg_error_log("GET", "HORA LOCAL = '%s'",$VALARME); /***************************************** **** Ajuste para TZ funcionar ************ *****************************************/ //$HorarioTimeZone = new DateTimeZone(date_default_timezone_get()); ///$create_data = dataSegundosParaT($item->datetime); //$retorna = date("Ymd\THis",$create_data); /******************* *NOME DA CATEGORIA* *******************/ $categories=""; //if (strlen($item->category)>2){ if ($item->category != "" ){ $x= "select cat_name from phpgw_categories WHERE cat_id = :category"; $phpgw_query = new AwlQuery ($x, array(':category' => $item->category)); if ( $phpgw_query->Exec() && $phpgw_query->rows() > 0 ) { while( $id_cale = $phpgw_query->Fetch() ) { $categories = "\n\nCATEGORIES:".utf8_encode($id_cale->cat_name); //$categories = $id_cale->cat_name; } } } $displayname = $item->title; /********** *CONVITES* **********/ $cn = array(); $mail = array(); $estado = array(); $members = ""; unset($cn); unset($mail); unset($estado); unset($envia_convite); unset($mails); $part2= "SELECT cal_login,cal_status FROM phpgw_cal_user WHERE cal_id = :cal_id AND cal_type = 'u'"; $querypart = new AwlQuery( $part2 , array(':cal_id' => $item->cal_id)); $i=0; if ( $querypart->Exec("REPORT",__LINE__,__FILE__) && $querypart->rows() > 0 ) { while( $id_cale = $querypart->Fetch() ) { if ($item->owner != $id_cale->cal_login){ $filtro = "uidNumber=$id_cale->cal_login" ; if (strlen($filtro) > 12){ $atributos=array("cn","mail"); $usuario= ldapDrivers::requestAtributo($filtro,$atributos); if (isset($usuario)) { $cn[$i] = $usuario['cn']; $mail[$i] = $usuario['mail']; switch ($id_cale->cal_status){ case 'A': $estado[$i] = "ACCEPTED"; break; case 'T': $estado[$i] = "TENTATIVE"; break; case 'U': $estado[$i] = "NEEDS-ACTION"; break; case 'R': $estado[$i] = "DECLINED"; break; } } } } $i++; } } if ( isset($item->ex_participants)) { $mails = split("[?,]",$item->ex_participants); } for ($i = 0; $i <= count($cn); $i++) { if (strlen($mail[$i])>5){ $members = $members."\nATTENDEE;RSVP=TRUE;CN=$cn[$i];PARTSTAT=$estado[$i];ROLE=REQ-PARTICIPANT:MAILTO:$mail[$i]\r"; } dbg_error_log("REPORT", "participantes interno funcao report $members"); } for ($i = 0 ; $i <= count($mails); $i++) { if ( $mails[$i] != '' ){ dbg_error_log("REPORT", "participante externo = '%s'",$mails[$i]); $members = $members."\nATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:MAILTO:$mails[$i]\r"; } } $HorarioTimeZone = new DateTimeZone(date_default_timezone_get()); $HorarioTime = new DateTime("now", $HorarioTimeZone); $convite = new AwlQuery( "SELECT cal_extra_value FROM phpgw_cal_extra WHERE cal_id = :cal_id", array(':cal_id' => $item->cal_id)); if ( $convite->Exec("REPORT",__LINE__,__FILE__) && $convite->rows() > 0 ) { $xmozconvite = $convite->Fetch(); dbg_error_log("REPORT", "estatus de ivio de convite = '%s'",$xmozconvite->cal_extra_value); if ($xmozconvite->cal_extra_value == "true"){ $envia_convite = "X-MOZ-SEND-INVITATIONS:TRUE"; $convite = new AwlQuery( "DELETE FROM phpgw_cal_extra WHERE cal_id = :cal_id", array(':cal_id' => $item->cal_id)); $convite->Exec("REPORT",__LINE__,__FILE__); }else{ $envia_convite = "X-MOZ-SEND-INVITATIONS:FALSE"; } } /********* *PUBLICO* *********/ if ( $item->is_public == 0 ){ $classe = "PRIVATE"; $transp = "\n\nTRANSP:TRANSPARENT"; } else{ $classe = "PUBLIC"; $transp = "\n\nTRANSP:OPAQUE"; } /******************* *EVENTOS REPETIDOS* *******************/ unset($Rrule); if ( $item->cal_type == 'M' ){ /**Busca exceções de eventos repetidos, quando são criados novos eventos a partir de uma repetição * Para ter funcionamento igual ao expresso, escondo o evento repetido. * Essa função apenas adiciona o horário dessa função ao campo EXDATE. */ if ( $item->recur_exception != ''){ $listadeexcecao = array(); $listadeexcecao = explode("," , $item->recur_exception); foreach ($listadeexcecao AS $dataexcecao){ $execao = dataSegundosParaT($dataexcecao,1); $exe = "$exe,$execao"; } } $exe = trim($exe, " ,"); $x= "select datetime from phpgw_cal where reference = :cal_id"; $phpgw_query = new AwlQuery ($x, array(':cal_id' => $item->cal_id)); if ( $phpgw_query->Exec() && $phpgw_query->rows() > 0 ) { while( $id_cale = $phpgw_query->Fetch() ) { date_default_timezone_set('UTC'); $data_antiga = date("Ymd\THis",$item->datetime); $data_nova = date("Ymd\THis",$id_cale->datetime); date_default_timezone_set('America/Sao_Paulo'); $data_n = new DateTime($data_nova); $data_a = new DateTime($data_antiga); if ( $data_n->getOffset() > $data_a->getOffset() ) { $dias = $data_n->format('z') - $data_a->format('z'); $dias = $item->datetime + ($dias*86400) - 3600; $data2 = dataSegundosParaT($dias,1); $exe = $exe . ",". $data2; } elseif ( $data_n->getOffset() < $data_a->getOffset() ) { $dias = $data_n->format('z') - $data_a->format('z'); $dias = $item->datetime + ($dias*86400) + 3600; $data2 = dataSegundosParaT($dias,1); $exe = $exe . ",". $data2; } else { $propstat = new XMLElement( "propstat", array( $prop, $status) ); $dias = $data_n->format('z') - $data_a->format('z'); $dias = $item->datetime + ($dias*86400); $data2 = dataSegundosParaT($dias,1); $exe = $exe . ",". $data2; } } } $exe = trim($exe, " ,"); $exe = "\n\nEXDATE:$exe"; if ( $item->recur_enddate != 0){ $until = dataSegundosParaT($item->recur_enddate,1); if (substr("$until", 9,2) == "03" ) { $until = dataSegundosParaT($item->recur_enddate + 86400,1); } } $intervalo = $item->recur_interval; switch($item->recur_type){ case 1: $frequencia = "DAILY"; $Rrule = "FREQ=$frequencia"; if ($until != ""){ $Rrule .= ";UNTIL=$until"; } if ($intervalo != ""){ $Rrule .= ";INTERVAL=$intervalo"; } break; case 2: $frequencia = "WEEKLY"; $dia_sem = converte_semana($item->recur_data); $Rrule = "FREQ=$frequencia"; if ($until != ""){ $Rrule .= ";UNTIL=$until"; } if ($intervalo !=""){ $Rrule .= ";INTERVAL=$intervalo"; } if($item->recur_data != ""){ $Rrule .= ";$dia_sem"; } break; case 3: $frequencia = "MONTHLY"; $Rrule = "FREQ=$frequencia"; if ($until != ""){ $Rrule .= ";UNTIL=$until"; } if ($intervalo !=""){ $Rrule .= ";INTERVAL=$intervalo"; } break; case 4: $frequencia = "MONTHLY"; $Rrule = "FREQ=$frequencia"; if ($until != ""){ $Rrule .= ";UNTIL=$until"; } if ($intervalo !=""){ $Rrule .= ";INTERVAL=$intervalo"; } break; case 5: $frequencia = "YEARLY"; $Rrule = "FREQ=$frequencia"; if ($until != ""){ $Rrule .= ";UNTIL=$until"; } if ($intervalo !=""){ $Rrule .= ";INTERVAL=$intervalo"; } break; } } if(isset($Rrule)) $Rrule = "\n\nRRULE:$Rrule"; else $Rrule = ""; $response = "BEGIN:VCALENDAR\n\nPRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN\n\nVERSION:2.0"; $response .= "\n\nBEGIN:VTIMEZONE TZID:America/Sao_Paulo X-LIC-LOCATION:America/Sao_Paulo BEGIN:DAYLIGHT TZOFFSETFROM:-0300 TZOFFSETTO:-0200 TZNAME:BRST DTSTART:19701018T000000 RRULE:FREQ=YEARLY;BYDAY=3SU;BYMONTH=10 END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0300 TZOFFSETTO:-0300 TZNAME:BRT DTSTART:19700215T000000 RRULE:FREQ=YEARLY;BYDAY=3SU;BYMONTH=2 END:STANDARD END:VTIMEZONE"; $response .= "\n\nBEGIN:VEVENT\n\nCREATED:$create_data\n\nLAST-MODIFIED:$modify_data\n\nDTSTAMP:$modify_data\n\nUID:$item->cal_id@$item->owner\n\n${members}\n\nSUMMARY:$titulo\n\n$recurrence_id\n\nDTSTART;TZID=America/Sao_Paulo:$start_data\n\nDTEND;TZID=America/Sao_Paulo:${end_data}${local}${categories}\r\nPRIORITY:$item->priority${descricao}${Rrule}${exe}${moz}$VALARME\n\n$envia_convite\n\nEND:VEVENT\n\n"; $response .= "END:VCALENDAR\n\n\n"; $caldav_data = $response; $dav_nam = "{$item->cal_id}{$item->owner}"; $dav_etag_nam= md5($item->cal_id.$item->owner.$item->last_update); //$dav_name = "{$item->cal_id}@{$item->owner}@{$item->last_update}"; $dav_name = sprintf('/%s/%s@%s.ics',$path,$item->cal_id,$item->owner); $url = ConstructURL($dav_name); $prop = new XMLElement("prop"); foreach( $properties AS $k => $v ) { switch( $k ) { case 'getcontentlength': $contentlength = strlen($caldav_data); $prop->NewElement($k, $contentlength ); break; case 'calendar-data': $reply->CalDAVElement($prop, $k, $caldav_data ); break; case 'getcontenttype': $prop->NewElement($k, "text/calendar" ); break; case 'current-user-principal': $prop->NewElement("current-user-principal", $request->current_user_principal_xml); break; case 'displayname': $prop->NewElement($k, $displayname ); break; case 'resourcetype': $prop->NewElement($k); // Just an empty resourcetype for a non-collection. break; case 'getetag': $prop->NewElement($k, '"'.$dav_etag_nam.'"' ); break; case '"current-user-privilege-set"': $prop->NewElement($k, privileges($request->permissions) ); break; case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */ $denied[] = $v; break; default: dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $v ); $unsupported[] = $v; } } $status = new XMLElement("status", "HTTP/1.1 200 OK" ); $propstat = new XMLElement( "propstat", array( $prop, $status) ); $href = new XMLElement("href", $url ); $elements = array($href,$propstat); if ( count($denied) > 0 ) { $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" ); $noprop = new XMLElement("prop"); foreach( $denied AS $k => $v ) { $noprop->NewElement( strtolower($v) ); } $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); } $response = new XMLElement( "response", $elements ); return $response; } /** * Return XML for a single component from the DB * * @param array $properties The properties for this component * @param string $item The DB row data for this component * * @return string An XML document which is the response for the component */ function component_to_xml( $properties, $item ) { global $session, $c, $request, $reply; dbg_error_log("REPORT","Building XML Response for item '%s'", $item->dav_name ); $denied = array(); $unsupported = array(); $caldav_data = $item->caldav_data; $displayname = preg_replace( '{^.*/}', '', $item->dav_name ); $type = 'unknown'; $contenttype = 'text/plain'; switch( $item->caldav_type ) { case 'VJOURNAL': case 'VEVENT': case 'VTODO': $displayname = $item->summary; $type = 'calendar'; $contenttype = 'text/calendar'; break; case 'VCARD': $displayname = $item->fn; $type = 'vcard'; $contenttype = 'text/x-vcard'; break; } if ( isset($properties['calendar-data']) || isset($properties['displayname']) ) { if ( !$request->AllowedTo('all') && $session->user_no != $item->user_no ){ // the user is not admin / owner of this calendarlooking at his calendar and can not admin the other cal /** @todo We should examine the ORGANIZER and ATTENDEE fields in the event. If this person is there then they should see this */ if ( $type == 'calendar' && $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read') ) { $ical = new iCalComponent( $caldav_data ); $resources = $ical->GetComponents('VTIMEZONE',false); $first = $resources[0]; // if the event is confidential we fake one that just says "Busy" $confidential = new iCalComponent(); $confidential->SetType($first->GetType()); $confidential->AddProperty( 'SUMMARY', translate('Busy') ); $confidential->AddProperty( 'CLASS', 'CONFIDENTIAL' ); $confidential->SetProperties( $first->GetProperties('DTSTART'), 'DTSTART' ); $confidential->SetProperties( $first->GetProperties('RRULE'), 'RRULE' ); $confidential->SetProperties( $first->GetProperties('DURATION'), 'DURATION' ); $confidential->SetProperties( $first->GetProperties('DTEND'), 'DTEND' ); $confidential->SetProperties( $first->GetProperties('UID'), 'UID' ); $ical->SetComponents(array($confidential),$confidential->GetType()); $caldav_data = $ical->Render(); $displayname = translate('Busy'); } } } $url = ConstructURL($item->dav_name); $prop = new XMLElement("prop"); foreach( $properties AS $k => $v ) { switch( $k ) { case 'getcontentlength': $contentlength = strlen($caldav_data); $prop->NewElement($k, $contentlength ); break; case 'calendar-data': if ( $type == 'calendar' ) $reply->CalDAVElement($prop, $k, $caldav_data ); else $unsupported[] = $k; break; case 'address-data': if ( $type == 'vcard' ) $reply->CardDAVElement($prop, $k, $caldav_data ); else $unsupported[] = $k; break; case 'getcontenttype': $prop->NewElement($k, $contenttype ); break; case 'current-user-principal': $prop->NewElement("current-user-principal", $request->current_user_principal_xml); break; case 'displayname': $prop->NewElement($k, $displayname ); break; case 'resourcetype': $prop->NewElement($k); // Just an empty resourcetype for a non-collection. break; case 'getetag': $prop->NewElement($k, '"'.$item->dav_etag.'"' ); break; case '"current-user-privilege-set"': $prop->NewElement($k, privileges($request->permissions) ); break; case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */ $denied[] = $k; break; default: dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $v ); $unsupported[] = $k; } } $status = new XMLElement("status", "HTTP/1.1 200 OK" ); $propstat = new XMLElement( "propstat", array( $prop, $status) ); $href = new XMLElement("href", $url ); $elements = array($href,$propstat); if ( count($denied) > 0 ) { $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" ); $noprop = new XMLElement("prop"); foreach( $denied AS $k => $v ) { $noprop->NewElement( strtolower($v) ); } $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); } if ( count($unsupported) > 0 ) { $status = new XMLElement("status", "HTTP/1.1 404 Not Found" ); $noprop = new XMLElement("prop"); foreach( $unsupported AS $k => $v ) { $noprop->NewElement( strtolower($v) ); } $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); } $response = new XMLElement( "response", $elements ); return $response; } if ( $xmltree->GetTag() == "urn:ietf:params:xml:ns:caldav:calendar-query" ) { $calquery = $xmltree->GetPath("/urn:ietf:params:xml:ns:caldav:calendar-query/*"); include("caldav-REPORT-calquery.php"); } elseif ( $xmltree->GetTag() == "urn:ietf:params:xml:ns:caldav:calendar-multiget" ) { $mode = 'caldav'; $qry_content = $xmltree->GetContent('urn:ietf:params:xml:ns:caldav:calendar-multiget'); include("caldav-REPORT-multiget.php"); } elseif ( $xmltree->GetTag() == "urn:ietf:params:xml:ns:carddav:addressbook-multiget" ) { $mode = 'carddav'; $qry_content = $xmltree->GetContent('urn:ietf:params:xml:ns:carddav:addressbook-multiget'); include("caldav-REPORT-multiget.php"); } elseif ( $xmltree->GetTag() == "urn:ietf:params:xml:ns:carddav:addressbook-query" ) { $cardquery = $xmltree->GetPath("/urn:ietf:params:xml:ns:carddav:addressbook-query/*"); include("caldav-REPORT-cardquery.php"); } else { $request->PreconditionFailed( 403, 'DAV::supported-report', sprintf( '"%s" is not a supported report type') ); } function converte_semana($sema){ $retorna = "BYDAY="; $param = 1; while( $param <= 64 ){ $numero = $sema & $param; if ( $numero != 0 ){ switch ($numero){ case 1: $retorna .= "SU,"; break; case 2: $retorna .= "MO,"; break; case 4: $retorna .= "TU,"; break; case 8: $retorna .= "WE,"; break; case 16: $retorna .= "TH,"; break; case 32: $retorna .= "FR,"; break; case 64: $retorna .= "SA"; break; default: continue; } } $param = $param * 2; } $nova = substr($retorna, 0, -1); return $nova; } function dataTzParaSegundos($datatz){ $HorarioTimeZone = new DateTimeZone(date_default_timezone_get()); $HorarioTime = new DateTime("now", $HorarioTimeZone); return mktime( substr("$datatz", 9,2),//hora substr("$datatz", 11,2),//min substr("$datatz", 13,2),//segundos substr("$datatz", 4,2),//mes substr("$datatz", 6,2),//dia substr("$datatz", 0,4)) + $HorarioTimeZone->getoffset($HorarioTime);//ano } function dataSegundosParaT($dataseg, $opcao = 0){ if ($opcao!=1){ $teste = getdate($dataseg); return date("Ymd\THis",$teste[0]); } date_default_timezone_set('UTC'); $data_nova = date("Ymd\THis",$dataseg); date_default_timezone_set('America/Sao_Paulo'); $HorarioTimeZone = new DateTimeZone(date_default_timezone_get()); $HorarioTime = new DateTime($data_nova, $HorarioTimeZone); //$teste = getdate($dataseg - $HorarioTimeZone->getoffset($HorarioTime)); //date_default_timezone_set('UTC'); //$retorna = date("Ymd\THis\Z",$dataseg); $teste = getdate($dataseg - $HorarioTimeZone->getoffset($HorarioTime)); return date("Ymd\THis\Z",$teste[0]); }