package com.intellij.lang.javascript.flex.run;
import com.intellij.flex.model.bc.LinkageType;
import com.intellij.lang.javascript.flex.FlexBundle;
import com.intellij.lang.javascript.flex.projectStructure.model.BuildConfigurationEntry;
import com.intellij.lang.javascript.flex.projectStructure.model.DependencyEntry;
import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfiguration;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.PathUtil;
import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.intellij.openapi.util.SystemInfo.isMac;
import static com.intellij.openapi.util.SystemInfo.isWinVistaOrNewer;
import static com.intellij.openapi.util.SystemInfo.isWindows;
public class FlashPlayerTrustUtil {
private final static String WINDOWS_VISTA_AND_7_TRUST_DIR_REL_PATH =
"\\AppData\\Roaming\\Macromedia\\Flash Player\\#Security\\FlashPlayerTrust";
private final static String WINDOWS_XP_TRUST_DIR_REL_PATH = "\\Application Data\\Macromedia\\Flash Player\\#Security\\FlashPlayerTrust";
private final static String MAC_TRUST_DIR_REL_PATH = "/Library/Preferences/Macromedia/Flash Player/#Security/FlashPlayerTrust";
private final static String UNIX_TRUST_DIR_REL_PATH = "/.macromedia/Flash_Player/#Security/FlashPlayerTrust";
private final static String INTELLIJ_IDEA_CFG = "intellij_idea.cfg";
private FlashPlayerTrustUtil() {
}
public static void updateTrustedStatus(final Module module, final FlexBuildConfiguration bc,
final boolean isDebug, final boolean isTrusted) {
final Collection<String> paths = new ArrayList<>();
try {
paths.add(new File(PathUtil.getParentPath(bc.getActualOutputFilePath())).getCanonicalPath());
}
catch (IOException e) {/**/}
for (DependencyEntry entry : bc.getDependencies().getEntries()) {
if (entry instanceof BuildConfigurationEntry && entry.getDependencyType().getLinkageType() == LinkageType.LoadInRuntime) {
final FlexBuildConfiguration dependencyBC = ((BuildConfigurationEntry)entry).findBuildConfiguration();
if (dependencyBC != null) {
try {
paths.add(new File(PathUtil.getParentPath(dependencyBC.getActualOutputFilePath())).getCanonicalPath());
}
catch (IOException e) {/**/}
}
}
}
updateTrustedStatus(module.getProject(), isTrusted, isDebug, paths.toArray(new String[paths.size()]));
}
public static void updateTrustedStatus(final Project project,
final boolean trustedStatus,
final boolean isDebug,
final String... paths) {
final File ideaCfgFile = getIdeaUserTrustConfigFile(project, isDebug, trustedStatus);
if (ideaCfgFile == null) {
return;
}
try {
fixIdeaCfgFileContentIfNeeded(ideaCfgFile, paths, trustedStatus);
}
catch (IOException e) {
// always show
final ToolWindowManager manager = ToolWindowManager.getInstance(project);
manager.notifyByBalloon(isDebug ? ToolWindowId.DEBUG : ToolWindowId.RUN, MessageType.WARNING,
FlexBundle.message("failed.to.update.idea.trust.cfg.file", INTELLIJ_IDEA_CFG, e.getMessage()));
}
}
private static void fixIdeaCfgFileContentIfNeeded(final @NotNull File ideaCfgFile,
final @NotNull String[] trustedPaths,
final boolean runTrusted) throws IOException {
final String[] trustedPathsFiltered = removeNestedPaths(trustedPaths);
final StringBuilder buf = new StringBuilder();
final List<String> lines = StringUtil.split(FileUtil.loadFile(ideaCfgFile, "UTF-8"), "\n");
for (String line : lines) {
boolean appendLine = true;
for (String path : trustedPathsFiltered) {
appendLine &= !line.equals(path) && !line.startsWith(path + File.separatorChar) && !path.startsWith(line + File.separatorChar);
}
if (appendLine) {
buf.append(line).append('\n');
}
}
if (runTrusted) {
for (String path : trustedPathsFiltered) {
buf.append(path).append('\n');
}
}
FileUtil.writeToFile(ideaCfgFile, buf.toString().getBytes("UTF-8"));
}
private static String[] removeNestedPaths(final String[] paths) {
if (paths.length < 2) return paths;
final Collection<String> result = new ArrayList<>(paths.length);
for (int i = 0; i < paths.length; i++) {
final String path = paths[i];
boolean include = true;
for (int j = 0; j < paths.length; j++) {
final String otherPath = paths[j];
if (i < j && path.equals(otherPath)) {
include = false;
break;
}
if (i != j && path.startsWith(otherPath + File.separatorChar)) {
include = false;
break;
}
}
if (include) {
result.add(path);
}
}
return result.toArray(new String[result.size()]);
}
@Nullable
private static File getIdeaUserTrustConfigFile(final Project project, final boolean isDebug, final boolean runTrusted) {
final File flashPlayerTrustDir = getFlashPlayerTrustDir(project, isDebug, runTrusted);
if (flashPlayerTrustDir == null) {
return null;
}
final File ideaTrustedCfgFile = new File(flashPlayerTrustDir, INTELLIJ_IDEA_CFG);
if (ideaTrustedCfgFile.isFile() && ideaTrustedCfgFile.length() > 102400) {
// this file may become such big only because of a bug like IDEA-86188
FileUtil.delete(ideaTrustedCfgFile);
}
if (!ideaTrustedCfgFile.exists() && runTrusted) {
try {
final boolean ok = ideaTrustedCfgFile.createNewFile();
if (!ok) {
showWarningBalloonIfNeeded(project, isDebug, runTrusted, FlexBundle
.message("error.creating.idea.trust.cfg.file", INTELLIJ_IDEA_CFG, flashPlayerTrustDir.getPath()));
}
}
catch (IOException e) {
showWarningBalloonIfNeeded(project, isDebug, runTrusted,
FlexBundle.message("error.creating.idea.trust.cfg.file", INTELLIJ_IDEA_CFG, e.getMessage()));
return null;
}
}
return ideaTrustedCfgFile;
}
@Nullable
private static File getFlashPlayerTrustDir(final Project project, final boolean isDebug, final boolean runTrusted) {
final String flashPlayerTrustDirRelPath =
isWindows ? (isWinVistaOrNewer ? WINDOWS_VISTA_AND_7_TRUST_DIR_REL_PATH : WINDOWS_XP_TRUST_DIR_REL_PATH) :
isMac ? MAC_TRUST_DIR_REL_PATH :
UNIX_TRUST_DIR_REL_PATH;
final File flashPlayerTrustDir = new File(SystemProperties.getUserHome() + flashPlayerTrustDirRelPath);
if (!flashPlayerTrustDir.isDirectory()) {
if (flashPlayerTrustDir.isFile()) {
showWarningBalloonIfNeeded(project, isDebug, runTrusted, FlexBundle.message("flash.player.trust.folder.does.not.exist"));
return null;
}
if (!flashPlayerTrustDir.mkdirs()) {
showWarningBalloonIfNeeded(project, isDebug, runTrusted,
FlexBundle.message("error.creating.flash.player.trust.folder", flashPlayerTrustDir));
return null;
}
}
return flashPlayerTrustDir;
}
private static void showWarningBalloonIfNeeded(final Project project,
final boolean isDebug,
final boolean runTrusted,
final String message) {
if (runTrusted) {
final ToolWindowManager manager = ToolWindowManager.getInstance(project);
manager.notifyByBalloon(isDebug ? ToolWindowId.DEBUG : ToolWindowId.RUN, MessageType.WARNING, message);
}
}
}