    private ModelAndView renameGroup(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String oldName = request.getParameter("groupName");
        String newName = request.getParameter("newName");

        if (StringUtils.hasText(oldName) && StringUtils.hasText(newName)) {
            m_groupRepository.renameGroup(oldName, newName);
        }

        return listGroups(request, response);
    }


    private void testKeyFactory(ECPublicKey pub, ECPrivateKey priv)
        throws Exception
    {
        KeyFactory ecFact = KeyFactory.getInstance("ECDSA");

        ECPublicKeySpec  pubSpec = (ECPublicKeySpec)ecFact.getKeySpec(pub, ECPublicKeySpec.class);
        ECPrivateKeySpec  privSpec = (ECPrivateKeySpec)ecFact.getKeySpec(priv, ECPrivateKeySpec.class);

        if (!pubSpec.getW().equals(pub.getW()) || !pubSpec.getParams().getCurve().equals(pub.getParams().getCurve()))
        {
            fail("pubSpec not correct");
        }

        if (!privSpec.getS().equals(priv.getS()) || !privSpec.getParams().getCurve().equals(priv.getParams().getCurve()))
        {
            fail("privSpec not correct");
        }

        ECPublicKey  pubKey = (ECPublicKey)ecFact.translateKey(pub);
        ECPrivateKey  privKey = (ECPrivateKey)ecFact.translateKey(priv);

        if (!pubKey.getW().equals(pub.getW()) || !pubKey.getParams().getCurve().equals(pub.getParams().getCurve()))
        {
            fail("pubKey not correct");
        }

        if (!privKey.getS().equals(priv.getS()) || !privKey.getParams().getCurve().equals(priv.getParams().getCurve()))
        {
            fail("privKey not correct");
        }
    }


    private Template getClassloaderTemplate(ClassLoader classloader, String suffixPath, String templateName)
    {
        String templatePath = suffixPath + templateName;

        URL url = classloader.getResource(templatePath);

        return url != null ? new ClassloaderTemplate(new ClassloaderResource(url, templateName)) : null;
    }


    void requestResetPasswordNoEmail() throws Exception
    {
        when(this.userManager.exists(this.userReference)).thenReturn(true);
        String exceptionMessage = "User has no email address.";
        when(this.localizationManager.getTranslationPlain("xe.admin.passwordReset.error.noEmail"))
            .thenReturn(exceptionMessage);
        ResetPasswordException resetPasswordException = assertThrows(ResetPasswordException.class,
            () -> this.resetPasswordManager.requestResetPassword(this.userReference));
        assertEquals(exceptionMessage, resetPasswordException.getMessage());
    }


    private static boolean pathContainsDoubleDots(Bytes path) {
        final int length = path.length;
        byte b0 = 0;
        byte b1 = 0;
        byte b2 = '/';
        for (int i = 1; i < length; i++) {
            final byte b3 = path.data[i];
            if (b3 == '/' && b2 == '.' && b1 == '.' && b0 == '/') {
                return true;
            }
            b0 = b1;
            b1 = b2;
            b2 = b3;
        }

        return b0 == '/' && b1 == '.' && b2 == '.';
    }


    public void testWrapMemoryMapped() throws Exception {
        File file = File.createTempFile("netty-test", "tmp");
        FileChannel output = null;
        FileChannel input = null;
        ByteBuf b1 = null;
        ByteBuf b2 = null;

        try {
            output = new RandomAccessFile(file, "rw").getChannel();
            byte[] bytes = new byte[1024];
            PlatformDependent.threadLocalRandom().nextBytes(bytes);
            output.write(ByteBuffer.wrap(bytes));

            input = new RandomAccessFile(file, "r").getChannel();
            ByteBuffer m = input.map(FileChannel.MapMode.READ_ONLY, 0, input.size());

            b1 = buffer(m);

            ByteBuffer dup = m.duplicate();
            dup.position(2);
            dup.limit(4);

            b2 = buffer(dup);

            Assert.assertEquals(b2, b1.slice(2, 2));
        } finally {
            if (b1 != null) {
                b1.release();
            }
            if (b2 != null) {
                b2.release();
            }
            if (output != null) {
                output.close();
            }
            if (input != null) {
                input.close();
            }
            file.delete();
        }
    }


    public static Document toXml(final List<IBaseDataObject> list) {
        final Element root = new Element("payload-list");
        for (final IBaseDataObject d : list) {
            final Document doc = toXml(d);
            root.addContent(doc.detachRootElement());
            logger.debug("Adding xml content for " + d.shortName() + " to document");
        }
        final Document doc = new Document(root);
        return doc;
    }


	private Document parseXml(String xmlContent) {
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = builder.parse(new InputSource(new StringReader(xmlContent)));

			document.getDocumentElement().normalize();

			return document;
		} catch (Exception e) {
			throw new JadxRuntimeException("Can not parse xml content", e);
		}
	}


    public boolean equals(Object o)
    {
        if (this == o) {
            return true;
        }

        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        DefaultResetPasswordRequestResponse that = (DefaultResetPasswordRequestResponse) o;

        return new EqualsBuilder()
            .append(userReference, that.userReference)
            .append(userEmail, that.userEmail)
            .append(verificationCode, that.verificationCode)
            .isEquals();
    }


    public void initWithcustomAccessRestrictor() throws ServletException {
        prepareStandardInitialisation();
        servlet.destroy();
    }


    private static File newFile() throws IOException {
        File file = File.createTempFile("netty-", ".tmp");
        file.deleteOnExit();

        final FileOutputStream out = new FileOutputStream(file);
        out.write(data);
        out.close();
        return file;
    }


    public void clientIdChanged(ClientModel client, String newClientId) {
        logger.debugf("Updating clientId from '%s' to '%s'", client.getClientId(), newClientId);

        UserModel serviceAccountUser = realmManager.getSession().users().getServiceAccount(client);
        if (serviceAccountUser != null) {
            String username = ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + newClientId;
            serviceAccountUser.setUsername(username);
            serviceAccountUser.setEmail(username + "@placeholder.org");
        }
    }


	public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset,
			byte[] ciphertext, int ciphertextOffset, int length)
			throws ShortBufferException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (keySpec == null) {
			// The key is not set yet - return the plaintext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
			return length;
		}
		if (space < 16 || length > (space - 16))
			throw new ShortBufferException();
		try {
			setup(ad);
			int result = cipher.update(plaintext, plaintextOffset, length, ciphertext, ciphertextOffset);
			cipher.doFinal(ciphertext, ciphertextOffset + result);
		} catch (InvalidKeyException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (InvalidAlgorithmParameterException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (IllegalBlockSizeException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (BadPaddingException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		ghash.update(ciphertext, ciphertextOffset, length);
		ghash.pad(ad != null ? ad.length : 0, length);
		ghash.finish(ciphertext, ciphertextOffset + length, 16);
		for (int index = 0; index < 16; ++index)
			ciphertext[ciphertextOffset + length + index] ^= hashKey[index];
		return length + 16;
	}


    public static byte[] serializeToBytes(final Object payload) throws IOException {
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        serializeToStream(bos, payload);
        return bos.toByteArray();
    }


	public boolean importWiki(File file, String filename, File targetDirectory) {
		try {
			Path path = FileResource.getResource(file, filename);
			if(path == null) {
				return false;
			}

			Path destDir = targetDirectory.toPath();
			Files.walkFileTree(path, new ImportVisitor(destDir));
			PathUtils.closeSubsequentFS(path);
			return true;
		} catch (IOException e) {
			log.error("", e);
			return false;
		}
	}


    public XMLReader getXMLReader() throws SAXException {
        if (xmlReader == null) {
            xmlReader = createXMLReader();
        }

        return xmlReader;
    }


    protected BigDecimal bcdToBigDecimal() {
        if (usingBytes) {
            // Converting to a string here is faster than doing BigInteger/BigDecimal arithmetic.
            BigDecimal result = new BigDecimal(toNumberString());
            if (isNegative()) {
                result = result.negate();
            }
            return result;
        } else {
            long tempLong = 0L;
            for (int shift = (precision - 1); shift >= 0; shift--) {
                tempLong = tempLong * 10 + getDigitPos(shift);
            }
            BigDecimal result = BigDecimal.valueOf(tempLong);
            result = result.scaleByPowerOfTen(scale);
            if (isNegative())
                result = result.negate();
            return result;
        }
    }


	public PersistentTask updateTask(Task task, Serializable runnableTask, Identity modifier, Date scheduledDate) {
		PersistentTask ptask = dbInstance.getCurrentEntityManager()
				.find(PersistentTask.class, task.getKey(), LockModeType.PESSIMISTIC_WRITE);
		if(ptask != null) {
			ptask.setLastModified(new Date());
			ptask.setScheduledDate(scheduledDate);
			ptask.setStatus(TaskStatus.newTask);
			ptask.setStatusBeforeEditStr(null);
			ptask.setTask(xstream.toXML(runnableTask));

			ptask = dbInstance.getCurrentEntityManager().merge(ptask);
			if(modifier != null) {
				//add to the list of modifier
				PersistentTaskModifier mod = new PersistentTaskModifier();
				mod.setCreationDate(new Date());
				mod.setModifier(modifier);
				mod.setTask(ptask);
				dbInstance.getCurrentEntityManager().persist(mod);
			}
			dbInstance.commit();
		}
		return ptask;
	}


    public SAXReader(DocumentFactory factory, boolean validating) {
        this.factory = factory;
        this.validating = validating;
    }


	private final HColor getBackColor(UmlDiagramType umlDiagramType, Style style) {
		if (EntityUtils.groupRoot(group))
			return null;

		final HColor result = group.getColors().getColor(ColorType.BACK);
		if (result != null)
			return result;

		final Stereotype stereo = group.getStereotype();

		if (UseStyle.useBetaStyle())
			return style.value(PName.BackGroundColor).asColor(skinParam.getThemeStyle(), skinParam.getIHtmlColorSet());

		final USymbol sym = group.getUSymbol() == null ? USymbols.PACKAGE : group.getUSymbol();
		final ColorParam backparam = umlDiagramType == UmlDiagramType.ACTIVITY ? ColorParam.partitionBackground
				: sym.getColorParamBack();
		final HColor c1 = skinParam.getHtmlColor(backparam, stereo, false);
		if (c1 != null)
			return c1;

		if (parentCluster == null)
			return null;

		return parentCluster.getBackColor(umlDiagramType, style);
	}


	public XssHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
	}


    public static String decodePath(String path) {
        if (path.indexOf('%') < 0) {
            // No need to decoded; not percent-encoded
            return path;
        }

        // Decode percent-encoded characters.
        // An invalid character is replaced with 0xFF, which will be replaced into '�' by UTF-8 decoder.
        final int len = path.length();
        try (TemporaryThreadLocals tempThreadLocals = TemporaryThreadLocals.acquire()) {
            final byte[] buf = tempThreadLocals.byteArray(len);
            int dstLen = 0;
            for (int i = 0; i < len; i++) {
                final char ch = path.charAt(i);
                if (ch != '%') {
                    buf[dstLen++] = (byte) ((ch & 0xFF80) == 0 ? ch : 0xFF);
                    continue;
                }

                // Decode a percent-encoded character.
                final int hexEnd = i + 3;
                if (hexEnd > len) {
                    // '%' or '%x' (must be followed by two hexadigits)
                    buf[dstLen++] = (byte) 0xFF;
                    break;
                }

                final int digit1 = decodeHexNibble(path.charAt(++i));
                final int digit2 = decodeHexNibble(path.charAt(++i));
                if (digit1 < 0 || digit2 < 0) {
                    // The first or second digit is not hexadecimal.
                    buf[dstLen++] = (byte) 0xFF;
                } else {
                    buf[dstLen++] = (byte) ((digit1 << 4) | digit2);
                }
            }

            return new String(buf, 0, dstLen, StandardCharsets.UTF_8);
        }
    }


	public void saveCustomConfigAndCompileCSS(Map<String, Map<String, Object>> customConfig, CourseEnvironment courseEnvironment){
		VFSContainer themeBase = null;
		VFSContainer base = null;
		base = (VFSContainer) courseEnvironment.getCourseBaseContainer().resolve(CourseLayoutHelper.LAYOUT_COURSE_SUBFOLDER);
		if (base == null) {
			base = courseEnvironment.getCourseBaseContainer().createChildContainer(CourseLayoutHelper.LAYOUT_COURSE_SUBFOLDER);
		}
		themeBase = (VFSContainer) base.resolve("/" + CourseLayoutHelper.CONFIG_KEY_CUSTOM);
		if (themeBase == null) {
			themeBase = base.createChildContainer(CourseLayoutHelper.CONFIG_KEY_CUSTOM);
		}
		VFSLeaf configTarget = (VFSLeaf) themeBase.resolve(CUSTOM_CONFIG_XML);
		if (configTarget == null) {
			configTarget = themeBase.createChildLeaf(CUSTOM_CONFIG_XML);
		}

		XStream xStream = XStreamHelper.createXStreamInstance();
		xStream.toXML(customConfig, configTarget.getOutputStream(false));

		// compile the css-files
		StringBuilder sbMain = new StringBuilder();
		StringBuilder sbIFrame = new StringBuilder();
		for (Entry<String, Map<String, Object>> iterator : customConfig.entrySet()) {
			String type = iterator.getKey();
			Map<String, Object> elementConfig = iterator.getValue();
		  AbstractLayoutElement configuredLayEl = createLayoutElementByType(type, elementConfig);
			sbIFrame.append(configuredLayEl.getCSSForIFrame());
			sbMain.append(configuredLayEl.getCSSForMain());
		}

		// attach line for logo, if there is any to cssForMain:
		appendLogoPart(sbMain, themeBase);

		VFSLeaf mainFile = (VFSLeaf) themeBase.resolve(MAIN_CSS);
		if (mainFile == null) mainFile = themeBase.createChildLeaf(MAIN_CSS);
		VFSLeaf iFrameFile = (VFSLeaf) themeBase.resolve(IFRAME_CSS);
		if (iFrameFile == null) iFrameFile = themeBase.createChildLeaf(IFRAME_CSS);
		FileUtils.save(mainFile.getOutputStream(false), sbMain.toString(), "utf-8");
		FileUtils.save(iFrameFile.getOutputStream(false), sbIFrame.toString(), "utf-8");
	}


  setStringInputSource(ThreadContext context, IRubyObject data, IRubyObject url)
  {
    source = new InputSource();
    ParserContext.setUrl(context, source, url);

    Ruby ruby = context.getRuntime();

    if (!(data instanceof RubyString)) {
      throw ruby.newArgumentError("must be kind_of String");
    }

    RubyString stringData = (RubyString) data;

    if (stringData.encoding(context) != null) {
      RubyString stringEncoding = stringData.encoding(context).asString();
      String encName = NokogiriHelpers.getValidEncodingOrNull(stringEncoding);
      if (encName != null) {
        java_encoding = encName;
      }
    }

    ByteList bytes = stringData.getByteList();

    stringDataSize = bytes.length() - bytes.begin();
    ByteArrayInputStream stream = new ByteArrayInputStream(bytes.unsafeBytes(), bytes.begin(), bytes.length());
    source.setByteStream(stream);
    source.setEncoding(java_encoding);
  }


  public TMap readMapBegin() throws TException {
    int size = readVarint32();
    byte keyAndValueType = size == 0 ? 0 : readByte();
    return new TMap(
        getTType((byte) (keyAndValueType >> 4)), getTType((byte) (keyAndValueType & 0xf)), size);
  }


	public Response attachTaskFile(@PathParam("courseId") Long courseId, @PathParam("nodeId") String nodeId,
			@Context HttpServletRequest request) {
			ICourse course = CoursesWebService.loadCourse(courseId);
		CourseEditorTreeNode parentNode = getParentNode(course, nodeId);
		if(course == null) {
			return Response.serverError().status(Status.NOT_FOUND).build();
		}
		if(parentNode == null) {
			return Response.serverError().status(Status.NOT_FOUND).build();
		} else if(!(parentNode.getCourseNode() instanceof TACourseNode)) {
			return Response.serverError().status(Status.NOT_ACCEPTABLE).build();
		}
		if (!isAuthorEditor(course, request)) {
			return Response.serverError().status(Status.UNAUTHORIZED).build();
		}

		InputStream in = null;
		MultipartReader reader = null;
		try {
			reader = new MultipartReader(request);
			String filename = reader.getValue("filename", "task");
			String taskFolderPath = TACourseNode.getTaskFolderPathRelToFolderRoot(course, parentNode.getCourseNode());
			VFSContainer taskFolder = VFSManager.olatRootContainer(taskFolderPath, null);
			VFSLeaf singleFile = (VFSLeaf) taskFolder.resolve("/" + filename);
			if (singleFile == null) {
				singleFile = taskFolder.createChildLeaf("/" + filename);
			}
			File file = reader.getFile();
			if(file != null) {
				in = new FileInputStream(file);
				OutputStream out = singleFile.getOutputStream(false);
				IOUtils.copy(in, out);
				IOUtils.closeQuietly(out);
			} else {
				return Response.status(Status.NOT_ACCEPTABLE).build();
			}
		} catch (Exception e) {
			log.error("", e);
			return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
		} finally {
			MultipartReader.closeQuietly(reader);
			IOUtils.closeQuietly(in);
		}

		return Response.ok().build();
	}


    void plus() {
        final PathAndQuery res = PathAndQuery.parse("/+?a+b=c+d");
        assertThat(res).isNotNull();
        assertThat(res.path()).isEqualTo("/+");
        assertThat(res.query()).isEqualTo("a+b=c+d");

        final PathAndQuery res2 = PathAndQuery.parse("/%2b?a%2bb=c%2bd");
        assertThat(res2).isNotNull();
        assertThat(res2.path()).isEqualTo("/+");
        assertThat(res2.query()).isEqualTo("a%2Bb=c%2Bd");
    }


  public TSet readSetBegin() throws TException {
    return new TSet(readByte(), readI32());
  }


    private Template getClassloaderTemplate(String suffixPath, String templateName)
    {
        return getClassloaderTemplate(Thread.currentThread().getContextClassLoader(), suffixPath, templateName);
    }


	final protected CommandExecutionResult executeArg(TimingDiagram diagram, LineLocation location, RegexResult arg) {
		final String compact = arg.get("COMPACT", 0);
		final String code = arg.get("CODE", 0);
		final String full = arg.get("FULL", 0);
		return diagram.createBinary(code, full, compact != null);
	}


		public void configure(ICourse course, CourseNode newNode, ModuleConfiguration moduleConfig) {

			if(displayType != null && (STCourseNodeEditController.CONFIG_VALUE_DISPLAY_TOC.equals(displayType)
					|| STCourseNodeEditController.CONFIG_VALUE_DISPLAY_PEEKVIEW.equals(displayType)
					|| STCourseNodeEditController.CONFIG_VALUE_DISPLAY_FILE.equals(displayType))) {
				moduleConfig.setStringValue(STCourseNodeEditController.CONFIG_KEY_DISPLAY_TYPE, displayType);
			}

			if(STCourseNodeEditController.CONFIG_VALUE_DISPLAY_FILE.equals(moduleConfig.getStringValue(STCourseNodeEditController.CONFIG_KEY_DISPLAY_TYPE))) {
				if(in != null && StringHelper.containsNonWhitespace(filename)) {
					VFSContainer rootContainer = course.getCourseFolderContainer();
					VFSLeaf singleFile = (VFSLeaf) rootContainer.resolve("/" + filename);
					if (singleFile == null) {
						singleFile = rootContainer.createChildLeaf("/" + filename);
					}

					moduleConfig.set(STCourseNodeEditController.CONFIG_KEY_FILE, "/" + filename);
					OutputStream out = singleFile.getOutputStream(false);
					FileUtils.copy(in, out);
					FileUtils.closeSafely(out);
					FileUtils.closeSafely(in);
				} else if (StringHelper.containsNonWhitespace(filename)) {
					VFSContainer rootContainer = course.getCourseFolderContainer();
					VFSLeaf singleFile = (VFSLeaf) rootContainer.resolve("/" + filename);
					if(singleFile != null) {
						moduleConfig.set(STCourseNodeEditController.CONFIG_KEY_FILE, "/" + filename);
					}
				}
			}
		}


  public static final void testClosedArray() {
    // Discovered by fuzzer with seed -Dfuzz.seed=df3b4778ce54d00a
    assertSanitized("-1742461140214282", "\ufeff-01742461140214282]");
  }


    void semicolon() {
        final PathAndQuery res = PathAndQuery.parse("/;?a=b;c=d");
        assertThat(res).isNotNull();
        assertThat(res.path()).isEqualTo("/;");
        assertThat(res.query()).isEqualTo("a=b;c=d");

        // '%3B' in a query string should never be decoded into ';'.
        final PathAndQuery res2 = PathAndQuery.parse("/%3b?a=b%3Bc=d");
        assertThat(res2).isNotNull();
        assertThat(res2.path()).isEqualTo("/;");
        assertThat(res2.query()).isEqualTo("a=b%3Bc=d");
    }


	public RefUpdated uploadFiles(Collection<FileUpload> uploads, String directory, String commitMessage) {
		Map<String, BlobContent> newBlobs = new HashMap<>();

		String parentPath = getDirectory();

		if (directory != null) {
			if (parentPath != null)
				parentPath += "/" + directory;
			else
				parentPath = directory;
		}

		User user = Preconditions.checkNotNull(SecurityUtils.getUser());
		BlobIdent blobIdent = getBlobIdent();

		for (FileUpload upload: uploads) {
			String blobPath = upload.getClientFileName();
			if (parentPath != null)
				blobPath = parentPath + "/" + blobPath;

			if (getProject().isReviewRequiredForModification(user, blobIdent.revision, blobPath))
				throw new BlobEditException("Review required for this change. Please submit pull request instead");
			else if (getProject().isBuildRequiredForModification(user, blobIdent.revision, blobPath))
				throw new BlobEditException("Build required for this change. Please submit pull request instead");

			BlobContent blobContent = new BlobContent.Immutable(upload.getBytes(), FileMode.REGULAR_FILE);
			newBlobs.put(blobPath, blobContent);
		}

		BlobEdits blobEdits = new BlobEdits(Sets.newHashSet(), newBlobs);
		String refName = blobIdent.revision!=null?GitUtils.branch2ref(blobIdent.revision):"refs/heads/master";

		ObjectId prevCommitId;
		if (blobIdent.revision != null)
			prevCommitId = getProject().getRevCommit(blobIdent.revision, true).copy();
		else
			prevCommitId = ObjectId.zeroId();

		while (true) {
			try {
				ObjectId newCommitId = blobEdits.commit(getProject().getRepository(), refName, prevCommitId,
						prevCommitId, user.asPerson(), commitMessage);
				return new RefUpdated(getProject(), refName, prevCommitId, newCommitId);
			} catch (ObjectAlreadyExistsException|NotTreeException e) {
				throw new BlobEditException(e.getMessage());
			} catch (ObsoleteCommitException e) {
				prevCommitId = e.getOldCommitId();
			}
		}
	}


    public boolean isStringInternEnabled() {
        return stringInternEnabled;
    }


    protected void onStart() {
        super.onStart();
        Intent intent = getIntent();
        intent.putExtra(
                SettingsActivity.SP_FEED_LIST_LAYOUT,
                mPrefs.getString(SettingsActivity.SP_FEED_LIST_LAYOUT, "0")
        );
        setResult(RESULT_OK,intent);
    }


    public void testReadBytesAndWriteBytesWithFileChannel() throws IOException {
        File file = File.createTempFile("file-channel", ".tmp");
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(file, "rw");
            FileChannel channel = randomAccessFile.getChannel();
            // channelPosition should never be changed
            long channelPosition = channel.position();

            byte[] bytes = {'a', 'b', 'c', 'd'};
            int len = bytes.length;
            ByteBuf buffer = newBuffer(len);
            buffer.resetReaderIndex();
            buffer.resetWriterIndex();
            buffer.writeBytes(bytes);

            int oldReaderIndex = buffer.readerIndex();
            assertEquals(len, buffer.readBytes(channel, 10, len));
            assertEquals(oldReaderIndex + len, buffer.readerIndex());
            assertEquals(channelPosition, channel.position());

            ByteBuf buffer2 = newBuffer(len);
            buffer2.resetReaderIndex();
            buffer2.resetWriterIndex();
            int oldWriterIndex = buffer2.writerIndex();
            assertEquals(len, buffer2.writeBytes(channel, 10, len));
            assertEquals(channelPosition, channel.position());
            assertEquals(oldWriterIndex + len, buffer2.writerIndex());
            assertEquals('a', buffer2.getByte(0));
            assertEquals('b', buffer2.getByte(1));
            assertEquals('c', buffer2.getByte(2));
            assertEquals('d', buffer2.getByte(3));
            buffer.release();
            buffer2.release();
        } finally {
            if (randomAccessFile != null) {
                randomAccessFile.close();
            }
            file.delete();
        }
    }


	public void testMatchTwoTypes() {

		JWKMatcher matcher = new JWKMatcher.Builder().keyTypes(KeyType.RSA, KeyType.EC).build();

		assertTrue(matcher.matches(new RSAKey.Builder(new Base64URL("n"), new Base64URL("e")).keyID("1").build()));
		assertTrue(matcher.matches(new ECKey.Builder(ECKey.Curve.P_256, new Base64URL("x"), new Base64URL("y")).keyID("2").build()));

		assertEquals("kty=[RSA, EC]", matcher.toString());
	}


	public int decryptWithAd(byte[] ad, byte[] ciphertext,
			int ciphertextOffset, byte[] plaintext, int plaintextOffset,
			int length) throws ShortBufferException, BadPaddingException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (length > space)
			throw new ShortBufferException();
		if (plaintextOffset > plaintext.length)
			space = 0;
		else
			space = plaintext.length - plaintextOffset;
		if (!haskey) {
			// The key is not set yet - return the ciphertext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length);
			return length;
		}
		if (length < 16)
			Noise.throwBadTagException();
		int dataLen = length - 16;
		if (dataLen > space)
			throw new ShortBufferException();
		setup(ad);
		ghash.update(ciphertext, ciphertextOffset, dataLen);
		ghash.pad(ad != null ? ad.length : 0, dataLen);
		ghash.finish(enciv, 0, 16);
		int temp = 0;
		for (int index = 0; index < 16; ++index)
			temp |= (hashKey[index] ^ enciv[index] ^ ciphertext[ciphertextOffset + dataLen + index]);
		if ((temp & 0xFF) != 0)
			Noise.throwBadTagException();
		encryptCTR(ciphertext, ciphertextOffset, plaintext, plaintextOffset, dataLen);
		return dataLen;
	}


	public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset,
			byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (!haskey) {
			// The key is not set yet - return the plaintext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
			return length;
		}
		if (space < 16 || length > (space - 16))
			throw new ShortBufferException();
		setup(ad);
		encrypt(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
		poly.update(ciphertext, ciphertextOffset, length);
		finish(ad, length);
		System.arraycopy(polyKey, 0, ciphertext, ciphertextOffset + length, 16);
		return length + 16;
	}


    public void testGetBytesAndSetBytesWithFileChannel() throws IOException {
        File file = File.createTempFile("file-channel", ".tmp");
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(file, "rw");
            FileChannel channel = randomAccessFile.getChannel();
            // channelPosition should never be changed
            long channelPosition = channel.position();

            byte[] bytes = {'a', 'b', 'c', 'd'};
            int len = bytes.length;
            ByteBuf buffer = newBuffer(len);
            buffer.resetReaderIndex();
            buffer.resetWriterIndex();
            buffer.writeBytes(bytes);

            int oldReaderIndex = buffer.readerIndex();
            assertEquals(len, buffer.getBytes(oldReaderIndex, channel, 10, len));
            assertEquals(oldReaderIndex, buffer.readerIndex());
            assertEquals(channelPosition, channel.position());

            ByteBuf buffer2 = newBuffer(len);
            buffer2.resetReaderIndex();
            buffer2.resetWriterIndex();
            int oldWriterIndex = buffer2.writerIndex();
            assertEquals(buffer2.setBytes(oldWriterIndex, channel, 10, len), len);
            assertEquals(channelPosition, channel.position());

            assertEquals(oldWriterIndex, buffer2.writerIndex());
            assertEquals('a', buffer2.getByte(oldWriterIndex));
            assertEquals('b', buffer2.getByte(oldWriterIndex + 1));
            assertEquals('c', buffer2.getByte(oldWriterIndex + 2));
            assertEquals('d', buffer2.getByte(oldWriterIndex + 3));

            buffer.release();
            buffer2.release();
        } finally {
            if (randomAccessFile != null) {
                randomAccessFile.close();
            }
            file.delete();
        }
    }


	private void saveToFile(VFSLeaf glossaryFile, List<GlossaryItem> glossaryItemArr) {
		// cdata-tags should be used instead of strings, overwrite writer.
		glossaryItemArr = removeEmptyGlossaryItems(glossaryItemArr);
		XStreamHelper.writeObject(xstreamWriter, glossaryFile, glossaryItemArr);
	}


  private XMLGregorianCalendar toXMLGregorianCalendar(ZonedDateTime instant) {
    if (instant == null) {
      return null;
    }

    return new XMLGregorianCalendarImpl(GregorianCalendar.from(instant));
  }


    public int addFileName(String file) {
        workUnitList.add(new WorkUnit(file));
        return size();
    }


	public OutputStream getOutputStream(boolean append) {
		return null;
	}


    public void testGetShellCommandLineBash()
        throws Exception
    {
        Commandline cmd = new Commandline( new BourneShell() );
        cmd.setExecutable( "/bin/echo" );
        cmd.addArguments( new String[] {
            "hello world"
        } );

        String[] shellCommandline = cmd.getShellCommandline();

        assertEquals( "Command line size", 3, shellCommandline.length );

        assertEquals( "/bin/sh", shellCommandline[0] );
        assertEquals( "-c", shellCommandline[1] );
        String expectedShellCmd = "/bin/echo \'hello world\'";
        if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
        {
            expectedShellCmd = "\\bin\\echo \'hello world\'";
        }
        assertEquals( expectedShellCmd, shellCommandline[2] );
    }


    public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
        if (javaVersion() >= 7) {
            if (directory == null) {
                return Files.createTempFile(prefix, suffix).toFile();
            }
            return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
        }
        if (directory == null) {
            return File.createTempFile(prefix, suffix);
        }
        File file = File.createTempFile(prefix, suffix, directory);
        // Try to adjust the perms, if this fails there is not much else we can do...
        file.setReadable(false, false);
        file.setReadable(true, true);
        return file;
    }


	public void testSelectByType() {

		JWKSelector selector = new JWKSelector(new JWKMatcher.Builder().keyType(KeyType.RSA).build());

		List<JWK> keyList = new ArrayList<>();
		keyList.add(new RSAKey.Builder(new Base64URL("n"), new Base64URL("e")).keyID("1").build());
		keyList.add(new ECKey.Builder(ECKey.Curve.P_256, new Base64URL("x"), new Base64URL("y")).keyID("2").build());

		JWKSet jwkSet = new JWKSet(keyList);

		List<JWK> matches = selector.select(jwkSet);

		RSAKey key1 = (RSAKey)matches.get(0);
		assertEquals(KeyType.RSA, key1.getKeyType());
		assertEquals("1", key1.getKeyID());

		assertEquals(1, matches.size());
	}


	protected SymbolContext getContextLegacy() {
		return new SymbolContext(HColorUtils.COL_D7E0F2, HColorUtils.COL_038048).withStroke(new UStroke(1.5));
	}


	protected StyleSignatureBasic getStyleSignature() {
		if (type == TimingStyle.CONCISE)
			return StyleSignatureBasic.of(SName.root, SName.element, SName.timingDiagram, SName.concise);
		if (type == TimingStyle.ROBUST)
			return StyleSignatureBasic.of(SName.root, SName.element, SName.timingDiagram, SName.robust);
		throw new IllegalStateException();
	}


  private ZonedDateTime toZonedDateTime(XMLGregorianCalendar instant) {
    if (instant == null) {
      return null;
    }

    return instant.toGregorianCalendar().toZonedDateTime();
  }


	private List<GlossaryItem> loadGlossaryItemListFromFile(VFSLeaf glossaryFile) {
		List<GlossaryItem> glossaryItemList = new ArrayList<>();
		if (glossaryFile == null) { return new ArrayList<>(); }

		Object glossObj = XStreamHelper.readObject(xstreamReader, glossaryFile);
		if (glossObj instanceof ArrayList) {
			ArrayList<GlossaryItem> glossItemsFromFile = (ArrayList<GlossaryItem>) glossObj;
			glossaryItemList.addAll(glossItemsFromFile);
		} else {
			log.error("The Glossary-XML-File " + glossaryFile.toString() + " seems not to be correct!");
		}

		Collections.sort(glossaryItemList);
		return glossaryItemList;
	}


    public boolean isIgnoreComments() {
        return ignoreComments;
    }


	public String getOrderBy() {
		return orderBy;
	}


    public void create_withNullThreadPool() throws Exception {
        final JettyServerFactory jettyServerFactory = mock(JettyServerFactory.class);
        final StaticFilesConfiguration staticFilesConfiguration = mock(StaticFilesConfiguration.class);
        final Routes routes = mock(Routes.class);

        when(jettyServerFactory.create(100,10,10000)).thenReturn(new Server());

        final EmbeddedJettyFactory embeddedJettyFactory = new EmbeddedJettyFactory(jettyServerFactory).withThreadPool(null);
        embeddedServer = embeddedJettyFactory.create(routes, staticFilesConfiguration, false);

        embeddedServer.ignite("localhost", 8080, null, 100,10,10000);

        verify(jettyServerFactory, times(1)).create(100,10,10000);
        verifyNoMoreInteractions(jettyServerFactory);
    }


	private static ECPrivateKey generateECPrivateKey(final ECKey.Curve curve)
		throws Exception {

		final ECParameterSpec ecParameterSpec = curve.toECParameterSpec();

		KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
		generator.initialize(ecParameterSpec);
		KeyPair keyPair = generator.generateKeyPair();

		return (ECPrivateKey) keyPair.getPrivate();
	}


    public static void unzipFilesToPath(String jarPath, String destinationDir) throws IOException {
        File file = new File(jarPath);
        try (JarFile jar = new JarFile(file)) {

            // fist get all directories,
            // then make those directory on the destination Path
            /*for (Enumeration<JarEntry> enums = jar.entries(); enums.hasMoreElements(); ) {
                JarEntry entry = (JarEntry) enums.nextElement();

                String fileName = destinationDir + File.separator + entry.getName();
                File f = new File(fileName);

                if (fileName.endsWith("/")) {
                    f.mkdirs();
                }

            }*/

            //now create all files
            for (Enumeration<JarEntry> enums = jar.entries(); enums.hasMoreElements(); ) {
                JarEntry entry = enums.nextElement();

                String fileName = destinationDir + File.separator + entry.getName();
                File f = new File(fileName);

                if (!f.getCanonicalPath().startsWith(destinationDir)) {
                    System.out.println("Zip Slip exploit detected. Skipping entry " + entry.getName());
                    continue;
                }

                File parent = f.getParentFile();
                if (!parent.exists()) {
                    parent.mkdirs();
                }

                if (!fileName.endsWith("/")) {
                    try (InputStream is = jar.getInputStream(entry);
                         FileOutputStream fos = new FileOutputStream(f)) {
                        // write contents of 'is' to 'fos'
                        while (is.available() > 0) {
                            fos.write(is.read());
                        }
                    }
                }
            }
        }
    }


    public SAXReader(XMLReader xmlReader) {
        this.xmlReader = xmlReader;
    }


    void relative() {
        assertThat(PathAndQuery.parse("foo")).isNull();
    }


    public <T extends JiffleRuntime> T getRuntimeInstance(Class<T> baseClass) throws
            it.geosolutions.jaiext.jiffle.JiffleException {
        RuntimeModel model = RuntimeModel.get(baseClass);
        if (model == null) {
            throw new it.geosolutions.jaiext.jiffle.JiffleException(baseClass.getName() +
                    " does not implement a required Jiffle runtime interface");
        }

        return (T) createRuntimeInstance(model, baseClass, false);
    }


	public void testSelectByTwoTypes() {

		JWKSelector selector = new JWKSelector(new JWKMatcher.Builder().keyTypes(KeyType.RSA, KeyType.EC).build());

		List<JWK> keyList = new ArrayList<>();
		keyList.add(new RSAKey.Builder(new Base64URL("n"), new Base64URL("e")).keyID("1").build());
		keyList.add(new ECKey.Builder(ECKey.Curve.P_256, new Base64URL("x"), new Base64URL("y")).keyID("2").build());

		JWKSet jwkSet = new JWKSet(keyList);

		List<JWK> matches = selector.select(jwkSet);

		RSAKey key1 = (RSAKey)matches.get(0);
		assertEquals(KeyType.RSA, key1.getKeyType());
		assertEquals("1", key1.getKeyID());

		ECKey key2 = (ECKey)matches.get(1);
		assertEquals(KeyType.EC, key2.getKeyType());
		assertEquals("2", key2.getKeyID());

		assertEquals(2, matches.size());
	}


    private void parseAttributesForKnownElements(Map<String, List<Entry>> subdirs, Node desc) {
        // NOTE: NamedNodeMap does not have any particular order...
        NamedNodeMap attributes = desc.getAttributes();

        for (Node attr : asIterable(attributes)) {
            if (!XMP.ELEMENTS.contains(attr.getNamespaceURI())) {
                continue;
            }

            List<Entry> dir = subdirs.get(attr.getNamespaceURI());

            if (dir == null) {
                dir = new ArrayList<Entry>();
                subdirs.put(attr.getNamespaceURI(), dir);
            }

            dir.add(new XMPEntry(attr.getNamespaceURI() + attr.getLocalName(), attr.getLocalName(), attr.getNodeValue()));
        }
    }


    public void create_withThreadPool() throws Exception {
        final QueuedThreadPool threadPool = new QueuedThreadPool(100);
        final JettyServerFactory jettyServerFactory = mock(JettyServerFactory.class);
        final StaticFilesConfiguration staticFilesConfiguration = mock(StaticFilesConfiguration.class);
        final Routes routes = mock(Routes.class);

        when(jettyServerFactory.create(threadPool)).thenReturn(new Server(threadPool));

        final EmbeddedJettyFactory embeddedJettyFactory = new EmbeddedJettyFactory(jettyServerFactory).withThreadPool(threadPool);
        embeddedServer = embeddedJettyFactory.create(routes, staticFilesConfiguration, false);

        embeddedServer.ignite("localhost", 8080, null, 0,0,0);

        verify(jettyServerFactory, times(1)).create(threadPool);
        verifyNoMoreInteractions(jettyServerFactory);
    }


	public int decryptWithAd(byte[] ad, byte[] ciphertext,
			int ciphertextOffset, byte[] plaintext, int plaintextOffset,
			int length) throws ShortBufferException, BadPaddingException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (length > space)
			throw new ShortBufferException();
		if (plaintextOffset > plaintext.length)
			space = 0;
		else
			space = plaintext.length - plaintextOffset;
		if (keySpec == null) {
			// The key is not set yet - return the ciphertext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length);
			return length;
		}
		if (length < 16)
			Noise.throwBadTagException();
		int dataLen = length - 16;
		if (dataLen > space)
			throw new ShortBufferException();
		try {
			setup(ad);
		} catch (InvalidKeyException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (InvalidAlgorithmParameterException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		ghash.update(ciphertext, ciphertextOffset, dataLen);
		ghash.pad(ad != null ? ad.length : 0, dataLen);
		ghash.finish(iv, 0, 16);
		int temp = 0;
		for (int index = 0; index < 16; ++index)
			temp |= (hashKey[index] ^ iv[index] ^ ciphertext[ciphertextOffset + dataLen + index]);
		if ((temp & 0xFF) != 0)
			Noise.throwBadTagException();
		try {
			int result = cipher.update(ciphertext, ciphertextOffset, dataLen, plaintext, plaintextOffset);
			cipher.doFinal(plaintext, plaintextOffset + result);
		} catch (IllegalBlockSizeException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (BadPaddingException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		return dataLen;
	}


	protected String getCorsDomain(String referer, String userAgent)
	{
		String dom = null;

		if (referer != null && referer.toLowerCase()
				.matches("https?://([a-z0-9,-]+[.])*draw[.]io/.*"))
		{
			dom = referer.toLowerCase().substring(0,
					referer.indexOf(".draw.io/") + 8);
		}
		else if (referer != null && referer.toLowerCase()
				.matches("https?://([a-z0-9,-]+[.])*diagrams[.]net/.*"))
		{
			dom = referer.toLowerCase().substring(0,
					referer.indexOf(".diagrams.net/") + 13);
		}
		else if (referer != null && referer.toLowerCase()
				.matches("https?://([a-z0-9,-]+[.])*quipelements[.]com/.*"))
		{
			dom = referer.toLowerCase().substring(0,
					referer.indexOf(".quipelements.com/") + 17);
		}
		// Enables Confluence/Jira proxy via referer or hardcoded user-agent (for old versions)
		// UA refers to old FF on macOS so low risk and fixes requests from existing servers
		else if ((referer != null
				&& referer.equals("draw.io Proxy Confluence Server"))
				|| (userAgent != null && userAgent.equals(
						"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0")))
		{
			dom = "";
		}

		return dom;
	}


    public void setXMLReader(XMLReader reader) {
        this.xmlReader = reader;
    }


    private Path getFilePath(String path) {
        return baseDirPath.map(dir -> dir.resolve(path)).orElseGet(() -> Paths.get(path));
    }


    void requestResetPassword() throws Exception
    {
        when(this.userManager.exists(this.userReference)).thenReturn(true);
        InternetAddress email = new InternetAddress("foobar@xwiki.org");
        when(this.userProperties.getEmail()).thenReturn(email);
        BaseObject xObject = mock(BaseObject.class);
        when(this.userDocument
            .getXObject(DefaultResetPasswordManager.RESET_PASSWORD_REQUEST_CLASS_REFERENCE, true, this.context))
            .thenReturn(xObject);
        String verificationCode = "abcde1234";
        when(this.xWiki.generateRandomString(30)).thenReturn(verificationCode);
        when(this.localizationManager.getTranslationPlain("xe.admin.passwordReset.versionComment"))
            .thenReturn("Save verification code 42");

        ResetPasswordRequestResponse expectedResult =
            new DefaultResetPasswordRequestResponse(this.userReference, email,
                verificationCode);
        assertEquals(expectedResult, this.resetPasswordManager.requestResetPassword(this.userReference));
        verify(xObject).set(DefaultResetPasswordManager.VERIFICATION_PROPERTY, verificationCode, context);
        verify(this.xWiki).saveDocument(this.userDocument, "Save verification code 42", true, this.context);
    }


    public void setXMLFilter(XMLFilter filter) {
        this.xmlFilter = filter;
    }


    void checkVerificationCodeUnexistingUser()
    {
        when(this.userReference.toString()).thenReturn("user:Foobar");
        when(this.userManager.exists(this.userReference)).thenReturn(false);
        String exceptionMessage = "User [user:Foobar] doesn't exist";
        when(this.localizationManager.getTranslationPlain("xe.admin.passwordReset.error.noUser",
            "user:Foobar")).thenReturn(exceptionMessage);
        ResetPasswordException resetPasswordException = assertThrows(ResetPasswordException.class,
            () -> this.resetPasswordManager.checkVerificationCode(this.userReference, "some code"));
        assertEquals(exceptionMessage, resetPasswordException.getMessage());
    }


    public String toString() {
        if (query == null) {
            return path;
        }
        return path + "?" + query;
    }


    static void setAttribute(TransformerFactory transformerFactory, String attributeName) {
        try {
            transformerFactory.setAttribute(attributeName, "");
        } catch (IllegalArgumentException iae) {
            if (Boolean.getBoolean(SYSTEM_PROPERTY_IGNORE_XXE_PROTECTION_FAILURES)) {
                LOGGER.warning("Enabling XXE protection failed. The attribute " + attributeName
                        + " is not supported by the TransformerFactory. The " + SYSTEM_PROPERTY_IGNORE_XXE_PROTECTION_FAILURES
                        + " system property is used so the XML processing continues in the UNSECURE mode"
                        + " with XXE protection disabled!!!");
            } else {
                LOGGER.severe("Enabling XXE protection failed. The attribute " + attributeName
                        + " is not supported by the TransformerFactory. This usually mean an outdated XML processor"
                        + " is present on the classpath (e.g. Xerces, Xalan). If you are not able to resolve the issue by"
                        + " fixing the classpath, the " + SYSTEM_PROPERTY_IGNORE_XXE_PROTECTION_FAILURES
                        + " system property can be used to disable XML External Entity protections."
                        + " We don't recommend disabling the XXE as such the XML processor configuration is unsecure!!!", iae);
                throw iae;
            }
        }
    }


    public void testPullCount() throws IOException {
        initializeSsl();
        String url = RepoUtils.getRemoteRepoURL() + "/modules/info/" + orgName + "/" + moduleName + "/*/";
        HttpURLConnection conn = createHttpUrlConnection(convertToUrl(url), "", 0, "", "");
        conn.setInstanceFollowRedirects(false);
        setRequestMethod(conn, Utils.RequestMethod.GET);

        int statusCode = conn.getResponseCode();
        if (statusCode == 200) {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),
                    Charset.defaultCharset()))) {
                StringBuilder result = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }
                Object payload = JSONParser.parse(result.toString());
                if (payload instanceof MapValue) {
                    long pullCount = ((MapValue) payload).getIntValue("totalPullCount");
                    Assert.assertEquals(pullCount, totalPullCount);
                } else {
                    Assert.fail("error: invalid response received");
                }
            }
        } else {
            Assert.fail("error: could not connect to remote repository to find the latest version of module");
        }
    }


    public byte[] toByteArray()
    {
		/* index || secretKeySeed || secretKeyPRF || publicSeed || root */
        int n = params.getDigestSize();
        int indexSize = (params.getHeight() + 7) / 8;
        int secretKeySize = n;
        int secretKeyPRFSize = n;
        int publicSeedSize = n;
        int rootSize = n;
        int totalSize = indexSize + secretKeySize + secretKeyPRFSize + publicSeedSize + rootSize;
        byte[] out = new byte[totalSize];
        int position = 0;
		/* copy index */
        byte[] indexBytes = XMSSUtil.toBytesBigEndian(index, indexSize);
        XMSSUtil.copyBytesAtOffset(out, indexBytes, position);
        position += indexSize;
		/* copy secretKeySeed */
        XMSSUtil.copyBytesAtOffset(out, secretKeySeed, position);
        position += secretKeySize;
		/* copy secretKeyPRF */
        XMSSUtil.copyBytesAtOffset(out, secretKeyPRF, position);
        position += secretKeyPRFSize;
		/* copy publicSeed */
        XMSSUtil.copyBytesAtOffset(out, publicSeed, position);
        position += publicSeedSize;
		/* copy root */
        XMSSUtil.copyBytesAtOffset(out, root, position);
		/* concatenate bdsState */
        byte[] bdsStateOut = null;
        try
        {
            bdsStateOut = XMSSUtil.serialize(bdsState);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            throw new RuntimeException("error serializing bds state");
        }
        return Arrays.concatenate(out, bdsStateOut);
    }


    public Response workspaceClientEnqueue(@FormParam(WorkSpaceAdapter.CLIENT_NAME) String clientName,
            @FormParam(WorkSpaceAdapter.WORK_BUNDLE_OBJ) String workBundleString) {
        logger.debug("TPWorker incoming execute! check prio={}", Thread.currentThread().getPriority());
        // TODO Doesn't look like anything is actually calling this, should we remove this?
        final boolean success;
        try {
            // Look up the place reference
            final String nsName = KeyManipulator.getServiceLocation(clientName);
            final IPickUpSpace place = (IPickUpSpace) Namespace.lookup(nsName);
            if (place == null) {
                throw new IllegalArgumentException("No client place found using name " + clientName);
            }

            final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(workBundleString.getBytes("8859_1")));
            WorkBundle paths = (WorkBundle) ois.readObject();
            success = place.enque(paths);
        } catch (Exception e) {
            logger.warn("WorkSpaceClientEnqueWorker exception", e);
            return Response.serverError().entity("WorkSpaceClientEnqueWorker exception:\n" + e.getMessage()).build();
        }

        if (success) {
            // old success from WorkSpaceClientEnqueWorker
            // return WORKER_SUCCESS;
            return Response.ok().entity("Successful add to the PickUpPlaceClient queue").build();
        } else {
            // old failure from WorkSpaceClientEnqueWorker
            // return new WorkerStatus(WorkerStatus.FAILURE, "WorkSpaceClientEnqueWorker failed, queue full");
            return Response.serverError().entity("WorkSpaceClientEnqueWorker failed, queue full").build();
        }
    }


	public static boolean copyResource(File file, String filename, File targetDirectory, PathMatcher filter) {
		try {
			Path path = getResource(file, filename);
			if(path == null) {
				return false;
			}

			Path destDir = targetDirectory.toPath();
			Files.walkFileTree(path, new CopyVisitor(path, destDir, filter));
			PathUtils.closeSubsequentFS(path);
			return true;
		} catch (IOException e) {
			log.error("", e);
			return false;
		}
	}


    public RainbowParameters(int[] vi)
    {
        this.vi = vi;
        try
        {
            checkParams();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }


    public Process execute()
        throws CommandLineException
    {
        // TODO: Provided only for backward compat. with <= 1.4
        verifyShellState();

        Process process;

        //addEnvironment( "MAVEN_TEST_ENVAR", "MAVEN_TEST_ENVAR_VALUE" );

        String[] environment = getEnvironmentVariables();

        File workingDir = shell.getWorkingDirectory();

        try
        {
            if ( workingDir == null )
            {
                process = Runtime.getRuntime().exec( getShellCommandline(), environment );
            }
            else
            {
                if ( !workingDir.exists() )
                {
                    throw new CommandLineException( "Working directory \"" + workingDir.getPath()
                        + "\" does not exist!" );
                }
                else if ( !workingDir.isDirectory() )
                {
                    throw new CommandLineException( "Path \"" + workingDir.getPath()
                        + "\" does not specify a directory." );
                }

                process = Runtime.getRuntime().exec( getShellCommandline(), environment, workingDir );
            }
        }
        catch ( IOException ex )
        {
            throw new CommandLineException( "Error while executing process.", ex );
        }

        return process;
    }


	private HColor getColor(ColorParam colorParam, Stereotype stereo) {
		final ISkinParam skinParam = diagram.getSkinParam();
		return rose.getHtmlColor(skinParam, stereo, colorParam);
	}


	public void testMatchOperations() {

		JWKMatcher matcher = new JWKMatcher.Builder().keyOperations(new LinkedHashSet<>(Arrays.asList(KeyOperation.SIGN, KeyOperation.VERIFY))).build();

		assertTrue(matcher.matches(new RSAKey.Builder(new Base64URL("n"), new Base64URL("e")).keyID("1")
			.keyOperations(new HashSet<>(Arrays.asList(KeyOperation.SIGN, KeyOperation.VERIFY))).build()));
		assertFalse(matcher.matches(new ECKey.Builder(ECKey.Curve.P_256, new Base64URL("x"), new Base64URL("y")).keyID("2").build()));

		assertEquals("key_ops=[sign, verify]", matcher.toString());
	}


    private boolean isStale(URL source, File target) {

        if( source.getProtocol().equals("jar") ) {
            // unwrap the jar protocol...
            try {
                String parts[] = source.getFile().split(Pattern.quote("!"));
                source = new URL(parts[0]);
            } catch (MalformedURLException e) {
                return false;
            }
        }

        File sourceFile=null;
        if( source.getProtocol().equals("file") ) {
            sourceFile = new File(source.getFile());
        }
        if( sourceFile!=null && sourceFile.exists() ) {
            if( sourceFile.lastModified() > target.lastModified() ) {
                return true;
            }
        }
        return false;
    }


    public ResetPasswordRequestResponse requestResetPassword(UserReference userReference) throws ResetPasswordException
    {
        this.checkUserReference(userReference);

        UserProperties userProperties = this.userPropertiesResolver.resolve(userReference);
        InternetAddress email = userProperties.getEmail();

        if (email == null) {
            String exceptionMessage =
                this.localizationManager.getTranslationPlain("xe.admin.passwordReset.error.noEmail");
            throw new ResetPasswordException(exceptionMessage);
        }

        DocumentUserReference documentUserReference = (DocumentUserReference) userReference;
        DocumentReference reference = documentUserReference.getReference();
        XWikiContext context = this.contextProvider.get();

        try {
            XWikiDocument userDocument = context.getWiki().getDocument(reference, context);

            if (userDocument.getXObject(LDAP_CLASS_REFERENCE) != null) {
                String exceptionMessage =
                    this.localizationManager.getTranslationPlain("xe.admin.passwordReset.error.ldapUser",
                        userReference.toString());
                throw new ResetPasswordException(exceptionMessage);
            }

            BaseObject xObject = userDocument.getXObject(RESET_PASSWORD_REQUEST_CLASS_REFERENCE, true, context);
            String verificationCode = context.getWiki().generateRandomString(30);
            xObject.set(VERIFICATION_PROPERTY, verificationCode, context);

            String saveComment =
                this.localizationManager.getTranslationPlain("xe.admin.passwordReset.versionComment");
            context.getWiki().saveDocument(userDocument, saveComment, true, context);

            return new DefaultResetPasswordRequestResponse(userReference, email, verificationCode);
        } catch (XWikiException e) {
            throw new ResetPasswordException("Error when reading user document to perform reset password request.", e);
        }
    }


    public static IRubyObject from_document(ThreadContext context, IRubyObject klazz, IRubyObject document) {
        XmlDocument doc = ((XmlDocument) ((XmlNode) document).document(context));

        RubyArray errors = (RubyArray) doc.getInstanceVariable("@errors");
        if (!errors.isEmpty()) {
            throw ((XmlSyntaxError) errors.first()).toThrowable();
        }

        DOMSource source = new DOMSource(doc.getDocument());

        IRubyObject uri = doc.url(context);

        if (!uri.isNil()) {
            source.setSystemId(uri.convertToString().asJavaString());
        }

        return getSchema(context, (RubyClass)klazz, source);
    }


    void doubleQuote() {
        final PathAndQuery res = PathAndQuery.parse("/\"?\"");
        assertThat(res).isNotNull();
        assertThat(res.path()).isEqualTo("/%22");
        assertThat(res.query()).isEqualTo("%22");
    }


    public byte[] allocateJobCaches(byte[] cacheAllocationRequestBytes) {
		CacheAllocationRequest allocationRequest = (CacheAllocationRequest) SerializationUtils
				.deserialize(cacheAllocationRequestBytes);
		return SerializationUtils.serialize((Serializable) jobManager.allocateJobCaches(
				getJobToken(), allocationRequest.getCurrentTime(), allocationRequest.getInstances()));
    }


    public boolean isValidating() {
        return validating;
    }


	public void drawU(UGraphic ug) {
		ug = ug.apply(backColor.bg()).apply(borderColor);
		final URectangle rect = new URectangle(dim.getWidth(), dim.getHeight()).rounded(rounded);
		rect.setDeltaShadow(shadowing);
		ug.apply(stroke).draw(rect);

		final double yLine = titleHeight + attributeHeight;

		ug = ug.apply(imgBackcolor.bg());

		final double thickness = stroke.getThickness();

		final URectangle inner = new URectangle(dim.getWidth() - 4 * thickness,
				dim.getHeight() - titleHeight - 4 * thickness - attributeHeight).rounded(rounded);
		ug.apply(imgBackcolor).apply(new UTranslate(2 * thickness, yLine + 2 * thickness)).draw(inner);

		if (titleHeight > 0) {
			ug.apply(stroke).apply(UTranslate.dy(yLine)).draw(ULine.hline(dim.getWidth()));
		}

		if (attributeHeight > 0) {
			ug.apply(stroke).apply(UTranslate.dy(yLine - attributeHeight)).draw(ULine.hline(dim.getWidth()));
		}

	}


        public String getShortDescription() {
            if(note != null) {
                return Messages.Cause_RemoteCause_ShortDescriptionWithNote(addr, note);
            } else {
                return Messages.Cause_RemoteCause_ShortDescription(addr);
            }
        }


	public static String applySorting(String query, Sort sort, String alias) {

		Assert.hasText(query);

		if (null == sort || !sort.iterator().hasNext()) {
			return query;
		}

		StringBuilder builder = new StringBuilder(query);

		if (!ORDER_BY.matcher(query).matches()) {
			builder.append(" order by ");
		} else {
			builder.append(", ");
		}

		Set<String> aliases = getOuterJoinAliases(query);

		for (Order order : sort) {
			builder.append(getOrderClause(aliases, alias, order)).append(", ");
		}

		builder.delete(builder.length() - 2, builder.length());

		return builder.toString();
	}


	public static boolean isAbsolute(String url)
	{
		if (url.startsWith("//"))  // //www.domain.com/start
		{
			return true;
		}

		if (url.startsWith("/")) // /somePage.html
		{
			return false;
		}

		boolean result = false;

		try
		{
			URI uri = new URI(url);
			result = uri.isAbsolute();
		}
		catch (URISyntaxException e) {} //Ignore

		return result;
	}


    public void encodeByteArray() {
        Packet<byte[]> packet = new Packet<>(Parser.BINARY_EVENT);
        packet.data = "abc".getBytes(Charset.forName("UTF-8"));
        packet.id = 23;
        packet.nsp = "/cool";
        Helpers.testBin(packet);
    }


	public int decryptWithAd(byte[] ad, byte[] ciphertext,
			int ciphertextOffset, byte[] plaintext, int plaintextOffset,
			int length) throws ShortBufferException, BadPaddingException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (length > space)
			throw new ShortBufferException();
		if (plaintextOffset > plaintext.length)
			space = 0;
		else
			space = plaintext.length - plaintextOffset;
		if (keySpec == null) {
			// The key is not set yet - return the ciphertext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length);
			return length;
		}
		if (length < 16)
			Noise.throwBadTagException();
		int dataLen = length - 16;
		if (dataLen > space)
			throw new ShortBufferException();
		try {
			setup(ad);
		} catch (InvalidKeyException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (InvalidAlgorithmParameterException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		ghash.update(ciphertext, ciphertextOffset, dataLen);
		ghash.pad(ad != null ? ad.length : 0, dataLen);
		ghash.finish(iv, 0, 16);
		int temp = 0;
		for (int index = 0; index < 16; ++index)
			temp |= (hashKey[index] ^ iv[index] ^ ciphertext[ciphertextOffset + dataLen + index]);
		if ((temp & 0xFF) != 0)
			Noise.throwBadTagException();
		try {
			int result = cipher.update(ciphertext, ciphertextOffset, dataLen, plaintext, plaintextOffset);
			cipher.doFinal(plaintext, plaintextOffset + result);
		} catch (IllegalBlockSizeException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (BadPaddingException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		return dataLen;
	}


    public static void zipFolderAPKTool(String srcFolder, String destZipFile) throws Exception {
        try (FileOutputStream fileWriter = new FileOutputStream(destZipFile);
             ZipOutputStream zip = new ZipOutputStream(fileWriter)){
            addFolderToZipAPKTool("", srcFolder, zip);
            zip.flush();
        }
    }


    public static void main(
        String[]    args)
    {
        Security.addProvider(new BouncyCastleProvider());

        runTest(new ECDSA5Test());
    }


    public void testSetContentFromFile() throws Exception {
        TestHttpData test = new TestHttpData("test", UTF_8, 0);
        try {
            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
            tmpFile.deleteOnExit();
            FileOutputStream fos = new FileOutputStream(tmpFile);
            byte[] bytes = new byte[4096];
            PlatformDependent.threadLocalRandom().nextBytes(bytes);
            try {
                fos.write(bytes);
                fos.flush();
            } finally {
                fos.close();
            }
            test.setContent(tmpFile);
            ByteBuf buf = test.getByteBuf();
            assertEquals(buf.readerIndex(), 0);
            assertEquals(buf.writerIndex(), bytes.length);
            assertArrayEquals(bytes, test.get());
            assertArrayEquals(bytes, ByteBufUtil.getBytes(buf));
        } finally {
            //release the ByteBuf
            test.delete();
        }
    }


    public static void execute(String url, String proxyHost, int proxyPort, String proxyUsername, String proxyPassword,
            String terminalWidth) {
        initializeSsl();
        HttpURLConnection conn = createHttpUrlConnection(convertToUrl(url), proxyHost, proxyPort, proxyUsername,
                proxyPassword);
        conn.setInstanceFollowRedirects(false);
        setRequestMethod(conn, Utils.RequestMethod.GET);
        handleResponse(conn, getStatusCode(conn), terminalWidth);
        Authenticator.setDefault(null);
    }


    public void setDocumentFactory(DocumentFactory documentFactory) {
        this.factory = documentFactory;
    }


  parse_io(ThreadContext context,
           IRubyObject klazz,
           IRubyObject data,
           IRubyObject enc)
  {
    //int encoding = (int)enc.convertToInteger().getLongValue();
    final Ruby runtime = context.runtime;
    XmlSaxParserContext ctx = newInstance(runtime, (RubyClass) klazz);
    ctx.initialize(runtime);
    ctx.setIOInputSource(context, data, runtime.getNil());
    return ctx;
  }


    public void setIgnoreComments(boolean ignoreComments) {
        this.ignoreComments = ignoreComments;
    }


	public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset,
			byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (!haskey) {
			// The key is not set yet - return the plaintext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
			return length;
		}
		if (space < 16 || length > (space - 16))
			throw new ShortBufferException();
		setup(ad);
		encrypt(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
		poly.update(ciphertext, ciphertextOffset, length);
		finish(ad, length);
		System.arraycopy(polyKey, 0, ciphertext, ciphertextOffset + length, 16);
		return length + 16;
	}


	public RoundedContainer(Dimension2D dim, double titleHeight, double attributeHeight, HColor borderColor,
			HColor backColor, HColor imgBackcolor, UStroke stroke, double rounded, double shadowing) {
		if (dim.getWidth() == 0) {
			throw new IllegalArgumentException();
		}
		this.rounded = rounded;
		this.dim = dim;
		this.imgBackcolor = imgBackcolor;
		this.titleHeight = titleHeight;
		this.borderColor = borderColor;
		this.backColor = backColor;
		this.attributeHeight = attributeHeight;
		this.stroke = stroke;
		this.shadowing = shadowing;
	}


    public DefaultFileSystemResourceLoader(Path path) {
        this.baseDirPath = Optional.of(path);
    }


    public boolean isStripWhitespaceText() {
        return stripWhitespaceText;
    }


    public BCXMSSMTPrivateKey(PrivateKeyInfo keyInfo)
        throws IOException
    {
        XMSSMTKeyParams keyParams = XMSSMTKeyParams.getInstance(keyInfo.getPrivateKeyAlgorithm().getParameters());
        this.treeDigest = keyParams.getTreeDigest().getAlgorithm();

        XMSSPrivateKey xmssMtPrivateKey = XMSSPrivateKey.getInstance(keyInfo.parsePrivateKey());

        try
        {
            XMSSMTPrivateKeyParameters.Builder keyBuilder = new XMSSMTPrivateKeyParameters
                .Builder(new XMSSMTParameters(keyParams.getHeight(), keyParams.getLayers(), DigestUtil.getDigest(treeDigest)))
                .withIndex(xmssMtPrivateKey.getIndex())
                .withSecretKeySeed(xmssMtPrivateKey.getSecretKeySeed())
                .withSecretKeyPRF(xmssMtPrivateKey.getSecretKeyPRF())
                .withPublicSeed(xmssMtPrivateKey.getPublicSeed())
                .withRoot(xmssMtPrivateKey.getRoot());

            if (xmssMtPrivateKey.getBdsState() != null)
            {
                keyBuilder.withBDSState((BDSStateMap)XMSSUtil.deserialize(xmssMtPrivateKey.getBdsState()));
            }

            this.keyParams = keyBuilder.build();
        }
        catch (ClassNotFoundException e)
        {
            throw new IOException("ClassNotFoundException processing BDS state: " + e.getMessage());
        }
    }


	public static List<String> checkLockedFileBeforeUnzipNonStrict(VFSLeaf zipLeaf, VFSContainer targetDir, Identity identity) {
		List<String> lockedFiles = new ArrayList<>();
		VFSLockManager vfsLockManager = CoreSpringFactory.getImpl(VFSLockManager.class);

		try(InputStream in = zipLeaf.getInputStream();
				net.sf.jazzlib.ZipInputStream oZip = new net.sf.jazzlib.ZipInputStream(in);) {
			// unzip files
			net.sf.jazzlib.ZipEntry oEntr = oZip.getNextEntry();
			while (oEntr != null) {
				if (oEntr.getName() != null && !oEntr.getName().startsWith(DIR_NAME__MACOSX)) {
					if (oEntr.isDirectory()) {
						// skip MacOSX specific metadata directory
						// directories aren't locked
						oZip.closeEntry();
						oEntr = oZip.getNextEntry();
						continue;
					} else {
						// search file
						VFSContainer createIn = targetDir;
						String name = oEntr.getName();
						// check if entry has directories which did not show up as
						// directories above
						int dirSepIndex = name.lastIndexOf('/');
						if (dirSepIndex == -1) {
							// try it windows style, backslash is also valid format
							dirSepIndex = name.lastIndexOf('\\');
						}
						if (dirSepIndex > 0) {
							// get subdirs
							createIn = getAllSubdirs(targetDir, name.substring(0, dirSepIndex), identity, false);
							if (createIn == null) {
								//sub directories don't exist, and aren't locked
								oZip.closeEntry();
								oEntr = oZip.getNextEntry();
								continue;
							}
							name = name.substring(dirSepIndex + 1);
						}

						VFSLeaf newEntry = (VFSLeaf)createIn.resolve(name);
						if(vfsLockManager.isLockedForMe(newEntry, identity, VFSLockApplicationType.vfs, null)) {
							lockedFiles.add(name);
						}
					}
				}
				oZip.closeEntry();
				oEntr = oZip.getNextEntry();
			}
		} catch (IOException e) {
			return null;
		}

		return lockedFiles;
	}


    private static Stream<Arguments> provideFilesAndExpectedExceptionType() {
        return Stream.of(
            Arguments.of("abnormal/corrupt-header.rar", CorruptHeaderException.class),
            Arguments.of("abnormal/mainHeaderNull.rar", BadRarArchiveException.class)
        );
    }


	protected SymbolContext getContextLegacy() {

		if (UseStyle.useBetaStyle() == false)
			return new SymbolContext(HColorUtils.COL_D7E0F2, HColorUtils.COL_038048).withStroke(new UStroke(2));

		final HColor lineColor = style.value(PName.LineColor).asColor(skinParam.getThemeStyle(),
				skinParam.getIHtmlColorSet());
		final HColor backgroundColor = style.value(PName.BackGroundColor).asColor(skinParam.getThemeStyle(),
				skinParam.getIHtmlColorSet());

		return new SymbolContext(backgroundColor, lineColor).withStroke(getStroke());

	}


    private void decodeTest()
    {
        EllipticCurve curve = new EllipticCurve(
                new ECFieldFp(new BigInteger("6277101735386680763835789423207666416083908700390324961279")), // q
                new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
                new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b

        ECPoint p = ECPointUtil.decodePoint(curve, Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"));

        if (!p.getAffineX().equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16)))
        {
            fail("x uncompressed incorrectly");
        }

        if (!p.getAffineY().equals(new BigInteger("7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 16)))
        {
            fail("y uncompressed incorrectly");
        }
    }


    public void testGetShellCommandLineNonWindows()
        throws Exception
    {
        Commandline cmd = new Commandline( new BourneShell() );
        cmd.setExecutable( "/usr/bin" );
        cmd.addArguments( new String[] {
            "a",
            "b"
        } );
        String[] shellCommandline = cmd.getShellCommandline();

        assertEquals( "Command line size", 3, shellCommandline.length );

        assertEquals( "/bin/sh", shellCommandline[0] );
        assertEquals( "-c", shellCommandline[1] );

        if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
        {
            assertEquals( "\\usr\\bin a b", shellCommandline[2] );
        }
        else
        {
            assertEquals( "/usr/bin a b", shellCommandline[2] );
        }
    }


    public Document read(URL url) throws DocumentException {
        String systemID = url.toExternalForm();

        InputSource source = new InputSource(systemID);
        if (this.encoding != null) {
            source.setEncoding(this.encoding);
        }

        return read(source);
    }


	protected Response attachToPost(Long messageKey, String filename, InputStream file,  HttpServletRequest request) {
		//load message
		Message mess = fom.loadMessage(messageKey);
		if(mess == null) {
			return Response.serverError().status(Status.NOT_FOUND).build();
		}
		if(!forum.equalsByPersistableKey(mess.getForum())) {
			return Response.serverError().status(Status.CONFLICT).build();
		}
		return attachToPost(mess, filename, file, request);
	}


	public static int sharedKeyLength(final JWEAlgorithm alg, final EncryptionMethod enc)
		throws JOSEException {

		if (alg.equals(JWEAlgorithm.ECDH_ES)) {

			int length = enc.cekBitLength();

			if (length == 0) {
				throw new JOSEException("Unsupported JWE encryption method " + enc);
			}

			return length;

		} else if (alg.equals(JWEAlgorithm.ECDH_ES_A128KW)) {
			return 128;
		} else if (alg.equals(JWEAlgorithm.ECDH_ES_A192KW)) {
			return  192;
		} else if (alg.equals(JWEAlgorithm.ECDH_ES_A256KW)) {
			return  256;
		} else {
			throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(
				alg, ECDHCryptoProvider.SUPPORTED_ALGORITHMS));
		}
	}


    public void testGetChunk() throws Exception {
        TestHttpData test = new TestHttpData("test", UTF_8, 0);
        try {
            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
            tmpFile.deleteOnExit();
            FileOutputStream fos = new FileOutputStream(tmpFile);
            byte[] bytes = new byte[4096];
            PlatformDependent.threadLocalRandom().nextBytes(bytes);
            try {
                fos.write(bytes);
                fos.flush();
            } finally {
                fos.close();
            }
            test.setContent(tmpFile);
            ByteBuf buf1 = test.getChunk(1024);
            assertEquals(buf1.readerIndex(), 0);
            assertEquals(buf1.writerIndex(), 1024);
            ByteBuf buf2 = test.getChunk(1024);
            assertEquals(buf2.readerIndex(), 0);
            assertEquals(buf2.writerIndex(), 1024);
            assertFalse("Arrays should not be equal",
                    Arrays.equals(ByteBufUtil.getBytes(buf1), ByteBufUtil.getBytes(buf2)));
        } finally {
            test.delete();
        }
    }


    public void sendError(int sc, String msg) throws IOException {
        if (isIncluding()) {
            Logger.log(Logger.ERROR, Launcher.RESOURCES, "IncludeResponse.Error",
                    new String[] { "" + sc, msg });
            return;
        }

        Logger.log(Logger.DEBUG, Launcher.RESOURCES,
                "WinstoneResponse.SendingError", new String[] { "" + sc, msg });

        if ((this.webAppConfig != null) && (this.req != null)) {

            RequestDispatcher rd = this.webAppConfig
                    .getErrorDispatcherByCode(req.getRequestURI(), sc, msg, null);
            if (rd != null) {
                try {
                    rd.forward(this.req, this);
                    return;
                } catch (IllegalStateException err) {
                    throw err;
                } catch (IOException err) {
                    throw err;
                } catch (Throwable err) {
                    Logger.log(Logger.WARNING, Launcher.RESOURCES,
                            "WinstoneResponse.ErrorInErrorPage", new String[] {
                                    rd.getName(), sc + "" }, err);
                    return;
                }
            }
        }
        // If we are here there was no webapp and/or no request object, so
        // show the default error page
        if (this.errorStatusCode == null) {
            this.statusCode = sc;
        }
        String output = Launcher.RESOURCES.getString("WinstoneResponse.ErrorPage",
                new String[] { sc + "", (msg == null ? "" : msg), "",
                        Launcher.RESOURCES.getString("ServerVersion"),
                        "" + new Date() });
        setContentLength(output.getBytes(getCharacterEncoding()).length);
        Writer out = getWriter();
        out.write(output);
        out.flush();
    }


    public void view(@RequestParam String filename,
                     @RequestParam(required = false) String base,
                     @RequestParam(required = false) Integer tailLines,
                     HttpServletResponse response) throws IOException {
        securityCheck(filename);
        response.setContentType(MediaType.TEXT_PLAIN_VALUE);

        Path path = loggingPath(base);
        FileProvider fileProvider = getFileProvider(path);
        if (tailLines != null) {
            fileProvider.tailContent(path, filename, response.getOutputStream(), tailLines);
        }
        else {
            fileProvider.streamContent(path, filename, response.getOutputStream());
        }
    }


    void empty() {
        final PathAndQuery res = PathAndQuery.parse(null);
        assertThat(res).isNotNull();
        assertThat(res.path()).isEqualTo("/");
        assertThat(res.query()).isNull();

        final PathAndQuery res2 = PathAndQuery.parse("");
        assertThat(res2).isNotNull();
        assertThat(res2.path()).isEqualTo("/");
        assertThat(res2.query()).isNull();

        final PathAndQuery res3 = PathAndQuery.parse("?");
        assertThat(res3).isNotNull();
        assertThat(res3.path()).isEqualTo("/");
        assertThat(res3.query()).isEqualTo("");
    }


    protected XMLReader createXMLReader() throws SAXException {
        return SAXHelper.createXMLReader(isValidating());
    }


		public void configure(ICourse course, CourseNode newNode, ModuleConfiguration moduleConfig) {
			newNode.setDisplayOption(CourseNode.DISPLAY_OPTS_TITLE_DESCRIPTION_CONTENT);
			VFSContainer rootContainer = course.getCourseFolderContainer();
			VFSLeaf singleFile = (VFSLeaf) rootContainer.resolve("/" + filename);
			if (singleFile == null) {
				singleFile = rootContainer.createChildLeaf("/" + filename);
			}

			if(in != null) {
				moduleConfig.set(SPEditController.CONFIG_KEY_FILE, "/" + filename);

				OutputStream out = singleFile.getOutputStream(false);
				FileUtils.copy(in, out);
				FileUtils.closeSafely(out);
				FileUtils.closeSafely(in);
			} else {
				if(StringHelper.containsNonWhitespace(path)) {
					if(!path.startsWith("/")) {
						path = "/" + path;
					}
					if(!path.endsWith("/")) {
						path += "/";
					}
				} else {
					path = "/";
				}
				moduleConfig.set(SPEditController.CONFIG_KEY_FILE, path + filename);
			}
			//saved node configuration
		}


  public void write(byte[] b, int offset, int length) throws IOException {
    if (b == null) {
      throw new NullPointerException();
    }

    if (offset < 0 || offset + length > b.length) {
      throw new ArrayIndexOutOfBoundsException();
    }

    write(fd, b, offset, length);
  }


    private static String encodeToPercents(Bytes value, boolean isPath) {
        final BitSet allowedChars = isPath ? ALLOWED_PATH_CHARS : ALLOWED_QUERY_CHARS;
        final int length = value.length;
        boolean needsEncoding = false;
        for (int i = 0; i < length; i++) {
            if (!allowedChars.get(value.data[i] & 0xFF)) {
                needsEncoding = true;
                break;
            }
        }

        if (!needsEncoding) {
            // Deprecated, but it fits perfect for our use case.
            // noinspection deprecation
            return new String(value.data, 0, 0, length);
        }

        final StringBuilder buf = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            final int b = value.data[i] & 0xFF;

            if (b == PERCENT_ENCODING_MARKER && (i + 1) < length) {
                final int marker = value.data[i + 1] & 0xFF;
                final String percentEncodedChar = MARKER_TO_PERCENT_ENCODED_CHAR[marker];
                if (percentEncodedChar != null) {
                    buf.append(percentEncodedChar);
                    i++;
                    continue;
                }
            }

            if (allowedChars.get(b)) {
                buf.append((char) b);
            } else if (b == ' ') {
                if (isPath) {
                    buf.append("%20");
                } else {
                    buf.append('+');
                }
            } else {
                buf.append('%');
                appendHexNibble(buf, b >>> 4);
                appendHexNibble(buf, b & 0xF);
            }
        }

        return buf.toString();
    }


  public synchronized <T extends Result> T setResult(Class<T> resultClass) throws SQLException {
    checkFreed();
    initialize();

    if (resultClass == null || DOMResult.class.equals(resultClass)) {
      domResult = new DOMResult();
      active = true;
      return (T) domResult;
    } else if (SAXResult.class.equals(resultClass)) {
      try {
        SAXTransformerFactory transformerFactory =
            (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
        stringWriter = new StringWriter();
        transformerHandler.setResult(new StreamResult(stringWriter));
        active = true;
        return (T) new SAXResult(transformerHandler);
      } catch (TransformerException te) {
        throw new PSQLException(GT.tr("Unable to create SAXResult for SQLXML."),
            PSQLState.UNEXPECTED_ERROR, te);
      }
    } else if (StreamResult.class.equals(resultClass)) {
      stringWriter = new StringWriter();
      active = true;
      return (T) new StreamResult(stringWriter);
    } else if (StAXResult.class.equals(resultClass)) {
      stringWriter = new StringWriter();
      try {
        XMLOutputFactory xof = XMLOutputFactory.newInstance();
        XMLStreamWriter xsw = xof.createXMLStreamWriter(stringWriter);
        active = true;
        return (T) new StAXResult(xsw);
      } catch (XMLStreamException xse) {
        throw new PSQLException(GT.tr("Unable to create StAXResult for SQLXML"),
            PSQLState.UNEXPECTED_ERROR, xse);
      }
    }

    throw new PSQLException(GT.tr("Unknown XML Result class: {0}", resultClass),
        PSQLState.INVALID_PARAMETER_TYPE);
  }


    public Directory read(final ImageInputStream input) throws IOException {
        Validate.notNull(input, "input");

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);

        try {
            // TODO: Consider parsing using SAX?
            // TODO: Determine encoding and parse using a Reader...
            // TODO: Refactor scanner to return inputstream?
            // TODO: Be smarter about ASCII-NULL termination/padding (the SAXParser aka Xerces DOMParser doesn't like it)...
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setErrorHandler(new DefaultHandler());
            Document document = builder.parse(new InputSource(IIOUtil.createStreamAdapter(input)));

//            XMLSerializer serializer = new XMLSerializer(System.err, System.getProperty("file.encoding"));
//            serializer.serialize(document);

            String toolkit = getToolkit(document);
            Node rdfRoot = document.getElementsByTagNameNS(XMP.NS_RDF, "RDF").item(0);
            NodeList descriptions = document.getElementsByTagNameNS(XMP.NS_RDF, "Description");

            return parseDirectories(rdfRoot, descriptions, toolkit);
        }
        catch (SAXException e) {
            throw new IIOException(e.getMessage(), e);
        }
        catch (ParserConfigurationException e) {
            throw new RuntimeException(e); // TODO: Or IOException?
        }
    }


	public static HColor noGradient(HColor color) {
		if (color instanceof HColorGradient) {
			return ((HColorGradient) color).getColor1();
		}
		return color;
	}


	public void testMatchUseNotSpecifiedOrSignature() {

		JWKMatcher matcher = new JWKMatcher.Builder().keyUses(KeyUse.SIGNATURE, null).build();

		assertTrue(matcher.matches(new RSAKey.Builder(new Base64URL("n"), new Base64URL("e")).keyID("1").keyUse(KeyUse.SIGNATURE).build()));
		assertTrue(matcher.matches(new ECKey.Builder(ECKey.Curve.P_256, new Base64URL("x"), new Base64URL("y")).keyID("2").build()));
		assertFalse(matcher.matches(new ECKey.Builder(ECKey.Curve.P_256, new Base64URL("x"), new Base64URL("y")).keyID("3").keyUse(KeyUse.ENCRYPTION).build()));

		assertEquals("use=[sig, null]", matcher.toString());
	}


    protected EntityResolver createDefaultEntityResolver(String systemId) {
        String prefix = null;

        if ((systemId != null) && (systemId.length() > 0)) {
            int idx = systemId.lastIndexOf('/');

            if (idx > 0) {
                prefix = systemId.substring(0, idx + 1);
            }
        }

        return new SAXEntityResolver(prefix);
    }


    public boolean isIncludeInternalDTDDeclarations() {
        return includeInternalDTDDeclarations;
    }


    static XmlSchema createSchemaInstance(ThreadContext context, RubyClass klazz, Source source) {
        Ruby runtime = context.getRuntime();
        XmlRelaxng xmlRelaxng = (XmlRelaxng) NokogiriService.XML_RELAXNG_ALLOCATOR.allocate(runtime, klazz);
        xmlRelaxng.setInstanceVariable("@errors", runtime.newEmptyArray());

        try {
            Schema schema = xmlRelaxng.getSchema(source, context);
            xmlRelaxng.setVerifier(schema.newVerifier());
            return xmlRelaxng;
        } catch (VerifierConfigurationException ex) {
            throw context.getRuntime().newRuntimeError("Could not parse document: " + ex.getMessage());
        }
    }


    public boolean isResetPasswordSent()
    {
        // If there is no form and we see an info box, then the request was sent.
        return !getDriver().hasElementWithoutWaiting(By.cssSelector("#resetPasswordForm"))
            && messageBox.getText().contains("An e-mail was sent to");
    }


    public SAXReader(String xmlReaderClassName, boolean validating)
            throws SAXException {
        if (xmlReaderClassName != null) {
            this.xmlReader = XMLReaderFactory
                    .createXMLReader(xmlReaderClassName);
        }

        this.validating = validating;
    }


    private void sendStreamingResponse(HttpExchange pExchange, ParsedUri pParsedUri, JSONStreamAware pJson) throws IOException {
        Headers headers = pExchange.getResponseHeaders();
        if (pJson != null) {
            headers.set("Content-Type", getMimeType(pParsedUri) + "; charset=utf-8");
            String callback = pParsedUri.getParameter(ConfigKey.CALLBACK.getKeyValue());
            pExchange.sendResponseHeaders(200, 0);
            Writer writer = new OutputStreamWriter(pExchange.getResponseBody(), "UTF-8");
            IoUtil.streamResponseAndClose(writer, pJson, callback);
        } else {
            headers.set("Content-Type", "text/plain");
            pExchange.sendResponseHeaders(200,-1);
        }
    }


	public VideoMetadata readVideoMetadataFile(OLATResource videoResource){
		VFSContainer baseContainer= FileResourceManager.getInstance().getFileResourceRootImpl(videoResource);
		VFSLeaf metaDataFile = (VFSLeaf) baseContainer.resolve(FILENAME_VIDEO_METADATA_XML);
		try {
			return (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
		} catch (Exception e) {
			log.error("Error while parsing XStream file for videoResource::{}", videoResource, e);
			// return an empty, so at least it displays something and not an error
			VideoMetadata meta =  new VideoMetadataImpl();
			meta.setWidth(800);
			meta.setHeight(600);
			return meta;
		}
	}


    private static IRubyObject getSchema(ThreadContext context, RubyClass klazz, Source source) {
        String moduleName = klazz.getName();
        if ("Nokogiri::XML::Schema".equals(moduleName)) {
            return XmlSchema.createSchemaInstance(context, klazz, source);
        } else if ("Nokogiri::XML::RelaxNG".equals(moduleName)) {
            return XmlRelaxng.createSchemaInstance(context, klazz, source);
        }
        return context.getRuntime().getNil();
    }


    public static IRubyObject read_memory(ThreadContext context, IRubyObject klazz, IRubyObject content) {
        String data = content.convertToString().asJavaString();
        return getSchema(context, (RubyClass) klazz, new StreamSource(new StringReader(data)));
    }


    public DocumentFactory getDocumentFactory() {
        if (factory == null) {
            factory = DocumentFactory.getInstance();
        }

        return factory;
    }


    public boolean isMergeAdjacentText() {
        return mergeAdjacentText;
    }


    public void encodeDeepBinaryJSONWithNullValue() throws JSONException {
        JSONObject data = new JSONObject("{a: \"b\", c: 4, e: {g: null}, h: null}");
        data.put("h", new byte[9]);

        Packet<JSONObject> packet = new Packet<>(Parser.BINARY_EVENT);
        packet.data = data;
        packet.nsp = "/";
        packet.id = 600;
        Helpers.testBin(packet);
    }


    private void checkParams()
        throws Exception
    {
        if (vi == null)
        {
            throw new Exception("no layers defined.");
        }
        if (vi.length > 1)
        {
            for (int i = 0; i < vi.length - 1; i++)
            {
                if (vi[i] >= vi[i + 1])
                {
                    throw new Exception(
                        "v[i] has to be smaller than v[i+1]");
                }
            }
        }
        else
        {
            throw new Exception(
                "Rainbow needs at least 1 layer, such that v1 < v2.");
        }
    }


    public void testEscapeSingleQuotesOnArgument()
    {
        Shell sh = newShell();

        sh.setWorkingDirectory( "/usr/bin" );
        sh.setExecutable( "chmod" );

        String[] args = { "arg'withquote" };

        List shellCommandLine = sh.getShellCommandLine( args );

        String cli = StringUtils.join( shellCommandLine.iterator(), " " );
        System.out.println( cli );
        assertEquals("cd /usr/bin && chmod 'arg'\\''withquote'", shellCommandLine.get(shellCommandLine.size() - 1));
    }


    public XMLFilter getXMLFilter() {
        return xmlFilter;
    }


    public URIDryConverter(URI base, Map<PackageID, Manifest> dependencyManifests, boolean isBuild) {
        super(base, dependencyManifests, isBuild);
        this.base = URI.create(base.toString() + "/modules/info/");
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            proxy = getProxy();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            // ignore errors
        }
    }


  private AuthnRequestParseResult parseRequest(byte[] xmlBytes) throws SAMLException {
    String xml = new String(xmlBytes, StandardCharsets.UTF_8);
    if (logger.isDebugEnabled()) {
      logger.debug("SAMLRequest XML is\n{}", xml);
    }

    AuthnRequestParseResult result = new AuthnRequestParseResult();
    result.document = parseFromBytes(xmlBytes);
    result.authnRequest = unmarshallFromDocument(result.document, AuthnRequestType.class);
    result.request = new AuthenticationRequest();
    result.request.xml = xml;
    result.request.id = result.authnRequest.getID();
    result.request.issuer = result.authnRequest.getIssuer().getValue();
    result.request.issueInstant = result.authnRequest.getIssueInstant().toGregorianCalendar().toZonedDateTime();
    NameIDPolicyType nameIdPolicyType = result.authnRequest.getNameIDPolicy();
    if (nameIdPolicyType == null) {
      result.request.nameIdFormat = NameIDFormat.EmailAddress;
    } else {
      result.request.nameIdFormat = NameIDFormat.fromSAMLFormat(nameIdPolicyType.getFormat());
    }
    result.request.version = result.authnRequest.getVersion();
    return result;
  }


	public int decryptWithAd(byte[] ad, byte[] ciphertext,
			int ciphertextOffset, byte[] plaintext, int plaintextOffset,
			int length) throws ShortBufferException, BadPaddingException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (length > space)
			throw new ShortBufferException();
		if (plaintextOffset > plaintext.length)
			space = 0;
		else
			space = plaintext.length - plaintextOffset;
		if (keySpec == null) {
			// The key is not set yet - return the ciphertext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length);
			return length;
		}
		if (length < 16)
			Noise.throwBadTagException();
		int dataLen = length - 16;
		if (dataLen > space)
			throw new ShortBufferException();
		try {
			setup(ad);
		} catch (InvalidKeyException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (InvalidAlgorithmParameterException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		ghash.update(ciphertext, ciphertextOffset, dataLen);
		ghash.pad(ad != null ? ad.length : 0, dataLen);
		ghash.finish(iv, 0, 16);
		int temp = 0;
		for (int index = 0; index < 16; ++index)
			temp |= (hashKey[index] ^ iv[index] ^ ciphertext[ciphertextOffset + dataLen + index]);
		if ((temp & 0xFF) != 0)
			Noise.throwBadTagException();
		try {
			int result = cipher.update(ciphertext, ciphertextOffset, dataLen, plaintext, plaintextOffset);
			cipher.doFinal(plaintext, plaintextOffset + result);
		} catch (IllegalBlockSizeException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (BadPaddingException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		return dataLen;
	}


    public void testCreateHttpUrlConnection() {
        HttpURLConnection conn;
        // Test without proxy
        conn = createHttpUrlConnection(convertToUrl(TEST_URL), "", 0, "", "");
        Assert.assertNotNull(conn);
        // Test with the proxy
        conn = createHttpUrlConnection(convertToUrl(TEST_URL), "http://localhost", 9090, "testUser", "testPassword");
        Assert.assertNotNull(conn);
    }


    public static Object deserialize(byte[] data)
        throws IOException, ClassNotFoundException
    {
        ByteArrayInputStream in = new ByteArrayInputStream(data);
        ObjectInputStream is = new ObjectInputStream(in);
        return is.readObject();
    }


    public DefaultFileSystemResourceLoader(File baseDirPath) {
        this.baseDirPath = Optional.of(baseDirPath.toPath());
    }


    private static void createBaloInHomeRepo(HttpURLConnection conn, String modulePathInBaloCache,
            String moduleNameWithOrg, boolean isNightlyBuild, String newUrl, String contentDisposition) {
        long responseContentLength = conn.getContentLengthLong();
        if (responseContentLength <= 0) {
            createError("invalid response from the server, please try again");
        }
        String resolvedURI = conn.getHeaderField(RESOLVED_REQUESTED_URI);
        if (resolvedURI == null || resolvedURI.equals("")) {
            resolvedURI = newUrl;
        }
        String[] uriParts = resolvedURI.split("/");
        String moduleVersion = uriParts[uriParts.length - 3];

        validateModuleVersion(moduleVersion);
        String baloFile = getBaloFileName(contentDisposition, uriParts[uriParts.length - 1]);
        Path baloCacheWithModulePath = Paths.get(modulePathInBaloCache, moduleVersion);
        //<user.home>.ballerina/balo_cache/<org-name>/<module-name>/<module-version>

        Path baloPath = Paths.get(baloCacheWithModulePath.toString(), baloFile);
        if (baloPath.toFile().exists()) {
            createError("module already exists in the home repository: " + baloPath.toString());
        }

        createBaloFileDirectory(baloCacheWithModulePath);
        writeBaloFile(conn, baloPath, moduleNameWithOrg + ":" + moduleVersion, responseContentLength);
        handleNightlyBuild(isNightlyBuild, baloCacheWithModulePath);
    }


	public void testCurveCheckOk()
		throws Exception {

		ECPublicKey ephemeralPublicKey = generateECPublicKey(ECKey.Curve.P_256);
		ECPrivateKey privateKey = generateECPrivateKey(ECKey.Curve.P_256);
		ECDH.ensurePointOnCurve(ephemeralPublicKey, privateKey);
	}


    public void setStripWhitespaceText(boolean stripWhitespaceText) {
        this.stripWhitespaceText = stripWhitespaceText;
    }