Commit 492ad980 authored by Grigory Fedorov's avatar Grigory Fedorov

Merge branch 'release/1.0.23'

parents 65a21109 ce018ce1
...@@ -72,14 +72,6 @@ app/src/main/res/layout/preference.xml ...@@ -72,14 +72,6 @@ app/src/main/res/layout/preference.xml
Also source code of following components is included in repository (see the source code or official sites for license details): Also source code of following components is included in repository (see the source code or official sites for license details):
ZXing
app/src/main/java/com/google/zxing/*
Apache License, Version 2.0 (the "License").
JZLib
app/src/main/java/com/jcraft/jzlib/*
BSD license.
Novel sasl client Novel sasl client
app/src/main/java/com/novell/sasl/* app/src/main/java/com/novell/sasl/*
The OpenLDAP Public License. The OpenLDAP Public License.
......
...@@ -7,8 +7,8 @@ android { ...@@ -7,8 +7,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 22
versionCode 194 versionCode 195
versionName '1.0.22' versionName '1.0.23'
} }
compileOptions { compileOptions {
...@@ -49,5 +49,7 @@ dependencies { ...@@ -49,5 +49,7 @@ dependencies {
compile 'com.melnykov:floatingactionbutton:1.2.0' compile 'com.melnykov:floatingactionbutton:1.2.0'
compile 'dnsjava:dnsjava:2.1.7' compile 'dnsjava:dnsjava:2.1.7'
compile 'com.github.bumptech.glide:glide:3.6.0' compile 'com.github.bumptech.glide:glide:3.6.0'
compile 'com.google.zxing:android-integration:3.1.0'
compile 'com.jcraft:jzlib:1.1.3'
compile project('otr4j') compile project('otr4j')
} }
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing.integration.android;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
/**
* <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
* way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
* project's source code.</p>
* <p/>
* <h2>Initiating a barcode scan</h2>
* <p/>
* <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait
* for the result in your app.</p>
* <p/>
* <p>It does require that the Barcode Scanner (or work-alike) application is installed. The
* {@link #initiateScan()} method will prompt the user to download the application, if needed.</p>
* <p/>
* <p>There are a few steps to using this integration. First, your {@link Activity} must implement
* the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
* <p/>
* <pre>{@code
* public void onActivityResult(int requestCode, int resultCode, Intent intent) {
* IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
* if (scanResult != null) {
* // handle scan result
* }
* // else continue with any other code you need in the method
* ...
* }
* }</pre>
* <p/>
* <p>This is where you will handle a scan result.</p>
* <p/>
* <p>Second, just call this in response to a user action somewhere to begin the scan process:</p>
* <p/>
* <pre>{@code
* IntentIntegrator integrator = new IntentIntegrator(yourActivity);
* integrator.initiateScan();
* }</pre>
* <p/>
* <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the
* user was prompted to download the application. This lets the calling app potentially manage the dialog.
* In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
* method.</p>
* <p/>
* <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
* {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
* yes/no button labels can be changed.</p>
* <p/>
* <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used
* to invoke the scanner. This can be used to set additional options not directly exposed by this
* simplified API.</p>
* <p/>
* <p>By default, this will only allow applications that are known to respond to this intent correctly
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(Collection)}.
* For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
* <p/>
* <h2>Sharing text via barcode</h2>
* <p/>
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p>
* <p/>
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
* <p/>
* <h2>Enabling experimental barcode formats</h2>
* <p/>
* <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as
* {@link com.google.zxing.BarcodeFormat#PDF_417}. Use {@link #initiateScan(java.util.Collection)} with
* a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such
* formats.</p>
*
* @author Sean Owen
* @author Fred Lin
* @author Isaac Potoczny-Jones
* @author Brad Drehmer
* @author gcstang
*/
public class IntentIntegrator {
public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
private static final String TAG = IntentIntegrator.class.getSimpleName();
public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
public static final String DEFAULT_MESSAGE =
"This application requires Barcode Scanner. Would you like to install it?";
public static final String DEFAULT_YES = "Yes";
public static final String DEFAULT_NO = "No";
public static final String BS_PACKAGE = "com.google.zxing.client.android";
private static final String BSPLUS_PACKAGE = "com.srowen.bs.android";
// supported barcode formats
public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
public static final Collection<String> ONE_D_CODE_TYPES =
list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128",
"ITF", "RSS_14", "RSS_EXPANDED");
public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE");
public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX");
public static final Collection<String> ALL_CODE_TYPES = null;
public static final Collection<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singleton(BS_PACKAGE);
public static final Collection<String> TARGET_ALL_KNOWN = list(
BS_PACKAGE, // Barcode Scanner
BSPLUS_PACKAGE, // Barcode Scanner+
BSPLUS_PACKAGE + ".simple" // Barcode Scanner+ Simple
// What else supports this intent?
);
private final Activity activity;
private String title;
private String message;
private String buttonYes;
private String buttonNo;
private Collection<String> targetApplications;
private final Map<String, Object> moreExtras;
public IntentIntegrator(Activity activity) {
this.activity = activity;
title = DEFAULT_TITLE;
message = DEFAULT_MESSAGE;
buttonYes = DEFAULT_YES;
buttonNo = DEFAULT_NO;
targetApplications = TARGET_ALL_KNOWN;
moreExtras = new HashMap<String, Object>(3);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setTitleByID(int titleID) {
title = activity.getString(titleID);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setMessageByID(int messageID) {
message = activity.getString(messageID);
}
public String getButtonYes() {
return buttonYes;
}
public void setButtonYes(String buttonYes) {
this.buttonYes = buttonYes;
}
public void setButtonYesByID(int buttonYesID) {
buttonYes = activity.getString(buttonYesID);
}
public String getButtonNo() {
return buttonNo;
}
public void setButtonNo(String buttonNo) {
this.buttonNo = buttonNo;
}
public void setButtonNoByID(int buttonNoID) {
buttonNo = activity.getString(buttonNoID);
}
public Collection<String> getTargetApplications() {
return targetApplications;
}
public void setTargetApplications(Collection<String> targetApplications) {
this.targetApplications = targetApplications;
}
public void setSingleTargetApplication(String targetApplication) {
this.targetApplications = Collections.singleton(targetApplication);
}
public Map<String, ?> getMoreExtras() {
return moreExtras;
}
public void addExtra(String key, Object value) {
moreExtras.put(key, value);
}
/**
* Initiates a scan for all known barcode types.
*/
public AlertDialog initiateScan() {
return initiateScan(ALL_CODE_TYPES);
}
/**
* Initiates a scan only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
// check which types of codes to scan for
if (desiredBarcodeFormats != null) {
// set the desired barcode types
StringBuilder joinedByComma = new StringBuilder();
for (String format : desiredBarcodeFormats) {
if (joinedByComma.length() > 0) {
joinedByComma.append(',');
}
joinedByComma.append(format);
}
intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
}
String targetAppPackage = findTargetAppPackage(intentScan);
if (targetAppPackage == null) {
return showDownloadDialog();
}
// intentScan.setPackage(targetAppPackage);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intentScan);
startActivityForResult(intentScan, REQUEST_CODE);
return null;
}
/**
* Start an activity.<br>
* This method is defined to allow different methods of activity starting for
* newer versions of Android and for compatibility library.
*
* @param intent Intent to start.
* @param code Request code for the activity
* @see android.app.Activity#startActivityForResult(Intent, int)
* @see android.app.Fragment#startActivityForResult(Intent, int)
*/
protected void startActivityForResult(Intent intent, int code) {
activity.startActivityForResult(intent, code);
}
private String findTargetAppPackage(Intent intent) {
PackageManager pm = activity.getPackageManager();
List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (availableApps != null) {
for (ResolveInfo availableApp : availableApps) {
String packageName = availableApp.activityInfo.packageName;
if (targetApplications.contains(packageName)) {
return packageName;
}
}
}
return null;
}
private AlertDialog showDownloadDialog() {
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
downloadDialog.setTitle(title);
downloadDialog.setMessage(message);
downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Uri uri = Uri.parse("market://details?id=" + BS_PACKAGE);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException anfe) {
// Hmm, market is not installed
Log.w(TAG, "Android Market is not installed; cannot install Barcode Scanner");
}
}
});
downloadDialog.setNegativeButton(buttonNo, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
return downloadDialog.show();
}
/**
* <p>Call this from your {@link Activity}'s
* {@link Activity#onActivityResult(int, int, Intent)} method.</p>
*
* @return null if the event handled here was not related to this class, or
* else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
* the fields will be null.
*/
public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES");
int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE);
Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation;
String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL");
return new IntentResult(contents,
formatName,
rawBytes,
orientation,
errorCorrectionLevel);
}
return new IntentResult();
}
return null;
}
/**
* Defaults to type "TEXT_TYPE".
*
* @see #shareText(CharSequence, CharSequence)
*/
public AlertDialog shareText(CharSequence text) {
return shareText(text, "TEXT_TYPE");
}
/**
* Shares the given text by encoding it as a barcode, such that another user can
* scan the text off the screen of the device.
*
* @param text the text string to encode as a barcode
* @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants.
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public AlertDialog shareText(CharSequence text, CharSequence type) {
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setAction(BS_PACKAGE + ".ENCODE");
intent.putExtra("ENCODE_TYPE", type);
intent.putExtra("ENCODE_DATA", text);
String targetAppPackage = findTargetAppPackage(intent);
if (targetAppPackage == null) {
return showDownloadDialog();
}
// intent.setPackage(targetAppPackage);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intent);
activity.startActivity(intent);
return null;
}
private static Collection<String> list(String... values) {
return Collections.unmodifiableCollection(Arrays.asList(values));
}
private void attachMoreExtras(Intent intent) {
for (Map.Entry<String, Object> entry : moreExtras.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// Kind of hacky
if (value instanceof Integer) {
intent.putExtra(key, (Integer) value);
} else if (value instanceof Long) {
intent.putExtra(key, (Long) value);
} else if (value instanceof Boolean) {
intent.putExtra(key, (Boolean) value);
} else if (value instanceof Double) {
intent.putExtra(key, (Double) value);
} else if (value instanceof Float) {
intent.putExtra(key, (Float) value);
} else if (value instanceof Bundle) {
intent.putExtra(key, (Bundle) value);
} else {
intent.putExtra(key, value.toString());
}
}
}
}
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing.integration.android;
/**
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
*
* @author Sean Owen
*/
public final class IntentResult {
private final String contents;
private final String formatName;
private final byte[] rawBytes;
private final Integer orientation;
private final String errorCorrectionLevel;
IntentResult() {
this(null, null, null, null, null);
}
IntentResult(String contents,
String formatName,
byte[] rawBytes,
Integer orientation,
String errorCorrectionLevel) {
this.contents = contents;
this.formatName = formatName;
this.rawBytes = rawBytes;
this.orientation = orientation;
this.errorCorrectionLevel = errorCorrectionLevel;
}
/**
* @return raw content of barcode
*/
public String getContents() {
return contents;
}
/**
* @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names.
*/
public String getFormatName() {
return formatName;
}
/**
* @return raw bytes of the barcode content, if applicable, or null otherwise
*/
public byte[] getRawBytes() {
return rawBytes;
}
/**
* @return rotation of the image, in degrees, which resulted in a successful scan. May be null.
*/
public Integer getOrientation() {
return orientation;
}
/**
* @return name of the error correction level used in the barcode, if applicable
*/
public String getErrorCorrectionLevel() {
return errorCorrectionLevel;
}
@Override
public String toString() {
StringBuilder dialogText = new StringBuilder(100);
dialogText.append("Format: ").append(formatName).append('\n');
dialogText.append("Contents: ").append(contents).append('\n');
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
dialogText.append("Raw bytes: (").append(rawBytesLength).append(" bytes)\n");
dialogText.append("Orientation: ").append(orientation).append('\n');
dialogText.append("EC level: ").append(errorCorrectionLevel).append('\n');
return dialogText.toString();
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class Adler32 {
// largest prime smaller than 65536
static final private int BASE = 65521;
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
static final private int NMAX = 5552;
long adler32(long adler, byte[] buf, int index, int len) {
if (buf == null) {
return 1L;
}
long s1 = adler & 0xffff;
long s2 = (adler >> 16) & 0xffff;
int k;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
s1 += buf[index++] & 0xff;
s2 += s1;
k -= 16;
}
if (k != 0) {
do {
s1 += buf[index++] & 0xff;
s2 += s1;
}
while (--k != 0);
}
s1 %= BASE;
s2 %= BASE;
}
return (s2 << 16) | s1;
}
/*
private java.util.zip.Adler32 adler=new java.util.zip.Adler32();
long adler32(long value, byte[] buf, int index, int len){
if(value==1) {adler.reset();}
if(buf==null) {adler.reset();}
else{adler.update(buf, index, len);}
return adler.getValue();
}
*/
}
ChangeLog of JZlib
====================================================================
Last modified: Thu Aug 18 16:16:06 UTC 2005
Changes since version 1.0.6:
- change: memory and performance optimizations in the inflate operation.
Many thanks to Paul Wakefield at platx.org(http://www.platx.org), who
suggested above improvements.
- change: added the nowrap argument to Z{Input,Output}?Stream.
Changes since version 1.0.5:
- ZInputStream.read(byte[], int, int) method return sometimes zero
instead of -1 at the end of stream.
- ZOutputStream.end() method should not declare IOException.
- It should be possible to call ZOutputStream.end() method more times
(because you can call close() method and after it end() method in
finally block).
- ZOutputStream.finish() method should not ignore IOException from flush().
Many thanks to Matej Kraus at seznam.cz , who pointed out above problems.
Changes since version 1.0.4:
- a minor bug fix in ZInputStream
Changes since version 1.0.3:
- fixed a bug in closing ZOutputStream.
The inflating and deflating processes were not finished successfully.
- added 'finish' and 'end' methods to ZOutputStream.java
- added 'example/test_stream_deflate_inflate.java'
Changes since version 1.0.2:
- enabled pure Java implementation of adler32 and
commented out the dependency on J2SE in Adler32.java for J2ME users.
Changes since version 1.0.1:
- fixed a bug in deflating some trivial data, for example,
large data chunk filled with zero.
- added 'version' method to JZlib class.
Changes since version 1.0.0:
- added ZInputStream and ZOutputStream classes.
- fixed a typo in LICENSE.txt.
Changes since version 0.0.9:
- fixed a bug in setting a dictionary in the inflation process.
- The license was changed to a BSD style license.
- Z{Input,Output}Stream classes were deleted.
Changes since version 0.0.8:
- fixed a bug in handling a preset dictionary in the inflation process.
Changes since version 0.0.7:
- added methods to control the window size (the size of the history
buffer) and to handle the no-wrap option (no zlib header or check),
which is the undocumented functionality of zlib.
Changes since version 0.0.6:
- updated InfBlocks.java as zlib did to fix the vulnerability related to
the 'double free'. Of course, JZlib is free from such a vulnerability
like the 'double free', but JZlib had crashed with NullPointerException
by a specially-crafted block of invalid deflated data.
Changes since version 0.0.5:
- added 'flush()' method to com.jcraft.jzlib.ZOutputStream.
- fixed to take care when occurring the buffer overflow in
com.jcraft.jzlib.ZOutputStream.
Many thanks to Tim Bendfelt at cs.wisc.edu , who pointed out above problems.
Changes since version 0.0.4:
............................
- fixed a bug in Adler32 class.
- fixed a bug in ZInputStream class
- modified ZInputStream to be extended from InputStream
instead of FileInputStream.
- modified ZOutputStream to be extended from OutputStream
instead of FileOutputStream.
- modified ZStream to be changeable wbits. Give wbits value to
the method 'deflateInit' of ZStream.
Many thanks to Bryan Keller<keller@neomar.com>, who reported bugs
and made suggestions.
Changes since version 0.0.3:
............................
- fixed a bug in the compression level 0.
- modified to be compatible with JIKES's bug.
- added Z[Input,Output]Stream written by Lapo Luchini<lapo@lapo.it>.
Changes since version 0.0.2:
............................
- fixed a critical bug, which had arisen in the deflating operation with
NO_FLUSH and DEFAULT_COMPRESSION mode.
Many thanks to Bryan Keller(keller@neomar.com), who reported this glitch.
Changes since version 0.0.1:
............................
- fixed the bad compression ratio problem, which is reported from
Martin Smith(martin@spamcop.net). The compression ratio was not so good
compared with the compression ration of zlib. Now, this problem has been
fixed and, I hope, that deflated files by JZlib and zlib are completely
same bit by bit.
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
public
final class Deflate {
static final private int MAX_MEM_LEVEL = 9;
static final private int Z_DEFAULT_COMPRESSION = -1;
static final private int MAX_WBITS = 15; // 32K LZ77 window
static final private int DEF_MEM_LEVEL = 8;
static class Config {
int good_length; // reduce lazy search above this match length
int max_lazy; // do not perform lazy search above this match length
int nice_length; // quit search above this match length
int max_chain;
int func;
Config(int good_length, int max_lazy,
int nice_length, int max_chain, int func) {
this.good_length = good_length;
this.max_lazy = max_lazy;
this.nice_length = nice_length;
this.max_chain = max_chain;
this.func = func;
}
}
static final private int STORED = 0;
static final private int FAST = 1;
static final private int SLOW = 2;
static final private Config[] config_table;
static {
config_table = new Config[10];
// good lazy nice chain
config_table[0] = new Config(0, 0, 0, 0, STORED);
config_table[1] = new Config(4, 4, 8, 4, FAST);
config_table[2] = new Config(4, 5, 16, 8, FAST);
config_table[3] = new Config(4, 6, 32, 32, FAST);
config_table[4] = new Config(4, 4, 16, 16, SLOW);
config_table[5] = new Config(8, 16, 32, 32, SLOW);
config_table[6] = new Config(8, 16, 128, 128, SLOW);
config_table[7] = new Config(8, 32, 128, 256, SLOW);
config_table[8] = new Config(32, 128, 258, 1024, SLOW);
config_table[9] = new Config(32, 258, 258, 4096, SLOW);
}
static final private String[] z_errmsg = {
"need dictionary", // Z_NEED_DICT 2
"stream end", // Z_STREAM_END 1
"", // Z_OK 0
"file error", // Z_ERRNO (-1)
"stream error", // Z_STREAM_ERROR (-2)
"data error", // Z_DATA_ERROR (-3)
"insufficient memory", // Z_MEM_ERROR (-4)
"buffer error", // Z_BUF_ERROR (-5)
"incompatible version",// Z_VERSION_ERROR (-6)
""
};
// block not completed, need more input or more output
static final private int NeedMore = 0;
// block flush performed
static final private int BlockDone = 1;
// finish started, need only more output at next deflate
static final private int FinishStarted = 2;
// finish done, accept no more input or output
static final private int FinishDone = 3;
// preset dictionary flag in zlib header
static final private int PRESET_DICT = 0x20;
static final private int Z_FILTERED = 1;
static final private int Z_HUFFMAN_ONLY = 2;
static final private int Z_DEFAULT_STRATEGY = 0;
static final private int Z_NO_FLUSH = 0;
static final private int Z_PARTIAL_FLUSH = 1;
static final private int Z_SYNC_FLUSH = 2;
static final private int Z_FULL_FLUSH = 3;
static final private int Z_FINISH = 4;
static final private int Z_OK = 0;
static final private int Z_STREAM_END = 1;
static final private int Z_NEED_DICT = 2;
static final private int Z_ERRNO = -1;
static final private int Z_STREAM_ERROR = -2;
static final private int Z_DATA_ERROR = -3;
static final private int Z_MEM_ERROR = -4;
static final private int Z_BUF_ERROR = -5;
static final private int Z_VERSION_ERROR = -6;
static final private int INIT_STATE = 42;
static final private int BUSY_STATE = 113;
static final private int FINISH_STATE = 666;
// The deflate compression method
static final private int Z_DEFLATED = 8;
static final private int STORED_BLOCK = 0;
static final private int STATIC_TREES = 1;
static final private int DYN_TREES = 2;
// The three kinds of block type
static final private int Z_BINARY = 0;
static final private int Z_ASCII = 1;
static final private int Z_UNKNOWN = 2;
static final private int Buf_size = 8 * 2;
// repeat previous bit length 3-6 times (2 bits of repeat count)
static final private int REP_3_6 = 16;
// repeat a zero length 3-10 times (3 bits of repeat count)
static final private int REPZ_3_10 = 17;
// repeat a zero length 11-138 times (7 bits of repeat count)
static final private int REPZ_11_138 = 18;
static final private int MIN_MATCH = 3;
static final private int MAX_MATCH = 258;
static final private int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
static final private int MAX_BITS = 15;
static final private int D_CODES = 30;
static final private int BL_CODES = 19;
static final private int LENGTH_CODES = 29;
static final private int LITERALS = 256;
static final private int L_CODES = (LITERALS + 1 + LENGTH_CODES);
static final private int HEAP_SIZE = (2 * L_CODES + 1);
static final private int END_BLOCK = 256;
ZStream strm; // pointer back to this zlib stream
int status; // as the name implies
byte[] pending_buf; // output still pending
int pending_buf_size; // size of pending_buf
int pending_out; // next pending byte to output to the stream
int pending; // nb of bytes in the pending buffer
int noheader; // suppress zlib header and adler32
byte data_type; // UNKNOWN, BINARY or ASCII
byte method; // STORED (for zip only) or DEFLATED
int last_flush; // value of flush param for previous deflate call
int w_size; // LZ77 window size (32K by default)
int w_bits; // log2(w_size) (8..16)
int w_mask; // w_size - 1
byte[] window;
// Sliding window. Input bytes are read into the second half of the window,
// and move to the first half later to keep a dictionary of at least wSize
// bytes. With this organization, matches are limited to a distance of
// wSize-MAX_MATCH bytes, but this ensures that IO is always
// performed with a length multiple of the block size. Also, it limits
// the window size to 64K, which is quite useful on MSDOS.
// To do: use the user input buffer as sliding window.
int window_size;
// Actual size of window: 2*wSize, except when the user input buffer
// is directly used as sliding window.
short[] prev;
// Link to older string with same hash index. To limit the size of this
// array to 64K, this link is maintained only for the last 32K strings.
// An index in this array is thus a window index modulo 32K.
short[] head; // Heads of the hash chains or NIL.
int ins_h; // hash index of string to be inserted
int hash_size; // number of elements in hash table
int hash_bits; // log2(hash_size)
int hash_mask; // hash_size-1
// Number of bits by which ins_h must be shifted at each input
// step. It must be such that after MIN_MATCH steps, the oldest
// byte no longer takes part in the hash key, that is:
// hash_shift * MIN_MATCH >= hash_bits
int hash_shift;
// Window position at the beginning of the current output block. Gets
// negative when the window is moved backwards.
int block_start;
int match_length; // length of best match
int prev_match; // previous match
int match_available; // set if previous match exists
int strstart; // start of string to insert
int match_start; // start of matching string
int lookahead; // number of valid bytes ahead in window
// Length of the best match at previous step. Matches not greater than this
// are discarded. This is used in the lazy match evaluation.
int prev_length;
// To speed up deflation, hash chains are never searched beyond this
// length. A higher limit improves compression ratio but degrades the speed.
int max_chain_length;
// Attempt to find a better match only when the current match is strictly
// smaller than this value. This mechanism is used only for compression
// levels >= 4.
int max_lazy_match;
// Insert new strings in the hash table only if the match length is not
// greater than this length. This saves time but degrades compression.
// max_insert_length is used only for compression levels <= 3.
int level; // compression level (1..9)
int strategy; // favor or force Huffman coding
// Use a faster search when the previous match is longer than this
int good_match;
// Stop searching when current match exceeds this
int nice_match;
short[] dyn_ltree; // literal and length tree
short[] dyn_dtree; // distance tree
short[] bl_tree; // Huffman tree for bit lengths
Tree l_desc = new Tree(); // desc for literal tree
Tree d_desc = new Tree(); // desc for distance tree
Tree bl_desc = new Tree(); // desc for bit length tree
// number of codes at each bit length for an optimal tree
short[] bl_count = new short[MAX_BITS + 1];
// heap used to build the Huffman trees
int[] heap = new int[2 * L_CODES + 1];
int heap_len; // number of elements in the heap
int heap_max; // element of largest frequency
// The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
// The same heap array is used to build all trees.
// Depth of each subtree used as tie breaker for trees of equal frequency
byte[] depth = new byte[2 * L_CODES + 1];
int l_buf; // index for literals or lengths */
// Size of match buffer for literals/lengths. There are 4 reasons for
// limiting lit_bufsize to 64K:
// - frequencies can be kept in 16 bit counters
// - if compression is not successful for the first block, all input
// data is still in the window so we can still emit a stored block even
// when input comes from standard input. (This can also be done for
// all blocks if lit_bufsize is not greater than 32K.)
// - if compression is not successful for a file smaller than 64K, we can
// even emit a stored file instead of a stored block (saving 5 bytes).
// This is applicable only for zip (not gzip or zlib).
// - creating new Huffman trees less frequently may not provide fast
// adaptation to changes in the input data statistics. (Take for
// example a binary file with poorly compressible code followed by
// a highly compressible string table.) Smaller buffer sizes give
// fast adaptation but have of course the overhead of transmitting
// trees more frequently.
// - I can't count above 4
int lit_bufsize;
int last_lit; // running index in l_buf
// Buffer for distances. To simplify the code, d_buf and l_buf have
// the same number of elements. To use different lengths, an extra flag
// array would be necessary.
int d_buf; // index of pendig_buf
int opt_len; // bit length of current block with optimal trees
int static_len; // bit length of current block with static trees
int matches; // number of string matches in current block
int last_eob_len; // bit length of EOB code for last block
// Output buffer. bits are inserted starting at the bottom (least
// significant bits).
short bi_buf;
// Number of valid bits in bi_buf. All bits above the last valid bit
// are always zero.
int bi_valid;
Deflate() {
dyn_ltree = new short[HEAP_SIZE * 2];
dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
}
void lm_init() {
window_size = 2 * w_size;
head[hash_size - 1] = 0;
for (int i = 0; i < hash_size - 1; i++) {
head[i] = 0;
}
// Set the default configuration parameters:
max_lazy_match = Deflate.config_table[level].max_lazy;
good_match = Deflate.config_table[level].good_length;
nice_match = Deflate.config_table[level].nice_length;
max_chain_length = Deflate.config_table[level].max_chain;
strstart = 0;
block_start = 0;
lookahead = 0;
match_length = prev_length = MIN_MATCH - 1;
match_available = 0;
ins_h = 0;
}
// Initialize the tree data structures for a new zlib stream.
void tr_init() {
l_desc.dyn_tree = dyn_ltree;
l_desc.stat_desc = StaticTree.static_l_desc;
d_desc.dyn_tree = dyn_dtree;
d_desc.stat_desc = StaticTree.static_d_desc;
bl_desc.dyn_tree = bl_tree;
bl_desc.stat_desc = StaticTree.static_bl_desc;
bi_buf = 0;
bi_valid = 0;
last_eob_len = 8; // enough lookahead for inflate
// Initialize the first block of the first file:
init_block();
}
void init_block() {
// Initialize the trees.
for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
dyn_ltree[END_BLOCK * 2] = 1;
opt_len = static_len = 0;
last_lit = matches = 0;
}
// Restore the heap property by moving down the tree starting at node k,
// exchanging a node with the smallest of its two sons if necessary, stopping
// when the heap property is re-established (each father smaller than its
// two sons).
void pqdownheap(short[] tree, // the tree to restore
int k // node to move down
) {
int v = heap[k];
int j = k << 1; // left son of k
while (j <= heap_len) {
// Set j to the smallest of the two sons:
if (j < heap_len &&
smaller(tree, heap[j + 1], heap[j], depth)) {
j++;
}
// Exit if v is smaller than both sons
if (smaller(tree, v, heap[j], depth)) break;
// Exchange v with the smallest son
heap[k] = heap[j];
k = j;
// And continue down the tree, setting j to the left son of k
j <<= 1;
}
heap[k] = v;
}
static boolean smaller(short[] tree, int n, int m, byte[] depth) {
short tn2 = tree[n * 2];
short tm2 = tree[m * 2];
return (tn2 < tm2 ||
(tn2 == tm2 && depth[n] <= depth[m]));
}
// Scan a literal or distance tree to determine the frequencies of the codes
// in the bit length tree.
void scan_tree(short[] tree,// the tree to be scanned
int max_code // and its largest code of non zero frequency
) {
int n; // iterates over all tree elements
int prevlen = -1; // last emitted length
int curlen; // length of current code
int nextlen = tree[0 * 2 + 1]; // length of next code
int count = 0; // repeat count of the current code
int max_count = 7; // max repeat count
int min_count = 4; // min repeat count
if (nextlen == 0) {
max_count = 138;
min_count = 3;
}
tree[(max_code + 1) * 2 + 1] = (short) 0xffff; // guard
for (n = 0; n <= max_code; n++) {
curlen = nextlen;
nextlen = tree[(n + 1) * 2 + 1];
if (++count < max_count && curlen == nextlen) {
continue;
} else if (count < min_count) {
bl_tree[curlen * 2] += count;
} else if (curlen != 0) {
if (curlen != prevlen) bl_tree[curlen * 2]++;
bl_tree[REP_3_6 * 2]++;
} else if (count <= 10) {
bl_tree[REPZ_3_10 * 2]++;
} else {
bl_tree[REPZ_11_138 * 2]++;
}
count = 0;
prevlen = curlen;
if (nextlen == 0) {
max_count = 138;
min_count = 3;
} else if (curlen == nextlen) {
max_count = 6;
min_count = 3;
} else {
max_count = 7;
min_count = 4;
}
}
}
// Construct the Huffman tree for the bit lengths and return the index in
// bl_order of the last bit length code to send.
int build_bl_tree() {
int max_blindex; // index of last bit length code of non zero freq
// Determine the bit length frequencies for literal and distance trees
scan_tree(dyn_ltree, l_desc.max_code);
scan_tree(dyn_dtree, d_desc.max_code);
// Build the bit length tree:
bl_desc.build_tree(this);
// opt_len now includes the length of the tree representations, except
// the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
// Determine the number of bit length codes to send. The pkzip format
// requires that at least 4 bit length codes be sent. (appnote.txt says
// 3 but the actual value used is 4.)
for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] != 0) break;
}
// Update opt_len to include the bit length tree and counts
opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
return max_blindex;
}
// Send the header for a block using dynamic Huffman trees: the counts, the
// lengths of the bit length codes, the literal tree and the distance tree.
// IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
void send_all_trees(int lcodes, int dcodes, int blcodes) {
int rank; // index in bl_order
send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
send_bits(dcodes - 1, 5);
send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
for (rank = 0; rank < blcodes; rank++) {
send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
}
send_tree(dyn_ltree, lcodes - 1); // literal tree
send_tree(dyn_dtree, dcodes - 1); // distance tree
}
// Send a literal or distance tree in compressed form, using the codes in
// bl_tree.
void send_tree(short[] tree,// the tree to be sent
int max_code // and its largest code of non zero frequency
) {
int n; // iterates over all tree elements
int prevlen = -1; // last emitted length
int curlen; // length of current code
int nextlen = tree[0 * 2 + 1]; // length of next code
int count = 0; // repeat count of the current code
int max_count = 7; // max repeat count
int min_count = 4; // min repeat count
if (nextlen == 0) {
max_count = 138;
min_count = 3;
}
for (n = 0; n <= max_code; n++) {
curlen = nextlen;
nextlen = tree[(n + 1) * 2 + 1];
if (++count < max_count && curlen == nextlen) {
continue;
} else if (count < min_count) {
do {
send_code(curlen, bl_tree);
} while (--count != 0);
} else if (curlen != 0) {
if (curlen != prevlen) {
send_code(curlen, bl_tree);
count--;
}
send_code(REP_3_6, bl_tree);
send_bits(count - 3, 2);
} else if (count <= 10) {
send_code(REPZ_3_10, bl_tree);
send_bits(count - 3, 3);
} else {
send_code(REPZ_11_138, bl_tree);
send_bits(count - 11, 7);
}
count = 0;
prevlen = curlen;
if (nextlen == 0) {
max_count = 138;
min_count = 3;
} else if (curlen == nextlen) {
max_count = 6;
min_count = 3;
} else {
max_count = 7;
min_count = 4;
}
}
}
// Output a byte on the stream.
// IN assertion: there is enough room in pending_buf.
final void put_byte(byte[] p, int start, int len) {
System.arraycopy(p, start, pending_buf, pending, len);
pending += len;
}
final void put_byte(byte c) {
pending_buf[pending++] = c;
}
final void put_short(int w) {
put_byte((byte) (w/*&0xff*/));
put_byte((byte) (w >>> 8));
}
final void putShortMSB(int b) {
put_byte((byte) (b >> 8));
put_byte((byte) (b/*&0xff*/));
}
final void send_code(int c, short[] tree) {
int c2 = c * 2;
send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
}
void send_bits(int value, int length) {
int len = length;
if (bi_valid > (int) Buf_size - len) {
int val = value;
// bi_buf |= (val << bi_valid);
bi_buf |= ((val << bi_valid) & 0xffff);
put_short(bi_buf);
bi_buf = (short) (val >>> (Buf_size - bi_valid));
bi_valid += len - Buf_size;
} else {
// bi_buf |= (value) << bi_valid;
bi_buf |= (((value) << bi_valid) & 0xffff);
bi_valid += len;
}
}
// Send one empty static block to give enough lookahead for inflate.
// This takes 10 bits, of which 7 may remain in the bit buffer.
// The current inflate code requires 9 bits of lookahead. If the
// last two codes for the previous block (real code plus EOB) were coded
// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
// the last real code. In this case we send two empty static blocks instead
// of one. (There are no problems if the previous block is stored or fixed.)
// To simplify the code, we assume the worst case of last real code encoded
// on one bit only.
void _tr_align() {
send_bits(STATIC_TREES << 1, 3);
send_code(END_BLOCK, StaticTree.static_ltree);
bi_flush();
// Of the 10 bits for the empty block, we have already sent
// (10 - bi_valid) bits. The lookahead for the last real code (before
// the EOB of the previous block) was thus at least one plus the length
// of the EOB plus what we have just sent of the empty static block.
if (1 + last_eob_len + 10 - bi_valid < 9) {
send_bits(STATIC_TREES << 1, 3);
send_code(END_BLOCK, StaticTree.static_ltree);
bi_flush();
}
last_eob_len = 7;
}
// Save the match info and tally the frequency counts. Return true if
// the current block must be flushed.
boolean _tr_tally(int dist, // distance of matched string
int lc // match length-MIN_MATCH or unmatched char (if dist==0)
) {
pending_buf[d_buf + last_lit * 2] = (byte) (dist >>> 8);
pending_buf[d_buf + last_lit * 2 + 1] = (byte) dist;
pending_buf[l_buf + last_lit] = (byte) lc;
last_lit++;
if (dist == 0) {
// lc is the unmatched char
dyn_ltree[lc * 2]++;
} else {
matches++;
// Here, lc is the match length - MIN_MATCH
dist--; // dist = match distance - 1
dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
dyn_dtree[Tree.d_code(dist) * 2]++;
}
if ((last_lit & 0x1fff) == 0 && level > 2) {
// Compute an upper bound for the compressed length
int out_length = last_lit * 8;
int in_length = strstart - block_start;
int dcode;
for (dcode = 0; dcode < D_CODES; dcode++) {
out_length += (int) dyn_dtree[dcode * 2] *
(5L + Tree.extra_dbits[dcode]);
}
out_length >>>= 3;
if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
}
return (last_lit == lit_bufsize - 1);
// We avoid equality with lit_bufsize because of wraparound at 64K
// on 16 bit machines and because stored blocks are restricted to
// 64K-1 bytes.
}
// Send the block data compressed using the given Huffman trees
void compress_block(short[] ltree, short[] dtree) {
int dist; // distance of matched string
int lc; // match length or unmatched char (if dist == 0)
int lx = 0; // running index in l_buf
int code; // the code to send
int extra; // number of extra bits to send
if (last_lit != 0) {
do {
dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
(pending_buf[d_buf + lx * 2 + 1] & 0xff);
lc = (pending_buf[l_buf + lx]) & 0xff;
lx++;
if (dist == 0) {
send_code(lc, ltree); // send a literal byte
} else {
// Here, lc is the match length - MIN_MATCH
code = Tree._length_code[lc];
send_code(code + LITERALS + 1, ltree); // send the length code
extra = Tree.extra_lbits[code];
if (extra != 0) {
lc -= Tree.base_length[code];
send_bits(lc, extra); // send the extra length bits
}
dist--; // dist is now the match distance - 1
code = Tree.d_code(dist);
send_code(code, dtree); // send the distance code
extra = Tree.extra_dbits[code];
if (extra != 0) {
dist -= Tree.base_dist[code];
send_bits(dist, extra); // send the extra distance bits
}
} // literal or match pair ?
// Check that the overlay between pending_buf and d_buf+l_buf is ok:
}
while (lx < last_lit);
}
send_code(END_BLOCK, ltree);
last_eob_len = ltree[END_BLOCK * 2 + 1];
}
// Set the data type to ASCII or BINARY, using a crude approximation:
// binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
// IN assertion: the fields freq of dyn_ltree are set and the total of all
// frequencies does not exceed 64K (to fit in an int on 16 bit machines).
void set_data_type() {
int n = 0;
int ascii_freq = 0;
int bin_freq = 0;
while (n < 7) {
bin_freq += dyn_ltree[n * 2];
n++;
}
while (n < 128) {
ascii_freq += dyn_ltree[n * 2];
n++;
}
while (n < LITERALS) {
bin_freq += dyn_ltree[n * 2];
n++;
}
data_type = (byte) (bin_freq > (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII);
}
// Flush the bit buffer, keeping at most 7 bits in it.
void bi_flush() {
if (bi_valid == 16) {
put_short(bi_buf);
bi_buf = 0;
bi_valid = 0;
} else if (bi_valid >= 8) {
put_byte((byte) bi_buf);
bi_buf >>>= 8;
bi_valid -= 8;
}
}
// Flush the bit buffer and align the output on a byte boundary
void bi_windup() {
if (bi_valid > 8) {
put_short(bi_buf);
} else if (bi_valid > 0) {
put_byte((byte) bi_buf);
}
bi_buf = 0;
bi_valid = 0;
}
// Copy a stored block, storing first the length and its
// one's complement if requested.
void copy_block(int buf, // the input data
int len, // its length
boolean header // true if block header must be written
) {
int index = 0;
bi_windup(); // align on byte boundary
last_eob_len = 8; // enough lookahead for inflate
if (header) {
put_short((short) len);
put_short((short) ~len);
}
// while(len--!=0) {
// put_byte(window[buf+index]);
// index++;
// }
put_byte(window, buf, len);
}
void flush_block_only(boolean eof) {
_tr_flush_block(block_start >= 0 ? block_start : -1,
strstart - block_start,
eof);
block_start = strstart;
strm.flush_pending();
}
// Copy without compression as much as possible from the input stream, return
// the current block state.
// This function does not insert new strings in the dictionary since
// uncompressible data is probably not useful. This function is used
// only for the level=0 compression option.
// NOTE: this function should be optimized to avoid extra copying from
// window to pending_buf.
int deflate_stored(int flush) {
// Stored blocks are limited to 0xffff bytes, pending_buf is limited
// to pending_buf_size, and each stored block has a 5 byte header:
int max_block_size = 0xffff;
int max_start;
if (max_block_size > pending_buf_size - 5) {
max_block_size = pending_buf_size - 5;
}
// Copy as much as possible from input to output:
while (true) {
// Fill the window as much as possible:
if (lookahead <= 1) {
fill_window();
if (lookahead == 0 && flush == Z_NO_FLUSH) return NeedMore;
if (lookahead == 0) break; // flush the current block
}
strstart += lookahead;
lookahead = 0;
// Emit a stored block if pending_buf will be full:
max_start = block_start + max_block_size;
if (strstart == 0 || strstart >= max_start) {
// strstart == 0 is possible when wraparound on 16-bit machine
lookahead = (int) (strstart - max_start);
strstart = (int) max_start;
flush_block_only(false);
if (strm.avail_out == 0) return NeedMore;
}
// Flush if we may have to slide, otherwise block_start may become
// negative and the data will be gone:
if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
flush_block_only(false);
if (strm.avail_out == 0) return NeedMore;
}
}
flush_block_only(flush == Z_FINISH);
if (strm.avail_out == 0)
return (flush == Z_FINISH) ? FinishStarted : NeedMore;
return flush == Z_FINISH ? FinishDone : BlockDone;
}
// Send a stored block
void _tr_stored_block(int buf, // input block
int stored_len, // length of input block
boolean eof // true if this is the last block for a file
) {
send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
copy_block(buf, stored_len, true); // with header
}
// Determine the best encoding for the current block: dynamic trees, static
// trees or store, and output the encoded block to the zip file.
void _tr_flush_block(int buf, // input block, or NULL if too old
int stored_len, // length of input block
boolean eof // true if this is the last block for a file
) {
int opt_lenb, static_lenb;// opt_len and static_len in bytes
int max_blindex = 0; // index of last bit length code of non zero freq
// Build the Huffman trees unless a stored block is forced
if (level > 0) {
// Check if the file is ascii or binary
if (data_type == Z_UNKNOWN) set_data_type();
// Construct the literal and distance trees
l_desc.build_tree(this);
d_desc.build_tree(this);
// At this point, opt_len and static_len are the total bit lengths of
// the compressed block data, excluding the tree representations.
// Build the bit length tree for the above two trees, and get the index
// in bl_order of the last bit length code to send.
max_blindex = build_bl_tree();
// Determine the best encoding. Compute first the block length in bytes
opt_lenb = (opt_len + 3 + 7) >>> 3;
static_lenb = (static_len + 3 + 7) >>> 3;
if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
} else {
opt_lenb = static_lenb = stored_len + 5; // force a stored block
}
if (stored_len + 4 <= opt_lenb && buf != -1) {
// 4: two words for the lengths
// The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
// Otherwise we can't have processed more than WSIZE input bytes since
// the last block flush, because compression would have been
// successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
// transform a block into a stored block.
_tr_stored_block(buf, stored_len, eof);
} else if (static_lenb == opt_lenb) {
send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
} else {
send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
compress_block(dyn_ltree, dyn_dtree);
}
// The above check is made mod 2^32, for files larger than 512 MB
// and uLong implemented on 32 bits.
init_block();
if (eof) {
bi_windup();
}
}
// Fill the window when the lookahead becomes insufficient.
// Updates strstart and lookahead.
//
// IN assertion: lookahead < MIN_LOOKAHEAD
// OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
// At least one byte has been read, or avail_in == 0; reads are
// performed for at least two bytes (required for the zip translate_eol
// option -- not supported here).
void fill_window() {
int n, m;
int p;
int more; // Amount of free space at the end of the window.
do {
more = (window_size - lookahead - strstart);
// Deal with !@#$% 64K limit:
if (more == 0 && strstart == 0 && lookahead == 0) {
more = w_size;
} else if (more == -1) {
// Very unlikely, but possible on 16 bit machine if strstart == 0
// and lookahead == 1 (input done one byte at time)
more--;
// If the window is almost full and there is insufficient lookahead,
// move the upper half to the lower one to make room in the upper half.
} else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
System.arraycopy(window, w_size, window, 0, w_size);
match_start -= w_size;
strstart -= w_size; // we now have strstart >= MAX_DIST
block_start -= w_size;
// Slide the hash table (could be avoided with 32 bit values
// at the expense of memory usage). We slide even when level == 0
// to keep the hash table consistent if we switch back to level > 0
// later. (Using level 0 permanently is not an optimal usage of
// zlib, so we don't care about this pathological case.)
n = hash_size;
p = n;
do {
m = (head[--p] & 0xffff);
head[p] = (m >= w_size ? (short) (m - w_size) : 0);
}
while (--n != 0);
n = w_size;
p = n;
do {
m = (prev[--p] & 0xffff);
prev[p] = (m >= w_size ? (short) (m - w_size) : 0);
// If n is not on any hash chain, prev[n] is garbage but
// its value will never be used.
}
while (--n != 0);
more += w_size;
}
if (strm.avail_in == 0) return;
// If there was no sliding:
// strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
// more == window_size - lookahead - strstart
// => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
// => more >= window_size - 2*WSIZE + 2
// In the BIG_MEM or MMAP case (not yet supported),
// window_size == input_size + MIN_LOOKAHEAD &&
// strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
// Otherwise, window_size == 2*WSIZE so more >= 2.
// If there was sliding, more >= WSIZE. So in all cases, more >= 2.
n = strm.read_buf(window, strstart + lookahead, more);
lookahead += n;
// Initialize the hash value now that we have some input:
if (lookahead >= MIN_MATCH) {
ins_h = window[strstart] & 0xff;
ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
}
// If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
// but this is not important since only literal bytes will be emitted.
}
while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0);
}
// Compress as much as possible from the input stream, return the current
// block state.
// This function does not perform lazy evaluation of matches and inserts
// new strings in the dictionary only for unmatched strings or for short
// matches. It is used only for the fast compression options.
int deflate_fast(int flush) {
// short hash_head = 0; // head of the hash chain
int hash_head = 0; // head of the hash chain
boolean bflush; // set if current block must be flushed
while (true) {
// Make sure that we always have enough lookahead, except
// at the end of the input file. We need MAX_MATCH bytes
// for the next match, plus MIN_MATCH bytes to insert the
// string following the next match.
if (lookahead < MIN_LOOKAHEAD) {
fill_window();
if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
return NeedMore;
}
if (lookahead == 0) break; // flush the current block
}
// Insert the string window[strstart .. strstart+2] in the
// dictionary, and set hash_head to the head of the hash chain:
if (lookahead >= MIN_MATCH) {
ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
// prev[strstart&w_mask]=hash_head=head[ins_h];
hash_head = (head[ins_h] & 0xffff);
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = (short) strstart;
}
// Find the longest match, discarding those <= prev_length.
// At this point we have always match_length < MIN_MATCH
if (hash_head != 0L &&
((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD
) {
// To simplify the code, we prevent matches with the string
// of window index 0 (in particular we have to avoid a match
// of the string with itself at the start of the input file).
if (strategy != Z_HUFFMAN_ONLY) {
match_length = longest_match(hash_head);
}
// longest_match() sets match_start
}
if (match_length >= MIN_MATCH) {
// check_match(strstart, match_start, match_length);
bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
lookahead -= match_length;
// Insert new strings in the hash table only if the match length
// is not too large. This saves time but degrades compression.
if (match_length <= max_lazy_match &&
lookahead >= MIN_MATCH) {
match_length--; // string at strstart already in hash table
do {
strstart++;
ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
// prev[strstart&w_mask]=hash_head=head[ins_h];
hash_head = (head[ins_h] & 0xffff);
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = (short) strstart;
// strstart never exceeds WSIZE-MAX_MATCH, so there are
// always MIN_MATCH bytes ahead.
}
while (--match_length != 0);
strstart++;
} else {
strstart += match_length;
match_length = 0;
ins_h = window[strstart] & 0xff;
ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
// If lookahead < MIN_MATCH, ins_h is garbage, but it does not
// matter since it will be recomputed at next deflate call.
}
} else {
// No match, output a literal byte
bflush = _tr_tally(0, window[strstart] & 0xff);
lookahead--;
strstart++;
}
if (bflush) {
flush_block_only(false);
if (strm.avail_out == 0) return NeedMore;
}
}
flush_block_only(flush == Z_FINISH);
if (strm.avail_out == 0) {
if (flush == Z_FINISH) return FinishStarted;
else return NeedMore;
}
return flush == Z_FINISH ? FinishDone : BlockDone;
}
// Same as above, but achieves better compression. We use a lazy
// evaluation for matches: a match is finally adopted only if there is
// no better match at the next window position.
int deflate_slow(int flush) {
// short hash_head = 0; // head of hash chain
int hash_head = 0; // head of hash chain
boolean bflush; // set if current block must be flushed
// Process the input block.
while (true) {
// Make sure that we always have enough lookahead, except
// at the end of the input file. We need MAX_MATCH bytes
// for the next match, plus MIN_MATCH bytes to insert the
// string following the next match.
if (lookahead < MIN_LOOKAHEAD) {
fill_window();
if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
return NeedMore;
}
if (lookahead == 0) break; // flush the current block
}
// Insert the string window[strstart .. strstart+2] in the
// dictionary, and set hash_head to the head of the hash chain:
if (lookahead >= MIN_MATCH) {
ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
// prev[strstart&w_mask]=hash_head=head[ins_h];
hash_head = (head[ins_h] & 0xffff);
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = (short) strstart;
}
// Find the longest match, discarding those <= prev_length.
prev_length = match_length;
prev_match = match_start;
match_length = MIN_MATCH - 1;
if (hash_head != 0 && prev_length < max_lazy_match &&
((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD
) {
// To simplify the code, we prevent matches with the string
// of window index 0 (in particular we have to avoid a match
// of the string with itself at the start of the input file).
if (strategy != Z_HUFFMAN_ONLY) {
match_length = longest_match(hash_head);
}
// longest_match() sets match_start
if (match_length <= 5 && (strategy == Z_FILTERED ||
(match_length == MIN_MATCH &&
strstart - match_start > 4096))) {
// If prev_match is also MIN_MATCH, match_start is garbage
// but we will ignore the current match anyway.
match_length = MIN_MATCH - 1;
}
}
// If there was a match at the previous step and the current
// match is not better, output the previous match:
if (prev_length >= MIN_MATCH && match_length <= prev_length) {
int max_insert = strstart + lookahead - MIN_MATCH;
// Do not insert strings in hash table beyond this.
// check_match(strstart-1, prev_match, prev_length);
bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
// Insert in hash table all strings up to the end of the match.
// strstart-1 and strstart are already inserted. If there is not
// enough lookahead, the last two strings are not inserted in
// the hash table.
lookahead -= prev_length - 1;
prev_length -= 2;
do {
if (++strstart <= max_insert) {
ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
//prev[strstart&w_mask]=hash_head=head[ins_h];
hash_head = (head[ins_h] & 0xffff);
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = (short) strstart;
}
}
while (--prev_length != 0);
match_available = 0;
match_length = MIN_MATCH - 1;
strstart++;
if (bflush) {
flush_block_only(false);
if (strm.avail_out == 0) return NeedMore;
}
} else if (match_available != 0) {
// If there was no match at the previous position, output a
// single literal. If there was a match but the current match
// is longer, truncate the previous match to a single literal.
bflush = _tr_tally(0, window[strstart - 1] & 0xff);
if (bflush) {
flush_block_only(false);
}
strstart++;
lookahead--;
if (strm.avail_out == 0) return NeedMore;
} else {
// There is no previous match to compare with, wait for
// the next step to decide.
match_available = 1;
strstart++;
lookahead--;
}
}
if (match_available != 0) {
bflush = _tr_tally(0, window[strstart - 1] & 0xff);
match_available = 0;
}
flush_block_only(flush == Z_FINISH);
if (strm.avail_out == 0) {
if (flush == Z_FINISH) return FinishStarted;
else return NeedMore;
}
return flush == Z_FINISH ? FinishDone : BlockDone;
}
int longest_match(int cur_match) {
int chain_length = max_chain_length; // max hash chain length
int scan = strstart; // current string
int match; // matched string
int len; // length of current match
int best_len = prev_length; // best match length so far
int limit = strstart > (w_size - MIN_LOOKAHEAD) ?
strstart - (w_size - MIN_LOOKAHEAD) : 0;
int nice_match = this.nice_match;
// Stop when cur_match becomes <= limit. To simplify the code,
// we prevent matches with the string of window index 0.
int wmask = w_mask;
int strend = strstart + MAX_MATCH;
byte scan_end1 = window[scan + best_len - 1];
byte scan_end = window[scan + best_len];
// The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
// It is easy to get rid of this optimization if necessary.
// Do not waste too much time if we already have a good match:
if (prev_length >= good_match) {
chain_length >>= 2;
}
// Do not look for matches beyond the end of the input. This is necessary
// to make deflate deterministic.
if (nice_match > lookahead) nice_match = lookahead;
do {
match = cur_match;
// Skip to next match if the match length cannot increase
// or if the match length is less than 2:
if (window[match + best_len] != scan_end ||
window[match + best_len - 1] != scan_end1 ||
window[match] != window[scan] ||
window[++match] != window[scan + 1]) continue;
// The check at best_len-1 can be removed because it will be made
// again later. (This heuristic is not always a win.)
// It is not necessary to compare scan[2] and match[2] since they
// are always equal when the other bytes match, given that
// the hash keys are equal and that HASH_BITS >= 8.
scan += 2;
match++;
// We check for insufficient lookahead only every 8th comparison;
// the 256th check will be made at strstart+258.
do {
} while (window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
scan < strend);
len = MAX_MATCH - (int) (strend - scan);
scan = strend - MAX_MATCH;
if (len > best_len) {
match_start = cur_match;
best_len = len;
if (len >= nice_match) break;
scan_end1 = window[scan + best_len - 1];
scan_end = window[scan + best_len];
}
} while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit
&& --chain_length != 0);
if (best_len <= lookahead) return best_len;
return lookahead;
}
int deflateInit(ZStream strm, int level, int bits) {
return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY);
}
int deflateInit(ZStream strm, int level) {
return deflateInit(strm, level, MAX_WBITS);
}
int deflateInit2(ZStream strm, int level, int method, int windowBits,
int memLevel, int strategy) {
int noheader = 0;
// byte[] my_version=ZLIB_VERSION;
//
// if (version == null || version[0] != my_version[0]
// || stream_size != sizeof(z_stream)) {
// return Z_VERSION_ERROR;
// }
strm.msg = null;
if (level == Z_DEFAULT_COMPRESSION) level = 6;
if (windowBits < 0) { // undocumented feature: suppress zlib header
noheader = 1;
windowBits = -windowBits;
}
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
method != Z_DEFLATED ||
windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
return Z_STREAM_ERROR;
}
strm.dstate = (Deflate) this;
this.noheader = noheader;
w_bits = windowBits;
w_size = 1 << w_bits;
w_mask = w_size - 1;
hash_bits = memLevel + 7;
hash_size = 1 << hash_bits;
hash_mask = hash_size - 1;
hash_shift = ((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
window = new byte[w_size * 2];
prev = new short[w_size];
head = new short[hash_size];
lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
// We overlay pending_buf and d_buf+l_buf. This works since the average
// output size for (length,distance) codes is <= 24 bits.
pending_buf = new byte[lit_bufsize * 4];
pending_buf_size = lit_bufsize * 4;
d_buf = lit_bufsize / 2;
l_buf = (1 + 2) * lit_bufsize;
this.level = level;
//System.out.println("level="+level);
this.strategy = strategy;
this.method = (byte) method;
return deflateReset(strm);
}
int deflateReset(ZStream strm) {
strm.total_in = strm.total_out = 0;
strm.msg = null; //
strm.data_type = Z_UNKNOWN;
pending = 0;
pending_out = 0;
if (noheader < 0) {
noheader = 0; // was set to -1 by deflate(..., Z_FINISH);
}
status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
strm.adler = strm._adler.adler32(0, null, 0, 0);
last_flush = Z_NO_FLUSH;
tr_init();
lm_init();
return Z_OK;
}
int deflateEnd() {
if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
return Z_STREAM_ERROR;
}
// Deallocate in reverse order of allocations:
pending_buf = null;
head = null;
prev = null;
window = null;
// free
// dstate=null;
return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
}
int deflateParams(ZStream strm, int _level, int _strategy) {
int err = Z_OK;
if (_level == Z_DEFAULT_COMPRESSION) {
_level = 6;
}
if (_level < 0 || _level > 9 ||
_strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
return Z_STREAM_ERROR;
}
if (config_table[level].func != config_table[_level].func &&
strm.total_in != 0) {
// Flush the last buffer:
err = strm.deflate(Z_PARTIAL_FLUSH);
}
if (level != _level) {
level = _level;
max_lazy_match = config_table[level].max_lazy;
good_match = config_table[level].good_length;
nice_match = config_table[level].nice_length;
max_chain_length = config_table[level].max_chain;
}
strategy = _strategy;
return err;
}
int deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength) {
int length = dictLength;
int index = 0;
if (dictionary == null || status != INIT_STATE)
return Z_STREAM_ERROR;
strm.adler = strm._adler.adler32(strm.adler, dictionary, 0, dictLength);
if (length < MIN_MATCH) return Z_OK;
if (length > w_size - MIN_LOOKAHEAD) {
length = w_size - MIN_LOOKAHEAD;
index = dictLength - length; // use the tail of the dictionary
}
System.arraycopy(dictionary, index, window, 0, length);
strstart = length;
block_start = length;
// Insert all strings in the hash table (except for the last two bytes).
// s->lookahead stays null, so s->ins_h will be recomputed at the next
// call of fill_window.
ins_h = window[0] & 0xff;
ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
for (int n = 0; n <= length - MIN_MATCH; n++) {
ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
prev[n & w_mask] = head[ins_h];
head[ins_h] = (short) n;
}
return Z_OK;
}
int deflate(ZStream strm, int flush) {
int old_flush;
if (flush > Z_FINISH || flush < 0) {
return Z_STREAM_ERROR;
}
if (strm.next_out == null ||
(strm.next_in == null && strm.avail_in != 0) ||
(status == FINISH_STATE && flush != Z_FINISH)) {
strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];
return Z_STREAM_ERROR;
}
if (strm.avail_out == 0) {
strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
return Z_BUF_ERROR;
}
this.strm = strm; // just in case
old_flush = last_flush;
last_flush = flush;
// Write the zlib header
if (status == INIT_STATE) {
int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
int level_flags = ((level - 1) & 0xff) >> 1;
if (level_flags > 3) level_flags = 3;
header |= (level_flags << 6);
if (strstart != 0) header |= PRESET_DICT;
header += 31 - (header % 31);
status = BUSY_STATE;
putShortMSB(header);
// Save the adler32 of the preset dictionary:
if (strstart != 0) {
putShortMSB((int) (strm.adler >>> 16));
putShortMSB((int) (strm.adler & 0xffff));
}
strm.adler = strm._adler.adler32(0, null, 0, 0);
}
// Flush as much pending output as possible
if (pending != 0) {
strm.flush_pending();
if (strm.avail_out == 0) {
//System.out.println(" avail_out==0");
// Since avail_out is 0, deflate will be called again with
// more output space, but possibly with both pending and
// avail_in equal to zero. There won't be anything to do,
// but this is not an error situation so make sure we
// return OK instead of BUF_ERROR at next call of deflate:
last_flush = -1;
return Z_OK;
}
// Make sure there is something to do and avoid duplicate consecutive
// flushes. For repeated and useless calls with Z_FINISH, we keep
// returning Z_STREAM_END instead of Z_BUFF_ERROR.
} else if (strm.avail_in == 0 && flush <= old_flush &&
flush != Z_FINISH) {
strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
return Z_BUF_ERROR;
}
// User must not provide more input after the first FINISH:
if (status == FINISH_STATE && strm.avail_in != 0) {
strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];
return Z_BUF_ERROR;
}
// Start a new block or continue the current one.
if (strm.avail_in != 0 || lookahead != 0 ||
(flush != Z_NO_FLUSH && status != FINISH_STATE)) {
int bstate = -1;
switch (config_table[level].func) {
case STORED:
bstate = deflate_stored(flush);
break;
case FAST:
bstate = deflate_fast(flush);
break;
case SLOW:
bstate = deflate_slow(flush);
break;
default:
}
if (bstate == FinishStarted || bstate == FinishDone) {
status = FINISH_STATE;
}
if (bstate == NeedMore || bstate == FinishStarted) {
if (strm.avail_out == 0) {
last_flush = -1; // avoid BUF_ERROR next call, see above
}
return Z_OK;
// If flush != Z_NO_FLUSH && avail_out == 0, the next call
// of deflate should use the same flush parameter to make sure
// that the flush is complete. So we don't have to output an
// empty block here, this will be done at next call. This also
// ensures that for a very small output buffer, we emit at most
// one empty block.
}
if (bstate == BlockDone) {
if (flush == Z_PARTIAL_FLUSH) {
_tr_align();
} else { // FULL_FLUSH or SYNC_FLUSH
_tr_stored_block(0, 0, false);
// For a full flush, this empty block will be recognized
// as a special marker by inflate_sync().
if (flush == Z_FULL_FLUSH) {
//state.head[s.hash_size-1]=0;
for (int i = 0; i < hash_size/*-1*/; i++) // forget history
head[i] = 0;
}
}
strm.flush_pending();
if (strm.avail_out == 0) {
last_flush = -1; // avoid BUF_ERROR at next call, see above
return Z_OK;
}
}
}
if (flush != Z_FINISH) return Z_OK;
if (noheader != 0) return Z_STREAM_END;
// Write the zlib trailer (adler32)
putShortMSB((int) (strm.adler >>> 16));
putShortMSB((int) (strm.adler & 0xffff));
strm.flush_pending();
// If avail_out is zero, the application will call deflate again
// to flush the rest.
noheader = -1; // write the trailer only once!
return pending != 0 ? Z_OK : Z_STREAM_END;
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class InfBlocks {
static final private int MANY = 1440;
// And'ing with mask[n] masks the lower n bits
static final private int[] inflate_mask = {
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
0x00007fff, 0x0000ffff
};
// Table for deflate from PKZIP's appnote.txt.
static final int[] border = { // Order of the bit length code lengths
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
static final private int Z_OK = 0;
static final private int Z_STREAM_END = 1;
static final private int Z_NEED_DICT = 2;
static final private int Z_ERRNO = -1;
static final private int Z_STREAM_ERROR = -2;
static final private int Z_DATA_ERROR = -3;
static final private int Z_MEM_ERROR = -4;
static final private int Z_BUF_ERROR = -5;
static final private int Z_VERSION_ERROR = -6;
static final private int TYPE = 0; // get type bits (3, including end bit)
static final private int LENS = 1; // get lengths for stored
static final private int STORED = 2;// processing stored block
static final private int TABLE = 3; // get table lengths
static final private int BTREE = 4; // get bit lengths tree for a dynamic block
static final private int DTREE = 5; // get length, distance trees for a dynamic block
static final private int CODES = 6; // processing fixed or dynamic block
static final private int DRY = 7; // output remaining window bytes
static final private int DONE = 8; // finished last block, done
static final private int BAD = 9; // ot a data error--stuck here
int mode; // current inflate_block mode
int left; // if STORED, bytes left to copy
int table; // table lengths (14 bits)
int index; // index into blens (or border)
int[] blens; // bit lengths of codes
int[] bb = new int[1]; // bit length tree depth
int[] tb = new int[1]; // bit length decoding tree
InfCodes codes = new InfCodes(); // if CODES, current state
int last; // true if this block is the last block
// mode independent information
int bitk; // bits in bit buffer
int bitb; // bit buffer
int[] hufts; // single malloc for tree space
byte[] window; // sliding window
int end; // one byte after sliding window
int read; // window read pointer
int write; // window write pointer
Object checkfn; // check function
long check; // check on output
InfTree inftree = new InfTree();
InfBlocks(ZStream z, Object checkfn, int w) {
hufts = new int[MANY * 3];
window = new byte[w];
end = w;
this.checkfn = checkfn;
mode = TYPE;
reset(z, null);
}
void reset(ZStream z, long[] c) {
if (c != null) c[0] = check;
if (mode == BTREE || mode == DTREE) {
}
if (mode == CODES) {
codes.free(z);
}
mode = TYPE;
bitk = 0;
bitb = 0;
read = write = 0;
if (checkfn != null)
z.adler = check = z._adler.adler32(0L, null, 0, 0);
}
int proc(ZStream z, int r) {
int t; // temporary storage
int b; // bit buffer
int k; // bits in bit buffer
int p; // input data pointer
int n; // bytes available there
int q; // output window write pointer
int m; // bytes to end of window or read pointer
// copy input/output information to locals (UPDATE macro restores)
{
p = z.next_in_index;
n = z.avail_in;
b = bitb;
k = bitk;
}
{
q = write;
m = (int) (q < read ? read - q - 1 : end - q);
}
// process input based on current state
while (true) {
switch (mode) {
case TYPE:
while (k < (3)) {
if (n != 0) {
r = Z_OK;
} else {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
;
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
t = (int) (b & 7);
last = t & 1;
switch (t >>> 1) {
case 0: // stored
{
b >>>= (3);
k -= (3);
}
t = k & 7; // go to byte boundary
{
b >>>= (t);
k -= (t);
}
mode = LENS; // get length of stored block
break;
case 1: // fixed
{
int[] bl = new int[1];
int[] bd = new int[1];
int[][] tl = new int[1][];
int[][] td = new int[1][];
InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z);
}
{
b >>>= (3);
k -= (3);
}
mode = CODES;
break;
case 2: // dynamic
{
b >>>= (3);
k -= (3);
}
mode = TABLE;
break;
case 3: // illegal
{
b >>>= (3);
k -= (3);
}
mode = BAD;
z.msg = "invalid block type";
r = Z_DATA_ERROR;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
break;
case LENS:
while (k < (32)) {
if (n != 0) {
r = Z_OK;
} else {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
;
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)) {
mode = BAD;
z.msg = "invalid stored block lengths";
r = Z_DATA_ERROR;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
left = (b & 0xffff);
b = k = 0; // dump bits
mode = left != 0 ? STORED : (last != 0 ? DRY : TYPE);
break;
case STORED:
if (n == 0) {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
if (m == 0) {
if (q == end && read != 0) {
q = 0;
m = (int) (q < read ? read - q - 1 : end - q);
}
if (m == 0) {
write = q;
r = inflate_flush(z, r);
q = write;
m = (int) (q < read ? read - q - 1 : end - q);
if (q == end && read != 0) {
q = 0;
m = (int) (q < read ? read - q - 1 : end - q);
}
if (m == 0) {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
}
}
r = Z_OK;
t = left;
if (t > n) t = n;
if (t > m) t = m;
System.arraycopy(z.next_in, p, window, q, t);
p += t;
n -= t;
q += t;
m -= t;
if ((left -= t) != 0)
break;
mode = last != 0 ? DRY : TYPE;
break;
case TABLE:
while (k < (14)) {
if (n != 0) {
r = Z_OK;
} else {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
;
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
table = t = (b & 0x3fff);
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) {
mode = BAD;
z.msg = "too many length or distance symbols";
r = Z_DATA_ERROR;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
if (blens == null || blens.length < t) {
blens = new int[t];
} else {
for (int i = 0; i < t; i++) {
blens[i] = 0;
}
}
{
b >>>= (14);
k -= (14);
}
index = 0;
mode = BTREE;
case BTREE:
while (index < 4 + (table >>> 10)) {
while (k < (3)) {
if (n != 0) {
r = Z_OK;
} else {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
;
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
blens[border[index++]] = b & 7;
{
b >>>= (3);
k -= (3);
}
}
while (index < 19) {
blens[border[index++]] = 0;
}
bb[0] = 7;
t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
if (t != Z_OK) {
r = t;
if (r == Z_DATA_ERROR) {
blens = null;
mode = BAD;
}
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
index = 0;
mode = DTREE;
case DTREE:
while (true) {
t = table;
if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) {
break;
}
int[] h;
int i, j, c;
t = bb[0];
while (k < (t)) {
if (n != 0) {
r = Z_OK;
} else {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
;
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
if (tb[0] == -1) {
//System.err.println("null...");
}
t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
if (c < 16) {
b >>>= (t);
k -= (t);
blens[index++] = c;
} else { // c == 16..18
i = c == 18 ? 7 : c - 14;
j = c == 18 ? 11 : 3;
while (k < (t + i)) {
if (n != 0) {
r = Z_OK;
} else {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
;
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
b >>>= (t);
k -= (t);
j += (b & inflate_mask[i]);
b >>>= (i);
k -= (i);
i = index;
t = table;
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
(c == 16 && i < 1)) {
blens = null;
mode = BAD;
z.msg = "invalid bit length repeat";
r = Z_DATA_ERROR;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
c = c == 16 ? blens[i - 1] : 0;
do {
blens[i++] = c;
}
while (--j != 0);
index = i;
}
}
tb[0] = -1;
{
int[] bl = new int[1];
int[] bd = new int[1];
int[] tl = new int[1];
int[] td = new int[1];
bl[0] = 9; // must be <= 9 for lookahead assumptions
bd[0] = 6; // must be <= 9 for lookahead assumptions
t = table;
t = inftree.inflate_trees_dynamic(257 + (t & 0x1f),
1 + ((t >> 5) & 0x1f),
blens, bl, bd, tl, td, hufts, z);
if (t != Z_OK) {
if (t == Z_DATA_ERROR) {
blens = null;
mode = BAD;
}
r = t;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
}
mode = CODES;
case CODES:
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
if ((r = codes.proc(this, z, r)) != Z_STREAM_END) {
return inflate_flush(z, r);
}
r = Z_OK;
codes.free(z);
p = z.next_in_index;
n = z.avail_in;
b = bitb;
k = bitk;
q = write;
m = (int) (q < read ? read - q - 1 : end - q);
if (last == 0) {
mode = TYPE;
break;
}
mode = DRY;
case DRY:
write = q;
r = inflate_flush(z, r);
q = write;
m = (int) (q < read ? read - q - 1 : end - q);
if (read != write) {
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
mode = DONE;
case DONE:
r = Z_STREAM_END;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
case BAD:
r = Z_DATA_ERROR;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
default:
r = Z_STREAM_ERROR;
bitb = b;
bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
write = q;
return inflate_flush(z, r);
}
}
}
void free(ZStream z) {
reset(z, null);
window = null;
hufts = null;
//ZFREE(z, s);
}
void set_dictionary(byte[] d, int start, int n) {
System.arraycopy(d, start, window, 0, n);
read = write = n;
}
// Returns true if inflate is currently at the end of a block generated
// by Z_SYNC_FLUSH or Z_FULL_FLUSH.
int sync_point() {
return mode == LENS ? 1 : 0;
}
// copy as much as possible from the sliding window to the output area
int inflate_flush(ZStream z, int r) {
int n;
int p;
int q;
// local copies of source and destination pointers
p = z.next_out_index;
q = read;
// compute number of bytes to copy as far as end of window
n = (int) ((q <= write ? write : end) - q);
if (n > z.avail_out) n = z.avail_out;
if (n != 0 && r == Z_BUF_ERROR) r = Z_OK;
// update counters
z.avail_out -= n;
z.total_out += n;
// update check information
if (checkfn != null)
z.adler = check = z._adler.adler32(check, window, q, n);
// copy as far as end of window
System.arraycopy(window, q, z.next_out, p, n);
p += n;
q += n;
// see if more to copy at beginning of window
if (q == end) {
// wrap pointers
q = 0;
if (write == end)
write = 0;
// compute bytes to copy
n = write - q;
if (n > z.avail_out) n = z.avail_out;
if (n != 0 && r == Z_BUF_ERROR) r = Z_OK;
// update counters
z.avail_out -= n;
z.total_out += n;
// update check information
if (checkfn != null)
z.adler = check = z._adler.adler32(check, window, q, n);
// copy
System.arraycopy(window, q, z.next_out, p, n);
p += n;
q += n;
}
// update pointers
z.next_out_index = p;
read = q;
// done
return r;
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class InfCodes {
static final private int[] inflate_mask = {
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
0x00007fff, 0x0000ffff
};
static final private int Z_OK = 0;
static final private int Z_STREAM_END = 1;
static final private int Z_NEED_DICT = 2;
static final private int Z_ERRNO = -1;
static final private int Z_STREAM_ERROR = -2;
static final private int Z_DATA_ERROR = -3;
static final private int Z_MEM_ERROR = -4;
static final private int Z_BUF_ERROR = -5;
static final private int Z_VERSION_ERROR = -6;
// waiting for "i:"=input,
// "o:"=output,
// "x:"=nothing
static final private int START = 0; // x: set up for LEN
static final private int LEN = 1; // i: get length/literal/eob next
static final private int LENEXT = 2; // i: getting length extra (have base)
static final private int DIST = 3; // i: get distance next
static final private int DISTEXT = 4;// i: getting distance extra
static final private int COPY = 5; // o: copying bytes in window, waiting for space
static final private int LIT = 6; // o: got literal, waiting for output space
static final private int WASH = 7; // o: got eob, possibly still output waiting
static final private int END = 8; // x: got eob and all data flushed
static final private int BADCODE = 9;// x: got error
int mode; // current inflate_codes mode
// mode dependent information
int len;
int[] tree; // pointer into tree
int tree_index = 0;
int need; // bits needed
int lit;
// if EXT or COPY, where and how much
int get; // bits to get for extra
int dist; // distance back to copy from
byte lbits; // ltree bits decoded per branch
byte dbits; // dtree bits decoder per branch
int[] ltree; // literal/length/eob tree
int ltree_index; // literal/length/eob tree
int[] dtree; // distance tree
int dtree_index; // distance tree
InfCodes() {
}
void init(int bl, int bd,
int[] tl, int tl_index,
int[] td, int td_index, ZStream z) {
mode = START;
lbits = (byte) bl;
dbits = (byte) bd;
ltree = tl;
ltree_index = tl_index;
dtree = td;
dtree_index = td_index;
tree = null;
}
int proc(InfBlocks s, ZStream z, int r) {
int j; // temporary storage
int[] t; // temporary pointer
int tindex; // temporary pointer
int e; // extra bits or operation
int b = 0; // bit buffer
int k = 0; // bits in bit buffer
int p = 0; // input data pointer
int n; // bytes available there
int q; // output window write pointer
int m; // bytes to end of window or read pointer
int f; // pointer to copy strings from
// copy input/output information to locals (UPDATE macro restores)
p = z.next_in_index;
n = z.avail_in;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
// process input and output based on current state
while (true) {
switch (mode) {
// waiting for "i:"=input, "o:"=output, "x:"=nothing
case START: // x: set up for LEN
if (m >= 258 && n >= 10) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
r = inflate_fast(lbits, dbits,
ltree, ltree_index,
dtree, dtree_index,
s, z);
p = z.next_in_index;
n = z.avail_in;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (r != Z_OK) {
mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
need = lbits;
tree = ltree;
tree_index = ltree_index;
mode = LEN;
case LEN: // i: get length/literal/eob next
j = need;
while (k < (j)) {
if (n != 0) r = Z_OK;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
tindex = (tree_index + (b & inflate_mask[j])) * 3;
b >>>= (tree[tindex + 1]);
k -= (tree[tindex + 1]);
e = tree[tindex];
if (e == 0) { // literal
lit = tree[tindex + 2];
mode = LIT;
break;
}
if ((e & 16) != 0) { // length
get = e & 15;
len = tree[tindex + 2];
mode = LENEXT;
break;
}
if ((e & 64) == 0) { // next table
need = e;
tree_index = tindex / 3 + tree[tindex + 2];
break;
}
if ((e & 32) != 0) { // end of block
mode = WASH;
break;
}
mode = BADCODE; // invalid code
z.msg = "invalid literal/length code";
r = Z_DATA_ERROR;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
case LENEXT: // i: getting length extra (have base)
j = get;
while (k < (j)) {
if (n != 0) r = Z_OK;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
len += (b & inflate_mask[j]);
b >>= j;
k -= j;
need = dbits;
tree = dtree;
tree_index = dtree_index;
mode = DIST;
case DIST: // i: get distance next
j = need;
while (k < (j)) {
if (n != 0) r = Z_OK;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
tindex = (tree_index + (b & inflate_mask[j])) * 3;
b >>= tree[tindex + 1];
k -= tree[tindex + 1];
e = (tree[tindex]);
if ((e & 16) != 0) { // distance
get = e & 15;
dist = tree[tindex + 2];
mode = DISTEXT;
break;
}
if ((e & 64) == 0) { // next table
need = e;
tree_index = tindex / 3 + tree[tindex + 2];
break;
}
mode = BADCODE; // invalid code
z.msg = "invalid distance code";
r = Z_DATA_ERROR;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
case DISTEXT: // i: getting distance extra
j = get;
while (k < (j)) {
if (n != 0) r = Z_OK;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
dist += (b & inflate_mask[j]);
b >>= j;
k -= j;
mode = COPY;
case COPY: // o: copying bytes in window, waiting for space
f = q - dist;
while (f < 0) { // modulo window size-"while" instead
f += s.end; // of "if" handles invalid distances
}
while (len != 0) {
if (m == 0) {
if (q == s.end && s.read != 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m == 0) {
s.write = q;
r = s.inflate_flush(z, r);
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (q == s.end && s.read != 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m == 0) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
}
}
s.window[q++] = s.window[f++];
m--;
if (f == s.end)
f = 0;
len--;
}
mode = START;
break;
case LIT: // o: got literal, waiting for output space
if (m == 0) {
if (q == s.end && s.read != 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m == 0) {
s.write = q;
r = s.inflate_flush(z, r);
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (q == s.end && s.read != 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m == 0) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
}
}
r = Z_OK;
s.window[q++] = (byte) lit;
m--;
mode = START;
break;
case WASH: // o: got eob, possibly more output
if (k > 7) { // return unused byte, if any
k -= 8;
n++;
p--; // can always return one
}
s.write = q;
r = s.inflate_flush(z, r);
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (s.read != s.write) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
mode = END;
case END:
r = Z_STREAM_END;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
case BADCODE: // x: got error
r = Z_DATA_ERROR;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
default:
r = Z_STREAM_ERROR;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
}
}
void free(ZStream z) {
// ZFREE(z, c);
}
// Called with number of bytes left to write in window at least 258
// (the maximum string length) and number of input bytes available
// at least ten. The ten bytes are six bytes for the longest length/
// distance pair plus four bytes for overloading the bit buffer.
int inflate_fast(int bl, int bd,
int[] tl, int tl_index,
int[] td, int td_index,
InfBlocks s, ZStream z) {
int t; // temporary pointer
int[] tp; // temporary pointer
int tp_index; // temporary pointer
int e; // extra bits or operation
int b; // bit buffer
int k; // bits in bit buffer
int p; // input data pointer
int n; // bytes available there
int q; // output window write pointer
int m; // bytes to end of window or read pointer
int ml; // mask for literal/length tree
int md; // mask for distance tree
int c; // bytes to copy
int d; // distance back to copy from
int r; // copy source pointer
int tp_index_t_3; // (tp_index+t)*3
// load input, output, bit values
p = z.next_in_index;
n = z.avail_in;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
// initialize masks
ml = inflate_mask[bl];
md = inflate_mask[bd];
// do until not enough input or output space for fast loop
do { // assume called with m >= 258 && n >= 10
// get literal/length code
while (k < (20)) { // max bits for literal/length code
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
t = b & ml;
tp = tl;
tp_index = tl_index;
tp_index_t_3 = (tp_index + t) * 3;
if ((e = tp[tp_index_t_3]) == 0) {
b >>= (tp[tp_index_t_3 + 1]);
k -= (tp[tp_index_t_3 + 1]);
s.window[q++] = (byte) tp[tp_index_t_3 + 2];
m--;
continue;
}
do {
b >>= (tp[tp_index_t_3 + 1]);
k -= (tp[tp_index_t_3 + 1]);
if ((e & 16) != 0) {
e &= 15;
c = tp[tp_index_t_3 + 2] + ((int) b & inflate_mask[e]);
b >>= e;
k -= e;
// decode distance base of block to copy
while (k < (15)) { // max bits for distance code
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
t = b & md;
tp = td;
tp_index = td_index;
tp_index_t_3 = (tp_index + t) * 3;
e = tp[tp_index_t_3];
do {
b >>= (tp[tp_index_t_3 + 1]);
k -= (tp[tp_index_t_3 + 1]);
if ((e & 16) != 0) {
// get extra bits to add to distance base
e &= 15;
while (k < (e)) { // get extra bits (up to 13)
n--;
b |= (z.next_in[p++] & 0xff) << k;
k += 8;
}
d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
b >>= (e);
k -= (e);
// do the copy
m -= c;
if (q >= d) { // offset before dest
// just copy
r = q - d;
if (q - r > 0 && 2 > (q - r)) {
s.window[q++] = s.window[r++]; // minimum count is three,
s.window[q++] = s.window[r++]; // so unroll loop a little
c -= 2;
} else {
System.arraycopy(s.window, r, s.window, q, 2);
q += 2;
r += 2;
c -= 2;
}
} else { // else offset after destination
r = q - d;
do {
r += s.end; // force pointer in window
} while (r < 0); // covers invalid distances
e = s.end - r;
if (c > e) { // if source crosses,
c -= e; // wrapped copy
if (q - r > 0 && e > (q - r)) {
do {
s.window[q++] = s.window[r++];
}
while (--e != 0);
} else {
System.arraycopy(s.window, r, s.window, q, e);
q += e;
r += e;
e = 0;
}
r = 0; // copy rest from start of window
}
}
// copy all or what's left
if (q - r > 0 && c > (q - r)) {
do {
s.window[q++] = s.window[r++];
}
while (--c != 0);
} else {
System.arraycopy(s.window, r, s.window, q, c);
q += c;
r += c;
c = 0;
}
break;
} else if ((e & 64) == 0) {
t += tp[tp_index_t_3 + 2];
t += (b & inflate_mask[e]);
tp_index_t_3 = (tp_index + t) * 3;
e = tp[tp_index_t_3];
} else {
z.msg = "invalid distance code";
c = z.avail_in - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_DATA_ERROR;
}
}
while (true);
break;
}
if ((e & 64) == 0) {
t += tp[tp_index_t_3 + 2];
t += (b & inflate_mask[e]);
tp_index_t_3 = (tp_index + t) * 3;
if ((e = tp[tp_index_t_3]) == 0) {
b >>= (tp[tp_index_t_3 + 1]);
k -= (tp[tp_index_t_3 + 1]);
s.window[q++] = (byte) tp[tp_index_t_3 + 2];
m--;
break;
}
} else if ((e & 32) != 0) {
c = z.avail_in - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_STREAM_END;
} else {
z.msg = "invalid literal/length code";
c = z.avail_in - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_DATA_ERROR;
}
}
while (true);
}
while (m >= 258 && n >= 10);
// not enough input or output--restore pointers and return
c = z.avail_in - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_OK;
}
}
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class InfTree {
static final private int MANY = 1440;
static final private int Z_OK = 0;
static final private int Z_STREAM_END = 1;
static final private int Z_NEED_DICT = 2;
static final private int Z_ERRNO = -1;
static final private int Z_STREAM_ERROR = -2;
static final private int Z_DATA_ERROR = -3;
static final private int Z_MEM_ERROR = -4;
static final private int Z_BUF_ERROR = -5;
static final private int Z_VERSION_ERROR = -6;
static final int fixed_bl = 9;
static final int fixed_bd = 5;
static final int[] fixed_tl = {
96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115,
82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192,
80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160,
0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 224,
80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144,
83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208,
81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 176,
0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240,
80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227,
83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200,
81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 168,
0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232,
80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152,
84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 216,
82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184,
0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248,
80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163,
83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 196,
81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164,
0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228,
80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 148,
84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212,
82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180,
0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244,
80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0,
83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204,
81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172,
0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 236,
80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156,
84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220,
82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188,
0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252,
96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131,
82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194,
80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 162,
0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226,
80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146,
83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210,
81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178,
0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242,
80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258,
83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 202,
81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170,
0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234,
80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154,
84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218,
82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186,
0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250,
80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195,
83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198,
81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166,
0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230,
80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150,
84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214,
82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182,
0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 246,
80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0,
83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206,
81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174,
0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238,
80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158,
84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222,
82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 190,
0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254,
96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115,
82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 193,
80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161,
0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225,
80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145,
83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 209,
81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177,
0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241,
80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227,
83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201,
81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169,
0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233,
80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 153,
84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217,
82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185,
0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 249,
80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163,
83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197,
81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165,
0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 229,
80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149,
84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213,
82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 181,
0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245,
80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0,
83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205,
81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 173,
0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237,
80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157,
84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 221,
82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189,
0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 253,
96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131,
82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 195,
80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163,
0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227,
80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 147,
83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211,
81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179,
0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243,
80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258,
83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203,
81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171,
0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 235,
80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155,
84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219,
82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187,
0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 251,
80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195,
83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199,
81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 167,
0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231,
80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151,
84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215,
82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 183,
0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247,
80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0,
83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 207,
81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175,
0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239,
80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159,
84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 223,
82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191,
0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255
};
static final int[] fixed_td = {
80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097,
81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385,
80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5, 8193,
82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577,
80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145,
81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5, 24577,
80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289,
82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577
};
// Tables for deflate from PKZIP's appnote.txt.
static final int[] cplens = { // Copy lengths for literal codes 257..285
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
};
// see note #13 above about 258
static final int[] cplext = { // Extra bits for literal codes 257..285
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
};
static final int[] cpdist = { // Copy offsets for distance codes 0..29
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577
};
static final int[] cpdext = { // Extra bits for distance codes
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
// If BMAX needs to be larger than 16, then h and x[] should be uLong.
static final int BMAX = 15; // maximum bit length of any code
int[] hn = null; // hufts used in space
int[] v = null; // work area for huft_build
int[] c = null; // bit length count table
int[] r = null; // table entry for structure assignment
int[] u = null; // table stack
int[] x = null; // bit offsets, then code stack
private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
int bindex,
int n, // number of codes (assumed <= 288)
int s, // number of simple-valued codes (0..s-1)
int[] d, // list of base values for non-simple codes
int[] e, // list of extra bits for non-simple codes
int[] t, // result: starting table
int[] m, // maximum lookup bits, returns actual
int[] hp,// space for trees
int[] hn,// hufts used in space
int[] v // working area: values in order of bit length
) {
// Given a list of code lengths and a maximum table size, make a set of
// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
// if the given code set is incomplete (the tables are still built in this
// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
// lengths), or Z_MEM_ERROR if not enough memory.
int a; // counter for codes of length k
int f; // i repeats in table every f entries
int g; // maximum code length
int h; // table level
int i; // counter, current code
int j; // counter
int k; // number of bits in current code
int l; // bits per table (returned in m)
int mask; // (1 << w) - 1, to avoid cc -O bug on HP
int p; // pointer into c[], b[], or v[]
int q; // points to current table
int w; // bits before this table == (l * h)
int xp; // pointer into x
int y; // number of dummy codes added
int z; // number of entries in current table
// Generate counts for each bit length
p = 0;
i = n;
do {
c[b[bindex + p]]++;
p++;
i--; // assume all entries <= BMAX
} while (i != 0);
if (c[0] == n) { // null input--all zero length codes
t[0] = -1;
m[0] = 0;
return Z_OK;
}
// Find minimum and maximum length, bound *m by those
l = m[0];
for (j = 1; j <= BMAX; j++)
if (c[j] != 0) break;
k = j; // minimum code length
if (l < j) {
l = j;
}
for (i = BMAX; i != 0; i--) {
if (c[i] != 0) break;
}
g = i; // maximum code length
if (l > i) {
l = i;
}
m[0] = l;
// Adjust last length count to fill out codes, if needed
for (y = 1 << j; j < i; j++, y <<= 1) {
if ((y -= c[j]) < 0) {
return Z_DATA_ERROR;
}
}
if ((y -= c[i]) < 0) {
return Z_DATA_ERROR;
}
c[i] += y;
// Generate starting offsets into the value table for each length
x[1] = j = 0;
p = 1;
xp = 2;
while (--i != 0) { // note that i == g from above
x[xp] = (j += c[p]);
xp++;
p++;
}
// Make a table of values in order of bit lengths
i = 0;
p = 0;
do {
if ((j = b[bindex + p]) != 0) {
v[x[j]++] = i;
}
p++;
}
while (++i < n);
n = x[g]; // set n to length of v
// Generate the Huffman codes and for each, make the table entries
x[0] = i = 0; // first Huffman code is zero
p = 0; // grab values in bit order
h = -1; // no tables yet--level -1
w = -l; // bits decoded == (l * h)
u[0] = 0; // just to keep compilers happy
q = 0; // ditto
z = 0; // ditto
// go through the bit lengths (k already is bits in shortest code)
for (; k <= g; k++) {
a = c[k];
while (a-- != 0) {
// here i is the Huffman code of length k bits for value *p
// make tables up to required level
while (k > w + l) {
h++;
w += l; // previous table always l bits
// compute minimum size table less than or equal to l bits
z = g - w;
z = (z > l) ? l : z; // table size upper limit
if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table
// too few codes for k-w bit table
f -= a + 1; // deduct codes from patterns left
xp = k;
if (j < z) {
while (++j < z) { // try smaller tables up to z bits
if ((f <<= 1) <= c[++xp])
break; // enough codes to use up j bits
f -= c[xp]; // else deduct codes from patterns
}
}
}
z = 1 << j; // table entries for j-bit table
// allocate new table
if (hn[0] + z > MANY) { // (note: doesn't matter for fixed)
return Z_DATA_ERROR; // overflow of MANY
}
u[h] = q = /*hp+*/ hn[0]; // DEBUG
hn[0] += z;
// connect to last table, if there is one
if (h != 0) {
x[h] = i; // save pattern for backing up
r[0] = (byte) j; // bits in this table
r[1] = (byte) l; // bits to dump before this table
j = i >>> (w - l);
r[2] = (int) (q - u[h - 1] - j); // offset to this table
System.arraycopy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
} else {
t[0] = q; // first table is returned result
}
}
// set up table entry in r
r[1] = (byte) (k - w);
if (p >= n) {
r[0] = 128 + 64; // out of values--invalid code
} else if (v[p] < s) {
r[0] = (byte) (v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
r[2] = v[p++]; // simple code is just the value
} else {
r[0] = (byte) (e[v[p] - s] + 16 + 64); // non-simple--look up in lists
r[2] = d[v[p++] - s];
}
// fill code-like entries with r
f = 1 << (k - w);
for (j = i >>> w; j < z; j += f) {
System.arraycopy(r, 0, hp, (q + j) * 3, 3);
}
// backwards increment the k-bit code i
for (j = 1 << (k - 1); (i & j) != 0; j >>>= 1) {
i ^= j;
}
i ^= j;
// backup over finished tables
mask = (1 << w) - 1; // needed on HP, cc -O bug
while ((i & mask) != x[h]) {
h--; // don't need to update q
w -= l;
mask = (1 << w) - 1;
}
}
}
// Return Z_BUF_ERROR if we were given an incomplete table
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
}
int inflate_trees_bits(int[] c, // 19 code lengths
int[] bb, // bits tree desired/actual depth
int[] tb, // bits tree result
int[] hp, // space for trees
ZStream z // for messages
) {
int result;
initWorkArea(19);
hn[0] = 0;
result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
if (result == Z_DATA_ERROR) {
z.msg = "oversubscribed dynamic bit lengths tree";
} else if (result == Z_BUF_ERROR || bb[0] == 0) {
z.msg = "incomplete dynamic bit lengths tree";
result = Z_DATA_ERROR;
}
return result;
}
int inflate_trees_dynamic(int nl, // number of literal/length codes
int nd, // number of distance codes
int[] c, // that many (total) code lengths
int[] bl, // literal desired/actual bit depth
int[] bd, // distance desired/actual bit depth
int[] tl, // literal/length tree result
int[] td, // distance tree result
int[] hp, // space for trees
ZStream z // for messages
) {
int result;
// build literal/length tree
initWorkArea(288);
hn[0] = 0;
result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
if (result != Z_OK || bl[0] == 0) {
if (result == Z_DATA_ERROR) {
z.msg = "oversubscribed literal/length tree";
} else if (result != Z_MEM_ERROR) {
z.msg = "incomplete literal/length tree";
result = Z_DATA_ERROR;
}
return result;
}
// build distance tree
initWorkArea(288);
result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
if (result != Z_OK || (bd[0] == 0 && nl > 257)) {
if (result == Z_DATA_ERROR) {
z.msg = "oversubscribed distance tree";
} else if (result == Z_BUF_ERROR) {
z.msg = "incomplete distance tree";
result = Z_DATA_ERROR;
} else if (result != Z_MEM_ERROR) {
z.msg = "empty distance tree with lengths";
result = Z_DATA_ERROR;
}
return result;
}
return Z_OK;
}
static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth
int[] bd, //distance desired/actual bit depth
int[][] tl,//literal/length tree result
int[][] td,//distance tree result
ZStream z //for memory allocation
) {
bl[0] = fixed_bl;
bd[0] = fixed_bd;
tl[0] = fixed_tl;
td[0] = fixed_td;
return Z_OK;
}
private void initWorkArea(int vsize) {
if (hn == null) {
hn = new int[1];
v = new int[vsize];
c = new int[BMAX + 1];
r = new int[3];
u = new int[BMAX];
x = new int[BMAX + 1];
}
if (v.length < vsize) {
v = new int[vsize];
}
for (int i = 0; i < vsize; i++) {
v[i] = 0;
}
for (int i = 0; i < BMAX + 1; i++) {
c[i] = 0;
}
for (int i = 0; i < 3; i++) {
r[i] = 0;
}
// for(int i=0; i<BMAX; i++){u[i]=0;}
System.arraycopy(c, 0, u, 0, BMAX);
// for(int i=0; i<BMAX+1; i++){x[i]=0;}
System.arraycopy(c, 0, x, 0, BMAX + 1);
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class Inflate {
static final private int MAX_WBITS = 15; // 32K LZ77 window
// preset dictionary flag in zlib header
static final private int PRESET_DICT = 0x20;
static final int Z_NO_FLUSH = 0;
static final int Z_PARTIAL_FLUSH = 1;
static final int Z_SYNC_FLUSH = 2;
static final int Z_FULL_FLUSH = 3;
static final int Z_FINISH = 4;
static final private int Z_DEFLATED = 8;
static final private int Z_OK = 0;
static final private int Z_STREAM_END = 1;
static final private int Z_NEED_DICT = 2;
static final private int Z_ERRNO = -1;
static final private int Z_STREAM_ERROR = -2;
static final private int Z_DATA_ERROR = -3;
static final private int Z_MEM_ERROR = -4;
static final private int Z_BUF_ERROR = -5;
static final private int Z_VERSION_ERROR = -6;
static final private int METHOD = 0; // waiting for method byte
static final private int FLAG = 1; // waiting for flag byte
static final private int DICT4 = 2; // four dictionary check bytes to go
static final private int DICT3 = 3; // three dictionary check bytes to go
static final private int DICT2 = 4; // two dictionary check bytes to go
static final private int DICT1 = 5; // one dictionary check byte to go
static final private int DICT0 = 6; // waiting for inflateSetDictionary
static final private int BLOCKS = 7; // decompressing blocks
static final private int CHECK4 = 8; // four check bytes to go
static final private int CHECK3 = 9; // three check bytes to go
static final private int CHECK2 = 10; // two check bytes to go
static final private int CHECK1 = 11; // one check byte to go
static final private int DONE = 12; // finished check, done
static final private int BAD = 13; // got an error--stay here
int mode; // current inflate mode
// mode dependent information
int method; // if FLAGS, method byte
// if CHECK, check values to compare
long[] was = new long[1]; // computed check value
long need; // stream check value
// if BAD, inflateSync's marker bytes count
int marker;
// mode independent information
int nowrap; // flag for no wrapper
int wbits; // log2(window size) (8..15, defaults to 15)
InfBlocks blocks; // current inflate_blocks state
int inflateReset(ZStream z) {
if (z == null || z.istate == null) return Z_STREAM_ERROR;
z.total_in = z.total_out = 0;
z.msg = null;
z.istate.mode = z.istate.nowrap != 0 ? BLOCKS : METHOD;
z.istate.blocks.reset(z, null);
return Z_OK;
}
int inflateEnd(ZStream z) {
if (blocks != null)
blocks.free(z);
blocks = null;
// ZFREE(z, z->state);
return Z_OK;
}
int inflateInit(ZStream z, int w) {
z.msg = null;
blocks = null;
// handle undocumented nowrap option (no zlib header or check)
nowrap = 0;
if (w < 0) {
w = -w;
nowrap = 1;
}
// set window size
if (w < 8 || w > 15) {
inflateEnd(z);
return Z_STREAM_ERROR;
}
wbits = w;
z.istate.blocks = new InfBlocks(z,
z.istate.nowrap != 0 ? null : this,
1 << w);
// reset state
inflateReset(z);
return Z_OK;
}
int inflate(ZStream z, int f) {
int r;
int b;
if (z == null || z.istate == null || z.next_in == null)
return Z_STREAM_ERROR;
f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
r = Z_BUF_ERROR;
while (true) {
//System.out.println("mode: "+z.istate.mode);
switch (z.istate.mode) {
case METHOD:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != Z_DEFLATED) {
z.istate.mode = BAD;
z.msg = "unknown compression method";
z.istate.marker = 5; // can't try inflateSync
break;
}
if ((z.istate.method >> 4) + 8 > z.istate.wbits) {
z.istate.mode = BAD;
z.msg = "invalid window size";
z.istate.marker = 5; // can't try inflateSync
break;
}
z.istate.mode = FLAG;
case FLAG:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
b = (z.next_in[z.next_in_index++]) & 0xff;
if ((((z.istate.method << 8) + b) % 31) != 0) {
z.istate.mode = BAD;
z.msg = "incorrect header check";
z.istate.marker = 5; // can't try inflateSync
break;
}
if ((b & PRESET_DICT) == 0) {
z.istate.mode = BLOCKS;
break;
}
z.istate.mode = DICT4;
case DICT4:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L;
z.istate.mode = DICT3;
case DICT3:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L;
z.istate.mode = DICT2;
case DICT2:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L;
z.istate.mode = DICT1;
case DICT1:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);
z.adler = z.istate.need;
z.istate.mode = DICT0;
return Z_NEED_DICT;
case DICT0:
z.istate.mode = BAD;
z.msg = "need dictionary";
z.istate.marker = 0; // can try inflateSync
return Z_STREAM_ERROR;
case BLOCKS:
r = z.istate.blocks.proc(z, r);
if (r == Z_DATA_ERROR) {
z.istate.mode = BAD;
z.istate.marker = 0; // can try inflateSync
break;
}
if (r == Z_OK) {
r = f;
}
if (r != Z_STREAM_END) {
return r;
}
r = f;
z.istate.blocks.reset(z, z.istate.was);
if (z.istate.nowrap != 0) {
z.istate.mode = DONE;
break;
}
z.istate.mode = CHECK4;
case CHECK4:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L;
z.istate.mode = CHECK3;
case CHECK3:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L;
z.istate.mode = CHECK2;
case CHECK2:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L;
z.istate.mode = CHECK1;
case CHECK1:
if (z.avail_in == 0) return r;
r = f;
z.avail_in--;
z.total_in++;
z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);
if (((int) (z.istate.was[0])) != ((int) (z.istate.need))) {
z.istate.mode = BAD;
z.msg = "incorrect data check";
z.istate.marker = 5; // can't try inflateSync
break;
}
z.istate.mode = DONE;
case DONE:
return Z_STREAM_END;
case BAD:
return Z_DATA_ERROR;
default:
return Z_STREAM_ERROR;
}
}
}
int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) {
int index = 0;
int length = dictLength;
if (z == null || z.istate == null || z.istate.mode != DICT0)
return Z_STREAM_ERROR;
if (z._adler.adler32(1L, dictionary, 0, dictLength) != z.adler) {
return Z_DATA_ERROR;
}
z.adler = z._adler.adler32(0, null, 0, 0);
if (length >= (1 << z.istate.wbits)) {
length = (1 << z.istate.wbits) - 1;
index = dictLength - length;
}
z.istate.blocks.set_dictionary(dictionary, index, length);
z.istate.mode = BLOCKS;
return Z_OK;
}
static private byte[] mark = {(byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff};
int inflateSync(ZStream z) {
int n; // number of bytes to look at
int p; // pointer to bytes
int m; // number of marker bytes found in a row
long r, w; // temporaries to save total_in and total_out
// set up
if (z == null || z.istate == null)
return Z_STREAM_ERROR;
if (z.istate.mode != BAD) {
z.istate.mode = BAD;
z.istate.marker = 0;
}
if ((n = z.avail_in) == 0)
return Z_BUF_ERROR;
p = z.next_in_index;
m = z.istate.marker;
// search
while (n != 0 && m < 4) {
if (z.next_in[p] == mark[m]) {
m++;
} else if (z.next_in[p] != 0) {
m = 0;
} else {
m = 4 - m;
}
p++;
n--;
}
// restore
z.total_in += p - z.next_in_index;
z.next_in_index = p;
z.avail_in = n;
z.istate.marker = m;
// return no joy or set up to restart on a new block
if (m != 4) {
return Z_DATA_ERROR;
}
r = z.total_in;
w = z.total_out;
inflateReset(z);
z.total_in = r;
z.total_out = w;
z.istate.mode = BLOCKS;
return Z_OK;
}
// Returns true if inflate is currently at the end of a block generated
// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
// implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
// but removes the length bytes of the resulting empty stored block. When
// decompressing, PPP checks that at the end of input packet, inflate is
// waiting for these length bytes.
int inflateSyncPoint(ZStream z) {
if (z == null || z.istate == null || z.istate.blocks == null)
return Z_STREAM_ERROR;
return z.istate.blocks.sync_point();
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final public class JZlib {
private static final String version = "1.0.2";
public static String version() {
return version;
}
// compression levels
static final public int Z_NO_COMPRESSION = 0;
static final public int Z_BEST_SPEED = 1;
static final public int Z_BEST_COMPRESSION = 9;
static final public int Z_DEFAULT_COMPRESSION = (-1);
// compression strategy
static final public int Z_FILTERED = 1;
static final public int Z_HUFFMAN_ONLY = 2;
static final public int Z_DEFAULT_STRATEGY = 0;
static final public int Z_NO_FLUSH = 0;
static final public int Z_PARTIAL_FLUSH = 1;
static final public int Z_SYNC_FLUSH = 2;
static final public int Z_FULL_FLUSH = 3;
static final public int Z_FINISH = 4;
static final public int Z_OK = 0;
static final public int Z_STREAM_END = 1;
static final public int Z_NEED_DICT = 2;
static final public int Z_ERRNO = -1;
static final public int Z_STREAM_ERROR = -2;
static final public int Z_DATA_ERROR = -3;
static final public int Z_MEM_ERROR = -4;
static final public int Z_BUF_ERROR = -5;
static final public int Z_VERSION_ERROR = -6;
}
JZlib 0.0.* were released under the GNU LGPL license. Later, we have switched
over to a BSD-style license.
------------------------------------------------------------------------------
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
JZlib
zlib in pure Java(TM)
by ymnk@jcraft.com, JCraft,Inc.
http://www.jcraft.com/jzlib/
Last modified: Fri Feb 14 13:31:26 UTC 2003
Description
===========
JZlib is a re-implementation of zlib in pure Java.
The first and final aim for hacking this stuff is
to add the packet compression support to pure Java SSH systems.
Documentation
=============
* README files all over the source tree have info related to the stuff
in the directories.
* ChangeLog: what changed from the previous version?
* LICENSE.txt
Directories & Files in the Source Tree
======================================
* com/ has source trees of JZlib.
* example/ has some samples, which demonstrate the usages.
* misc/ has some stuffs. At present, this directory includes
a patch file for MindTerm v.1.2.1, which adds the packet compression
functionality.
Features
========
* Needless to say, JZlib can inflate data, which is deflated by zlib and
JZlib can generate deflated data, which is acceptable and inflated by zlib.
* JZlib supports all compression level and all flushing mode in zlib.
* JZlib does not support gzip file handling supports.
* The performance has not been estimated yet, but it will be not so bad
in deflating/inflating data stream on the low bandwidth network.
* JZlib is licensed under BSD style license.
* Any invention has not been done in developing JZlib.
So, if zlib is patent free, JZlib is also not covered by any patents.
Why JZlib?
==========
Java Platform API provides packages 'java.util.zip.*' for
accessing to zlib, but that support is very limited
if you need to use the essence of zlib. For example,
we needed to full access to zlib to add the packet compression
support to pure Java SSH system, but they are useless for our requirements.
The Internet draft, SSH Transport Layer Protocol, says in the section '4.2 Compression' as follows,
The following compression methods are currently defined:
none REQUIRED no compression
zlib OPTIONAL GNU ZLIB (LZ77) compression
The "zlib" compression is described in [RFC-1950] and in [RFC-1951]. The
compression context is initialized after each key exchange, and is
passed from one packet to the next with only a partial flush being
performed at the end of each packet. A partial flush means that all data
will be output, but the next packet will continue using compression
tables from the end of the previous packet.
To implement this functionality, the Z_PARTIAL_FLUSH mode of zlib must be
used, however JDK does not permit us to do so. It seems that this problem has
been well known and some people have already reported to
JavaSoft's BugParade(for example, BugId:4255743),
but any positive response has not been returned from JavaSoft,
so this problem will not be solved forever.
This is our motivation to hack JZlib.
A unofficial patch for MindTerm v.1.2.1
=======================================
A unofficial patch file for MindTerm v.1.2.1 has included in 'misc' directory.
It adds the packet compression support to MindTerm.
Please refer to 'misc/README' file.
Copyrights & Disclaimers
========================
JZlib is copyrighted by ymnk, JCraft,Inc. and is licensed through BSD
style license. Read the LICENSE.txt file for the complete license.
ZInputStream and ZOutputStream classes were contributed by Lapo Luchini.
Credits
=======
JZlib has been developed by ymnk@jcraft.com,
but he has just re-implemented zlib in pure Java.
So, all credit should go to authors Jean-loup Gailly and Mark Adler
and contributors of zlib. Here is the copyright notice of zlib version 1.1.3,
|Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
|
|This software is provided 'as-is', without any express or implied
|warranty. In no event will the authors be held liable for any damages
|arising from the use of this software.
|
|Permission is granted to anyone to use this software for any purpose,
|including commercial applications, and to alter it and redistribute it
|freely, subject to the following restrictions:
|
|1. The origin of this software must not be misrepresented; you must not
| claim that you wrote the original software. If you use this software
| in a product, an acknowledgment in the product documentation would be
| appreciated but is not required.
|2. Altered source versions must be plainly marked as such, and must not be
| misrepresented as being the original software.
|3. This notice may not be removed or altered from any source distribution.
|
|Jean-loup Gailly Mark Adler
|jloup@gzip.org madler@alumni.caltech.edu
If you have any comments, suggestions and questions, write us
at jzlib@jcraft.com
``SSH is a registered trademark and Secure Shell is a trademark of
SSH Communications Security Corp (www.ssh.com)''.
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class StaticTree {
static final private int MAX_BITS = 15;
static final private int BL_CODES = 19;
static final private int D_CODES = 30;
static final private int LITERALS = 256;
static final private int LENGTH_CODES = 29;
static final private int L_CODES = (LITERALS + 1 + LENGTH_CODES);
// Bit length codes must not exceed MAX_BL_BITS bits
static final int MAX_BL_BITS = 7;
static final short[] static_ltree = {
12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
163, 8, 99, 8, 227, 8
};
static final short[] static_dtree = {
0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
19, 5, 11, 5, 27, 5, 7, 5, 23, 5
};
static StaticTree static_l_desc =
new StaticTree(static_ltree, Tree.extra_lbits,
LITERALS + 1, L_CODES, MAX_BITS);
static StaticTree static_d_desc =
new StaticTree(static_dtree, Tree.extra_dbits,
0, D_CODES, MAX_BITS);
static StaticTree static_bl_desc =
new StaticTree(null, Tree.extra_blbits,
0, BL_CODES, MAX_BL_BITS);
short[] static_tree; // static tree or null
int[] extra_bits; // extra bits for each code or null
int extra_base; // base index for extra_bits
int elems; // max number of elements in the tree
int max_length; // max bit length for the codes
StaticTree(short[] static_tree,
int[] extra_bits,
int extra_base,
int elems,
int max_length
) {
this.static_tree = static_tree;
this.extra_bits = extra_bits;
this.extra_base = extra_base;
this.elems = elems;
this.max_length = max_length;
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final class Tree {
static final private int MAX_BITS = 15;
static final private int BL_CODES = 19;
static final private int D_CODES = 30;
static final private int LITERALS = 256;
static final private int LENGTH_CODES = 29;
static final private int L_CODES = (LITERALS + 1 + LENGTH_CODES);
static final private int HEAP_SIZE = (2 * L_CODES + 1);
// Bit length codes must not exceed MAX_BL_BITS bits
static final int MAX_BL_BITS = 7;
// end of block literal code
static final int END_BLOCK = 256;
// repeat previous bit length 3-6 times (2 bits of repeat count)
static final int REP_3_6 = 16;
// repeat a zero length 3-10 times (3 bits of repeat count)
static final int REPZ_3_10 = 17;
// repeat a zero length 11-138 times (7 bits of repeat count)
static final int REPZ_11_138 = 18;
// extra bits for each length code
static final int[] extra_lbits = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
};
// extra bits for each distance code
static final int[] extra_dbits = {
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
};
// extra bits for each bit length code
static final int[] extra_blbits = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7
};
static final byte[] bl_order = {
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
// The lengths of the bit length codes are sent in order of decreasing
// probability, to avoid transmitting the lengths for unused bit
// length codes.
static final int Buf_size = 8 * 2;
// see definition of array dist_code below
static final int DIST_CODE_LEN = 512;
static final byte[] _dist_code = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
static final byte[] _length_code = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
static final int[] base_length = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};
static final int[] base_dist = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};
// Mapping from a distance to a distance code. dist is the distance - 1 and
// must not have side effects. _dist_code[256] and _dist_code[257] are never
// used.
static int d_code(int dist) {
return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);
}
short[] dyn_tree; // the dynamic tree
int max_code; // largest code with non zero frequency
StaticTree stat_desc; // the corresponding static tree
// Compute the optimal bit lengths for a tree and update the total bit length
// for the current block.
// IN assertion: the fields freq and dad are set, heap[heap_max] and
// above are the tree nodes sorted by increasing frequency.
// OUT assertions: the field len is set to the optimal bit length, the
// array bl_count contains the frequencies for each bit length.
// The length opt_len is updated; static_len is also updated if stree is
// not null.
void gen_bitlen(Deflate s) {
short[] tree = dyn_tree;
short[] stree = stat_desc.static_tree;
int[] extra = stat_desc.extra_bits;
int base = stat_desc.extra_base;
int max_length = stat_desc.max_length;
int h; // heap index
int n, m; // iterate over the tree elements
int bits; // bit length
int xbits; // extra bits
short f; // frequency
int overflow = 0; // number of elements with bit length too large
for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
// In a first pass, compute the optimal bit lengths (which may
// overflow in the case of the bit length tree).
tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
n = s.heap[h];
bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
if (bits > max_length) {
bits = max_length;
overflow++;
}
tree[n * 2 + 1] = (short) bits;
// We overwrite tree[n*2+1] which is no longer needed
if (n > max_code) continue; // not a leaf node
s.bl_count[bits]++;
xbits = 0;
if (n >= base) xbits = extra[n - base];
f = tree[n * 2];
s.opt_len += f * (bits + xbits);
if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
}
if (overflow == 0) return;
// This happens for example on obj2 and pic of the Calgary corpus
// Find the first bit length which could increase:
do {
bits = max_length - 1;
while (s.bl_count[bits] == 0) bits--;
s.bl_count[bits]--; // move one leaf down the tree
s.bl_count[bits + 1] += 2; // move one overflow item as its brother
s.bl_count[max_length]--;
// The brother of the overflow item also moves one step up,
// but this does not affect bl_count[max_length]
overflow -= 2;
}
while (overflow > 0);
for (bits = max_length; bits != 0; bits--) {
n = s.bl_count[bits];
while (n != 0) {
m = s.heap[--h];
if (m > max_code) continue;
if (tree[m * 2 + 1] != bits) {
s.opt_len += ((long) bits - (long) tree[m * 2 + 1]) * (long) tree[m * 2];
tree[m * 2 + 1] = (short) bits;
}
n--;
}
}
}
// Construct one Huffman tree and assigns the code bit strings and lengths.
// Update the total bit length for the current block.
// IN assertion: the field freq is set for all tree elements.
// OUT assertions: the fields len and code are set to the optimal bit length
// and corresponding code. The length opt_len is updated; static_len is
// also updated if stree is not null. The field max_code is set.
void build_tree(Deflate s) {
short[] tree = dyn_tree;
short[] stree = stat_desc.static_tree;
int elems = stat_desc.elems;
int n, m; // iterate over heap elements
int max_code = -1; // largest code with non zero frequency
int node; // new node being created
// Construct the initial heap, with least frequent element in
// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
// heap[0] is not used.
s.heap_len = 0;
s.heap_max = HEAP_SIZE;
for (n = 0; n < elems; n++) {
if (tree[n * 2] != 0) {
s.heap[++s.heap_len] = max_code = n;
s.depth[n] = 0;
} else {
tree[n * 2 + 1] = 0;
}
}
// The pkzip format requires that at least one distance code exists,
// and that at least one bit should be sent even if there is only one
// possible code. So to avoid special checks later on we force at least
// two codes of non zero frequency.
while (s.heap_len < 2) {
node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
tree[node * 2] = 1;
s.depth[node] = 0;
s.opt_len--;
if (stree != null) s.static_len -= stree[node * 2 + 1];
// node is 0 or 1 so it does not have extra bits
}
this.max_code = max_code;
// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
// establish sub-heaps of increasing lengths:
for (n = s.heap_len / 2; n >= 1; n--)
s.pqdownheap(tree, n);
// Construct the Huffman tree by repeatedly combining the least two
// frequent nodes.
node = elems; // next internal node of the tree
do {
// n = node of least frequency
n = s.heap[1];
s.heap[1] = s.heap[s.heap_len--];
s.pqdownheap(tree, 1);
m = s.heap[1]; // m = node of next least frequency
s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
s.heap[--s.heap_max] = m;
// Create a new node father of n and m
tree[node * 2] = (short) (tree[n * 2] + tree[m * 2]);
s.depth[node] = (byte) (Math.max(s.depth[n], s.depth[m]) + 1);
tree[n * 2 + 1] = tree[m * 2 + 1] = (short) node;
// and insert the new node in the heap
s.heap[1] = node++;
s.pqdownheap(tree, 1);
}
while (s.heap_len >= 2);
s.heap[--s.heap_max] = s.heap[1];
// At this point, the fields freq and dad are set. We can now
// generate the bit lengths.
gen_bitlen(s);
// The field len is now set, we can generate the bit codes
gen_codes(tree, max_code, s.bl_count);
}
// Generate the codes for a given tree and bit counts (which need not be
// optimal).
// IN assertion: the array bl_count contains the bit length statistics for
// the given tree and the field len is set for all tree elements.
// OUT assertion: the field code is set for all tree elements of non
// zero code length.
static void gen_codes(short[] tree, // the tree to decorate
int max_code, // largest code with non zero frequency
short[] bl_count // number of codes at each bit length
) {
short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
short code = 0; // running code value
int bits; // bit index
int n; // code index
// The distribution counts are first used to generate the code values
// without bit reversal.
for (bits = 1; bits <= MAX_BITS; bits++) {
next_code[bits] = code = (short) ((code + bl_count[bits - 1]) << 1);
}
// Check that the bit counts in bl_count are consistent. The last code
// must be all ones.
//Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
// "inconsistent bit counts");
//Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
for (n = 0; n <= max_code; n++) {
int len = tree[n * 2 + 1];
if (len == 0) continue;
// Now reverse the bits
tree[n * 2] = (short) (bi_reverse(next_code[len]++, len));
}
}
// Reverse the first len bits of a code, using straightforward code (a faster
// method would use a table)
// IN assertion: 1 <= len <= 15
static int bi_reverse(int code, // the value to invert
int len // its bit length
) {
int res = 0;
do {
res |= code & 1;
code >>>= 1;
res <<= 1;
}
while (--len > 0);
return res >>> 1;
}
}
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2001 Lapo Luchini.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
import java.io.*;
public class ZInputStream extends FilterInputStream {
protected ZStream z = new ZStream();
protected int bufsize = 512;
protected int flush = JZlib.Z_NO_FLUSH;
protected byte[] buf = new byte[bufsize],
buf1 = new byte[1];
protected boolean compress;
protected InputStream in = null;
public ZInputStream(InputStream in) {
this(in, false);
}
public ZInputStream(InputStream in, boolean nowrap) {
super(in);
this.in = in;
z.inflateInit(nowrap);
compress = false;
z.next_in = buf;
z.next_in_index = 0;
z.avail_in = 0;
}
public ZInputStream(InputStream in, int level) {
super(in);
this.in = in;
z.deflateInit(level);
compress = true;
z.next_in = buf;
z.next_in_index = 0;
z.avail_in = 0;
}
/*public int available() throws IOException {
return inf.finished() ? 0 : 1;
}*/
public int read() throws IOException {
if (read(buf1, 0, 1) == -1)
return (-1);
return (buf1[0] & 0xFF);
}
private boolean nomoreinput = false;
public int read(byte[] b, int off, int len) throws IOException {
if (len == 0)
return (0);
int err;
z.next_out = b;
z.next_out_index = off;
z.avail_out = len;
do {
if ((z.avail_in == 0) && (!nomoreinput)) { // if buffer is empty and more input is avaiable, refill it
z.next_in_index = 0;
z.avail_in = in.read(buf, 0, bufsize);//(bufsize<z.avail_out ? bufsize : z.avail_out));
if (z.avail_in == -1) {
z.avail_in = 0;
nomoreinput = true;
}
}
if (compress)
err = z.deflate(flush);
else
err = z.inflate(flush);
if (nomoreinput && (err == JZlib.Z_BUF_ERROR))
return (-1);
if (err != JZlib.Z_OK && err != JZlib.Z_STREAM_END)
throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
if ((nomoreinput || err == JZlib.Z_STREAM_END) && (z.avail_out == len))
return (-1);
}
while (z.avail_out == len && err == JZlib.Z_OK);
//System.err.print("("+(len-z.avail_out)+")");
return (len - z.avail_out);
}
public long skip(long n) throws IOException {
int len = 512;
if (n < len)
len = (int) n;
byte[] tmp = new byte[len];
return ((long) read(tmp));
}
public int getFlushMode() {
return (flush);
}
public void setFlushMode(int flush) {
this.flush = flush;
}
/**
* Returns the total number of bytes input so far.
*/
public long getTotalIn() {
return z.total_in;
}
/**
* Returns the total number of bytes output so far.
*/
public long getTotalOut() {
return z.total_out;
}
public void close() throws IOException {
in.close();
}
}
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2001 Lapo Luchini.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
import java.io.*;
public class ZOutputStream extends OutputStream {
protected ZStream z = new ZStream();
protected int bufsize = 512;
protected int flush = JZlib.Z_NO_FLUSH;
protected byte[] buf = new byte[bufsize],
buf1 = new byte[1];
protected boolean compress;
protected OutputStream out;
public ZOutputStream(OutputStream out) {
super();
this.out = out;
z.inflateInit();
compress = false;
}
public ZOutputStream(OutputStream out, int level) {
this(out, level, false);
}
public ZOutputStream(OutputStream out, int level, boolean nowrap) {
super();
this.out = out;
z.deflateInit(level, nowrap);
compress = true;
}
public void write(int b) throws IOException {
buf1[0] = (byte) b;
write(buf1, 0, 1);
}
public void write(byte b[], int off, int len) throws IOException {
if (len == 0)
return;
int err;
z.next_in = b;
z.next_in_index = off;
z.avail_in = len;
do {
z.next_out = buf;
z.next_out_index = 0;
z.avail_out = bufsize;
if (compress)
err = z.deflate(flush);
else
err = z.inflate(flush);
if (err != JZlib.Z_OK)
throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
out.write(buf, 0, bufsize - z.avail_out);
}
while (z.avail_in > 0 || z.avail_out == 0);
}
public int getFlushMode() {
return (flush);
}
public void setFlushMode(int flush) {
this.flush = flush;
}
public void finish() throws IOException {
int err;
do {
z.next_out = buf;
z.next_out_index = 0;
z.avail_out = bufsize;
if (compress) {
err = z.deflate(JZlib.Z_FINISH);
} else {
err = z.inflate(JZlib.Z_FINISH);
}
if (err != JZlib.Z_STREAM_END && err != JZlib.Z_OK)
throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
if (bufsize - z.avail_out > 0) {
out.write(buf, 0, bufsize - z.avail_out);
}
}
while (z.avail_in > 0 || z.avail_out == 0);
flush();
}
public void end() {
if (z == null)
return;
if (compress) {
z.deflateEnd();
} else {
z.inflateEnd();
}
z.free();
z = null;
}
public void close() throws IOException {
try {
try {
finish();
} catch (IOException ignored) {
}
} finally {
end();
out.close();
out = null;
}
}
/**
* Returns the total number of bytes input so far.
*/
public long getTotalIn() {
return z.total_in;
}
/**
* Returns the total number of bytes output so far.
*/
public long getTotalOut() {
return z.total_out;
}
public void flush() throws IOException {
out.flush();
}
}
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
final public class ZStream {
static final private int MAX_WBITS = 15; // 32K LZ77 window
static final private int DEF_WBITS = MAX_WBITS;
static final private int Z_NO_FLUSH = 0;
static final private int Z_PARTIAL_FLUSH = 1;
static final private int Z_SYNC_FLUSH = 2;
static final private int Z_FULL_FLUSH = 3;
static final private int Z_FINISH = 4;
static final private int MAX_MEM_LEVEL = 9;
static final private int Z_OK = 0;
static final private int Z_STREAM_END = 1;
static final private int Z_NEED_DICT = 2;
static final private int Z_ERRNO = -1;
static final private int Z_STREAM_ERROR = -2;
static final private int Z_DATA_ERROR = -3;
static final private int Z_MEM_ERROR = -4;
static final private int Z_BUF_ERROR = -5;
static final private int Z_VERSION_ERROR = -6;
public byte[] next_in; // next input byte
public int next_in_index;
public int avail_in; // number of bytes available at next_in
public long total_in; // total nb of input bytes read so far
public byte[] next_out; // next output byte should be put there
public int next_out_index;
public int avail_out; // remaining free space at next_out
public long total_out; // total nb of bytes output so far
public String msg;
Deflate dstate;
Inflate istate;
int data_type; // best guess about the data type: ascii or binary
public long adler;
Adler32 _adler = new Adler32();
public int inflateInit() {
return inflateInit(DEF_WBITS);
}
public int inflateInit(boolean nowrap) {
return inflateInit(DEF_WBITS, nowrap);
}
public int inflateInit(int w) {
return inflateInit(w, false);
}
public int inflateInit(int w, boolean nowrap) {
istate = new Inflate();
return istate.inflateInit(this, nowrap ? -w : w);
}
public int inflate(int f) {
if (istate == null) return Z_STREAM_ERROR;
return istate.inflate(this, f);
}
public int inflateEnd() {
if (istate == null) return Z_STREAM_ERROR;
int ret = istate.inflateEnd(this);
istate = null;
return ret;
}
public int inflateSync() {
if (istate == null)
return Z_STREAM_ERROR;
return istate.inflateSync(this);
}
public int inflateSetDictionary(byte[] dictionary, int dictLength) {
if (istate == null)
return Z_STREAM_ERROR;
return istate.inflateSetDictionary(this, dictionary, dictLength);
}
public int deflateInit(int level) {
return deflateInit(level, MAX_WBITS);
}
public int deflateInit(int level, boolean nowrap) {
return deflateInit(level, MAX_WBITS, nowrap);
}
public int deflateInit(int level, int bits) {
return deflateInit(level, bits, false);
}
public int deflateInit(int level, int bits, boolean nowrap) {
dstate = new Deflate();
return dstate.deflateInit(this, level, nowrap ? -bits : bits);
}
public int deflate(int flush) {
if (dstate == null) {
return Z_STREAM_ERROR;
}
return dstate.deflate(this, flush);
}
public int deflateEnd() {
if (dstate == null) return Z_STREAM_ERROR;
int ret = dstate.deflateEnd();
dstate = null;
return ret;
}
public int deflateParams(int level, int strategy) {
if (dstate == null) return Z_STREAM_ERROR;
return dstate.deflateParams(this, level, strategy);
}
public int deflateSetDictionary(byte[] dictionary, int dictLength) {
if (dstate == null)
return Z_STREAM_ERROR;
return dstate.deflateSetDictionary(this, dictionary, dictLength);
}
// Flush as much pending output as possible. All deflate() output goes
// through this function so some applications may wish to modify it
// to avoid allocating a large strm->next_out buffer and copying into it.
// (See also read_buf()).
void flush_pending() {
int len = dstate.pending;
if (len > avail_out) len = avail_out;
if (len == 0) return;
if (dstate.pending_buf.length <= dstate.pending_out ||
next_out.length <= next_out_index ||
dstate.pending_buf.length < (dstate.pending_out + len) ||
next_out.length < (next_out_index + len)) {
System.out.println(dstate.pending_buf.length + ", " + dstate.pending_out +
", " + next_out.length + ", " + next_out_index + ", " + len);
System.out.println("avail_out=" + avail_out);
}
System.arraycopy(dstate.pending_buf, dstate.pending_out,
next_out, next_out_index, len);
next_out_index += len;
dstate.pending_out += len;
total_out += len;
avail_out -= len;
dstate.pending -= len;
if (dstate.pending == 0) {
dstate.pending_out = 0;
}
}
// Read a new buffer from the current input stream, update the adler32
// and total number of bytes read. All deflate() input goes through
// this function so some applications may wish to modify it to avoid
// allocating a large strm->next_in buffer and copying from it.
// (See also flush_pending()).
int read_buf(byte[] buf, int start, int size) {
int len = avail_in;
if (len > size) len = size;
if (len == 0) return 0;
avail_in -= len;
if (dstate.noheader == 0) {
adler = _adler.adler32(adler, next_in, next_in_index, len);
}
System.arraycopy(next_in, next_in_index, buf, start, len);
next_in_index += len;
total_in += len;
return len;
}
public void free() {
next_in = null;
next_out = null;
msg = null;
_adler = null;
}
}
/* -*-mode:java; c-basic-offset:2; -*- */
/*
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This program is based on zlib-1.1.3, so all credit should go authors
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
* and contributors of zlib.
*/
package com.jcraft.jzlib;
public class ZStreamException extends java.io.IOException {
public ZStreamException() {
super();
}
public ZStreamException(String s) {
super(s);
}
}
...@@ -66,10 +66,8 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -66,10 +66,8 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
private final EntityNotificationProvider<RoomAuthorizationError> authorizationErrorProvider; private final EntityNotificationProvider<RoomAuthorizationError> authorizationErrorProvider;
private MUCManager() { private MUCManager() {
inviteProvider = new EntityNotificationProvider<RoomInvite>( inviteProvider = new EntityNotificationProvider<>(R.drawable.ic_stat_add_circle);
R.drawable.ic_stat_add_circle); authorizationErrorProvider = new EntityNotificationProvider<>(R.drawable.ic_stat_error);
authorizationErrorProvider = new EntityNotificationProvider<RoomAuthorizationError>(
R.drawable.ic_stat_error);
} }
public static MUCManager getInstance() { public static MUCManager getInstance() {
...@@ -78,19 +76,18 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -78,19 +76,18 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
@Override @Override
public void onLoad() { public void onLoad() {
final Collection<RoomChat> roomChats = new ArrayList<RoomChat>(); final Collection<RoomChat> roomChats = new ArrayList<>();
final Collection<RoomChat> needJoins = new ArrayList<RoomChat>(); final Collection<RoomChat> needJoins = new ArrayList<>();
Cursor cursor = RoomTable.getInstance().list(); Cursor cursor = RoomTable.getInstance().list();
try { try {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
do { do {
RoomChat roomChat = new RoomChat( RoomChat roomChat = new RoomChat(
RoomTable.getAccount(cursor), RoomTable.getAccount(cursor), RoomTable.getRoom(cursor),
RoomTable.getRoom(cursor), RoomTable.getNickname(cursor), RoomTable.getPassword(cursor));
RoomTable.getNickname(cursor), if (RoomTable.needJoin(cursor)) {
RoomTable.getPassword(cursor));
if (RoomTable.needJoin(cursor))
needJoins.add(roomChat); needJoins.add(roomChat);
}
roomChats.add(roomChat); roomChats.add(roomChat);
} while (cursor.moveToNext()); } while (cursor.moveToNext());
} }
...@@ -105,38 +102,34 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -105,38 +102,34 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
}); });
} }
private void onLoaded(Collection<RoomChat> roomChats, private void onLoaded(Collection<RoomChat> roomChats, Collection<RoomChat> needJoins) {
Collection<RoomChat> needJoins) {
for (RoomChat roomChat : roomChats) { for (RoomChat roomChat : roomChats) {
AbstractChat abstractChat = MessageManager.getInstance().getChat( AbstractChat abstractChat = MessageManager.getInstance().getChat(
roomChat.getAccount(), roomChat.getUser()); roomChat.getAccount(), roomChat.getUser());
if (abstractChat != null) if (abstractChat != null) {
MessageManager.getInstance().removeChat(abstractChat); MessageManager.getInstance().removeChat(abstractChat);
}
MessageManager.getInstance().addChat(roomChat); MessageManager.getInstance().addChat(roomChat);
if (needJoins.contains(roomChat)) if (needJoins.contains(roomChat)) {
roomChat.setState(RoomState.waiting); roomChat.setState(RoomState.waiting);
}
} }
NotificationManager.getInstance().registerNotificationProvider( NotificationManager.getInstance().registerNotificationProvider(inviteProvider);
inviteProvider); NotificationManager.getInstance().registerNotificationProvider(authorizationErrorProvider);
NotificationManager.getInstance().registerNotificationProvider(
authorizationErrorProvider);
} }
/** /**
* @param account
* @param room
* @return <code>null</code> if does not exists. * @return <code>null</code> if does not exists.
*/ */
private RoomChat getRoomChat(String account, String room) { private RoomChat getRoomChat(String account, String room) {
AbstractChat chat = MessageManager.getInstance().getChat(account, room); AbstractChat chat = MessageManager.getInstance().getChat(account, room);
if (chat != null && chat instanceof RoomChat) if (chat != null && chat instanceof RoomChat) {
return (RoomChat) chat; return (RoomChat) chat;
}
return null; return null;
} }
/** /**
* @param account
* @param room
* @return Whether there is such room. * @return Whether there is such room.
*/ */
public boolean hasRoom(String account, String room) { public boolean hasRoom(String account, String room) {
...@@ -144,14 +137,13 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -144,14 +137,13 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
} }
/** /**
* @param account
* @param room
* @return nickname or empty string if room does not exists. * @return nickname or empty string if room does not exists.
*/ */
public String getNickname(String account, String room) { public String getNickname(String account, String room) {
RoomChat roomChat = getRoomChat(account, room); RoomChat roomChat = getRoomChat(account, room);
if (roomChat == null) if (roomChat == null) {
return ""; return "";
}
return roomChat.getNickname(); return roomChat.getNickname();
} }
...@@ -162,26 +154,24 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -162,26 +154,24 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
*/ */
public String getPassword(String account, String room) { public String getPassword(String account, String room) {
RoomChat roomChat = getRoomChat(account, room); RoomChat roomChat = getRoomChat(account, room);
if (roomChat == null) if (roomChat == null) {
return ""; return "";
}
return roomChat.getPassword(); return roomChat.getPassword();
} }
/** /**
* @param account
* @param room
* @return list of occupants or empty list. * @return list of occupants or empty list.
*/ */
public Collection<Occupant> getOccupants(String account, String room) { public Collection<Occupant> getOccupants(String account, String room) {
RoomChat roomChat = getRoomChat(account, room); RoomChat roomChat = getRoomChat(account, room);
if (roomChat == null) if (roomChat == null) {
return Collections.emptyList(); return Collections.emptyList();
}
return roomChat.getOccupants(); return roomChat.getOccupants();
} }
/** /**
* @param account
* @param room
* @return <code>null</code> if there is no such invite. * @return <code>null</code> if there is no such invite.
*/ */
public RoomInvite getInvite(String account, String room) { public RoomInvite getInvite(String account, String room) {
...@@ -195,8 +185,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -195,8 +185,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
public void removeRoom(final String account, final String room) { public void removeRoom(final String account, final String room) {
removeInvite(getInvite(account, room)); removeInvite(getInvite(account, room));
RoomChat roomChat = getRoomChat(account, room); RoomChat roomChat = getRoomChat(account, room);
if (roomChat == null) if (roomChat == null) {
return; return;
}
leaveRoom(account, room); leaveRoom(account, room);
MessageManager.getInstance().removeChat(roomChat); MessageManager.getInstance().removeChat(roomChat);
RosterManager.getInstance().onContactChanged(account, room); RosterManager.getInstance().onContactChanged(account, room);
...@@ -211,10 +202,6 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -211,10 +202,6 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
/** /**
* Creates or updates existed room. * Creates or updates existed room.
* *
* @param account
* @param room
* @param nickname
* @param password
*/ */
public void createRoom(String account, String room, String nickname, public void createRoom(String account, String room, String nickname,
String password, boolean join) { String password, boolean join) {
...@@ -222,8 +209,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -222,8 +209,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
AbstractChat chat = MessageManager.getInstance().getChat(account, room); AbstractChat chat = MessageManager.getInstance().getChat(account, room);
RoomChat roomChat; RoomChat roomChat;
if (chat == null || !(chat instanceof RoomChat)) { if (chat == null || !(chat instanceof RoomChat)) {
if (chat != null) if (chat != null) {
MessageManager.getInstance().removeChat(chat); MessageManager.getInstance().removeChat(chat);
}
roomChat = new RoomChat(account, room, nickname, password); roomChat = new RoomChat(account, room, nickname, password);
MessageManager.getInstance().addChat(roomChat); MessageManager.getInstance().addChat(roomChat);
} else { } else {
...@@ -232,8 +220,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -232,8 +220,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
roomChat.setPassword(password); roomChat.setPassword(password);
} }
requestToWriteRoom(account, room, nickname, password, join); requestToWriteRoom(account, room, nickname, password, join);
if (join) if (join) {
joinRoom(account, room, true); joinRoom(account, room, true);
}
} }
private void requestToWriteRoom(final String account, final String room, private void requestToWriteRoom(final String account, final String room,
...@@ -248,8 +237,6 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -248,8 +237,6 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
} }
/** /**
* @param account
* @param room
* @return Whether room is disabled. * @return Whether room is disabled.
*/ */
public boolean isDisabled(final String account, final String room) { public boolean isDisabled(final String account, final String room) {
...@@ -258,8 +245,6 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -258,8 +245,6 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
} }
/** /**
* @param account
* @param room
* @return Whether connected is establish or connection is in progress. * @return Whether connected is establish or connection is in progress.
*/ */
public boolean inUse(final String account, final String room) { public boolean inUse(final String account, final String room) {
...@@ -270,12 +255,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -270,12 +255,9 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
/** /**
* Requests to join to the room. * Requests to join to the room.
* *
* @param account
* @param room
* @param requested Whether user request to join the room. * @param requested Whether user request to join the room.
*/ */
public void joinRoom(final String account, final String room, public void joinRoom(final String account, final String room, boolean requested) {
boolean requested) {
final XMPPConnection xmppConnection; final XMPPConnection xmppConnection;
final RoomChat roomChat; final RoomChat roomChat;
final String nickname; final String nickname;
...@@ -323,19 +305,21 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -323,19 +305,21 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
@Override @Override
public void run() { public void run() {
try { try {
if (roomChat.getMultiUserChat() != multiUserChat) if (roomChat.getMultiUserChat() != multiUserChat) {
return; return;
}
multiUserChat.join(nickname, password); multiUserChat.join(nickname, password);
Application.getInstance().runOnUiThread(new Runnable() { Application.getInstance().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (roomChat.getMultiUserChat() != multiUserChat) if (roomChat.getMultiUserChat() != multiUserChat) {
return; return;
if (roomChat.getState() == RoomState.joining) }
if (roomChat.getState() == RoomState.joining) {
roomChat.setState(RoomState.occupation); roomChat.setState(RoomState.occupation);
}
removeAuthorizationError(account, room); removeAuthorizationError(account, room);
RosterManager.getInstance().onContactChanged( RosterManager.getInstance().onContactChanged(account, room);
account, room);
} }
}); });
return; return;
...@@ -343,42 +327,35 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -343,42 +327,35 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
Application.getInstance().runOnUiThread(new Runnable() { Application.getInstance().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (roomChat.getMultiUserChat() != multiUserChat) if (roomChat.getMultiUserChat() != multiUserChat) {
return; return;
}
roomChat.setState(RoomState.error); roomChat.setState(RoomState.error);
addAuthorizationError(account, room); addAuthorizationError(account, room);
if (e.getXMPPError() != null if (e.getXMPPError() != null && e.getXMPPError().getCode() == 409) {
&& e.getXMPPError().getCode() == 409) Application.getInstance().onError(R.string.NICK_ALREADY_USED);
Application.getInstance().onError( } else if (e.getXMPPError() != null && e.getXMPPError().getCode() == 401) {
R.string.NICK_ALREADY_USED); Application.getInstance().onError(R.string.AUTHENTICATION_FAILED);
else if (e.getXMPPError() != null } else {
&& e.getXMPPError().getCode() == 401) Application.getInstance().onError(R.string.NOT_CONNECTED);
Application.getInstance().onError( }
R.string.AUTHENTICATION_FAILED); RosterManager.getInstance().onContactChanged(account, room);
else
Application.getInstance().onError(
R.string.NOT_CONNECTED);
RosterManager.getInstance().onContactChanged(
account, room);
} }
}); });
return; return;
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
} catch (RuntimeException e) {
LogManager.exception(this, e);
} catch (Exception e) { } catch (Exception e) {
LogManager.exception(this, e); LogManager.exception(this, e);
} }
Application.getInstance().runOnUiThread(new Runnable() { Application.getInstance().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (roomChat.getMultiUserChat() != multiUserChat) if (roomChat.getMultiUserChat() != multiUserChat) {
return; return;
}
roomChat.setState(RoomState.waiting); roomChat.setState(RoomState.waiting);
Application.getInstance().onError( Application.getInstance().onError(R.string.NOT_CONNECTED);
R.string.NOT_CONNECTED); RosterManager.getInstance().onContactChanged(account, room);
RosterManager.getInstance().onContactChanged(account,
room);
} }
}); });
} }
...@@ -390,17 +367,16 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -390,17 +367,16 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
public void leaveRoom(String account, String room) { public void leaveRoom(String account, String room) {
final MultiUserChat multiUserChat; final MultiUserChat multiUserChat;
RoomChat roomChat = getRoomChat(account, room); RoomChat roomChat = getRoomChat(account, room);
if (roomChat == null) if (roomChat == null) {
return; return;
}
multiUserChat = roomChat.getMultiUserChat(); multiUserChat = roomChat.getMultiUserChat();
roomChat.setState(RoomState.unavailable); roomChat.setState(RoomState.unavailable);
roomChat.setRequested(false); roomChat.setRequested(false);
roomChat.newAction(roomChat.getNickname(), null, ChatAction.leave); roomChat.newAction(roomChat.getNickname(), null, ChatAction.leave);
requestToWriteRoom(account, room, roomChat.getNickname(), requestToWriteRoom(account, room, roomChat.getNickname(), roomChat.getPassword(), false);
roomChat.getPassword(), false);
if (multiUserChat != null) { if (multiUserChat != null) {
Thread thread = new Thread("Leave to room " + room + " from " Thread thread = new Thread("Leave to room " + room + " from " + account) {
+ account) {
@Override @Override
public void run() { public void run() {
try { try {
...@@ -417,41 +393,39 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -417,41 +393,39 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
} }
@Override @Override
public void onPacket(ConnectionItem connection, String bareAddress, public void onPacket(ConnectionItem connection, String bareAddress, Packet packet) {
Packet packet) { if (!(connection instanceof AccountItem)) {
if (!(connection instanceof AccountItem))
return; return;
}
String account = ((AccountItem) connection).getAccount(); String account = ((AccountItem) connection).getAccount();
if (bareAddress == null || !(packet instanceof Message)) if (bareAddress == null || !(packet instanceof Message)) {
return; return;
}
Message message = (Message) packet; Message message = (Message) packet;
if (message.getType() != Message.Type.normal if (message.getType() != Message.Type.normal && message.getType() != Message.Type.chat) {
&& message.getType() != Message.Type.chat)
return; return;
}
MUCUser mucUser = MUC.getMUCUserExtension(packet); MUCUser mucUser = MUC.getMUCUserExtension(packet);
if (mucUser == null || mucUser.getInvite() == null) if (mucUser == null || mucUser.getInvite() == null) {
return; return;
}
RoomChat roomChat = getRoomChat(account, bareAddress); RoomChat roomChat = getRoomChat(account, bareAddress);
if (roomChat == null || !roomChat.getState().inUse()) { if (roomChat == null || !roomChat.getState().inUse()) {
String inviter = mucUser.getInvite().getFrom(); String inviter = mucUser.getInvite().getFrom();
if (inviter == null) if (inviter == null) {
inviter = bareAddress; inviter = bareAddress;
}
inviteProvider.add(new RoomInvite(account, bareAddress, inviter, inviteProvider.add(new RoomInvite(account, bareAddress, inviter,
mucUser.getInvite().getReason(), mucUser.getPassword()), mucUser.getInvite().getReason(), mucUser.getPassword()), true);
true);
} }
} }
/** /**
* Sends invitation. * Sends invitation.
* *
* @param account
* @param room
* @param user
* @throws NetworkException * @throws NetworkException
*/ */
public void invite(String account, String room, String user) public void invite(String account, String room, String user) throws NetworkException {
throws NetworkException {
RoomChat roomChat = getRoomChat(account, room); RoomChat roomChat = getRoomChat(account, room);
if (roomChat == null || roomChat.getState() != RoomState.available) { if (roomChat == null || roomChat.getState() != RoomState.available) {
Application.getInstance().onError(R.string.NOT_CONNECTED); Application.getInstance().onError(R.string.NOT_CONNECTED);
...@@ -474,8 +448,7 @@ public class MUCManager implements OnLoadListener, OnPacketListener { ...@@ -474,8 +448,7 @@ public class MUCManager implements OnLoadListener, OnPacketListener {
} }
public void addAuthorizationError(String account, String room) { public void addAuthorizationError(String account, String room) {
authorizationErrorProvider.add( authorizationErrorProvider.add(new RoomAuthorizationError(account, room), null);
new RoomAuthorizationError(account, room), null);
} }
} }
...@@ -91,8 +91,9 @@ public class Occupant implements Comparable<Occupant> { ...@@ -91,8 +91,9 @@ public class Occupant implements Comparable<Occupant> {
@Override @Override
public int compareTo(Occupant another) { public int compareTo(Occupant another) {
int result = another.role.ordinal() - role.ordinal(); int result = another.role.ordinal() - role.ordinal();
if (result != 0) if (result != 0) {
return result; return result;
}
return nickname.compareTo(another.nickname); return nickname.compareTo(another.nickname);
} }
......
...@@ -22,8 +22,7 @@ import com.xabber.android.data.entity.BaseEntity; ...@@ -22,8 +22,7 @@ import com.xabber.android.data.entity.BaseEntity;
import com.xabber.android.data.notification.EntityNotificationItem; import com.xabber.android.data.notification.EntityNotificationItem;
import com.xabber.android.ui.ConferenceAdd; import com.xabber.android.ui.ConferenceAdd;
public class RoomAuthorizationError extends BaseEntity implements public class RoomAuthorizationError extends BaseEntity implements EntityNotificationItem {
EntityNotificationItem {
public RoomAuthorizationError(String account, String user) { public RoomAuthorizationError(String account, String user) {
super(account, user); super(account, user);
...@@ -31,8 +30,7 @@ public class RoomAuthorizationError extends BaseEntity implements ...@@ -31,8 +30,7 @@ public class RoomAuthorizationError extends BaseEntity implements
@Override @Override
public Intent getIntent() { public Intent getIntent() {
return ConferenceAdd.createIntent(Application.getInstance(), return ConferenceAdd.createIntent(Application.getInstance(), account, user);
account, user);
} }
@Override @Override
...@@ -42,8 +40,7 @@ public class RoomAuthorizationError extends BaseEntity implements ...@@ -42,8 +40,7 @@ public class RoomAuthorizationError extends BaseEntity implements
@Override @Override
public String getText() { public String getText() {
return Application.getInstance().getString( return Application.getInstance().getString(R.string.AUTHENTICATION_FAILED);
R.string.AUTHENTICATION_FAILED);
} }
} }
...@@ -85,8 +85,8 @@ public class RoomChat extends AbstractChat { ...@@ -85,8 +85,8 @@ public class RoomChat extends AbstractChat {
state = RoomState.unavailable; state = RoomState.unavailable;
subject = ""; subject = "";
multiUserChat = null; multiUserChat = null;
occupants = new HashMap<String, Occupant>(); occupants = new HashMap<>();
invites = new HashMap<String, String>(); invites = new HashMap<>();
} }
@Override @Override
...@@ -138,8 +138,9 @@ public class RoomChat extends AbstractChat { ...@@ -138,8 +138,9 @@ public class RoomChat extends AbstractChat {
occupants.clear(); occupants.clear();
invites.clear(); invites.clear();
} }
if (state == RoomState.available) if (state == RoomState.available) {
sendMessages(); sendMessages();
}
} }
Collection<Occupant> getOccupants() { Collection<Occupant> getOccupants() {
...@@ -164,15 +165,12 @@ public class RoomChat extends AbstractChat { ...@@ -164,15 +165,12 @@ public class RoomChat extends AbstractChat {
@Override @Override
protected MessageItem newMessage(String text) { protected MessageItem newMessage(String text) {
return newMessage(nickname, text, null, null, false, false, false, return newMessage(nickname, text, null, null, false, false, false, false, true);
false, true);
} }
@Override @Override
protected boolean canSendMessage() { protected boolean canSendMessage() {
if (super.canSendMessage()) return super.canSendMessage() && state == RoomState.available;
return state == RoomState.available;
return false;
} }
@Override @Override
...@@ -182,8 +180,9 @@ public class RoomChat extends AbstractChat { ...@@ -182,8 +180,9 @@ public class RoomChat extends AbstractChat {
@Override @Override
protected boolean onPacket(String bareAddress, Packet packet) { protected boolean onPacket(String bareAddress, Packet packet) {
if (!super.onPacket(bareAddress, packet)) if (!super.onPacket(bareAddress, packet)) {
return false; return false;
}
final String from = packet.getFrom(); final String from = packet.getFrom();
final String resource = StringUtils.parseResource(from); final String resource = StringUtils.parseResource(from);
if (packet instanceof Message) { if (packet instanceof Message) {
...@@ -197,36 +196,38 @@ public class RoomChat extends AbstractChat { ...@@ -197,36 +196,38 @@ public class RoomChat extends AbstractChat {
} }
MUCUser mucUser = MUC.getMUCUserExtension(packet); MUCUser mucUser = MUC.getMUCUserExtension(packet);
if (mucUser != null && mucUser.getDecline() != null) { if (mucUser != null && mucUser.getDecline() != null) {
onInvitationDeclined(mucUser.getDecline().getFrom(), mucUser onInvitationDeclined(mucUser.getDecline().getFrom(), mucUser.getDecline().getReason());
.getDecline().getReason());
return true; return true;
} }
final String text = message.getBody(); final String text = message.getBody();
final String subject = message.getSubject(); final String subject = message.getSubject();
if (text == null && subject == null) if (text == null && subject == null) {
return true; return true;
if (isSelf(resource)) // Own message }
if (isSelf(resource)) { // Own message
return true; return true;
}
if (subject != null) { if (subject != null) {
if (this.subject.equals(subject)) if (this.subject.equals(subject)) {
return true; return true;
}
this.subject = subject; this.subject = subject;
RosterManager.getInstance().onContactChanged(account, RosterManager.getInstance().onContactChanged(account, bareAddress);
bareAddress);
newAction(resource, subject, ChatAction.subject); newAction(resource, subject, ChatAction.subject);
} else { } else {
String packetID = message.getPacketID(); String packetID = message.getPacketID();
Date delay = Delay.getDelay(message); Date delay = Delay.getDelay(message);
for (MessageItem messageItem : messages) { for (MessageItem messageItem : messages) {
// Search for duplicates // Search for duplicates
if (packetID != null if (packetID != null && packetID.equals(messageItem.getPacketID())) {
&& packetID.equals(messageItem.getPacketID()))
return true; return true;
}
if (delay != null) { if (delay != null) {
if (delay.equals(messageItem.getDelayTimestamp()) if (delay.equals(messageItem.getDelayTimestamp())
&& resource.equals(messageItem.getResource()) && resource.equals(messageItem.getResource())
&& text.equals(messageItem.getText())) && text.equals(messageItem.getText())) {
return true; return true;
}
} }
} }
updateThreadId(message.getThread()); updateThreadId(message.getThread());
...@@ -246,30 +247,24 @@ public class RoomChat extends AbstractChat { ...@@ -246,30 +247,24 @@ public class RoomChat extends AbstractChat {
RosterManager.getInstance().onContactChanged(account, user); RosterManager.getInstance().onContactChanged(account, user);
} else { } else {
boolean changed = false; boolean changed = false;
if (oldOccupant.getAffiliation() != newOccupant if (oldOccupant.getAffiliation() != newOccupant.getAffiliation()) {
.getAffiliation()) {
changed = true; changed = true;
onAffiliationChanged(resource, onAffiliationChanged(resource, newOccupant.getAffiliation());
newOccupant.getAffiliation());
} }
if (oldOccupant.getRole() != newOccupant.getRole()) { if (oldOccupant.getRole() != newOccupant.getRole()) {
changed = true; changed = true;
onRoleChanged(resource, newOccupant.getRole()); onRoleChanged(resource, newOccupant.getRole());
} }
if (oldOccupant.getStatusMode() != newOccupant if (oldOccupant.getStatusMode() != newOccupant.getStatusMode()
.getStatusMode() || !oldOccupant.getStatusText().equals(newOccupant.getStatusText())) {
|| !oldOccupant.getStatusText().equals(
newOccupant.getStatusText())) {
changed = true; changed = true;
onStatusChanged(resource, newOccupant.getStatusMode(), onStatusChanged(resource, newOccupant.getStatusMode(), newOccupant.getStatusText());
newOccupant.getStatusText()); }
if (changed) {
RosterManager.getInstance().onContactChanged(account, user);
} }
if (changed)
RosterManager.getInstance().onContactChanged(account,
user);
} }
} else if (presence.getType() == Presence.Type.unavailable } else if (presence.getType() == Presence.Type.unavailable && state == RoomState.available) {
&& state == RoomState.available) {
occupants.remove(stringPrep); occupants.remove(stringPrep);
MUCUser mucUser = MUC.getMUCUserExtension(presence); MUCUser mucUser = MUC.getMUCUserExtension(presence);
if (mucUser != null && mucUser.getStatus() != null) { if (mucUser != null && mucUser.getStatus() != null) {
...@@ -280,8 +275,9 @@ public class RoomChat extends AbstractChat { ...@@ -280,8 +275,9 @@ public class RoomChat extends AbstractChat {
onBan(resource, mucUser.getItem().getActor()); onBan(resource, mucUser.getItem().getActor());
} else if ("303".equals(code)) { } else if ("303".equals(code)) {
String newNick = mucUser.getItem().getNick(); String newNick = mucUser.getItem().getNick();
if (newNick == null) if (newNick == null) {
return true; return true;
}
onRename(resource, newNick); onRename(resource, newNick);
Occupant occupant = createOccupant(newNick, presence); Occupant occupant = createOccupant(newNick, presence);
occupants.put(Jid.getStringPrep(newNick), occupant); occupants.put(Jid.getStringPrep(newNick), occupant);
...@@ -305,7 +301,6 @@ public class RoomChat extends AbstractChat { ...@@ -305,7 +301,6 @@ public class RoomChat extends AbstractChat {
} }
/** /**
* @param resource
* @return Whether resource is own nickname. * @return Whether resource is own nickname.
*/ */
private boolean isSelf(String resource) { private boolean isSelf(String resource) {
...@@ -314,9 +309,6 @@ public class RoomChat extends AbstractChat { ...@@ -314,9 +309,6 @@ public class RoomChat extends AbstractChat {
/** /**
* Informs that the invitee has declined the invitation. * Informs that the invitee has declined the invitation.
*
* @param from
* @param reason
*/ */
private void onInvitationDeclined(String from, String reason) { private void onInvitationDeclined(String from, String reason) {
// TODO // TODO
...@@ -324,38 +316,35 @@ public class RoomChat extends AbstractChat { ...@@ -324,38 +316,35 @@ public class RoomChat extends AbstractChat {
/** /**
* A occupant becomes available. * A occupant becomes available.
*
* @param resource
*/ */
private void onAvailable(String resource) { private void onAvailable(String resource) {
if (isSelf(resource)) { if (isSelf(resource)) {
setState(RoomState.available); setState(RoomState.available);
if (isRequested()) { if (isRequested()) {
if (showStatusChange()) if (showStatusChange()) {
newMessage( newMessage(resource, Application.getInstance().getString(
resource,
Application.getInstance().getString(
R.string.action_join_complete_to, user), R.string.action_join_complete_to, user),
ChatAction.complete, null, true, true, false, ChatAction.complete, null, true, true, false, false, true);
false, true); }
active = true; active = true;
setRequested(false); setRequested(false);
} else { } else {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, null, ChatAction.complete); newAction(resource, null, ChatAction.complete);
}
} }
} else { } else {
if (state == RoomState.available) if (state == RoomState.available) {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, null, ChatAction.join); newAction(resource, null, ChatAction.join);
}
}
} }
} }
/** /**
* Warning: this method should be placed with packet provider. * Warning: this method should be placed with packet provider.
* *
* @param resource
* @param presence
* @return New occupant based on presence information. * @return New occupant based on presence information.
*/ */
private Occupant createOccupant(String resource, Presence presence) { private Occupant createOccupant(String resource, Presence presence) {
...@@ -382,8 +371,9 @@ public class RoomChat extends AbstractChat { ...@@ -382,8 +371,9 @@ public class RoomChat extends AbstractChat {
statusText = presence.getStatus(); statusText = presence.getStatus();
} }
} }
if (statusText == null) if (statusText == null) {
statusText = ""; statusText = "";
}
occupant.setJid(jid); occupant.setJid(jid);
occupant.setAffiliation(affiliation); occupant.setAffiliation(affiliation);
occupant.setRole(role); occupant.setRole(role);
...@@ -398,18 +388,16 @@ public class RoomChat extends AbstractChat { ...@@ -398,18 +388,16 @@ public class RoomChat extends AbstractChat {
private void onRoleChanged(String resource, Role role) { private void onRoleChanged(String resource, Role role) {
} }
private void onStatusChanged(String resource, StatusMode statusMode, private void onStatusChanged(String resource, StatusMode statusMode, String statusText) {
String statusText) {
} }
/** /**
* A occupant leaves room. * A occupant leaves room.
*
* @param resource
*/ */
private void onLeave(String resource) { private void onLeave(String resource) {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, null, ChatAction.leave); newAction(resource, null, ChatAction.leave);
}
if (isSelf(resource)) { if (isSelf(resource)) {
setState(RoomState.waiting); setState(RoomState.waiting);
RosterManager.getInstance().onContactChanged(account, user); RosterManager.getInstance().onContactChanged(account, user);
...@@ -419,65 +407,66 @@ public class RoomChat extends AbstractChat { ...@@ -419,65 +407,66 @@ public class RoomChat extends AbstractChat {
/** /**
* A occupant was kicked. * A occupant was kicked.
* *
* @param resource
* @param actor
*/ */
private void onKick(String resource, String actor) { private void onKick(String resource, String actor) {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, actor, ChatAction.kick); newAction(resource, actor, ChatAction.kick);
if (isSelf(resource)) }
if (isSelf(resource)) {
MUCManager.getInstance().leaveRoom(account, user); MUCManager.getInstance().leaveRoom(account, user);
}
} }
/** /**
* A occupant was banned. * A occupant was banned.
* *
* @param resource
* @param actor
*/ */
private void onBan(String resource, String actor) { private void onBan(String resource, String actor) {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, actor, ChatAction.ban); newAction(resource, actor, ChatAction.ban);
if (isSelf(resource)) }
if (isSelf(resource)) {
MUCManager.getInstance().leaveRoom(account, user); MUCManager.getInstance().leaveRoom(account, user);
}
} }
/** /**
* A occupant has changed his nickname in the room. * A occupant has changed his nickname in the room.
* *
* @param resource
* @param newNick
*/ */
private void onRename(String resource, String newNick) { private void onRename(String resource, String newNick) {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, newNick, ChatAction.nickname); newAction(resource, newNick, ChatAction.nickname);
}
} }
/** /**
* A user's membership was revoked from the room * A user's membership was revoked from the room
* *
* @param resource
* @param actor
*/ */
private void onRevoke(String resource, String actor) { private void onRevoke(String resource, String actor) {
if (showStatusChange()) if (showStatusChange()) {
newAction(resource, actor, ChatAction.kick); newAction(resource, actor, ChatAction.kick);
if (isSelf(resource)) }
if (isSelf(resource)) {
MUCManager.getInstance().leaveRoom(account, user); MUCManager.getInstance().leaveRoom(account, user);
}
} }
@Override @Override
protected void onComplete() { protected void onComplete() {
super.onComplete(); super.onComplete();
if (getState() == RoomState.waiting) if (getState() == RoomState.waiting) {
MUCManager.getInstance().joinRoom(account, user, false); MUCManager.getInstance().joinRoom(account, user, false);
}
} }
@Override @Override
protected void onDisconnect() { protected void onDisconnect() {
super.onDisconnect(); super.onDisconnect();
if (state != RoomState.unavailable) if (state != RoomState.unavailable) {
setState(RoomState.waiting); setState(RoomState.waiting);
}
} }
} }
\ No newline at end of file
...@@ -46,8 +46,7 @@ public class RoomInvite extends BaseEntity implements EntityNotificationItem { ...@@ -46,8 +46,7 @@ public class RoomInvite extends BaseEntity implements EntityNotificationItem {
*/ */
private final String password; private final String password;
public RoomInvite(String account, String user, String inviter, public RoomInvite(String account, String user, String inviter, String reason, String password) {
String reason, String password) {
super(account, user); super(account, user);
this.inviter = inviter; this.inviter = inviter;
this.reason = reason == null ? "" : reason; this.reason = reason == null ? "" : reason;
...@@ -73,18 +72,17 @@ public class RoomInvite extends BaseEntity implements EntityNotificationItem { ...@@ -73,18 +72,17 @@ public class RoomInvite extends BaseEntity implements EntityNotificationItem {
* @return Text for the confirmation. * @return Text for the confirmation.
*/ */
public String getConfirmation() { public String getConfirmation() {
String accountName = AccountManager.getInstance().getVerboseName( String accountName = AccountManager.getInstance().getVerboseName(account);
account); String inviterName = RosterManager.getInstance().getName(account, inviter);
String inviterName = RosterManager.getInstance().getName(account, if (reason == null || "".equals(reason)) {
inviter);
if (reason == null || "".equals(reason))
return Application.getInstance() return Application.getInstance()
.getString(R.string.muc_invite_confirm, accountName, .getString(R.string.muc_invite_confirm, accountName,
inviterName, user); inviterName, user);
else } else {
return Application.getInstance().getString( return Application.getInstance().getString(
R.string.muc_invite_confirm_reason, accountName, R.string.muc_invite_confirm_reason, accountName,
inviterName, user, reason); inviterName, user, reason);
}
} }
public String getInviter() { public String getInviter() {
......
...@@ -62,29 +62,40 @@ public enum RoomState { ...@@ -62,29 +62,40 @@ public enum RoomState {
* @return Status mode used in contact list. * @return Status mode used in contact list.
*/ */
StatusMode toStatusMode() { StatusMode toStatusMode() {
if (this == RoomState.available) switch (this) {
return StatusMode.available; case available:
else if (this == RoomState.occupation) return StatusMode.available;
return StatusMode.connection; case occupation:
else if (this == RoomState.joining) case joining:
return StatusMode.connection; case creating:
else if (this == RoomState.creating) case waiting:
return StatusMode.connection; return StatusMode.connection;
else if (this == RoomState.unavailable) case unavailable:
return StatusMode.unavailable; return StatusMode.unavailable;
else if (this == RoomState.waiting) case error:
return StatusMode.connection; return StatusMode.unsubscribed;
else if (this == RoomState.error) default:
return StatusMode.unsubscribed; throw new IllegalStateException();
else }
throw new IllegalStateException();
} }
/** /**
* @return Connected is establish or connection is in progress. * @return Connected is establish or connection is in progress.
*/ */
boolean inUse() { boolean inUse() {
return this == RoomState.available || this == RoomState.occupation switch (this) {
|| this == RoomState.creating || this == RoomState.joining;
case available:
case occupation:
case joining:
case creating:
return true;
case unavailable:
case waiting:
case error:
default:
return false;
}
} }
} }
...@@ -56,9 +56,8 @@ class RoomTable extends AbstractAccountTable { ...@@ -56,9 +56,8 @@ class RoomTable extends AbstractAccountTable {
} }
private static final String NAME = "rooms"; private static final String NAME = "rooms";
private static final String[] PROJECTION = new String[]{Fields._ID, private static final String[] PROJECTION = new String[]{ Fields._ID,
Fields.ACCOUNT, Fields.ROOM, Fields.NICKNAME, Fields.PASSWORD, Fields.ACCOUNT, Fields.ROOM, Fields.NICKNAME, Fields.PASSWORD, Fields.NEED_JOIN };
Fields.NEED_JOIN,};
private final DatabaseManager databaseManager; private final DatabaseManager databaseManager;
private SQLiteStatement writeStatement; private SQLiteStatement writeStatement;
...@@ -123,20 +122,12 @@ class RoomTable extends AbstractAccountTable { ...@@ -123,20 +122,12 @@ class RoomTable extends AbstractAccountTable {
/** /**
* Adds or updates room. * Adds or updates room.
*
* @param account
* @param room
* @param nickname
* @param password
* @param join
*/ */
void write(String account, String room, String nickname, String password, void write(String account, String room, String nickname, String password, boolean join) {
boolean join) {
synchronized (writeLock) { synchronized (writeLock) {
if (writeStatement == null) { if (writeStatement == null) {
SQLiteDatabase db = databaseManager.getWritableDatabase(); SQLiteDatabase db = databaseManager.getWritableDatabase();
writeStatement = db writeStatement = db.compileStatement("INSERT OR REPLACE INTO " + NAME
.compileStatement("INSERT OR REPLACE INTO " + NAME
+ " (" + Fields.ACCOUNT + ", " + Fields.ROOM + " (" + Fields.ACCOUNT + ", " + Fields.ROOM
+ ", " + Fields.NICKNAME + ", " + ", " + Fields.NICKNAME + ", "
+ Fields.PASSWORD + ", " + Fields.NEED_JOIN + Fields.PASSWORD + ", " + Fields.NEED_JOIN
...@@ -153,14 +144,10 @@ class RoomTable extends AbstractAccountTable { ...@@ -153,14 +144,10 @@ class RoomTable extends AbstractAccountTable {
/** /**
* Removes room. * Removes room.
*
* @param account
* @param room
*/ */
void remove(String account, String room) { void remove(String account, String room) {
SQLiteDatabase db = databaseManager.getWritableDatabase(); SQLiteDatabase db = databaseManager.getWritableDatabase();
db.delete(NAME, Fields.ACCOUNT + " = ? AND " + Fields.ROOM + " = ?", db.delete(NAME, Fields.ACCOUNT + " = ? AND " + Fields.ROOM + " = ?", new String[]{account, room});
new String[]{account, room});
} }
@Override @Override
......
...@@ -77,7 +77,7 @@ public class ContactAdd extends ManagedActivity implements ContactAddFragment.Li ...@@ -77,7 +77,7 @@ public class ContactAdd extends ManagedActivity implements ContactAddFragment.Li
} }
private void addContact() { private void addContact() {
((ContactAddFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_container)).addContact(); ((ContactAdder) getSupportFragmentManager().findFragmentById(R.id.fragment_container)).addContact();
} }
@Override @Override
......
...@@ -22,7 +22,8 @@ import com.xabber.android.ui.adapter.AccountChooseAdapter; ...@@ -22,7 +22,8 @@ import com.xabber.android.ui.adapter.AccountChooseAdapter;
import java.util.Collection; import java.util.Collection;
public class ContactAddFragment extends GroupEditorFragment implements AdapterView.OnItemSelectedListener { public class ContactAddFragment extends GroupEditorFragment
implements AdapterView.OnItemSelectedListener, ContactAdder {
private static final String SAVED_NAME = "com.xabber.android.ui.ContactAdd.SAVED_NAME"; private static final String SAVED_NAME = "com.xabber.android.ui.ContactAdd.SAVED_NAME";
private static final String SAVED_ACCOUNT = "com.xabber.android.ui.ContactAdd.SAVED_ACCOUNT"; private static final String SAVED_ACCOUNT = "com.xabber.android.ui.ContactAdd.SAVED_ACCOUNT";
...@@ -166,6 +167,7 @@ public class ContactAddFragment extends GroupEditorFragment implements AdapterVi ...@@ -166,6 +167,7 @@ public class ContactAddFragment extends GroupEditorFragment implements AdapterVi
public void onNothingSelected(AdapterView<?> parent) { public void onNothingSelected(AdapterView<?> parent) {
} }
@Override
public void addContact() { public void addContact() {
if (getAccount() == null) { if (getAccount() == null) {
Toast.makeText(getActivity(), getString(R.string.EMPTY_ACCOUNT), Toast.makeText(getActivity(), getString(R.string.EMPTY_ACCOUNT),
......
package com.xabber.android.ui;
public interface ContactAdder {
void addContact();
}
...@@ -223,6 +223,7 @@ public class ContactListFragment extends Fragment implements OnAccountChangedLis ...@@ -223,6 +223,7 @@ public class ContactListFragment extends Fragment implements OnAccountChangedLis
scrollToChatsActionButtonContainer.setVisibility(View.GONE); scrollToChatsActionButtonContainer.setVisibility(View.GONE);
} }
contactListFragmentListener.onContactListChange(commonState);
if (hasVisibleContacts) { if (hasVisibleContacts) {
infoView.setVisibility(View.GONE); infoView.setVisibility(View.GONE);
...@@ -343,9 +344,6 @@ public class ContactListFragment extends Fragment implements OnAccountChangedLis ...@@ -343,9 +344,6 @@ public class ContactListFragment extends Fragment implements OnAccountChangedLis
buttonView.setText(button); buttonView.setText(button);
} }
buttonView.setOnClickListener(listener); buttonView.setOnClickListener(listener);
contactListFragmentListener.onContactListChange(commonState);
} }
/** /**
......
...@@ -15,11 +15,8 @@ ...@@ -15,11 +15,8 @@
package com.xabber.android.ui; package com.xabber.android.ui;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.ClipboardManager; import android.text.ClipboardManager;
...@@ -44,11 +41,6 @@ import com.xabber.android.data.intent.EntityIntentBuilder; ...@@ -44,11 +41,6 @@ import com.xabber.android.data.intent.EntityIntentBuilder;
import com.xabber.android.data.roster.AbstractContact; import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.data.roster.OnContactChangedListener; import com.xabber.android.data.roster.OnContactChangedListener;
import com.xabber.android.data.roster.RosterManager; import com.xabber.android.data.roster.RosterManager;
import com.xabber.android.ui.dialog.ConfirmDialogBuilder;
import com.xabber.android.ui.dialog.ConfirmDialogListener;
import com.xabber.android.ui.dialog.DialogBuilder;
import com.xabber.android.ui.dialog.NotificationDialogBuilder;
import com.xabber.android.ui.dialog.NotificationDialogListener;
import com.xabber.android.ui.helper.ContactTitleActionBarInflater; import com.xabber.android.ui.helper.ContactTitleActionBarInflater;
import com.xabber.android.ui.helper.ManagedActivity; import com.xabber.android.ui.helper.ManagedActivity;
import com.xabber.xmpp.address.Jid; import com.xabber.xmpp.address.Jid;
...@@ -57,8 +49,7 @@ import java.util.Collection; ...@@ -57,8 +49,7 @@ import java.util.Collection;
public class FingerprintViewer extends ManagedActivity implements public class FingerprintViewer extends ManagedActivity implements
OnCheckedChangeListener, OnAccountChangedListener, OnCheckedChangeListener, OnAccountChangedListener,
OnContactChangedListener, OnClickListener, ConfirmDialogListener, OnContactChangedListener, OnClickListener {
NotificationDialogListener {
private static final String SAVED_REMOTE_FINGERPRINT = "com.xabber.android.ui.FingerprintViewer.SAVED_REMOTE_FINGERPRINT"; private static final String SAVED_REMOTE_FINGERPRINT = "com.xabber.android.ui.FingerprintViewer.SAVED_REMOTE_FINGERPRINT";
private static final String SAVED_LOCAL_FINGERPRINT = "com.xabber.android.ui.FingerprintViewer.SAVED_LOCAL_FINGERPRINT"; private static final String SAVED_LOCAL_FINGERPRINT = "com.xabber.android.ui.FingerprintViewer.SAVED_LOCAL_FINGERPRINT";
...@@ -170,11 +161,15 @@ public class FingerprintViewer extends ManagedActivity implements ...@@ -170,11 +161,15 @@ public class FingerprintViewer extends ManagedActivity implements
String code = scanResult.getContents(); String code = scanResult.getContents();
boolean equals = code != null && code.equals(remoteFingerprint); boolean equals = code != null && code.equals(remoteFingerprint);
verifiedView.setChecked(equals); verifiedView.setChecked(equals);
int dialogMessageId;
if (equals) { if (equals) {
showDialog(R.string.action_otr_smp_verified); dialogMessageId = R.string.action_otr_smp_verified;
} else { } else {
showDialog(R.string.action_otr_smp_unverified); dialogMessageId = R.string.action_otr_smp_unverified;
} }
new AlertDialog.Builder(this).setMessage(dialogMessageId)
.setNeutralButton(android.R.string.ok, null).show();
} }
} }
...@@ -209,27 +204,14 @@ public class FingerprintViewer extends ManagedActivity implements ...@@ -209,27 +204,14 @@ public class FingerprintViewer extends ManagedActivity implements
} }
} }
/** @Override
* Show native dialog instead of provided by ZXing.
*
* @param alertDialog
*/
private void wrapInstallDialog(AlertDialog alertDialog) {
if (alertDialog == null) {
return;
}
alertDialog.dismiss();
showDialog(R.string.zxing_install_message);
}
@Override
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.scan: case R.id.scan:
wrapInstallDialog(integrator.initiateScan(IntentIntegrator.QR_CODE_TYPES)); integrator.initiateScan(IntentIntegrator.QR_CODE_TYPES);
break; break;
case R.id.show: case R.id.show:
wrapInstallDialog(integrator.shareText(localFingerprint)); integrator.shareText(localFingerprint);
break; break;
case R.id.copy: case R.id.copy:
((ClipboardManager) getSystemService(CLIPBOARD_SERVICE)) ((ClipboardManager) getSystemService(CLIPBOARD_SERVICE))
...@@ -240,52 +222,6 @@ public class FingerprintViewer extends ManagedActivity implements ...@@ -240,52 +222,6 @@ public class FingerprintViewer extends ManagedActivity implements
} }
} }
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case R.string.zxing_install_message:
return new ConfirmDialogBuilder(this, id, this)
.setMessage(R.string.zxing_install_message).create();
case R.string.zxing_install_fail:
return new NotificationDialogBuilder(this, id, this)
.setMessage(R.string.zxing_install_fail).create();
case R.string.action_otr_smp_verified:
return new NotificationDialogBuilder(this, id, this)
.setMessage(R.string.action_otr_smp_verified).create();
case R.string.action_otr_smp_unverified:
return new NotificationDialogBuilder(this, id, this)
.setMessage(R.string.action_otr_smp_unverified).create();
default:
return super.onCreateDialog(id);
}
}
@Override
public void onAccept(DialogBuilder dialogBuilder) {
switch (dialogBuilder.getDialogId()) {
case R.string.zxing_install_message:
Uri uri = Uri.parse("market://details?id=" + IntentIntegrator.BS_PACKAGE);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try {
startActivity(intent);
} catch (ActivityNotFoundException anfe) {
showDialog(R.string.zxing_install_fail);
break;
}
break;
default:
break;
}
}
@Override
public void onDecline(DialogBuilder dialogBuilder) {
}
@Override
public void onCancel(DialogBuilder dialogBuilder) {
}
private void update() { private void update() {
isUpdating = true; isUpdating = true;
AbstractContact abstractContact = RosterManager.getInstance().getBestContact(account, user); AbstractContact abstractContact = RosterManager.getInstance().getBestContact(account, user);
......
...@@ -80,31 +80,38 @@ public class ContactItemInflater { ...@@ -80,31 +80,38 @@ public class ContactItemInflater {
MessageManager messageManager = MessageManager.getInstance(); MessageManager messageManager = MessageManager.getInstance();
viewHolder.smallRightText.setVisibility(View.GONE);
viewHolder.smallRightIcon.setVisibility(View.GONE);
if (messageManager.hasActiveChat(contact.getAccount(), contact.getUser())) { if (messageManager.hasActiveChat(contact.getAccount(), contact.getUser())) {
AbstractChat chat = messageManager.getChat(contact.getAccount(), contact.getUser()); AbstractChat chat = messageManager.getChat(contact.getAccount(), contact.getUser());
statusText = chat.getLastText().trim(); statusText = chat.getLastText().trim();
viewHolder.smallRightText.setText(StringUtils.getSmartTimeText(context, chat.getLastTime())); view.setBackgroundColor(context.getResources().getColor(R.color.contact_list_active_chat_background));
viewHolder.smallRightText.setVisibility(View.VISIBLE);
if (!chat.isLastMessageIncoming()) {
viewHolder.outgoingMessageIndicator.setText(context.getString(R.string.sender_is_you) + ": ");
viewHolder.outgoingMessageIndicator.setVisibility(View.VISIBLE);
viewHolder.outgoingMessageIndicator.setTextColor(accountMainColors[colorLevel]);
if (!statusText.isEmpty()) {
viewHolder.smallRightText.setText(StringUtils.getSmartTimeText(context, chat.getLastTime()));
viewHolder.smallRightText.setVisibility(View.VISIBLE);
if (!chat.isLastMessageIncoming()) {
viewHolder.outgoingMessageIndicator.setText(context.getString(R.string.sender_is_you) + ": ");
viewHolder.outgoingMessageIndicator.setVisibility(View.VISIBLE);
viewHolder.outgoingMessageIndicator.setTextColor(accountMainColors[colorLevel]);
}
viewHolder.smallRightIcon.setImageResource(R.drawable.ic_client_small);
viewHolder.smallRightIcon.setVisibility(View.VISIBLE);
viewHolder.smallRightIcon.setImageLevel(clientSoftware.ordinal());
viewHolder.largeClientIcon.setVisibility(View.GONE);
} else {
viewHolder.largeClientIcon.setVisibility(View.VISIBLE);
viewHolder.largeClientIcon.setImageLevel(clientSoftware.ordinal());
} }
view.setBackgroundColor(context.getResources().getColor(R.color.contact_list_active_chat_background));
viewHolder.smallRightIcon.setImageResource(R.drawable.ic_client_small);
viewHolder.smallRightIcon.setVisibility(View.VISIBLE);
viewHolder.smallRightIcon.setImageLevel(clientSoftware.ordinal());
viewHolder.largeClientIcon.setVisibility(View.GONE);
} else { } else {
statusText = contact.getStatusText().trim(); statusText = contact.getStatusText().trim();
viewHolder.smallRightText.setVisibility(View.GONE);
view.setBackgroundColor(context.getResources().getColor(R.color.contact_list_contact_background)); view.setBackgroundColor(context.getResources().getColor(R.color.contact_list_contact_background));
viewHolder.smallRightIcon.setVisibility(View.GONE);
viewHolder.largeClientIcon.setVisibility(View.VISIBLE); viewHolder.largeClientIcon.setVisibility(View.VISIBLE);
viewHolder.largeClientIcon.setImageLevel(clientSoftware.ordinal()); viewHolder.largeClientIcon.setImageLevel(clientSoftware.ordinal());
} }
......
...@@ -20,6 +20,7 @@ import android.content.DialogInterface; ...@@ -20,6 +20,7 @@ import android.content.DialogInterface;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import com.xabber.android.R; import com.xabber.android.R;
...@@ -66,7 +67,18 @@ public class ContextMenuHelper { ...@@ -66,7 +67,18 @@ public class ContextMenuHelper {
final String account = abstractContact.getAccount(); final String account = abstractContact.getAccount();
final String user = abstractContact.getUser(); final String user = abstractContact.getUser();
menu.setHeaderTitle(abstractContact.getName()); menu.setHeaderTitle(abstractContact.getName());
menu.add(R.string.chat_viewer).setOnMenuItemClickListener( MenuInflater inflater = activity.getMenuInflater();
inflater.inflate(R.menu.contact_list_contact_context_menu, menu);
setContactContextMenuActions(activity, adapter, menu, account, user);
setContactContextMenuItemsVisibilty(abstractContact, menu, account, user);
}
private static void setContactContextMenuActions(final FragmentActivity activity,
final UpdatableAdapter adapter,
ContextMenu menu,
final String account, final String user) {
menu.findItem(R.id.action_chat).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() { new MenuItem.OnMenuItemClickListener() {
@Override @Override
...@@ -78,138 +90,166 @@ public class ContextMenuHelper { ...@@ -78,138 +90,166 @@ public class ContextMenuHelper {
} }
}); });
if (MUCManager.getInstance().hasRoom(account, user)) { menu.findItem(R.id.action_edit_conference).setIntent(
if (!MUCManager.getInstance().inUse(account, user)) ConferenceAdd.createIntent(activity, account, user));
menu.add(R.string.muc_edit).setIntent(
ConferenceAdd.createIntent(activity, account, user));
menu.add(R.string.muc_delete).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
MUCDeleteDialogFragment.newInstance(account, user)
.show(activity.getFragmentManager(),
"MUC_DELETE");
return true;
}
});
if (MUCManager.getInstance().isDisabled(account, user)) {
menu.add(R.string.muc_join).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
MUCManager.getInstance().joinRoom(account,
user, true);
return true;
}
});
} else {
menu.add(R.string.muc_leave).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override menu.findItem(R.id.action_delete_conference).setOnMenuItemClickListener(
public boolean onMenuItemClick(MenuItem item) { new MenuItem.OnMenuItemClickListener() {
MUCManager.getInstance().leaveRoom(account, @Override
user); public boolean onMenuItemClick(MenuItem item) {
MessageManager.getInstance().closeChat(account, MUCDeleteDialogFragment.newInstance(account, user)
user); .show(activity.getFragmentManager(), "MUC_DELETE");
NotificationManager.getInstance() return true;
.removeMessageNotification(account, }
user); });
adapter.onChange();
return true;
}
}); menu.findItem(R.id.action_join_conference).setOnMenuItemClickListener(
} new MenuItem.OnMenuItemClickListener() {
} else { @Override
menu.add(R.string.contact_viewer).setIntent( public boolean onMenuItemClick(MenuItem item) {
ContactEditor.createIntent(activity, account, user)); MUCManager.getInstance().joinRoom(account,
menu.add(R.string.edit_contact_groups).setIntent( user, true);
GroupEditor.createIntent(activity, account, user)); return true;
}
});
menu.add(R.string.contact_delete).setOnMenuItemClickListener( menu.findItem(R.id.action_leave_conference).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() { new MenuItem.OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
ContactDeleteDialogFragment.newInstance(account, MUCManager.getInstance().leaveRoom(account, user);
user).show(activity.getFragmentManager(), MessageManager.getInstance().closeChat(account, user);
"CONTACT_DELETE"); NotificationManager.getInstance().removeMessageNotification(account, user);
return true; adapter.onChange();
} return true;
}
}); });
if (MessageManager.getInstance().hasActiveChat(account, user)) {
menu.add(R.string.close_chat).setOnMenuItemClickListener( menu.findItem(R.id.action_contact_info).setIntent(
ContactEditor.createIntent(activity, account, user));
menu.findItem(R.id.action_edit_contact_groups).setIntent(
GroupEditor.createIntent(activity, account, user));
menu.findItem(R.id.action_delete_contact).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
ContactDeleteDialogFragment.newInstance(account,
user).show(activity.getFragmentManager(), "CONTACT_DELETE");
return true;
}
});
menu.findItem(R.id.action_close_chat).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
MessageManager.getInstance().closeChat(account,
user);
NotificationManager.getInstance()
.removeMessageNotification(account,
user);
adapter.onChange();
return true;
}
});
menu.findItem(R.id.action_request_subscription)
.setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() { new MenuItem.OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
MessageManager.getInstance().closeChat(account, try {
user); PresenceManager.getInstance()
NotificationManager.getInstance() .requestSubscription(
.removeMessageNotification(account, account, user);
user); } catch (NetworkException e) {
adapter.onChange(); Application.getInstance()
.onError(e);
}
return true; return true;
} }
}); });
menu.findItem(R.id.action_accept_subscription).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
try {
PresenceManager.getInstance().acceptSubscription(account, user);
} catch (NetworkException e) {
Application.getInstance().onError(e);
}
activity.startActivity(GroupEditor.createIntent(activity, account, user));
return true;
}
});
menu.findItem(R.id.action_discard_subscription).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
try {
PresenceManager.getInstance()
.discardSubscription(account, user);
} catch (NetworkException e) {
Application.getInstance().onError(e);
}
return true;
}
});
}
private static void setContactContextMenuItemsVisibilty(AbstractContact abstractContact,
ContextMenu menu,
String account, String user) {
// all menu items are visible by default
// it allows to hide items in xml file without touching code
if (!MUCManager.getInstance().hasRoom(account, user)) {
// is not conference
menu.findItem(R.id.action_edit_conference).setVisible(false);
menu.findItem(R.id.action_delete_conference).setVisible(false);
menu.findItem(R.id.action_leave_conference).setVisible(false);
menu.findItem(R.id.action_join_conference).setVisible(false);
if (!MessageManager.getInstance().hasActiveChat(account, user)) {
menu.findItem(R.id.action_close_chat).setVisible(false);
} }
if (abstractContact.getStatusMode() == StatusMode.unsubscribed) { if (abstractContact.getStatusMode() != StatusMode.unsubscribed) {
menu.add(R.string.request_subscription) menu.findItem(R.id.action_request_subscription).setVisible(false);
.setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
try {
PresenceManager.getInstance()
.requestSubscription(
account, user);
} catch (NetworkException e) {
Application.getInstance()
.onError(e);
}
return true;
}
});
} }
} } else { // is conference
if (PresenceManager.getInstance().hasSubscriptionRequest(account, user)) {
menu.add(R.string.accept_subscription).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
@Override menu.findItem(R.id.action_contact_info).setVisible(false);
public boolean onMenuItemClick(MenuItem item) { menu.findItem(R.id.action_edit_contact_groups).setVisible(false);
try { menu.findItem(R.id.action_delete_contact).setVisible(false);
PresenceManager.getInstance() menu.findItem(R.id.action_close_chat).setVisible(false);
.acceptSubscription(account, user); menu.findItem(R.id.action_request_subscription).setVisible(false);
} catch (NetworkException e) {
Application.getInstance().onError(e);
}
activity.startActivity(GroupEditor.createIntent(
activity, account, user));
return true;
}
}); if (MUCManager.getInstance().inUse(account, user)) {
menu.add(R.string.discard_subscription).setOnMenuItemClickListener( menu.findItem(R.id.action_edit_conference).setVisible(false);
new MenuItem.OnMenuItemClickListener() { }
@Override if (MUCManager.getInstance().isDisabled(account, user)) {
public boolean onMenuItemClick(MenuItem item) { menu.findItem(R.id.action_leave_conference).setVisible(false);
try { } else {
PresenceManager.getInstance() menu.findItem(R.id.action_join_conference).setVisible(false);
.discardSubscription(account, user); }
} catch (NetworkException e) {
Application.getInstance().onError(e);
}
return true;
}
}); }
if (!PresenceManager.getInstance().hasSubscriptionRequest(account, user)) {
menu.findItem(R.id.action_accept_subscription).setVisible(false);
menu.findItem(R.id.action_discard_subscription).setVisible(false);
} }
} }
......
...@@ -24,33 +24,7 @@ ...@@ -24,33 +24,7 @@
<include layout="@layout/account_select_spinner" /> <include layout="@layout/account_select_spinner" />
<TextView <include layout="@layout/contact_add_username_and_alias" />
android:text="@string/contact_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<EditText
android:text=""
android:id="@+id/contact_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/user_domain_name"
android:singleLine="true"
android:inputType="textEmailAddress"
/>
<TextView
android:text="@string/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<EditText
android:text=""
android:id="@+id/contact_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
<TextView <TextView
android:id="@+id/select_groups_text_view" android:id="@+id/select_groups_text_view"
......
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:showIn="@layout/contact_add_header">
<TextView
android:text="@string/contact_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:text=""
android:id="@+id/contact_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/user_domain_name"
android:singleLine="true"
android:inputType="textEmailAddress" />
<TextView
android:text="@string/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:text=""
android:id="@+id/contact_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
</merge>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_chat"
android:title="@string/chat_viewer" />
<item android:id="@+id/action_edit_conference"
android:title="@string/muc_edit" />
<item android:id="@+id/action_delete_conference"
android:title="@string/muc_delete" />
<item android:id="@+id/action_join_conference"
android:title="@string/muc_join" />
<item android:id="@+id/action_leave_conference"
android:title="@string/muc_leave" />
<item android:id="@+id/action_contact_info"
android:title="@string/contact_viewer" />
<item android:id="@+id/action_edit_contact_groups"
android:title="@string/edit_contact_groups" />
<item android:id="@+id/action_delete_contact"
android:title="@string/contact_delete" />
<item android:id="@+id/action_close_chat"
android:title="@string/close_chat" />
<item android:id="@+id/action_request_subscription"
android:title="@string/request_subscription" />
<item android:id="@+id/action_accept_subscription"
android:title="@string/accept_subscription" />
<item android:id="@+id/action_discard_subscription"
android:title="@string/discard_subscription" />
</menu>
\ No newline at end of file
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">بصمة الطرف الآخر:</string> <string name="otr_remote_fingerprint">بصمة الطرف الآخر:</string>
<string name="otr_scan_fingerprint">مسح رمز QR لبصمة الطرف الآخر</string> <string name="otr_scan_fingerprint">مسح رمز QR لبصمة الطرف الآخر</string>
<string name="otr_show_fingerprint">إظهار رمز QR لبصمتك</string> <string name="otr_show_fingerprint">إظهار رمز QR لبصمتك</string>
<string name="zxing_install_fail">لم يتمكن تثبيت تطبيق Barcode Scanner. برجاء تثبيته بمعرفتك.</string>
<string name="zxing_install_message">هذا التطبيق يتطلب تطبيق Barcode Scanner. هل تحب أن تثبته؟</string>
<string name="otr_copy_fingerprint">نسخ بصمتك للحافظة</string> <string name="otr_copy_fingerprint">نسخ بصمتك للحافظة</string>
</resources> </resources>
...@@ -12,25 +12,25 @@ ...@@ -12,25 +12,25 @@
<string name="account_server_name">Servername</string> <string name="account_server_name">Servername</string>
<string name="account_type">Kontotyp</string> <string name="account_type">Kontotyp</string>
<string name="account_type_hints_gtalk">Benutzername für Google Talk</string> <string name="account_type_hints_gtalk">Benutzername für Google Talk</string>
<string name="account_type_helps_gtalk">Wenn Sie über kein Google-Konto verfügen, können Sie eines unter http://mail.google.com\n erstellen. Dann verwenden Sie bitte your_user_name@your_google_domain</string> <string name="account_type_helps_gtalk">Wenn du über kein Google-Konto verfügst, kannst du unter http://mail.google.com\n eins erstellen. Verwende bitte your_user_name@your_google_domain</string>
<string name="account_type_helps_xmpp">Wenn Sie mehr über XMPP (Jabber) erfahren möchten: https://xmpp.org</string> <string name="account_type_helps_xmpp">Wenn du mehr über XMPP (Jabber) erfahren möchtest, besuche https://xmpp.org</string>
<string name="account_user_name">Benutzername</string> <string name="account_user_name">Benutzername</string>
<string name="EMPTY_SERVER_NAME">Servername nicht angegeben</string> <string name="EMPTY_SERVER_NAME">Der Servername wurde nicht angegeben</string>
<string name="EMPTY_USER_NAME">Benutzername nicht angegeben</string> <string name="EMPTY_USER_NAME">Benutzername nicht angegeben</string>
<string name="CONFIRM_PASSWORD">Unterschiedliche Passwörter</string> <string name="CONFIRM_PASSWORD">Die Passwörter stimmen nicht überein</string>
<string name="account_archive_mode">Speichern des Chatverlaufs</string> <string name="account_archive_mode">Speichern des Chatverlaufs</string>
<string name="account_archive_mode_available">Auf dem Server, wenn möglich</string> <string name="account_archive_mode_available">Auf dem Server, wenn möglich</string>
<string name="account_archive_mode_dont_store">Nicht speichern</string> <string name="account_archive_mode_dont_store">Nicht speichern</string>
<string name="account_archive_mode_local">Auf diesem Gerät</string> <string name="account_archive_mode_local">Auf diesem Gerät</string>
<string name="account_archive_mode_server">Auf dem Server</string> <string name="account_archive_mode_server">Auf dem Server</string>
<string name="account_archive_mode_unread">Auf diesem Gerät (nur ungelesen/ungesendet)</string> <string name="account_archive_mode_unread">Auf diesem Gerät (nur ungelesen/ungesendet)</string>
<string name="account_compression_summary">Datenkomprimierung aktivieren</string> <string name="account_compression_summary">Auswählen um die Datenkompression zu aktivieren</string>
<string name="account_custom">Benutzerdefinierter Host</string> <string name="account_custom">Benutzerdefinierter Host</string>
<string name="account_custom_summary">Benutzerdefinierte Einstellung statt SRV-Eintrag nutzen</string> <string name="account_custom_summary">Benutzerdefinierte Einstellung statt SRV-Eintrag nutzen</string>
<string name="account_enabled_summary">Auswählen um das Konto zu aktivieren</string> <string name="account_enabled_summary">Auswählen um das Konto zu aktivieren</string>
<string name="account_invalid_port">Port muss eine Zahl sein (Standard: 5222)</string> <string name="account_invalid_port">Der Port muss numerisch sein (Standard: 5222)</string>
<string name="account_invalid_priority">Priorität muss eine Zahl zwischen -128 und 128 sein (Standardwert: 10)</string> <string name="account_invalid_priority">Die Priorität muss ein numerischer Wert zwischen -128 und 128 sein (Standardwert: 10)</string>
<string name="account_oauth">Authentifizierung</string> <string name="account_oauth">Autorisierung</string>
<string name="account_oauth_invalidated">Nicht autorisiert</string> <string name="account_oauth_invalidated">Nicht autorisiert</string>
<string name="account_oauth_summary">OAuth-Einstellungen</string> <string name="account_oauth_summary">OAuth-Einstellungen</string>
<string name="account_proxy_host">Proxy-Host</string> <string name="account_proxy_host">Proxy-Host</string>
...@@ -38,26 +38,26 @@ ...@@ -38,26 +38,26 @@
<string name="account_proxy_port">Proxy-Port</string> <string name="account_proxy_port">Proxy-Port</string>
<string name="account_proxy_type">Proxy-Typ</string> <string name="account_proxy_type">Proxy-Typ</string>
<string name="account_proxy_type_none">Deaktiviert</string> <string name="account_proxy_type_none">Deaktiviert</string>
<string name="account_proxy_user">Proxy-Benutzer</string> <string name="account_proxy_user">Proxy-Benutzername</string>
<string name="account_sasl">SASL-Authentifizierung nutzen (empfohlen)</string> <string name="account_sasl">SASL-Authentifizierung nutzen (empfohlen)</string>
<string name="account_sasl_summary">Für sehr alte Server deaktivieren</string> <string name="account_sasl_summary">Sollte für sehr alte Server deaktiviert werden</string>
<string name="account_store_password">Kennwort speichern</string> <string name="account_store_password">Kennwort speichern</string>
<string name="account_store_password_summary">Deaktivieren um das Kennwort bei jedem Start eingeben zu müssen</string> <string name="account_store_password_summary">Deaktiviere diese Option um dein Kennwort bei jedem Verbinden neu einzugeben</string>
<string name="account_syncable">Mit Telefonbuch synchronisieren</string> <string name="account_syncable">Mit Telefonbuch synchronisieren</string>
<string name="account_syncable_summary">Kontakte dieses Kontos im Telefonbuch anzeigen</string> <string name="account_syncable_summary">Kontakte dieses Kontos im Telefonbuch anzeigen</string>
<string name="account_tls_enable">TLS verwenden</string> <string name="account_tls_enable">TLS verwenden</string>
<string name="account_tls_enable_summary">TLS Verschlüsselung für die Serververbindung verwenden (falls möglich)</string> <string name="account_tls_enable_summary">TLS Verschlüsselung für die Serververbindung verwenden (falls möglich)</string>
<string name="account_tls_legacy">Herkömmliches SSL</string> <string name="account_tls_legacy">Herkömmliches SSL</string>
<string name="account_tls_legacy_summary">Herkömmliche SSL-Verschlüsselung für Serververbindung verwenden</string> <string name="account_tls_legacy_summary">Herkömmliche SSL-Verschlüsselung für die Serververbindung verwenden</string>
<string name="account_tls_mode">TLS/SSL-Verschlüsselung</string> <string name="account_tls_mode">TLS/SSL-Verschlüsselung</string>
<string name="account_tls_require">TLS benötigt</string> <string name="account_tls_require">TLS benötigt</string>
<string name="account_tls_require_summary">TLS-Verschlüsselung für Verbindung zum Server benötig</string> <string name="account_tls_require_summary">Für die Verbindung zum Server wird TLS-Verschlüsselung benötigt</string>
<string name="account_use_orbot">Chatten über das anonyme Netzwerk TOR und erzwingen einer TLS Verschlüsselung\nFür Google Talk nicht empfohlen</string> <string name="account_use_orbot">Chatte über das anonyme Netzwerk TOR und erzwinge eine TLS Verschlüsselung\nWird für Google Talk nicht empfohlen</string>
<string name="confirm_cancellation">Willst du wirklich alle Änderungen verwerfen?</string> <string name="confirm_cancellation">Willst du wirklich alle Änderungen verwerfen?</string>
<string name="INCORRECT_USER_NAME">Falscher Benutzername. Details siehe Hilfe unten.</string> <string name="INCORRECT_USER_NAME">Überprüfe den Benutzernamen. Details findest du unten im Hilfetext.</string>
<string name="orbot_required_message">Für die Nutzung von TOR muss Orbot installiert sein und die Proxy-Verbindung darüber laufen. Möchten Sie die App von Google Play herunterladen?</string> <string name="orbot_required_message">Für die Nutzung von TOR muss Orbot installiert sein und die Proxy-Verbindung darüber laufen. Möchtest du Orbot von Google Play herunterladen?</string>
<string name="orbot_required_title">Soll Orbot installiert werden?</string> <string name="orbot_required_title">Soll Orbot installiert werden?</string>
<string name="ACCOUNT_REGISTER_FAILED">Benutzerkonto konnte auf Server nicht angelegt werden.</string> <string name="ACCOUNT_REGISTER_FAILED">Das Benutzerkonto konnte nicht auf dem Server angelegt werden.</string>
<string name="account_color">Kontofarbe</string> <string name="account_color">Kontofarbe</string>
<string name="account_color_name_green">Grün</string> <string name="account_color_name_green">Grün</string>
<string name="account_color_name_orange">Orange</string> <string name="account_color_name_orange">Orange</string>
...@@ -65,6 +65,6 @@ ...@@ -65,6 +65,6 @@
<string name="account_color_name_blue">Blau</string> <string name="account_color_name_blue">Blau</string>
<string name="account_color_name_indigo">Indigoblau</string> <string name="account_color_name_indigo">Indigoblau</string>
<string name="account_color_name_teal">Blaugrün</string> <string name="account_color_name_teal">Blaugrün</string>
<string name="account_color_name_blue_grey">Blaugrau</string> <string name="account_color_name_blue_grey">Graublau</string>
<string name="account_color_name_cyan">Cyan</string> <string name="account_color_name_cyan">Türkis</string>
</resources> </resources>
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
<string name="action_status_text_none">%1$s hat den Statustext gelöscht</string> <string name="action_status_text_none">%1$s hat den Statustext gelöscht</string>
<string name="action_join">%1$s hat die Konferenz betreten</string> <string name="action_join">%1$s hat die Konferenz betreten</string>
<string name="action_kick">%1$s wurde rausgeworfen</string> <string name="action_kick">%1$s wurde rausgeworfen</string>
<string name="account_is_offline">Sie sind momentan offline. Nachrichten, die Sie senden, werden erst zugestellt sobald Sie sich erneut verbinden.</string> <string name="account_is_offline">Du bist offline. Gesendete Nachrichten werden erst zugestellt, sobald du wieder verbunden bist.</string>
<string name="chat_delay">gesendet um %s</string> <string name="chat_delay">gesendet um %s</string>
<string name="chat_input_hint">Geben Sie Ihre Nachricht hier ein</string> <string name="chat_input_hint">Geben Sie Ihre Nachricht hier ein</string>
<string name="chat_send">Senden</string> <string name="chat_send">Senden</string>
<string name="clear_history">Gesprächsverlauf löschen</string> <string name="clear_history">Gesprächsverlauf löschen</string>
<string name="contact_is_offline">Der Empfänger ist offline. Nachrichten, die Sie senden werden erst zugestellt, sobald er wieder online ist.</string> <string name="contact_is_offline">Der Empfänger ist offline. Nachrichten werden erst zugestellt, sobald er wieder online ist.</string>
<string name="ENTRY_IS_NOT_AVAILABLE">Kontakt ist nicht verfügbar</string> <string name="ENTRY_IS_NOT_AVAILABLE">Kontakt ist nicht verfügbar</string>
<string name="FILE_NOT_FOUND">Datei nicht gefunden</string> <string name="FILE_NOT_FOUND">Datei nicht gefunden</string>
<string name="message_copy">Nachricht kopieren</string> <string name="message_copy">Nachricht kopieren</string>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<string name="save_history">Gesprächsverlauf speichern\nDen Gesprächsverlauf lokal speichern</string> <string name="save_history">Gesprächsverlauf speichern\nDen Gesprächsverlauf lokal speichern</string>
<string name="show_history">Gesprächsverlauf anzeigen</string> <string name="show_history">Gesprächsverlauf anzeigen</string>
<string name="action_attention_called">Aufmerksamkeitswunsch wurde versandt</string> <string name="action_attention_called">Aufmerksamkeitswunsch wurde versandt</string>
<string name="action_attention_requested">Aufmerksamkeit wurde erbeten</string> <string name="action_attention_requested">Deine Aufmerksamkeit wird verlangt!</string>
<string name="action_ban">%1$s wurde verbannt</string> <string name="action_ban">%1$s wurde verbannt</string>
<string name="action_ban_by">%1$s wurde verbannt von %2$s</string> <string name="action_ban_by">%1$s wurde verbannt von %2$s</string>
<string name="action_invite_error">%s hat die Einladung nicht empfangen</string> <string name="action_invite_error">%s hat die Einladung nicht empfangen</string>
......
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">Virtueller Fingerabdruck deines Gesprächspartners:</string> <string name="otr_remote_fingerprint">Virtueller Fingerabdruck deines Gesprächspartners:</string>
<string name="otr_scan_fingerprint">QR Code von virtuellem Fingerabdruck des Gesprächspartners scannen</string> <string name="otr_scan_fingerprint">QR Code von virtuellem Fingerabdruck des Gesprächspartners scannen</string>
<string name="otr_show_fingerprint">QR Code mit deinem virtuellem Fingerabdruck zeigen</string> <string name="otr_show_fingerprint">QR Code mit deinem virtuellem Fingerabdruck zeigen</string>
<string name="zxing_install_fail">Google Play nicht installiert. Bitte installiere die App Barcode Scanner manuell.</string>
<string name="zxing_install_message">Diese Anwendung benötigt die App Barcode Scanner. Möchtest du diese installieren?</string>
<string name="otr_copy_fingerprint">Virtuellen Fingerabdruck in Zwischenablage kopieren</string> <string name="otr_copy_fingerprint">Virtuellen Fingerabdruck in Zwischenablage kopieren</string>
</resources> </resources>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<string name="application_state_waiting">Conectando...</string> <string name="application_state_waiting">Conectando...</string>
<string name="chat_list">Lista de conversaciones</string> <string name="chat_list">Lista de conversaciones</string>
<string name="chat_list_is_empty">No hay conversaciones activas</string> <string name="chat_list_is_empty">No hay conversaciones activas</string>
<string name="chat_viewer">Iniciar conversación</string> <string name="chat_viewer">Conversación</string>
<string name="close_chat">Cerrar conversación</string> <string name="close_chat">Cerrar conversación</string>
<string name="CONNECTION_FAILED">Error de conexión</string> <string name="CONNECTION_FAILED">Error de conexión</string>
<string name="contact_add">Añadir contacto</string> <string name="contact_add">Añadir contacto</string>
......
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">Huella de seguridad del interlocutor:</string> <string name="otr_remote_fingerprint">Huella de seguridad del interlocutor:</string>
<string name="otr_scan_fingerprint">Escanear código QR de la huella de seguridad del interlocutor</string> <string name="otr_scan_fingerprint">Escanear código QR de la huella de seguridad del interlocutor</string>
<string name="otr_show_fingerprint">Mostrar código QR con tu huella de seguridad</string> <string name="otr_show_fingerprint">Mostrar código QR con tu huella de seguridad</string>
<string name="zxing_install_fail">No tienes instalado Google Play. Por favor instala \"Barcode Scanner\" manualmente.</string>
<string name="zxing_install_message">Esta aplicación necesita \"Barcode Scanner\". ¿Quieres instalarlo?</string>
<string name="otr_copy_fingerprint">Copiar tu huella de seguridad al portapapeles</string> <string name="otr_copy_fingerprint">Copiar tu huella de seguridad al portapapeles</string>
</resources> </resources>
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<string name="account_sasl">Utiliser l\'authentification SASL (recommandé)</string> <string name="account_sasl">Utiliser l\'authentification SASL (recommandé)</string>
<string name="account_sasl_summary">Désactiver pour les serveurs obsolètes</string> <string name="account_sasl_summary">Désactiver pour les serveurs obsolètes</string>
<string name="account_store_password">Enregistrer le mot de passe</string> <string name="account_store_password">Enregistrer le mot de passe</string>
<string name="account_store_password_summary">Désactiver cette option pour demander le mot de passe à chaque connexion</string> <string name="account_store_password_summary">Désactivez cette option pour demander le mot de passe à chaque connexion</string>
<string name="account_syncable">Intégration aux contacts du système</string> <string name="account_syncable">Intégration aux contacts du système</string>
<string name="account_syncable_summary">Afficher les contacts de ce compte dans la liste de contacts de l\'appareil</string> <string name="account_syncable_summary">Afficher les contacts de ce compte dans la liste de contacts de l\'appareil</string>
<string name="account_tls_enable">Activer TLS</string> <string name="account_tls_enable">Activer TLS</string>
......
...@@ -11,6 +11,6 @@ ...@@ -11,6 +11,6 @@
<string name="account_state_connected">En ligne</string> <string name="account_state_connected">En ligne</string>
<string name="account_state_connecting">Connexion en cours</string> <string name="account_state_connecting">Connexion en cours</string>
<string name="account_state_disconnecting">Déconnexion en cours</string> <string name="account_state_disconnecting">Déconnexion en cours</string>
<string name="account_state_offline">Hors ligne</string> <string name="account_state_offline">Hors-ligne</string>
<string name="account_state_waiting">En attente de reconnexion</string> <string name="account_state_waiting">En attente de reconnexion</string>
</resources> </resources>
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
<string name="message_copy">Copier</string> <string name="message_copy">Copier</string>
<string name="message_quote">Citer</string> <string name="message_quote">Citer</string>
<string name="message_remove">Supprimer de l\'historique</string> <string name="message_remove">Supprimer de l\'historique</string>
<string name="message_repeat">Tenter à nouveau l\'envoi</string> <string name="message_repeat">Retenter l\'envoi</string>
<string name="save_history">Stocker l\'historique localement\nSauvegarder l\'historique des messages localement</string> <string name="save_history">Stocker l\'historique localement\nSauvegarder l\'historique des messages localement</string>
<string name="show_history">Afficher l\'historique</string> <string name="show_history">Afficher l\'historique</string>
<string name="action_attention_called">Une demande d\'attention a été envoyée</string> <string name="action_attention_called">Demande d\'attention envoyée</string>
<string name="action_attention_requested">Une demande d\'attention a été reçue</string> <string name="action_attention_requested">Une demande d\'attention a été reçue</string>
<string name="action_ban">%1$s a été banni</string> <string name="action_ban">%1$s a été banni</string>
<string name="action_ban_by">%1$s a été banni par %2$s</string> <string name="action_ban_by">%1$s a été banni par %2$s</string>
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
<string name="export_chat_send">Envoyer après avoir exporté</string> <string name="export_chat_send">Envoyer après avoir exporté</string>
<string name="export_chat_title">Entrer un nom de fichier</string> <string name="export_chat_title">Entrer un nom de fichier</string>
<string name="muc_invite">Inviter à discuter</string> <string name="muc_invite">Inviter à discuter</string>
<string name="muc_is_unavailable">Vos messages ne peuvent être délivrés. Rejoignez la discussion s\'il vous plait.</string> <string name="muc_is_unavailable">Vos messages ne peuvent être délivrés. Veuillez rejoindre la discussion</string>
<string name="occupant_list">Liste des participants</string> <string name="occupant_list">Liste des participants</string>
<string name="otr_encryption">Chiffrement OTR</string> <string name="otr_encryption">Chiffrement OTR</string>
<string name="otr_end">Arrêter le chiffrement</string> <string name="otr_end">Arrêter le chiffrement</string>
......
...@@ -6,17 +6,17 @@ ...@@ -6,17 +6,17 @@
<string name="application_action_disabled">Gérer les comptes</string> <string name="application_action_disabled">Gérer les comptes</string>
<string name="application_action_empty">Ajouter un compte</string> <string name="application_action_empty">Ajouter un compte</string>
<string name="application_action_no_contacts">Ajouter un contact</string> <string name="application_action_no_contacts">Ajouter un contact</string>
<string name="application_action_no_online">Afficher les contacts hors ligne</string> <string name="application_action_no_online">Afficher les contacts hors-ligne</string>
<string name="application_action_offline">Se connecter</string> <string name="application_action_offline">Se connecter</string>
<string name="application_action_waiting">Reconnecter</string> <string name="application_action_waiting">Reconnecter</string>
<string name="application_state_connecting">Connexion en cours&#8230;</string> <string name="application_state_connecting">Connexion en cours&#8230;</string>
<string name="application_state_disabled">Comptes désactivés</string> <string name="application_state_disabled">Comptes désactivés</string>
<string name="application_state_empty">Vous n\'avez aucun compte</string> <string name="application_state_empty">Vous n\'avez aucun compte</string>
<string name="application_state_no_contacts">Vous n\'avez pas de contacts</string> <string name="application_state_no_contacts">Vous n\'avez pas de contact</string>
<string name="application_state_no_online">Personne n\'est en ligne</string> <string name="application_state_no_online">Personne n\'est en ligne</string>
<string name="application_state_offline">Pas de compte en ligne</string> <string name="application_state_offline">Pas de compte en ligne</string>
<string name="application_state_roster">Connecté.</string> <string name="application_state_roster">Connecté.</string>
<string name="application_state_starting">Démarrage de l\'application... </string> <string name="application_state_starting">Démarrage en cours&#8230;</string>
<string name="application_state_waiting">En attente de connexion...</string> <string name="application_state_waiting">En attente de connexion...</string>
<string name="chat_list">Liste des conversations</string> <string name="chat_list">Liste des conversations</string>
<string name="chat_list_is_empty">Pas de conversation active</string> <string name="chat_list_is_empty">Pas de conversation active</string>
...@@ -51,9 +51,9 @@ ...@@ -51,9 +51,9 @@
<string name="OTR_ERROR">Erreur OTR</string> <string name="OTR_ERROR">Erreur OTR</string>
<string name="select_contact">Appuyez pour sélectionner le contact</string> <string name="select_contact">Appuyez pour sélectionner le contact</string>
<string name="show_offline_always">Toujours afficher</string> <string name="show_offline_always">Toujours afficher</string>
<string name="show_offline_never">Masquer les contacts hors ligne</string> <string name="show_offline_never">Masquer les contacts hors-ligne</string>
<string name="show_offline_normal">Utiliser les paramètres généraux</string> <string name="show_offline_normal">Utiliser les paramètres généraux</string>
<string name="show_offline_settings">Afficher les contacts hors ligne</string> <string name="show_offline_settings">Afficher les contacts hors-ligne</string>
<string name="start_at_boot_suggest">Voulez-vous lancer Xabber au démarrage ?\nCeci peut être changé via \"Paramètres\" → \"Paramètres de connexion\" → \"Démarrer avec Android\"</string> <string name="start_at_boot_suggest">Voulez-vous lancer Xabber au démarrage ?\nCeci peut être changé via \"Paramètres\" → \"Paramètres de connexion\" → \"Démarrer avec Android\"</string>
<string name="contact_search_hint">Chercher contacts</string> <string name="contact_search_hint">Chercher contacts</string>
<string name="sender_is_you">Vous </string> <string name="sender_is_you">Vous </string>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com--> <!--Generated by crowdin.com-->
<resources> <resources>
<string name="otr_fingerprint_description">Votre interlocuteur ne peut fournir son empreinte, vous pouvez la comparer méticuleusement pour être sûr qu\'il est bien celui que vous pensez. Vous ne devriez pas utiliser le chat XMPP à cet effet.</string> <string name="otr_fingerprint_description">Pour confirmer l\'identité de votre interlocuteur, demandez lui de fournir son empreinte et comparez-la à celle ci-dessous. N\'échangez surtout pas vos empreintes via XMPP.</string>
<string name="otr_is_verified">Ce contact est digne de confiance</string> <string name="otr_is_verified">Ce contact est digne de confiance</string>
<string name="otr_local_fingerprint">Votre empreinte :</string> <string name="otr_local_fingerprint">Votre empreinte :</string>
<string name="otr_remote_fingerprint">L\'empreinte de votre interlocuteur :</string> <string name="otr_remote_fingerprint">L\'empreinte de votre interlocuteur :</string>
<string name="otr_scan_fingerprint">Scanner le code QR de votre interlocuteur</string> <string name="otr_scan_fingerprint">Scanner le code QR de votre interlocuteur</string>
<string name="otr_show_fingerprint">Afficher le code QR de votre empreinte</string> <string name="otr_show_fingerprint">Afficher le code QR de votre empreinte</string>
<string name="zxing_install_fail">Google Play ne semble pas installé. Merci d\'installer Barcode Scanner manuellement.</string>
<string name="zxing_install_message">Cette application nécessite Barcode Scanner. Voulez-vous l\'installer ?</string>
<string name="otr_copy_fingerprint">Copier votre empreinte dans le presse-papier</string> <string name="otr_copy_fingerprint">Copier votre empreinte dans le presse-papier</string>
</resources> </resources>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<string name="muc_nick">Pseudo</string> <string name="muc_nick">Pseudo</string>
<string name="muc_nick_hint">Votre pseudo dans la conférence</string> <string name="muc_nick_hint">Votre pseudo dans la conférence</string>
<string name="muc_password">Mot de passe</string> <string name="muc_password">Mot de passe</string>
<string name="muc_password_hint">le mot de passe n\'est pas requis</string> <string name="muc_password_hint">Le mot de passe n\'est pas obligatoire</string>
<string name="muc_room">Conférence</string> <string name="muc_room">Conférence</string>
<string name="muc_server">Serveur de discussions multi-utilisateur (MUC)</string> <string name="muc_server">Serveur de discussions multi-utilisateur (MUC)</string>
<string name="NICK_ALREADY_USED">Pseudo déjà utilisé</string> <string name="NICK_ALREADY_USED">Pseudo déjà utilisé</string>
......
...@@ -26,13 +26,13 @@ ...@@ -26,13 +26,13 @@
<string name="connection_state_waiting_1">%1$d sur %2$d %3$s en attente de connexion</string> <string name="connection_state_waiting_1">%1$d sur %2$d %3$s en attente de connexion</string>
<string name="connection_state_waiting_2">%1$d sur %2$d %3$s en attente de connexion</string> <string name="connection_state_waiting_2">%1$d sur %2$d %3$s en attente de connexion</string>
<string name="connection_state_waiting_5">-</string> <string name="connection_state_waiting_5">-</string>
<string name="connection_state_offline">%1$d %2$s hors ligne</string> <string name="connection_state_offline">%1$d %2$s hors-ligne</string>
<string name="archive_available_request_message">Souhaitez-vous stocker l\'historique des messages sur le serveur ?\nCela permet à Xabber d\'obtenir l\'historique de tous les messages envoyés avec ce compte quels que soient les appareils ayant été utilisés.\nCette fonction génère un peu de trafic supplémentaire et réduit donc légèrement la vitesse de connexion.\nAVERTISSEMENT: Tout votre historique local sera supprimé.</string> <string name="archive_available_request_message">Souhaitez-vous stocker l\'historique des messages sur le serveur ?\nCela permet à Xabber d\'obtenir l\'historique de tous les messages envoyés avec ce compte, quels que soient les appareils ayant été utilisés.\nCette fonction génère un peu de trafic supplémentaire et réduit donc légèrement la vitesse de connexion.\nATTENTION : Tout votre historique local sera supprimé.</string>
<string name="archive_available_request_title">Activer l\'archivage des messages?</string> <string name="archive_available_request_title">Activer l\'archivage des messages ?</string>
<string name="INVALID_CERTIFICATE">Certificat non valide</string> <string name="INVALID_CERTIFICATE">Problème de certificat</string>
<string name="muc_invite_message">Souhaitez-vous entrer dans la conférence ?</string> <string name="muc_invite_message">Souhaitez-vous rejoindre la conférence ?</string>
<string name="otr_verification_in_progress">Cliquez ici pour annuler.</string> <string name="otr_verification_in_progress">Appuyez ici pour annuler.</string>
<string name="PASSWORD_REQUIRED">Mot de passe requis</string> <string name="PASSWORD_REQUIRED">Mot de passe requis</string>
<string name="pay_attention">Porte attention</string> <string name="pay_attention">Demande d\'attention</string>
<string name="subscription_request_message">Demande d\'autorisation</string> <string name="subscription_request_message">Demande d\'autorisation</string>
</resources> </resources>
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<resources> <resources>
<string name="cache_clear">Vider le cache\nSupprime toutes les données locales. Peut libérer de l\'espace.</string> <string name="cache_clear">Vider le cache\nSupprime toutes les données locales. Peut libérer de l\'espace.</string>
<string name="cache_clear_warning">Êtes-vous sûr de vouloir supprimer les historiques des conversations et autres données locales ?\nLes paramètres des comptes et les listes de contacts ne seront pas affectés. L\'application sera fermée.</string> <string name="cache_clear_warning">Êtes-vous sûr de vouloir supprimer les historiques des conversations et autres données locales ?\nLes paramètres des comptes et les listes de contacts ne seront pas affectés. L\'application sera fermée.</string>
<string name="chats_send_by_enter">Entrée pour envoyer\nAppuyer sur Entrée pour envoyer un message</string> <string name="chats_send_by_enter">\"Entrée\" pour envoyer\nAppuyer sur \"Entrée\" pour envoyer un message</string>
<string name="connection_go_away">Absence automatique\nPasser au statut \"Absent\" au verrouillage de l\'écran</string> <string name="connection_go_away">Absence automatique\nPasser au statut \"Absent\" au verrouillage de l\'écran</string>
<string name="contacts_order">Trier les contacts\nChoisir l\'ordre d\'affichage des contacts</string> <string name="contacts_order">Trier les contacts\nChoisir l\'ordre d\'affichage des contacts</string>
<string name="contacts_order_alphabet">Alphabétique</string> <string name="contacts_order_alphabet">Alphabétique</string>
...@@ -13,28 +13,28 @@ ...@@ -13,28 +13,28 @@
<string name="contacts_show_avatars">Afficher les avatars\nAfficher les avatars des utilisateurs dans la liste de contacts</string> <string name="contacts_show_avatars">Afficher les avatars\nAfficher les avatars des utilisateurs dans la liste de contacts</string>
<string name="contacts_show_empty_groups">Afficher les groupes vides\nAfficher les groupes sans contact en ligne</string> <string name="contacts_show_empty_groups">Afficher les groupes vides\nAfficher les groupes sans contact en ligne</string>
<string name="contacts_show_groups">Afficher les groupes\nAfficher les groupes dans la liste de contacts</string> <string name="contacts_show_groups">Afficher les groupes\nAfficher les groupes dans la liste de contacts</string>
<string name="contacts_show_offline">Afficher les contacts hors ligne</string> <string name="contacts_show_offline">Afficher les contacts hors-ligne</string>
<string name="contacts_show_panel">Afficher les panneaux de comptes\nAfficher les boutons d\'action avec avatars en bas à droite de la liste de contacts</string> <string name="contacts_show_panel">Boutons de compte\nAfficher les boutons d\'action avec avatars en bas à droite de la liste de contacts</string>
<string name="contacts_stay_active_chats">Dupliquer les conversations actives\nLes conversations actives apparaissent à la fois en haut de la liste de contact et dans les groupes</string> <string name="contacts_stay_active_chats">Dupliquer les conversations actives\nLes conversations actives apparaissent à la fois en haut de la liste de contact et dans les groupes</string>
<string name="debug_log">Journal de débogage\nÉcrire les messages dans le journal de débogage (veuillez redémarrer l\'application pour appliquer les modifications)</string> <string name="debug_log">Journal de débogage\nÉcrire les messages dans le journal de débogage (redémarrez l\'application pour appliquer)</string>
<string name="events_lightning">Notification lumineuse\nLa LED clignote lors d\'une notification</string> <string name="events_lightning">Notification lumineuse\nLa LED clignote lors d\'une notification</string>
<string name="events_persistent">Icône de barre des tâches\nAfficher une notification permanente. Cette option force Android à garder l\'application en mémoire</string> <string name="events_persistent">Icône de barre des tâches\nAffiche une notification permanente. Cette option force Android à garder l\'application en mémoire</string>
<string name="events_sound">Alerte sonore\nChoisir le son de notification</string> <string name="events_sound">Alerte sonore\nChoisir la sonnerie de notification</string>
<string name="events_vibro">Vibration\nVibrer sur notification</string> <string name="events_vibro">Vibration\nVibrer lors de la notification</string>
<string name="interface_theme">Thème\nParamètres de thème</string> <string name="interface_theme">Thème\nParamètres de thème</string>
<string name="interface_theme_dark">Foncé</string> <string name="interface_theme_dark">Foncé</string>
<string name="interface_theme_light">Clair</string> <string name="interface_theme_light">Clair</string>
<string name="interface_theme_normal">Défaut</string> <string name="interface_theme_normal">Défaut</string>
<string name="interface_smiles">Émoticônes\nParamètres émoticônes (connu avant comme smiley)</string> <string name="interface_smiles">Émoticônes\nParamètres des émoticônes / smileys / emojis</string>
<string name="interface_smiles_android">Émoticônes Android</string> <string name="interface_smiles_android">Émoticônes Android</string>
<string name="interface_smiles_none">Pas d\'émoticônes graphiques</string> <string name="interface_smiles_none">Pas d\'émoticônes graphiques</string>
<string name="preference_connection">Paramètres de connexion\nParamètres de connexion</string> <string name="preference_connection">Paramètres de connexion\nParamètres de connexion</string>
<string name="preference_contacts">Liste de contacts\nPersonnaliser l\'apparence de la liste de contacts</string> <string name="preference_contacts">Liste de contacts\nPersonnaliser l\'apparence de la liste de contacts</string>
<string name="preference_debug">Paramètres de débuggage\nMerci de sélectionner ceci si vous souhaitez aider les développeurs à améliorer Xabber</string> <string name="preference_debug">Paramètres de débogage\nParamètres pour aider les développeurs à améliorer Xabber</string>
<string name="preference_editor">Paramètres</string> <string name="preference_editor">Paramètres</string>
<string name="preference_events">Notifications\nParamètres de notification</string> <string name="preference_events">Notifications\nParamètres de notification</string>
<string name="preference_interface">Apparence\nParamètres du thème</string> <string name="preference_interface">Apparence\nParamètres du thème</string>
<string name="about_viewer">A propos</string> <string name="about_viewer">À propos</string>
<string name="chats_show_background">Afficher l\'arrière-plan\nDésactiver cette option peut améliorer les performances</string> <string name="chats_show_background">Afficher l\'arrière-plan\nDésactiver cette option peut améliorer les performances</string>
<string name="chats_font_size">Taille de police\nTaille du texte des messages</string> <string name="chats_font_size">Taille de police\nTaille du texte des messages</string>
<string name="chats_font_size_large">Grande</string> <string name="chats_font_size_large">Grande</string>
...@@ -45,26 +45,26 @@ ...@@ -45,26 +45,26 @@
<string name="chats_hide_keyboard_landscape">En mode paysage</string> <string name="chats_hide_keyboard_landscape">En mode paysage</string>
<string name="chats_receipt">Accusés de réception\nEnvoyer et recevoir des accusés de réception</string> <string name="chats_receipt">Accusés de réception\nEnvoyer et recevoir des accusés de réception</string>
<string name="chats_show_avatars">Avatars dans les messages\nAfficher les avatars dans chaque message</string> <string name="chats_show_avatars">Avatars dans les messages\nAfficher les avatars dans chaque message</string>
<string name="chats_show_status_change">Afficher les changements de statut\nAfficher un messages lors du changement de statut de votre correspondant</string> <string name="chats_show_status_change">Afficher les changements de statut\nAfficher les messages de changement de statut</string>
<string name="chats_show_status_change_muc">Dans les salons de discussions</string> <string name="chats_show_status_change_muc">Dans les conférences</string>
<string name="chats_state_notification">Afficher notification d\'écriture\nNotifier que l\'interlocuteur est en train d\'écrire</string> <string name="chats_state_notification">Afficher notification d\'écriture\nNotifier que l\'interlocuteur est en train d\'écrire</string>
<string name="connection_adjust_priority">Ajuster la priorité\nModifier la priorité en fonction du statut. Ce paramètre l\'emportera sur la priorité globale du compte.</string> <string name="connection_adjust_priority">Ajuster la priorité\nModifier la priorité en fonction du statut. Ce paramètre l\'emportera sur la priorité globale du compte.</string>
<string name="connection_go_away_immediately">Immédiatement au verrouillage d\'écran</string> <string name="connection_go_away_immediately">Immédiatement au verrouillage d\'écran</string>
<string name="connection_go_xa">Absence prolongée en cas d\'inactivité\nPasser en absence prolongée au verrouillage de l\'écran</string> <string name="connection_go_xa">Absence prolongée en cas d\'inactivité\nPasser en absence prolongée au verrouillage de l\'écran</string>
<string name="connection_priority">Configuration de la priorité</string> <string name="connection_priority">Configuration de la priorité</string>
<string name="connection_start_at_boot">Démarrer avec Android\nL\'application sera lancée au démarrage d\'Android. Ne fonctionne pas quand Xabber est installé sur une carte SD.</string> <string name="connection_start_at_boot">Démarrer avec Android\nL\'application sera lancée au démarrage d\'Android. Ne fonctionne pas quand Xabber est installé sur une carte SD.</string>
<string name="connection_wake_lock">Empêcher la mise en veille\nEmpêcher l\'appareil de se mettre veille. Décharge la batterie plus rapidement.</string> <string name="connection_wake_lock">Empêcher la mise en veille\nEmpêche l\'appareil de se mettre veille. Décharge la batterie plus rapidement.</string>
<string name="connection_wifi_lock">Garder le Wi-Fi activé\nEmpêcher le Wi-Fi de se mettre en veille. Décharge la batterie plus rapidement.</string> <string name="connection_wifi_lock">Garder le Wi-Fi activé\nEmpêche le Wi-Fi de se mettre en veille. Décharge la batterie plus rapidement</string>
<string name="contacts_reset_offline">Réinitialiser les paramètres hors connexion\nEffacer les paramètres individuels pour les groupes et les comptes</string> <string name="contacts_reset_offline">Réinitialiser les paramètres hors-ligne\nEffacer les paramètres individuels pour les groupes et les comptes</string>
<string name="contacts_reset_offline_warning">Voulez-vous réellement effacer les paramètres individuels des groupes et des comptes ?</string> <string name="contacts_reset_offline_warning">Êtes-vous sûr de vouloir effacer les paramètres individuels des groupes et des comptes ?</string>
<string name="events_first_only">Notifier au 1er message\nAlerter uniquement à la réception du 1er message d\'une conversation</string> <string name="events_first_only">Notifier au 1er message\nAlerter uniquement à la réception du 1er message d\'une conversation</string>
<string name="events_ignore_system_vibro">Ignorer les paramètres système du vibreur\nUtiliser cette option si le vibreur ne fonctionne pas</string> <string name="events_ignore_system_vibro">Ignorer les paramètres système du vibreur\nUtilisez cette option si le vibreur ne fonctionne pas</string>
<string name="events_message">Paramètres de notification\nConfigurer les notifications des messages entrants</string> <string name="events_message">Paramètres de notification\nConfigurer les notifications des messages entrants</string>
<string name="events_message_chat">Discussions seulement</string> <string name="events_message_chat">Conversations seulement</string>
<string name="events_message_chat_and_muc">Discussions et conférences</string> <string name="events_message_chat_and_muc">Conversations et conférences</string>
<string name="events_message_none">Ne pas signaler</string> <string name="events_message_none">Ne pas notifier</string>
<string name="events_show_text">Voir le message dans la zone de notification\nVoir le message texte dans la zone de notification</string> <string name="events_show_text">Afficher les messages dans la barre des tâches\nAffiche le texte des messages dans la zone de notification</string>
<string name="events_visible_chat">Signaler dans la discussion courante\nSignaler un message entrant dans la discussion courante</string> <string name="events_visible_chat">Notifier dans la conversation en cours\nSignaler les messages entrants dans la conversation en cours</string>
<string name="negative_priotiry_summary">%s (Vous ne recevrez aucun message)</string> <string name="negative_priotiry_summary">%s (Vous ne recevrez aucun message)</string>
<string name="preference_accounts">Comptes XMPP\nGérer les comptes</string> <string name="preference_accounts">Comptes XMPP\nGérer les comptes</string>
<string name="preference_security">Sécurité\nParamètres de sécurité</string> <string name="preference_security">Sécurité\nParamètres de sécurité</string>
...@@ -73,9 +73,9 @@ ...@@ -73,9 +73,9 @@
<string name="security_otr_history">Conserver l\'historique\nStocker l\'historique des conversations pour les sessions OTR</string> <string name="security_otr_history">Conserver l\'historique\nStocker l\'historique des conversations pour les sessions OTR</string>
<string name="security_otr_mode">Mode OTR</string> <string name="security_otr_mode">Mode OTR</string>
<string name="chats_attention">Demande d\'attention\nNotifier pour les demandes d\'attention reçues</string> <string name="chats_attention">Demande d\'attention\nNotifier pour les demandes d\'attention reçues</string>
<string name="chats_attention_sound">Son de demande d\'attention\nChoisir une sonnerie</string> <string name="chats_attention_sound">Sonnerie de demande d\'attention\nChoisir une sonnerie</string>
<string name="connection_load_vcard">Charger les vCard\nCharger et mettre à jour les informations personnelles et les avatars des contacts. Désactiver pour réduire l\'utilisation réseau.</string> <string name="connection_load_vcard">Charger les vCard\nTélécharger et mettre à jour les informations personnelles et les avatars des contacts. Désactivez pour réduire l\'utilisation réseau.</string>
<string name="connection_use_carbons">Mode copie carbone\nPeut être instable ! Partagera les messages de ce compte avec d\'autre clients activés. Désactiver pour réduire le traffic de données.</string> <string name="connection_use_carbons">Mode copie carbone\nPeut être instable ! Permet de partager simultanément les messages d\'un compte avec d\'autres clients en ligne. Désactiver pour réduire le traffic de données.</string>
<string name="events_phrases">Expressions clé\nCréer des notifications personnalisées pour les messages reçus contenant des données spécifiques</string> <string name="events_phrases">Expressions clé\nCréer des notifications personnalisées pour les messages reçus contenant des données spécifiques</string>
<string name="security_clear_certificate_warning">Êtes-vous sûr de vouloir supprimer tous les certificats ignorés ?</string> <string name="security_clear_certificate_warning">Êtes-vous sûr de vouloir supprimer tous les certificats ignorés ?</string>
</resources> </resources>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com--> <!--Generated by crowdin.com-->
<resources> <resources>
<string name="otr_answer">Réponse à la question secrète:</string> <string name="otr_answer">Réponse à la question secrète :</string>
<string name="otr_question">Question secrète:</string> <string name="otr_question">Question secrète :</string>
<string name="otr_question_description">Utiliser une question secrète pour vérifier votre interlocuteur.</string> <string name="otr_question_description">Utilisez une question secrète pour vous vérifier mutuellement.</string>
<string name="otr_secret">Secret partagé:</string> <string name="otr_secret">Secret partagé :</string>
<string name="otr_secret_description">Utiliser le secret partagé pour vous vérifier mutuellement.</string> <string name="otr_secret_description">Utiliser un secret partagé pour vous vérifier mutuellement.</string>
</resources> </resources>
...@@ -9,13 +9,13 @@ ...@@ -9,13 +9,13 @@
<string name="empty_status">&lt;Pas de message&gt;</string> <string name="empty_status">&lt;Pas de message&gt;</string>
<string name="invisible">Invisible</string> <string name="invisible">Invisible</string>
<string name="remove_status">Supprimer le statut</string> <string name="remove_status">Supprimer le statut</string>
<string name="status_editor">Définir le statut</string> <string name="status_editor">Paramétrer le statut</string>
<string name="status_text_hint">Écrire message de statut</string> <string name="status_text_hint">Écrire message de statut</string>
<string name="unavailable">Hors ligne</string> <string name="unavailable">Hors-ligne</string>
<string name="unsubscribed">Autorisation refusée</string> <string name="unsubscribed">Autorisation refusée</string>
<string name="xa">Absent depuis un moment</string> <string name="xa">Absent depuis un moment</string>
<string name="new_status">Nouveau statut</string> <string name="new_status">Nouveau statut</string>
<string name="saved_statuses">Statuts enregistrés</string> <string name="saved_statuses">Statuts enregistrés</string>
<string name="clear_status_history">Effacer l\'historique des status</string> <string name="clear_status_history">Effacer l\'historique des statuts</string>
<string name="status_message">Message d\'état</string> <string name="status_message">Message de statut</string>
</resources> </resources>
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<string name="disabled">Désactivé</string> <string name="disabled">Désactivé</string>
<string name="manual">Manuel</string> <string name="manual">Manuel</string>
<string name="never">Jamais</string> <string name="never">Jamais</string>
<string name="required">Requis</string> <string name="required">Obligatoire</string>
<string name="auto">Automatiquement</string> <string name="auto">Automatique</string>
<string name="save">Enregistrer</string> <string name="save">Enregistrer</string>
</resources> </resources>
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
<string name="account_tls_mode">TLS/SSL 使用方法</string> <string name="account_tls_mode">TLS/SSL 使用方法</string>
<string name="account_tls_require">TLS が必要</string> <string name="account_tls_require">TLS が必要</string>
<string name="account_tls_require_summary">サーバーに接続時 TLS 暗号化を必要とします</string> <string name="account_tls_require_summary">サーバーに接続時 TLS 暗号化を必要とします</string>
<string name="account_use_orbot">TOR 匿名ネットワークでチャットし, TLS 暗号プロトコルを強制的に使用します\nGoogle Talk では推奨しません</string> <string name="account_use_orbot">TOR 匿名ネットワークでチャットし, TLS 暗号プロトコルを強制的に使用\nGoogle Talk では推奨しません</string>
<string name="confirm_cancellation">すべての変更を取り消してもよろしいですか?</string> <string name="confirm_cancellation">すべての変更を取り消してもよろしいですか?</string>
<string name="INCORRECT_USER_NAME">ユーザー名が正しくありません. 詳細は下部のヘルプテキストを確認してください.</string> <string name="INCORRECT_USER_NAME">ユーザー名が正しくありません. 詳細は下部のヘルプテキストを確認してください.</string>
<string name="orbot_required_message">TOR を使用して処理するには Orbot をインストールし proxy のトラフィックを有効にする必要があります. Google Play からインストールしますか?</string> <string name="orbot_required_message">TOR を使用して処理するには Orbot をインストールし proxy のトラフィックを有効にする必要があります. Google Play からインストールしますか?</string>
......
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">相手のフィンガープリント:</string> <string name="otr_remote_fingerprint">相手のフィンガープリント:</string>
<string name="otr_scan_fingerprint">相手のフィンガープリントで QR コードをスキャン</string> <string name="otr_scan_fingerprint">相手のフィンガープリントで QR コードをスキャン</string>
<string name="otr_show_fingerprint">あなたのフィンガープリントで QR コードを表示</string> <string name="otr_show_fingerprint">あなたのフィンガープリントで QR コードを表示</string>
<string name="zxing_install_fail">Google Play がインストールされていません. バーコード・スキャナーを手動でインストールしてください.</string>
<string name="zxing_install_message">このアプリケーションはバーコード・スキャナーが必要です. インストールしますか?</string>
<string name="otr_copy_fingerprint">あなたのフィンガープリントをクリップボードにコピー</string> <string name="otr_copy_fingerprint">あなたのフィンガープリントをクリップボードにコピー</string>
</resources> </resources>
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<string name="debug_log">デバッグ・ログ\nメッセージをデバッグ・ログに書き込む (変更を適用するにはアプリケーションを再起動してください)</string> <string name="debug_log">デバッグ・ログ\nメッセージをデバッグ・ログに書き込む (変更を適用するにはアプリケーションを再起動してください)</string>
<string name="events_lightning">ライト通知\n通知時に LED を点滅します</string> <string name="events_lightning">ライト通知\n通知時に LED を点滅します</string>
<string name="events_persistent">タスクバーアイコン\n永続的な通知を表示します。このオプションは、Android がアプリケーションをメモリからアンロードしないようにします</string> <string name="events_persistent">タスクバーアイコン\n永続的な通知を表示します。このオプションは、Android がアプリケーションをメモリからアンロードしないようにします</string>
<string name="events_sound">オーディオ・アラート\n通知サウンドを選択してください</string> <string name="events_sound">オーディオ・アラート\n通知サウンドを選択します</string>
<string name="events_vibro">バイブレート\n通知時にバイブレートします</string> <string name="events_vibro">バイブレート\n通知時にバイブレートします</string>
<string name="interface_theme">テーマ\nテーマ設定</string> <string name="interface_theme">テーマ\nテーマ設定</string>
<string name="interface_theme_dark">ダーク</string> <string name="interface_theme_dark">ダーク</string>
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
<string name="connection_priority">優先度設定</string> <string name="connection_priority">優先度設定</string>
<string name="connection_start_at_boot">Android の起動時に開始\nAndroid の起動時にアプリケーションを開始します。これは Xabber が SD カードにインストールされている場合は動作しません。</string> <string name="connection_start_at_boot">Android の起動時に開始\nAndroid の起動時にアプリケーションを開始します。これは Xabber が SD カードにインストールされている場合は動作しません。</string>
<string name="connection_wake_lock">スリープモードを防止\nデバイスのスリープを防止します。これは、バッテリーの使用量が増えます。</string> <string name="connection_wake_lock">スリープモードを防止\nデバイスのスリープを防止します。これは、バッテリーの使用量が増えます。</string>
<string name="connection_wifi_lock">WiFi をアクティブのままにする\nスタンバイ時に WiFi をアクティブにしておきます。これは、バッテリーの使用量を増やします</string> <string name="connection_wifi_lock">WiFi をアクティブのままにする\nスタンバイ時に WiFi をアクティブにしておきます。これは、バッテリーの使用量が増えます</string>
<string name="contacts_reset_offline">オフライン設定をリセット\nグループおよびアカウントに対する個々の設定をクリアします</string> <string name="contacts_reset_offline">オフライン設定をリセット\nグループおよびアカウントに対する個々の設定をクリアします</string>
<string name="contacts_reset_offline_warning">グループおよびアカウントに対する個々の設定をクリアしてもよろしいですか?</string> <string name="contacts_reset_offline_warning">グループおよびアカウントに対する個々の設定をクリアしてもよろしいですか?</string>
<string name="events_first_only">最初のメッセージでアラート\nチャットの最初のメッセージのみ通知します</string> <string name="events_first_only">最初のメッセージでアラート\nチャットの最初のメッセージのみ通知します</string>
...@@ -76,6 +76,6 @@ ...@@ -76,6 +76,6 @@
<string name="chats_attention_sound">注意サウンド\n着信音を選択します</string> <string name="chats_attention_sound">注意サウンド\n着信音を選択します</string>
<string name="connection_load_vcard">vCard をロード\n連絡先の個人情報およびアバターをロードして更新します. 無効にすると通信の使用量が減ります.</string> <string name="connection_load_vcard">vCard をロード\n連絡先の個人情報およびアバターをロードして更新します. 無効にすると通信の使用量が減ります.</string>
<string name="connection_use_carbons">カーボン コピー モード\n不安定になることがあります! このクライアントで同じアカウントのセッションを共有します。無効にすると、トラフィックの使用状況を削減します。</string> <string name="connection_use_carbons">カーボン コピー モード\n不安定になることがあります! このクライアントで同じアカウントのセッションを共有します。無効にすると、トラフィックの使用状況を削減します。</string>
<string name="events_phrases">キーフレーズ\n重要な phrases\nプリセットしたフレーズが含まれたメッセージを通知します。サウンドを選択します</string> <string name="events_phrases">キーフレーズ\n指定したフレーズが含まれるメッセージを通知します</string>
<string name="security_clear_certificate_warning">無視された証明書をすべて削除してもよろしいですか?</string> <string name="security_clear_certificate_warning">無視された証明書をすべて削除してもよろしいですか?</string>
</resources> </resources>
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">Цифровой отпечаток пальца собеседника:</string> <string name="otr_remote_fingerprint">Цифровой отпечаток пальца собеседника:</string>
<string name="otr_scan_fingerprint">Сканировать QR код с цифровым отпечатком пальца собеседника</string> <string name="otr_scan_fingerprint">Сканировать QR код с цифровым отпечатком пальца собеседника</string>
<string name="otr_show_fingerprint">Показать QR код с Вашим отпечатком пальца</string> <string name="otr_show_fingerprint">Показать QR код с Вашим отпечатком пальца</string>
<string name="zxing_install_fail">У вас не установлен Google Play. Пожалуйста установите Сканер штрих-кодов вручную.</string>
<string name="zxing_install_message">Приложению требуется Сканер штрих-кодов. Вы хотите его установить?</string>
<string name="otr_copy_fingerprint">Скопировать ваш отпечаток в буфер обмена</string> <string name="otr_copy_fingerprint">Скопировать ваш отпечаток в буфер обмена</string>
</resources> </resources>
...@@ -42,11 +42,11 @@ ...@@ -42,11 +42,11 @@
<string name="action_otr_smp_verified">Проверавање завршено успешно</string> <string name="action_otr_smp_verified">Проверавање завршено успешно</string>
<string name="action_otr_unreadable">Примљена шифрована порука је нечитљива</string> <string name="action_otr_unreadable">Примљена шифрована порука је нечитљива</string>
<string name="action_otr_verified">Шифровање је укључено</string> <string name="action_otr_verified">Шифровање је укључено</string>
<string name="action_status_available">%1$s је сад на вези</string> <string name="action_status_available">корисник %1$s је сад на вези</string>
<string name="action_status_away">%1$s је сад одсутан</string> <string name="action_status_away">корисник %1$s је сад одсутан</string>
<string name="action_status_chat">%1$s слободан за ћаскање</string> <string name="action_status_chat">корисник %1$s је слободан за ћаскање</string>
<string name="action_status_dnd">%1$s моли да се не узнемирава</string> <string name="action_status_dnd">корисник %1$s моли да се не узнемирава</string>
<string name="action_status_unavailable">корисник %1$s није недоступан</string> <string name="action_status_unavailable">корисник %1$s је сад недоступан</string>
<string name="action_status_xa">корисник %1$s је одсутан дуже време</string> <string name="action_status_xa">корисник %1$s је одсутан дуже време</string>
<string name="action_subject">%1$s измени тему у: %2$s</string> <string name="action_subject">%1$s измени тему у: %2$s</string>
<string name="ATTENTION_IS_NOT_SUPPORTED">Контакт не подржава или је искључио пажњу</string> <string name="ATTENTION_IS_NOT_SUPPORTED">Контакт не подржава или је искључио пажњу</string>
......
...@@ -50,8 +50,8 @@ ...@@ -50,8 +50,8 @@
<string name="group_room">Групна ћаскања</string> <string name="group_room">Групна ћаскања</string>
<string name="OTR_ERROR">ОТР грешка</string> <string name="OTR_ERROR">ОТР грешка</string>
<string name="select_contact">Тапните за избор контакта</string> <string name="select_contact">Тапните за избор контакта</string>
<string name="show_offline_always">увек прикажи</string> <string name="show_offline_always">увек</string>
<string name="show_offline_never">никад не приказуј</string> <string name="show_offline_never">никад</string>
<string name="show_offline_normal">користи опште поставке</string> <string name="show_offline_normal">користи опште поставке</string>
<string name="show_offline_settings">Прикажи неповезане контакте</string> <string name="show_offline_settings">Прикажи неповезане контакте</string>
<string name="start_at_boot_suggest">Желите ли покретати Ксабер при дизању система?\nМожете да измените ово у \"Поставке\" → \"Поставке везе\" → \"Покрени при подизању система\"</string> <string name="start_at_boot_suggest">Желите ли покретати Ксабер при дизању система?\nМожете да измените ово у \"Поставке\" → \"Поставке везе\" → \"Покрени при подизању система\"</string>
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<string name="vcard_type_msg">Говорна пошта</string> <string name="vcard_type_msg">Говорна пошта</string>
<string name="vcard_type_internet">Интернет</string> <string name="vcard_type_internet">Интернет</string>
<string name="please_wait">Сачекајте...</string> <string name="please_wait">Сачекајте...</string>
<string name="unknown">Непознато</string> <string name="unknown">непознат</string>
<string name="edit_alias">Уреди псеудоним</string> <string name="edit_alias">Уреди псеудоним</string>
<string name="edit_contact_groups">Уреди групе</string> <string name="edit_contact_groups">Уреди групе</string>
<string name="remove_contact">Уклони контакт</string> <string name="remove_contact">Уклони контакт</string>
......
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">Отисак вашег саговорника:</string> <string name="otr_remote_fingerprint">Отисак вашег саговорника:</string>
<string name="otr_scan_fingerprint">Скенирајте QR код са отиском саговорника</string> <string name="otr_scan_fingerprint">Скенирајте QR код са отиском саговорника</string>
<string name="otr_show_fingerprint">Прикажи QR код мог отиска</string> <string name="otr_show_fingerprint">Прикажи QR код мог отиска</string>
<string name="zxing_install_fail">Нема Гуглове Плеј продавнице. Инсталирајте скенер бар-кôда ручно.</string>
<string name="zxing_install_message">Ова апликација захтева скенер бар-кôда. Желите ли да га инсталирате?</string>
<string name="otr_copy_fingerprint">Копирај мој отисак у клипборд</string> <string name="otr_copy_fingerprint">Копирај мој отисак у клипборд</string>
</resources> </resources>
...@@ -8,15 +8,15 @@ ...@@ -8,15 +8,15 @@
<string name="contacts_order">Редослед контаката\nОдређује редослед којим се приказују контакти</string> <string name="contacts_order">Редослед контаката\nОдређује редослед којим се приказују контакти</string>
<string name="contacts_order_alphabet">по имену</string> <string name="contacts_order_alphabet">по имену</string>
<string name="contacts_order_status">по стању</string> <string name="contacts_order_status">по стању</string>
<string name="contacts_show_accounts">Групиши по налогу\nГрупише контакте у листи по налозима</string> <string name="contacts_show_accounts">Групиши по налогу\nГруписање контаката у листи по налозима</string>
<string name="contacts_show_active_chats">Активна ћаскања на врху\nПриказује активна ћаскања изнад листе контаката</string> <string name="contacts_show_active_chats">Активна ћаскања на врху\nПриказ активних ћаскања изнад листе контаката</string>
<string name="contacts_show_avatars">Прикажи аватаре\nПриказује аватаре корисника у листи</string> <string name="contacts_show_avatars">Прикажи аватаре\nПриказ аватара корисника у листи</string>
<string name="contacts_show_empty_groups">Прикажи празне групе\nПриказује и групе без контаката на вези</string> <string name="contacts_show_empty_groups">Прикажи празне групе\nПриказ група без контаката на вези</string>
<string name="contacts_show_groups">Прикажи групе\nПриказује групе у листи контаката</string> <string name="contacts_show_groups">Прикажи групе\nПриказ групе у листи контаката</string>
<string name="contacts_show_offline">Прикажи неповезане контакте</string> <string name="contacts_show_offline">Прикажи неповезане контакте</string>
<string name="contacts_show_panel">Прикажи панел налога\nПриказује дугмад радњи са аватарима у доњем десном углу листе</string> <string name="contacts_show_panel">Прикажи панел налога\nПриказ дугмади радњи са аватарима у доњем десном углу листе</string>
<string name="contacts_stay_active_chats">Дупликати активног ћаскања\nАктивна ћаскања се приказују и изнад листе и у групама</string> <string name="contacts_stay_active_chats">Дупликати активног ћаскања\nАктивна ћаскања се приказују и изнад листе и у групама</string>
<string name="debug_log">Дневник грешака\nУписује поруке у дневник за отклањање грешака (потребан рестарт)</string> <string name="debug_log">Дневник грешака\nУпис порука у дневник за отклањање грешака (потребан рестарт)</string>
<string name="events_lightning">Светлосна индикација\nЛЕД трепће при обавештењима</string> <string name="events_lightning">Светлосна индикација\nЛЕД трепће при обавештењима</string>
<string name="events_persistent">Икона траке задатака\nПриказује стално обавештење. Ова опција спречава Андроид да избаци програм из меморије</string> <string name="events_persistent">Икона траке задатака\nПриказује стално обавештење. Ова опција спречава Андроид да избаци програм из меморије</string>
<string name="events_sound">Звучно упозорење\nИзаберите звук обавештења</string> <string name="events_sound">Звучно упозорење\nИзаберите звук обавештења</string>
...@@ -44,8 +44,8 @@ ...@@ -44,8 +44,8 @@
<string name="chats_hide_keyboard">Сакриј тастатуру\nСакриј софтверску тастатуру након слања поруке</string> <string name="chats_hide_keyboard">Сакриј тастатуру\nСакриј софтверску тастатуру након слања поруке</string>
<string name="chats_hide_keyboard_landscape">у положеном режиму</string> <string name="chats_hide_keyboard_landscape">у положеном режиму</string>
<string name="chats_receipt">Потврда о пријему поруке\nШаљи и примај потврде о пријему поруке</string> <string name="chats_receipt">Потврда о пријему поруке\nШаљи и примај потврде о пријему поруке</string>
<string name="chats_show_avatars">Аватари у порукама\nПрикажи аватаре у свакој поруци</string> <string name="chats_show_avatars">Аватари у порукама\nПриказ аватара у свакој поруци</string>
<string name="chats_show_status_change">Прикажи промену стања\nПриказуј поруке о променама стања</string> <string name="chats_show_status_change">Прикажи промену стања\nПриказ порука о променама стања</string>
<string name="chats_show_status_change_muc">у групним ћаскањима</string> <string name="chats_show_status_change_muc">у групним ћаскањима</string>
<string name="chats_state_notification">Прикажи обавештење о куцању\nПриказује кад други корисник куца поруку</string> <string name="chats_state_notification">Прикажи обавештење о куцању\nПриказује кад други корисник куца поруку</string>
<string name="connection_adjust_priority">Подеси важност\nПодеси важност на основу изабраног стања. Важност налога биће занемарена.</string> <string name="connection_adjust_priority">Подеси важност\nПодеси важност на основу изабраног стања. Важност налога биће занемарена.</string>
...@@ -57,20 +57,20 @@ ...@@ -57,20 +57,20 @@
<string name="connection_wifi_lock">Бежична веза активна\nДржи бежичну везу активном и током спавања. Повећаће потрошњу батерије</string> <string name="connection_wifi_lock">Бежична веза активна\nДржи бежичну везу активном и током спавања. Повећаће потрошњу батерије</string>
<string name="contacts_reset_offline">Ресетуј поставке „ван везе“\nБрише појединачне поставке за групе и налоге за приказ неповезаних контаката</string> <string name="contacts_reset_offline">Ресетуј поставке „ван везе“\nБрише појединачне поставке за групе и налоге за приказ неповезаних контаката</string>
<string name="contacts_reset_offline_warning">Заиста желите да очистите појединачне поставке за групе и налоге?</string> <string name="contacts_reset_offline_warning">Заиста желите да очистите појединачне поставке за групе и налоге?</string>
<string name="events_first_only">Упозори само на прву поруку\nОбавештава само за прву поруку у ћаскању</string> <string name="events_first_only">Упозори само на прву поруку\nОбавештење само за прву поруку у ћаскању</string>
<string name="events_ignore_system_vibro">Занемари системске поставке вибрације\nКористите ову опцију ако вам вибрација не ради</string> <string name="events_ignore_system_vibro">Занемари системске поставке вибрације\nКористите ову опцију ако вам вибрација не ради</string>
<string name="events_message">Поставке обавештења\nПоставке обавештења за долазне поруке</string> <string name="events_message">Поставке обавештења\nПоставке обавештења за долазне поруке</string>
<string name="events_message_chat">само ћаскања</string> <string name="events_message_chat">само ћаскања</string>
<string name="events_message_chat_and_muc">ћаскања и конференције</string> <string name="events_message_chat_and_muc">ћаскања и конференције</string>
<string name="events_message_none">не обавештавај</string> <string name="events_message_none">не обавештавај</string>
<string name="events_show_text">Прикажи поруку као обавештење\nПриказује текст поруке у траци обавештења</string> <string name="events_show_text">Прикажи поруку као обавештење\nПриказ текста поруке у траци обавештења</string>
<string name="events_visible_chat">Обавештење у текућем ћаскању\nОбавештава о долазним порукама текућег ћаскања</string> <string name="events_visible_chat">Обавештење у текућем ћаскању\nОбавештава о долазним порукама текућег ћаскања</string>
<string name="negative_priotiry_summary">%s (нећете примати никакве поруке)</string> <string name="negative_priotiry_summary">%s (нећете примати никакве поруке)</string>
<string name="preference_accounts">ИксМПП налози\nУправљање налозима</string> <string name="preference_accounts">ИксМПП налози\nУправљање налозима</string>
<string name="preference_security">Безбедност\nПоставке безбедности</string> <string name="preference_security">Безбедност\nПоставке безбедности</string>
<string name="security_check_certificate">Провери сертификат сервера\nОбавештава о проблематичним сертификатима за шифроване везе</string> <string name="security_check_certificate">Провери сертификат сервера\nОбавештава о проблематичним сертификатима за шифроване везе</string>
<string name="security_clear_certificate">Уклони сертификате\nОчисти листу занемарених сертификата</string> <string name="security_clear_certificate">Уклони сертификате\nОчисти листу занемарених сертификата</string>
<string name="security_otr_history">Бележи историјат\nИсторијат се бележи за ОТР сесије</string> <string name="security_otr_history">Бележи историјат\nБележење историјата за ОТР сесије</string>
<string name="security_otr_mode">ОТР режим</string> <string name="security_otr_mode">ОТР режим</string>
<string name="chats_attention">Пажња\nРеаговаће се на долазне захтеве за пажњом</string> <string name="chats_attention">Пажња\nРеаговаће се на долазне захтеве за пажњом</string>
<string name="chats_attention_sound">Звук за пажњу\nИзаберите звоно</string> <string name="chats_attention_sound">Звук за пажњу\nИзаберите звоно</string>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com--> <!--Generated by crowdin.com-->
<resources> <resources>
<string name="available">Доступан</string> <string name="available">ту сам</string>
<string name="away">Одсутан</string> <string name="away">нисам ту</string>
<string name="chat">Спреман за ћаскање!</string> <string name="chat">ћаска ми се!</string>
<string name="dnd">Не ометај</string> <string name="dnd">не ометај</string>
<string name="edit_status">Уреди стање</string> <string name="edit_status">Уреди стање</string>
<string name="empty_status">&lt;без поруке&gt;</string> <string name="empty_status">&lt;без поруке&gt;</string>
<string name="invisible">Невидљив</string> <string name="invisible">невидљиво</string>
<string name="remove_status">Обриши стање</string> <string name="remove_status">Обриши стање</string>
<string name="status_editor">Постави стање</string> <string name="status_editor">Постави стање</string>
<string name="status_text_hint">Унесите поруку стања</string> <string name="status_text_hint">Унесите поруку стања</string>
<string name="unavailable">Неповезан</string> <string name="unavailable">ван везе</string>
<string name="unsubscribed">Неаутентификован</string> <string name="unsubscribed">Неаутентификован</string>
<string name="xa">Одсутан дуго времена</string> <string name="xa">нисам ту дуго времена</string>
<string name="new_status">Нова порука стања</string> <string name="new_status">Нова порука стања</string>
<string name="saved_statuses">Сачуване поруке стања</string> <string name="saved_statuses">Сачуване поруке стања</string>
<string name="clear_status_history">Очисти историјат порука стања</string> <string name="clear_status_history">Очисти историјат порука стања</string>
......
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="account_compression">Використовувати стиснення</string>
<string name="account_enabled">Активна</string>
<string name="account_host">Хост</string>
<string name="account_password">Пароль</string>
<string name="confirm_password">Підтвердіть пароль</string>
<string name="account_port">Порт</string>
<string name="account_priority">Пріоритет</string>
<string name="account_resource">Ресурс</string>
<string name="account_server_name">Сервер</string>
<string name="account_type">Тип облікового запису</string>
<string name="account_type_hints_gtalk">обліковий запис gmail.com чи служби google</string>
<string name="account_type_helps_gtalk">Якщо ви не маєте облікового запису Google, ви можете створити його на http://mail.google.com\nАбо ви можете використати your_user_name@your_google_domain</string>
<string name="account_type_helps_xmpp">Якщо ви хочете дізнатися більше про XMPP (Jabber) тут: https://xmpp.org</string>
<string name="account_user_name">Ім’я користувача</string>
<string name="EMPTY_SERVER_NAME">Не вказано ім’я сервера</string>
<string name="EMPTY_USER_NAME">Не вказано ім’я користувача</string>
<string name="CONFIRM_PASSWORD">Паролі не збігаються</string>
<string name="account_archive_mode">Зберігати історію повідомлень</string>
<string name="account_archive_mode_available">На сервері, за можливістю</string>
<string name="account_archive_mode_dont_store">Не зберігати</string>
<string name="account_archive_mode_local">На пристрої</string>
<string name="account_archive_mode_server">На сервері</string>
<string name="account_archive_mode_unread">Лише не відправлені і не прочитані повідомлення</string>
<string name="account_compression_summary">Позначте для включення стиснення даних</string>
<string name="account_custom">Вказати хост вручну</string>
<string name="account_custom_summary">Вказати хост для підключення вручну, замість використання SRV запису</string>
<string name="account_enabled_summary">Позначте, для включення облікового запису</string>
<string name="account_invalid_port">Порт має бути числом (типове значення: 5222)</string>
<string name="account_invalid_priority">Пріоритет має бути в діапазоні між -128 і 128 (типове значення :10)</string>
<string name="account_oauth">Авторизація</string>
<string name="account_oauth_invalidated">Не авторизований</string>
<string name="account_oauth_summary">Налаштування OAuth авторизації</string>
<string name="account_proxy_host">Вузол проксі</string>
<string name="account_proxy_password">Пароль</string>
<string name="account_proxy_port">Порт проксі</string>
<string name="account_proxy_type">Тип проксі</string>
<string name="account_proxy_type_none">Вимкнено</string>
<string name="account_proxy_user">Ім’я користувача</string>
<string name="account_sasl">Використовувати SASL авторизацію (рекомендовано)</string>
<string name="account_sasl_summary">Відключіть цей параметр при підключені до дуже старого серверу</string>
<string name="account_store_password">Зберігати пароль</string>
<string name="account_store_password_summary">Відключення призведе до запиту пароля, під час кожного під\'єднання</string>
<string name="account_syncable">Інтеграція із контактами в телефоні</string>
<string name="account_syncable_summary">Показувати контакти з даного облікового запису в телефонній книзі</string>
<string name="account_tls_enable">Використовувати TLS</string>
<string name="account_tls_enable_summary">Використовувати TLS шифрування, якщо сервер підтримує</string>
<string name="account_tls_legacy">Старий SSL</string>
<string name="account_tls_legacy_summary">Використовувати старий SSL метод шифрування з’єднання із сервером</string>
<string name="account_tls_mode">Використання TLS/SSL</string>
<string name="account_tls_require">Вимагати TLS</string>
<string name="account_tls_require_summary">Вимагати TLS шифрування при підключені до серверу</string>
<string name="account_use_orbot">Вести балачку через анонімну мережу TOR використовуючи TLS протокол шифрування\nНе рекомендується для Google Talk</string>
<string name="confirm_cancellation">Ви впевнені, що бажаєте скасувати всі не збережені зміни?</string>
<string name="INCORRECT_USER_NAME">Неправильне ім’я користувача. Перегляньте підказку в нижній частині екрану</string>
<string name="orbot_required_message">Для використання TOR має бути встановлений Orbot і використаний як проксі сервер. Бажаєте встановити його із Google Play?</string>
<string name="orbot_required_title">Встановити Orbot?</string>
<string name="ACCOUNT_REGISTER_FAILED">Не вдалося зареєструвати обліковий запис на сервері.</string>
<string name="account_color">Колір облікового запису</string>
<string name="account_color_name_green">Зелений</string>
<string name="account_color_name_orange">Помаранчевий</string>
<string name="account_color_name_red">Червоний</string>
<string name="account_color_name_blue">Синій</string>
<string name="account_color_name_indigo">Індіго</string>
<string name="account_color_name_teal">Зеленовато-Голубий</string>
<string name="account_color_name_blue_grey">Синій сірий</string>
<string name="account_color_name_cyan">Блакитний</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="account_delete_confirm">Ви дійсно бажаєте видалити обліковий запис %s?\n(його не буде видалено з сервера, тільки з Xabber)</string>
<string name="account_add">Додати обліковий запис</string>
<string name="account_register">Реєстрація нового акаунта</string>
<string name="account_delete">Видалити обліковий запис</string>
<string name="account_editor">Редагувати обліковий запис</string>
<string name="account_state_registration">Реєстрація</string>
<string name="account_state_authentication">Авторизація</string>
<string name="account_state_connected">У мережі</string>
<string name="account_state_connecting">Підключення</string>
<string name="account_state_disconnecting">Відключення</string>
<string name="account_state_offline">Не у мережі</string>
<string name="account_state_waiting">Очікування підключення</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="action_status_text">%1$s встановив статус: %2$s</string>
<string name="action_status_text_none">%1$s очистив текст статусу</string>
<string name="action_join">%1$s підключився</string>
<string name="action_kick">%1$s був випханий</string>
<string name="account_is_offline">Повідомлення будуть доставлені після підключення до мережі</string>
<string name="chat_delay">надіслано %s</string>
<string name="chat_input_hint">Введіть повідомлення</string>
<string name="chat_send">Надіслати</string>
<string name="clear_history">Очистити історію</string>
<string name="contact_is_offline">Повідомлення доставлено на сервер отримувача і можуть бути прочитані ним після підключення до мережі</string>
<string name="ENTRY_IS_NOT_AVAILABLE">Контакт не доступний</string>
<string name="FILE_NOT_FOUND">Файл не знайдено</string>
<string name="message_copy">Копіювати</string>
<string name="message_quote">Цитувати</string>
<string name="message_remove">Вилучити з історії</string>
<string name="message_repeat">Повторити надсилання</string>
<string name="save_history">Зберегти локальну історію\nЗберігати історію повідомлень локально</string>
<string name="show_history">Показати історію</string>
<string name="action_attention_called">Виклик уваги було відправлено</string>
<string name="action_attention_requested">Увагу було звернуто</string>
<string name="action_ban">%1$s був заблокований</string>
<string name="action_ban_by">%2$s заблокував %1$s</string>
<string name="action_invite_error">Запрошення не було отримано %s</string>
<string name="action_invite_sent">Запрошення було відправлено %s</string>
<string name="action_join_complete">Ви підключились до конференції, Ваш псевдонім %1$s</string>
<string name="action_join_complete_to">Ви під\'єднались до конференції %1$s</string>
<string name="action_kick_by">%2$s викинув %1$s</string>
<string name="action_leave">%1$s покинув чат</string>
<string name="action_nickname">%1$s змінив нік на %2$s</string>
<string name="action_otr_encryption">Шифрування було включено, але особистість співрозмовника не була перевірена. Ви можете обрати метод перевірки в меню OTR шифрування</string>
<string name="action_otr_error">Помилка OTR: %1$s</string>
<string name="action_otr_finish">Співрозмовник завершив шифровану співбесіду, ви повинні зробити теж саме, або почати нову співбесіду знову.</string>
<string name="action_otr_finished_session">Ваше повідомлення не було надіслано. Покиньте розмову або перезапустіть її.</string>
<string name="action_otr_plain">Ви завершили шифровану бесіду</string>
<string name="action_otr_smp_cheated">Співрозмовник намагався обійти систему перевірки особистості</string>
<string name="action_otr_smp_failed">Не вдалося перевірити особистість співрозмовника</string>
<string name="action_otr_smp_not_approved">Ваша відповідь була успішно перевірена. Вам також слід задати питання співрозмовнику чи перевірити секретний ключ.</string>
<string name="action_otr_smp_unverified">Помилка перевірки</string>
<string name="action_otr_smp_verified">Перевірка особистості успішно завершено</string>
<string name="action_otr_unreadable">Неможливо прочитати отримане зашифроване повідомлення</string>
<string name="action_otr_verified">Шифрування було увімкнено</string>
<string name="action_status_available">%1$s тепер в мережі</string>
<string name="action_status_away">%1$s відійшов</string>
<string name="action_status_chat">%1$s готовий до спілкування</string>
<string name="action_status_dnd">%1$s просить не турбувати</string>
<string name="action_status_unavailable">%1$s від\'єднався</string>
<string name="action_status_xa">%1$s відійшов на довго</string>
<string name="action_subject">%1$s змінив(ла) тему: %2$s</string>
<string name="ATTENTION_IS_NOT_SUPPORTED">Контакт не підтримує можливість звернути свою увагу, або відключив дану функцію.</string>
<string name="call_attention">Звернути увагу</string>
<string name="chat_settings">Налаштування</string>
<string name="chat_state_composing">Набирає...</string>
<string name="chat_state_paused">Вводить текст...</string>
<string name="chat_typed">увійшов у %s</string>
<string name="export_chat">Зберегти чат</string>
<string name="export_chat_done">Історія збережена на SD-картці</string>
<string name="export_chat_mask">%2$s для %1$s.html</string>
<string name="export_chat_send">Надіслати після експорту</string>
<string name="export_chat_title">Вкажіть ім\'я файлу</string>
<string name="muc_invite">Запросити до конференції</string>
<string name="muc_is_unavailable">Повідомлення не можуть бути доставлені. Будь-ласка, приєднайтесь до конференції</string>
<string name="occupant_list">Перелік учасників</string>
<string name="otr_encryption">OTR шифрування</string>
<string name="otr_end">Зупинити шифрування</string>
<string name="otr_refresh">Почати шифрування спочатку</string>
<string name="otr_request">Співрозмовник відправив запит на OTR шифрування розмови, але у Вас не встановлено додаток, який його підтримує. Використайте Pidgin, Gajim чи Adium для PC/Mac та Xabber чи ChatSecure для Android. Завітайте на http://otr.cypherpunks.ca/ для отримання більш детальної інформації.</string>
<string name="otr_start">Почати шифрування</string>
<string name="otr_unencrypted_message">Це повідомлення не було зашифровано</string>
<string name="otr_unreadable_message">Зашифроване повідомлення, відправлено Вами, неможливо прочитати</string>
<string name="otr_verification">Перевірка особистості OTR</string>
<string name="otr_verify_fingerprint">Перевірка цифровим відбитком</string>
<string name="otr_verify_question">Перевірка питанням</string>
<string name="otr_verify_secret">Перевірка секретним ключем</string>
<string name="recent_chats">Недавні чати</string>
<string name="under_construction">В розробці</string>
<string name="under_construction_message">Цей екран у розробці</string>
<string name="chat_events_show_text_global">Використовувати глобальні параметри</string>
<string name="chat_events_show_text_always">Показати текст повідомлення</string>
<string name="chat_events_show_text_never">Приховати текст повідомлення</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="contact_account">Обліковий запис</string>
<string name="contact_group">Оберіть групи</string>
<string name="contact_name">Псевдонім (не обов\'язково)</string>
<string name="contact_subscribe_confirm">Надати доступ до статусу вашого облікового запису %1$s?</string>
<string name="contact_user">Ім\'я співрозмовника</string>
<string name="ENTRY_IS_NOT_FOUND">Контакт не знайдено</string>
<string name="group_is_empty">Вкажіть ім\'я групи</string>
<string name="group_name">Ім\'я групи</string>
<string name="choose_account">Оберіть обліковий запис</string>
<string name="EMPTY_ACCOUNT">Будь-ласка, оберіть обліковий запис</string>
<string name="add_new_group">Додати нову групу...</string>
<string name="accept_contact">Авторизувати</string>
<string name="decline_contact">Відхилити</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="accept_subscription">Прийняти контакт</string>
<string name="account_reconnect">Перепідключитись</string>
<string name="application_action_disabled">Керування обліковими записами</string>
<string name="application_action_empty">Додати обліковий запис</string>
<string name="application_action_no_contacts">Додати контакт</string>
<string name="application_action_no_online">Показувати контакти не в мережі</string>
<string name="application_action_offline">Підключитись</string>
<string name="application_action_waiting">Перепідключитись</string>
<string name="application_state_connecting">Підключення...</string>
<string name="application_state_disabled">Обліковий запис вимкнено</string>
<string name="application_state_empty">Ви не маєте жодного облікового запису</string>
<string name="application_state_no_contacts">Ви не маєте контактів</string>
<string name="application_state_no_online">Жодного в мережі</string>
<string name="application_state_offline">Облікові записи не підключені</string>
<string name="application_state_roster">Підключено.</string>
<string name="application_state_starting">Запуск додатку... </string>
<string name="application_state_waiting">Очікування підключення...</string>
<string name="chat_list">Перелік чатів</string>
<string name="chat_list_is_empty">Відсутні активні чати</string>
<string name="chat_viewer">Балачка</string>
<string name="close_chat">Закрити балачку</string>
<string name="CONNECTION_FAILED">Помилка підключення</string>
<string name="contact_add">Додати контакт</string>
<string name="contact_delete">Стерти</string>
<string name="contact_delete_confirm">Ви дійсно бажаєте вилучити контакт %1$s з облікового запису %2$s?</string>
<string name="contact_list">Перелік контактів</string>
<string name="discard_subscription">Відхилити контакт</string>
<string name="exit">Вийти</string>
<string name="group_active_chat">Активні чати</string>
<string name="group_none">Поза групами</string>
<string name="group_remove">Вилучити групу</string>
<string name="group_remove_confirm">Ви дійсно бажаєте вилучити групу %s? Користувачі із групи лишаться в переліку контактів.</string>
<string name="group_rename">Перейменувати групу</string>
<string name="NO_SUCH_ACCOUNT">Обліковий запис не знайдено</string>
<string name="NOT_CONNECTED">Підключення не встановлено</string>
<string name="request_subscription">Запросити підпис</string>
<string name="XMPP_EXCEPTION">Помилка з\'єднання</string>
<string name="application_state_closing">Збереження змін...\nДодаток скоро закриється.</string>
<string name="certificate_confirmation">%1$s\nВи довіряєте сертифікату із цифровим відбитком:\n%2$s?\nНе сповіщати надалі о подібних проблемах з даним сертифікатом?</string>
<string name="certificate_details">\n\nКому виданий:\nІм\'я (CN): %1$s\nОрганізація (O): %2$s\nПідрозділ (OU): %3$s\nСерійний номер: %4$s\n\nКим виданий:\nІм\'я (CN): %5$s\nОрганізація (O): %6$s\nПідрозділ (OU): %7$s\n\nСтрок дії:\nНабуває чинності: %8$s\nСпливає: %9$s.</string>
<string name="certificate_invalid_chane">Помилка під час перевірки ланцюга підписів</string>
<string name="certificate_invalid_target">Помилка цільової верифікацію</string>
<string name="certificate_self_signed">Само-підписаний сертифікат</string>
<string name="certificate_show_details">Докладніше ...</string>
<string name="close_chats">Закрити всі чати</string>
<string name="contact_integration_suggest">Бажаєте інтегрувати Xabber із системними контактами?\nЦе можна змінити в \"Налаштування\" → \"XMPP облікові записи\" → Ваш обліковий запис → \"Інтеграція контактів\".\nУвага: Системний список контактів може стати повільнішим на декілька хвилин.</string>
<string name="group_room">Конференції</string>
<string name="OTR_ERROR">Помилка OTR</string>
<string name="select_contact">Оберіть потрібний контакт</string>
<string name="show_offline_always">Завжди показувати</string>
<string name="show_offline_never">Завжди приховувати</string>
<string name="show_offline_normal">Використати загальні налаштування</string>
<string name="show_offline_settings">Показ контактів поза мережею</string>
<string name="start_at_boot_suggest">Бажаєте запускати Xabber під час запуску пристрою?\nЦе можна змінити в \"Налаштування\" → \"Параметри підключення\" → \"Запускати при завантажені Android\"</string>
<string name="contact_search_hint">Пошук контактів</string>
<string name="sender_is_you">Ви</string>
<string name="xmpp_accounts">Аккаунти XMPP</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="contact_viewer">Контактна інформація</string>
<string name="contact_viewer_client">Клієнт</string>
<string name="vcard_nick_name">Нік</string>
<string name="vcard_formatted_name">Повне ім\'я</string>
<string name="vcard_prefix_name">Звертання</string>
<string name="vcard_given_name">Ім\'я</string>
<string name="vcard_middle_name">По батькові</string>
<string name="vcard_family_name">Прізвище</string>
<string name="vcard_suffix_name">Назва суфіксу</string>
<string name="vcard_birth_date">День народження</string>
<string name="vcard_url">Веб-сайт</string>
<string name="vcard_organization">Організація</string>
<string name="vcard_title">Посада</string>
<string name="vcard_role">Роль</string>
<string name="vcard_other">Інша інформація</string>
<string name="vcard_categories">Категорії</string>
<string name="vcard_decsription">Опис</string>
<string name="vcard_note">Нотатки</string>
<string name="vcard_address">Адреса</string>
<string name="vcard_address_pobox">Абонентська скринька</string>
<string name="vcard_address_extadr">Розширена адреса</string>
<string name="vcard_address_street">Вулиця</string>
<string name="vcard_address_locality">Місто</string>
<string name="vcard_address_region">Район</string>
<string name="vcard_address_pcode">Поштовий індекс</string>
<string name="vcard_address_ctry">Держава</string>
<string name="vcard_telephone">Телефон</string>
<string name="vcard_email">E-mail</string>
<string name="vcard_type_home">Домашня</string>
<string name="vcard_type_work">Робоча</string>
<string name="vcard_type_postal">Поштовий</string>
<string name="vcard_type_parcel">Для посилок</string>
<string name="vcard_type_dom">Внутрішній</string>
<string name="vcard_type_intl">Міжнародний</string>
<string name="vcard_type_pref">Привілейовані</string>
<string name="vcard_type_voice">Голосовий</string>
<string name="vcard_type_fax">Факс</string>
<string name="vcard_type_pager">Пейджер</string>
<string name="vcard_type_cell">Мобільний</string>
<string name="vcard_type_video">Відео</string>
<string name="vcard_type_modem">Модем</string>
<string name="vcard_type_msg">Голосова пошта</string>
<string name="vcard_type_internet">Інтернет</string>
<string name="please_wait">Зачекайте...</string>
<string name="unknown">Невідомо</string>
<string name="edit_alias">Редагувати псевдонім</string>
<string name="edit_contact_groups">Редагувати групу</string>
<string name="remove_contact">Видалити контакт</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="otr_fingerprint_description">Для впевненості, що співрозмовник не видає себе за іншого, він може повідомити Вам цифровий відбиток, який порівнюється із вказаним тут. Не слід використовувати XMPP чат для такої перевірки.</string>
<string name="otr_is_verified">Довіряю цьому контакту</string>
<string name="otr_local_fingerprint">Ваш відбиток</string>
<string name="otr_remote_fingerprint">Відбиток співрозмовника</string>
<string name="otr_scan_fingerprint">Сканувати QR-код відбитка Вашого співрозмовника</string>
<string name="otr_show_fingerprint">Показати QR-код з Вашим відбитком</string>
<string name="otr_copy_fingerprint">Скопіювати Ваш відбиток до буферу обміну</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="EMPTY_NICK_NAME">Псевдонім не вказано</string>
<string name="EMPTY_ROOM_NAME">Конференція не вказана</string>
<string name="muc_join">Приєднатись до конференції</string>
<string name="muc_nick">Псевдонім</string>
<string name="muc_nick_hint">Ваш псевдонім в конференції</string>
<string name="muc_password">Пароль</string>
<string name="muc_password_hint">Не потребує пароль</string>
<string name="muc_room">Конференція</string>
<string name="muc_server">Сервер конференції</string>
<string name="NICK_ALREADY_USED">Псевдонім вже використовується</string>
<string name="ALREADY_IN_PROGRESS">Вже в процесі</string>
<string name="ALREADY_JOINED">Вже приєднано</string>
<string name="muc_add">Додати конференцію</string>
<string name="muc_delete">Вилучити конференцію</string>
<string name="muc_delete_confirm">Видалити конференцію %1$s з облікового запису %2$s?</string>
<string name="muc_edit">Параметри авторизації</string>
<string name="muc_invite_confirm">%2$s запрошує Вас до конференції %3$s. Приєднатись з облікового запису %1$s?</string>
<string name="muc_invite_confirm_reason">%2$s запрошує Вас до конференції %3$s: %4$s. Приєднатись з облікового запису %1$s?</string>
<string name="muc_leave">Покинути конференцію</string>
<string name="muc_save">Зберегти конференцію</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="account_quantity_1">обліковий запис</string>
<string name="account_quantity_2">облікових записів</string>
<string name="account_quantity_5">облікових записів</string>
<string name="account_quantity_offline_1">обліковий запис</string>
<string name="account_quantity_offline_2">облікових записів</string>
<string name="account_quantity_offline_5">облікових записів</string>
<string name="AUTHENTICATION_FAILED">Помилка авторизації</string>
<string name="chat_contact_quantity_1">користувач</string>
<string name="chat_contact_quantity_2">користувачів</string>
<string name="chat_contact_quantity_5">користувачів</string>
<string name="chat_message_quantity_1">повідомлення</string>
<string name="chat_message_quantity_2">повідомлень</string>
<string name="chat_message_quantity_5">повідомлень</string>
<string name="chat_status">%1$d %2$s від %3$d %4$s</string>
<string name="chat_messages_from_contact">%1$d %2$s з %3$s</string>
<string name="chat_contact_and_message">%1$s: %2$s</string>
<string name="connection_state_connected_1">%1$d з %2$d %3$s в мережі</string>
<string name="connection_state_connected_2">%1$d з %2$d %3$s в мережі</string>
<string name="connection_state_connected_5">-</string>
<string name="connection_state_connecting_1">%1$d із %2$d %3$s підключається</string>
<string name="connection_state_connecting_2">%1$d із %2$d %3$s підключається</string>
<string name="connection_state_connecting_5">-</string>
<string name="connection_state_waiting_1">%1$d із %2$d %3$s очікує на підключення</string>
<string name="connection_state_waiting_2">%1$d із %2$d %3$s очікує на підключення</string>
<string name="connection_state_waiting_5">-</string>
<string name="connection_state_offline">%1$d %2$s поза мережею</string>
<string name="archive_available_request_message">Ви бажаєте зберігати історію повідомлень на сервері?\nЦе дозволить Xabber завантажувати історію на будь-якому пристрої, використовуючи Ваш обліковий запис.\nЦя можливість призведе до збільшення трафіку і може суттєво зменшити швидкість підключення.\nУВАГА: Вся Ваша локальна історія буде вилучена.</string>
<string name="archive_available_request_title">Дозволити архівування повідомлень?</string>
<string name="INVALID_CERTIFICATE">Недійсний сертифікат</string>
<string name="muc_invite_message">Бажаєте підключитись до конференції?</string>
<string name="otr_verification_in_progress">Натисніть, щоб перервати</string>
<string name="PASSWORD_REQUIRED">Необхідно ввести пароль</string>
<string name="pay_attention">Звернути увагу</string>
<string name="subscription_request_message">Запит авторизації</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="phrase_add">Додати фразу</string>
<string name="phrase_delete">Вилучити фразу</string>
<string name="phrase_delete_confirm">Ви дійсно хочете видалити фразу: %s?</string>
<string name="phrase_empty">&lt; Будь-який текст &gt;</string>
<string name="phrase_group">Частина назви групи контактів</string>
<string name="phrase_regexp">Регулярний вираз</string>
<string name="phrase_sound">Звук\nВиберіть звукове сповіщення</string>
<string name="phrase_text">Текст для пошуку</string>
<string name="phrase_user">Частина Jabber ID контакту</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="cache_clear">Очистити кеш\nОчистити всі локальні данні. Це може звільнити трохи пам\'яті.</string>
<string name="cache_clear_warning">Ви дійсно бажаєте видалити історію чату та інші локальні данні? \nОбліковий запис та список залишаться недоторканними. Програму буде закрито.</string>
<string name="chats_send_by_enter">Надіслати по Enter\nПовідомлення можe бути відправленe, натиснувши клавішу Enter</string>
<string name="connection_go_away">Авто статус\nАвтоматично встановити статус \"Відійшов\" при блокування екрану</string>
<string name="contacts_order">Сортувати контакти\nОберіть порядок, в якому будуть відображатись контакти</string>
<string name="contacts_order_alphabet">За абеткою</string>
<string name="contacts_order_status">По статусу</string>
<string name="contacts_show_accounts">Групувати по обліковим записам\nДозволяє групувати співрозмовників по обліковим записам</string>
<string name="contacts_show_active_chats">Активні чати на горі\nВідображати активні чати у верхній частині списку контактів</string>
<string name="contacts_show_avatars">Показувати аватарки\nПоказувати аватарки користувачів в переліку контактів</string>
<string name="contacts_show_empty_groups">Показати порожні групи\nПоказати групи в яких немає онлайн-контактів</string>
<string name="contacts_show_groups">Показувати групи\nПоказувати групи в переліку контактів</string>
<string name="contacts_show_offline">Показувати контакти які не в мережі</string>
<string name="contacts_show_panel">Показати панель облікових записів\nПоказати облікові записи з аватарами в нижньому правому куті списку контактів</string>
<string name="contacts_stay_active_chats">Дублювати активні чати\nАктивні чати, з\'являються з верху списку контактів і груп</string>
<string name="debug_log">Журнал зневадження\nВиводити повідомлення для для зневадження в окремий журнал\n(перезапустіть додаток, для набуття чинності параметру)</string>
<string name="events_lightning">Світлова індикація\nБлимати LED індикатором при сповіщеннях</string>
<string name="events_persistent">Піктограма на Taskbar\nВідображати постійне повідомлення. Цей параметр запобігає Android вигружати програму з пам\'яті</string>
<string name="events_sound">Звукові сповіщення\nОберіть звукове сповіщення</string>
<string name="events_vibro">Вібрація\nВикористовувати вібрацію для сповіщення</string>
<string name="interface_theme">Стилі\nНалаштування стилів</string>
<string name="interface_theme_dark">Темний</string>
<string name="interface_theme_light">Світлий</string>
<string name="interface_theme_normal">Типовий</string>
<string name="interface_smiles">Смайли\nНалаштування смайлів</string>
<string name="interface_smiles_android">Стандартні смайли</string>
<string name="interface_smiles_none">Відключити графічні смайли</string>
<string name="preference_connection">Налаштування підключення\nВстановлення параметрів підключення</string>
<string name="preference_contacts">Перелік контактів\nПараметри показу переліку контактів</string>
<string name="preference_debug">Параметри зневадження\nОберіть цей пункт, якщо у Вас є можливість допомогти розробникам зробити Xabber краще</string>
<string name="preference_editor">Установки</string>
<string name="preference_events">Сповіщення\nПараметри варіантів сповіщення</string>
<string name="preference_interface">Теми\nПараметри зовнішнього вигляду</string>
<string name="about_viewer">Інформація</string>
<string name="chats_show_background">Показати фон\nВідключення може збільшити продуктивність</string>
<string name="chats_font_size">Розмір шрифта\nРозмір тексту повідомлення</string>
<string name="chats_font_size_large">Великий</string>
<string name="chats_font_size_normal">Звичайний</string>
<string name="chats_font_size_small">Малий</string>
<string name="chats_font_size_xlarge">Збільшений</string>
<string name="chats_hide_keyboard">Приховати клавіатуру\nПриховувати віртуальну клавіатуру після відправлення повідомлення</string>
<string name="chats_hide_keyboard_landscape">В ландшафтному режимі</string>
<string name="chats_receipt">Сповіщення про доставку повідомлення\nВідправляти і отримувати сповіщення про доставку повідомлення</string>
<string name="chats_show_avatars">Аватарки в повідомленнях\nПоказувати аватарки в кожному повідомленні</string>
<string name="chats_show_status_change">Показувати зміну статусів\nПоказувати повідомлення про зміну статусів співрозмовника</string>
<string name="chats_show_status_change_muc">В конференціях</string>
<string name="chats_state_notification">Показати статус набору\nПоказати коли інший користувач набирає</string>
<string name="connection_adjust_priority">Настроїти пріоритет\nВстановити відповідно до вибраного стану. Пріоритет облікового запису буде перевизначено.</string>
<string name="connection_go_away_immediately">Одразу після блокування екрану</string>
<string name="connection_go_xa">\"Розширений геть\" при простої\nВстановити \"Розширений геть» на екран блокування</string>
<string name="connection_priority">Параметри пріоритету</string>
<string name="connection_start_at_boot">Запускати разом з Android\nЗапускати додаток коли завантажується Android. Це не працює, коли Xabber встановлений на SD-карту.</string>
<string name="connection_wake_lock">Заборонити режим сну\nНе давати пристрою спати. Це збільшить використання акумулятора.</string>
<string name="connection_wifi_lock">Тримати WiFi увімкненим\nТримати WiFi активним в режимі очікування. Це збільшить використання акумулятора</string>
<string name="contacts_reset_offline">Скинути поза мережеві параметри\nОчистити індивідуальні параметри для груп і облікових записів</string>
<string name="contacts_reset_offline_warning">Ви дійсно хочете очистити індивідуальні налаштування для груп та облікових записів?</string>
<string name="events_first_only">Попередити про перше повідомлення\nПовідомити тільки про перше повідомлення в чаті</string>
<string name="events_ignore_system_vibro">Ігнорувати системні налаштування\nВключіть, якщо не працює системна вібрація</string>
<string name="events_message">Налаштування повідомлень\nНалаштувати сповіщення про вхідні повідомлення</string>
<string name="events_message_chat">Тільки в чаті</string>
<string name="events_message_chat_and_muc">В чатах і конференціях</string>
<string name="events_message_none">Не сповіщати</string>
<string name="events_show_text">Повідомлення в сповіщеннях\nПоказувати текст повідомлення в області сповіщень</string>
<string name="events_visible_chat">Сповіщення в поточному чаті\nСповіщати о вхідних повідомлення в поточному чаті</string>
<string name="negative_priotiry_summary">%s (Ви не зможете отримувати повідомлення із будь-яких балачок)</string>
<string name="preference_accounts">XMPP аккаунти\nУправління аккаунтами</string>
<string name="preference_security">Безпека\nНалаштування безпеки</string>
<string name="security_check_certificate">Перевірте сертифікат сервера\nСповістити про проблеми з сертифікатом при шифрованому підключенні</string>
<string name="security_clear_certificate">Видалити сертифікати\nОчистити список ігнорованих сертифікатів</string>
<string name="security_otr_history">Зберігати історію\nЗберігати історію чату для OTR сесій</string>
<string name="security_otr_mode">Режим OTR шифрування</string>
<string name="chats_attention">Увага\nРеагувати на вхідні запити уваги</string>
<string name="chats_attention_sound">Звуки уваги\nОберіть рингтон</string>
<string name="connection_load_vcard">Завантажувати vCard\nЗавантажувати і оновлювати персональну інформацію контактів. Відключення параметру допоможе зекономити трафік.</string>
<string name="connection_use_carbons">Режим Всіх\nМоже бути нестабільним! Ділиться сеансами для того ж облікового запису на цьому клієнті. Вимкніть для зменшення трафіку.</string>
<string name="events_phrases">Ключові слова\nСтворити спеціальні сповіщення для отриманих повідомлень, які містять спеціальні фрази</string>
<string name="security_clear_certificate_warning">Ви дійсно хочете видалити всі ігноровані сертифікати?</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="otr_answer">Відповідь на секретне запитання:</string>
<string name="otr_question">Секретне запитання:</string>
<string name="otr_question_description">Для впевненості, що ніхто не видає себе за іншого, користуйтесь секретним запитанням.</string>
<string name="otr_secret">Секретний ключ:</string>
<string name="otr_secret_description">Для впевненості, що ніхто не видає себе за іншого, користуйтесь секретним ключем.</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="available">Доступний</string>
<string name="away">Відійшов</string>
<string name="chat">Готовий до спілкування!</string>
<string name="dnd">Не турбувати</string>
<string name="edit_status">Редагувати статус</string>
<string name="empty_status">&lt;Статус не встановлено&gt;</string>
<string name="invisible">Прихований</string>
<string name="remove_status">Очистити статус</string>
<string name="status_editor">Встановити статус</string>
<string name="status_text_hint">Введіть повідомлення статусу</string>
<string name="unavailable">Не в мережі</string>
<string name="unsubscribed">Не авторизований</string>
<string name="xa">Відійшов на довго</string>
<string name="new_status">Новий статус</string>
<string name="saved_statuses">Збережені статуси</string>
<string name="clear_status_history">Очистити історію статусу</string>
<string name="status_message">Повідомлення про стан</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="is_translated">true</bool>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
<string name="in10m">Через 10 хвилин</string>
<string name="in15m">Через 15 хвилин</string>
<string name="in1h">Через годину</string>
<string name="in1m">Через хвилину</string>
<string name="in2m">Через 2 хвилини</string>
<string name="in30m">Через 30 хвилин</string>
<string name="in5m">Через 5 хвилин</string>
<string name="always">Завжди</string>
<string name="disabled">Вимкнено</string>
<string name="manual">Вручну</string>
<string name="never">Ніколи</string>
<string name="required">Обов\'язково</string>
<string name="auto">Автоматично</string>
<string name="save">Зберегти</string>
</resources>
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">对方的指纹:</string> <string name="otr_remote_fingerprint">对方的指纹:</string>
<string name="otr_scan_fingerprint">扫描对方指纹的QR码</string> <string name="otr_scan_fingerprint">扫描对方指纹的QR码</string>
<string name="otr_show_fingerprint">显示你指纹的QR码</string> <string name="otr_show_fingerprint">显示你指纹的QR码</string>
<string name="zxing_install_fail">未安装Google Play,请手动安装Barcode Scanner。</string>
<string name="zxing_install_message">这应用程序需要Barcode Scanner,你想要安装吗?</string>
<string name="otr_copy_fingerprint">复制指纹到剪贴板</string> <string name="otr_copy_fingerprint">复制指纹到剪贴板</string>
</resources> </resources>
...@@ -7,7 +7,5 @@ ...@@ -7,7 +7,5 @@
<string name="otr_remote_fingerprint">對方的指紋:</string> <string name="otr_remote_fingerprint">對方的指紋:</string>
<string name="otr_scan_fingerprint">掃描對方指紋的QR碼</string> <string name="otr_scan_fingerprint">掃描對方指紋的QR碼</string>
<string name="otr_show_fingerprint">顯示你指紋的QR碼</string> <string name="otr_show_fingerprint">顯示你指紋的QR碼</string>
<string name="zxing_install_fail">未安裝Google Play,請手動安裝Barcode Scanner。</string>
<string name="zxing_install_message">這應用程式需要Barcode Scanner,你想要安裝嗎?</string>
<string name="otr_copy_fingerprint">複製指紋到剪貼簿</string> <string name="otr_copy_fingerprint">複製指紋到剪貼簿</string>
</resources> </resources>
...@@ -6,7 +6,5 @@ ...@@ -6,7 +6,5 @@
<string name="otr_remote_fingerprint">Your opponent\'s fingerprint:</string> <string name="otr_remote_fingerprint">Your opponent\'s fingerprint:</string>
<string name="otr_scan_fingerprint">Scan QR code with opponent\'s fingerprint</string> <string name="otr_scan_fingerprint">Scan QR code with opponent\'s fingerprint</string>
<string name="otr_show_fingerprint">Show QR code with your fingerprint</string> <string name="otr_show_fingerprint">Show QR code with your fingerprint</string>
<string name="zxing_install_fail">There is no Google Play installed. Please install Barcode Scanner manually.</string>
<string name="zxing_install_message">This application requires Barcode Scanner. Would you like to install it?</string>
<string name="otr_copy_fingerprint">Copy your fingerprint to clipboard</string> <string name="otr_copy_fingerprint">Copy your fingerprint to clipboard</string>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment