protected Url decryptEntireUrl()

in wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java [418:541]


	protected Url decryptEntireUrl(final Request request, final Url encryptedUrl)
	{
		Url url = new Url(request.getCharset());

		List<String> encryptedSegments = encryptedUrl.getSegments();

		if (encryptedSegments.isEmpty())
		{
			return null;
		}

		/*
		 * The first encrypted segment contains an encrypted version of the entire plain text url.
		 */
		String encryptedUrlString = encryptedSegments.get(0);
		if (Strings.isEmpty(encryptedUrlString))
		{
			return null;
		}

		if (getMarkEncryptedUrls())
		{
			if (encryptedUrlString.startsWith(ENCRYPTED_URL_MARKER_PREFIX))
			{
				encryptedUrlString = encryptedUrlString.substring(ENCRYPTED_URL_MARKER_PREFIX.length());
			}
			else
			{
				return null;
			}
		}

		String decryptedUrl;
		try
		{
			decryptedUrl = getCrypt().decryptUrlSafe(encryptedUrlString);
		}
		catch (Exception e)
		{
			log.error("Error decrypting URL", e);
			return null;
		}

		if (decryptedUrl == null)
		{
			if (getMarkEncryptedUrls())
			{
				throw new PageExpiredException("Encrypted URL is no longer decryptable");
			}
			else
			{
				return null;
			}
		}

		Url originalUrl = Url.parse(decryptedUrl, request.getCharset());

		int originalNumberOfSegments = originalUrl.getSegments().size();
		int encryptedNumberOfSegments = encryptedUrl.getSegments().size();

		if (originalNumberOfSegments > 0)
		{
			/*
			 * This should always be true. Home page URLs are the only ones without
			 * segments, and we don't encrypt those with this method.
			 * 
			 * We always add the first segment of the URL, because we encrypt a URL like:
			 *	/path/to/something
			 * to:
			 *	/encrypted_full/hash/hash
			 * 
			 * Notice the consistent number of segments. If we applied the following relative URL:
			 *	../../something
			 * then the resultant URL would be:
			 *	/something
			 * 
			 * Hence, the mere existence of the first, encrypted version of complete URL, segment
			 * tells us that the first segment of the original URL is still to be used.
			 */
			url.getSegments().add(originalUrl.getSegments().get(0));
		}

		HashedSegmentGenerator generator = new HashedSegmentGenerator(encryptedUrlString);
		int segNo = 1;
		for (; segNo < encryptedNumberOfSegments; segNo++)
		{
			if (segNo >= originalNumberOfSegments)
			{
				break;
			}

			String next = generator.next();
			String encryptedSegment = encryptedSegments.get(segNo);
			if (!next.equals(encryptedSegment))
			{
				/*
				 * This segment received from the browser is not the same as the expected segment generated
				 * by the HashSegmentGenerator. Hence it, and all subsequent segments are considered plain
				 * text siblings of the original encrypted url.
				 */
				break;
			}

			/*
			 * This segments matches the expected checksum, so we add the corresponding segment from the
			 * original URL.
			 */
			url.getSegments().add(originalUrl.getSegments().get(segNo));
		}
		/*
		 * Add all remaining segments from the encrypted url as plain text segments.
		 */
		for (; segNo < encryptedNumberOfSegments; segNo++)
		{
			// modified or additional segment
			url.getSegments().add(encryptedUrl.getSegments().get(segNo));
		}

		url.getQueryParameters().addAll(originalUrl.getQueryParameters());
		// WICKET-4923 additional parameters
		url.getQueryParameters().addAll(encryptedUrl.getQueryParameters());

		return url;
	}