View Javadoc
1   /*
2    * Copyright 2024–2026 Michael Osipov
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.michaelo.tomcat.pac;
17  
18  import java.math.BigInteger;
19  import java.nio.Buffer;
20  import java.nio.ByteBuffer;
21  import java.nio.ByteOrder;
22  
23  /**
24   * A thin wrapper around {@link ByteBuffer} to comply with the encoding rules defined by the <a href=
25   * "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/6655b92f-ab06-490b-845d-037e6987275f">{@code PACTYPE}</a>
26   * structure from MS-PAC.
27   */
28  public class PacDataBuffer {
29  
30  	private static final BigInteger TWO_COMPL_REF = BigInteger.ONE.shiftLeft(64);
31  
32  	private final ByteBuffer buf;
33  
34  	/**
35  	 * Constructs a PAC data buffer from a byte array.
36  	 *
37  	 * @param pacDataBytes PAC data encoded as bytes
38  	 */
39  	public PacDataBuffer(byte[] pacDataBytes) {
40  		buf = ByteBuffer.wrap(pacDataBytes);
41  		buf.order(ByteOrder.LITTLE_ENDIAN);
42  	}
43  
44  	public int position() {
45  		return ((Buffer) buf).position();
46  	}
47  
48  	public PacDataBuffer position(int newPosition) {
49  		((Buffer) buf).position(newPosition);
50  		return this;
51  	}
52  
53  	public PacDataBuffer skip(int bytes) {
54  		((Buffer) buf).position(buf.position() + bytes);
55  		return this;
56  	}
57  
58  	protected PacDataBuffer align(int bytes) {
59  		int shift = ((Buffer) buf).position() & bytes - 1;
60  		if (bytes != 0 && shift != 0) skip(bytes - shift);
61  		return this;
62  	}
63  
64  	public PacDataBuffer get(byte[] dst) {
65  		buf.get(dst);
66  		return this;
67  	}
68  
69  	public int getInt() {
70  		align(4);
71  		return buf.getInt();
72  	}
73  
74  	public int getUnsignedShort() {
75  		align(2);
76  		return buf.getShort() & 0xffff;
77  	}
78  
79  	public long getUnsignedInt() {
80  		align(4);
81  		return buf.getInt() & 0xffffffffL;
82  	}
83  
84  	public BigInteger getUnsignedLong() {
85  		align(8);
86  		long temp = buf.getLong();
87  		BigInteger value = BigInteger.valueOf(temp);
88  		if (value.compareTo(BigInteger.ZERO) < 0) value = value.add(TWO_COMPL_REF);
89  		return value;
90  	}
91  }