Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

941 lines
14 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. mime.cpp
  5. Abstract:
  6. Mime mapping dialog
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #include "resource.h"
  19. #include "mime.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. CMimeEditDlg::CMimeEditDlg(
  26. IN CWnd * pParent OPTIONAL
  27. )
  28. /*++
  29. Routine Description:
  30. Constructor to create new mime mapping
  31. Arguments:
  32. CWnd * pParent : Optional parent window or NULL
  33. Return Value:
  34. N/A
  35. --*/
  36. : m_strExt(),
  37. m_strMime(),
  38. CDialog(CMimeEditDlg::IDD, pParent)
  39. {
  40. }
  41. CMimeEditDlg::CMimeEditDlg(
  42. IN LPCTSTR lpstrExt,
  43. IN LPCTSTR lpstrMime,
  44. IN CWnd * pParent OPTIONAL
  45. )
  46. /*++
  47. Routine Description:
  48. Constructor to edit existing mime mapping
  49. Arguments:
  50. LPCTSTR lpstrExt : Extension
  51. LPCTSTR lpstrMime : Mime mapping
  52. CWnd * pParent : Optional parent window or NULL
  53. Return Value:
  54. N/A
  55. --*/
  56. : m_strExt(lpstrExt),
  57. m_strMime(lpstrMime),
  58. CDialog(CMimeEditDlg::IDD, pParent)
  59. {
  60. //{{AFX_DATA_INIT(CMimeEditDlg)
  61. //}}AFX_DATA_INIT
  62. }
  63. void
  64. CMimeEditDlg::DoDataExchange(
  65. IN CDataExchange * pDX
  66. )
  67. /*++
  68. Routine Description:
  69. Initialise/Store control data
  70. Arguments:
  71. CDataExchange * pDX - DDX/DDV control structure
  72. Return Value:
  73. None
  74. --*/
  75. {
  76. CDialog::DoDataExchange(pDX);
  77. //{{AFX_DATA_MAP(CMimeEditDlg)
  78. DDX_Control(pDX, IDOK, m_button_Ok);
  79. DDX_Control(pDX, IDC_EDIT_MIME, m_edit_Mime);
  80. DDX_Control(pDX, IDC_EDIT_EXTENT, m_edit_Extent);
  81. //}}AFX_DATA_MAP
  82. }
  83. //
  84. // Message Map
  85. //
  86. BEGIN_MESSAGE_MAP(CMimeEditDlg, CDialog)
  87. //{{AFX_MSG_MAP(CMimeEditDlg)
  88. //}}AFX_MSG_MAP
  89. ON_EN_CHANGE(IDC_EDIT_MIME, OnItemChanged)
  90. ON_EN_CHANGE(IDC_EDIT_EXTENT, OnItemChanged)
  91. END_MESSAGE_MAP()
  92. void
  93. CMimeEditDlg::SetControlStates()
  94. /*++
  95. Routine Description:
  96. Enable/disable controls depending on current dialog data
  97. Arguments:
  98. None
  99. Return Value:
  100. None
  101. --*/
  102. {
  103. m_button_Ok.EnableWindow(
  104. m_edit_Extent.GetWindowTextLength() > 0
  105. && m_edit_Mime.GetWindowTextLength() > 0
  106. );
  107. }
  108. //
  109. // Message Handlers
  110. //
  111. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  112. void
  113. CMimeEditDlg::OnItemChanged()
  114. /*++
  115. Routine Description:
  116. Respond to changes
  117. Arguments:
  118. None.
  119. Return Value:
  120. None.
  121. --*/
  122. {
  123. SetControlStates();
  124. }
  125. BOOL
  126. CMimeEditDlg::OnInitDialog()
  127. /*++
  128. Routine Description:
  129. WM_INITDIALOG handler. Initialize the dialog.
  130. Arguments:
  131. None.
  132. Return Value:
  133. TRUE if no focus is to be set automatically, FALSE if the focus
  134. is already set.
  135. --*/
  136. {
  137. CDialog::OnInitDialog();
  138. m_edit_Extent.SetWindowText(m_strExt);
  139. m_edit_Mime.SetWindowText(m_strMime);
  140. SetControlStates();
  141. return TRUE;
  142. }
  143. void
  144. CMimeEditDlg::OnOK()
  145. /*++
  146. Routine Description:
  147. 'OK' button was pressed -- store data.
  148. Arguments:
  149. None.
  150. Return Value:
  151. TRUE if no focus is to be set automatically, FALSE if the focus
  152. is already set.
  153. --*/
  154. {
  155. m_edit_Extent.GetWindowText(m_strExt);
  156. m_edit_Mime.GetWindowText(m_strMime);
  157. CleanExtension(m_strExt);
  158. CDialog::OnOK();
  159. }
  160. CMimeDlg::CMimeDlg(
  161. IN CStringListEx & strlMimeTypes,
  162. IN CWnd * pParent OPTIONAL
  163. )
  164. /*++
  165. Routine Description:
  166. Constructor for the MIME listing dialog
  167. Arguments:
  168. CStringListEx & strlMimeTypes : Listing of mime types to edit
  169. CWnd * pParent : Optional parent window or NULL
  170. Return Value:
  171. N/A
  172. --*/
  173. : m_fDirty(FALSE),
  174. m_strlMimeTypes(strlMimeTypes),
  175. CDialog(CMimeDlg::IDD, pParent)
  176. {
  177. //{{AFX_DATA_INIT(CMimeDlg)
  178. //}}AFX_DATA_INIT
  179. }
  180. void
  181. CMimeDlg::DoDataExchange(
  182. IN OUT CDataExchange * pDX
  183. )
  184. /*++
  185. Routine Description:
  186. Initialise/Store control data
  187. Arguments:
  188. CDataExchange * pDX - DDX/DDV control structure
  189. Return Value:
  190. None
  191. --*/
  192. {
  193. CDialog::DoDataExchange(pDX);
  194. //{{AFX_DATA_MAP(CMimeDlg)
  195. DDX_Control(pDX, IDOK, m_button_Ok);
  196. DDX_Control(pDX, IDC_EDIT_EXTENSION, m_edit_Extention);
  197. DDX_Control(pDX, IDC_EDIT_CONTENT_TYPE, m_edit_ContentType);
  198. DDX_Control(pDX, IDC_BUTTON_REMOVE_MIME, m_button_Remove);
  199. DDX_Control(pDX, IDC_BUTTON_EDIT_MIME, m_button_Edit);
  200. //}}AFX_DATA_MAP
  201. DDX_Control(pDX, IDC_LIST_MIME_TYPES, m_list_MimeTypes);
  202. }
  203. //
  204. // Message Map
  205. //
  206. BEGIN_MESSAGE_MAP(CMimeDlg, CDialog)
  207. //{{AFX_MSG_MAP(CMimeDlg)
  208. ON_BN_CLICKED(IDC_BUTTON_EDIT_MIME, OnButtonEdit)
  209. ON_BN_CLICKED(IDC_BUTTON_NEW_TYPE, OnButtonNewType)
  210. ON_BN_CLICKED(IDC_BUTTON_REMOVE_MIME, OnButtonRemove)
  211. ON_LBN_DBLCLK(IDC_LIST_MIME_TYPES, OnDblclkListMimeTypes)
  212. ON_LBN_SELCHANGE(IDC_LIST_MIME_TYPES, OnSelchangeListMimeTypes)
  213. //}}AFX_MSG_MAP
  214. ON_EN_CHANGE(IDC_EDIT_CONTENT_TYPE, OnItemChanged)
  215. ON_EN_CHANGE(IDC_EDIT_EXTENSION, OnItemChanged)
  216. END_MESSAGE_MAP()
  217. void
  218. CMimeDlg::SetControlStates()
  219. /*++
  220. Routine Description:
  221. Enable/disable controls depending on current dialog data
  222. Arguments:
  223. None
  224. Return Value:
  225. None
  226. --*/
  227. {
  228. m_button_Remove.EnableWindow(m_list_MimeTypes.GetSelCount() > 0);
  229. m_button_Edit.EnableWindow(m_list_MimeTypes.GetSelCount() == 1);
  230. m_button_Ok.EnableWindow(m_fDirty);
  231. }
  232. BOOL
  233. CMimeDlg::BuildDisplayString(
  234. IN CString & strIn,
  235. OUT CString & strOut
  236. )
  237. /*++
  238. Routine Description:
  239. Build a listbox-suitable display string for the mime type
  240. Arguments:
  241. CString & strIn : Input string in metabase format
  242. CString & strOut : Output string in display format
  243. Return Value:
  244. TRUE if successfull, FALSE otherwise
  245. --*/
  246. {
  247. BOOL fSuccess = FALSE;
  248. int nComma = strIn.Find(_T(','));
  249. if (nComma >= 0)
  250. {
  251. CString strExt = strIn.Left(nComma);
  252. CString strMime = strIn.Mid(nComma + 1);
  253. try
  254. {
  255. BuildDisplayString(strExt, strMime, strOut);
  256. ++fSuccess;
  257. }
  258. catch(CMemoryException * e)
  259. {
  260. TRACEEOLID("Mem exception in BuildDisplayString");
  261. e->ReportError();
  262. e->Delete();
  263. }
  264. }
  265. return fSuccess;
  266. }
  267. BOOL
  268. CMimeDlg::CrackDisplayString(
  269. IN CString & strIn,
  270. OUT CString & strExt,
  271. OUT CString & strMime
  272. )
  273. /*++
  274. Routine Description:
  275. Parse a display-formatted mime mapping string, and break into
  276. component parts
  277. Arguments:
  278. CString & strIn : Input string in display format
  279. CString & strExt : Output extension string
  280. CString & strMime : Output MIME string.
  281. Return Value:
  282. TRUE if successfull, FALSE otherwise
  283. --*/
  284. {
  285. BOOL fSuccess = FALSE;
  286. try
  287. {
  288. int nTab = strIn.Find(_T('\t'));
  289. if (nTab >= 0)
  290. {
  291. strExt = strIn.Left(nTab);
  292. strMime = strIn.Mid(nTab + 1);
  293. ++fSuccess;
  294. }
  295. }
  296. catch(CMemoryException * e)
  297. {
  298. TRACEEOLID("Mem exception in CrackDisplayString");
  299. e->ReportError();
  300. e->Delete();
  301. }
  302. return fSuccess;
  303. }
  304. int
  305. CMimeDlg::FindMimeType(
  306. IN const CString & strTargetExt
  307. )
  308. /*++
  309. Routine Description:
  310. Find a mime type by its extention. The return value
  311. is the listbox index where the item may be found, or
  312. -1 if the item doesn't exist
  313. Arguments:
  314. const CString & strTargetExt : Target extension we're searching for
  315. Return Value:
  316. The index of the MIME mapping for this extension if found, or -1
  317. otherwise.
  318. --*/
  319. {
  320. CString str;
  321. CString strExt;
  322. CString strMime;
  323. //
  324. // CODEWORK: Change to binsearch
  325. //
  326. for (int n = 0; n < m_list_MimeTypes.GetCount(); ++n)
  327. {
  328. m_list_MimeTypes.GetText(n, str);
  329. if (CrackDisplayString(str, strExt, strMime))
  330. {
  331. if (!strExt.CompareNoCase(strTargetExt))
  332. {
  333. //
  334. // Found it.
  335. //
  336. return n;
  337. }
  338. }
  339. }
  340. //
  341. // Not found
  342. //
  343. return -1;
  344. }
  345. void
  346. CMimeDlg::FillListBox()
  347. /*++
  348. Routine Description:
  349. Move the mime mappings from the string list to
  350. the listbox
  351. Arguments:
  352. None.
  353. Return Value:
  354. None.
  355. --*/
  356. {
  357. BeginWaitCursor();
  358. POSITION pos = m_strlMimeTypes.GetHeadPosition();
  359. while(pos)
  360. {
  361. CString & str = m_strlMimeTypes.GetNext(pos);
  362. CString strOut;
  363. if (BuildDisplayString(str, strOut))
  364. {
  365. m_list_MimeTypes.AddString(strOut);
  366. }
  367. }
  368. EndWaitCursor();
  369. }
  370. void
  371. CMimeDlg::FillFromListBox()
  372. /*++
  373. Routine Description:
  374. Reverse the above; Move the contents of the listbox
  375. back to the stringlist
  376. Arguments:
  377. None.
  378. Return Value:
  379. None.
  380. --*/
  381. {
  382. CString str;
  383. CString strExt;
  384. CString strMime;
  385. BeginWaitCursor();
  386. m_strlMimeTypes.RemoveAll();
  387. for (int n = 0; n < m_list_MimeTypes.GetCount(); ++n)
  388. {
  389. m_list_MimeTypes.GetText(n, str);
  390. if (CrackDisplayString(str, strExt, strMime))
  391. {
  392. BuildMetaString(strExt, strMime, str);
  393. m_strlMimeTypes.AddTail(str);
  394. }
  395. }
  396. EndWaitCursor();
  397. }
  398. //
  399. // Message Handlers
  400. //
  401. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  402. BOOL
  403. CMimeDlg::OnInitDialog()
  404. /*++
  405. Routine Description:
  406. WM_INITDIALOG handler. Initialize the dialog.
  407. Arguments:
  408. None.
  409. Return Value:
  410. TRUE if no focus is to be set automatically, FALSE if the focus
  411. is already set.
  412. --*/
  413. {
  414. CDialog::OnInitDialog();
  415. m_list_MimeTypes.Initialize();
  416. FillListBox();
  417. SetControlStates();
  418. return TRUE;
  419. }
  420. void
  421. CMimeDlg::OnButtonEdit()
  422. /*++
  423. Routine Description:
  424. 'Edit' button has been pressed -- edit current selection
  425. Arguments:
  426. None.
  427. Return Value:
  428. None.
  429. --*/
  430. {
  431. int nCurSel = m_list_MimeTypes.GetCurSel();
  432. if (nCurSel >= 0)
  433. {
  434. CString str;
  435. CString strExt;
  436. CString strMime;
  437. m_list_MimeTypes.GetText(nCurSel, str);
  438. if (CrackDisplayString(str, strExt, strMime))
  439. {
  440. CMimeEditDlg dlg(strExt, strMime, this);
  441. if (dlg.DoModal() == IDOK)
  442. {
  443. strExt = dlg.m_strExt;
  444. strMime = dlg.m_strMime;
  445. BuildDisplayString(strExt, strMime, str);
  446. m_list_MimeTypes.DeleteString(nCurSel);
  447. nCurSel = m_list_MimeTypes.AddString(str);
  448. m_list_MimeTypes.SetCurSel(nCurSel);
  449. m_fDirty = TRUE;
  450. OnSelchangeListMimeTypes();
  451. }
  452. }
  453. }
  454. }
  455. void
  456. CMimeDlg::OnButtonNewType()
  457. /*++
  458. Routine Description:
  459. 'New' button has been pressed. Create new MIME mapping, and
  460. bring up configuration on it.
  461. Arguments:
  462. None.
  463. Return Value:
  464. None.
  465. --*/
  466. {
  467. CMimeEditDlg dlg(this);
  468. if (dlg.DoModal() == IDOK)
  469. {
  470. CString str;
  471. CString strExt = dlg.m_strExt;
  472. CString strMime = dlg.m_strMime;
  473. //
  474. // Check to see if this extension already existed
  475. // in the list
  476. //
  477. int nOldSel = FindMimeType(strExt);
  478. if (nOldSel >= 0)
  479. {
  480. //
  481. // Yes, ask to have it replaced
  482. //
  483. if (::AfxMessageBox(
  484. IDS_REPLACE_MIME,
  485. MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2
  486. ) == IDYES)
  487. {
  488. //
  489. // Kill the old one
  490. //
  491. m_list_MimeTypes.DeleteString(nOldSel);
  492. }
  493. else
  494. {
  495. //
  496. // Nope..
  497. //
  498. return;
  499. }
  500. }
  501. BuildDisplayString(strExt, strMime, str);
  502. int nCurSel = m_list_MimeTypes.AddString(str);
  503. m_list_MimeTypes.SetCurSel(nCurSel);
  504. m_fDirty = TRUE;
  505. OnSelchangeListMimeTypes();
  506. }
  507. }
  508. void
  509. CMimeDlg::OnButtonRemove()
  510. /*++
  511. Routine Description:
  512. 'Remove' button has been pressed. Remove the current MIME mapping.
  513. Arguments:
  514. None.
  515. Return Value:
  516. None.
  517. --*/
  518. {
  519. if (::AfxMessageBox(
  520. IDS_REMOVE_MIME,
  521. MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2
  522. ) != IDYES)
  523. {
  524. //
  525. // Changed his mind
  526. //
  527. return;
  528. }
  529. int nCurSel = m_list_MimeTypes.GetCurSel();
  530. int nSel = 0;
  531. while (nSel < m_list_MimeTypes.GetCount())
  532. {
  533. if (m_list_MimeTypes.GetSel(nSel))
  534. {
  535. m_list_MimeTypes.DeleteString(nSel);
  536. m_fDirty = TRUE;
  537. continue;
  538. }
  539. ++nSel;
  540. }
  541. if (m_fDirty)
  542. {
  543. if (nCurSel > 0)
  544. {
  545. --nCurSel;
  546. }
  547. m_list_MimeTypes.SetCurSel(nCurSel);
  548. OnSelchangeListMimeTypes();
  549. }
  550. }
  551. void
  552. CMimeDlg::OnItemChanged()
  553. /*++
  554. Routine Description:
  555. Respond to changes
  556. Arguments:
  557. None.
  558. Return Value:
  559. None.
  560. --*/
  561. {
  562. SetControlStates();
  563. }
  564. void
  565. CMimeDlg::OnDblclkListMimeTypes()
  566. /*++
  567. Routine Description:
  568. Double clicking on an item is the same as pressing edit
  569. Arguments:
  570. None.
  571. Return Value:
  572. None.
  573. --*/
  574. {
  575. OnButtonEdit();
  576. }
  577. void
  578. CMimeDlg::OnSelchangeListMimeTypes()
  579. /*++
  580. Routine Description:
  581. Respond to change in selection in the listbox.
  582. Arguments:
  583. None.
  584. Return Value:
  585. None.
  586. --*/
  587. {
  588. //
  589. // Update the text in the description box
  590. //
  591. int nCurSel = m_list_MimeTypes.GetCurSel();
  592. if (nCurSel >= 0)
  593. {
  594. CString str;
  595. CString strExt;
  596. CString strMime;
  597. m_list_MimeTypes.GetText(nCurSel, str);
  598. if (CrackDisplayString(str, strExt, strMime))
  599. {
  600. m_edit_Extention.SetWindowText(strExt);
  601. m_edit_ContentType.SetWindowText(strMime);
  602. }
  603. }
  604. else
  605. {
  606. m_edit_Extention.SetWindowText(_T(""));
  607. m_edit_ContentType.SetWindowText(_T(""));
  608. }
  609. SetControlStates();
  610. }
  611. void
  612. CMimeDlg::OnOK()
  613. /*++
  614. Routine Description:
  615. 'OK' button was pressed -- store data.
  616. Arguments:
  617. None.
  618. Return Value:
  619. TRUE if no focus is to be set automatically, FALSE if the focus
  620. is already set.
  621. --*/
  622. {
  623. if (m_fDirty)
  624. {
  625. FillFromListBox();
  626. }
  627. CDialog::OnOK();
  628. }