6 votes

Réglage du compte Photo/JPEGPhoto avec dscl dans le terminal

Je travaille sur un script basé sur cette question : Quelles sont les étapes nécessaires pour créer un nouvel utilisateur à partir de la ligne de commande sur Mountain Lion ?

Le script est intégré dans un programme d'installation vide en tant que script post-vol.

Tout fonctionne assez bien, mais je n'arrive pas à régler l'image de compte. Je peux utiliser dscl pour définir la propriété Picture sur un fichier image, par exemple le fichier les photos par défaut du compte Apple.

Je peux même copier une photo que j'inclus dans le paquet dans un certain nombre de répertoires, y compris /Users/newAccount/Public. Mais les autorisations sont mal réglées et personne d'autre que le nouveau compte ne peut voir l'image de profil. Je ne parviens pas à modifier le code du fichier. Au lieu de cela, je dois utiliser l'interface graphique et "obtenir des informations -> Définir les autorisations"

L'autre option que je vois est de définir la valeur JPEGPhoto. C'est ce qui se passe lorsque vous utilisez une photo personnalisée ou que vous en prenez une dans le photobooth. Cependant, je ne sais pas comment convertir la photo que j'inclus dans le programme d'installation en hexadécimal ou en tout autre élément stocké dans la valeur JPEGPhoto.

T - Chris

Edit : Ajouté script. Tout fonctionne dans ce script - l'image ne s'affiche pas, à cause des permissions. Le chemin d'accès est correctement défini. J'ai essayé de le placer à plusieurs endroits différents qui ont un accès partagé, mais quoi qu'il en soit les permissions sont mauvaises et je ne peux pas les chmoder.

###CREATE TP ADMINISTRATOR ACCOUNT###

LastID=`dscl . -list /Users UniqueID | awk '{print $2}' | sort -n | tail -1`

NextID=$((LastID + 1))
. /etc/rc.common
dscl . create /Users/administrator

dscl . create /Users/administrator RealName "Administrator Account"
dscl . create /Users/administrator hint "the password Duh"

dscl . passwd /Users/administrator password
dscl . create /Users/administrator UniqueID $NextID
dscl . create /Users/administrator PrimaryGroupID 80
dscl . create /Users/administrator UserShell /bin/bash
dscl . create /Users/administrator NFSHomeDirectory /Users/administrator
cp -R /System/Library/User\ Template/English.lproj /Users/administrator
chown -R administrator:staff /Users/administrator

cp $1"/Contents/Resources/admin.jpg" /Users/administrator/Public
dscl . create /Users/administrator Picture "/Users/administrator/Public/admin.jpg"

###CREATE TP ADMINISTRATOR ACCOUNT###

6voto

Dscl

Il semble que la méthode la plus prometteuse consiste à modifier le système de gestion de l'information. JPEGPhoto pour l'utilisateur. Le problème est que, bien que l'image JPEG puisse être convertie très simplement en une chaîne hexagonale, la valeur est trop longue pour être transmise à la ligne de commande. Cet attribut semble être ce que l'interface graphique écrit lorsque vous faites glisser une image. Récupérer l'image à partir de cette variable lorsqu'elle est définie est aussi simple que :

dscl . read /Users/username JPEGPhoto | xxd -r -p > ./username.jpg

La deuxième méthode couramment mentionnée sur les forums est la suivante :

dscl . delete /Users/username JPEGPhoto
dscl . delete /Users/username Picture
dscl . delete /Users/username Picture "/Library/User Pictures/username.jpg"

Cette opération ne modifie que l'icône de connexion et non l'icône affichée sur la page des détails de l'utilisateur dans les préférences du système.

Utilisation de dsimport

Ce qui fonctionne pour changer l'image de l'utilisateur est dsimport .

L'utilisation de script est la suivante :

./change_userpic.sh USERNAME /path/to/image/jpg

GIST

#!/bin/bash

set -e

declare -x USERNAME="$1"
declare -x USERPIC="$2"

declare -r DSIMPORT_CMD="/usr/bin/dsimport"
declare -r ID_CMD="/usr/bin/id"

