/** * Starts the configuration service * * @param bundleContext the <tt>BundleContext</tt> as provided by the OSGi framework. * @throws Exception if anything goes wrong */ public void start(BundleContext bundleContext) throws Exception { FileAccessService fas = ServiceUtils.getService(bundleContext, FileAccessService.class); if (fas != null) { File usePropFileConfig; try { usePropFileConfig = fas.getPrivatePersistentFile(".usepropfileconfig", FileCategory.PROFILE); } catch (Exception ise) { // There is somewhat of a chicken-and-egg dependency between // FileConfigurationServiceImpl and ConfigurationServiceImpl: // FileConfigurationServiceImpl throws IllegalStateException if // certain System properties are not set, // ConfigurationServiceImpl will make sure that these properties // are set but it will do that later. // A SecurityException is thrown when the destination // is not writable or we do not have access to that folder usePropFileConfig = null; } if (usePropFileConfig != null && usePropFileConfig.exists()) { logger.info("Using properties file configuration store."); this.cs = LibJitsi.getConfigurationService(); } } if (this.cs == null) { this.cs = new JdbcConfigService(fas); } bundleContext.registerService(ConfigurationService.class.getName(), this.cs, null); fixPermissions(this.cs); }
/** * Makes home folder and the configuration file readable and writable only to the owner. * * @param cs the <tt>ConfigurationService</tt> instance to check for home folder and configuration * file. */ private static void fixPermissions(ConfigurationService cs) { if (!OSUtils.IS_LINUX && !OSUtils.IS_MAC) return; try { // let's check config file and config folder File homeFolder = new File(cs.getScHomeDirLocation(), cs.getScHomeDirName()); Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>() { { add(PosixFilePermission.OWNER_READ); add(PosixFilePermission.OWNER_WRITE); add(PosixFilePermission.OWNER_EXECUTE); } }; Files.setPosixFilePermissions(Paths.get(homeFolder.getAbsolutePath()), perms); String fileName = cs.getConfigurationFilename(); if (fileName != null) { File cf = new File(homeFolder, fileName); if (cf.exists()) { perms = new HashSet<PosixFilePermission>() { { add(PosixFilePermission.OWNER_READ); add(PosixFilePermission.OWNER_WRITE); } }; Files.setPosixFilePermissions(Paths.get(cf.getAbsolutePath()), perms); } } } catch (Throwable t) { logger.error("Error creating c lib instance for fixing file permissions", t); if (t instanceof InterruptedException) Thread.currentThread().interrupt(); else if (t instanceof ThreadDeath) throw (ThreadDeath) t; } }
/** * Checks whether <tt>path</tt> is a valid directory for recording (creates it if necessary). * * @param path the path to the directory to check. * @return <tt>true</tt> if the directory <tt>path</tt> can be used for media recording, * <tt>false</tt> otherwise. */ private boolean checkRecordingDirectory(String path) { if (path == null || "".equals(path)) return false; File dir = new File(path); if (!dir.exists()) { dir.mkdir(); if (!dir.exists()) return false; } if (!dir.isDirectory() || !dir.canWrite()) return false; return true; }
/** * Starts recording {@link #call} creating {@link #recorder} first and asking the user for the * recording format and file if they are not configured in the "Call Recording" configuration * form. * * @return <tt>true</tt> if the recording has been started successfully; otherwise, <tt>false</tt> */ private boolean startRecording() { String savedCallsPath = configuration.getString(Recorder.SAVED_CALLS_PATH); String callFormat; // Ask the user where to save the call. if ((savedCallsPath == null) || (savedCallsPath.length() == 0)) { /* * Delay the initialization of callFileChooser in order to delay the * creation of the recorder. */ if (callFileChooser == null) { callFileChooser = GenericFileDialog.create( null, resources.getI18NString("plugin.callrecordingconfig.SAVE_CALL"), SipCommFileChooser.SAVE_FILE_OPERATION); callFileChooser.addFilter( new SipCommFileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || isSupportedFormat(f); } @Override public String getDescription() { StringBuilder description = new StringBuilder(); description.append("Recorded call"); Recorder recorder; try { recorder = getRecorder(); } catch (OperationFailedException ofex) { logger.error("Failed to get Recorder", ofex); recorder = null; } if (recorder != null) { List<String> supportedFormats = recorder.getSupportedFormats(); if (supportedFormats != null) { description.append(" ("); boolean firstSupportedFormat = true; for (String supportedFormat : supportedFormats) { if (firstSupportedFormat) firstSupportedFormat = false; else description.append(", "); description.append("*."); description.append(supportedFormat); } description.append(')'); } } return description.toString(); } }); } // Offer a default name for the file to record into. callFileChooser.setStartPath(createDefaultFilename(null)); File selectedFile = callFileChooser.getFileFromDialog(); if (selectedFile != null) { callFilename = selectedFile.getAbsolutePath(); /* * If the user specified no extension (which seems common on Mac * OS X at least) i.e. no format, then it is not obvious that we * have to override the set Recorder.CALL_FORMAT. */ callFormat = SoundFileUtils.getExtension(selectedFile); if ((callFormat != null) && (callFormat.length() != 0)) { /* * If the use has specified an extension and thus a format * which is not supported, use a default format instead. */ if (!isSupportedFormat(selectedFile)) { /* * If what appears to be an extension seems a lot like * an extension, then it should be somewhat safer to * replace it. */ if (SoundFileUtils.isSoundFile(selectedFile)) { callFilename = callFilename.substring(0, callFilename.lastIndexOf('.')); } String configuredFormat = configuration.getString(Recorder.FORMAT); callFormat = (configuredFormat != null && configuredFormat.length() != 0) ? configuredFormat : SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; callFilename += '.' + callFormat; } configuration.setProperty(Recorder.FORMAT, callFormat); } } else { // user canceled the recording return false; } } else { callFilename = createDefaultFilename(savedCallsPath); callFormat = SoundFileUtils.getExtension(new File(callFilename)); } Throwable exception = null; try { Recorder recorder = getRecorder(); if (recorder != null) { if ((callFormat == null) || (callFormat.length() <= 0)) callFormat = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; recorder.start(callFormat, callFilename); } this.recorder = recorder; } catch (IOException ioex) { exception = ioex; } catch (MediaException mex) { exception = mex; } catch (OperationFailedException ofex) { exception = ofex; } if ((recorder == null) || (exception != null)) { logger.error( "Failed to start recording call " + call + " into file " + callFilename, exception); return false; } else return true; }