Changeset 3984
- Timestamp:
- 04/12/11 09:27:42 (12 years ago)
- Location:
- branches/2.2
- Files:
-
- 4 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2/security/classes/funcoes_auxiliares.php
r3563 r3984 1 1 <?php 2 2 // Conjunto de funcoes de apoio as Classes de tratamento do certificado digital. 3 3 4 4 function pega_path($chaves,$linha) 5 5 { … … 33 33 return $ret; 34 34 } 35 35 36 36 function ler_certificados_CAS($path,$flag=false) 37 37 { … … 98 98 return $aux_xml; 99 99 } 100 101 102 function data_hora ($valor) 100 101 102 function data_hora ($valor) 103 103 { 104 104 $year = substr($valor, 0, 2); … … 123 123 $N = $lista[rand(0,count($lista)-1)].date('U').$lista[rand(0,count($lista)-1)].RAND(12345,9999999999).$lista[rand(0,count($lista)-1)].$lista[rand(0,count($lista)-1)].RAND(12345,9999999999).'.tmp'; 124 124 $aux = $GLOBALS['dirtemp'].'/'.$N;; 125 array_push($tab_arqs ,$aux); 126 return $aux; 125 array_push($tab_arqs ,$aux); 126 return $aux; 127 127 } 128 128 … … 138 138 return $ret; 139 139 } 140 141 140 141 142 142 function deleta_arquivos_temporarios($tab_arqs) 143 143 { 144 144 foreach($tab_arqs as $arquivo ) 145 { 145 { 146 146 if(file_exists($arquivo)) 147 147 { 148 148 unlink($arquivo); 149 149 } 150 } 151 } 152 153 150 } 151 } 152 153 function troca_espaco_por_mais($pem_data) 154 { 155 $begin = "CERTIFICATE-----"; 156 $end = "-----END"; 157 $aux = substr($pem_data, strpos($pem_data, $begin)+strlen($begin)); 158 $aux = substr($aux, 0, strpos($aux, $end)); 159 $aux = strtr($aux,' ','+'); 160 $aux = '-----BEGIN CERTIFICATE-----'.$aux.'-----END CERTIFICATE-----'; 161 return $aux; 162 } 154 163 function verificaopenssl() 155 164 { … … 165 174 function print_hex($value) 166 175 { 167 $tab_val = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 176 $tab_val = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 168 177 for($A=0;$A<strlen($value);$A++) 169 178 { … … 184 193 # Testa se tamanho menor/igual a 127 bytes.. 185 194 # Neste caso $len ja he o tamanho do conteudo 186 if ($len & 0x80) 195 if ($len & 0x80) 187 196 { 188 197 # Testa se tamanho indefinido (nao deve ocorrer em uma codificação DER. … … 193 202 $bytes = 0; 194 203 } 195 else 196 { 197 # he tamanho definido. diz quantos bytes formam o tamanho.... 204 else 205 { 206 # he tamanho definido. diz quantos bytes formam o tamanho.... 198 207 $bytes = $len & 0x0f; 199 208 $len = 0; 200 for ($i = 0; $i < $bytes; $i++) 209 for ($i = 0; $i < $bytes; $i++) 201 210 { 202 211 $len = ($len << 8) | ord($data[$i + 2]); … … 205 214 } 206 215 } 207 216 208 217 function xBase128($ab,$q,$flag ) 209 218 { 210 $abc = $ab; 219 $abc = $ab; 211 220 if( $q > 127 ) 212 221 { … … 256 265 return $value; 257 266 } 258 259 260 267 268 269 261 270 function Crl_parseASN($data,$context_especific = false) 262 { 271 { 263 272 // Tabela de OIDs . 264 273 $_oids = array( … … 290 299 '1.2.840.10040.4.3' => 'id-dsa-with-sha-1', 291 300 '1.3.6.1.5.5.7.3.2' => 'id_kp_clientAuth', 292 '1.3.6.1.5.5.7.3.4' => 'id_kp_securityemail', 301 '1.3.6.1.5.5.7.3.4' => 'id_kp_securityemail', 293 302 '1.3.6.1.5.5.7.2.1' => 'id_certificatePolicies', 294 303 '2.16.840.1.113730.1.1' => 'netscape-cert-type', … … 300 309 '2.16.840.1.113730.1.12' => 'netscape-ssl-server-name', 301 310 '2.16.840.1.113730.1.13' => 'netscape-comment', 302 '2.16.76.1.2.1' => 'A1', 303 '2.16.76.1.2.3' => 'A3', 311 '2.16.76.1.2.1' => 'A1', 312 '2.16.76.1.2.3' => 'A3', 304 313 '2.16.76.1.2.1.16' => 'Certification Practice Statement pointer', 305 314 '2.16.76.1.3.1' => 'Dados do cert parte 1', … … 1132 1141 1133 1142 $result = array(); 1134 1135 while (strlen($data) > 1) 1143 1144 while (strlen($data) > 1) 1136 1145 { 1137 1146 $class = ord($data[0]); 1138 switch ($class) 1147 switch ($class) 1139 1148 { 1140 1149 case 0x30: … … 1146 1155 $data = substr($data, 2 + $bytes + $len); 1147 1156 $values = Crl_parseASN($sequence_data); 1148 if (!is_array($values) || is_string($values[0])) 1157 if (!is_array($values) || is_string($values[0])) 1149 1158 { 1150 1159 $values = array($values); … … 1169 1178 $result[] = array('boolean (1)' , $boolean_value); 1170 1179 break; 1171 1180 1172 1181 case 0x02: 1173 1182 // Integer type … … 1188 1197 { 1189 1198 $value = 0; 1190 if ($len <= 4) 1199 if ($len <= 4) 1191 1200 { 1192 1201 // Method works fine for small integers 1193 for ($i = 0; $i < strlen($integer_data); $i++) 1202 for ($i = 0; $i < strlen($integer_data); $i++) 1194 1203 { 1195 1204 $value = ($value << 8) | ord($integer_data[$i]); 1196 1205 } 1197 } 1198 else 1206 } 1207 else 1199 1208 { 1200 // Method works for arbitrary length integers 1201 if (extension_loaded('bcmath')) 1209 // Method works for arbitrary length integers 1210 if (extension_loaded('bcmath')) 1202 1211 { 1203 for ($i = 0; $i < strlen($integer_data); $i++) 1212 for ($i = 0; $i < strlen($integer_data); $i++) 1204 1213 { 1205 1214 $value = bcadd(bcmul($value, 256), ord($integer_data[$i])); 1206 1215 } 1207 } 1208 else 1216 } 1217 else 1209 1218 { 1210 1219 $value = -1; … … 1227 1236 1228 1237 case 0x04: 1229 // Octetstring type 1238 // Octetstring type 1230 1239 $len = ord($data[1]); 1231 1240 $bytes = 0; … … 1242 1251 } 1243 1252 break; 1244 1253 1245 1254 case 0x0C: 1246 1255 // UTF8 STRING … … 1281 1290 $value = 0; 1282 1291 $i = 1; 1283 while ($i < strlen($oid_data)) 1292 while ($i < strlen($oid_data)) 1284 1293 { 1285 1294 $value = $value << 7; 1286 1295 $value = $value | (ord($oid_data[$i]) & 0x7f); 1287 1296 1288 if (!(ord($oid_data[$i]) & 0x80)) 1297 if (!(ord($oid_data[$i]) & 0x80)) 1289 1298 { 1290 1299 $plain .= '.' . $value; … … 1294 1303 } 1295 1304 1296 if (isset($_oids[$plain])) 1305 if (isset($_oids[$plain])) 1297 1306 { 1298 1307 $result[] = array('oid(' . $len . '): ' . $plain, $_oids[$plain]); 1299 } 1300 else 1308 } 1309 else 1301 1310 { 1302 1311 $result[] = array('oid(' . $len . '): ' . $plain, $plain); … … 1313 1322 $result[] = array('IA5 String (' . $len . ')' , $string_data); 1314 1323 break; 1315 1324 1316 1325 case 0x12: 1317 1326 case 0x14: 1318 case 0x15: 1319 case 0x81: 1327 case 0x15: 1328 case 0x81: 1320 1329 // Character string type 1321 1330 $len = ord($data[1]); … … 1336 1345 $result[] = array('string (' . $len . ')' , print_hex($string_data)); 1337 1346 break; 1338 1347 1339 1348 case 0x13: 1340 1349 case 0x86: … … 1379 1388 $result[] = array('Context Especific (' . $len . ')' , array(Crl_parseASN($extension_data,true))); 1380 1389 break; 1381 1390 1382 1391 case 0xa3: 1383 1392 // Extensions … … 1414 1423 1415 1424 } 1416 1417 function openssl_to_timestamp ($in) 1425 1426 function openssl_to_timestamp ($in) 1418 1427 { 1419 1428 $year = substr($in, 0, 4); /* NOTE: Yes, this returns a two digit year */ … … 1423 1432 $min = substr($in, 10, 2); 1424 1433 $sec = substr($in, 12, 2); 1425 1434 1426 1435 return gmmktime($hour, $min, $sec, $month, $day, $year); 1427 1436 } … … 1429 1438 #============================================================================================ 1430 1439 # Transforma o certificado do formato PEM para o formato DER ... 1431 function pem2der($pem_data) 1440 function pem2der($pem_data) 1432 1441 { 1433 1442 $begin = "CERTIFICATE-----"; 1434 1443 $end = "-----END"; 1435 $pem_data = substr($pem_data, strpos($pem_data, $begin)+strlen($begin)); 1444 $pem_data = substr($pem_data, strpos($pem_data, $begin)+strlen($begin)); 1436 1445 $pem_data = substr($pem_data, 0, strpos($pem_data, $end)); 1437 1446 $der = base64_decode($pem_data); … … 1442 1451 function testa_p7m($msg) 1443 1452 { 1444 // oids pesquisadas: 1453 // oids pesquisadas: 1445 1454 // 1.2.840.113549.1.7.2 assinatura digital 1446 1455 // 1.2.840.113549.1.7.3 envelopeddata … … 1455 1464 return 'signature' ; 1456 1465 } 1457 $oid_hexa = OIDtoHex('1.2.840.113549.1.7.3'); 1466 $oid_hexa = OIDtoHex('1.2.840.113549.1.7.3'); 1458 1467 $partes = explode($oid_hexa,$p7m_formato_der); // Faz o split pela oid... 1459 1468 if(count($partes)>1) 1460 1469 { 1461 1470 return 'cipher' ; 1462 } 1471 } 1463 1472 return 'normal'; 1464 1473 } … … 1492 1501 { 1493 1502 $xcv = $xcv2; 1494 $data = $xcv . $oid_hexa . $partes[$i]; // reconstroi a sequencia..... 1503 $data = $xcv . $oid_hexa . $partes[$i]; // reconstroi a sequencia..... 1495 1504 $ret = parse_sequence($data); 1496 1505 … … 1504 1513 { 1505 1514 $xcv = $xcv3; 1506 $data = $xcv . $oid_hexa . $partes[$i]; // reconstroi a sequencia..... 1515 $data = $xcv . $oid_hexa . $partes[$i]; // reconstroi a sequencia..... 1507 1516 $ret = parse_sequence($data); 1508 1517 if($ret[0] != '') … … 1515 1524 { 1516 1525 $xcv = $xcv4; 1517 $data = $xcv . $oid_hexa . $partes[$i]; // reconstroi a sequencia..... 1526 $data = $xcv . $oid_hexa . $partes[$i]; // reconstroi a sequencia..... 1518 1527 $ret = parse_sequence($data); 1519 1528 if($ret[0] != '') … … 1521 1530 $retr[] = $ret; 1522 1531 continue; 1523 } 1524 } 1525 } 1532 } 1533 } 1534 } 1526 1535 } 1527 1536 return $retr; … … 1535 1544 // OID's PESSOA FISICA = 2.16.76.1.3.1 , 2.16.76.1.3.6 , 2.16.76.1.3.5 , 2.16.76.1.4.n ... as 2.16.1.4.n não são obrigatórias e ão sao tratadas.. 1536 1545 // 1537 // OID's PESSOA JURIDICA = 2.16.76.1.3.4 , 2.16.76.1.3.2 , 2.16.76.1.3.3 , 2.16.76.1.3.7 1546 // OID's PESSOA JURIDICA = 2.16.76.1.3.4 , 2.16.76.1.3.2 , 2.16.76.1.3.3 , 2.16.76.1.3.7 1538 1547 // 1539 // OID's EQUIPAMENTO/APLICAÇÃO = 2.16.76.1.3.8 , 2.16.76.1.3.3 , 2.16.76.1.3.2 , 2.16.76.1.3.4 1540 // 1548 // OID's EQUIPAMENTO/APLICAÇÃO = 2.16.76.1.3.8 , 2.16.76.1.3.3 , 2.16.76.1.3.2 , 2.16.76.1.3.4 1549 // 1541 1550 // OID para logon no NT: 1.3.6.1.4.1.311.20.2.3 1542 1551 // … … 1552 1561 '3'=>array('NIS',11), 1553 1562 '4'=>array('RG',15), 1554 '5'=>array('ORGAOUF',6)), 1563 '5'=>array('ORGAOUF',6)), 1555 1564 '2.16.76.1.3.5' => array('1'=>array('TITULO',12), 1556 1565 '2'=>array('ZONA',3), 1557 1566 '3'=>array('SECAO',4), 1558 '4'=>array('TITULO_CIDADE_UF',0)), 1559 '2.16.76.1.3.6' => array('1'=>array('CADINSS',12)), 1560 '2.16.76.1.3.7' => array('1'=>array('CEI',12)), 1567 '4'=>array('TITULO_CIDADE_UF',0)), 1568 '2.16.76.1.3.6' => array('1'=>array('CADINSS',12)), 1569 '2.16.76.1.3.7' => array('1'=>array('CEI',12)), 1561 1570 '2.16.76.1.3.8' => array('1'=>array('NOMEEMPRESARIAL',0)), 1562 '1.3.6.1.4.1.311.20.2.3' => array('1'=>array('NTNOMEPRINCIPAL',0))); 1563 1564 $resultado = array(); 1571 '1.3.6.1.4.1.311.20.2.3' => array('1'=>array('NTNOMEPRINCIPAL',0))); 1572 1573 $resultado = array(); 1565 1574 $esta_oid = $oids[$oid]; 1566 1575 $p = 0; … … 1575 1584 { 1576 1585 $tamanho = $esta_oid[$i][1]; 1577 } 1586 } 1578 1587 $resultado[$oid][$esta_oid[$i][0]] = substr($valor,$p,$tamanho); 1579 1588 // A linha logo abaixo he para manter compatibilidade com versoes anteriores... Sera desativada assim que possivel... … … 1583 1592 1584 1593 return $resultado; 1585 } 1586 1587 1594 } 1595 1596 1588 1597 function subjectAltName($xx, $certificado_digital_formato_der) 1589 1598 { … … 1621 1630 } 1622 1631 1623 1632 1624 1633 function CRLDistributionPointsxx($xx, $certificado_digital_formato_der) 1625 1634 { … … 1629 1638 echo '</pre><br/><br/>'; 1630 1639 exit(); 1631 1632 1640 1641 1633 1642 $i=1; 1634 1643 if(substr($AUX[0][1][0],0,7) == 'boolean') … … 1638 1647 $AUX1 = $AUX[0][$i][1][1][0]; 1639 1648 // Pode existir mais de uma crl, mas vamos considerar apenas a primeira..... 1640 return array('CRLDISTRIBUTIONPOINTS' => $AUX1[1][0][1][0][1][0][1]); 1641 } 1649 return array('CRLDISTRIBUTIONPOINTS' => $AUX1[1][0][1][0][1][0][1]); 1650 } 1642 1651 1643 1652 function CRLDistributionPoints($xx, $certificado_digital_formato_der) … … 1664 1673 } 1665 1674 } 1666 1675 1667 1676 // Se $ret esta vazio tenta obter crls em outra estrutura(outro layout). 1668 1677 if(count($ret) == 0) … … 1680 1689 } 1681 1690 } 1682 1691 1683 1692 return array('CRLDISTRIBUTIONPOINTS' => $ret); 1684 } 1685 1686 1693 } 1694 1695 1687 1696 function SERIALNUMBER($cert_data,$KK) 1688 1697 { … … 1692 1701 $dados['SERIALNUMBER'] = $cert_data[1][0][1][$KK][1]; 1693 1702 } 1694 return $dados; 1695 } 1696 1703 return $dados; 1704 } 1705 1697 1706 function SUBJECT($cert_data,$KK) 1698 1707 { … … 1705 1714 $AUX = explode(':',$dados['SUBJECT']['CN']); 1706 1715 $dados['NOME'] = $AUX[0]; 1707 return $dados; 1708 } 1709 1710 function ISSUER($cert_data,$KK) 1711 { 1712 $dados = array(); 1716 return $dados; 1717 } 1718 1719 function ISSUER($cert_data,$KK) 1720 { 1721 $dados = array(); 1713 1722 $dados['EMISSOR_CAMINHO_COMPLETO'] = array(); 1714 1723 1715 1724 foreach($cert_data[1][0][1][$KK][1] as $AUX2) 1716 1725 { … … 1718 1727 } 1719 1728 $dados['EMISSOR'] = $dados['EMISSOR_CAMINHO_COMPLETO']['CN']; 1720 return $dados; 1721 } 1722 1723 1729 return $dados; 1730 } 1731 1732 1724 1733 function BEFOREAFTER($cert_data,$KK) 1725 1734 { … … 1735 1744 { 1736 1745 $dados['EXPIRADO'] = false; 1737 } 1738 return $dados; 1739 } 1746 } 1747 return $dados; 1748 } 1740 1749 1741 1750 … … 1758 1767 $dados['AUTHORITYKEYIDENTIFIER'] = "auto-assinado"; 1759 1768 } 1760 return $dados; 1761 } 1762 1769 return $dados; 1770 } 1771 1763 1772 function KEYUSAGE($xx, $certificado_digital_formato_der) 1764 1773 { 1765 $KeyUsage= array( 0x80 => 'digitalSignature', 1774 $KeyUsage= array( 0x80 => 'digitalSignature', 1766 1775 0x40 => 'nonRepudiation', 1767 1776 0x20 => 'keyEncipherment', … … 1786 1795 } 1787 1796 } 1788 } 1789 return $dados; 1797 } 1798 return $dados; 1790 1799 } 1791 1800 … … 1806 1815 } 1807 1816 } 1808 return $dados; 1809 } 1810 1817 return $dados; 1818 } 1819 1811 1820 function BASICCONSTRAINTS($xx, $certificado_digital_formato_der) 1812 1821 { … … 1820 1829 } 1821 1830 } 1822 return $dados; 1823 } 1824 1831 return $dados; 1832 } 1833 1825 1834 function recupera_dados_do_ceritificado_digital($certificado_digital_formato_pem) 1826 1835 { 1827 1836 $cert_der = pem2der($certificado_digital_formato_pem); 1828 1837 1829 1838 $funcoes = array(SERIALNUMBER => 1, 1830 1839 ISSUER => 3, … … 1837 1846 CRLDistributionPoints => $cert_der, 1838 1847 subjectAltName => $cert_der); 1839 1848 1840 1849 $dados=array(); 1841 1850 1842 1851 $cert_data = Crl_parseASN( $cert_der); 1843 1852 1844 1853 foreach($funcoes as $funcao => $parametro) 1845 1854 { … … 1854 1863 } 1855 1864 } 1856 return $dados; 1865 return $dados; 1857 1866 } 1858 1867 -
branches/2.2/security/vercert.php
r3232 r3984 1 1 <?php 2 function item_para_uid($dados_do_certificado)3 {4 /*5 // Exemplo do Array $dados_do_certificado padrao ICP-BRASIL6 // O conteudo do array pode variar conforme a AC emissora.7 Array8 (9 [SERIALNUMBER] => 200903181623280210 [EMISSOR_CAMINHO_COMPLETO] => Array11 (12 [C] => BR13 [O] => ICP-Brasil14 [OU] => CSPB-115 [CN] => HOMAutoridade Certificadora do SERPRO Final v216 )17 18 [EMISSOR] => HOMAutoridade Certificadora do SERPRO Final v219 [INICIO_VALIDADE] => 2009031820521620 [FIM_VALIDADE] => 2012031720521621 [EXPIRADO] =>22 [SUBJECT] => Array23 (24 [C] => BR25 [O] => ICP-Brasil26 [OU] => Pessoa Fisica A327 [CN] => CESAR VIANNA28 )29 30 [NOME] => CESAR VIANNA31 [AUTHORITYKEYIDENTIFIER] => AE34F397BB05B1AA6CC3FD6C4F0E9129BBB61BE232 [KEYUSAGE] => Array33 (34 [digitalSignature] => 135 [nonRepudiation] => 136 [keyEncipherment] => 137 )38 39 [EXTKEYUSAGE] => Array40 (41 [clientAuth] => 1.3.6.1.5.5.7.3.242 [emailProtection] => 1.3.6.1.5.5.7.3.443 )44 45 [CA] =>46 [CRLDISTRIBUTIONPOINTS] => Array47 (48 [0] => http://ccdhom.serpro.gov.br/lcr/serproacfv2.crl49 [1] => http://ccdhom.serpro.gov.br/lcr/serproacfv3.crl50 [2] => http://ccdhom.serpro.gov.br/lcr/serproacfv4.crl51 )52 53 [2.16.76.1.3.6] => Array54 (55 [CADINSS] => 00000000000056 )57 58 [CADINSS] => 00000000000059 [2.16.76.1.3.5] => Array60 (61 [TITULO] => 00000000000062 [ZONA] => 00063 [SECAO] => 000064 [TITULO_CIDADE_UF] =>65 )66 67 [TITULO] => 00000000000068 [ZONA] => 00069 [SECAO] => 000070 [TITULO_CIDADE_UF] =>71 [2.16.76.1.3.1] => Array72 (73 [NASCIMENTO] => 1908198174 [CPF] => 1234567890275 [NIS] => 1234567890176 [RG] => 00020107515095377 [ORGAOUF] => SSPRS78 )79 80 [NASCIMENTO] => 1908198181 [CPF] => 1234567890282 [NIS] => 1234567890183 [RG] => 00020107515095384 [ORGAOUF] => SSPRS85 [EMAIL] => cesar.vianna@pr.planalto.gov.br86 )87 */88 89 // Retorna o CPF para usar como uid.90 return $dados_do_certificado['2.16.76.1.3.1']['CPF'];91 }92 93 94 2 $GLOBALS['phpgw_info']['flags'] = array( 95 3 'disable_Template_class' => True, … … 118 26 require_once('classes/Verifica_Certificado.php'); 119 27 include('classes/Verifica_Certificado_conf.php'); 120 121 # Transforma o certificado do formato PEM para o formato DER ...122 function troca_espaco_por_mais($pem_data)123 {124 $begin = "CERTIFICATE-----";125 $end = "-----END";126 $aux = substr($pem_data, strpos($pem_data, $begin)+strlen($begin));127 $aux = substr($aux, 0, strpos($aux, $end));128 $aux = strtr($aux,' ','+');129 $aux = '-----BEGIN CERTIFICATE-----'.$aux.'-----END CERTIFICATE-----';130 return $aux;131 }132 28 133 29 $cert =str_replace(chr(0x0A).chr(0x0A),chr(0x0A),$_REQUEST['certificado']); … … 184 80 } 185 81 186 $filtro = 'uid='. item_para_uid($c->dados);82 $filtro = 'uid='. $c->dados['2.16.76.1.3.1']['CPF']; 187 83 $atributos = array(); 188 //$atributos[] = 'phpgwaccountexpires';189 $atributos[] = 'phpgwlastpasswdchange';190 191 if(isset($GLOBALS['phpgw_info']['server']['atributoexpiracao']))192 { 193 $atributos[] = $GLOBALS['phpgw_info']['server']['atributoexpiracao']; 194 } 195 84 if(isset($GLOBALS['phpgw_info']['server']['atributoexpiracao']) && $GLOBALS['phpgw_info']['server']['atributoexpiracao']) 85 { 86 $atributos[] = $GLOBALS['phpgw_info']['server']['atributoexpiracao']; 87 } 88 else 89 { 90 $atributos[] = 'phpgwlastpasswdchange'; 91 } 196 92 $atributos[] = "usercertificate"; 197 93 $atributos[] = "phpgwaccountstatus"; … … 231 127 $aux1 = $info[0]["dn"]; 232 128 $user_info['usercertificate'] = $cert; 233 if(isset($GLOBALS['phpgw_info']['server']['atributoexpiracao']) )129 if(isset($GLOBALS['phpgw_info']['server']['atributoexpiracao']) && $GLOBALS['phpgw_info']['server']['atributoexpiracao']) 234 130 { 235 131 if(substr($info[0][$GLOBALS['phpgw_info']['server']['atributoexpiracao']][0],-1,1)=="Z")
Note: See TracChangeset
for help on using the changeset viewer.