declare -r MAPPINGS='0x0A 0x5C 0x3A 0x2C'
declare -r ATTRS='dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName externalbinary:dsAttrTypeStandard:JPEGPhoto'

if [ ! -f "${USERPIC}" ]; then
  echo "User image required"
fi

# Check that the username exists - exit on error
${ID_CMD} "${USERNAME}" &>/dev/null || ( echo "User does not exist" && exit 1 )

declare -r PICIMPORT="$(mktemp /tmp/${USERNAME}_dsimport.XXXXXX)" || exit 1
printf "%s %s \n%s:%s" "${MAPPINGS}" "${ATTRS}" "${USERNAME}" "${USERPIC}" >"${PICIMPORT}"
${DSIMPORT_CMD} "${PICIMPORT}" /Local/Default M &&
    echo "Successfully imported ${USERPIC} for ${USERNAME}."

rm "${PICIMPORT}"

4voto

bernedef Points 723

Après quelques jours de réflexion, j'ai pensé partager ce que j'ai découvert à ce sujet...

Les données des utilisateurs sont stockées dans l'"Open Directory", comme la version d'Apple d'OpenLDAP ou d'ActiveDirectory. Ancienne documentation ici . Deux données utilisateur contiennent des images :

  • Les données d'image originales (qui remontent aux premières versions d'OSX) sont appelées Picture et contient un chemin d'accès à une image sur le système de fichiers. Il n'est pas nécessaire qu'il s'agisse d'une image JPEG, mais le chemin d'accès est limité à 255 caractères UTF-8.
  • En JPEGPhoto est une image au format JPEG qui est intégrée dans l'enregistrement de l'utilisateur (contrairement à l'image qui pointe vers un fichier sur le système de fichiers). Elle semble avoir été introduite vers OSX 10.5/6.
  • Si un utilisateur a à la fois JPEGPhoto y Picture puis le Picture est ignorée (au moins par les écrans de connexion et de préférences de l'utilisateur).
  • En JPEGPhoto est stockée sous forme de données d'image JPEG codées en base64.

Vous pouvez utiliser dscl (ligne de commande du service d'annuaire) pour interroger l'annuaire et extraire les données de l'image. Dans ce cas, les données de l'image sont présentées sous forme de données hexadécimales (c'est-à-dire que la base64 est décodée en hexadécimal) :

dscl . read /Users/alice JPEGPhoto

Vous pouvez décoder les données hexagonales dans un fichier image :

dscl . read /Users/alice JPEGPhoto | tail -1 | xxd -r -p > photo.jpg

(un moyen rapide de visualiser une image à partir de la ligne de commande de MacOS est le suivant qlmanage -p photo.jpg )

La suppression d'images se fait également à l'aide de dscl :

dscl . delete /Users/alice JPEGPhoto
dscl . delete /Users/alice Picture

Vous pouvez également utiliser dscl pour charger les données :

dscl . read /Users/alice Picture /path/to/alice.jpg

C'est pratique pour le Picture mais JPEGPhoto a peu de chances de tenir sur la ligne de commande en tant qu'argument. À la place, vous pouvez utiliser dsimport pour importer JPEGPhoto. Pour ce faire, vous devez créer un fichier d'importation comme indiqué ci-dessous. ici ce qui se traduit par le schéma suivant, que l'on retrouve dans d'autres réponses, articles et billets de blog :

0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName externalbinary:dsAttrTypeStandard:JPEGPhoto
alice:/path/to/alice.jpg

Ceci importe l'image au chemin donné dans le JPEGPhoto de l'enregistrement de l'utilisateur, en la stockant en interne sous forme de données binaires encodées en base64. Une autre façon de procéder consiste à transmettre directement les données codées de l'image :

0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName base64:dsAttrTypeStandard:JPEGPhoto
alice:<base64 data>

En résumé, les importer un format de fichier les quatre caractères hexadécimaux du début spécifient le format des données :

  • 0x0A La fin de l'enregistrement est indiquée par une nouvelle ligne
  • 0x5C Le caractère d'échappement est défini comme suit : \N- Le caractère d'échappement est défini comme suit
  • 0x3A Le séparateur de champ est un :
  • 0x2C Le séparateur de valeur est un , (virgule)

Ces valeurs, qui sont les seules jamais vues dans les exemples, définissent le format des données de telle sorte que chaque enregistrement est une ligne à part entière, terminée par une nouvelle ligne. L'enregistrement est composé de champs séparés par des deux points et les champs à valeurs multiples séparent les valeurs à l'aide de virgules. S'il est nécessaire d'échapper à l'un ou l'autre de ces caractères, le caractère d'échappement est \ .

Ces quatre valeurs hexagonales sont suivies du type d'enregistrement (ici, nous avons dsRecTypeStandard:Users pour les enregistrements d'utilisateurs), le nombre de champs (2) et leur nature ( dsAttrTypeStandard:RecordName - qui est le nom d'utilisateur - et dsAttrTypeStandard:JPEGPhoto ). Les externalbinary Le préfixe indique dsimport comment interpréter le champ, dans ce cas comme le chemin d'accès à un fichier image (il en existe un certain nombre, notamment base64 , utf8 y externalutf8 mais la documentation à ce sujet semble manquer).

Rappelons que le JPEGPhoto est stocké sous forme de données encodées en base64 - dsimport effectue toute conversion nécessaire (dans le cas de base64 tel qu'il est utilisé ci-dessus, il n'y a pas de conversion).

Vous importez le fichier d'importation préparé comme suit :

dsimport dsimport_file /Local/Default M

Encore une fois, une petite explication : /Local/Default est le chemin d'accès à l'Open Directory et M demande que les données d'importation soient fusionnées lorsqu'elles existent. Voir le page de manuel pour dsimport . Vous pouvez ajouter --loglevel nn est comprise entre 0 et 3 ( Documentation de la ligne de commande , page 118) et de visualiser les fichiers journaux écrits sur le serveur ~/Library/Logs/ImportExport .

Si l'on remplace une image, il est nécessaire de supprimer d'abord toute image existante (utiliser dscl décrit ci-dessus), sinon l'image n'est pas mise à jour.

En résumé, deux exemples. D'abord, passer le chemin du fichier image dans le fichier d'importation :

#!/bin/sh
user="$1"
image="$2"
dscl . delete /Users/$user JPEGPhoto
dscl . delete /Users/$user Picture
tmp="$(mktemp)"
printf "0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName externalbinary:dsAttrTypeStandard:JPEGPhoto\n%s:%s" "$user" "$image" > "$tmp"
dsimport "$tmp" /Local/Default M
rm "$tmp"

Et, deuxièmement, l'encodage de l'image dans le fichier d'importation :

#!/bin/sh
user="$1"
image="$2"
dscl . delete /Users/$user JPEGPhoto
dscl . delete /Users/$user Picture
tmp="$(mktemp)"
printf "0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName base64:dsAttrTypeStandard:JPEGPhoto\n%s:%s" "$user" "$(base64 "$image")" > "$tmp"
dsimport "$tmp" /Local/Default M
rm "$tmp"

Utiliser comme ceci :

$ sudo add-photo username /path/to/photo.jpg

Note de bas de page

Je l'utilise dans un Ansible pour mettre à jour les avatars des utilisateurs sur plusieurs Apple Macs. Ansible est exécuté sur une machine Linux, c'est pourquoi la méthode de l'image embarquée m'intéressait car je n'avais pas besoin d'écrire l'image sur le disque de chaque Mac. Au cas où quelqu'un trouverait cela utile :

- name: User avatars
  become: true
  ansible.builtin.shell:
    cmd: |
      tmp="$(mktemp)"
      printf "0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 2 dsAttrTypeStandard:RecordName base64:dsAttrTypeStandard:JPEGPhoto\n%s:" "{{item.name}}" > "$tmp"
      cat >> "$tmp"
      dscl . delete /Users/{{ item.name }} JPEGPhoto
      dsimport "$tmp" /Local/Default M
      rc=$?
      rm "$tmp"
      exit $rc
    stdin: "{{lookup('file', item.avatar) | b64encode }}"
  loop:
    "{{ users | selectattr('avatar', 'defined') }}"

En users transmis est une liste ayant un name y avatar pour chacun d'entre eux.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X