diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java b/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java index 843154d24..3764cbcd8 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java @@ -10,6 +10,7 @@ import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JPanel; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; @@ -55,7 +56,6 @@ public class SimpleToast extends UIDialog { pane.add(textLabel, BorderLayout.CENTER); pane.setBorder(BorderFactory.createEmptyBorder(8, 15, 8, 15)); - return pane; } @@ -101,19 +101,30 @@ public class SimpleToast extends UIDialog { tipToolTimer.scheduleAtFixedRate(new Runnable() { @Override public void run() { - Point point = outerPanel.getLocation(); - if (point.y >= 0 && !tipToolTimer.isShutdown()) { - tipToolTimer.shutdown(); - } - int showDistance = 5 + point.y < 0 ? 5 : -point.y; - outerPanel.setLocation(point.x, point.y + showDistance); - Dimension dimension = SimpleToast.this.getSize(); - SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height + showDistance)); + SwingUtilities.invokeLater(()->{ + displayStep(outerPanel, tipToolTimer); + }); } }, 0, 50, TimeUnit.MILLISECONDS); } + void displayStep(JPanel outerPanel, ScheduledExecutorService timer) { + Point point = outerPanel.getLocation(); + if (point.y >= 0 && !timer.isShutdown()) { + timer.shutdown(); + } + int showDistance = 5 + point.y < 0 ? 5 : -point.y; + outerPanel.setLocation(point.x, point.y + showDistance); + Dimension dimension = SimpleToast.this.getSize(); + SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height + showDistance)); + } + + + + + + private void disappear(JPanel outerPanel, long delay, TimeUnit timeUnit) { timer = createToastScheduleExecutorService(); timer.schedule(new DisappearMotion(outerPanel), delay, timeUnit); @@ -135,21 +146,26 @@ public class SimpleToast extends UIDialog { tipToolTimer.scheduleAtFixedRate(new Runnable() { @Override public void run() { - Point point = panel.getLocation(); - if (point.y <= -hideHeight && !tipToolTimer.isShutdown()) { - tipToolTimer.shutdown(); - SimpleToast.this.setVisible(false); - SimpleToast.this.dispose(); - SimpleToast.this.show = false; - } - panel.setLocation(point.x, point.y - 5); - Dimension dimension = SimpleToast.this.getSize(); - SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height - 5)); + SwingUtilities.invokeLater(()->{ + disappearStep(tipToolTimer); + }); } }, 0, 50, TimeUnit.MILLISECONDS); } - } + void disappearStep(ScheduledExecutorService timer) { + Point point = panel.getLocation(); + if (point.y <= -hideHeight && !timer.isShutdown()) { + timer.shutdown(); + SimpleToast.this.setVisible(false); + SimpleToast.this.dispose(); + SimpleToast.this.show = false; + } + panel.setLocation(point.x, point.y - 5); + Dimension dimension = SimpleToast.this.getSize(); + SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height - 5)); + } + } private void disappear(JPanel outerPanel) { disappear(outerPanel, DEFAULT_DISAPPEAR_DELAY, DEFAULT_TIME_UNIT); @@ -175,7 +191,4 @@ public class SimpleToast extends UIDialog { super.dispose(); } - public boolean isShow() { - return show; - } } \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/action/StartUseAction.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/action/StartUseAction.java index e2758bb40..2315fbb0e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/action/StartUseAction.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/action/StartUseAction.java @@ -1,12 +1,20 @@ package com.fr.design.mainframe.alphafine.action; +import com.fr.common.util.Strings; +import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.download.FineMarketConstants; import com.fr.design.mainframe.alphafine.download.FineMarketDownloadManager; import com.fr.design.mainframe.alphafine.model.TemplateResourceDetail; +import com.fr.file.FileFILE; +import com.fr.log.FineLoggerFactory; import javax.swing.SwingWorker; +import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; /** @@ -26,13 +34,53 @@ public class StartUseAction implements ActionListener { @Override public void actionPerformed(ActionEvent e) { - new SwingWorker() { + new SwingWorker() { @Override - protected Void doInBackground() throws Exception { - FineMarketDownloadManager.getInstance().downloadAndOpenTemplateResource(resourceDetail.getRoot(), AlphaFineHelper.getAlphaFineDialog()); - return null; + protected String doInBackground() throws Exception { + return FineMarketDownloadManager.getInstance().installResource(resourceDetail.getRoot(), AlphaFineHelper.getAlphaFineDialog()); + } + + @Override + protected void done() { + try { + open(get()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + super.done(); } }.execute(); } -} \ No newline at end of file + + void open(String fileName) throws IOException { + if (Strings.isEmpty(fileName)) { + return; + } + File fileNeedOpen = new File(fileName); + if (fileName.endsWith(FineMarketConstants.ZIP)) { + File[] files = fileNeedOpen.listFiles(); + fileNeedOpen = getFirstCptOrFrm(files); + } else if (fileName.endsWith(FineMarketConstants.RAR)) { + // rar直接打开系统文件夹 + File parentDir = new File(fileName).getParentFile(); + Desktop.getDesktop().open(parentDir); + return; + } + openInDesigner(fileNeedOpen); + } + + void openInDesigner(File file) { + DesignerContext.getDesignerFrame().openTemplate(new FileFILE(file)); + } + + + private File getFirstCptOrFrm(File[] files) { + for (File f : files) { + if (f.getName().endsWith(FineMarketConstants.CPT) || f.getName().endsWith(FineMarketConstants.FRM)) { + return f; + } + } + return null; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketConstants.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketConstants.java new file mode 100644 index 000000000..f17095b09 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketConstants.java @@ -0,0 +1,10 @@ +package com.fr.design.mainframe.alphafine.download; + +public class FineMarketConstants { + + public static final String REPORTLETS = "/reportlets"; + public static final String ZIP = ".zip"; + public static final String RAR = ".rar"; + public static final String CPT = ".cpt"; + public static final String FRM = ".frm"; +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketDownloadManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketDownloadManager.java index a51c4b4cc..08a785311 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketDownloadManager.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/download/FineMarketDownloadManager.java @@ -7,17 +7,15 @@ import com.fr.design.extra.Process; import com.fr.design.i18n.Toolkit; import com.fr.design.login.DesignerLoginHelper; import com.fr.design.login.DesignerLoginSource; -import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.alphafine.AlphaFineHelper; import com.fr.design.mainframe.alphafine.model.TemplateResource; import com.fr.design.mainframe.alphafine.search.helper.FineMarketClientHelper; import com.fr.design.mainframe.toast.SimpleToast; -import com.fr.file.FileFILE; import com.fr.log.FineLoggerFactory; import com.fr.third.jodd.io.ZipUtil; import com.fr.workspace.WorkContext; -import java.awt.Desktop; +import javax.swing.SwingUtilities; import java.awt.Window; import java.io.File; import java.io.IOException; @@ -43,78 +41,50 @@ public class FineMarketDownloadManager { private static final String OPENING_PLEASE_WAIT = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Opening"); private static final String DOWNLOAD_FAILED = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Resource_Download_Failed_Check_Network"); - private static final String REPORTLETS = "/reportlets"; - private static final String ZIP = ".zip"; - private static final String RAR = ".rar"; - private static final String CPT = ".cpt"; - private static final String FRM = ".frm"; + /** - * 下载资源并解压, + * 下载资源并解压 * */ - public void downloadAndOpenTemplateResource(TemplateResource resource, Window parentWindow){ + public String installResource(TemplateResource resource, Window parentWindow){ // 验证登录 String token = DesignerEnvManager.getEnvManager().getDesignerLoginRefreshToken(); if (Strings.isEmpty(token)) { DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL, new HashMap<>(), AlphaFineHelper.getAlphaFineDialog()); - return; + return null; } - downloadAndOpen(resource, parentWindow); + return install(resource, parentWindow); } - private void downloadAndOpen(TemplateResource resource, Window parentWindow) { + private String install(TemplateResource resource, Window parentWindow) { // 获取报表录作为下载位置 - String workDir = WorkContext.getCurrent().getPath() + REPORTLETS; + String workDir = WorkContext.getCurrent().getPath() + FineMarketConstants.REPORTLETS; File destDir = new File(workDir); DownloadProcess downloadProcess = new DownloadProcess(parentWindow); String fileName = null; try { fileName = FineMarketClientHelper.getInstance().download(resource, destDir, downloadProcess); - open(fileName, downloadProcess); + unzip(fileName, downloadProcess); + return fileName; } catch (Exception e) { downloadProcess.process(FineMarketDownloadManager.PROCESS_FAILED); FineLoggerFactory.getLogger().error(e, e.getMessage()); } + return null; } - void open(String fileName, DownloadProcess process) throws IOException { + void unzip(String fileName, DownloadProcess process) throws IOException { process.process(OPENING_FILE); - if (Strings.isEmpty(fileName)) { - return; - } - File fileNeedOpen = new File(fileName); - if (fileName.endsWith(ZIP)) { - File[] files = unzip(fileName); - fileNeedOpen = getFirstCptOrFrm(files); - } else if (fileName.endsWith(RAR)) { - // rar直接打开系统文件夹 - File parentDir = new File(fileName).getParentFile(); - Desktop.getDesktop().open(parentDir); - return; - } - openInDesigner(fileNeedOpen); - } - private File getFirstCptOrFrm(File[] files) { - for (File f : files) { - if (f.getName().endsWith(CPT) || f.getName().endsWith(FRM)) { - return f; - } + if (fileName.endsWith(FineMarketConstants.ZIP)) { + File file = new File(fileName); + File parentDir = file.getParentFile(); + ZipUtil.unzip(file, parentDir); } - return null; } - File[] unzip(String fileName) throws IOException { - File file = new File(fileName); - File parentDir = file.getParentFile(); - ZipUtil.unzip(file, parentDir); - return parentDir.listFiles(); - } - void openInDesigner(File file) { - DesignerContext.getDesignerFrame().openTemplate(new FileFILE(file)); - } /** @@ -138,13 +108,15 @@ public class FineMarketDownloadManager { @Override public void process(Double aDouble) { - if (aDouble == PROCESS_FAILED) { - downloadFailed(); - } else if (aDouble == PROCESS_SUCCESS) { - downloadSuccess(); - } else if (aDouble == OPENING_FILE) { - openingFile(); - } + SwingUtilities.invokeLater(()->{ + if (aDouble == PROCESS_FAILED) { + downloadFailed(); + } else if (aDouble == PROCESS_SUCCESS) { + downloadSuccess(); + } else if (aDouble == OPENING_FILE) { + openingFile(); + } + }); } public void downloadFailed() { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResource.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResource.java index 7bb4c879f..56cc25a0c 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResource.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/TemplateResource.java @@ -2,6 +2,7 @@ package com.fr.design.mainframe.alphafine.model; import com.fr.common.util.Strings; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.alphafine.download.FineMarketConstants; import com.fr.design.mainframe.alphafine.search.manager.impl.TemplateResourceSearchManager; import com.fr.general.IOUtils; import com.fr.json.JSONArray; @@ -120,7 +121,7 @@ public class TemplateResource { public TemplateResource setFileName(String fileName) { if (Strings.isEmpty(fileName)) { - this.fileName = getName() + ".zip"; + this.fileName = getName() + FineMarketConstants.ZIP; } else { this.fileName = fileName; } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java index 194f3dfc8..52e7e3a80 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/helper/FineMarketClientHelper.java @@ -4,11 +4,13 @@ import com.fr.design.DesignerEnvManager; import com.fr.design.extra.PluginConstants; import com.fr.design.mainframe.alphafine.download.FineMarketDownloadManager; import com.fr.design.mainframe.alphafine.model.TemplateResource; +import com.fr.file.FileCommonUtils; import com.fr.general.CloudCenter; import com.fr.general.http.HttpToolbox; import com.fr.json.JSONArray; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; +import com.fr.market.key.FineMarketPublicKeyHolder; import com.fr.security.SecurityToolbox; import com.fr.stable.StableUtils; import com.fr.third.org.apache.http.HttpEntity; @@ -42,10 +44,7 @@ public class FineMarketClientHelper { return INSTANCE; } - private static final String CERTIFICATE_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw\n" + - "1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8D\n" + - "tT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYX\n" + - "nMdTIrkz8tYkG3QoFQIDAQAB"; + private static final String CERTIFICATE_PUBLIC_KEY = FineMarketPublicKeyHolder.getInstance().getDefaultKey(); public static final String FINE_MARKET_TEMPLATE_INFO = CloudCenter.getInstance().acquireUrlByKind("market.template.info"); public static final String FINE_MARKET_TEMPLATE_URL = CloudCenter.getInstance().acquireUrlByKind("market.template.url"); public static final String FILE_DOWNLOAD = "file/download/"; @@ -101,7 +100,7 @@ public class FineMarketClientHelper { InputStream content = null; FileOutputStream writer = null; try { - writer = new FileOutputStream(destFile.getAbsolutePath()); + writer = new FileOutputStream(FileCommonUtils.getAbsolutePath(destFile)); HttpEntity entity = fileRes.getEntity(); long totalSize = entity.getContentLength(); @@ -130,7 +129,7 @@ public class FineMarketClientHelper { FineLoggerFactory.getLogger().info("download resource{} success", resourceId); process.process(FineMarketDownloadManager.PROCESS_SUCCESS); - return destFile.getAbsolutePath(); + return FileCommonUtils.getAbsolutePath(destFile); } else { FineLoggerFactory.getLogger().info("download resource{} failed", resourceId); process.process(FineMarketDownloadManager.PROCESS_FAILED); @@ -156,7 +155,7 @@ public class FineMarketClientHelper { private File createDestFile(File destDir, TemplateResource resource) { String fileName = resource.getName(); try { - File finalDir = new File(destDir.getAbsolutePath() + "/" + fileName); + File finalDir = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(destDir), fileName)); if (!finalDir.exists()) { finalDir.mkdir(); } @@ -181,7 +180,7 @@ public class FineMarketClientHelper { - File destFile = new File(finalDir.getAbsolutePath() + "/" + fileName); + File destFile = new File(StableUtils.pathJoin(FileCommonUtils.getAbsolutePath(finalDir), fileName)); destFile.createNewFile(); return destFile; } catch (Exception e) { diff --git a/designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java b/designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java new file mode 100644 index 000000000..d17a61727 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/market/key/FineMarketDefaultKeyProperties.java @@ -0,0 +1,67 @@ +package com.fr.market.key; + +import com.fr.general.IOUtils; +import com.fr.io.utils.ResourceIOUtils; +import com.fr.log.FineLoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * @author Link + * @version 11.0 + * Created by Yvan on 2022/8/25 + */ +public class FineMarketDefaultKeyProperties { + + private Properties properties = new Properties(); + + private Map publicKeyMap = new HashMap<>(); + + private String propertyPath; + + private FineMarketDefaultKeyProperties(String propertyPath) { + this.propertyPath = propertyPath; + load(); + } + + public static FineMarketDefaultKeyProperties create(String propertyPath) { + return new FineMarketDefaultKeyProperties(propertyPath); + } + + private void load() { + try (InputStream inputStream = IOUtils.readResource(getPropertyPath())) { + byte[] data = ResourceIOUtils.inputStream2Bytes(inputStream); + properties.load(new ByteArrayInputStream(data)); + trims(properties); + publicKeyMap.put(FineMarketPublicKeyConstants.DEFAULT_KEY_KEY, properties.getProperty(FineMarketPublicKeyConstants.DEFAULT_KEY_KEY)); + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + private String getPropertyPath() { + return this.propertyPath; + } + + public String getPublicKey() { + return publicKeyMap.get(FineMarketPublicKeyConstants.DEFAULT_KEY_KEY); + } + + /** + * 去除properties中value末尾的空格 + * @param properties + */ + public static void trims(Properties properties) { + for (String key : properties.stringPropertyNames()) { + String value = properties.getProperty(key); + if (value != null) { + properties.put(key, value.trim()); + } + } + } +} diff --git a/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java b/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java new file mode 100644 index 000000000..cab87bec3 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyConstants.java @@ -0,0 +1,29 @@ +package com.fr.market.key; + + +/** + * @author Link + * @version 11.0 + * Created by Link on 2022/8/25 + */ +public class FineMarketPublicKeyConstants { + + public static final String DEFAULT_KEY_KEY = "defaultKey"; + + public static final String DEFAULT_KEY_DIRECTORY = "/com/fr/market/key"; + + /** + * 公钥第一段 + */ + public static final String FIRST_PROPERTY = "76c1/default"; + + /** + * 公钥第二段 + */ + public static final String SECOND_PROPERTY = "943f/default"; + + /** + * 公钥第三段 + */ + public static final String THIRD_PROPERTY = "d8a3/default"; +} diff --git a/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java b/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java new file mode 100644 index 000000000..b37493559 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/market/key/FineMarketPublicKeyHolder.java @@ -0,0 +1,48 @@ +package com.fr.market.key; + +import com.fr.stable.StableUtils; + +/** + * 帆软市场公钥Holder + * @author Link + * @version 10.0 + * Created by Link on 2022/8/25 + */ +public class FineMarketPublicKeyHolder { + + private static FineMarketPublicKeyHolder instance = null; + + private String defaultKey; + + public static FineMarketPublicKeyHolder getInstance() { + + if (instance == null) { + synchronized (FineMarketPublicKeyHolder.class) { + if (instance == null) { + instance = new FineMarketPublicKeyHolder(); + } + } + } + return instance; + } + + private FineMarketPublicKeyHolder() { + init(); + } + + private void init() { + // 读取三个default.properties文件,组成公钥 + String firstPart = FineMarketDefaultKeyProperties.create(StableUtils.pathJoin(FineMarketPublicKeyConstants.DEFAULT_KEY_DIRECTORY, FineMarketPublicKeyConstants.FIRST_PROPERTY)).getPublicKey(); + String secondPart = FineMarketDefaultKeyProperties.create(StableUtils.pathJoin(FineMarketPublicKeyConstants.DEFAULT_KEY_DIRECTORY, FineMarketPublicKeyConstants.SECOND_PROPERTY)).getPublicKey(); + String thirdPart = FineMarketDefaultKeyProperties.create(StableUtils.pathJoin(FineMarketPublicKeyConstants.DEFAULT_KEY_DIRECTORY, FineMarketPublicKeyConstants.THIRD_PROPERTY)).getPublicKey(); + this.defaultKey = firstPart + secondPart + thirdPart; + } + + /** + * 获取默认公钥 + * @return 公钥 + */ + public String getDefaultKey() { + return this.defaultKey; + } +} diff --git a/designer-realize/src/main/resources/com/fr/market/key/76c1/default b/designer-realize/src/main/resources/com/fr/market/key/76c1/default new file mode 100644 index 000000000..58044d9c0 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/market/key/76c1/default @@ -0,0 +1 @@ +defaultKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw \ No newline at end of file diff --git a/designer-realize/src/main/resources/com/fr/market/key/943f/default b/designer-realize/src/main/resources/com/fr/market/key/943f/default new file mode 100644 index 000000000..80946f51c --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/market/key/943f/default @@ -0,0 +1 @@ +defaultKey=1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8D \ No newline at end of file diff --git a/designer-realize/src/main/resources/com/fr/market/key/d8a3/default b/designer-realize/src/main/resources/com/fr/market/key/d8a3/default new file mode 100644 index 000000000..af41473f3 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/market/key/d8a3/default @@ -0,0 +1 @@ +defaultKey=tT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYXnMdTIrkz8tYkG3QoFQIDAQAB \ No newline at end of file