_common.sh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #!/bin/bash
  2. #=================================================
  3. # FUTUR OFFICIAL HELPERS
  4. #=================================================
  5. # Install or update the main directory yunohost.multimedia
  6. #
  7. # usage: ynh_multimedia_build_main_dir
  8. ynh_multimedia_build_main_dir () {
  9. local ynh_media_release="v1.2"
  10. local checksum="806a827ba1902d6911095602a9221181"
  11. # Download yunohost.multimedia scripts
  12. wget -nv https://github.com/YunoHost-Apps/yunohost.multimedia/archive/${ynh_media_release}.tar.gz
  13. # Check the control sum
  14. echo "${checksum} ${ynh_media_release}.tar.gz" | md5sum -c --status \
  15. || ynh_die "Corrupt source"
  16. # Check if the package acl is installed. Or install it.
  17. ynh_package_is_installed 'acl' \
  18. || ynh_package_install acl
  19. # Extract
  20. mkdir yunohost.multimedia-master
  21. tar -xf ${ynh_media_release}.tar.gz -C yunohost.multimedia-master --strip-components 1
  22. ./yunohost.multimedia-master/script/ynh_media_build.sh
  23. }
  24. # Add a directory in yunohost.multimedia
  25. # This "directory" will be a symbolic link to a existing directory.
  26. #
  27. # usage: ynh_multimedia_addfolder "Source directory" "Destination directory"
  28. #
  29. # | arg: -s, --source_dir= - Source directory - The real directory which contains your medias.
  30. # | arg: -d, --dest_dir= - Destination directory - The name and the place of the symbolic link, relative to "/home/yunohost.multimedia"
  31. ynh_multimedia_addfolder () {
  32. # Declare an array to define the options of this helper.
  33. declare -Ar args_array=( [s]=source_dir= [d]=dest_dir= )
  34. local source_dir
  35. local dest_dir
  36. # Manage arguments with getopts
  37. ynh_handle_getopts_args "$@"
  38. ./yunohost.multimedia-master/script/ynh_media_addfolder.sh --source="$source_dir" --dest="$dest_dir"
  39. }
  40. # Move a directory in yunohost.multimedia, and replace by a symbolic link
  41. #
  42. # usage: ynh_multimedia_movefolder "Source directory" "Destination directory"
  43. #
  44. # | arg: -s, --source_dir= - Source directory - The real directory which contains your medias.
  45. # It will be moved to "Destination directory"
  46. # A symbolic link will replace it.
  47. # | arg: -d, --dest_dir= - Destination directory - The new name and place of the directory, relative to "/home/yunohost.multimedia"
  48. ynh_multimedia_movefolder () {
  49. # Declare an array to define the options of this helper.
  50. declare -Ar args_array=( [s]=source_dir= [d]=dest_dir= )
  51. local source_dir
  52. local dest_dir
  53. # Manage arguments with getopts
  54. ynh_handle_getopts_args "$@"
  55. ./yunohost.multimedia-master/script/ynh_media_addfolder.sh --inv --source="$source_dir" --dest="$dest_dir"
  56. }
  57. # Allow an user to have an write authorisation in multimedia directories
  58. #
  59. # usage: ynh_multimedia_addaccess user_name
  60. #
  61. # | arg: -u, --user_name= - The name of the user which gain this access.
  62. ynh_multimedia_addaccess () {
  63. # Declare an array to define the options of this helper.
  64. declare -Ar args_array=( [u]=user_name=)
  65. local user_name
  66. # Manage arguments with getopts
  67. ynh_handle_getopts_args "$@"
  68. groupadd -f multimedia
  69. usermod -a -G multimedia $user_name
  70. }
  71. #=================================================
  72. # EXPERIMENTAL HELPERS
  73. #=================================================
  74. # Send an email to inform the administrator
  75. #
  76. # usage: ynh_send_readme_to_admin --app_message=app_message [--recipients=recipients] [--type=type]
  77. # | arg: -m --app_message= - The file with the content to send to the administrator.
  78. # | arg: -r, --recipients= - The recipients of this email. Use spaces to separate multiples recipients. - default: root
  79. # example: "root admin@domain"
  80. # If you give the name of a YunoHost user, ynh_send_readme_to_admin will find its email adress for you
  81. # example: "root admin@domain user1 user2"
  82. # | arg: -t, --type= - Type of mail, could be 'backup', 'change_url', 'install', 'remove', 'restore', 'upgrade'
  83. ynh_send_readme_to_admin() {
  84. # Declare an array to define the options of this helper.
  85. declare -Ar args_array=( [m]=app_message= [r]=recipients= [t]=type= )
  86. local app_message
  87. local recipients
  88. local type
  89. # Manage arguments with getopts
  90. ynh_handle_getopts_args "$@"
  91. app_message="${app_message:-}"
  92. recipients="${recipients:-root}"
  93. type="${type:-install}"
  94. # Get the value of admin_mail_html
  95. admin_mail_html=$(ynh_app_setting_get $app admin_mail_html)
  96. admin_mail_html="${admin_mail_html:-0}"
  97. # Retrieve the email of users
  98. find_mails () {
  99. local list_mails="$1"
  100. local mail
  101. local recipients=" "
  102. # Read each mail in argument
  103. for mail in $list_mails
  104. do
  105. # Keep root or a real email address as it is
  106. if [ "$mail" = "root" ] || echo "$mail" | grep --quiet "@"
  107. then
  108. recipients="$recipients $mail"
  109. else
  110. # But replace an user name without a domain after by its email
  111. if mail=$(ynh_user_get_info "$mail" "mail" 2> /dev/null)
  112. then
  113. recipients="$recipients $mail"
  114. fi
  115. fi
  116. done
  117. echo "$recipients"
  118. }
  119. recipients=$(find_mails "$recipients")
  120. # Subject base
  121. local mail_subject="☁️🆈🅽🅷☁️: \`$app\`"
  122. # Adapt the subject according to the type of mail required.
  123. if [ "$type" = "backup" ]; then
  124. mail_subject="$mail_subject has just been backup."
  125. elif [ "$type" = "change_url" ]; then
  126. mail_subject="$mail_subject has just been moved to a new URL!"
  127. elif [ "$type" = "remove" ]; then
  128. mail_subject="$mail_subject has just been removed!"
  129. elif [ "$type" = "restore" ]; then
  130. mail_subject="$mail_subject has just been restored!"
  131. elif [ "$type" = "upgrade" ]; then
  132. mail_subject="$mail_subject has just been upgraded!"
  133. else # install
  134. mail_subject="$mail_subject has just been installed!"
  135. fi
  136. local mail_message="This is an automated message from your beloved YunoHost server.
  137. Specific information for the application $app.
  138. $(if [ -n "$app_message" ]
  139. then
  140. cat "$app_message"
  141. else
  142. echo "...No specific information..."
  143. fi)
  144. ---
  145. Automatic diagnosis data from YunoHost
  146. __PRE_TAG1__$(yunohost tools diagnosis | grep -B 100 "services:" | sed '/services:/d')__PRE_TAG2__"
  147. # Store the message into a file for further modifications.
  148. echo "$mail_message" > mail_to_send
  149. # If a html email is required. Apply html tags to the message.
  150. if [ "$admin_mail_html" -eq 1 ]
  151. then
  152. # Insert 'br' tags at each ending of lines.
  153. ynh_replace_string "$" "<br>" mail_to_send
  154. # Insert starting HTML tags
  155. sed --in-place '1s@^@<!DOCTYPE html>\n<html>\n<head></head>\n<body>\n@' mail_to_send
  156. # Keep tabulations
  157. ynh_replace_string " " "\&#160;\&#160;" mail_to_send
  158. ynh_replace_string "\t" "\&#160;\&#160;" mail_to_send
  159. # Insert url links tags
  160. ynh_replace_string "__URL_TAG1__\(.*\)__URL_TAG2__\(.*\)__URL_TAG3__" "<a href=\"\2\">\1</a>" mail_to_send
  161. # Insert pre tags
  162. ynh_replace_string "__PRE_TAG1__" "<pre>" mail_to_send
  163. ynh_replace_string "__PRE_TAG2__" "<\pre>" mail_to_send
  164. # Insert finishing HTML tags
  165. echo -e "\n</body>\n</html>" >> mail_to_send
  166. # Otherwise, remove tags to keep a plain text.
  167. else
  168. # Remove URL tags
  169. ynh_replace_string "__URL_TAG[1,3]__" "" mail_to_send
  170. ynh_replace_string "__URL_TAG2__" ": " mail_to_send
  171. # Remove PRE tags
  172. ynh_replace_string "__PRE_TAG[1-2]__" "" mail_to_send
  173. fi
  174. # Define binary to use for mail command
  175. if [ -e /usr/bin/bsd-mailx ]
  176. then
  177. local mail_bin=/usr/bin/bsd-mailx
  178. else
  179. local mail_bin=/usr/bin/mail.mailutils
  180. fi
  181. if [ "$admin_mail_html" -eq 1 ]
  182. then
  183. content_type="text/html"
  184. else
  185. content_type="text/plain"
  186. fi
  187. # Send the email to the recipients
  188. cat mail_to_send | $mail_bin -a "Content-Type: $content_type; charset=UTF-8" -s "$mail_subject" "$recipients"
  189. }
  190. #=================================================
  191. ynh_maintenance_mode_ON () {
  192. # Load value of $path_url and $domain from the config if their not set
  193. if [ -z $path_url ]; then
  194. path_url=$(ynh_app_setting_get $app path)
  195. fi
  196. if [ -z $domain ]; then
  197. domain=$(ynh_app_setting_get $app domain)
  198. fi
  199. mkdir -p /var/www/html/
  200. # Create an html to serve as maintenance notice
  201. echo "<!DOCTYPE html>
  202. <html>
  203. <head>
  204. <meta http-equiv="refresh" content="3">
  205. <title>Your app $app is currently under maintenance!</title>
  206. <style>
  207. body {
  208. width: 70em;
  209. margin: 0 auto;
  210. }
  211. </style>
  212. </head>
  213. <body>
  214. <h1>Your app $app is currently under maintenance!</h1>
  215. <p>This app has been put under maintenance by your administrator at $(date)</p>
  216. <p>Please wait until the maintenance operation is done. This page will be reloaded as soon as your app will be back.</p>
  217. </body>
  218. </html>" > "/var/www/html/maintenance.$app.html"
  219. # Create a new nginx config file to redirect all access to the app to the maintenance notice instead.
  220. echo "# All request to the app will be redirected to ${path_url}_maintenance and fall on the maintenance notice
  221. rewrite ^${path_url}/(.*)$ ${path_url}_maintenance/? redirect;
  222. # Use another location, to not be in conflict with the original config file
  223. location ${path_url}_maintenance/ {
  224. alias /var/www/html/ ;
  225. try_files maintenance.$app.html =503;
  226. # Include SSOWAT user panel.
  227. include conf.d/yunohost_panel.conf.inc;
  228. }" > "/etc/nginx/conf.d/$domain.d/maintenance.$app.conf"
  229. # The current config file will redirect all requests to the root of the app.
  230. # To keep the full path, we can use the following rewrite rule:
  231. # rewrite ^${path_url}/(.*)$ ${path_url}_maintenance/\$1? redirect;
  232. # The difference will be in the $1 at the end, which keep the following queries.
  233. # But, if it works perfectly for a html request, there's an issue with any php files.
  234. # This files are treated as simple files, and will be downloaded by the browser.
  235. # Would be really be nice to be able to fix that issue. So that, when the page is reloaded after the maintenance, the user will be redirected to the real page he was.
  236. systemctl reload nginx
  237. }
  238. ynh_maintenance_mode_OFF () {
  239. # Load value of $path_url and $domain from the config if their not set
  240. if [ -z $path_url ]; then
  241. path_url=$(ynh_app_setting_get $app path)
  242. fi
  243. if [ -z $domain ]; then
  244. domain=$(ynh_app_setting_get $app domain)
  245. fi
  246. # Rewrite the nginx config file to redirect from ${path_url}_maintenance to the real url of the app.
  247. echo "rewrite ^${path_url}_maintenance/(.*)$ ${path_url}/\$1 redirect;" > "/etc/nginx/conf.d/$domain.d/maintenance.$app.conf"
  248. systemctl reload nginx
  249. # Sleep 4 seconds to let the browser reload the pages and redirect the user to the app.
  250. sleep 4
  251. # Then remove the temporary files used for the maintenance.
  252. rm "/var/www/html/maintenance.$app.html"
  253. rm "/etc/nginx/conf.d/$domain.d/maintenance.$app.conf"
  254. systemctl reload nginx
  255. }
  256. #=================================================
  257. # Create a changelog for an app after an upgrade from the file CHANGELOG.md.
  258. #
  259. # usage: ynh_app_changelog [--format=markdown/html/plain] [--output=changelog_file] --changelog=changelog_source]
  260. # | arg: -f --format= - Format in which the changelog will be printed
  261. # markdown: Default format.
  262. # html: Turn urls into html format.
  263. # plain: Plain text changelog
  264. # | arg: -o --output= - Output file for the changelog file (Default ./changelog)
  265. # | arg: -c --changelog= - CHANGELOG.md source (Default ../CHANGELOG.md)
  266. #
  267. # The changelog is printed into the file ./changelog and ./changelog_lite
  268. ynh_app_changelog () {
  269. # Declare an array to define the options of this helper.
  270. local legacy_args=foc
  271. declare -Ar args_array=( [f]=format= [o]=output= [c]=changelog= )
  272. local format
  273. local output
  274. local changelog
  275. # Manage arguments with getopts
  276. ynh_handle_getopts_args "$@"
  277. format=${format:-markdown}
  278. output=${output:-changelog}
  279. changelog=${changelog:-../CHANGELOG.md}
  280. local original_changelog="$changelog"
  281. local temp_changelog="changelog_temp"
  282. local final_changelog="$output"
  283. if [ ! -n "$original_changelog" ]
  284. then
  285. echo "No changelog available..." > "$final_changelog"
  286. echo "No changelog available..." > "${final_changelog}_lite"
  287. return 0
  288. fi
  289. local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version")
  290. local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version")
  291. # Get the line of the version to update to into the changelog
  292. local update_version_line=$(grep --max-count=1 --line-number "^## \[$update_version" "$original_changelog" | cut -d':' -f1)
  293. # If there's no entry for this version yet into the changelog
  294. # Get the first available version
  295. if [ -z "$update_version_line" ]
  296. then
  297. update_version_line=$(grep --max-count=1 --line-number "^##" "$original_changelog" | cut -d':' -f1)
  298. fi
  299. # Get the length of the complete changelog.
  300. local changelog_length=$(wc --lines "$original_changelog" | awk '{print $1}')
  301. # Cut the file before the version to update to.
  302. tail --lines=$(( $changelog_length - $update_version_line + 1 )) "$original_changelog" > "$temp_changelog"
  303. # Get the length of the troncated changelog.
  304. changelog_length=$(wc --lines "$temp_changelog" | awk '{print $1}')
  305. # Get the line of the current version into the changelog
  306. # Keep only the last line found
  307. local current_version_line=$(grep --line-number "^## \[$current_version" "$temp_changelog" | cut -d':' -f1 | tail --lines=1)
  308. # If there's no entry for this version into the changelog
  309. # Get the last available version
  310. if [ -z "$current_version_line" ]
  311. then
  312. current_version_line=$(grep --line-number "^##" "$original_changelog" | cut -d':' -f1 | tail --lines=1)
  313. fi
  314. # Cut the file before the current version.
  315. # Then grep the previous version into the changelog to get the line number of the previous version
  316. local previous_version_line=$(tail --lines=$(( $changelog_length - $current_version_line )) \
  317. "$temp_changelog" | grep --max-count=1 --line-number "^## " | cut -d':' -f1)
  318. # If there's no previous version into the changelog
  319. # Go until the end of the changelog
  320. if [ -z "$previous_version_line" ]
  321. then
  322. previous_version_line=$changelog_length
  323. fi
  324. # Cut the file after the previous version to keep only the changelog between the current version and the version to update to.
  325. head --lines=$(( $current_version_line + $previous_version_line - 1 )) "$temp_changelog" | tee "$final_changelog"
  326. if [ "$format" = "html" ]
  327. then
  328. # Replace markdown links by html links
  329. ynh_replace_string --match_string="\[\(.*\)\](\(.*\)))" --replace_string="<a href=\"\2\">\1</a>)" --target_file="$final_changelog"
  330. ynh_replace_string --match_string="\[\(.*\)\](\(.*\))" --replace_string="<a href=\"\2\">\1</a>" --target_file="$final_changelog"
  331. elif [ "$format" = "plain" ]
  332. then
  333. # Change title format.
  334. ynh_replace_string --match_string="^##.*\[\(.*\)\](\(.*\)) - \(.*\)$" --replace_string="## \1 (\3) - \2" --target_file="$final_changelog"
  335. # Change modifications lines format.
  336. ynh_replace_string --match_string="^\([-*]\).*\[\(.*\)\]\(.*\)" --replace_string="\1 \2 \3" --target_file="$final_changelog"
  337. fi
  338. # else markdown. As the file is already in markdown, nothing to do.
  339. # Keep only important changes into the changelog
  340. # Remove all minor changes
  341. sed '/^-/d' "$final_changelog" > "${final_changelog}_lite"
  342. # Remove all blank lines (to keep a clear workspace)
  343. sed --in-place '/^$/d' "${final_changelog}_lite"
  344. # Add a blank line at the end
  345. echo "" >> "${final_changelog}_lite"
  346. # Clean titles if there's no significative changes
  347. local line
  348. local previous_line=""
  349. while read line <&3
  350. do
  351. if [ -n "$previous_line" ]
  352. then
  353. # Remove the line if it's a title or a blank line, and the previous one was a title as well.
  354. if ( [ "${line:0:1}" = "#" ] || [ ${#line} -eq 0 ] ) && [ "${previous_line:0:1}" = "#" ]
  355. then
  356. ynh_replace_special_string --match_string="${previous_line//[/.}" --replace_string="" --target_file="${final_changelog}_lite"
  357. fi
  358. fi
  359. previous_line="$line"
  360. done 3< "${final_changelog}_lite"
  361. # Remove all blank lines again
  362. sed --in-place '/^$/d' "${final_changelog}_lite"
  363. # Restore changelog format with blank lines
  364. ynh_replace_string --match_string="^##.*" --replace_string="\n\n&\n" --target_file="${final_changelog}_lite"
  365. # Remove the 2 first blank lines
  366. sed --in-place '1,2d' "${final_changelog}_lite"
  367. # Add a blank line at the end
  368. echo "" >> "${final_changelog}_lite"
  369. # If changelog are empty, add an info
  370. if [ $(wc --words "$final_changelog" | awk '{print $1}') -eq 0 ]
  371. then
  372. echo "No changes from the changelog..." > "$final_changelog"
  373. fi
  374. if [ $(wc --words "${final_changelog}_lite" | awk '{print $1}') -eq 0 ]
  375. then
  376. echo "No significative changes from the changelog..." > "${final_changelog}_lite"
  377. fi
  378. }
  379. #=================================================
  380. # Execute a command as another user
  381. # usage: exec_as USER COMMAND [ARG ...]
  382. ynh_exec_as() {
  383. local USER=$1
  384. shift 1
  385. if [[ $USER = $(whoami) ]]; then
  386. eval "$@"
  387. else
  388. sudo -u "$USER" "$@"
  389. fi
  390. }