Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

LogFileLocator.java 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright (c) 2006-2015 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.addons.logging;
  23. import com.dmdirc.commandline.CommandLineOptionsModule.Directory;
  24. import com.dmdirc.config.ConfigBinding;
  25. import com.dmdirc.config.GlobalConfig;
  26. import com.dmdirc.interfaces.Connection;
  27. import com.dmdirc.interfaces.GroupChat;
  28. import com.dmdirc.interfaces.User;
  29. import com.dmdirc.interfaces.config.AggregateConfigProvider;
  30. import com.dmdirc.plugins.PluginDomain;
  31. import java.io.File;
  32. import java.math.BigInteger;
  33. import java.security.MessageDigest;
  34. import java.security.NoSuchAlgorithmException;
  35. import java.text.SimpleDateFormat;
  36. import java.util.Date;
  37. import java.util.Optional;
  38. import javax.annotation.Nullable;
  39. import javax.inject.Inject;
  40. import javax.inject.Provider;
  41. import javax.inject.Singleton;
  42. import org.slf4j.Logger;
  43. import org.slf4j.LoggerFactory;
  44. import static com.dmdirc.util.LogUtils.USER_ERROR;
  45. /**
  46. * Facilitates finding a path for log files.
  47. */
  48. @Singleton
  49. public class LogFileLocator {
  50. private static final Logger LOG = LoggerFactory.getLogger(LogFileLocator.class);
  51. private final Provider<String> directoryProvider;
  52. /** Whether to append a hash of the file name to the file name... */
  53. @ConfigBinding(key = "advanced.filenamehash")
  54. private boolean filenamehash;
  55. /** Whether to create a new folder for each network. */
  56. @ConfigBinding(key = "general.networkfolders")
  57. private boolean networkfolders;
  58. /** Whether to use date formats in file names. */
  59. @ConfigBinding(key = "advanced.usedate")
  60. private boolean usedate;
  61. /** Date format to use in file names if {@link #usedate} is true. */
  62. @ConfigBinding(key = "advanced.usedateformat")
  63. private String usedateformat;
  64. @Inject
  65. public LogFileLocator(
  66. @Directory(LoggingModule.LOGS_DIRECTORY) final Provider<String> directoryProvider,
  67. @GlobalConfig final AggregateConfigProvider globalConfig,
  68. @PluginDomain(LoggingPlugin.class) final String domain) {
  69. this.directoryProvider = directoryProvider;
  70. globalConfig.getBinder().withDefaultDomain(domain).bind(this, LogFileLocator.class);
  71. }
  72. /**
  73. * Sanitises the log file directory.
  74. *
  75. * @return Log directory
  76. */
  77. private StringBuffer getLogDirectory() {
  78. final StringBuffer directory = new StringBuffer();
  79. directory.append(directoryProvider.get());
  80. if (directory.charAt(directory.length() - 1) != File.separatorChar) {
  81. directory.append(File.separatorChar);
  82. }
  83. return directory;
  84. }
  85. /**
  86. * Get the name of the log file for a specific object.
  87. *
  88. * @param channel Channel to get the name for
  89. *
  90. * @return the name of the log file to use for this object.
  91. */
  92. public String getLogFile(final GroupChat channel) {
  93. final StringBuffer directory = getLogDirectory();
  94. final StringBuffer file = new StringBuffer();
  95. final Optional<String> network = channel.getConnection().map(Connection::getNetwork);
  96. network.ifPresent(n -> addNetworkDir(directory, file, n));
  97. file.append(sanitise(channel.getName().toLowerCase()));
  98. return getPath(directory, file, channel.getName());
  99. }
  100. /**
  101. * Get the name of the log file for a specific object.
  102. *
  103. * @param user Client to get the name for
  104. *
  105. * @return the name of the log file to use for this object.
  106. */
  107. public String getLogFile(final User user) {
  108. final StringBuffer directory = getLogDirectory();
  109. final StringBuffer file = new StringBuffer();
  110. addNetworkDir(directory, file, user.getConnection().getNetwork());
  111. file.append(sanitise(user.getNickname().toLowerCase()));
  112. return getPath(directory, file, user.getNickname());
  113. }
  114. /**
  115. * Get the name of the log file for a specific object.
  116. *
  117. * @param descriptor Description of the object to get a log file for.
  118. *
  119. * @return the name of the log file to use for this object.
  120. */
  121. public String getLogFile(@Nullable final String descriptor) {
  122. final StringBuffer directory = getLogDirectory();
  123. final StringBuffer file = new StringBuffer();
  124. final String md5String;
  125. if (descriptor == null) {
  126. file.append("null.log");
  127. md5String = "";
  128. } else {
  129. file.append(sanitise(descriptor.toLowerCase()));
  130. md5String = descriptor;
  131. }
  132. return getPath(directory, file, md5String);
  133. }
  134. /**
  135. * Gets the path for the given file and directory. Only intended to be used from getLogFile
  136. * methods.
  137. *
  138. * @param directory Log file directory
  139. * @param file Log file path
  140. * @param md5String Log file object MD5 hash
  141. *
  142. * @return Name of the log file
  143. */
  144. public String getPath(final StringBuffer directory, final StringBuffer file,
  145. final String md5String) {
  146. if (usedate) {
  147. final String dateFormat = usedateformat;
  148. final String dateDir = new SimpleDateFormat(dateFormat).format(new Date());
  149. directory.append(dateDir);
  150. if (directory.charAt(directory.length() - 1) != File.separatorChar) {
  151. directory.append(File.separatorChar);
  152. }
  153. if (!new File(directory.toString()).exists()
  154. && !new File(directory.toString()).mkdirs()) {
  155. LOG.info(USER_ERROR, "Unable to create data dirs");
  156. }
  157. }
  158. if (filenamehash) {
  159. file.append('.');
  160. file.append(md5(md5String));
  161. }
  162. file.append(".log");
  163. return directory + file.toString();
  164. }
  165. /**
  166. * This function adds the networkName to the log file. It first tries to create a directory for
  167. * each network, if that fails it will prepend the networkName to the filename instead.
  168. *
  169. * @param directory Current directory name
  170. * @param file Current file name
  171. * @param networkName Name of network
  172. */
  173. protected void addNetworkDir(final StringBuffer directory, final StringBuffer file,
  174. final String networkName) {
  175. if (!networkfolders) {
  176. return;
  177. }
  178. final String network = sanitise(networkName.toLowerCase());
  179. boolean prependNetwork = false;
  180. // Check dir exists
  181. final File dir = new File(directory + network + System.getProperty(
  182. "file.separator"));
  183. if (dir.exists() && !dir.isDirectory()) {
  184. LOG.info(USER_ERROR, "Unable to create networkfolders dir (file exists instead)");
  185. // Prepend network name to file instead.
  186. prependNetwork = true;
  187. } else if (!dir.exists() && !dir.mkdirs()) {
  188. LOG.info(USER_ERROR, "Unable to create networkfolders dir");
  189. prependNetwork = true;
  190. }
  191. if (prependNetwork) {
  192. file.insert(0, " -- ");
  193. file.insert(0, network);
  194. } else {
  195. directory.append(network);
  196. directory.append(System.getProperty("file.separator"));
  197. }
  198. }
  199. /**
  200. * Sanitise a string to be used as a filename.
  201. *
  202. * @param name String to sanitise
  203. *
  204. * @return Sanitised version of name that can be used as a filename.
  205. */
  206. protected static String sanitise(final String name) {
  207. // Replace illegal chars with
  208. return name.replaceAll("[^\\w\\.\\s\\-#&_]", "_");
  209. }
  210. /**
  211. * Get the md5 hash of a string.
  212. *
  213. * @param string String to hash
  214. *
  215. * @return md5 hash of given string
  216. */
  217. protected static String md5(final String string) {
  218. try {
  219. final MessageDigest m = MessageDigest.getInstance("MD5");
  220. m.update(string.getBytes(), 0, string.length());
  221. return new BigInteger(1, m.digest()).toString(16);
  222. } catch (NoSuchAlgorithmException e) {
  223. return "";
  224. }
  225. }
  226. }