fork-openpgpjs/src/packet/packetlist.js
Daniel Kahn Gillmor 4da28fcc29 move from http to https where possible.
There are dozens of links in the OpenPGP.js codebase that are http but
could be replaced with https links.  I've converted as many of them as
i could find.
2018-02-01 09:58:06 -05:00

232 lines
5.5 KiB
JavaScript

/**
* This class represents a list of openpgp packets.
* Take care when iterating over it - the packets themselves
* are stored as numerical indices.
* @requires util
* @requires enums
* @requires packet
* @requires packet/packet
* @module packet/packetlist
*/
'use strict';
import util from '../util';
import packetParser from './packet.js';
import * as packets from './all_packets.js';
import enums from '../enums.js';
import config from '../config';
/**
* @constructor
*/
export default function Packetlist() {
/** The number of packets contained within the list.
* @readonly
* @type {Integer} */
this.length = 0;
}
/**
* Reads a stream of binary data and interprents it as a list of packets.
* @param {Uint8Array} A Uint8Array of bytes.
*/
Packetlist.prototype.read = function (bytes) {
var i = 0;
while (i < bytes.length) {
var parsed = packetParser.read(bytes, i, bytes.length - i);
i = parsed.offset;
var pushed = false;
try {
var tag = enums.read(enums.packet, parsed.tag);
var packet = packets.newPacketFromTag(tag);
this.push(packet);
pushed = true;
packet.read(parsed.packet);
} catch(e) {
if (!config.tolerant || parsed.tag == enums.packet.symmetricallyEncrypted || parsed.tag == enums.packet.literal || parsed.tag == enums.packet.compressed) {
throw e;
}
if (pushed) {
this.pop(); // drop unsupported packet
}
}
}
};
/**
* Creates a binary representation of openpgp objects contained within the
* class instance.
* @returns {Uint8Array} A Uint8Array containing valid openpgp packets.
*/
Packetlist.prototype.write = function () {
var arr = [];
for (var i = 0; i < this.length; i++) {
var packetbytes = this[i].write();
arr.push(packetParser.writeHeader(this[i].tag, packetbytes.length));
arr.push(packetbytes);
}
return util.concatUint8Array(arr);
};
/**
* Adds a packet to the list. This is the only supported method of doing so;
* writing to packetlist[i] directly will result in an error.
*/
Packetlist.prototype.push = function (packet) {
if (!packet) {
return;
}
packet.packets = packet.packets || new Packetlist();
this[this.length] = packet;
this.length++;
};
/**
* Remove a packet from the list and return it.
* @return {Object} The packet that was removed
*/
Packetlist.prototype.pop = function() {
if (this.length === 0) {
return;
}
var packet = this[this.length - 1];
delete this[this.length - 1];
this.length--;
return packet;
};
/**
* Creates a new PacketList with all packets that pass the test implemented by the provided function.
*/
Packetlist.prototype.filter = function (callback) {
var filtered = new Packetlist();
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
filtered.push(this[i]);
}
}
return filtered;
};
/**
* Creates a new PacketList with all packets from the given types
*/
Packetlist.prototype.filterByTag = function () {
var args = Array.prototype.slice.call(arguments);
var filtered = new Packetlist();
var that = this;
function handle(packetType) {return that[i].tag === packetType;}
for (var i = 0; i < this.length; i++) {
if (args.some(handle)) {
filtered.push(this[i]);
}
}
return filtered;
};
/**
* Executes the provided callback once for each element
*/
Packetlist.prototype.forEach = function (callback) {
for (var i = 0; i < this.length; i++) {
callback(this[i]);
}
};
/**
* Traverses packet tree and returns first matching packet
* @param {module:enums.packet} type The packet type
* @return {module:packet/packet|null}
*/
Packetlist.prototype.findPacket = function (type) {
var packetlist = this.filterByTag(type);
if (packetlist.length) {
return packetlist[0];
} else {
var found = null;
for (var i = 0; i < this.length; i++) {
if (this[i].packets.length) {
found = this[i].packets.findPacket(type);
if (found) {
return found;
}
}
}
}
return null;
};
/**
* Returns array of found indices by tag
*/
Packetlist.prototype.indexOfTag = function () {
var args = Array.prototype.slice.call(arguments);
var tagIndex = [];
var that = this;
function handle(packetType) {return that[i].tag === packetType;}
for (var i = 0; i < this.length; i++) {
if (args.some(handle)) {
tagIndex.push(i);
}
}
return tagIndex;
};
/**
* Returns slice of packetlist
*/
Packetlist.prototype.slice = function (begin, end) {
if (!end) {
end = this.length;
}
var part = new Packetlist();
for (var i = begin; i < end; i++) {
part.push(this[i]);
}
return part;
};
/**
* Concatenates packetlist or array of packets
*/
Packetlist.prototype.concat = function (packetlist) {
if (packetlist) {
for (var i = 0; i < packetlist.length; i++) {
this.push(packetlist[i]);
}
}
};
/**
* Allocate a new packetlist from structured packetlist clone
* See {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data}
* @param {Object} packetClone packetlist clone
* @returns {Object} new packetlist object with data from packetlist clone
*/
Packetlist.fromStructuredClone = function(packetlistClone) {
var packetlist = new Packetlist();
for (var i = 0; i < packetlistClone.length; i++) {
packetlist.push(packets.fromStructuredClone(packetlistClone[i]));
if (packetlist[i].packets.length !== 0) {
packetlist[i].packets = this.fromStructuredClone(packetlist[i].packets);
} else {
packetlist[i].packets = new Packetlist();
}
}
return packetlist;
};