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.

930 lines
14 KiB

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