private Boolean isValidVCardChange(String username, Element newvCard) {
        if (newvCard == null) {
            // Well if there's nothing to change, of course it's valid.
            Log.debug("LdapVCardProvider: No new vcard provided (no changes), accepting.");
            return true;
        }
        // Un-escape username.
        username = JID.unescapeNode(username);
        Map<String, String> map = getLdapAttributes(username);
        // Retrieve LDAP created vcard for comparison
        Element ldapvCard = new VCard(template).getVCard(map);
        if (ldapvCard == null) {
            // This person has no vcard at all, may not change it!
            Log.debug("LdapVCardProvider: User has no LDAP vcard, nothing they can change, rejecting.");
            return false;
        }
        // If the LDAP vcard has a non-empty PHOTO element set, then there is literally no way this will be accepted.
        Element ldapPhotoElem = ldapvCard.element("PHOTO");
        if (ldapPhotoElem != null) {
            Element ldapBinvalElem = ldapPhotoElem.element("BINVAL");
            if (ldapBinvalElem != null && !ldapBinvalElem.getTextTrim().matches("\\s*")) {
                // LDAP is providing a valid PHOTO element, byebye!
                Log.debug("LdapVCardProvider: LDAP has a PHOTO element set, no way to override, rejecting.");
                return false;
            }
        }
        // Retrieve database vcard, if it exists
        Element dbvCard = defaultProvider.loadVCard(username);
        if (dbvCard != null) {
            Element dbPhotoElem = dbvCard.element("PHOTO");
            if (dbPhotoElem == null) {
                // DB has no photo, lets accept what we got.
                Log.debug("LdapVCardProvider: Database has no PHOTO element, accepting update.");
                return true;
            }
            else {
                Element newPhotoElem = newvCard.element("PHOTO");
                if (newPhotoElem == null) {
                    Log.debug("LdapVCardProvider: Photo element was removed, accepting update.");
                    return true;
                }
                // Note: NodeComparator never seems to consider these equal, even if they are?
                if (!dbPhotoElem.asXML().equals(newPhotoElem.asXML())) {
                    // Photo element was changed.  Ignore all other changes and accept this.
                    Log.debug("LdapVCardProvider: PHOTO element changed, accepting update.");
                    return true;
                }
            }
        }
        else {
            // No vcard exists in database
            Log.debug("LdapVCardProvider: Database has no vCard stored, accepting update.");
            return true;
        }
        // Ok, either something bad changed or nothing changed.  Either way, user either:
        // 1. should not have tried to change something 'readonly'
        // 2. shouldn't have bothered submitting no changes
        // So we'll consider this a bad return.
        Log.debug("LdapVCardProvider: PHOTO element didn't change, no reason to accept this, rejecting.");
        return false;
    }
Returns true or false if the change to the existing vcard is valid (only to PHOTO element)

@param username User who's LDAP-based vcard we will compare with.
@param newvCard New vCard Element we will compare against.
@return True or false if the changes made were valid (only to PHOTO element)
xmppserver/src/main/java/org/jivesoftware/openfire/ldap/LdapVCardProvider.java