Terrano
Membres-
Compteur de contenus
373 -
Inscription
-
Dernière visite
-
Jours gagnés
5
Tout ce qui a été posté par Terrano
-
Si vous avez suivi mes précédents tutos pour CardDav, notamment celui-ci : Vous avez tous vos contacts de vos téléphones mobiles dans votre messagerie Mail. C'est déjà bien mais le must serait que cela soit utilisé encore plus. Le but de ce tutorial est triple : Ajouter une vue et un export de vos contacts pour synchroniser avec d'autres outils Ajouter vos contacts sur le répertoire téléphonique de vos téléphones IP A noter que j'ai testé et validé le fonctionnement du système en utilisant la fonctionnalité de Provisioning de mes téléphones IP Alcatel à savoir : 2 Alcatel Temporis IP600 (POE, SIP, Filaire) 1 Alcatel IP 1020 (POE, SIP, DECT) Nous allons procéder en plusieurs étapes. Export de l'annuaire CardDav Se connecter en ssh au Synology. Taper les commandes suivantes : mkdir /volume1/scripts mkdir /volume1/scripts/CardDav mkdir /volume1/web/tel mkdir /volume1/web/carddav cd /volume1/scripts/CardDav vi carddav.sh Nous allons mettre en place un script BASH pour exporter le contenu d'un annuaire, voici le script. Tapez i et insérez le code suivant : #!/bin/sh DIR=/volume1/scripts/CardDav HTMLXML="https://www.mondomaine.fr/carddav/carddav.php?action=EXTRACT&file=book&format=XML&view=FILE&option=ATR" HTMLCSV="https://www.mondomaine.fr/carddav/carddav.php?action=EXTRACT&file=book&format=CSV&view=FILE" ALC=/volume1/web/tel/contactData1.xml AST=/volume1/web/carddav/book.csv job () { ADDRESSBOOK=$SERVER"/addressbooks/users/"$USER"/addressbook/" rm $FILE"vcf.txt" rm $FILE".txt" curl -X PROPFIND -u $USER:$PASSWORD -H "Content-Type: text/xml" -H "Depth: 1" --data "<propfind xmlns='DAV:'><prop><address-data xmlns='urn:ietf:params:xml:ns:carddav'/></prop></propfind>" "$ADDRESSBOOK" -k >> $FILE"vcf.txt" while IFS='' read -r line || [[ -n "$line" ]]; do case "$line" in *".vcf"*) url=${line%</href>*} url=${url#*<href>} curl -u $USER:$PASSWORD -H "Content-Type: text/xml" "$SERVER$url" -k >> $FILE".txt" ;; *) ;; esac done < $FILE"vcf.txt" wget --no-check-certificate $HTMLXML -O $ALC wget --no-check-certificate $HTMLCSV -O $AST } while getopts "a:u:p:f:s:" opt; do case $opt in a) echo "-a was triggered, Parameter: $OPTARG" >&2 ACTION=$OPTARG ;; u) echo "-u was triggered, Parameter: $OPTARG" >&2 USER=$OPTARG ;; p) echo "-p was triggered, Parameter: $OPTARG" >&2 PASSWORD=$OPTARG ;; f) echo "-f was triggered, Parameter: $OPTARG" >&2 FILE=$OPTARG ;; s) echo "-s was triggered, Parameter: $OPTARG" >&2 SERVER=$OPTARG ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done cd $DIR case "$ACTION" in ("JOB") echo $(job) ;; (*) exit 1 ;; esac Appuyez sur Echappement, puis :wq pour sauvegarder le fichier. Rendre le fichier exécutable avec : chmod 755 carddav.sh Les variables dans le script : DIR : Dossier du script HTML : Lien HTTP ou HTTPS vers la vue et export PHP (installation dans la deuxième étape) ALC : Dossier et nom du fichier pour le provisioning des contacts pour les téléphones Alcatel Les paramètres d'exécution du script : -a JOB : Exécution du job du script -u user : Identifiant de l'utilisateur CardDav (utilisateur du Synology) -p password : Mot de passe Synology pour l'utilisateur précédent -f file : Libellé du fichier généré (au cas où on met en place l'export de plusieurs annuaires CardDav -s https://localhost:8443 : Lien HTTP du serveur CardDav (hébergé sur le Synology) Mise en place des vues et exports PHP La première chose à faire, est d'autoriser PHP à accèder à certains dossiers. Sous l'interface DSM, aller dans Panneau de Configuration,Services Web, Paramètres PHP et ajouter les éléments suivant au début de la variable PHP open_basedir : /volume1/web:/volume1/scripts: Reste à ajouter les scripts PHP suivant dans le dossier /volume1/web/carddav : class.php : <?php $carddav_dir = "/volume1/scripts/CardDav/"; $carddav_sh = $carddav_dir."carddav.sh"; $ssh2_ip = "ipdusyno"; $ssh2_port = "portssh"; $ssh2_password = "passwordssh"; $ssh2_account = "comptessh"; $carddavserver = "https://localhost:8443"; include_once(dirname(__FILE__) . "/vcard.php"); function strWithoutAccent($string){ $string = htmlentities($string, ENT_NOQUOTES, 'utf-8'); $string = preg_replace('#&([A-za-z])(?:uml|circ|tilde|acute|grave|cedil|ring);#', '\1', $string); $string = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $string); $string = preg_replace('#&[^;]+;#', '', $string); return $string; } function isJSON($string){ return is_string($string) && is_object(json_decode($string)) ? true : false; } function xml_to_array($xml,$main_heading = '') { $deXml = simplexml_load_string($xml); $deJson = json_encode($deXml); $xml_array = json_decode($deJson,TRUE); if (! empty($main_heading)) { $returned = $xml_array[$main_heading]; return $returned; } else { return $xml_array; } } function arguments ( $args ){ array_shift( $args ); $endofoptions = false; $ret = array ( 'commands' => array(), 'options' => array(), 'flags' => array(), 'arguments' => array(), ); while ( $arg = array_shift($args) ) { // if we have reached end of options, //we cast all remaining argvs as arguments if ($endofoptions) { $ret['arguments'][] = $arg; continue; } // Is it a command? (prefixed with --) if ( substr( $arg, 0, 2 ) === '--' ) { // is it the end of options flag? if (!isset ($arg[3])) { $endofoptions = true;; // end of options; continue; } $value = ""; $com = substr( $arg, 2 ); // is it the syntax '--option=argument'? if (strpos($com,'=')) list($com,$value) = split("=",$com,2); // is the option not followed by another option but by arguments elseif (strpos($args[0],'-') !== 0) { while (strpos($args[0],'-') !== 0) $value .= array_shift($args).' '; $value = rtrim($value,' '); } $ret['options'][$com] = !empty($value) ? $value : true; continue; } // Is it a flag or a serial of flags? (prefixed with -) if ( substr( $arg, 0, 1 ) === '-' ) { for ($i = 1; isset($arg[$i]) ; $i++) $ret['flags'][] = $arg[$i]; continue; } // finally, it is not option, nor flag, nor argument $ret['commands'][] = $arg; continue; } if (!count($ret['options']) && !count($ret['flags'])) { $ret['arguments'] = array_merge($ret['commands'], $ret['arguments']); $ret['commands'] = array(); } return $ret; } function makeXML($user, $password, $file){ $stack = array(); global $carddav_sh, $ssh2_ip, $ssh2_port, $ssh2_account, $ssh2_password, $carddavserver; $connection = ssh2_connect($ssh2_ip, $ssh2_port); if (!ssh2_auth_password($connection, $ssh2_account, $ssh2_password)) { array_push($stack, 'Echec de l\'identification...'); die(); } $stream = ssh2_exec($connection, $carddav_sh.' -a JOB -u '.$user.' -p '.$password.' -f '.$file.' -s '.$carddavserver); // Enable blocking for both streams stream_set_blocking($stream, true); while($line = fgets($stream)) { flush(); array_push($stack, $line); } // Close the streams fclose($stream); ssh2_exec($connection, 'exit'); unset($connection); } function string_to_ascii($string){ $ascii = NULL; for ($i = 0; $i < strlen($string); $i++) { $ascii = $ascii.'/'.ord($string[$i]); } return($ascii); } function print_vcard_address_book($file, $title, $style, $cat, $hide){ if ($title) { $title = stripcslashes($title); } else if ($file) { $title = $file; } else { $title = "vCard PHP - A vCard Address Book"; } echo "<html>\n<head>\n<title>$title</title>\n"; header('Content-Type: text/html; charset=utf-8'); if (!$style) { $style = "style.css"; } echo "<link href='$style' type='text/css' rel='stylesheet'>\n"; echo "</head>\n<body>\n"; echo "<h1>$title</h1>\n"; if (!$file) { exit('Required $file parameter not specified.'); } $lines = file($file); if (!$lines) { exit("Can't read the vCard file: $file"); } $cards = parse_vcards($lines); print_vcards($cards, $cat, $hide); echo "</body>\n</html>\n"; } /** * Prints a set of vCards in two columns. The $categories_to_display is a * comma delimited list of categories. */ function print_vcards(&$cards, $categories_to_display, $hide){ $all_categories = get_vcard_categories($cards); if (!$categories_to_display) { $categories_to_display = array('All'); } else if ($categories_to_display == '*') { $categories_to_display = $all_categories; } else { $categories_to_display = explode(',', $categories_to_display); } if ($hide) { $hide = explode(',', $hide); } else { $hide = array(); } echo "<p class='categories'>\nCategories: "; echo join(', ', $categories_to_display); echo "<br />\n</p>\n"; $i = 0; foreach ($cards as $card_name => $card) { if (!$card->inCategories($categories_to_display)) { continue; } if ($i == 0) { echo "<table width='100%' cellspacing='4' border='0'>\n"; echo "<tr>\n"; } echo "<td class='vcard' width='50%' valign='top'>\n"; echo "<p class='name'><strong>$card_name</strong>"; // Add the categories (if present) after the name. $property = $card->getProperty('CATEGORIES'); if ($property) { // Replace each comma by a comma and a space. $categories = $property->getComponents(','); $categories = join(', ', $categories); echo " ($categories)"; } echo "</p>\n"; print_vcard($card, $hide); echo "</td>\n"; $i = ($i + 1) % 2; if ($i == 0) { echo "</tr>\n"; echo "</table>\n"; } } if ($i != 0) { echo "<td> </td>\n"; echo "</tr>\n"; echo "</table>\n"; } } /** * Prints the vCard as HTML. */ function print_vcard($card, $hide){ $names = array('FN', 'TITLE', 'ORG', 'TEL', 'EMAIL', 'URL', 'ADR', 'BDAY', 'NOTE'); $row = 0; foreach ($names as $name) { if (in_array_case($name, $hide)) { continue; } $properties = $card->getProperties($name); if ($properties) { foreach ($properties as $property) { $show = true; $types = $property->params['TYPE']; if ($types) { foreach ($types as $type) { if (in_array_case($type, $hide)) { $show = false; break; } } } if ($show) { $class = ($row++ % 2 == 0) ? "property-even" : "property-odd"; print_vcard_property($property, $class, $hide); } } } } } /** * Prints a VCardProperty as HTML. */ function print_vcard_property($property, $class, $hide){ $name = $property->name; $value = $property->value; switch ($name) { case 'ADR': $adr = $property->getComponents(); $lines = array(); for ($i = 0; $i < 3; $i++) { if ($adr[$i]) { $lines[] = $adr[$i]; } } $city_state_zip = array(); for ($i = 3; $i < 6; $i++) { if ($adr[$i]) { $city_state_zip[] = $adr[$i]; } } if ($city_state_zip) { // Separate the city, state, and zip with spaces and add // it as the last line. $lines[] = join(" ", $city_state_zip); } // Add the country. if ($adr[6]) { $lines[] = $adr[6]; } $html = join("\n", $lines); break; case 'EMAIL': $html = "<a href='mailto:$value'>$value</a>"; break; case 'URL': $html = "<a href='$value' target='_base'>$value</a>"; break; case 'BDAY': $html = "Birthdate: $value"; break; default: $components = $property->getComponents(); $lines = array(); foreach ($components as $component) { if ($component) { $lines[] = $component; } } $html = join("\n", $lines); break; } echo "<p class='$class'>\n"; echo nl2br(stripcslashes($html)); $types = $property->params['TYPE']; if ($types) { $type = join(", ", $types); echo " (" . ucwords(strtolower($type)) . ")"; } echo "\n</p>\n"; } function get_vcard_categories(&$cards){ $unfiled = false; // set if there is at least one unfiled card $result = array(); foreach ($cards as $card_name => $card) { $properties = $card->getProperties('CATEGORIES'); if ($properties) { foreach ($properties as $property) { $categories = $property->getComponents(','); foreach ($categories as $category) { if (!in_array($category, $result)) { $result[] = $category; } } } } else { $unfiled = true; } } if ($unfiled && !in_array('Unfiled', $result)) { $result[] = 'Unfiled'; } return $result; } function parse_vcards(&$lines){ $cards = array(); $card = new VCard(); while ($card->parse($lines)) { $property = $card->getProperty('FN'); if (!$property) { return ""; } $n = $property->getComponents(); $tmp = array(); if ($n[3]) $tmp[] = $n[3]; // Mr. if ($n[1]) $tmp[] = $n[1]; // John if ($n[2]) $tmp[] = $n[2]; // Quinlan if ($n[4]) $tmp[] = $n[4]; // Esq. $ret = array(); if ($n[0]) $ret[] = $n[0]; $tmp = join(" ", $tmp); if ($tmp) $ret[] = $tmp; $key = join(", ", $ret); $cards[$key] = $card; $card = new VCard(); } ksort($cards); return $cards; } // ----- Utility Functions ----- /** * Checks if needle $str is in haystack $arr but ignores case. */ function in_array_case($str, $arr){ foreach ($arr as $s) { if (strcasecmp($str, $s) == 0) { return true; } } return false; } function convert_french_type($type){ $types = array('HOME' => 'Domicile','HOME2' => 'Domicile','WORK' => 'Travail', 'WORK2' => 'Travail', 'MOBILE' => 'Mobile', 'CELL' => 'Mobile', 'MAIN' => 'Principal', 'OTHER' => 'Autre', 'HOMEFAX' => 'Fax', 'WORKFAX' => 'Fax', 'CAR' => 'Voiture', 'PAGER' => 'Pager', 'VIDEO' => 'Video', 'ASSISTANT' => 'Assistant'); return $types[$type]; } ?> vcard.php : <?php /* * File: * vcard.php * * Project: * vCard PHP <http://vcardphp.sourceforge.net> * * Author: * Frank Hellwig <frank@hellwig.org> * * Usage: * Use the following URL to display the help text: * * http://host/path/vcard.php */ /** * The VCard class encapsulates a single vCard object by maintaining a map of * property names to one or more property values associated with that name. * A name is the unique property identifier such as N, ADR, and TEL. */ class VCard { /** * An associative array where each key is the property name and each value * is a VCardProperty array of properties which share that property name. */ var $_map; /** * Parses a vCard from one or more lines. Lines that are not property * lines, such as blank lines, are skipped. Returns false if there are * no more lines to be parsed. */ function parse(&$lines) { $this->_map = null; $property = new VCardProperty(); while ($property->parse($lines)) { if (is_null($this->_map)) { if ($property->name == 'BEGIN') { $this->_map = array(); } } else { if ($property->name == 'END') { break; } else { $this->_map[$property->name][] = $property; } } // MDH: Create new property to prevent overwriting previous one // (PHP5) $property = new VCardProperty(); } return $this->_map != null; } /** * Returns the first property mapped to the specified name or null if * there are no properties with that name. */ function getProperty($name) { return $this->_map[$name][0]; } /** * Returns the properties mapped to the specified name or null if * there are no properties with that name. */ function getProperties($name) { return $this->_map[$name]; } /** * Returns an array of categories for this card or a one-element array with * the value 'Unfiled' if no CATEGORIES property is found. */ function getCategories() { $property = $this->getProperty('CATEGORIES'); // The Mac OS X Address Book application uses the CATEGORY property // instead of the CATEGORIES property. if (!$property) { $property = $this->getProperty('CATEGORY'); } if ($property) { $result = $property->getComponents(','); } else { $result = array('Unfiled'); } $result[] = "All"; // Each card is always a member of "All" return $result; } /** * Returns true if the card belongs to at least one of the categories. */ function inCategories(&$categories) { $our_categories = $this->getCategories(); foreach ($categories as $category) { if (in_array_case($category, $our_categories)) { return true; } } return false; } } /** * The VCardProperty class encapsulates a single vCard property consisting * of a name, zero or more parameters, and a value. * * The parameters are stored as an associative array where each key is the * parameter name and each value is an array of parameter values. */ class VCardProperty { var $name; // string var $params; // params[PARAM_NAME] => value[,value...] var $value; // string /** * Parses a vCard property from one or more lines. Lines that are not * property lines, such as blank lines, are skipped. Returns false if * there are no more lines to be parsed. */ function parse(&$lines) { while (list(, $line) = each($lines)) { $line = rtrim($line); $tmp = split_quoted_string(":", $line, 2); if (count($tmp) == 2) { $this->value = $tmp[1]; $tmp = strtoupper($tmp[0]); $tmp = split_quoted_string(";", $tmp); $this->name = $tmp[0]; $this->params = array(); for ($i = 1; $i < count($tmp); $i++) { $this->_parseParam($tmp[$i]); } if ($this->params['ENCODING'][0] == 'QUOTED-PRINTABLE') { $this->_decodeQuotedPrintable($lines); } if ($this->params['CHARSET'][0] == 'UTF-8') { $this->value = utf8_decode($this->value); } return true; } } return false; } /** * Splits the value on unescaped delimiter characters. */ function getComponents($delim = ";") { $value = $this->value; // Save escaped delimiters. $value = str_replace("\\$delim", "\x00", $value); // Tag unescaped delimiters. $value = str_replace("$delim", "\x01", $value); // Restore the escaped delimiters. $value = str_replace("\x00", "$delim", $value); // Split the line on the delimiter tag. return explode("\x01", $value); } // ----- Private methods ----- /** * Parses a parameter string where the parameter string is either in the * form "name=value[,value...]" such as "TYPE=WORK,CELL" or is a * vCard 2.1 parameter value such as "WORK" in which case the parameter * name is determined from the parameter value. */ function _parseParam($param) { $tmp = split_quoted_string('=', $param, 2); if (count($tmp) == 1) { $value = $tmp[0]; $name = $this->_paramName($value); $this->params[$name][] = $value; } else { $name = $tmp[0]; $values = split_quoted_string(',', $tmp[1]); foreach ($values as $value) { $this->params[$name][] = $value; } } } /** * The vCard 2.1 specification allows parameter values without a name. * The parameter name is then determined from the unique parameter value. */ function _paramName($value) { static $types = array ( 'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK', 'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER', 'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO', 'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD', 'INTERNET', 'IBMMAIL', 'MCIMAIL', 'POWERSHARE', 'PRODIGY', 'TLX', 'X400', 'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB', 'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME', 'MPEG', 'MPEG2', 'AVI', 'WAVE', 'AIFF', 'PCM', 'X509', 'PGP'); static $values = array ( 'INLINE', 'URL', 'CID'); static $encodings = array ( '7BIT', 'QUOTED-PRINTABLE', 'BASE64'); $name = 'UNKNOWN'; if (in_array($value, $types)) { $name = 'TYPE'; } elseif (in_array($value, $values)) { $name = 'VALUE'; } elseif (in_array($value, $encodings)) { $name = 'ENCODING'; } return $name; } /** * Decodes a quoted printable value spanning multiple lines. */ function _decodeQuotedPrintable(&$lines) { $value = &$this->value; while ($value[strlen($value) - 1] == "=") { $value = substr($value, 0, strlen($value) - 1); if (!(list(, $line) = each($lines))) { break; } $value .= rtrim($line); } $value = quoted_printable_decode($value); } } // ----- Utility Functions ----- /** * Splits a string. Similar to the split function but uses a single character * delimiter and ignores delimiters in double quotes. */ function split_quoted_string($d, $s, $n = 0) { $quote = false; $len = strlen($s); for ($i = 0; $i < $len && ($n == 0 || $n > 1); $i++) { $c = $s{$i}; if ($c == '"') { $quote = !$quote; } else if (!$quote && $c == $d) { $s{$i} = "\x00"; if ($n > 0) { $n--; } } } return explode("\x00", $s); } ?> style.css : body { color: black; background: white; margin: 1em; font: normal 8pt Verdana, Arial, sans-serif; } h1 { font: bold 12pt Verdana, Arial, sans-serif; text-align: center; } h2 { font: normal 12pt Verdana, Arial, sans-serif; color: navy; margin-left: -1px; border-bottom: thin solid navy; } p { font: normal 8pt Verdana, Arial, sans-serif; } p.categories { margin-left: 2px; } p.name { padding: 2px; margin: 0; } p.property-even { background: #eee; padding: 2px; margin: 0; } p.property-odd { background: #ddd; padding: 2px; margin: 0; } td { padding: 2px; } td.vcard { border: thin solid #f99; background: #cbdced; } dt, li { margin-top: 1ex; } a { cursor: pointer } a:link { color: blue; background: transparent; text-decoration: none } a:visited { color: blue; background: transparent; text-decoration: none } a:active { color: blue; background: transparent; text-decoration: none } a:hover { color: red; background: transparent; text-decoration: underline } carddav.php : <?php include_once(dirname(__FILE__) . "/class.php"); $data = stripslashes(file_get_contents('php://input')); $data = str_replace("\"{","{",$data); $data = str_replace("}\"","}",$data); $json = json_decode($data, true); $action = $_POST['action'].$_GET['action'].$json['action']; $user = $_POST['user'].$_GET['user'].$json['user']; $password = $_POST['password'].$_GET['password'].$json['password']; $file = $_POST['file'].$_GET['file'].$json['file']; $format = $_POST['format'].$_GET['format'].$json['format']; $view = $_POST['view'].$_GET['view'].$json['view']; $option = $_POST['option'].$_GET['option'].$json['option']; if (!$file) { exit('Required $file parameter not specified.'); } if (!$action) { $action = "LIST"; //$action = "EXTRACT"; } if (!$view) { $view = "HTML"; //$view = "FILE"; } if (!$format) { $format = "XML"; //$view = "CSV"; } if (!$option) { $option = "ATR"; //$option = "VAL"; } if ($action == "LIST") { echo makeXML($user, $password, $file); } if ($action == "EXTRACT") { $lines = file($carddav_dir.$file.'.txt'); if (!$lines) { exit("Can't read the vCard file: $file"); } $cards = parse_vcards($lines); if ($format == "XML") { if ($option == "ATR") { $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><contactData/>'); $xml->addChild('groupinfo'); $xml->addChild('blacklist'); $group = $xml->addChild('group'); foreach ($cards as $card_name => $card) { $property = $card->getProperty('FN'); $properties = $card->getProperties('TEL'); if ($properties) { foreach ($properties as $telproperty) { $types = $telproperty->params['TYPE']; if ($types) { foreach ($types as $type) { $contact = $group->addChild('contact'); $contact['sDisplayName'] = strWithoutAccent($property->getComponents()[0]).' ('.convert_french_type($type).')'; $contact['sOfficeNumber'] = $telproperty->getComponents()[0]; $contact['sMobilNumber'] = ''; $contact['sOtherNumber'] = ''; } } } } $contact['sLine'] = ''; $contact['sRing'] = ''; $contact['group'] = ''; } } if ($option == "VAL") { $xml = new SimpleXMLElement('<?xml version="1.0" encoding="ISO-8859-1"?><MyCompanyDirectory/>'); $xml->addChild('Title', 'Famille'); foreach ($cards as $card_name => $card) { $property = $card->getProperty('FN'); $properties = $card->getProperties('TEL'); if ($properties) { foreach ($properties as $telproperty) { $types = $telproperty->params['TYPE']; if ($types) { foreach ($types as $type) { $group = $xml->addChild('MenuItem'); $group->addChild('Prompt', strWithoutAccent($property->getComponents()[0]).' ('.convert_french_type($type).')'); $group->addChild('URI', $telproperty->getComponents()[0]); } } } } } } if ($view == "HTML") { Header('Content-type: text/xml; charset=utf-8'); echo ($xml->asXML()); } if ($view == "FILE") { $dom = new DOMDocument('1.0'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->loadXML($xml->asXML()); $dom->save($file.$option.'.xml'); if (file_exists($file.$option.'.xml')) { header($_SERVER["SERVER_PROTOCOL"] . " 200 OK"); header("Cache-Control: public"); // needed for i.e. header("Content-Type: application/xml; charset=utf-8"); header("Content-Transfer-Encoding: Binary"); header("Content-Length:".filesize($file.$option.'.xml')); header("Content-Disposition: attachment; filename=".$file.$option.'.xml'); readfile($file.$option.'.xml'); die(); } else { die("Error: File not found."); } } } if ($format == "CSV") { $contact = array(); foreach ($cards as $card_name => $card) { $property = $card->getProperty('FN'); $properties = $card->getProperties('TEL'); if ($properties) { foreach ($properties as $telproperty) { $types = $telproperty->params['TYPE']; if ($types) { foreach ($types as $type) { $contact[] = array($property->getComponents()[0].' ('.convert_french_type($type).')', $telproperty->getComponents()[0]); } } } } } $f = fopen($file.'.csv', 'w'); foreach ($contact as $fields) { fputcsv($f, $fields); } fclose($f); if ($view == "HTML") { echo "<html><body><table>\n\n"; $f = fopen($file.'.csv', 'r'); while (($line = fgetcsv($f)) !== false) { echo "<tr>"; foreach ($line as $cell) { echo "<td>" . htmlspecialchars($cell) . "</td>"; } echo "</tr>\n"; } fclose($f); echo "\n</table></body></html>"; } if ($view == "FILE") { if (file_exists($file.'.csv')) { header($_SERVER["SERVER_PROTOCOL"] . " 200 OK"); header("Cache-Control: public"); // needed for i.e. header("Content-Type: text/csv"); header("Content-Transfer-Encoding: Binary"); header("Content-Length:".filesize($file.'.csv')); header("Content-Disposition: attachment; filename=".$file.'.csv'); readfile($file.'.csv'); die(); } else { die("Error: File not found."); } } } } if ($action == "SHOW") { print_vcard_address_book( $carddav_dir.$file.'.txt', $_GET['title'], $_GET['style'], $_GET['cat'], $_GET['hide']); } ?> A partir de là, vous pouvez faire plusieurs choses : https://www.mondomaine.fr/carddav/carddav.php?action=LIST&file=file&user=user&password=password Permet de lancer la synchronisation (bash) à partir d'une requête web, utile si vous avez programmé une synchronisation quotidienne mais que vous voulez pouvoir le lancer à la demande https://www.mondomaine.fr/carddav/carddav.php?action=SHOW&file=file&cat=All Permet de visionner en HTML la liste des contacts https://www.mondomaine.fr/carddav/carddav.php?action=EXTRACT&file=file&format=XML&view=HTML&option=VAL Lien HTTP permettant d'extraire les données avec plusieurs paramètres : format : XML : Représentation XML CSV : Représentation CSV view : HTML : Sortie graphique FILE : Fichier téléchargé option : VAL : Fichier XML ISO-8859-1 utilisant les Valeurs pour afficher les données ATR : Fichier XML UTF-8 utilisants les Attributs pour afficher les données Mise en place du job de synchronisation Rien de plus simple, sous l'interface DSM, aller dans Panneau de Configuration, Planificateur de Tâches. Cliquer sur Créer / Script défini par l'utilisateur Donner un nom à la tâche, la faire exécuter par l'utilisateur root et renseigner le lien suivant dans Exécuter la commande : /volume1/scripts/CardDav/carddav.sh -a JOB -u user -p password -f file -s https://localhost:8443 J'ai programmé la tâche pour s'exécuter toutes les 5 minutes. A vous de voir à quel rythme vous souhaitez voir vos contacts synchronisés. Mise en place du provisioning des répertoires locaux des téléphones IP Maintenant, plus spécifiquement pour les téléphones Alcatel, nous allons mettre en place le provisionning pour 2 choses : Mise à jour des firmware Mise à jour de l'annuaire des contacts sur le téléphones Pour se faire, il suffit de déposer dans le dossier /volume1/web/tel les fichiers suivants : firmware.rom : Correspond au logiciel interne du téléphone à mettre à jour y000000000014.cfg : fichier de provisioning propre aux modèles IP600 PS : il est possible de créer des fichiers de provisionning propre à chaque tel en nommant le fichier avec l'adresse MAC du tel Le contenu du fichier y000000000014.cfg : #Version 201509301404 [ firmware ] path = /tmp/download.cfg server_type = https server_ip = server_port = login_name = login_pswd = http_url = https://www.mondomaine.fr/tel/ firmware_name = firmware.rom [ ContactList ] path = /tmp/download.cfg server_address = https://www.mondomaine.fr/tel/contactData1.xml Conclusion : Je me retrouve avec un système de gestion des contacts (perso, famille...) très complet qui me permet d'avoir mes contacts synchronisés sur les téléphones fixes, les téléphones mobiles, ma messagerie mail. Je peux alors facilement ajouter un contact en passant par la saisie dans l'interface Web de ma messagerie et le retrouver sur mon tel en déplacement ou au bureau. :)
-
Personnellement, le script ne marche plus a cause d'un captcha qui apparait. Je vais essayer de trouver une solution.
-
Ip locale bloquée mais liste vide...
Terrano a répondu à un(e) sujet de Terrano dans Pare-Feu et QoS
Comme déjà dit plusieurs fois, gaetan, déjà fait et ça ne marche pas que pour l'ip 192.168.0.9. ;) Toutes les autres, aucun problème. -
Ip locale bloquée mais liste vide...
Terrano a répondu à un(e) sujet de Terrano dans Pare-Feu et QoS
SSH et VPN par SSLH et pas par NGINX, oui. :) Pour iptables -L -v -n, aucune règle propre à l'IP 192.168.0.9. Les mêmes règles s'appliquent à l'IP 192.168.0.50 et tout marche bien de ce coté là. Sur le réseau, j'ai vérifié également le routeur, rien de spécifique non plus. Par contre, sur le PC, je n'ai effectivement rien vérifié mis à part le Firewall. C'est un Windows 10, donc si vous avez des pistes sur ce que je dois vérifier, suis preneur. -
Ip locale bloquée mais liste vide...
Terrano a répondu à un(e) sujet de Terrano dans Pare-Feu et QoS
J'ai essayé avec l'ip directe, sans passer donc par Nginx ou DNS server, même résultat. J'ai essayé de désactiver tous les firewall (PC et NAS), rien. Pour rappel, juste en changeant l'ip sur le PC, le problème disparait. Il s'agit d'une page web qui me dit que le serveur a refusé la connexion, avant même d'avoir la page d'accueil de DSM par exemple. Par contre, en VPN, en passant a travers SSLH, ou en SSH en passant par NGINX, aucun problème. Je pense que l'IP est directement bloquée par le NAS au niveau de Web Station car même le site web n'est pas accessible. -
Ip locale bloquée mais liste vide...
Terrano a répondu à un(e) sujet de Terrano dans Pare-Feu et QoS
J'ai essayé, y compris reboot, pas de changement :/ -
Bonjour, Bizarrement, j'ai un ordi fixe qui ne peut pas accéder à mon NAS par le Web, cela me renvoie "connexion refusée". Or, ça marche pour les partages réseaux, le VPN, SSH, bref... J'ai remarqué que si je change l'adresse IP fixe, là, ce n'est plus bloqué et tout fonctionne. Dans Panneau de Configuration, Sécurité, Blocage Auto, mon adresse IP n'est pas présente dans la liste des adresses bloquées. J'ai également essayé de la mettre dans la liste des adresses autorisées, mais rien n'y fait. Une idée pour trouver où est bloquée cette adresse et comment la libérer ?
-
Exact, ça fonctionne parfaitement sur TCP, ce qui posait le problème, c'était les certificats en fait. Avec la perte de mes disques et la reconstruction du serveur, j'ai pu revoir l'installation et là, tout fonctionne nickel avec mes certificats
-
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
Alors, pour rendre le changement persistant après chaque redémarrage ou update, très simple : Sous SSH, faire : vi /usr/local/etc/rc.d/S99fwrules.sh Appuyer sur i pour passer en mode édition, copier/coller le code suivant #!/bin/sh [ "$1" == "start" ] || exit iptables -t nat -A PREROUTING -m iprange --src-range IPDEBUT-IPFIN -i bond0 -p tcp --dport 443 -j DNAT --to IPDUNAS:444 iptables -t nat -A PREROUTING -m iprange --src-range IPDEBUT-IPFIN -i bond0 -p tcp --dport 80 -j DNAT --to IPDUNAS:81 Appuyer sur Escape puis :wq et Enter pour sauver Terminer par la commande suivante pour rendre le fichier exécutable au démarrage : chmod +x /usr/local/etc/rc.d/S99fwrules.sh -
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
J'ai fait un test local et externe et tout marche nickel, plus de problème de Loopback. Juste à faire attention de bien pointer vers le DNS du server Synology. -
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
J'ai trouvé !!! \o/ Reste à trouver comment le rendre permanent à chaque reboot du NAS. -
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
Quelque chose de ce genre ? REDIRECT plutot, non ? Je sais pas là... :/ -
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
Pour dsm, comme pour SSH, pas de soucis, j'ai un accès direct à partir d'un seul PC d'administration du réseau qui sert qu'à ça ^^ Si nginx déconne, ou iptable, j'aurais toujours accés. Reste à écrire les règles iptables, sauf que j'y connais rien lol -
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
Nginx et Httpd étant sur le syno. Ce que j'ai actuellement : De l'exterieur : 443 -> livebox -> 444 -> Nginx -> 443 -> HTTPD De l'intérieur : 444 -> Nginx -> 443 -> HTTPD Ce que tu proposes, c'est router les paquets venant du réseau local en 443 vers 444 avant qu'ils soient traités par httpd pour que ce soit nginx qui les gère ? En quoi cela ferait perdre l'accès à Webstation ? Vu que de toute façon cette accès passe par nginx donc en local sur le serveur ? Suffit de router tous les paquets venant du réseau local sauf ceux venant du routeur ou du synology lui-même ? -
Loopback Orange
Terrano a répondu à un(e) sujet de KZL dans Installation, Démarrage et Configuration
Coucou les louloutes. Perso, j'arrive à gérer le loopback en mettant les entrées DNS de mes noms de domaines sur le DNS Server Syno et en faisant pointer les DNS des appareils sur le réseau interne vers le Syno. Sauf que... Et oui... Faut pas réver... Depuis l'extérieur, j'attaque le port 443 de la livebox qui renvoie vers le port 444 du synology. Sur le port 444, c'est nginx qui prend le relais pour renvoyer vers les sous-domaines correspondants sur les ports souhaités. Sauf que, quand je suis sur le port 443 en externe, ça fonctionne, mais en interne, ça fonctionne si je précise le port 444. ^^ Vous voyez le problème ? Il faudrait que le port externe de la livebox et le port interne du Synology utilisait par nginx soit identique, sauf que le port 443 ne peut être utilisé par nginx car déjà utilisé par Web Station. :/ Est-ce envisageable de changer le port de Web Station en https par défaut de 443 à 444 pour que je puisse utiliser le port 443 dans nginx ? -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Tous les tests ont été passé avec succès même si plus long que pour les 3 autres. Aucune alerte avec les différents outils smart. Vais pouvoir monter les 4 disques. ^^ -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Bon j'attend qu'il termine le full zéro writing et après je fais un test smart complet -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Heureusement que le disque est encore sous garantie ^^ -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Peut être que je m'y prend mal. ^^ Pour information, j'utilise l'outil Western Digital Data LifeGuard Diagnostics. Devrais-je en utiliser un autre ? Genre CrystalDiskInfo (http://www.pcastuces.com/logitheque/crystaldiskinfo.htm) ? -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
J'ai fait un Quick test SMART qui a duré 2 minutes avant de lancer le Full Zero Writing. Il s'est bien terminé en succès sans erreurs relevées. Dois-je faire un Full Test SMART ? P.S. : J'ai modifié ma signature, avec un disque en moins pour le moment, je vais faire du SHR. -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Un truc que je ne pige pas.... le 4ème disque en est à 17h pour le Full Zero Writing et il n'a toujours pas terminé alors qu'il est de modèle identique aux autres... Se pourrait-il qu'il ai un problème ? Je pense que je le verrais à la fin du processus, mais pas rassurant. -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Déjà 2 disques de préparé, 14h par disque, pffiooouuu ^^ -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Je vais m'y atteler mais faut aussi pouvoir monter un raid de 4 disques dans le Pc ^^ -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
N'ayant pas de Linux sous la main et vu le peu de perte (3 films que j'ai en DVD à rip de nouveau, que j'ai récupéré mes mails et que je referais les photos), j'ai entamé de remonter les disques. En attendant, c'est le disque de backup qui sert de secours. les tests SMART sont tout bon. Suis entrain de les réécrire en full zéro, 7h par disque. je réinstalle tout fin de semaine prochaine. C'est tout bon. une bonne pub pour faire toujours des backup par contre, pourquoi ça a planté, mystère, je continue à penser que c'est la partition système qui a planté suite au double reset. -
Perte Connexion RS814+
Terrano a répondu à un(e) sujet de Terrano dans Installation, Démarrage et Configuration
Alors la, c'est du shr sur, mais le type m'en souviens plus :/ ca doit être du 10 effectivement, le problème c'est que je n'ai pas de Linux. Va falloir que je m'en fasse un.