001/**
002 *
003 * Copyright 2017 Paul Schaub
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.omemo.provider;
018
019import static org.jivesoftware.smackx.omemo.element.OmemoElement.ATTR_PAYLOAD;
020import static org.jivesoftware.smackx.omemo.element.OmemoElement.NAME_ENCRYPTED;
021
022import java.io.IOException;
023import java.util.ArrayList;
024
025import org.jivesoftware.smack.packet.XmlEnvironment;
026import org.jivesoftware.smack.provider.ExtensionElementProvider;
027import org.jivesoftware.smack.util.stringencoder.Base64;
028import org.jivesoftware.smack.xml.XmlPullParser;
029import org.jivesoftware.smack.xml.XmlPullParserException;
030
031import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
032import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement;
033import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement_VAxolotl;
034import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
035
036/**
037 * Smack ExtensionProvider that parses incoming OMEMO Message element into OmemoMessageElement objects.
038 *
039 * @author Paul Schaub
040 */
041public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoElement_VAxolotl> {
042
043    @Override
044    public OmemoElement_VAxolotl parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException {
045        boolean inEncrypted = true;
046        int sid = -1;
047        ArrayList<OmemoKeyElement> keys = new ArrayList<>();
048        byte[] iv = null;
049        byte[] payload = null;
050
051        while (inEncrypted) {
052            XmlPullParser.Event tag = parser.next();
053            String name = parser.getName();
054            switch (tag) {
055                case START_ELEMENT:
056                    switch (name) {
057                        case OmemoHeaderElement.ELEMENT:
058                            for (int i = 0; i < parser.getAttributeCount(); i++) {
059                                if (parser.getAttributeName(i).equals(OmemoHeaderElement.ATTR_SID)) {
060                                    sid = Integer.parseInt(parser.getAttributeValue(i));
061                                }
062                            }
063                            break;
064                        case OmemoKeyElement.ELEMENT:
065                            boolean prekey = false;
066                            int rid = -1;
067                            for (int i = 0; i < parser.getAttributeCount(); i++) {
068                                if (parser.getAttributeName(i).equals(OmemoKeyElement.ATTR_PREKEY)) {
069                                    prekey = Boolean.parseBoolean(parser.getAttributeValue(i));
070                                } else if (parser.getAttributeName(i).equals(OmemoKeyElement.ATTR_RID)) {
071                                    rid = Integer.parseInt(parser.getAttributeValue(i));
072                                }
073                            }
074                            keys.add(new OmemoKeyElement(Base64.decode(parser.nextText()), rid, prekey));
075                            break;
076                        case OmemoHeaderElement.ATTR_IV:
077                            iv = Base64.decode(parser.nextText());
078                            break;
079                        case ATTR_PAYLOAD:
080                            payload = Base64.decode(parser.nextText());
081                            break;
082                    }
083                    break;
084                case END_ELEMENT:
085                    if (name.equals(NAME_ENCRYPTED)) {
086                        inEncrypted = false;
087                    }
088                    break;
089                default:
090                    // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
091                    break;
092            }
093        }
094        OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(sid, keys, iv);
095        return new OmemoElement_VAxolotl(header, payload);
096    }
097}