SonarQube fixes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1777669 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9ee04feeb9
commit
1042dacd93
@ -19,6 +19,12 @@
|
|||||||
|
|
||||||
package org.apache.poi.ss.examples.formula;
|
package org.apache.poi.ss.examples.formula;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
||||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||||
@ -29,19 +35,11 @@ import org.apache.poi.ss.usermodel.Sheet;
|
|||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstrates how to use functions provided by third-party add-ins, e.g. Bloomberg Excel Add-in.
|
* Demonstrates how to use functions provided by third-party add-ins, e.g. Bloomberg Excel Add-in.
|
||||||
*
|
*
|
||||||
* There can be situations when you are not interested in formula evaluation,
|
* There can be situations when you are not interested in formula evaluation,
|
||||||
* you just need to set the formula and the workbook will be evaluation by the client.
|
* you just need to set the formula and the workbook will be evaluation by the client.
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public class SettingExternalFunction {
|
public class SettingExternalFunction {
|
||||||
|
|
||||||
@ -91,6 +89,7 @@ public class SettingExternalFunction {
|
|||||||
wb.write(out);
|
wb.write(out);
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
|
wb.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ public class CryptoAPIDecryptor extends Decryptor implements Cloneable {
|
|||||||
assert(entry.streamName.length() == nameSize);
|
assert(entry.streamName.length() == nameSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
fsOut = new POIFSFileSystem();
|
fsOut = new POIFSFileSystem(); // NOSONAR
|
||||||
for (StreamDescriptorEntry entry : entries) {
|
for (StreamDescriptorEntry entry : entries) {
|
||||||
sbis.seek(entry.streamOffset);
|
sbis.seek(entry.streamOffset);
|
||||||
sbis.setBlock(entry.block);
|
sbis.setBlock(entry.block);
|
||||||
|
@ -126,7 +126,7 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable {
|
|||||||
*/
|
*/
|
||||||
public OutputStream getSummaryEntries(DirectoryNode dir)
|
public OutputStream getSummaryEntries(DirectoryNode dir)
|
||||||
throws IOException, GeneralSecurityException {
|
throws IOException, GeneralSecurityException {
|
||||||
CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this);
|
CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this); // NOSONAR
|
||||||
byte buf[] = new byte[8];
|
byte buf[] = new byte[8];
|
||||||
|
|
||||||
bos.write(buf, 0, 8); // skip header
|
bos.write(buf, 0, 8); // skip header
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.eventfilesystem;
|
package org.apache.poi.poifs.eventfilesystem;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.io.InputStream;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||||
import org.apache.poi.poifs.filesystem.OPOIFSDocument;
|
import org.apache.poi.poifs.filesystem.OPOIFSDocument;
|
||||||
@ -34,6 +35,7 @@ import org.apache.poi.poifs.storage.BlockList;
|
|||||||
import org.apache.poi.poifs.storage.HeaderBlock;
|
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||||
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event-driven reader for POIFS file systems. Users of this class
|
* An event-driven reader for POIFS file systems. Users of this class
|
||||||
@ -42,8 +44,6 @@ import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
|||||||
* documents. Once all the listeners have been registered, the read()
|
* documents. Once all the listeners have been registered, the read()
|
||||||
* method is called, which results in the listeners being notified as
|
* method is called, which results in the listeners being notified as
|
||||||
* their documents are read.
|
* their documents are read.
|
||||||
*
|
|
||||||
* @author Marc Johnson (mjohnson at apache dot org)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class POIFSReader
|
public class POIFSReader
|
||||||
@ -190,20 +190,19 @@ public class POIFSReader
|
|||||||
{
|
{
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
{
|
{
|
||||||
System.err
|
System.err.println("at least one argument required: input filename(s)");
|
||||||
.println("at least one argument required: input filename(s)");
|
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register for all
|
// register for all
|
||||||
for (int j = 0; j < args.length; j++)
|
for (String arg : args)
|
||||||
{
|
{
|
||||||
POIFSReader reader = new POIFSReader();
|
POIFSReader reader = new POIFSReader();
|
||||||
POIFSReaderListener listener = new SampleListener();
|
POIFSReaderListener listener = new SampleListener();
|
||||||
|
|
||||||
reader.registerListener(listener);
|
reader.registerListener(listener);
|
||||||
System.out.println("reading " + args[ j ]);
|
System.out.println("reading " + arg);
|
||||||
FileInputStream istream = new FileInputStream(args[ j ]);
|
FileInputStream istream = new FileInputStream(arg);
|
||||||
|
|
||||||
reader.read(istream);
|
reader.read(istream);
|
||||||
istream.close();
|
istream.close();
|
||||||
@ -300,31 +299,25 @@ public class POIFSReader
|
|||||||
* @param event
|
* @param event
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event)
|
@Override
|
||||||
{
|
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
||||||
@SuppressWarnings("resource")
|
|
||||||
DocumentInputStream istream = event.getStream();
|
DocumentInputStream istream = event.getStream();
|
||||||
POIFSDocumentPath path = event.getPath();
|
POIFSDocumentPath path = event.getPath();
|
||||||
String name = event.getName();
|
String name = event.getName();
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
byte[] data = IOUtils.toByteArray(istream);
|
||||||
byte[] data = new byte[ istream.available() ];
|
|
||||||
|
|
||||||
istream.read(data);
|
|
||||||
int pathLength = path.length();
|
int pathLength = path.length();
|
||||||
|
|
||||||
for (int k = 0; k < pathLength; k++)
|
for (int k = 0; k < pathLength; k++) {
|
||||||
{
|
|
||||||
System.out.print("/" + path.getComponent(k));
|
System.out.print("/" + path.getComponent(k));
|
||||||
}
|
}
|
||||||
System.out.println("/" + name + ": " + data.length
|
System.out.println("/" + name + ": " + data.length + " bytes read");
|
||||||
+ " bytes read");
|
} catch (IOException ignored) {
|
||||||
}
|
} finally {
|
||||||
catch (IOException ignored)
|
IOUtils.closeQuietly(istream);
|
||||||
{
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end private class SampleListener
|
|
||||||
} // end public class POIFSReader
|
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import java.awt.geom.AffineTransform;
|
|||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -53,6 +52,7 @@ import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
|||||||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
||||||
import org.apache.poi.sl.usermodel.Shadow;
|
import org.apache.poi.sl.usermodel.Shadow;
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape;
|
import org.apache.poi.sl.usermodel.SimpleShape;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
|
|
||||||
@ -110,15 +110,21 @@ public class DrawSimpleShape extends DrawShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void drawDecoration(Graphics2D graphics, Paint line, BasicStroke stroke) {
|
protected void drawDecoration(Graphics2D graphics, Paint line, BasicStroke stroke) {
|
||||||
if(line == null) return;
|
if(line == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
graphics.setPaint(line);
|
graphics.setPaint(line);
|
||||||
|
|
||||||
List<Outline> lst = new ArrayList<Outline>();
|
List<Outline> lst = new ArrayList<Outline>();
|
||||||
LineDecoration deco = getShape().getLineDecoration();
|
LineDecoration deco = getShape().getLineDecoration();
|
||||||
Outline head = getHeadDecoration(graphics, deco, stroke);
|
Outline head = getHeadDecoration(graphics, deco, stroke);
|
||||||
if (head != null) lst.add(head);
|
if (head != null) {
|
||||||
|
lst.add(head);
|
||||||
|
}
|
||||||
Outline tail = getTailDecoration(graphics, deco, stroke);
|
Outline tail = getTailDecoration(graphics, deco, stroke);
|
||||||
if (tail != null) lst.add(tail);
|
if (tail != null) {
|
||||||
|
lst.add(tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for(Outline o : lst){
|
for(Outline o : lst){
|
||||||
@ -126,8 +132,12 @@ public class DrawSimpleShape extends DrawShape {
|
|||||||
Path p = o.getPath();
|
Path p = o.getPath();
|
||||||
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
|
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
|
||||||
|
|
||||||
if(p.isFilled()) graphics.fill(s);
|
if(p.isFilled()) {
|
||||||
if(p.isStroked()) graphics.draw(s);
|
graphics.fill(s);
|
||||||
|
}
|
||||||
|
if(p.isStroked()) {
|
||||||
|
graphics.draw(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +231,7 @@ public class DrawSimpleShape extends DrawShape {
|
|||||||
double lineWidth = Math.max(2.5, stroke.getLineWidth());
|
double lineWidth = Math.max(2.5, stroke.getLineWidth());
|
||||||
|
|
||||||
Rectangle2D anchor = getAnchor(graphics, getShape());
|
Rectangle2D anchor = getAnchor(graphics, getShape());
|
||||||
double x1 = anchor.getX(),
|
double x1 = anchor.getX(), y1 = anchor.getY();
|
||||||
y1 = anchor.getY();
|
|
||||||
|
|
||||||
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
|
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
|
||||||
|
|
||||||
@ -289,7 +298,9 @@ public class DrawSimpleShape extends DrawShape {
|
|||||||
, Paint line
|
, Paint line
|
||||||
) {
|
) {
|
||||||
Shadow<?,?> shadow = getShape().getShadow();
|
Shadow<?,?> shadow = getShape().getShadow();
|
||||||
if (shadow == null || (fill == null && line == null)) return;
|
if (shadow == null || (fill == null && line == null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SolidPaint shadowPaint = shadow.getFillStyle();
|
SolidPaint shadowPaint = shadow.getFillStyle();
|
||||||
Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor());
|
Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor());
|
||||||
@ -373,11 +384,7 @@ public class DrawSimpleShape extends DrawShape {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Unable to load preset geometries.", e);
|
throw new RuntimeException("Unable to load preset geometries.", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
IOUtils.closeQuietly(presetIS);
|
||||||
presetIS.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Unable to load preset geometries.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,16 +16,20 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.sl.usermodel;
|
package org.apache.poi.sl.usermodel;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PushbackInputStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import org.apache.poi.EncryptedDocumentException;
|
import org.apache.poi.EncryptedDocumentException;
|
||||||
import org.apache.poi.OldFileFormatException;
|
import org.apache.poi.OldFileFormatException;
|
||||||
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
|
|
||||||
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
|
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
|
||||||
import org.apache.poi.poifs.crypt.Decryptor;
|
import org.apache.poi.poifs.crypt.Decryptor;
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||||
|
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
|
||||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||||
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
|
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
@ -66,7 +70,7 @@ public class SlideShowFactory {
|
|||||||
|
|
||||||
return createXSLFSlideShow(stream);
|
return createXSLFSlideShow(stream);
|
||||||
} finally {
|
} finally {
|
||||||
if (stream != null) stream.close();
|
IOUtils.closeQuietly(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,14 +215,10 @@ public class SlideShowFactory {
|
|||||||
fs = new NPOIFSFileSystem(file, readOnly);
|
fs = new NPOIFSFileSystem(file, readOnly);
|
||||||
return create(fs, password);
|
return create(fs, password);
|
||||||
} catch(OfficeXmlFileException e) {
|
} catch(OfficeXmlFileException e) {
|
||||||
if(fs != null) {
|
IOUtils.closeQuietly(fs);
|
||||||
fs.close();
|
|
||||||
}
|
|
||||||
return createXSLFSlideShow(file, readOnly);
|
return createXSLFSlideShow(file, readOnly);
|
||||||
} catch(RuntimeException e) {
|
} catch(RuntimeException e) {
|
||||||
if(fs != null) {
|
IOUtils.closeQuietly(fs);
|
||||||
fs.close();
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,7 @@ import java.util.Map;
|
|||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimisation - compacts many blank cell references used by a single formula.
|
* Optimization - compacts many blank cell references used by a single formula.
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
final class FormulaUsedBlankCellSet {
|
final class FormulaUsedBlankCellSet {
|
||||||
public static final class BookSheetKey {
|
public static final class BookSheetKey {
|
||||||
@ -39,11 +37,15 @@ final class FormulaUsedBlankCellSet {
|
|||||||
_bookIndex = bookIndex;
|
_bookIndex = bookIndex;
|
||||||
_sheetIndex = sheetIndex;
|
_sheetIndex = sheetIndex;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return _bookIndex * 17 + _sheetIndex;
|
return _bookIndex * 17 + _sheetIndex;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
assert obj instanceof BookSheetKey : "these private cache key instances are only compared to themselves";
|
if (!(obj instanceof BookSheetKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
BookSheetKey other = (BookSheetKey) obj;
|
BookSheetKey other = (BookSheetKey) obj;
|
||||||
return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
|
return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
|
||||||
}
|
}
|
||||||
@ -148,6 +150,7 @@ final class FormulaUsedBlankCellSet {
|
|||||||
_lastRowIndex = rowIndex;
|
_lastRowIndex = rowIndex;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer(64);
|
StringBuffer sb = new StringBuffer(64);
|
||||||
CellReference crA = new CellReference(_firstRowIndex, _firstColumnIndex, false, false);
|
CellReference crA = new CellReference(_firstRowIndex, _firstColumnIndex, false, false);
|
||||||
|
@ -20,10 +20,6 @@ package org.apache.poi.ss.formula;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
|
||||||
final class PlainCellCache {
|
final class PlainCellCache {
|
||||||
|
|
||||||
public static final class Loc {
|
public static final class Loc {
|
||||||
@ -48,12 +44,16 @@ final class PlainCellCache {
|
|||||||
_rowIndex = rowIndex;
|
_rowIndex = rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return (int)(_bookSheetColumn ^ (_bookSheetColumn >>> 32)) + 17 * _rowIndex;
|
return (int)(_bookSheetColumn ^ (_bookSheetColumn >>> 32)) + 17 * _rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
assert obj instanceof Loc : "these package-private cache key instances are only compared to themselves";
|
if (!(obj instanceof Loc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Loc other = (Loc) obj;
|
Loc other = (Loc) obj;
|
||||||
return _bookSheetColumn == other._bookSheetColumn && _rowIndex == other._rowIndex;
|
return _bookSheetColumn == other._bookSheetColumn && _rowIndex == other._rowIndex;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,6 @@ import org.apache.poi.util.LocaleUtil;
|
|||||||
* Internal calculation methods for Excel 'Analysis ToolPak' function YEARFRAC()<br/>
|
* Internal calculation methods for Excel 'Analysis ToolPak' function YEARFRAC()<br/>
|
||||||
*
|
*
|
||||||
* Algorithm inspired by www.dwheeler.com/yearfrac
|
* Algorithm inspired by www.dwheeler.com/yearfrac
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
final class YearFracCalculator {
|
final class YearFracCalculator {
|
||||||
private static final int MS_PER_HOUR = 60 * 60 * 1000;
|
private static final int MS_PER_HOUR = 60 * 60 * 1000;
|
||||||
@ -212,17 +210,12 @@ final class YearFracCalculator {
|
|||||||
* @return <code>true</code> if dates both within a leap year, or span a period including Feb 29
|
* @return <code>true</code> if dates both within a leap year, or span a period including Feb 29
|
||||||
*/
|
*/
|
||||||
private static boolean shouldCountFeb29(SimpleDate start, SimpleDate end) {
|
private static boolean shouldCountFeb29(SimpleDate start, SimpleDate end) {
|
||||||
boolean startIsLeapYear = isLeapYear(start.year);
|
if (isLeapYear(start.year)) {
|
||||||
if (startIsLeapYear && start.year == end.year) {
|
if (start.year == end.year) {
|
||||||
// note - dates may not actually span Feb-29, but it gets counted anyway in this case
|
// note - dates may not actually span Feb-29, but it gets counted anyway in this case
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean endIsLeapYear = isLeapYear(end.year);
|
|
||||||
if (!startIsLeapYear && !endIsLeapYear) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (startIsLeapYear) {
|
|
||||||
switch (start.month) {
|
switch (start.month) {
|
||||||
case SimpleDate.JANUARY:
|
case SimpleDate.JANUARY:
|
||||||
case SimpleDate.FEBRUARY:
|
case SimpleDate.FEBRUARY:
|
||||||
@ -230,7 +223,8 @@ final class YearFracCalculator {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (endIsLeapYear) {
|
|
||||||
|
if (isLeapYear(end.year)) {
|
||||||
switch (end.month) {
|
switch (end.month) {
|
||||||
case SimpleDate.JANUARY:
|
case SimpleDate.JANUARY:
|
||||||
return false;
|
return false;
|
||||||
|
@ -37,8 +37,6 @@ import org.apache.poi.util.Internal;
|
|||||||
* will be used in all subsequent evaluations.<br/>
|
* will be used in all subsequent evaluations.<br/>
|
||||||
*
|
*
|
||||||
* For POI internal use only
|
* For POI internal use only
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
final class ForkedEvaluationSheet implements EvaluationSheet {
|
final class ForkedEvaluationSheet implements EvaluationSheet {
|
||||||
@ -128,7 +126,9 @@ final class ForkedEvaluationSheet implements EvaluationSheet {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
assert obj instanceof RowColKey : "these private cache key instances are only compared to themselves";
|
if (!(obj instanceof RowColKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
RowColKey other = (RowColKey) obj;
|
RowColKey other = (RowColKey) obj;
|
||||||
return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;
|
return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;
|
||||||
}
|
}
|
||||||
@ -136,6 +136,7 @@ final class ForkedEvaluationSheet implements EvaluationSheet {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return _rowIndex ^ _columnIndex;
|
return _rowIndex ^ _columnIndex;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public int compareTo(RowColKey o) {
|
public int compareTo(RowColKey o) {
|
||||||
int cmp = _rowIndex - o._rowIndex;
|
int cmp = _rowIndex - o._rowIndex;
|
||||||
if (cmp != 0) {
|
if (cmp != 0) {
|
||||||
|
@ -136,6 +136,7 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
throw new RuntimeException("Cannot call boolean evaluate on non-equality operator '"
|
throw new RuntimeException("Cannot call boolean evaluate on non-equality operator '"
|
||||||
+ _representation + "'");
|
+ _representation + "'");
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer(64);
|
StringBuffer sb = new StringBuffer(64);
|
||||||
sb.append(getClass().getName());
|
sb.append(getClass().getName());
|
||||||
@ -187,6 +188,7 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
return String.valueOf(_value);
|
return String.valueOf(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean matches(ValueEval x) {
|
public boolean matches(ValueEval x) {
|
||||||
double testValue;
|
double testValue;
|
||||||
if(x instanceof StringEval) {
|
if(x instanceof StringEval) {
|
||||||
@ -246,22 +248,21 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
return value ? 1 : 0;
|
return value ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean matches(ValueEval x) {
|
public boolean matches(ValueEval x) {
|
||||||
int testValue;
|
int testValue;
|
||||||
if(x instanceof StringEval) {
|
if(x instanceof StringEval) {
|
||||||
if (true) { // change to false to observe more intuitive behaviour
|
|
||||||
// Note - Unlike with numbers, it seems that COUNTIF never matches
|
// Note - Unlike with numbers, it seems that COUNTIF never matches
|
||||||
// boolean values when the target(x) is a string
|
// boolean values when the target(x) is a string
|
||||||
return false;
|
return false;
|
||||||
}
|
// uncomment to observe more intuitive behaviour
|
||||||
@SuppressWarnings("unused")
|
// StringEval se = (StringEval)x;
|
||||||
StringEval se = (StringEval)x;
|
// Boolean val = parseBoolean(se.getStringValue());
|
||||||
Boolean val = parseBoolean(se.getStringValue());
|
// if(val == null) {
|
||||||
if(val == null) {
|
// // x is text that is not a boolean
|
||||||
// x is text that is not a boolean
|
// return false;
|
||||||
return false;
|
// }
|
||||||
}
|
// testValue = boolToInt(val.booleanValue());
|
||||||
testValue = boolToInt(val.booleanValue());
|
|
||||||
} else if((x instanceof BoolEval)) {
|
} else if((x instanceof BoolEval)) {
|
||||||
BoolEval be = (BoolEval) x;
|
BoolEval be = (BoolEval) x;
|
||||||
testValue = boolToInt(be.getBooleanValue());
|
testValue = boolToInt(be.getBooleanValue());
|
||||||
@ -300,6 +301,7 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
return FormulaError.forInt(_value).getString();
|
return FormulaError.forInt(_value).getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean matches(ValueEval x) {
|
public boolean matches(ValueEval x) {
|
||||||
if(x instanceof ErrorEval) {
|
if(x instanceof ErrorEval) {
|
||||||
int testValue = ((ErrorEval)x).getErrorCode();
|
int testValue = ((ErrorEval)x).getErrorCode();
|
||||||
@ -339,6 +341,7 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
return _pattern.pattern();
|
return _pattern.pattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean matches(ValueEval x) {
|
public boolean matches(ValueEval x) {
|
||||||
if (x instanceof BlankEval) {
|
if (x instanceof BlankEval) {
|
||||||
switch(getCode()) {
|
switch(getCode()) {
|
||||||
@ -433,6 +436,7 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
|
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
|
||||||
|
|
||||||
I_MatchPredicate mp = createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex);
|
I_MatchPredicate mp = createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex);
|
||||||
@ -525,13 +529,27 @@ public final class Countif extends Fixed2ArgFunction {
|
|||||||
if (value.length() < 4 || value.charAt(0) != '#') {
|
if (value.length() < 4 || value.charAt(0) != '#') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (value.equals("#NULL!")) return ErrorEval.NULL_INTERSECTION;
|
if (value.equals("#NULL!")) {
|
||||||
if (value.equals("#DIV/0!")) return ErrorEval.DIV_ZERO;
|
return ErrorEval.NULL_INTERSECTION;
|
||||||
if (value.equals("#VALUE!")) return ErrorEval.VALUE_INVALID;
|
}
|
||||||
if (value.equals("#REF!")) return ErrorEval.REF_INVALID;
|
if (value.equals("#DIV/0!")) {
|
||||||
if (value.equals("#NAME?")) return ErrorEval.NAME_INVALID;
|
return ErrorEval.DIV_ZERO;
|
||||||
if (value.equals("#NUM!")) return ErrorEval.NUM_ERROR;
|
}
|
||||||
if (value.equals("#N/A")) return ErrorEval.NA;
|
if (value.equals("#VALUE!")) {
|
||||||
|
return ErrorEval.VALUE_INVALID;
|
||||||
|
}
|
||||||
|
if (value.equals("#REF!")) {
|
||||||
|
return ErrorEval.REF_INVALID;
|
||||||
|
}
|
||||||
|
if (value.equals("#NAME?")) {
|
||||||
|
return ErrorEval.NAME_INVALID;
|
||||||
|
}
|
||||||
|
if (value.equals("#NUM!")) {
|
||||||
|
return ErrorEval.NUM_ERROR;
|
||||||
|
}
|
||||||
|
if (value.equals("#N/A")) {
|
||||||
|
return ErrorEval.NA;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,6 @@ import org.apache.poi.util.LittleEndianOutput;
|
|||||||
* parsed formula. However, in BIFF files <tt>Ptg</tt>s are written/read in
|
* parsed formula. However, in BIFF files <tt>Ptg</tt>s are written/read in
|
||||||
* <em>Reverse-Polish Notation</em> order. The RPN ordering also simplifies formula
|
* <em>Reverse-Polish Notation</em> order. The RPN ordering also simplifies formula
|
||||||
* evaluation logic, so POI mostly accesses <tt>Ptg</tt>s in the same way.
|
* evaluation logic, so POI mostly accesses <tt>Ptg</tt>s in the same way.
|
||||||
*
|
|
||||||
* @author andy
|
|
||||||
* @author avik
|
|
||||||
* @author Jason Height (jheight at chariot dot net dot au)
|
|
||||||
*/
|
*/
|
||||||
public abstract class Ptg {
|
public abstract class Ptg {
|
||||||
public static final Ptg[] EMPTY_PTG_ARRAY = { };
|
public static final Ptg[] EMPTY_PTG_ARRAY = { };
|
||||||
@ -201,7 +197,7 @@ public abstract class Ptg {
|
|||||||
* @return number of bytes written
|
* @return number of bytes written
|
||||||
*/
|
*/
|
||||||
public static int serializePtgs(Ptg[] ptgs, byte[] array, int offset) {
|
public static int serializePtgs(Ptg[] ptgs, byte[] array, int offset) {
|
||||||
LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(array, offset);
|
LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(array, offset); // NOSONAR
|
||||||
|
|
||||||
List<Ptg> arrayPtgs = null;
|
List<Ptg> arrayPtgs = null;
|
||||||
|
|
||||||
|
@ -323,6 +323,7 @@ public class CellReference {
|
|||||||
/**
|
/**
|
||||||
* @deprecated 3.15 beta 2. Use {@link #isColumnWithinRange}.
|
* @deprecated 3.15 beta 2. Use {@link #isColumnWithinRange}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static boolean isColumnWithnRange(String colStr, SpreadsheetVersion ssVersion) {
|
public static boolean isColumnWithnRange(String colStr, SpreadsheetVersion ssVersion) {
|
||||||
return isColumnWithinRange(colStr, ssVersion);
|
return isColumnWithinRange(colStr, ssVersion);
|
||||||
}
|
}
|
||||||
@ -352,6 +353,7 @@ public class CellReference {
|
|||||||
/**
|
/**
|
||||||
* @deprecated 3.15 beta 2. Use {@link #isRowWithinRange}
|
* @deprecated 3.15 beta 2. Use {@link #isRowWithinRange}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static boolean isRowWithnRange(String rowStr, SpreadsheetVersion ssVersion) {
|
public static boolean isRowWithnRange(String rowStr, SpreadsheetVersion ssVersion) {
|
||||||
return isRowWithinRange(rowStr, ssVersion);
|
return isRowWithinRange(rowStr, ssVersion);
|
||||||
}
|
}
|
||||||
@ -388,7 +390,9 @@ public class CellReference {
|
|||||||
final String sheetName = parseSheetName(reference, plingPos);
|
final String sheetName = parseSheetName(reference, plingPos);
|
||||||
String cell = reference.substring(plingPos+1).toUpperCase(Locale.ROOT);
|
String cell = reference.substring(plingPos+1).toUpperCase(Locale.ROOT);
|
||||||
Matcher matcher = CELL_REF_PATTERN.matcher(cell);
|
Matcher matcher = CELL_REF_PATTERN.matcher(cell);
|
||||||
if (!matcher.matches()) throw new IllegalArgumentException("Invalid CellReference: " + reference);
|
if (!matcher.matches()) {
|
||||||
|
throw new IllegalArgumentException("Invalid CellReference: " + reference);
|
||||||
|
}
|
||||||
String col = matcher.group(1);
|
String col = matcher.group(1);
|
||||||
String row = matcher.group(2);
|
String row = matcher.group(2);
|
||||||
|
|
||||||
@ -430,14 +434,12 @@ public class CellReference {
|
|||||||
sb.append(ch);
|
sb.append(ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(i < lastQuotePos) {
|
if(i+1 < lastQuotePos && reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
|
||||||
if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
|
|
||||||
// two consecutive quotes is the escape sequence for a single one
|
// two consecutive quotes is the escape sequence for a single one
|
||||||
i++; // skip this and keep parsing the special name
|
i++; // skip this and keep parsing the special name
|
||||||
sb.append(ch);
|
sb.append(ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Bad sheet name quote escaping: (" + reference + ")");
|
throw new IllegalArgumentException("Bad sheet name quote escaping: (" + reference + ")");
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
@ -48,6 +48,7 @@ import java.util.UUID;
|
|||||||
import javax.xml.crypto.MarshalException;
|
import javax.xml.crypto.MarshalException;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.xml.security.c14n.Canonicalizer;
|
import org.apache.xml.security.c14n.Canonicalizer;
|
||||||
@ -62,28 +63,7 @@ import org.bouncycastle.asn1.x509.Extension;
|
|||||||
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
|
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
|
||||||
import org.bouncycastle.cert.ocsp.OCSPResp;
|
import org.bouncycastle.cert.ocsp.OCSPResp;
|
||||||
import org.bouncycastle.cert.ocsp.RespID;
|
import org.bouncycastle.cert.ocsp.RespID;
|
||||||
import org.etsi.uri.x01903.v13.CRLIdentifierType;
|
import org.etsi.uri.x01903.v13.*;
|
||||||
import org.etsi.uri.x01903.v13.CRLRefType;
|
|
||||||
import org.etsi.uri.x01903.v13.CRLRefsType;
|
|
||||||
import org.etsi.uri.x01903.v13.CRLValuesType;
|
|
||||||
import org.etsi.uri.x01903.v13.CertIDListType;
|
|
||||||
import org.etsi.uri.x01903.v13.CertIDType;
|
|
||||||
import org.etsi.uri.x01903.v13.CertificateValuesType;
|
|
||||||
import org.etsi.uri.x01903.v13.CompleteCertificateRefsType;
|
|
||||||
import org.etsi.uri.x01903.v13.CompleteRevocationRefsType;
|
|
||||||
import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
|
|
||||||
import org.etsi.uri.x01903.v13.EncapsulatedPKIDataType;
|
|
||||||
import org.etsi.uri.x01903.v13.OCSPIdentifierType;
|
|
||||||
import org.etsi.uri.x01903.v13.OCSPRefType;
|
|
||||||
import org.etsi.uri.x01903.v13.OCSPRefsType;
|
|
||||||
import org.etsi.uri.x01903.v13.OCSPValuesType;
|
|
||||||
import org.etsi.uri.x01903.v13.QualifyingPropertiesDocument;
|
|
||||||
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
|
||||||
import org.etsi.uri.x01903.v13.ResponderIDType;
|
|
||||||
import org.etsi.uri.x01903.v13.RevocationValuesType;
|
|
||||||
import org.etsi.uri.x01903.v13.UnsignedPropertiesType;
|
|
||||||
import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType;
|
|
||||||
import org.etsi.uri.x01903.v13.XAdESTimeStampType;
|
|
||||||
import org.etsi.uri.x01903.v14.ValidationDataType;
|
import org.etsi.uri.x01903.v14.ValidationDataType;
|
||||||
import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType;
|
import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@ -341,8 +321,8 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
|
|||||||
ASN1Integer integer = (ASN1Integer)asn1IS2.readObject();
|
ASN1Integer integer = (ASN1Integer)asn1IS2.readObject();
|
||||||
return integer.getPositiveValue();
|
return integer.getPositiveValue();
|
||||||
} finally {
|
} finally {
|
||||||
asn1IS2.close();
|
IOUtils.closeQuietly(asn1IS2);
|
||||||
asn1IS1.close();
|
IOUtils.closeQuietly(asn1IS1);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("I/O error: " + e.getMessage(), e);
|
throw new RuntimeException("I/O error: " + e.getMessage(), e);
|
||||||
|
@ -16,11 +16,14 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.ss.usermodel;
|
package org.apache.poi.ss.usermodel;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PushbackInputStream;
|
||||||
|
|
||||||
import org.apache.poi.EmptyFileException;
|
import org.apache.poi.EmptyFileException;
|
||||||
import org.apache.poi.EncryptedDocumentException;
|
import org.apache.poi.EncryptedDocumentException;
|
||||||
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
|
|
||||||
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
|
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
@ -28,6 +31,7 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
|
|||||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||||
import org.apache.poi.poifs.crypt.Decryptor;
|
import org.apache.poi.poifs.crypt.Decryptor;
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||||
|
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
|
||||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||||
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
|
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
@ -252,8 +256,7 @@ public class WorkbookFactory {
|
|||||||
return create(fs, password);
|
return create(fs, password);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// ensure that the file-handle is closed again
|
// ensure that the file-handle is closed again
|
||||||
fs.close();
|
IOUtils.closeQuietly(fs);
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} catch(OfficeXmlFileException e) {
|
} catch(OfficeXmlFileException e) {
|
||||||
@ -261,20 +264,18 @@ public class WorkbookFactory {
|
|||||||
OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
|
OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
|
||||||
try {
|
try {
|
||||||
return new XSSFWorkbook(pkg);
|
return new XSSFWorkbook(pkg);
|
||||||
} catch (IOException ioe) {
|
} catch (Exception ioe) {
|
||||||
// ensure that file handles are closed (use revert() to not re-write the file)
|
// ensure that file handles are closed - use revert() to not re-write the file
|
||||||
pkg.revert();
|
pkg.revert();
|
||||||
//pkg.close();
|
// do not pkg.close();
|
||||||
|
|
||||||
// rethrow exception
|
if (ioe instanceof IOException) {
|
||||||
throw ioe;
|
throw (IOException)ioe;
|
||||||
} catch (RuntimeException ioe) {
|
} else if (ioe instanceof RuntimeException) {
|
||||||
// ensure that file handles are closed (use revert() to not re-write the file)
|
throw (RuntimeException)ioe;
|
||||||
pkg.revert();
|
} else {
|
||||||
//pkg.close();
|
throw new IOException(ioe);
|
||||||
|
}
|
||||||
// rethrow exception
|
|
||||||
throw ioe;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user