Задать вопрос
guvijur
@guvijur
Практик, кинестетик, ретроград и консерватор

Как определить кодировку и перекодировать имена папок?

Добрый день!
У меня есть почтовый сервер MDaemon. Все, кто с ним знаком, прекрасно знают, что в папке почтового ящика есть ряд папок - Входящие, Исходящие, Удалённые и т.д.. Но Эти названия этих папок выглядят так - &BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-.IMAP. Соответственно понять через проводник Windows то, с какой папкой ты имеешь дело очень трудно. Но даже не в этом дело. Мне понадобилось перенести всю почту с виндового сервера в Linux и адаптировать это всё под Postfix+Dovecot+Roundcube+Postfixadmin+MySQL. Эту всю связку я настроил, но linux точно так же видит эти папки с нечитаемыми именами.
5ced2ddda0941507278398.jpeg
Для начала я не могу определить кодировку, в которой названы папки, второе - мне надо как-то их перекодировать в UTF8.

Смотрите, я нашёл ответ!
1. Берём из нашего примера строку "&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-", убираем в начале символ "&", а в конце "-" заменяем на два равно - "==".
2. Полученную строку декодируем с помощью base64.
3. Результат перекодируем из UTF-16BE в UTF-8

Полная хрень!
  • Вопрос задан
  • 2059 просмотров
Подписаться 1 Простой 3 комментария
Пригласить эксперта
Ответы на вопрос 2
@Kiber63
Дополнение: примерно так же кодирует Dovecot
Ответ написан
Комментировать
guvijur
@guvijur Автор вопроса
Практик, кинестетик, ретроград и консерватор
Есть дополнение:
import base64
import re
import tkinter as tk
from tkinter import filedialog, messagebox
import pyperclip  # Для работы с буфером обмена

def decode_utf7_folder_name(encoded_name):
    # Удаляем '&' в начале и заменяем '-' в конце на '=='
    encoded_name = encoded_name.replace('&', '').replace('-', '==')
    
    try:
        # Декодируем из base64
        decoded_bytes = base64.b64decode(encoded_name)
        
        # Преобразуем из UTF-16BE в UTF-8
        decoded_name = decoded_bytes.decode('utf-16be')
    except Exception as e:
        print(f"Ошибка при декодировании строки '{encoded_name}': {e}")
        decoded_name = encoded_name  # Возвращаем исходное имя при ошибке
    
    return decoded_name

def decode_path(path):
    # Ищем все закодированные имена, начинающиеся с '&' и заканчивающиеся на '-'
    encoded_names = re.findall(r'&[A-Za-z0-9+]+-', path)
    
    # Создаем массив для хранения декодированных имен
    decoded_names = {}
    
    # Декодируем каждое найденное имя и сохраняем в словарь с оригинальным именем
    for encoded_name in encoded_names:
        decoded_name = decode_utf7_folder_name(encoded_name)
        decoded_names[encoded_name] = decoded_name
    
    # Теперь заменим закодированные имена на декодированные, сохраняя все остальные символы
    for encoded_name, decoded_name in decoded_names.items():
        path = path.replace(encoded_name, decoded_name)
    
    return path

def on_decode_button_click():
    input_path = entry.get()  # Получаем введённый путь
    if input_path:
        decoded_path = decode_path(input_path)
        result_text.config(state=tk.NORMAL)  # Разрешаем редактирование
        result_text.delete(1.0, tk.END)  # Очищаем старый результат
        result_text.insert(tk.END, decoded_path)  # Вставляем новый результат
        result_text.config(state=tk.DISABLED)  # Делаем поле только для чтения
    else:
        messagebox.showwarning("Предупреждение", "Пожалуйста, введите путь для декодирования.")

def on_browse_button_click():
    folder_selected = filedialog.askdirectory()  # Открывает диалог для выбора каталога
    if folder_selected:
        entry.delete(0, tk.END)  # Очищаем поле ввода
        entry.insert(0, folder_selected)  # Вставляем выбранный путь в поле ввода

def copy_to_clipboard():
    # Получаем текст из результата и копируем в буфер обмена
    result_text.config(state=tk.NORMAL)  # Разрешаем редактирование
    result_text_content = result_text.get(1.0, tk.END).strip()  # Получаем текст без лишних переносов
    result_text.config(state=tk.DISABLED)  # Делаем поле только для чтения
    pyperclip.copy(result_text_content)  # Копируем текст в буфер обмена
    messagebox.showinfo("Успех", "Результат скопирован в буфер обмена.")

# Создаем окно
window = tk.Tk()
window.title("Декодер пути MDaemon")

# Размеры окна с минимальными размерами
window.geometry("800x500")
window.minsize(800, 500)

# Метка для инструкции
label = tk.Label(window, text="Введите путь для декодирования:")
label.pack(pady=10)

# Поле ввода пути с растягиванием по ширине
entry = tk.Entry(window, width=50)
entry.pack(pady=5, padx=25, fill=tk.X)  # Растягиваем по ширине окна с отступами

# Кнопка для выбора каталога
browse_button = tk.Button(window, text="Выбрать каталог", command=on_browse_button_click)
browse_button.pack(pady=10)

# Кнопка для декодирования пути
decode_button = tk.Button(window, text="Декодировать путь!", command=on_decode_button_click)
decode_button.pack(pady=10)

# Заголовок для поля результата, по центру
result_label = tk.Label(window, text="Декодированный путь:")
result_label.pack(pady=5, anchor="center")

# Поле для вывода результата, доступное только для чтения
result_text = tk.Text(window, height=5, wrap=tk.WORD, bg="white", relief="sunken", state=tk.DISABLED)
result_text.pack(padx=25, pady=25, fill=tk.BOTH, expand=True)

# Кнопка для копирования результата в буфер обмена
copy_button = tk.Button(window, text="Копировать в буфер обмена", command=copy_to_clipboard)
copy_button.pack(pady=10)

# Запуск главного цикла Tkinter
window.mainloop()


Только через pip надо будет установить кое-что, возможно. Типа:
pip install pyperclip

Код декодирует русскоязычные папки в путях на сервере с MDaemon.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы