Leaked source code of windows server 2003
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.

1455 lines
26 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. httppage.cpp
  5. Abstract:
  6. HTTP Headers property page
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include "common.h"
  16. #include "inetprop.h"
  17. #include "InetMgrapp.h"
  18. #include "shts.h"
  19. #include "w3sht.h"
  20. #include "resource.h"
  21. #include "fltdlg.h"
  22. #include "hdrdlg.h"
  23. #include "HTTPPage.h"
  24. #include "mime.h"
  25. #include "iisobj.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. /* static */
  32. void
  33. CHeader::CrackDisplayString(
  34. IN LPCTSTR lpstrDisplayString,
  35. OUT CString & strHeader,
  36. OUT CString & strValue
  37. )
  38. /*++
  39. Routine Description:
  40. Crack the display string into component formats
  41. Arguments:
  42. LPCTSTR lpstrDisplayString : Input display string
  43. CString & strHeader : Header
  44. CString & strValue : Value
  45. Return Value:
  46. N/A
  47. --*/
  48. {
  49. strHeader = lpstrDisplayString;
  50. strHeader.TrimLeft();
  51. strHeader.TrimRight();
  52. int nColon = strHeader.Find(_T(':'));
  53. if (nColon >= 0)
  54. {
  55. strValue = (lpstrDisplayString + nColon + 1);
  56. strHeader.ReleaseBuffer(nColon);
  57. }
  58. strValue.TrimLeft();
  59. strValue.TrimRight();
  60. }
  61. //
  62. // HTTP Custom Header Property Page
  63. //
  64. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  65. #define MINUTE (60L)
  66. #define HOUR (60L * MINUTE)
  67. #define DAY (24L * HOUR)
  68. #define YEAR (365 * DAY)
  69. #define EXPIRE_IMMEDIATELY ((LONG)(0L))
  70. #define EXPIRE_INFINITE ((LONG)(0xffffffff))
  71. #define EXPIRE_DEFAULT ((LONG)(1L * DAY)) // 1 day
  72. #define DEFAULT_DYN_EXPIRE (10L * DAY)
  73. #define EXPIRE_MIN_NUMBER (1)
  74. #define EXPIRE_MAX_NUMBER (32767)
  75. IMPLEMENT_DYNCREATE(CW3HTTPPage, CInetPropertyPage)
  76. CW3HTTPPage::CW3HTTPPage(
  77. IN CInetPropertySheet * pSheet
  78. )
  79. /*++
  80. Routine Description:
  81. Property page constructor
  82. Arguments:
  83. CInetPropertySheet * pSheet : Sheet data
  84. Return Value:
  85. N/A
  86. --*/
  87. : CInetPropertyPage(CW3HTTPPage::IDD, pSheet),
  88. m_fValuesAdjusted(FALSE),
  89. m_ppropMimeTypes(NULL),
  90. m_tmNow(CTime::GetCurrentTime())
  91. {
  92. #if 0 // Keep Class Wizard happy
  93. //{{AFX_DATA_INIT(CW3HTTPPage)
  94. // m_nTimeSelector = -1;
  95. // m_nImmediateTemporary = -1;
  96. m_fEnableExpiration = FALSE;
  97. // m_nExpiration = 0L;
  98. m_strlCustomHeaders = _T("");
  99. //}}AFX_DATA_INIT
  100. #endif // 0
  101. m_nExpiration = 1L;
  102. m_nImmediateTemporary = RADIO_EXPIRE;
  103. m_nTimeSelector = COMBO_DAYS;
  104. }
  105. CW3HTTPPage::~CW3HTTPPage()
  106. /*++
  107. Routine Description:
  108. Destructor
  109. Arguments:
  110. N/A
  111. Return Value:
  112. N/A
  113. --*/
  114. {
  115. }
  116. void
  117. CW3HTTPPage::DoDataExchange(
  118. IN CDataExchange * pDX
  119. )
  120. /*++
  121. Routine Description:
  122. Initialise/Store control data
  123. Arguments:
  124. CDataExchange * pDX - DDX/DDV control structure
  125. Return Value:
  126. None
  127. --*/
  128. {
  129. CInetPropertyPage::DoDataExchange(pDX);
  130. //{{AFX_DATA_MAP(CW3HTTPPage)
  131. DDX_Control(pDX, IDC_BUTTON_FILE_TYPES, m_button_FileTypes);
  132. DDX_Radio(pDX, IDC_RADIO_IMMEDIATELY, m_nImmediateTemporary);
  133. DDX_Check(pDX, IDC_CHECK_EXPIRATION, m_fEnableExpiration);
  134. DDX_Control(pDX, IDC_EDIT_EXPIRE, m_edit_Expire);
  135. DDX_Control(pDX, IDC_RADIO_IMMEDIATELY, m_radio_Immediately);
  136. DDX_Control(pDX, IDC_BUTTON_DELETE, m_button_Delete);
  137. DDX_Control(pDX, IDC_BUTTON_EDIT, m_button_Edit);
  138. DDX_Control(pDX, IDC_STATIC_CONTENT_SHOULD, m_static_Contents);
  139. DDX_Control(pDX, IDC_COMBO_TIME, m_combo_Time);
  140. //}}AFX_DATA_MAP
  141. //
  142. // Only store and validate immediate expiration date if immediate
  143. // is selected.
  144. //
  145. if (!pDX->m_bSaveAndValidate || m_nImmediateTemporary == RADIO_EXPIRE)
  146. {
  147. DDX_CBIndex(pDX, IDC_COMBO_TIME, m_nTimeSelector);
  148. if (m_fEnableExpiration)
  149. {
  150. // This Needs to come before DDX_Text which will try to put text big number into small number
  151. DDV_MinMaxBalloon(pDX, IDC_EDIT_EXPIRE, EXPIRE_MIN_NUMBER, EXPIRE_MAX_NUMBER);
  152. }
  153. DDX_Text(pDX, IDC_EDIT_EXPIRE, m_nExpiration);
  154. }
  155. DDX_Control(pDX, IDC_RADIO_TIME, m_radio_Time);
  156. DDX_Control(pDX, IDC_RADIO_ABS_TIME, m_radio_AbsTime);
  157. DDX_Control(pDX, IDC_DTP_ABS_DATE, m_dtpDate);
  158. DDX_Control(pDX, IDC_DTP_ABS_TIME, m_dtpTime);
  159. DDX_Control(pDX, IDC_LIST_HEADERS, m_list_Headers);
  160. if (pDX->m_bSaveAndValidate)
  161. {
  162. StoreTime();
  163. StoreHeaders();
  164. }
  165. }
  166. //
  167. // Message Map
  168. //
  169. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  170. BEGIN_MESSAGE_MAP(CW3HTTPPage, CInetPropertyPage)
  171. //{{AFX_MSG_MAP(CW3HTTPPage)
  172. ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAdd)
  173. ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
  174. ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit)
  175. ON_BN_CLICKED(IDC_BUTTON_FILE_TYPES, OnButtonFileTypes)
  176. ON_BN_CLICKED(IDC_BUTTON_RATINGS_TEMPLATE, OnButtonRatingsTemplate)
  177. ON_BN_CLICKED(IDC_CHECK_EXPIRATION, OnCheckExpiration)
  178. ON_CBN_SELCHANGE(IDC_COMBO_TIME, OnSelchangeComboTime)
  179. ON_LBN_SELCHANGE(IDC_LIST_HEADERS, OnSelchangeListHeaders)
  180. ON_LBN_DBLCLK(IDC_LIST_HEADERS, OnDblclkListHeaders)
  181. ON_BN_CLICKED(IDC_RADIO_IMMEDIATELY, OnRadioImmediately)
  182. ON_BN_CLICKED(IDC_RADIO_TIME, OnRadioTime)
  183. ON_BN_CLICKED(IDC_RADIO_ABS_TIME, OnRadioAbsTime)
  184. ON_WM_DESTROY()
  185. //}}AFX_MSG_MAP
  186. ON_EN_CHANGE(IDC_EDIT_EXPIRE, OnItemChanged)
  187. END_MESSAGE_MAP()
  188. BOOL
  189. AdjustIfEvenMultiple(
  190. IN OUT CILong & ilValue,
  191. IN LONG lMultiple
  192. )
  193. /*++
  194. Routine Description:
  195. Check to see if ilValue is an even multiple of lMultiple.
  196. If so, divide ilValue by lMultiple
  197. Arguments:
  198. CILong & ilValue : Value
  199. LONG lMultiple : Multiple
  200. Return Value:
  201. TRUE if ilValue is an even multiple of lMultiple.
  202. --*/
  203. {
  204. DWORD dw = (DWORD)(LONG)ilValue / (DWORD)lMultiple;
  205. if (dw * (DWORD)lMultiple == (DWORD)(LONG)ilValue)
  206. {
  207. ilValue = (LONG)dw;
  208. return TRUE;
  209. }
  210. return FALSE;
  211. }
  212. BOOL
  213. CW3HTTPPage::CrackExpirationString(
  214. IN CString & strExpiration
  215. )
  216. /*++
  217. Routine Description:
  218. Crack the expiration string into component parts. Using either N or a blank
  219. string to signify "No expiration"
  220. Arguments:
  221. None
  222. Return Value:
  223. return TRUE if the values had to be adjusted because they were out of
  224. range.
  225. --*/
  226. {
  227. strExpiration.TrimLeft();
  228. strExpiration.TrimRight();
  229. BOOL fValueAdjusted = FALSE;
  230. m_fEnableExpiration = !strExpiration.IsEmpty();
  231. LPCTSTR lp = strExpiration;
  232. BOOL fAbs = FALSE;
  233. if (m_fEnableExpiration)
  234. {
  235. switch(*lp)
  236. {
  237. case _T('D'):
  238. case _T('d'):
  239. lp += 2;
  240. while (_istspace(*lp)) ++lp;
  241. CvtStringToLong(lp, &m_dwRelTime);
  242. break;
  243. case _T('S'):
  244. case _T('s'):
  245. lp += 2;
  246. while (_istspace(*lp)) ++lp;
  247. m_dwRelTime = EXPIRE_DEFAULT;
  248. time_t tm;
  249. if (!CvtGMTStringToInternal(lp, &tm))
  250. {
  251. DoHelpMessageBox(m_hWnd,IDS_ERR_EXPIRE_RANGE, MB_APPLMODAL | MB_OK | MB_ICONINFORMATION, 0);
  252. fValueAdjusted = TRUE;
  253. }
  254. m_tm = tm;
  255. fAbs = TRUE;
  256. break;
  257. case _T('N'):
  258. case _T('n'):
  259. m_fEnableExpiration = FALSE;
  260. break;
  261. default:
  262. TRACEEOLID("Expiration string in bogus format");
  263. m_fEnableExpiration = FALSE;
  264. }
  265. }
  266. //
  267. // Set Values:
  268. //
  269. m_nExpiration = (LONG)m_dwRelTime;
  270. m_nImmediateTemporary = fAbs
  271. ? RADIO_EXPIRE_ABS
  272. : (m_nExpiration == EXPIRE_IMMEDIATELY)
  273. ? RADIO_IMMEDIATELY
  274. : RADIO_EXPIRE;
  275. //
  276. // Adjust time
  277. //
  278. if (m_nExpiration == EXPIRE_INFINITE
  279. || m_nExpiration == EXPIRE_IMMEDIATELY)
  280. {
  281. m_nExpiration = EXPIRE_DEFAULT;
  282. }
  283. if (AdjustIfEvenMultiple(m_nExpiration, DAY))
  284. {
  285. m_nTimeSelector = COMBO_DAYS;
  286. }
  287. else if (AdjustIfEvenMultiple(m_nExpiration, HOUR))
  288. {
  289. m_nTimeSelector = COMBO_HOURS;
  290. }
  291. else
  292. {
  293. m_nExpiration /= MINUTE;
  294. m_nExpiration = __max((DWORD)(LONG)m_nExpiration, 1L);
  295. if (m_nExpiration < EXPIRE_MIN_NUMBER ||
  296. m_nExpiration > EXPIRE_MAX_NUMBER)
  297. {
  298. m_nExpiration = (EXPIRE_DEFAULT / MINUTE);
  299. DoHelpMessageBox(m_hWnd,IDS_ERR_EXPIRE_RANGE, MB_APPLMODAL | MB_OK | MB_ICONINFORMATION, 0);
  300. }
  301. m_nTimeSelector = COMBO_MINUTES;
  302. }
  303. return fValueAdjusted;
  304. }
  305. void
  306. CW3HTTPPage::MakeExpirationString(
  307. OUT CString & strExpiration
  308. )
  309. /*++
  310. Routine Description:
  311. Make the expiration string from component parts
  312. Arguments:
  313. None
  314. Return Value:
  315. None
  316. --*/
  317. {
  318. strExpiration.Empty();
  319. DWORD dwExpiration = m_nExpiration;
  320. if (m_fEnableExpiration)
  321. {
  322. switch(m_nImmediateTemporary)
  323. {
  324. case RADIO_IMMEDIATELY:
  325. strExpiration = _T("D, 0");
  326. break;
  327. case RADIO_EXPIRE:
  328. switch(m_nTimeSelector)
  329. {
  330. case COMBO_MINUTES:
  331. dwExpiration *= MINUTE;
  332. break;
  333. case COMBO_HOURS:
  334. dwExpiration *= HOUR;
  335. break;
  336. case COMBO_DAYS:
  337. dwExpiration *= DAY;
  338. break;
  339. default:
  340. ASSERT(FALSE);
  341. }
  342. strExpiration.Format(_T("D, 0x%0x"), dwExpiration);
  343. break;
  344. case RADIO_EXPIRE_ABS:
  345. CvtInternalToGMTString(m_tm.GetTime(), strExpiration);
  346. strExpiration = _T("S, ") + strExpiration;
  347. break;
  348. default:
  349. TRACEEOLID("Unknown expiration format");
  350. ASSERT(FALSE);
  351. return;
  352. }
  353. }
  354. }
  355. /* virtual */
  356. HRESULT
  357. CW3HTTPPage::FetchLoadedValues()
  358. /*++
  359. Routine Description:
  360. Move configuration data from sheet to dialog controls
  361. Arguments:
  362. None
  363. Return Value:
  364. HRESULT
  365. --*/
  366. {
  367. BEGIN_META_DIR_READ(CW3Sheet)
  368. CString m_strExpiration;
  369. FETCH_DIR_DATA_FROM_SHEET(m_strExpiration);
  370. FETCH_DIR_DATA_FROM_SHEET(m_strlCustomHeaders);
  371. //
  372. // Set up some defaults.
  373. //
  374. m_dwRelTime = EXPIRE_DEFAULT;
  375. m_tm = CTime(
  376. m_tmNow.GetYear(),
  377. m_tmNow.GetMonth(),
  378. m_tmNow.GetDay(),
  379. 0, 0, 0 // Midnight
  380. );
  381. m_tm += DEFAULT_DYN_EXPIRE;
  382. m_fValuesAdjusted = CrackExpirationString(m_strExpiration);
  383. END_META_DIR_READ(err)
  384. //
  385. // Fetch the properties from the metabase
  386. //
  387. ASSERT(m_ppropMimeTypes == NULL);
  388. CError err;
  389. m_ppropMimeTypes = new CMimeTypes(
  390. QueryAuthInfo(),
  391. // CMetabasePath(g_cszSvc, QueryInstance(), SZ_MBN_ROOT)
  392. QueryMetaPath()
  393. );
  394. if (m_ppropMimeTypes)
  395. {
  396. err = m_ppropMimeTypes->LoadData();
  397. if (err.Succeeded())
  398. {
  399. m_strlMimeTypes = m_ppropMimeTypes->m_strlMimeTypes;
  400. }
  401. }
  402. else
  403. {
  404. err = ERROR_NOT_ENOUGH_MEMORY;
  405. }
  406. return err;
  407. }
  408. void
  409. CW3HTTPPage::StoreTime()
  410. /*++
  411. Routine Description:
  412. Built datetime by combining current date with the time from the time
  413. controls.
  414. Arguments:
  415. None
  416. Return Value:
  417. None
  418. --*/
  419. {
  420. SYSTEMTIME tmDate, tmTime;
  421. m_dtpDate.GetTime(&tmDate);
  422. m_dtpTime.GetTime(&tmTime);
  423. m_tm = CTime(
  424. tmDate.wYear,
  425. tmDate.wMonth,
  426. tmDate.wDay,
  427. tmTime.wHour,
  428. tmTime.wMinute,
  429. tmTime.wSecond
  430. );
  431. }
  432. void
  433. CW3HTTPPage::SetTimeFields()
  434. /*++
  435. Routine Description:
  436. Set time fields from CTime structure
  437. Arguments:
  438. None
  439. Return Value:
  440. None
  441. --*/
  442. {
  443. SYSTEMTIME stm =
  444. {
  445. (WORD)m_tm.GetYear(),
  446. (WORD)m_tm.GetMonth(),
  447. (WORD)m_tm.GetDayOfWeek(),
  448. (WORD)m_tm.GetDay(),
  449. (WORD)m_tm.GetHour(),
  450. (WORD)m_tm.GetMinute(),
  451. (WORD)m_tm.GetSecond(),
  452. 0 // Milliseconds
  453. };
  454. m_dtpDate.SetTime(&stm);
  455. m_dtpTime.SetTime(&stm);
  456. }
  457. void
  458. CW3HTTPPage::FillListBox()
  459. /*++
  460. Routine Description:
  461. Fill the custom headers listbox with the custom headers entries
  462. Arguments:
  463. None
  464. Return Value:
  465. None
  466. --*/
  467. {
  468. CObListIter obli(m_oblHeaders);
  469. CHeader * pHeader;
  470. //
  471. // Remember the selection.
  472. //
  473. int nCurSel = m_list_Headers.GetCurSel();
  474. m_list_Headers.SetRedraw(FALSE);
  475. m_list_Headers.ResetContent();
  476. int cItems = 0 ;
  477. CString strCustom;
  478. for ( /**/ ; pHeader = (CHeader *)obli.Next() ; cItems++ )
  479. {
  480. m_list_Headers.AddString(pHeader->DisplayString(strCustom));
  481. }
  482. m_list_Headers.SetRedraw(TRUE);
  483. m_list_Headers.SetCurSel(nCurSel);
  484. }
  485. BOOL
  486. CW3HTTPPage::SetControlStates()
  487. /*++
  488. Routine Description:
  489. Set the control enabled/disabled states depending on the state of the
  490. dialog
  491. Arguments:
  492. None
  493. Return Value:
  494. TRUE if an item was selected in the headers listbox, FALSE otherwise.
  495. --*/
  496. {
  497. BOOL fSingleSelection = m_list_Headers.GetSelCount() == 1;
  498. m_button_Edit.EnableWindow(fSingleSelection);
  499. m_button_Delete.EnableWindow(m_list_Headers.GetSelCount() > 0);
  500. BOOL fExpire = (m_nImmediateTemporary == RADIO_EXPIRE);
  501. BOOL fExpireAbs = (m_nImmediateTemporary == RADIO_EXPIRE_ABS);
  502. m_static_Contents.EnableWindow(m_fEnableExpiration);
  503. m_radio_Immediately.EnableWindow(m_fEnableExpiration);
  504. m_radio_Time.EnableWindow(m_fEnableExpiration);
  505. m_radio_AbsTime.EnableWindow(m_fEnableExpiration);
  506. m_edit_Expire.EnableWindow(m_fEnableExpiration && fExpire);
  507. m_combo_Time.EnableWindow(m_fEnableExpiration && fExpire);
  508. m_dtpDate.EnableWindow(m_fEnableExpiration && fExpireAbs);
  509. m_dtpTime.EnableWindow(m_fEnableExpiration && fExpireAbs);
  510. return fSingleSelection;
  511. }
  512. void
  513. CW3HTTPPage::FetchHeaders()
  514. /*++
  515. Routine Description:
  516. Build custom headers oblist
  517. Arguments:
  518. None
  519. Return Value:
  520. None
  521. --*/
  522. {
  523. POSITION pos = m_strlCustomHeaders.GetHeadPosition();
  524. while(pos)
  525. {
  526. CString & str = m_strlCustomHeaders.GetNext(pos);
  527. m_oblHeaders.AddTail(new CHeader(str));
  528. }
  529. }
  530. BOOL
  531. CW3HTTPPage::HeaderExists(
  532. IN LPCTSTR lpHeader
  533. )
  534. /*++
  535. Routine Description:
  536. Check to see if a given header exists in the list
  537. Arguments:
  538. LPCTSTR strHeader : Header name
  539. Return Value:
  540. TRUE if the entry exists, FALSE otherwise.
  541. --*/
  542. {
  543. POSITION pos = m_oblHeaders.GetHeadPosition();
  544. while(pos)
  545. {
  546. CHeader * pHeader = (CHeader *)m_oblHeaders.GetNext(pos);
  547. ASSERT(pHeader);
  548. if (!pHeader->GetHeader().CompareNoCase(lpHeader))
  549. {
  550. return TRUE;
  551. }
  552. }
  553. return FALSE;
  554. }
  555. void
  556. CW3HTTPPage::StoreHeaders()
  557. /*++
  558. Routine Description:
  559. Convert the headers oblist to a stringlist
  560. Arguments:
  561. None
  562. Return Value:
  563. None
  564. --*/
  565. {
  566. m_strlCustomHeaders.RemoveAll();
  567. POSITION pos = m_oblHeaders.GetHeadPosition();
  568. while(pos)
  569. {
  570. CHeader * pHdr = (CHeader *)m_oblHeaders.GetNext(pos);
  571. ASSERT(pHdr != NULL);
  572. CString str;
  573. pHdr->DisplayString(str);
  574. m_strlCustomHeaders.AddTail(str);
  575. }
  576. }
  577. INT_PTR
  578. CW3HTTPPage::ShowPropertiesDialog(
  579. IN BOOL fAdd
  580. )
  581. /*++
  582. Routine Description:
  583. Bring up the dialog used for add or edit.
  584. return the value returned by the dialog
  585. Arguments:
  586. None
  587. Return Value:
  588. Return value of the dialog (IDOK or IDCANCEL)
  589. --*/
  590. {
  591. //
  592. // Bring up the dialog
  593. //
  594. CHeader * pHeader = NULL;
  595. LPCTSTR lpstrHeader = NULL;
  596. LPCTSTR lpstrValue = NULL;
  597. int nCurSel = LB_ERR;
  598. INT_PTR nReturn;
  599. if (!fAdd)
  600. {
  601. nCurSel = m_list_Headers.GetCurSel();
  602. ASSERT(nCurSel != LB_ERR);
  603. pHeader = (CHeader *)m_oblHeaders.GetAt(m_oblHeaders.FindIndex(nCurSel));
  604. ASSERT(pHeader != NULL);
  605. lpstrHeader = pHeader->QueryHeader();
  606. lpstrValue = pHeader->QueryValue();
  607. }
  608. CHeaderDlg dlg(lpstrHeader, lpstrValue, this);
  609. nReturn = dlg.DoModal();
  610. if (nReturn == IDOK)
  611. {
  612. CString strEntry;
  613. if (fAdd)
  614. {
  615. if (HeaderExists(dlg.GetHeader()))
  616. {
  617. DoHelpMessageBox(m_hWnd,IDS_ERR_DUP_HEADER, MB_APPLMODAL | MB_OK | MB_ICONINFORMATION, 0);
  618. return IDCANCEL;
  619. }
  620. pHeader = new CHeader(dlg.GetHeader(), dlg.GetValue());
  621. m_oblHeaders.AddTail(pHeader);
  622. m_list_Headers.SetCurSel(m_list_Headers.AddString(
  623. pHeader->DisplayString(strEntry))
  624. );
  625. }
  626. else
  627. {
  628. pHeader->SetHeader(dlg.GetHeader());
  629. pHeader->SetValue(dlg.GetValue());
  630. m_list_Headers.DeleteString(nCurSel);
  631. m_list_Headers.InsertString(
  632. nCurSel,
  633. pHeader->DisplayString(strEntry)
  634. );
  635. m_list_Headers.SetCurSel(nCurSel);
  636. }
  637. }
  638. return nReturn;
  639. }
  640. //
  641. // Message Handlers
  642. //
  643. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  644. void
  645. CW3HTTPPage::OnItemChanged()
  646. /*++
  647. Routine Description:
  648. All EN_CHANGE messages map to this function
  649. Arguments:
  650. None
  651. Return Value:
  652. None
  653. --*/
  654. {
  655. SetModified(TRUE);
  656. }
  657. void
  658. CW3HTTPPage::OnButtonAdd()
  659. /*++
  660. Routine Description:
  661. 'add' button handler
  662. Arguments:
  663. None
  664. Return Value:
  665. None
  666. --*/
  667. {
  668. if (ShowPropertiesDialog(TRUE) == IDOK)
  669. {
  670. SetControlStates();
  671. OnItemChanged();
  672. }
  673. }
  674. void
  675. CW3HTTPPage::OnButtonDelete()
  676. /*++
  677. Routine Description:
  678. 'delete' button handler
  679. Arguments:
  680. None
  681. Return Value:
  682. None
  683. --*/
  684. {
  685. int nCurSel = m_list_Headers.GetCurSel();
  686. int nSel = 0;
  687. int cChanges = 0;
  688. while (nSel < m_list_Headers.GetCount())
  689. {
  690. if (m_list_Headers.GetSel(nSel))
  691. {
  692. m_oblHeaders.RemoveIndex(nSel);
  693. m_list_Headers.DeleteString(nSel);
  694. ++cChanges;
  695. continue;
  696. }
  697. ++nSel;
  698. }
  699. if (cChanges)
  700. {
  701. m_list_Headers.SetCurSel(nCurSel);
  702. if (!SetControlStates())
  703. {
  704. //
  705. // Delete button will be disabled, move focus elsewhere
  706. //
  707. GetDlgItem(IDC_BUTTON_ADD)->SetFocus();
  708. }
  709. OnItemChanged();
  710. }
  711. }
  712. void
  713. CW3HTTPPage::OnButtonEdit()
  714. /*++
  715. Routine Description:
  716. 'edit' button handler
  717. Arguments:
  718. None
  719. Return Value:
  720. None
  721. --*/
  722. {
  723. if (ShowPropertiesDialog(FALSE) == IDOK)
  724. {
  725. SetControlStates();
  726. OnItemChanged();
  727. }
  728. }
  729. void
  730. CW3HTTPPage::OnCheckExpiration()
  731. /*++
  732. Routine Description:
  733. 'expiration' checkbox
  734. Arguments:
  735. None
  736. Return Value:
  737. None
  738. --*/
  739. {
  740. m_fEnableExpiration = !m_fEnableExpiration;
  741. SetControlStates();
  742. OnItemChanged();
  743. }
  744. void
  745. CW3HTTPPage::OnSelchangeComboTime()
  746. /*++
  747. Routine Description:
  748. 'selection change' in time combobox handler
  749. Arguments:
  750. None
  751. Return Value:
  752. None
  753. --*/
  754. {
  755. SetControlStates();
  756. OnItemChanged();
  757. }
  758. void
  759. CW3HTTPPage::OnSelchangeListHeaders()
  760. /*++
  761. Routine Description:
  762. 'selection change' in headers listbox handler
  763. Arguments:
  764. None
  765. Return Value:
  766. None
  767. --*/
  768. {
  769. SetControlStates();
  770. }
  771. void
  772. CW3HTTPPage::OnDblclkListHeaders()
  773. /*++
  774. Routine Description:
  775. 'double click' in headers listbox handler
  776. Arguments:
  777. None
  778. Return Value:
  779. None
  780. --*/
  781. {
  782. OnButtonEdit();
  783. }
  784. void
  785. CW3HTTPPage::OnRadioImmediately()
  786. /*++
  787. Routine Description:
  788. 'immediate' radio button handler
  789. Arguments:
  790. None
  791. Return Value:
  792. None
  793. --*/
  794. {
  795. m_nImmediateTemporary = RADIO_IMMEDIATELY;
  796. SetControlStates();
  797. OnItemChanged();
  798. }
  799. void
  800. CW3HTTPPage::OnRadioTime()
  801. /*++
  802. Routine Description:
  803. 'expire' radio button
  804. Arguments:
  805. None
  806. Return Value:
  807. None
  808. --*/
  809. {
  810. m_nImmediateTemporary = RADIO_EXPIRE;
  811. SetControlStates();
  812. OnItemChanged();
  813. }
  814. void
  815. CW3HTTPPage::OnRadioAbsTime()
  816. /*++
  817. Routine Description:
  818. 'absolute expire' radio button
  819. Arguments:
  820. None
  821. Return Value:
  822. None
  823. --*/
  824. {
  825. m_nImmediateTemporary = RADIO_EXPIRE_ABS;
  826. SetControlStates();
  827. OnItemChanged();
  828. }
  829. BOOL
  830. CW3HTTPPage::OnInitDialog()
  831. /*++
  832. Routine Description:
  833. WM_INITDIALOG handler. Initialize the dialog.
  834. Arguments:
  835. None.
  836. Return Value:
  837. TRUE if focus is to be set automatically, FALSE if the focus
  838. is already set.
  839. --*/
  840. {
  841. CInetPropertyPage::OnInitDialog();
  842. m_button_FileTypes.EnableWindow(m_ppropMimeTypes != NULL);
  843. m_list_Headers.Initialize();
  844. //
  845. // Fill combo box with (Minutes, hours, days)
  846. //
  847. CString str;
  848. VERIFY(str.LoadString(IDS_MINUTES));
  849. m_combo_Time.AddString(str);
  850. VERIFY(str.LoadString(IDS_HOURS));
  851. m_combo_Time.AddString(str);
  852. VERIFY(str.LoadString(IDS_DAYS));
  853. m_combo_Time.AddString(str);
  854. m_combo_Time.SetCurSel(m_nTimeSelector);
  855. //
  856. // Set the minimum of the date picker to today
  857. // and the maximum to Dec 31, 2035.
  858. //
  859. CTime m_tmNow(CTime::GetCurrentTime());
  860. CTime tmThen(2035, 12, 31, 23, 59, 59);
  861. m_dtpDate.SetRange(&m_tmNow, &tmThen);
  862. //
  863. // Create a hidden ratings OCX, which is activated by a press
  864. // on the ratings button. We never did get our problems with
  865. // mnemonics straightened out so that we could use the ocx
  866. // directly.
  867. //
  868. m_ocx_Ratings.Create(_T("Rat"), WS_BORDER, CRect(0, 0, 0, 0), this, IDC_BUTTON_RATINGS);
  869. CComBSTR url;
  870. CIISMBNode * pNode = (CIISMBNode *)GetSheet()->GetParameter();
  871. pNode->BuildURL(url);
  872. m_ocx_Ratings.SetAdminTarget(QueryAuthInfo()->QueryServerName(), QueryMetaPath());
  873. m_ocx_Ratings.SetUserData(QueryAuthInfo()->QueryUserName(), QueryAuthInfo()->QueryPassword());
  874. m_ocx_Ratings.SetUrl(url);
  875. SetTimeFields();
  876. FetchHeaders();
  877. FillListBox();
  878. SetControlStates();
  879. if (m_fValuesAdjusted)
  880. {
  881. //
  882. // One or more input values was adjusted
  883. //
  884. OnItemChanged();
  885. m_fValuesAdjusted = FALSE;
  886. }
  887. return TRUE;
  888. }
  889. HRESULT
  890. CW3HTTPPage::SaveInfo()
  891. /*++
  892. Routine Description:
  893. Save the information on this property page
  894. Arguments:
  895. None
  896. Return Value:
  897. Error return code
  898. --*/
  899. {
  900. ASSERT(IsDirty());
  901. TRACEEOLID("Saving W3 HTTP directory page now...");
  902. CError err;
  903. CString m_strExpiration;
  904. MakeExpirationString(m_strExpiration);
  905. BeginWaitCursor();
  906. BEGIN_META_DIR_WRITE(CW3Sheet)
  907. STORE_DIR_DATA_ON_SHEET(m_strExpiration)
  908. STORE_DIR_DATA_ON_SHEET(m_strlCustomHeaders)
  909. END_META_DIR_WRITE(err)
  910. if (err.Succeeded() && m_ppropMimeTypes)
  911. {
  912. m_ppropMimeTypes->m_strlMimeTypes = m_strlMimeTypes;
  913. err = m_ppropMimeTypes->WriteDirtyProps();
  914. if (err.Succeeded())
  915. {
  916. err = ((CW3Sheet *)GetSheet())->SetKeyType();
  917. }
  918. }
  919. EndWaitCursor();
  920. return err;
  921. }
  922. void
  923. CW3HTTPPage::OnButtonFileTypes()
  924. /*++
  925. Routine Description:
  926. 'file types' button handler
  927. Arguments:
  928. None
  929. Return Value:
  930. None
  931. --*/
  932. {
  933. CMimeDlg dlg(m_strlMimeTypes, this);
  934. if (dlg.DoModal() == IDOK)
  935. {
  936. OnItemChanged();
  937. }
  938. }
  939. void
  940. CW3HTTPPage::OnButtonRatingsTemplate()
  941. /*++
  942. Routine Description:
  943. Pass on "ratings" button click to the ocx.
  944. Arguments:
  945. None
  946. Return Value:
  947. None
  948. --*/
  949. {
  950. CError err;
  951. CString mpath = GetSheet()->QueryMetaPath();
  952. {
  953. CMetaKey mk(m_ppropMimeTypes->QueryAuthInfo(), METADATA_MASTER_ROOT_HANDLE, METADATA_PERMISSION_READ);
  954. err = mk.DoesPathExist(mpath);
  955. }
  956. BOOL key = err.Failed();
  957. m_ocx_Ratings.DoClick();
  958. if (key)
  959. {
  960. // User may cancel dialog, and path wasn't created
  961. CMetaKey mk(m_ppropMimeTypes->QueryAuthInfo(), METADATA_MASTER_ROOT_HANDLE, METADATA_PERMISSION_READ);
  962. err = mk.DoesPathExist(mpath);
  963. key = err.Succeeded();
  964. }
  965. // This is pretty annoying, but metabase should not be locked to set a key type
  966. if (key)
  967. {
  968. err = ((CW3Sheet *)GetSheet())->SetKeyType();
  969. ASSERT(err.Succeeded());
  970. }
  971. }
  972. void
  973. CW3HTTPPage::OnDestroy()
  974. /*++
  975. Routine Description:
  976. WM_DESTROY handler. Clean up internal data
  977. Arguments:
  978. None
  979. Return Value:
  980. None
  981. --*/
  982. {
  983. CInetPropertyPage::OnDestroy();
  984. SAFE_DELETE(m_ppropMimeTypes);
  985. }
  986. BOOL
  987. CW3HTTPPage::OnNotify(
  988. WPARAM wParam,
  989. LPARAM lParam,
  990. LRESULT * pResult
  991. )
  992. /*++
  993. Routine Description:
  994. Handle notification changes
  995. Arguments:
  996. WPARAM wParam : Control ID
  997. LPARAM lParam : NMHDR *
  998. LRESULT * pResult : Result pointer
  999. Return Value:
  1000. TRUE if handled, FALSE if not
  1001. --*/
  1002. {
  1003. //
  1004. // Message cracker crashes - so checking this here instead
  1005. //
  1006. if (wParam == IDC_DTP_ABS_DATE || wParam == IDC_DTP_ABS_TIME)
  1007. {
  1008. NMHDR * pHdr = (NMHDR *)lParam;
  1009. if (pHdr->code == DTN_DATETIMECHANGE)
  1010. {
  1011. OnItemChanged();
  1012. }
  1013. }
  1014. //
  1015. // Default behaviour -- go to the message map
  1016. //
  1017. return CInetPropertyPage::OnNotify(wParam, lParam, pResult);
  1018. }